# 例)最低限の環境
export DATABASE_URL="sqlite:///./dev.db" # settingsの必須回避用
export CHROMA_PATH="/tmp/chroma" # サーバ無しモードでOK。Serverなら CHROMA_HOST/PORT
# 任意:既定コレクションを上書きして挙動確認したい場合
# export CHROMA_DEFAULT_COLLECTION="nlq_sessions_override"
# API起動(例)
uvicorn app.main:app --host 0.0.0.0 --port 8081 --reload
1) パッケージ生成の確認(/chroma/package)
1-1. 基本ケース(stats.metabase 経由)
curl -s -X POST http://localhost:8081/chroma/package \
-H 'Content-Type: application/json' \
-d '{
"session_id":"S1","turn_no":1,"lang":"en","variant":"execute",
"input_message":"Show me sales trend",
"validated_sql":"select 1 as col_1",
"used_tables":["sales"],
"stats":{"metabase":{"mode":"public","resource":"question","id":101,"hash":"mh101","url":"http://..."}}
}' | jq .
見るポイント
doc_textに 署名URLが直埋めされていない(「Visualization: Metabase card (id=…, hash=…)」のように安定識別子のみ)meta.metabase側にurl/iframe_srcが保持されているcollectionがCHROMA_DEFAULT_COLLECTIONを設定していればその値- 無ければ
nlq_sessions_en(言語既定)
source_hashが返っている(これが doc_id)
1-2. フォールバックケース(artifacts から取得)
curl -s -X POST http://localhost:8081/chroma/package \
-H 'Content-Type: application/json' \
-d '{
"session_id":"S1","turn_no":2,"lang":"ja","variant":"execute",
"validated_sql":"select 2 as col_2",
"artifacts":[{"kind":"metabase","mode":"public","resource":"question","id":202,"hash":"mh202","url":"http://..."}]
}' | jq .
見るポイント:stats.metabase が無くても、artifacts[kind="metabase"] から id/hash を拾って doc_text に反映される。
2) upsert の確認(/chroma/upsert)
2-1. 乾式(dry_run)— 形だけ検査
(上の 1-1 の応答を pkg.json に保存したと仮定)
curl -s -X POST http://localhost:8081/chroma/upsert \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"dry_run": true,
"items": [{
"entity":"nlq_history",
"natural_key":"S1#1",
"lang":"en",
"doc_text":"dummy",
"meta":{"session_id":"S1","turn_no":1},
"source_hash":"deadbeefdeadbeef", // ← 実際は 1-1 の source_hash を入れる
"collection":"nlq_sessions_en" // ← 1-1 で返った collection を入れる
}]
}
JSON
期待:items[0].doc_id == source_hash、ok: true、processed:1
2-2. 湿式(live)— 実際に upsert
# 1-1 のレスポンス全体(doc_textやmetaを含む)を "pkg.json" として保存している想定
curl -s -X POST http://localhost:8081/chroma/upsert \
-H 'Content-Type: application/json' \
-d "{\"items\":[$(cat pkg.json)]}" | jq .
期待:succeeded:1、items[0].doc_id が表示。
(同じ doc_id で再実行しても上書き=重複は増えません)
3) doc_id(source_hash)の“安定性”と“変化”の確認
3-1. 同一内容 → 同一 doc_id(再実行=上書き)
- 1-1 と同じ HistoryItem をもう一度
/chroma/packageに投げる
→ 同じsource_hashが返る - そのまま
/chroma/upsert(live)
→ 同じ doc_id で upsert される(Chroma 側では上書き)
3-2. SQL or Metabaseが変わる → doc_idが変わる(新規ドキュメント)
validated_sqlを"select 999 as col_x"に変更して/chroma/package
→ 違うsource_hash(=doc_id)に変わる/chroma/upsert(live)
→ 別の doc_id で upsert(※設計どおり “内容が変われば別ドキュメント”)
※要件の解釈:内容が同じ再処理は重複を増やさない(同じ doc_id で上書き)。
SQLや可視化が変わった再処理は“別の知識”として保持(doc_id も変わる)— こちらの挙動で合意済みです。
4) /nlq/history の正規化(任意)
curl -s -X POST http://localhost:8081/nlq/history \
-H 'Content-Type: application/json' \
-d '{
"session_id":"S2","turn_no":1,"variant":"execute","lang":"ja",
"stats":{
"metabase":{"mode":"public","resource":"question","id":301,"hash":"mh301","url":"http://..."},
"metabase_items":[{"mode":"public","resource":"question","id":302,"hash":"mh302","url":"http://..."}]
},
"artifacts":[
{"kind":"metabase","mode":"public","resource":"question","id":301,"hash":"mh301","url":"http://..."}
]
}' | jq .
期待:202 が返る。保存層の実装次第だが、artifacts が重複排除され、全件に created_at(サーバ付与)が入る。
5) 既定コレクションの補完確認(env / lang)
export CHROMA_DEFAULT_COLLECTION="nlq_sessions_override"を入れて 1-1 を実行
→collectionが nlq_sessions_override になる- その env を unset して lang=
enで 1-1 を実行
→collectionが nlq_sessions_en になる
(jaならnlq_sessions_ja)
6) トラブルシュート(詰まりやすい所だけ)
- doc_id が出ない →
/chroma/upsertが必ずdoc_idを返すよう調整済み。レスポンスitems[].doc_idを確認(出ない時はルータが_ensure_doc_id_on_responseを通っているか見直し) - doc_text に署名URLが混入 →
chroma_packagerの方針どおり、本文には安定識別子(id/hash)のみ。URL はmeta.metabaseで保持。 - Chroma サーバ未起動 →
CHROMA_HOSTを外せばPersistentClientでファイル永続に自動フォールバック(CHROMA_PATH参照)。
これで「差分ドキュメント → Chroma へ upsert」の設計どおりの動きを一通り確認できます。
必要なら、この確認フローを make chroma-smoke 的なシェルに落とし込むテンプレも出します。
コメントを残す