Phase C0: 入口の安全装置(最初に固定)
ゴール
/analytics/queryが 必ずstatus + reason_code + diagnostics + errors[] (+ join_plan)を返す- まだ中身が無くても、例外でも HTTP 200 で契約通り返る
この段階の方針
- retrieval/LLM/execute は最初はスタブでOK(ただし 契約だけ 完全にする)
- ここが固まると、nlq-dev 側が reason_code で分岐を先に作れる(手戻り激減)
Phase C1: ir_*_src 取り込み(検証ソースの唯一性を確保)
ゴール
- devportal DB に
ir_model_src / ir_field_src / ir_view_srcが存在し、最低限の必要カラムが揃う - “検証SQL” が通る(many2one/one2manyの存在確認)
ここでやること
- 取り込み方式はCSVでも一旦OK(あなたの認識通り「CSVに落とすが故の事故」なので、後でPostgres→Postgres直同期に置き換えればよい)
- 重要なのは「テーブル名・カラム名をここで確定して固定」すること(後工程のブレを止める)
Phase C2: Chromaの起動+collection常在(top_k>0 の前提)
ゴール
- Chromaが起動していて、少なくとも
portal_field_jaとportal_view_common_jaが 常に存在 - 無ければ 起動時に get_or_create される(“存在しない”で落ちない)
ポイント
- ここが固まるまで
top_k=0をデフォルトにしておくのが安全(ただしレスポンス契約は返す)
Phase C3: retrieval → allowlist抽出(“材料”を安定化)
ゴール
hits -> allowed_fields(set)を安定して作れる- hits 0件なら
RETRIEVAL_NO_HITSを返せる - diagnostics に retrieval 情報(top_k/collections/hits)を入れられる
注意
- allowlist抽出の仕様(metadataに
model/fieldを必ず入れる等)を ここで固定すると、後からJOIN/SQLがブレない
Phase C4: join_planner(View優先+ir_src検証+採否ログ)
ゴール
view_edges + llm_edges(提案のみ)をdecisionsに落とし込み- 採用条件(ir_src + allowlist)で
accepted_edges -> final_joinsが作れる - 採用0なら
VALIDATION_FAILEDで返せる(join_plan付き)
このフェーズが“本丸”
- ここを分離しておくと、LLMやSQL生成が壊れてもJOIN確定の品質は維持できる
Phase C5: SQL生成 → Odoo実行 → EXECUTION_ERROR_* を“必ずきれいに返す”
ゴール
- Odoo実行で落ちても
EXECUTION_ERROR_*+ details(sqlstate等) を必ず返す undefined_table/undefined_column/permission/timeout/syntax/otherのマッピングを固定
ここで大事
- あなたの方針通り、OdooDBでズレて死ぬのは許容。その代わり reason_code が運用の命綱。
Phase C6: E2Eスモーク(/query→/plan→/act が“安定して通る”)
ゴール
- top_k>0 での代表クエリが通る
- 失敗ケースも契約通り(RETRIEVAL_NO_HITS / VALIDATION_FAILED / EXECUTION_ERROR_*)が返る
- 監視・診断(timings/sql_hash/guards_applied)が揃う
進め方のコツ(手戻りをさらに減らすルール)
- Feature flag を最初から:
TOP_K=0/RETRIEVAL_ENABLED/LLM_ENABLED/EXECUTE_ENABLEDみたいに段階解放できるようにする
→ これで「壊れたら全部止まる」を防げます。 - “契約は最初に完成”:中身がスタブでも、reason_code/diagnostics/errors/join_plan の形だけ先に確定。
- 1フェーズ1PR:レビュー/ロールバックが簡単で、原因の切り分けが速い。
- DoD(完了条件)を各フェーズに置く:次に進む条件が明確だとブレない。
結論
安全最優先なら、上のように段階化が正解です。
特に、あなたが書いた「OdooDBを検証に使わない」方針は“実行時エラーが必ず起きる設計”なので、Phase C0(レスポンス契約)と Phase C5(EXECUTION_ERROR整形)を先に固めるのが、最短で事故を減らします。
次の一手としては、あなたが宣言している通り **「ir_*_src取り込み(Phase C1)」→「テーブル名/カラム名の確定」**を最初にやるのが良いです。
そこが確定したら、こちらで **検証SQL(many2one/one2many)を“実名に置換した確定版”**と、join_planner.py + ir_src_repo.py の実装雛形(コピペでPR化できる粒度)まで一気に出せます。
コメントを残す