Skip to content

複数コマンド併用時の合計トークン量制御 #117

@Kewton

Description

@Kewton

概要

search + related + impact + context の結果を併用する際の合計トークン量を制御する機能を追加する。

背景・課題

anvil 0.0.6 + commandindex 0.1.0 での8パターン性能検証で、複数コマンドの結果を結合した際のトークン量が成功率に直接影響することが判明した。

問題

P6パターンでは search + related + impact + context の結果をJSON結合してプロンプトに渡した結果、合計20KBに到達。これがanvildevのコンテキストウィンドウを圧迫し:

  • コンテキストリセット(完全重複サイクル)が発生
  • 73回のfile.readのうち61回が無駄な重複
  • 最終的に変更0件で463秒を浪費

最適範囲の推定

パターン プロンプトサイズ 結果
P2 (context のみ) 3.5KB 成功 (240秒/2ファイル)
P3 (related のみ) 2.5KB 部分的 (75秒/1ファイル)
P6 (全コマンド) 20KB 失敗 (463秒/0ファイル)
P7 (全コマンド+tag) 20KB 成功 (416秒/3ファイル)

5〜10KB程度が最適範囲と推定される。

補足: P6とP7は同じ20KBだがP7はtag付きで情報の構造化・質が異なるため成功した可能性がある。トークン量だけでなく情報の質(冗長度・構造化度)も成功率に影響する。

提案(スコープ: Phase 1のみ)

本Issueでは以下のPhase 1のみを対象とする。自動調整モードは別Issue化を検討する。

Phase 1: 各コマンドへの --max-tokens オプション追加

設計方針: 各サブコマンドに個別に --max-tokens を追加し、呼び出し側(anvil等)がコマンドごとのトークン配分を制御する方式(方針A)を採用する。

理由: commandindexは各サブコマンドが独立したCLIコマンドとして実行される設計であり、コマンド横断の合計制御は呼び出し側の責務とするのが最も自然。

対象コマンド:

コマンド 現状 追加内容
search --limit(件数制御のみ) --max-tokens 追加(全モード対応)
search --related --limit(件数制御のみ) --max-tokens 追加
search --related-stdin --limit(件数制御のみ) --max-tokens 追加(related と同様)
search --changed-since impact に委譲 --max-tokens を impact に伝達
search --workspace 複数リポジトリ集約 集約後の最終結果に --max-tokens 適用
impact --limit(件数制御のみ) --max-tokens 追加
context --max-tokens 実装済み(#105 変更なし

: suggest コマンドは出力が通常小さく、途中切断でLLMが不完全な戦略を受け取るリスクがあるため、Phase 1のスコープから除外する。

--limit との併用ルール: まず --limit で件数を絞り、その結果に --max-tokens でトークン制限をかける(--limit が先に適用される)。

--rerank との併用ルール: limit → rerank → limit trim → max_tokens trim の順で適用する。

--with-snippet との併用ルール: スニペット付与後に --max-tokens トークン打ち切りを適用する。

--max-tokens パラメータ仕様:

  • 型: u64
  • 範囲: 1..=1_000_000(context と統一)
  • 未指定時: 制限なし(後方互換性)

トークン制限の実装方式

共通モジュール化: context.rs の打ち切りロジック(estimate_entry_tokens, tokens_to_char_budget, truncate_snippet_for_char_budget 等)を共通モジュール(output/token_budget.rs)に抽出し、各コマンドから呼び出す。

トークン推定方式(コンテンツベース推定): 出力フォーマットのオーバーヘッド(JSON構造、Markdownヘッダー等)は無視し、コンテンツベースの推定で --max-tokens を適用する。フォーマット差によるずれはドキュメントに注記する。

各出力型のトークン推定対象フィールド:

出力型 トークン推定対象フィールド
SearchResult body(検索結果本文)
SymbolSearchResult name + kind + file_path + children のテキスト表現
RelatedSearchResult file_path + relation_types + snippet
SemanticSearchResult body(検索結果本文)
ImpactResult file_path + snippet

早期打ち切りパターン: context の build_context_pack() と同一のパターンを使用。各結果アイテムの推定トークン数を累積し、max_tokens を超えた時点で残りをスキップ。最初のエントリは例外として必ず含める(context と同じ設計)。

help_llm 対応

  • help_llm.rs の CommandInfo 定義に search/impact の --max-tokens オプション情報を追加

トークン推定に関する注意

現在の推定式: text.chars().count() / 4(1トークン≒4文字)

日本語テキストの注意: 日本語では1文字≒1トークンに近いため、この推定式は過小評価になる可能性がある。将来的にtiktoken等の正確なトークナイザー導入を検討する余地がある。

フォーマットオーバーヘッド: --max-tokens はコンテンツベースのトークン推定に基づく制限であり、各フォーマット(human/json/path/llm)の装飾・構造オーバーヘッドは含まない。実際の出力トークン数はフォーマットにより上回る場合がある。

受け入れ基準

  1. search コマンド(全モード: 通常/symbol/related/related-stdin/semantic/changed_since/workspace)に --max-tokens オプションが追加され、出力のトークン量を制限できること
  2. impact コマンドに --max-tokens オプションが追加され、出力のトークン量を制限できること
  3. search --changed-since 経由で --max-tokens が impact に正しく伝達されること
  4. search --workspace で集約後の結果に --max-tokens が適用されること
  5. --max-tokens 未指定時は従来どおり制限なしで動作すること(後方互換性)
  6. --limit--max-tokens の両方が指定された場合、--limit--max-tokens の順で適用されること
  7. --rerank--max-tokens の両方が指定された場合、limit → rerank → limit trim → max_tokens trim の順で適用されること
  8. トークン推定には既存の estimate_tokens 関数を使用すること
  9. トークン打ち切りロジックは共通モジュール(output/token_budget.rs)に実装し、各コマンドから呼び出すこと
  10. help_llm 出力に新オプション情報が含まれること
  11. --max-tokens 指定時に出力トークン数が上限を超えないことを検証するテストが存在すること
  12. cargo test, cargo clippy, cargo fmt が全てパスすること

優先度

関連

将来の拡張(別Issue)

  • 自動調整モード: 各コマンドの出力を関連度順にランク付けし、上限内で最も重要な情報を残す
  • tiktoken等の正確なトークナイザー導入
  • config デフォルト値: commandindex.toml に default_max_tokens 設定を追加
  • suggest への --max-tokens 追加: 出力構造の安全な切り詰め方式を設計してから追加
  • suggest 戦略への --max-tokens 自動配分: suggest が提案するコマンドにトークン予算を自動配分

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