型付き辺: 出 2 / 入 0
ADR-0078: RQ 調査結果セマンティック検索基盤の構築(Cloudflare Workers + D1 + Vectorize)
- Status: Accepted
- Mode: Standard
- Kruchten Type: Existence/Executive
- Scope: platform
- Implementation Status: In Progress
- 起案者: [email protected]
- 起案日時 (JST): 2026-05-27 17:17
- 承認日時 (JST): 2026-06-21
- Deciders: [email protected] (単独)
1. コンテキスト
1.1 背景 (Background)
RQ (Research Question) 調査結果を蓄積するリポジトリ運用が継続しており、grep ベースでの既調査検索が限界に近づいている。Deep Research を 1 回あたり 50K-200K tokens 消費して実行しているため、既調査の再実行を防ぐ仕組みが必要になった。
1.2 現状 (Current State / As-Is)
RQ 調査結果は 105 ファイル・61 件存在し、月 5-10 件のペースで増加している。検索手段は grep のみで、週 2-3 回の grep 失敗(語彙ミスマッチによる Hit 漏れ)が観測されている。git markdown が source of truth となっている。
1.3 課題 (Problem)
- grep は概念検索が不可能で、同義語・言い換え表現を含むクエリで既調査を発見できない (週 2-3 回失敗)。
- Deep Research の既調査再実行が発生し、1 回あたり 50K-200K tokens の無駄が発生する。
- 3 年後 300-500 件規模では grep ベース運用は持続不可能。
1.4 制約・要件 (Constraints & Requirements)
- Source of truth = git markdown を維持し、reindex で完全再生成可能であること。
- CLI から複数 PC で同一結果を得られること。
- Negative scope: Web UI なし、RQ 以外のインデックス化なし、LLM 回答生成なし。
- ADR-0069 (Vectorize+bge-m3, LLM re-ranking 不使用) / ADR-0019 (Workers 基盤+secrets 管理, LiteLLM 不使用) に整合。
- Workers AI 推論 API の DPA スコープに関する法務確認が完了していること (Accepted 移行ゲート)。
1.5 目標 (Goals / To-Be)
Cloudflare Workers + D1 + Vectorize + Workers AI (bge-m3, 1024 次元) でセマンティック検索基盤を構築し、CLI から find / overlap / prompt の 3 機能を提供する。Embedding アダプター層を介して、Workers AI / OpenAI / transformers.js (ONNX) を切替可能な構造とする。Non-Goals: Web UI 提供、LLM による回答生成、RQ 以外ドキュメントのインデックス化。
2. 決定
Cloudflare Workers + D1 + Vectorize + Workers AI (bge-m3, 1024 次元) を採用し、rq-search-worker/ パッケージを新設する。Embedding 生成は embed(texts[]) → number[][] + dimensions + modelId のアダプター層で抽象化し、Workers AI bge-m3 をデフォルト実装、OpenAI / transformers.js+ONNX をフォールバック実装として持つ。D1/Vectorize 整合性はサーガパターン (vector_sync_status pending/confirmed/failed) で担保し、検索は confirmed のみを対象とする。
3. 判断基準 (Decision Drivers)
3.1 評価軸 (Q42 9 タグから選定)
| # | 軸 | 重要度 (係数) | 案件特有の解釈 |
|---|---|---|---|
| 1 | #suitable | Must (×2.0) | セマンティック検索品質 (MRR@5)、概念検索可否 |
| 2 | #operable | Must (×2.0) | 複数 PC アクセス、reindex 運用負荷、整合性管理、ベンダー障害時のフォールバック |
| 3 | #maintainable | High (×1.0) | アダプター切替可能性、モデル廃止対応、ADR-0069/ADR-0019 整合 |
| 4 | #efficient | High (×1.0) | コスト ($0-5/月)、Free tier 収まり、年間メンテ工数 |
| 5 | #secure | Medium (×0.5) | DPA スコープ、read/write API key 分離、PII 混入防止 |
K.O. criterion: Must 軸 (#suitable, #operable) の score < 3 は不採用。
3.2 評価軸 × 案スコア表
| 軸 | 係数 | 採択案 (Workers+D1+Vectorize) | 案 A (Local SQLite+sqlite-vec) | 案 B (Pinecone/Qdrant) | 案 C (grep+同義語辞書) |
|---|---|---|---|---|---|
#suitable | ×2.0 | 4 | 4 | 4 | 1 |
#operable | ×2.0 | 4 | 3 | 3 | 5 |
#maintainable | ×1.0 | 4 | 3 | 2 | 3 |
#efficient | ×1.0 | 5 | 4 | 2 | 5 |
#secure | ×0.5 | 3 | 4 | 3 | 5 |
| 加重和 (正規化) | 0.815 | 0.700 | 0.585 | 0.685 | |
| K.O. 通過 (Must ≥3) | ✓ | ✓ | ✓ | ❌ (#suitable=1) |
4. 検討した代替案 (Alternatives Considered)
- 案 A (Local SQLite + sqlite-vec): ローカル DB に sqlite-vec で埋め込みを格納し、git-lfs/SSH で同期。— 不採用理由: 複数 PC 間の同期競合・ロック管理で
#operable=3。DPA NG 時のフォールバックは採択案のアダプター層 (transformers.js) で代替可能であり、SQLite 同期の恒常運用は不要。 - 案 B (Pinecone/Qdrant): マネージド/セルフホスト ベクタ DB を Workers から呼び出し。— 不採用理由: ADR-0069 (Vectorize 採用) と重複・ベンダー増加で
#maintainable=2。技術的優位 (filtering, ハイブリッド検索, スパース+デンス) は本ユースケース (RQ 61 件→500 件規模) では過剰機能 (盲点 #9 への暫定回答; 6 ヶ月レビュー時に Workers→Qdrant 呼び出しレイテンシ実測と機能比較を実施)。 - 案 C (grep + 同義語辞書): 既存 grep に同義語展開を加える。— 不採用理由: 概念検索不可で
#suitable=1(K.O. 違反)。
5. 影響 (Consequences)
5.1 正の影響 (Good)
- 概念検索が可能になり、週 2-3 回の grep 失敗を解消。
- Deep Research 既調査再実行 (50K-200K tokens/回) を
find/overlap/promptで抑止。 - Embedding アダプター層により、Workers AI / OpenAI / transformers.js (ONNX) 切替がアプリ層変更ゼロで可能 (DPA NG・モデル廃止・次元数変更に対応)。
- Source of truth = git markdown を維持、reindex で完全再生成可能。
- ADR-0069 / ADR-0019 と整合し、Cloudflare スタックに統一。
- Workers AI 月間 ~110 neurons (Free tier 0.04%)、Vectorize 1.07M/5M dims (21%)、月額 $0。
5.2 負の影響 (Bad)
- transformers.js フォールバック時のベクトル互換性リスク (盲点 #1, critical): Workers AI bge-m3 と transformers.js (Xenova) bge-m3 は量子化・トークナイザ実装の差異により異なるベクトルを生成する可能性 (GitHub issue #537 等でコサイン類似度 0.95 未満報告)。Proposed 段階でコサイン類似度 ≥0.99 の互換性検証を実施し、結果を ADR に追記する。互換性が無い場合、DPA NG 時の作業は「アダプター差替 +0.5 日」では不足し、全件 reindex (2-4h) + 全 PC 同時切替 + eval 再検証 が必須となるため工数を 2 日相当に修正する。複数 PC でモデルバージョンが混在すると検索結果が PC 間で乖離し
#operableを毀損する。 - 28 件 eval set の統計的脆弱性 (盲点 #2, high): Bootstrap CI 幅 0.197 は広く、差分 CI [-0.003, 0.137] の上限は OpenAI が 13.7pt 優位の可能性を含むため「同等」とは言い切れない。MRR@5≥0.7 の撤退基準は 28 件では測定誤差範囲内。Accepted 移行ゲートに eval set 50 件以上への拡張を追加 (盲点 #2 推奨)。評価セット作成者が設計者と同一であることによる認知バイアスを 6 ヶ月レビュー時に第三者作成クエリ最低 20 件で再測定。
- Workers AI DPA 法務確認の長期化リスク (盲点 #3, high): 法務レビューが長期化すると transformers.js 暫定運用が恒常化し、~100MB モデル配布・ONNX 依存管理が非公式の本番構成になる。法務確認期限を ADR 採択後 60 日に設定し、期限超過時は (a) transformers.js を正式採用 (b) Workers AI 機能凍結 のいずれかを明示的意思決定する。
- 第三者インデックス追加時の機密データ混入リスク (盲点 #8, medium): 6 ヶ月で第三者追加を想定するが、社外秘・PII 混入時に Vectorize 上へ機密データが保存される。CI でホワイトリスト (ディレクトリパターン + frontmatter 条件) を強制し、対象外ファイルは reindex を失敗させる。PII 正規表現スキャンを送信前に実施。
- 新規
rq-search-worker/追加。pnpm-workspace.yamlを 1 行変更。
5.3 中立・トレードオフ (Neutral / Trade-offs)
- D1/Vectorize 整合性 (盲点 #5, high): サーガパターン (
vector_sync_statuspending/confirmed/failed) + 日次 cron で ID セット完全一致チェック (phantom confirmed 検出)。追加対策: (a)content_hashを D1 に保存し日次 cron で Vectorize 側と照合 (内容更新後の古いベクトル検知)、(b) Vectorize upsert 後の D1 更新失敗時のロールバック手順を Runbook に明記、(c) reindex に Cloudflare KV ベース TTL 付き分散ロックを実装、GHA workflow に concurrency group を設定。D1 書き込みスループット ~100 writes/sec は 500 件規模では問題ないが監視対象とする。 - Cloudflare 障害時: エラー返却 (サイレント誤判定防止) + CLI
--grepフォールバック。 - frontmatter 変更なし (
indexable:falseopt-out 追加可能)。read/write API key 分離。 - レイテンシ変動 (盲点 #6, medium): bge-m3 1024 次元のコールドスタート/負荷変動でレイテンシ変動の可能性。reindex 105 件は Workers AI Batch API またはキュー処理で CPU 時間制限を回避。CLI に応答時間計測+ログ出力を組み込み p95 を週次トラッキング、3 秒超が連続 5 回でアラート。
- staleness 警告の扱い (盲点 #7, medium): 完了条件「staleness 7 日警告 (API 側強制)」は HTTP エラーではなくレスポンスボディの警告フィールドで通知し HTTP ステータス 200 を維持。強制エラー化は
--strict-freshnessフラグでのみ有効化 (CI フォールスアラーム回避)。 - アダプター初期スコープ (盲点 #10, low): 初期実装は Workers AI アダプターのみ完成品、OpenAI / transformers.js はインターフェース定義 + stub で完了条件を満たす。追加実装は Just-in-Time 方針。
- ADR-0069 との循環論法懸念 (盲点 #9, high): 6 ヶ月レビューを実質的撤退オプションとして機能させるため、移行コスト上限を事前定義 (例: 移行工数 5 日超 / 切替期間 2 週超で撤退見送り) する。
6. 撤退条件 (Rollback Plan)
- Vectorize 値上げ ($10/月 超) → ローカル SQLite (案 A) へ移行。
- bge-m3 品質劣化 (MRR@5 < 0.7、ただし eval 50 件以上拡張後の値で判定) → アダプター層で OpenAI へ切替。
- Vectorize Free tier 制限値が現行比 50% 未満に引き下げ (盲点 #4, high) → 30 日以内に移行。bulk export 未サポートを前提に、撤退時の全ベクトル再生成手順を事前検証し Runbook に含める。Vectorize 使用量月次モニタリング + Free tier 上限 70% 到達時アラートを完了条件に追加。
- 検索利用 10 回未満が 3 ヶ月継続 → 廃止検討。
- Free tier 廃止 → 30 日以内に Paid / 案 A へ移行。
- Workers AI DPA 法務確認が ADR 採択後 60 日超で未完了 → transformers.js 正式採用 or Workers AI 機能凍結を意思決定。
6.5 Confirmation (準拠確認 / Fitness Function)
- 検証手段 1: eval CI ジョブ —
rq-search-worker/eval/に eval set (Proposed: 28 件 → Accepted ゲート: 50 件以上) を配置、GHA で MRR@5 を週次計測。MRR@5 < 0.7 で fail。 - 検証手段 2: D1/Vectorize 整合性日次 cron — ID セット完全一致 +
content_hash照合。不一致検出時は Slack 通知。 - 検証手段 3: ベクトル互換性検証スクリプト — Workers AI bge-m3 vs transformers.js bge-m3 のコサイン類似度を eval set 全件で計測 (≥0.99 を gate)。Accepted 移行前に 1 回、その後はモデル更新時に手動実行。
- 検証手段 4: Vectorize 使用量モニタリング — Cloudflare Analytics API から週次取得し Free tier 70% 到達でアラート。
- 検証手段 5: ホワイトリスト CI — インデックス対象ファイルのディレクトリパターン + frontmatter 条件を CI で強制、対象外検出で reindex 失敗 + PII 正規表現スキャン。
- 実行頻度: 週次 (eval, レイテンシ p95)、日次 (整合性 cron)、PR ごと (ホワイトリスト CI)、モデル更新時 (互換性検証)。
- 違反時の対応: eval fail → 起案者がアダプター切替判断、整合性不一致 → サーガロールバック手順実行、互換性 < 0.99 → DPA NG 時のフォールバック計画を再見積もり。
7. 参照 (References)
- 関連 ADR: ADR-0069 (Confirms: Vectorize+bge-m3, LLM re-ranking 不使用), ADR-0019 (Extends: Workers 基盤+secrets 管理, LiteLLM 不使用)
- 関連 PR/Issue: -
- 外部資料: transformers.js GitHub issue #537 (bge-m3 量子化差異報告, 要追記), Suhr 1999 CBA criterion
- Review After: 2026-11-27