Skip to content

search/related/impact のJSON出力のLLMプロンプト最適化 #116

@Kewton

Description

@Kewton

概要

search/related/impact の --format llm 出力をさらに最適化し、LLMプロンプトサイズを削減する。

背景・課題

anvil 0.0.6 + commandindex 0.1.0 での8パターン性能検証で、JSON出力の冗長性が成功率に直接影響することが判明した。

P6パターン(全コマンド併用)の失敗

  • search + related + impact + context のJSON結合でプロンプト20KBに到達
  • 73回のfile.read + 66回のfile.editを消費して変更0件で終了
  • searchのJSON出力には関連度スコア・メタデータなど、LLMにとって不要な情報が大量に含まれ、情報過多でLLMが迷走

P2パターン(context のみ)の成功

  • プロンプトサイズ3.5KBで240秒/2ファイル変更に成功
  • 必要な情報だけを適切な粒度で提供

プロンプトサイズと成功率の相関

パターン プロンプトサイズ 結果
P2 (context のみ) 3.5KB 成功 (2ファイル)
P6 (全コマンド) 20KB 失敗 (0ファイル)

前提: Issue #104 の成果

Issue #104--format llm は実装済み。現行の LLM 出力は:

  • search: メタデータ(score, heading_level, line_start)除去、Markdown h2/h3 + コードフェンス形式
  • related: ファイルパス + 関連タイプのみ、スコア除去
  • impact: インパクト概要 + ファイルパス + 関連タイプのみ
  • トークン推定を HTML コメントで付与

提案: 追加最適化

Issue #104--format llm 実装をベースに、以下の追加最適化を行う。

設計方針

  • 後方互換性維持: デフォルト動作は現行のまま変更しない。新機能はオプトインのCLIフラグで制御
  • 設定構造体の導入: LlmFormatOptions 構造体を導入し、format_llm系関数への新パラメータを集約。既存呼び出し側の変更を最小化
  • 既存CLIオプションの活用: 新規フラグは最小限にし、既存の --snippet-lines--format llm 時のbodyトランケーションにも適用(CLI引数指定時のみ。設定ファイルの search.snippet_lines は LLM には適用しない)
  • 変更範囲の限定: LlmFormatOptions は search/related/impact の format_llm / format_related_llm / format_impact_llm でのみ使用。workspace/semantic/symbol/diff の LLM formatter は変更しない
  • データ構造の不変: ImpactResult 等のデータ構造は変更しない。impacted_by の省略は format_impact_llm の表示ロジックのみで実装
  • context コマンドは対象外: 本Issueでは context の出力仕様・トークン制御は変更しない

1. search 出力の最適化

  • コードスニペットの行数制限: 既存の --snippet-lines オプション値を --format llm 時のbodyトランケーションにも適用(デフォルト: 無制限=現行動作維持)
  • トランケーション時の安全処理: 末尾に ... (truncated) マーカー付与、開いたコードブロックの閉じ処理
  • 重複コンテンツの除去: 同一ファイル内で path + heading + body 完全一致のエントリを除外

2. related 出力の最適化(search --related の文脈)

  • 結果件数の上限: --limit オプションで制御(既存動作)
  • : 現行の format_related_llm はスニペットを出力しない仕様のため、スニペット最適化は本Issue対象外

3. impact 出力の最適化

  • impacted_by の簡略化: 4件以上の場合に a.rs, b.rs, c.rs, ... (+N more) 形式で省略(format_impact_llm の表示ロジックのみ。JSON/Human出力・データ構造は変更しない)
  • : 現行の format_impact_llm はスニペットを出力しない仕様のため、スニペット最適化は本Issue対象外

4. 共通最適化

  • トークン推定コメントの制御: LlmFormatOptions で制御(デフォルト: 表示=現行動作維持)

影響範囲

変更対象ファイル

  • src/output/llm.rs — LLM出力フォーマッタ(主な変更箇所)
  • src/output/mod.rsLlmFormatOptions 構造体定義、format_*_results ディスパッチ
  • src/cli/search.rsLlmFormatOptions の組み立て・受け渡し
  • src/main.rs — impact サブコマンドでの LlmFormatOptions 組み立て

変更なし確認対象

  • src/output/llm.rs の workspace/semantic/symbol/diff 系関数 — 動作変更なし
  • src/output/json.rs, src/output/human.rs, src/output/path.rs — 変更なし
  • src/cli/context.rs — 変更なし
  • ImpactResult 等のデータ構造 — 変更なし

テスト影響範囲

  • tests/output_format.rs — LLM出力テストの更新・追加
  • tests/cli_args.rs — help-llm 関連テストの確認
  • tests/e2e_impact.rs — impact LLM出力テストの確認

パフォーマンス影響

  • 検索・関連性計算・DBアクセスには影響なし
  • 出力整形段階の O(n) 相当の追加処理のみ(重複除去・トランケーション)
  • 重複排除・トランケーションはフォーマット層に閉じる

依存関係

  • 新規crate追加なし。既存の output/config/CLI 層の内部変更のみ

受け入れ基準

  1. --format llm で search の出力において --snippet-lines 指定時にbodyがトランケーションされること
  2. トランケーション時に ... (truncated) マーカーが付与され、コードフェンスが正しく閉じられること
  3. 同一ファイル内の完全重複エントリ(path + heading + body 一致)が除去されること
  4. impact の impacted_by が4件以上の場合に省略表記になること(format_impact_llm のみ)
  5. デフォルト動作(フラグ未指定時)が現行と同一であること(後方互換性)
  6. workspace/semantic/symbol/diff の LLM出力が変更されていないこと
  7. JSON/Human/Path 出力が変更されていないこと
  8. 既存テスト(cargo test --all)が全てパスすること
  9. cargo clippy --all-targets 警告ゼロを維持すること
  10. 新パラメータ適用時・未適用時の両方のテストケースが存在すること

優先度

関連

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