やることはシンプルに 2 つです。
1) Retrieval(Chroma検索)をどこかで実行する
「次のターン」や「次の改善提案」を生成する直前に、
- query = 今回の質問 + SQL(base/revised) + 直近の状況(target kind など)
- collection =
nlq_sessions_{lang}(もしくは comment専用collection) - filter = 同じ session_id(これが“同一人物/同一会話”の代替になる)
で Chroma から top_k 件取る。
※ あなたの package は meta.session_id が入ってるので、where フィルタで session_id 絞り込みできます。
2) LLMプロンプトに「過去の学習(retrieved docs)」を混ぜる
LLMに渡す入力に、例えばこういうブロックを追加します:
- “Past feedback / learned diffs (retrieved from memory)”
- 取得した YAML diff(comment_diff の doc_text)をそのまま数件貼る
- 量は少なく(例: 3〜5件)、長いものは切る
そしてプロンプトでルール化:
- 「過去の指摘に従う(同じミスを繰り返さない)」
- 「過去と矛盾する提案を出すなら理由を明記」
“同じnatural_key” を使うか? “session_id” を使うか?
あなたの目的(「一人の人に対していろんな条件を覚える」)に近いのは、正直 natural_key一致より session_id 絞り込みです。
- natural_key は今の実装だと
- execute:
sid#turn(ターン単位) - comment:
nlq::<sid>::<turn>::cmt::<idx>(指摘idx単位)
なので “人物単位メモリ”にはなってないです。
- execute:
人物単位っぽくしたいならまずは:
- where={session_id: sid} で検索
- さらに
meta.variant(comment/execute)で分ける
が一番早いです。
実装的に「まだ何もできてない」ポイント(どこに入れる?)
あなたの提示コードだと、生成の中心は services/nlq_execute.py → RouteExecutor の中です。
なので “次のコメント(改善案)をLLMが考える” を入れるなら、候補は2つ:
- SQL生成/分析生成の直前(RouteExecutor内部 or sql生成サービス内部)
- → ここに retrieval を入れて、LLMの入力に混ぜる
- UI側で「コメント案を生成」するAPIを別に作る
- 例:
POST /nlq/comment/suggest - 入力:session_id, turn_no, base_sql, revised_sql, user_comment(optional)
- 中で retrieval → LLM → suggestion を返す
- これだと責務が分かれてデバッグしやすい
- 例:
先に直すべき1点:upsertの“上書き”が成立してから
あなたも言ってた通り、/chroma/upsert 側の add→upsert を揃えるのは重要です。
- 「同じ学習対象を更新」したいなら、Chromaでは基本 upsert 前提
- さらに、doc_id(Chroma ids)が 同じ対象で固定になってないと「更新」になりません
(ここが揃ってないと、学習が“増えるだけ”になって retrieval がノイズ化します)
必要なら次に、あなたの現行構成(collection設計も含めて)に合わせて、
- どのタイミングで retrieval を呼ぶか(RouteExecutorのどこか / 新APIか)
- where フィルタのキー設計(session_id / user_id導入するならどうするか)
- retrieval結果をプロンプトにどう詰めるか(YAML diff をそのまま?要約してメタ化?)
を、最短で動く形に落として具体案(ファイル単位)まで出します。
コメントを残す