全部文章
发布于 2026-07-12

预定义查询智能检查校正机制解析

配好查数语句之后,系统会检查什么、和对话里查数失败有什么关系。

来源 docs/技术博客/预定义查询智能检查校正机制解析.md

表述:本文面向 工作区管理员与开发/运维,说明 Cadau 在配置 HR 等数据连接的 预定义查询query.run)时,「智能检查校正」具体做什么、依赖哪些真实库表信息、与对话里工具调用失败的关系。用户侧「生成员工画像」操作见 对话生成员工画像操作指南;rilong 连接参数对照见 docs/data-connection-templates/caretop-employee-profile/

日期:2026-07-12 相关代码backend/internal/datasource/query_defs_review.goquery_def_schema.goquery_def_sql_fix.goquery_run_params.gobackend/internal/api/handlers/workspace_data_sources.go


结论

Cadau 的 预定义查询智能检查校正 不是单纯的「JSON 排版」或「参数格式校验」,而是一套 逐条流水线

阶段输入输出
本地规范单条 QueryDef? 占位、@param 消除、少量 HR 硬规则
表结构校正(须选数据连接)SQL 涉及表 + information_schema 列名WHERE =? 绑定处列名自动对齐(如 empIdemp_id
AI 逐条审查上一步结果 + 真实列名清单 + 全库表名列表校正后的 query_def 与中文 note

关键前提:管理端调用检查接口时必须带上 data_source_id,平台才会连上该数据连接拉列结构;否则 AI 只能做格式层修正,无法可靠修正栏位名

对话侧另有 query.run 运行时容错(平级参数并入内层、id/empId/emp_id 别名互认),与检查校正互补,见 §5


1. 背景:为什么需要机制而不只靠 AI

1.1 典型故障(以 rilong / 员工画像为例)

在一次真实对话中,智能体对 rilong 连接发起了大量 query.run,失败集中在两类:

错误信息根因
缺少参数 id / emp_id / empId绑定值与 query_id 平级传入,未放在内层 params
Unknown column 'empId' in 'where clause'SQL WHERE 写了 empId,表列实为 emp_id

第二类错误说明:仅有表名列表时,AI 无法知道列名;本地若只做 JSON/? 规范,也修不掉列名错误。

1.2 设计目标

  1. 可验证:尽可能以数据库 真实列元数据 为依据,而不是模型猜测。
  2. 可解释:每条查询返回 note,写明本地与 AI 做了哪些校正。
  3. 可渐进:连库失败或未选连接时,降级为格式校正,不阻断流程。

2. 入口与权限

2.1 API

方法路径说明
POST/api/v1/workspaces/{id}/data-sources/review-query-defs一次性返回校正结果
POST/api/v1/workspaces/{id}/data-sources/review-query-defs/streamSSE 逐条进度(localllmdone

请求体(管理员):

{
  "query_defs_json": "[{\"id\":\"eaemp_by_id\",\"name\":\"...\",\"sql\":\"SELECT ... WHERE empId = ?\", \"params\":[{\"name\":\"id\",\"required\":true}]}]",
  "data_source_id": "<工作区数据连接 UUID>"
}
  • data_source_id 强烈建议填写:用于拉取库名、表列表,并 连库读列结构
  • 工作区管理员;平台须开启数据连接能力且配置 LLM。

2.2 响应

{
  "query_defs_json": "[...]",
  "note": "[eaemp_by_id] 按表结构校正列名:empId→emp_id\n[...]",
  "changed": true,
  "warnings": []
}

管理员将 query_defs_json 写回数据连接配置并保存后,对话中的 query.run 才使用校正后的 SQL。


3. 流水线架构

flowchart TB
    subgraph Input
        A[query_defs_json]
        B[data_source_id]
    end
    subgraph Enrich
        C[库名 + ListTables]
        D[QueryDefsReviewSchema 连接信息]
    end
    subgraph PerQuery["逐条 QueryDef"]
        L1[本地规范 normalizeQueryDefLocal]
        L2[拉取涉及表列名 ListColumns]
        L3[本地列名校正 fixQueryDefColumnsFromSchema]
        L4[AI 审查 reviewQueryDefItem]
    end
    subgraph Output
        O[校正后 JSON + note + warnings]
    end
    A --> PerQuery
    B --> Enrich
    Enrich --> L2
    L1 --> L2 --> L3 --> L4 --> O

核心类型:QueryDefsReviewInputquery_defs_review.go)在原有 QueryDefsJSONTableNamesDatabaseName 上增加:

Schema *QueryDefsReviewSchema // Engine + Conn,用于 ListColumns

Handler enrichQueryDefsInputFromDataSource 在传入 data_source_id 时填充上述字段(workspace_data_sources.go)。


4. 三阶段校正详解

4.1 阶段一:本地规范(normalizeQueryDefLocal

不连库,对单条查询做确定性改写:

规则示例
@param?WHERE empName = @empNameWHERE empName = ?
HR 硬编码 WHERE 替换empId = ?emp_id = ?query_def_sql_fix.go
按 query_id 的 empName 替换mostayentry*by_empname 类:empName = ?emp_name = ?

这一阶段解决 占位符与少数已知惯例,不读取 information_schema

4.2 阶段二:表结构校正(query_def_schema.go

条件QueryDefsReviewInput.Schema != nil(即请求带了有效 data_source_id 且能连库)。

步骤:

  1. ExtractTablesFromSelectSQL:从 SQL 的 FROM / JOIN 解析表名(adhoc_select.go)。
  2. ListColumns:对每张表查 information_schema.columns(MySQL / PostgreSQL 各有实现)。
  3. fixQueryDefColumnsFromSchema:用正则匹配 WHERE … col = ?,若 col 不在列清单中,则尝试 camelCase → snake_caseempIdemp_id)并在列清单中解析 canonical 列名后替换。

示例:

-- 校正前
SELECT * FROM rt_emergency_contact WHERE empId = ?

-- 列清单含 emp_id、不含 empId
-- 校正后
SELECT * FROM rt_emergency_contact WHERE emp_id = ?

note 中会记录:[rt_emergency_contact_by_empid] 按表结构校正列名:empId→emp_id

列名缓存:同一检查任务内按表名缓存列清单,避免重复查库。

4.3 阶段三:AI 逐条审查(reviewQueryDefItem

将以下内容拼进 user payloadbuildQueryDefsReviewItemPayload):

内容
数据库名Conn.Database
库中实际表名ListTables 全量列表(校正 FROM/JOIN 表名)
涉及表的实际列名阶段二已拉取的每张表列清单(校正 SELECT/WHERE 字段
待检查 JSON当前 QueryDef

System prompt 硬性要求(节选):

  • 若提供了 涉及表的实际列名,SELECT/WHERE 字段 必须与列名列表一致,禁止臆造。
  • 常见纠错示例:empIdemp_idempNameemp_name(以列名列表为准)。
  • 表名/列名列表为空时,仅做 JSON/SQL 规范校正

AI 输出单条 query_def + note;若 JSON 不合法则保留阶段二结果并写入 warnings


5. 与 query.run 运行时容错的关系

检查校正解决的是 配置落盘时的 SQL/params 定义;对话执行时另有运行时层(query_run_params.goinvoke.go):

能力作用
normalizeQueryRunArgs把与 query_id 平级的 id/emp_id/empId 并入内层 params
resolveQueryParam按查询定义的 params[].name 解析时,对员工主键/姓名做别名互认

因此:

  • 检查校正:让 SQL 列名、params 定义尽量正确,减少上线后错误。
  • 运行时容错:减轻智能体 调用形状 错误(嵌套、别名),不能修复 SQL 里写错的列名或缺失的表。

两者应同时存在;不应指望仅靠运行时容错掩盖错误 SQL。


6. 与员工画像场景的对照

rilong 连接上,同一 query_id 的内层参数名 并不统一(须以 query.list 或检查后的定义为准),例如:

query_id内层 params 键
eaemp_by_idid
eabasicinfo_by_empidemp_id
eaworkexperience_by_empidempId

智能检查 不会 统一全库参数命名(避免破坏已有 SQL),但会:

  1. note 中暴露列名修正;
  2. 把真实列名交给 AI,减少 SELECT 列表、WHERE 中 栏位 写错;
  3. 配合技能文档要求画像流程 query.list 再按 pipeline 取数。

详细对照表:docs/data-connection-templates/caretop-employee-profile/PARAMS-REFERENCE.md


7. 边界与已知限制

场景行为
未传 data_source_idSchema,跳过阶段二;AI 无列名清单,栏位校正不可靠
连库失败warnings 记录原因,降级为格式 + AI(无列名块)
SQL 中表不存在ListColumns 失败,该条 warning,不阻塞其余条
SELECT 列表错列名当前 本地规则主要校正 WHERE col = ?;SELECT 字段依赖 AI + 列名块
无试跑检查流程 自动 query.run 试执行;保存后须人工或对话验证
子查询 / 复杂 SQLExtractTablesFromSelectSQL 仅解析顶层 FROM/JOIN;复杂 SQL 可能拉不全列

8. 推荐使用方式(管理员)

  1. 数据集成 → 数据连接 中编辑 HR 连接(如 rilong),粘贴或维护 query_defs_json
  2. 点击 智能检查校正(确保请求带上当前连接 ID)。
  3. 阅读返回 note:关注 按表结构校正列名 与 AI 说明。
  4. 保存 连接配置。
  5. 用固定 empId(如 892)对关键 query_id 各执行一次 query.run 验证。
  6. 再让用户在对话中说「生成某某的员工画像」。

对话中可向工作智能体说:

请对 rilong 数据连接执行预定义查询智能检查,保存后列出仍有 SQL 错误的 query_id

9. 实现对照索引

模块路径职责
审查编排datasource/query_defs_review.go逐条流水线、SSE 进度、LLM prompt
表结构datasource/query_def_schema.go列缓存、fixQueryDefColumnsFromSchema
HR 硬规则datasource/query_def_sql_fix.go本地 empId/empName 替换
运行时参数datasource/query_run_params.goquery.run 平级/别名容错
SQL 表解析datasource/adhoc_select.goExtractTablesFromSelectSQL
列元数据datasource/mysql.gopostgres.goListColumns
HTTPhandlers/workspace_data_sources.goReviewQueryDefsenrichQueryDefsInputFromDataSource
SSEhandlers/workspace_data_sources_review_stream.go流式进度

测试:query_def_schema_test.goquery_run_params_test.goquery_defs_review_test.go


10. 演进方向(未实现)

以下能力可按需迭代,当前 不在 检查流水线内:

  • 对 SELECT 列表、JOIN ON 条件做列名静态校验与自动替换;
  • 检查完成后对每条查询 自动试跑(带默认参数或 EXPLAIN);
  • 将校正结果写回前生成 diff 预览 与按 query_id 的回滚;
  • 与「从文档合成预定义查询」(SynthesizeQueryDefsFromDocument)共用同一 schema 上下文。

相关阅读

  • 对话生成员工画像操作指南 — 用户侧话术与 pipeline 流程
  • docs/data-connection-templates/caretop-employee-profile/README.md — rilong 参数与 SQL 修复清单
  • examples/employee-profile-pipeline/data-connection/query-defs.example.json — 标准 pipeline 查询范例