Skip to content

suggest の英語クエリ精度改善 #144

@Kewton

Description

@Kewton

概要

suggestコマンドの英語クエリでの推薦精度を改善する。

現状

BGE-M3対応(#134)により日本語suggestは大幅改善:

しかし英語クエリは依然としてBM25が支配的:

  • "add fullscreen feature to terminal display" → terminal-highlight.ts(部分的。5番目にuseFullscreen.ts)

原因

suggestはBM25全文検索の上位5件(DEDUP_FILE_LIMIT=5)に基づいて戦略を生成する。BM25で「display」→ app-version-display.test.tsxterminal-highlight.ts のような汎用語マッチが上位に来る。

日本語が改善された理由は、日本語クエリではBM25のマッチが弱い(形態素分析なしのtantivyでは日本語トークンが正しく分割されない)ためBM25=0件となり、セマンティック検索(BGE-M3)のフォールバックが効いたため。

根本原因: 現在のsuggestはフォールバック方式(BM25=0件の場合のみセマンティック検索を使用)であり、BM25結果が1件以上ある英語クエリではセマンティック結果が完全に無視される。既存のhybrid.rs(RRF統合)はsuggestでは未使用。

改善方針

コア改善: フォールバック方式からRRFハイブリッド方式への移行

現在のフォールバック方式(BM25=0の場合のみセマンティック検索)を廃止し、常時ハイブリッド方式に移行する:

  • BM25結果が存在する場合でも、常にセマンティック検索を併用
  • 既存のhybrid.rsを参考にRRF統合ロジックを活用
  • RRFはランクベースの統合のため、BM25スコアとcosine similarityのスケール差を自然に吸収

データフロー設計(ファイル単位RRF)

suggestが必要とするのはファイル単位のランキングであり、既存のrrf_merge(path, heading)単位で動作する。そのため:

  1. BM25結果・セマンティック結果の双方を先にファイル単位でdedup/集約する(各ファイルの最高スコアを採用)
  2. ファイル単位の結果それぞれにfile_type_weightを適用し再ソート
  3. ファイル単位でRRF統合(suggest専用のファイルキーRRFヘルパーを使用、または既存rrf_mergeをファイル単位に適用)
  4. 統合結果をDEDUP_FILE_LIMITでtruncate

注意: section-levelのrrf_mergeをそのまま使って後段dedupする方式は避ける(同一ファイルの複数セクションがRRFスコアに過剰寄与するため)

セマンティック結果の変換

  • EmbeddingSimilarityResultSearchResult型に変換する共通ユーティリティをsrc/search/配下に配置(原則は共通モジュール化、最小変更ならsearch.rsのpub化も可)
  • search.rssuggest.rsの両方から利用可能にする

ファイルタイプ重み付け(実装済み・RRF対応調整)

以下は既に実装済み。必要に応じて値の調整を検討:

  • テストファイル: TEST_FILE_WEIGHT = 0.3(スコア-70%減衰)
  • ドキュメント/レポート: DOC_FILE_WEIGHT = 0.5(スコア-50%減衰)
  • ソースコード: 1.0(調整なし)

設計判断: BM25結果とセマンティック結果それぞれにfile_type_weightを適用し再ソートしてからRRF統合する。RRFはランク順位ベースのため、スコア乗算だけでは効果がない。重み付け→再ソートすることでRRFのランク入力に反映される。

パフォーマンス考慮

  • セマンティック検索追加によるレイテンシ増加は許容する
  • embedding provider(Ollama/OpenAI)の障害時はBM25のみにgraceful degradation
    • Ollama未起動、OpenAI API到達不可、認証失敗、レート制限等すべてのprovider障害をカバー
  • 既存のembedding provider timeout(Ollama: 60秒、OpenAI: 30秒)をそのまま利用
    • provider障害時の最悪待ち時間はtimeout値まで増加する点に注意
    • suggest用の短いtimeoutや条件付きsemantic実行は将来の改善余地として別Issue管理
  • search.rstry_hybrid_searchパターンを踏襲

戦略生成ロジックの調整

  • 内部ではハイブリッド検索を使うが、ユーザー向けの探索ステップとしてsearch --semanticコマンド提案(maybe_add_semantic_step)は維持する(調査の横展開として価値があるため)
  • ハイブリッド化によりトップファイルが変わるため、生成されるstrategy(context/related/impactコマンド)も連動して変化する

受け入れ基準

  1. suggestがBM25>0の場合でもセマンティック結果をRRFで統合すること
  2. BM25>0かつsemantic結果ありの英語クエリで、BM25単独時と上位候補が変化すること(ハイブリッド統合の効果確認)
  3. 生成されるstrategyがハイブリッド後のトップファイルに正しく追従すること
  4. 日本語クエリの既存精度が劣化しないこと(リグレッションなし)
  5. embedding未構築環境で従来通りBM25のみで動作すること(graceful degradation維持)
  6. embedding provider障害時(Ollama未起動、OpenAI API失敗等)にエラーにならずBM25フォールバックすること
  7. suggest固有のテストが存在すること:
    • BM25>0でもセマンティックを併用することの確認
    • embedding未構築時のBM25-only継続
    • provider障害時のgraceful degradation
    • file_type_weightとファイル単位dedup順序が意図どおり働くこと
  8. 共通化リファクタ後にsearch周辺の既存テストが回帰パスすること
  9. cargo clippy --all-targets -- -D warnings 警告0件
  10. cargo test --all 全テストパス

影響範囲

ユーザー向け挙動変更

  • embedding利用時のsuggest出力順位が変化する(ハイブリッド化による改善)
  • 出力順位変化に伴い、生成されるstrategy(context/related/impactコマンド)も変化する
  • embedding未構築環境では従来と同一の挙動

コード変更範囲

  • 主要変更: src/cli/suggest.rs(フォールバック→ハイブリッド化)
  • 活用: src/search/hybrid.rs(RRFロジック参考、変更なし or 軽微な追加)
  • 共通化リファクタ: src/cli/search.rsのセマンティック結果変換関数をsrc/search/に移動(searchコマンドのユーザー向け挙動変更は想定しない)
  • テスト追加: tests/e2e_suggest.rsの拡張 + embeddingあり/provider失敗/file-level RRFの新規テスト

依存関係

  • ビルド時依存追加なし: Cargo.toml変更不要
  • 実行時依存の変化: embedding provider設定に応じてsuggestの実行時依存が強まる
    • embeddings.db存在時: provider呼び出しが毎回発生
    • OpenAI利用時: API到達性・APIキー・コスト・レート制限の影響を受ける
    • provider障害時: timeout値までの待ち時間発生後にBM25 degrade

関連

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions