9.8 KiB
9.8 KiB
Internal Query DSL Plan Design
Goal
为 query.answer 的内部只读查询引入一条受控、可审计、可校验的查询计划链,让大模型只负责“理解问题并产出结构化计划”,数据库与执行器只负责“按白名单模板取证”,最后再由 verifier 检查“回答是否真的对上了用户的问题”。
Why Now
当前链路已经能先判 internal / external / uncertain,但一旦进入内部问答,rag_query_semantics 对问句类型的表达仍然过粗,且执行层缺少“问法合同”和“结果校验”这两道边界。
直接表现就是:
- “有没有 A 股项目”会被压扁成
count + project - 执行层随后直接进入“项目总数”分支
- 最终返回一个真实但答非所问的数字
这不是单点 existence 漏洞,而是内部查询缺少统一查询计划与回答合同的系统性问题。
Confirmed Baseline
- 方案 1 是内部查询的第一道必经步骤。
route_mode=internal的 non-planquery.answer在真正查库前,必须先生成Query DSL Plan,并在计划定稿后组装InternalContextPacket作为 internal-only 运行时单一真源。- 大模型禁止自由写 SQL;只能输出受控 DSL。
- 受控执行器只能命中白名单实体、白名单字段映射、白名单查询模板。
- 协议短回复、模式控制、执行动作请求不得进入 DSL 规划;必须在 ingress / followup gate 提前拦住。
- 执行结果必须经过 answer verifier;如果 verifier 发现“问的是 existence,答的是 total count”这类合同漂移,必须显式失败或重试,不得直接出站。
Scope
In Scope
query.answer的内部只读查询路径rag_query_semantics的问句类型收口Query DSL Plan结构定义- 受控执行器与回答合同
- verifier 校验与审计字段
- 与
Query Route Gateway、后续semantic_facts读模型的衔接
Out Of Scope
plan mode、requirement-plan、draft confirm 主链- 外部实时检索链
- 自由 SQL agent、多轮自反思 text-to-SQL
- 内部写操作或自动入库
Query Taxonomy Baseline
内部只读查询的 query_type 基线统一为:
| query_type | 用户真实意图 | 典型问法 | 默认回答合同 |
|---|---|---|---|
existence |
某对象/语义是否存在 | 有没有 A 股项目 | yes_no_with_evidence |
count |
数量、总数、人数 | 现在有多少个项目 | count_scalar |
list |
枚举、有哪些、分别是什么 | 系统里有哪些项目 | entity_list |
status |
状态、属性、配置值、快照 | 项目 64 现在什么状态 | entity_snapshot |
explain |
原理、用途、调用链、定义 | 当前系统架构是什么 | explanation_with_citations |
diagnose |
异常原因、根因、证据链 | 为什么刚才答错了 | diagnosis_with_evidence |
compare |
差异、对比、谁更适合 | 现在接的和最新模型差别 | comparison_with_basis |
unknown |
无法可靠归类 | 低信息量或语义不足 | clarify_or_fail |
下面这些不属于 query_type,必须在进入 rag_query_semantics 之前处理掉:
- 协议回复:
A/B/C、确认、继续 - 模式控制:
退出需求模式 - 执行动作:
接入外部来源继续核实 - 草稿/需求收敛动作:
再出一版草稿
Query DSL Plan Contract
Query DSL Plan 建议统一为单一结构化对象:
| 字段 | 说明 |
|---|---|
plan_version |
DSL 版本号,便于平滑演进 |
query_type |
上表中的标准问句类型 |
entity_type |
project/task/signal/user/doc/config/run/... |
answer_contract |
最终回答必须满足的合同 |
filters[] |
结构化过滤条件,支持 field/operator/value/value_source |
scope |
tenant_id/project_id/thread_anchor/referenced_objects 等上下文限定 |
projection |
回答所需字段或摘要目标 |
sort |
列表/比较类排序意图 |
limit |
列表上限 |
retrieval_policy |
facts_first / allow_fallback_text / require_fresh_fact 等 |
verifier_checks[] |
出站前必须通过的校验项 |
clarify_on_empty |
命中为空时是澄清还是直接回“未找到” |
示例:用户问“帮我看看系统里面有没有 A 股项目。”
{
"plan_version": "v1",
"query_type": "existence",
"entity_type": "project",
"answer_contract": "yes_no_with_evidence",
"filters": [
{
"field": "market_theme",
"operator": "equals_or_alias",
"value": "A股",
"value_source": "user_text"
}
],
"scope": {
"tenant_bound": true
},
"projection": ["project_id", "title", "matched_evidence"],
"retrieval_policy": {
"facts_first": true,
"allow_fallback_text": true
},
"verifier_checks": [
"contract_matches_query_type",
"evidence_backed",
"no_total_count_substitution"
],
"clarify_on_empty": false
}
Mandatory Execution Flow
route_mode=internal 后的内部问答链路统一为:
Query Route Gateway决定本轮必须走内部查询。rag_query_semantics只产出标准query_type、entity_type与 DSL 所需槽位,不再直接决定最终回答。Query DSL Normalizer做 schema 校验、枚举收口、上下文补足与黑名单清洗。InternalContextPacket固化question / scope / route_decision / operation_contract / target_resolution / query_plan,并作为 internal executor / verifier / runtime summary 的单一真源;query_semantics只保留上游 scratchpad 与兼容镜像。- mainline 必须先对 packet 做预检;若 packet 缺失、
operation_contract.query_type缺失、target_resolution.resolution_mode=clarify或query_plan.answer_contract缺失,直接返回clarify / explicit_insufficient_evidence,不允许继续执行。 Bounded Executor根据 packet 内的entity_type + query_type + filters选择白名单模板执行。- 若
semantic_facts可用,则先走 facts-first;证据不足时再走受控 fallback 检索。 Answer Verifier校验“问法合同、证据合同、来源合同”是否一致。- verifier 通过后再进入回答渲染;不通过则显式失败或重试,不允许静默出错。
Bounded Executor Rules
执行器必须遵守以下硬边界:
- 不接收自由 SQL 字符串
- 不允许 LLM 决定 join 路径、表名、排序字段白名单之外的内容
- 只允许已声明的实体模板,如
project existence/count/list/status - 所有执行都必须自动绑定
tenant_id - facts-first 命中时,回答证据必须能回指到具体 fact 或原始证据对象
- fallback 文本检索只能在 DSL 明确允许时触发
Answer Verifier Contract
verifier 至少检查:
query_type与answer_contract是否一致- 回答正文是否覆盖了用户真正问的对象和条件
- 是否误把 existence / status / compare 问题答成 total count
- 回答所引用的证据是否真实命中本次执行结果
reply_contract是否与route_mode=internal一致- verifier 的合同真源必须来自
InternalContextPacket.operation_contract.query_type与InternalContextPacket.query_plan.answer_contract,禁止根据 answer 文本或散落的query_semantics字段倒推
verifier 不通过时,统一返回三类结果之一:
retry_with_same_planretry_with_clarified_planexplicit_insufficient_evidence
Failure Semantics
- DSL 结构化失败:显式失败,不回退自由回答
InternalContextPacket缺失:直接clarify / explicit_insufficient_evidenceoperation_contract.query_type缺失:直接clarify / explicit_insufficient_evidencetarget_resolution.resolution_mode=clarify:直接澄清,不回退自由回答query_plan.answer_contract缺失:直接explicit_insufficient_evidence- 执行器无模板支持:显式返回“当前内部查询模板未覆盖”
- 命中为空但证据不足:按
clarify_on_empty澄清或返回“当前未确认到” - verifier 判定合同漂移:拒绝出站并写审计日志
Rollout
Phase A
先把本设计写入架构基线,不动运行时代码。
Phase B
实现 Query DSL Plan + Bounded Executor + Answer Verifier,先止住“答非所问”的问题。
Phase C
接入 semantic_facts 读模型后,内部查询默认走 facts-first,再做受控 fallback。
计划改动文件清单(基线确认后)
方案 1 运行时主链
backend/app/config/ai_prompts.pybackend/app/services/adaptive_rag_service/shared_part_02.pybackend/app/services/adaptive_rag_service/mixin_core_intent.pybackend/app/services/adaptive_rag_service/mixin_query_route_gateway.pybackend/app/services/adaptive_rag_service/mixin_answer_mainline.pybackend/app/services/adaptive_rag_service/internal_query_context.pybackend/app/services/adaptive_rag_service/mixin_answer_payload.pybackend/app/services/adaptive_rag_service/mixin_deterministic_query_core.pybackend/app/services/adaptive_rag_service/mixin_deterministic_query_count.pybackend/app/services/adaptive_rag_service/mixin_deterministic_query_list.pybackend/app/services/adaptive_rag_service/mixin_fast_answer_project_main.pybackend/app/services/adaptive_rag_service/mixin_retrieval_router_db.pybackend/app/services/adaptive_rag_service/service.py
方案 1 回归测试
backend/tests/test_adaptive_rag_mainline_contract.pybackend/tests/test_ai_pmo_ingress_mainline.pybackend/tests/test_rag_route_contract.pybackend/tests/test_runtime_structured_semantics_contract.py
本轮文档基线
AGENTS.mdCLAUDE.mddocs/architecture/RUNTIME_GUARDRAILS.mddocs/architecture/DATAFLOW.mddocs/architecture/ARCHITECTURE_INVENTORY.mddocs/superpowers/specs/2026-04-15-internal-query-dsl-plan-design.mddocs/superpowers/specs/2026-04-15-semantic-facts-read-model-design.md