工程1:ShapeAdapterの“箱”だけ(LLMなし、ルール優先)
目的:/nlq/execute が rows を返しつつ、shape判定も返す(Metabaseはまだ繋がない)
app/services/shape/base.py:ShapeAdapter interface(id/describe/match/normalize)registry.py:登録・選択(まずルールで確定、ダメならtable.generic)adapters/time_series.py,ranking.py,scalar.py,table.py(最低4つ)
/nlq/executeのレスポンスに 後方互換で追加shape: {adapter_id, confidence, params}をmetaかトップレベルに追加(どっちでもOK。あなたのAPI規約に合わせる)
✅ この時点で「固定shapeの拡張方式」が確定して、実装が前に進みます。
工程2:キャッシュ保存(Metabaseに見せるための“安定テーブル”)
目的:rowsをキャッシュテーブルへ保存して、run_idで参照できる
ここがキモで、汎用テーブルにJSONBで突っ込むより、**shapeごとに“安定した縦持ちテーブル”**にすると後がラクです。
例(おすすめ):
- time_series 用:
nlq_cache_timeseriesrun_id, bucket_date, metric_name, metric_value_num, metric_value_text
- ranking 用:
nlq_cache_rankingrun_id, rank, dimension, metric_name, metric_value_num
- scalar 用:
nlq_cache_scalarrun_id, key, value_num, value_text, value_date
- table.generic 用:
nlq_cache_kv(最後の逃げ道)run_id, row_idx, col_name, value_text, value_num, value_date
Adapter側に write_cache(normalized) -> cache_ref を持たせる(=プラグインの責務)と拡張が綺麗です。
✅ この時点で「Metabaseカードはrun_idパラメータで引く」が成立します。
工程3:Metabase連結(埋め込みURL生成)
目的:shapeに応じて “固定カードID” を選び、run_idを渡して埋め込む
MetabaseSpec(shape→カード/パラメータ名の対応)を追加MetabaseEmbedを呼んで signed/public URL を生成/nlq/executeのstats.metabase/stats.metabase_itemsをちゃんと埋める
(今は null のままなのでここで初めて繋がる)
✅ フロントは「Metabase iframe で表示」が完成します。
工程4:LLMに“選ばせる”(tie-break専用)
目的:拡張性UP。ただし LLMは最終決定者にしない。
- ルールで確定できるなら確定
- 競合・曖昧時だけ LLM(JSON schema固定)で adapter_id を提案させる
- サーバ側で必ず検証(列存在/閾値/adapter存在)→ダメなら table.generic
✅ ここで「ShapeAdapterを追加しやすい」が完成します。
工程5:DeciKG “箱”だけ(GraphAdapter Registry)
目的:routeがCYPHER系ならMetabaseではなくGraph表示にできる足場
GraphAdapterregistry(まずはgraph.placeholderだけ)/nlq/executeのレスポンスにexecution_kind: "graph"とgraph: {nodes, edges, meta}を出すだけ
✅ DeciKG未実装でも、UI側は切り替え可能になります。
「一気に」やる場合の現実
一気にやるなら 工程1〜3は同時に触ることになるので、落とし穴はこの3つです:
- shape判定のブレで cache schema と合わない
- metabase card 側のパラメータ/型が噛み合わない
- generic table の格納形式が後で地獄になる
なので、やるなら 最低でも 1→2→3 の順で動作確認しながらが安全です。
次スレッドに持ち越す「決定事項」テンプレ(これで合意すると早い)
- ShapeAdapter方式で行く(rules優先、LLMはtie-break)
- 最低shape:time_series / ranking / scalar / table.generic
- キャッシュは “shape別の安定テーブル + run_id参照”
- Metabaseは固定カード(shapeごと)+ run_id パラメータ
- DeciKGはGraphAdapter箱だけ先に作る
コメントを残す