7.4 KiB
7.4 KiB
Review: OpenAI Responses prompt_cache_key 送出によるキャッシュ有効化
前提・要件の確認
llm-worker 側
Requestにcache_key: Option<String>を追加し doc を整備:crates/llm-worker/src/llm_client/types.rs:458-465。cache_anchorの直下、要件通りの位置。doc にも「会話単位の安定キー」「prompt_cache_keyとして送られる」「持たない provider は無視」が明記されている。Request::cache_key(impl Into<String>)builder:crates/llm-worker/src/llm_client/types.rs:546-552。要件通り。OpenAIResponsesScheme::build_requestでrequest.cache_key.clone()をResponsesRequest::prompt_cache_keyに投影:crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs:228。ResponsesRequest::prompt_cache_key: Option<String>を#[serde(skip_serializing_if = "Option::is_none")]付きで追加: 同request.rs:51-57。- 他 scheme (
anthropic,gemini,openai_chat) は touch されておらず、Request::cache_keyを未参照のまま無視している(grep 確認済)。要件通り。
pod 側
- 主 Worker の構築 3 経路すべてで
set_cache_key(Some(session_id.to_string()))を実施:from_manifest:crates/pod/src/pod.rs:1915from_manifest_spawned: 同:1976restore_from_manifest: 同:2064
- compactor (
summary_worker) と memory extract (extract_worker) も session_id でキー付け済み:pod.rs:1198,pod.rs:1553。要件で明示された 3 経路(主 Run / compactor / extract)すべてカバーされている。 Worker::set_cache_keyの追加と、build_request時のrequest.cache_key = self.cache_key.clone()投影、lock()/unlock()越しの引き継ぎ:crates/llm-worker/src/worker.rs:193, 399-405, 600, 1338, 1418。状態遷移で落ちないことが確認できる。
docs
docs/research/openai_responses_prompt_cache_key.mdを新規作成。 「ChatGPT backend では prompt_cache_key 必須」「codex-rs の挙動」「insomnia での Fork / Compaction 方針」「公式 API での挙動」「URL」がカバーされている。openai_responses_max_output_tokens.mdと同じ並び。要件通り。
完了条件
- ユニットテスト 2 件:
prompt_cache_key_passed_through_when_set/prompt_cache_key_omitted_when_none(crates/llm-worker/src/llm_client/scheme/openai_responses/request.rs:540-560)。 body にキーが乗る/省略される、両方を JSON 値で確認している。完了条件を満たす。 cargo check --workspace通過確認済(手元再実行で確認)。cargo test -p llm-worker --lib121 件パス、-p provider --lib41 件、-p pod --lib133 件パスを確認。- 「pod の Run で codex-oauth + Responses を使ったとき、2 turn 目以降の
cache_read_tokensが 0 でない」については実セッションログ要観測(実装上は events.rs のパース修正でcache_read_input_tokensを埋める経路が出来ており、prompt_cache_keyも乗ることがテストで確認できているので、計測経路としては揃っている)。これはコード単体では検証できない要件で、実走行に委ねるのが妥当。
アーキテクチャ・スコープ
- llm-worker は provider-agnostic な
cache_keyを持ち、scheme ごとの解釈は scheme 配下で完結。cache_anchor(Anthropic 用 prefix index) と並立して別概念として扱う方針が doc とコードの両方で明確。低レベル基盤を歪めず、cache_anchorの規約パターンに素直に乗っている。 - 他 scheme (
anthropic,gemini,openai_chat) はフィールドを未参照のまま残しており、不要な実装拡散がない。 - 範囲外項目への踏み込み確認:
- memory consolidate worker への適用 (
pod.rs:1750): ticket の要件節で明示されているのは Run/compactor/extract の 3 件だが、同節末尾に「compactor / extract のように pod の中で派生する worker でも 同じ session_id を使う。これにより pod 内のすべての LLM 呼び出しが同一 cache_key 名前空間で動き、prefix が共有されるところでヒットが期待できる」というポリシーが明記されている。consolidate も pod 内派生 worker なので、明示列挙されていなくとも policy の対象に当然含まれる解釈で妥当。漏れて consolidate だけ別 namespace になる方が不自然。 - compact 後の re-key (
pod.rs:1363): compact 中にself.session_id = new_session_id(1333) で session_id 自体が入れ替わる。worker 側のキャッシュキーを古い session_id のまま放置すると、post-compact turn と extract/consolidate (これらはself.session_id= 新) で namespace が分裂する。範囲外の「compaction の cache_key 戦略」は「明示キーを別系統に切り替える等の最適化」を指しており、ここは「session_id 一本で動かす」という ticket 末尾の方針 (110行) を素直に維持しているだけ。むしろ re-key しない方がポリシー違反になる。
- memory consolidate worker への適用 (
- Worker の構築・状態遷移箇所すべてで
cache_keyをハンドリング (Worker::new初期化、lock/unlock引き継ぎ) しており、後段で見落としによる空キー問題が起きない。 events.rsのinput_tokens_details.cached_tokens取り込みは ticket 本文では「直近のパース修正で復旧した」前提として記述されているが、実際には未コミットだった分が今回まとめて入っている。これは本 ticket 完了の前提として必要な計測経路であり (= cache 効果が実環境で確認可能になる)、ticket の精神を満たすために必要。範囲外項目ではない。
指摘事項
Blocking
なし。
Non-blocking / Follow-up
- 完了条件の最後(codex-oauth で実走行して
cache_read_tokensが 0 でないことを実セッションログで確認)は実装変更だけでは取り込めない。ticket クローズ前に 1 セッション流してcache_read_input_tokensがログに出ることを確認してほしい。 - ticket 本文では
cache_anchorの隣としていたが、Request::cache_anchorフィールドの doc コメントが英語、cache_keyは日本語になっている。プロジェクト方針として混在は許容されているように見えるが、両者揃える価値はある。優先度は低い。
Nits
docs/research/openai_responses_prompt_cache_key.md:79-83「Compaction との関係」セクションは ticket 範囲外項目を補足する形になっているが、現時点の実装方針 (post-compact で new session_id に re-key) と完全整合しているので有用。残してよい。
判断
Approve — ticket の前提・要件・完了条件はコード上満たされており、ticket 範囲外と明記された fork 越し継承や compaction 戦略への踏み込みも無い。consolidate worker への展開と post-compact re-key は ticket の policy 文 (「pod 内のすべての LLM 呼び出しが同一 cache_key 名前空間で動き」「session_id 一本で動かす」) に沿った最小拡張で、コードベースを歪めていない。残るは実セッションでの cache_read_tokens > 0 観測のみで、これは実走確認に委ねるのが妥当。