0. ゴール(役割分担)
- DeciKG:
questionを(LLM or ルールで)パラメータ化 → spec選択 → Cypher生成 → 実行 → rows返却- 返すもの:Cypher / params / rows / diagnostics(分析文章は返さない)
- nlq-dev:DeciKGの rows を分析して文章化(必要なら追加質問を作って Dev-Portal へ)
- 旧案の
CYPHER_THEN_SQLは 「CypherでID解決 → SQLで詳細取得/集計」 のときに意味が出る。
今回の当面運用は DeciKG=Cypher+データまで、分析はnlq-dev。
1. ここまでやったこと(時系列)
1) レスポンス整形の安定化(schemas.py)
response_to_dict()に add-only の補正を追加:rows[*].analysis_packがnull/欠損なら{}を強制(7-5)analysis_pack.explanationを(LLMなしで)最小付与(7-6)confidenceを常に object 形状に正規化(Engineering-5)- dynamic fallback cypher が
diagnostics.assist.dynamic_cypherにある場合、diagnostics.cypher/paramsに ミラー(デバッグ容易化)
- jqで合格判定:
diagnostics.cypherが埋まっていることを確認済み(別ファイルでOK表示)
2) Neo4jデータ実態の確認
- Labels / relTypes / counts 確認済み
- Labels: Company, Opportunity, Partner, SalesRep, User, EmailEvent, PhraseStat, ProposalSignal, Outcome, DomainGuide, ViewCommon
- RelationshipTypes: HAS_CUSTOMER, OWNED_BY, HAS_EMAIL_EVENT, HAS_PHRASE_STAT, HAS_SIGNAL, IN_PERIOD, IS_USER, etc.
- Opportunity は
company_id="c001"に 300件
3) 「佐藤」検索が当たらない原因の切り分け
Userに「佐藤 奈々」がいるが、**Userが孤立(関係0)**の例が多く、Opportunity→SalesRep→User の経路で当たらなかった- 対策として、孤立Userを
loginからrep_id_guess=u07を生成し、SalesRep(company_id, rep_id)を MERGE して(:SalesRep)-[:IS_USER]->(:User)を付与 - さらに、PoC案件の一部 Opportunity を
OWNED_BY -> u07に差し替えて、「佐藤」→案件 がヒットする状態を作成 - Neo4j直接クエリでは、以下が成立:
User(name contains 佐藤)→SalesRep(rep_id=u07)→Opportunity(OWNED_BY u07)が 2件ヒット(op0006/op0011)
2. 現状のAPI検証結果(DeciKG /graph/query)
実行したcurl
curl -sS http://127.0.0.1:${API_PORT:-8000}/graph/query \
-H 'Content-Type: application/json' \
-d '{
"request": {
"request_id":"chk_sato_search_01",
"question":"佐藤の案件を10件",
"slots":{"company_id":"c001"},
"params":{"q":"佐藤","limit":10},
"options":{"include_cypher":true,"include_params":true}
}
}' \
| jq -c '{status, reason_code, cypher:(.diagnostics.cypher//null), params:(.diagnostics.params//{}), rows_len:(.rows|length), rows:(.rows[0:2])}'
結果(重要)
status=ok, reason_code=ok- diagnostics.cypher が “Opportunity.name のみ CONTAINS” のシンプル版になっている:
MATCH (n:Opportunity {company_id: $company_id}) WHERE toLower(n.name) CONTAINS toLower($q) RETURN ... LIMIT $limit params={"limit":10,"timeout_ms":800}(company_id と q が出ていない点も注意)rows_len=0(0件)
解釈
- DeciKG側の spec 推定が “fuzzy横断テンプレ” を選んでいない
- かつ、Cypherが Partner/SalesRep/User を見に行っていないので「佐藤」を拾えない
LIMIT $limitを使っている(cypher-shellではLIMITに変数が使えない環境もあるが、API実行側Neo4jでは通ることが多い。ただし安全策としてDeciKG側でリテラル化を推奨)- paramsに
company_id/qが diagnostics.params に反映されていない(response_to_dict のミラーは limit/timeout のみ入っている)
→ どこで params を組んでいるか確認が必要
3. 設計方針(3軸テンプレ)
「検索」「深掘り」「評価」の3軸で query_key / spec を固定する。
A) search.fuzzy_match(探索の起点)
- LLM(またはルール)が吐く params(最小):
{ "entity_type": "Opportunity", "q": "...", "limit": 10 }
- Cypherは Opportunity/Partner/SalesRep/User を横断して
CONTAINSで当てる(今回の目的:固有名詞・担当者名で見つける)
B) detail.trace_impact(周辺を展開)
{ "opp_id": "...", "depth": 1 or 2 }- 1〜2 hop で EmailEvent/PhraseStat/Signal/Outcome などをまとめて返す(直積回避のため CALL { } 集計)
C) rank.bottleneck_priority(重み付け評価)
{ "metric": "risk", "limit": 5 }- 例:signal/email/phrase を重み付けして score を作り ORDER BY
DeciKG 工程(4つ)
工程D1: データ健全性(Neo4jが正しいか)
目的:グラフ自体は答えを持っていることを証明する(DeciKGの外)。
- labels / rel types / counts
- “佐藤→案件” が Neo4j直で2件以上返る
→ ここがOKなら「データが無い」は否定できる。
工程D2: Spec推定(question → spec/intent の決定)
目的:**LLM(またはルール)が「どのテンプレを使うか」**を当てられているか確認。
- 入力:
question="佐藤の案件を10件"とslots.company_id - 出力:
intent=search.fuzzy_match(最低でも search 系)
かつparams.q="佐藤",params.limit=10が生える(または既存 params を維持)
→ ここが壊れてると、以降は全部ズレる。
工程D3: Cypher生成(spec + params → cypher)
目的:正しいCypherテンプレが選ばれているか確認。
期待:Opportunity.name だけじゃなく、最低でも以下のどれかが入る
HAS_CUSTOMER(Partner.name 検索)OWNED_BY→IS_USER(担当者名検索)
さらに重要:LIMIT は Neo4j都合で “変数limit” はNGなので、DeciKG側は
LIMIT $limitを使う(パラメータ化)
※あなたのCLI検証で通ってる方式
→ ここで “狭いCypher” ならテンプレ側の問題。
工程D4: 実行+レスポンス整形(neo4j run → response_to_dict)
目的:rowsが返る + diagnostics mirror が入る(あなたが直したところ)。
rows_len>0diagnostics.cypher/diagnostics.paramsが埋まる- 追加で
analysis_packが per-row object になっている
→ ここがOKなら、DeciKGは「Cypherとデータを返す」責務を満たした状態。
結論:分けるなら “D2→D3” が境界
いま詰まってるのはほぼここです。
- Neo4j直ではヒットする(D1 OK)
- APIは
Opportunity.name CONTAINS $qしか出していない(D3 NG) - なので Spec推定 or テンプレ選択(D2) が間違ってるか、
search.fuzzy_match のテンプレ自体(D3) が未実装/古い
次スレに持っていく「DeciKG工程テンプレ(短文)」
次スレ冒頭はこれで十分です:
- D1: Neo4j直で “佐藤→案件” は2件返る(OK)
- D2: question→spec 推定が search.fuzzy_match になっているか要確認(未確認)
- D3: 生成Cypherが Opportunity.name のみで狭い(NG)
- D4: diagnostics mirror はOK(OK)
コメントを残す