写给开发者的智能问数 Skill 维护手册
写给开发者的智能问数 Skill 维护手册
分层、消歧、回归:让 Agent 说明书别变成无法合并的屎山
面向:正在用 Cursor / Agent Skill 做 NL2SQL、企业问数的开发与架构同学
(例子优先用电商/物流等通用场景,石油现场作为对照附在后面)
阅读时间:大约一刻钟
你可能已经会让模型「写出能跑的 SQL」了。
这篇文章想聊的是下一步更难受、也更值钱的事:怎么把 Skill 知识库写成可维护的工程资产——尤其当你手里不止一个业务库(比如生产数据一套、工程技术又一套),还要挂在同一个助手上时。
1. 我们真正卡住的地方,往往不是「模型会不会写 SELECT」
搭问数 Skill 的第一周通常很爽:扔进表结构,加两句约束,连上只读库,演示能出数。
难受从第二个月开始:
- 用户随口问「这个产品卖了多少」,交易库 Skill 和履约库 Skill 都能各自查一版数,系统却答成用户不要的那一种;
- 数据库里表和字段描述长得像,智能体检索时分不清,找错表找错字段,查出来的不是用户想要的。
- 同一个计算公式被多处文件引用,改一处漏两处;
- 目录拆了,链接还指着旧路径,Agent 读到两套互相打架的说明书;
- 改完规则只能靠人工抽几问,说不清到底变好了还是变坏了。
换句话说:瓶颈从「生成 SQL」转移到了「知识怎么组织、决策怎么可调试、改完怎么验收」。
这种同词异义不是石油独有。先用大家更熟的「销量」把机制说清,再回到现场:
用户问「这个产品卖了多少」,至少可能是两回事——
下单量:购物车里点了购买、生成了订单(还没付款也可能算进去);
成交量:钱已经付清、才算真正卖掉。
听起来都是「销量」,背后却是两套统计、两张表、两套算法;答错一种,业务侧会觉得系统「胡说八道」。
石油现场也一样:「产了多少油」可能指试油阶段的折算日产(工程技术库),也可能指投产后井口日产(生产数据库)——同词异义,只是词换成了「产油」。
本文不写指标百科,只讲编写方法:目录怎么分、每层写多细、跨库怎么拦、错了怎么归因。
2. 从「能演示」到「能维护」:常见崩法
2.1 起步包长什么样
多数团队一开始只有三样东西:
- 表结构说明(整份或按前缀切开)
- 偏长的
SKILL.md - 只读执行脚本
这也是我们做初版时的样子:单库、问题涉及的表不多、问法固定时,把字段备注描述清楚,就足够证明——约束写清楚,模型可以生成可用 SQL。
这段起步包我们自己踩了大约两个月:内部评测能跑通,但迟迟拿不到客户侧验证,就不知道该往哪改——没有真实反馈,迭代等于空转。工期拉长的主因不是「写不动」,而是验不了、不敢大改。
2.2 复杂度上升后的五类故障
§1 那几条痛点,拆开看就是下面五类:
口径复制粘贴。
同一个「销售额」,在 metrics、WHERE 说明、样例题里写了三种算法,改一处漏两处,线上表现像随机数。
说明书自相矛盾。
被引用的文件更换地方了,入口没改,导致无法直接找到该文件;
明细当汇总。
没有「先用汇总表、明细必须限流」的硬约束,模型把全平台几百万条订单明细一把拉出来再口算加总——数据量一大,算术幻觉就来了。
多 Skill 抢答。
两个问数 Skill 同时挂着时,用户随口一句「卖了多少」「货怎么样了」,两边都能圆上,不能靠模型临场猜该进哪扇门。
常见撞车说法可以先记成对照表(写进两边的 routing):
| 用户随口说 | Skill A(如下单/交易侧)可能指… | Skill B(如发货/履约侧)可能指… |
|---|---|---|
| 卖了多少 / 销量 | 下单量、成交金额 | 已出库件数、妥投量 |
| 货到哪了 | 订单物流状态字段(若交易库有镜像) | 仓储发运、在途、签收 |
| 退了多少 | 退款金额 | 退货入库量 |
| 查一下这个单 / 这个货 | 订单号、买家信息 | 运单号、仓位库存 |
不同部门用的数据源不一致,挂的 Skill 也不是同一个,不能指望用户每次手动指定。
石油现场同理:「产了多少油」在生产库和工程技术库之间也会撞车,机制一样,只是词换成了产量/注气/措施。
没有回归语言。
团队只会说「感觉不准」,不会说「本轮失败里 30% 是选表,还是选字段失败」。
2.3 转折点
后来反馈通路打通、开始按错因改知识之后,分层架构(入口 / 路由 / 领域 / 字典 + 回归)大约半个月就从实践里定型了——比起步包那两个月短很多,因为这时候已经知道「改哪一层、用什么题验收」。
根因可以压成一句:
把本该写成说明书需要规则与分层文档的东西,全部丢给模型「临场发挥」。
模型适合理解自然语言、组织回答;对于查询数据对准确率有要求的不适合在无规则时稳定完成「进哪个系统、选哪张表、用哪个算法」这种分类题。
所以要把 Skill 当成小型后端:入口、路由、领域规则、字典、测试,各管一段。
3. Skill 内部怎么分层(写到能落 SQL)
「统一」不等于只做一个 Skill。
更稳妥的目标是:每个问数 Skill 内部工作流一致、知识分层、关键路由可追踪;生产库和工程库可以各做一个 Skill,但必须先解决「进哪扇门」即用哪个skill。
下面以电商取数为例说一层一层怎么写,石油现场对照附在括号里。
3.1 四层分工
| 层 | 典型文件 | 写到什么粒度 |
|---|---|---|
| 入口 | SKILL.md |
固定步骤:定 Skill → 选表 → 读口径 → 自检 → 执行;只读;不贴计算公式 |
| 路由 | intent / clarifications / skill-routing | 口语 → 首选表 → 见指标编号;两种理解都合理则给 A/B;若已判定属于另一套业务库,本 Skill 不查数,只告诉用户去用对应 Skill |
| 领域规则 | metrics、WHERE 说明、JOIN 说明 | 指标唯一写全;过滤写到列;关联写到 ON 键 |
| 字典与测试 | schema 分片、golden、评测题 | 字段有什么;期望是什么;出现失败改哪个文件 |
上面表格里「去用对应 Skill」就是常说的转交,举个现场例子:
- 用户问「昨天出库了多少」→ 当前若在交易 Skill 里,应直接说:这题归履约 Skill,请改用那个;不要用订单表的发货状态字段硬凑一个数。
- 反过来,用户问「这单成交金额多少」→ 履约 Skill 应转给交易 Skill,不要用出库件数 × 单价硬算。
石油现场同理:在工程技术 Skill 里被问「开发井口昨天产了多少油」,应转给生产数据 Skill,别用试油日报字段硬凑。
注意:转交只要一句话指到正确 Skill;不要在转交时把对方怎么算(字段、公式)写进本包——那叫口径渗入影响后续计算查询。细节见第 5 章。
优化路由不必重写全部口径;补字段说明不必改工作流。这才叫分层,而不是「文件夹好看」。
3.2 目录示例
my-askdata-skill/
SKILL.md
references/
00-meta/ # 维护公约、编号总表
10-route/ # 跨系统边界、选表、澄清
20-domain/ # 口径、WHERE、JOIN
30-schema/ # 表与字段
40-qa/ # 回归样例
scripts/ # 脚本执行代码,或辅助工具
目录同时服务两件事:人维护时知道改哪;Agent 按需加载时知道读哪。
一次问答只应装入当前系统、当前候选表相关文档,而不是整包说明书。
3.3 系统内选表:先定库,再按映射与优先级选表
同词异义在企业取数里很常见(电商的「销量」「货到哪了」「退款」,石油的「产量」「注气」「措施」),所以我们把选表拆成两步,都落在可改的规则文档里,而不是靠模型临场猜:
- 先定业务库:交易还是履约(石油里是生产数据还是工程技术;写在
skill-routing;两可则澄清,已能判定属另一库则转交); - 再在本库内选表:查「问题类型 → 推荐表」映射(写在 intent / table-fit);
- 附优先级:月度汇总类问题先走月度汇总表;单笔订单明细只用于点查、异常名单,且必须限流(石油里:油田/区块月汇总优先,单井日明细限流)。
这样做的直接好处是可追问、可改规则:「为什么选了这张表?」能指到某一行映射;选错了就改那一行,而不是调一句玄学 Prompt。
3.4 统一步骤(质量基线)
建议所有问数 Skill 共用同一套节奏:
- 前置检查(时间、只读、权限)
- 定库:生产 or 工程技术;属另一库则转交;两可则先给跨库澄清选项
- 按需加载本库知识
- 本域澄清(未说清才问):如下单/成交、当日/累计、已付/待付(石油里:试油/修井、日产/累计、设计/实钻);用户已钉死则跳过
- 库内选表 + 读口径 + 写 SQL + 自检
- 执行 + 按返回结果解释(附来源表与过滤条件)
步骤一致,评测才有共同标尺;否则 A 模块爱澄清、B 模块直接出 SQL,评分无法横向比较。定库前后两处澄清的分工,见第 5.1 节。
4. 知识怎么写:唯一源、同粒度、可引用
4.1 指标只写一处
「怎么算」的完整说明,只放在口径文档(metrics)里;入口、路由、样例题里不要再抄一遍公式,只写一行引用,例如:
见 M01·下单量
见 M02·成交量
为什么要两个编号?因为用户都说「卖了多少」,背后却是下单量和成交量两套算法(见 §1)。
若只写一个糊成一团的「销量」,改漏、答错都查不清。
所以:同名不同算法,就拆成两个编号;回答时也要说清楚本次用的是哪一个。
石油里的「产油」同理——试油阶段的折算日产、投产后的井口日产,也应是两个编号,别混称「产量」不声明。(对应电商里:下单量、成交量拆成两个编号。)
对开发同学来说,编号不是炫技,只是约定:改算法只改一处,别处靠编号找到它。
4.2 WHERE 与 JOIN 必须一样具体
| 类型 | 合格写法 | 不合格写法 |
|---|---|---|
| 过滤(精确) | 「订单号 SO202401」→ 订单号列精确匹配;「某日成交」→ 用成交日期列 | 「订单号模糊匹配一下」;用创建日期冒充成交日期 |
| 过滤(范围) | 「华东大区」→ 按大区/组织规则展开(写清用哪张关联表) | 用订单号 LIKE 'HD%' 冒充华东全量 |
| 关联 | 订单表 JOIN 用户表 ON 用户ID;写清内连/左连 |
「订单和用户表关联一下」 |
再补一句给非石油同学:
订单表里往往存的是内部用户 ID,用户却说手机号——所以要先连用户表,用手机号换 ID。石油现场同理:试油日报存内部井 ID,用户说井号(如 FY210H),要先连井基础表换 ID。都是「业务表要 JOIN 维度表才能按用户嘴里的字段查」这一类工程问题。
4.3 澄清只给选项,例外只管边界
澄清:2~3 个选项,例如
- A. 下单量(交易库,看订单表)
- B. 成交量(交易库,看支付表)
或已经确认是交易语境,但没说清:
- A. 看某天的成交额
- B. 看年初至今累计
石油现场对应:A. 试油求产(工程技术库)B. 开发井口日产(生产数据库);进库后再问 A. 当天折算日产 B. 该层累计。
转交时只说「请用生产数据 / 工程技术 Skill」,不要把对方计算公式抄进本包。
4.4 表文档写「有什么」,口径文档写「怎么算」
字段列表服务于选列;计算公式服务于选算法。混在一起,改字段注释时容易误伤业务规则。
字段是否存在,以数据库元数据查询为准,不拿「中文长得像」当证据。
举个通俗例子:一张销售明细表里既有「当日销售额」,又有「年初至今累计销售额」。
用户问「昨天卖了多少」,却拿累计字段去答,数字会差得离谱——列没选错语法,但答非所问。
项目实践中石油日报里「日产油」和「累产油」并存,也是同一类坑。
4.5 新系统借鉴旧 Skill:只借壳,不借肉
把生产库 Skill 的写法搬到工程技术库时:
| 可以抄结构 | 必须重写内容 |
|---|---|
| 目录、步骤、自检形态、评测框架 | 连接配置、表映射、全部指标与 SQL 模板 |
| 编号指针写法、澄清文档形态 | WHERE/JOIN 规则、回归题 |
自检句:删掉生产库特有的表名和算法后,工程技术包是否还能独立回答试油/钻井类问题?反过来亦然。
5. 多 Skill 并列:先关门禁,再进库选表
5.1 顺序不能反(含澄清)
完整一点应是:
问句
→ 定 Skill(交易 or 履约)
├─ 已能判定属另一库 → 转交,结束
└─ 两库都像 → 先澄清(给 A/B,如:下单量 vs 成交量)
→ 进入本库后:本域澄清(用户没说清才问;已钉死则跳过)
例如:下单还是成交?当天还是累计?已付还是待付?订单号精确还是模糊?
→ 以下接 §3.4 第 4 步起:库内选表 → 读口径 → 自检 → 执行
两处澄清不要混:
| 时机 | 问什么 | 举例 |
|---|---|---|
| 定库之前 | 进哪个 Skill | A. 下单量(交易)B. 已出库件数(履约) |
| 进库之后 | 本库内怎么收窄 | A. 当天成交额 B. 年初至今累计;或 A. 下单 B. 退款 |
库都没定就生成 SQL,属于提前答题;本域条件没钉死就直接汇总,也容易答非所问。
5.2 对照表要写在 routing 里
把第 2.2 节那张对照表写进两边 Skill 的 skill-routing,并且对称:
- 交易侧遇到「出库了没、在途多少、仓库还剩多少」→ 转交履约/仓储 Skill;
- 仓储侧遇到「成交金额、是否已付款、退款到账了没」→ 转交交易 Skill。
石油落地时同样对称即可:生产侧遇到试油日报/钻井/录井 → 转交工程技术;工程侧遇到井口日产/核实/措施增油 → 转交生产数据。机制相同,只是对照表里的词换成现场说法。
对照表的价值是:让模型少猜,让开发者改规则有落点。
5.3 对称铁律
两边 Skill 都要写:
- 不执行对方库 SQL
- 不用近似字段冒充(尤其禁止用「下单量」冒充「成交量」,或用「出库件数」冒充「成交件数」)
- 转交一句话,不讲对方算法
- 不把对方指标编号粘进本包 metrics
6. 回归:把「感觉不准」翻译成「改哪个文件」
6.1 最小评测闭环
题库批量提问 → 记录 SQL/用表/是否澄清/是否执行成功 → 对照期望 → 出通过率,并做错因统计。
样例题可以很土、很现场,例如:
- 「订单 SO202401 成交金额多少」(应进交易库、带成交日期)
- 「这个买家下过几单」(交易库用户维度,不必硬联物流表)
- 「华东大区昨天卖了多少」(未说清下单还是成交 → 应澄清)
- 「这批货出库了没」(交易库应转交履约,不得用订单状态硬答)
石油现场对应一组:试油日报产油、开钻完钻日期、哈得昨天产量(应澄清)、开发井口日产(工程库应转交)。
6.2 四类错因
| 错因 | 开发动作 |
|---|---|
| 选表错 | 改路由映射、适用/不适用说明 |
| SQL 错 | 补字段确认、修模板、更新表结构文档 |
| 口径错 | 改 metrics / WHERE / JOIN(列选错、日期列用错也算) |
| 该问没问 | 补澄清与跨系统对照 |
知识或路由变更后跑冒烟;合并前跑扩大回归。
评测脚手架可共用,题目按系统分目录,别拿生产库的题测工程库。
6.3 执行前自检(示例)
- Schema 前缀正确,无串库表名
- 订单号优先精确匹配;禁止用订单号前缀模糊冒充全量(石油里:井号精确,禁止用前缀
LIKE冒充全油田) - 列已做元数据确认(成交额 vs 累计、成交日期 vs 创建日期;石油里:日产 vs 累产、日报日期 vs 创建日期)
- 指标钉死条件已写入
- 单笔/批量明细已限流,或先走汇总表(石油里:单井日明细限流)
- JOIN 键正确(常见:订单表
用户ID= 用户表用户ID;石油里:业务表井ID= 井基础表井ID) - 仅只读
失败就报失败,禁止用「分析报告」口吻补造数字。
7. 我们认的几条工程原则
- 分类决策交给规则,语言理解留给模型。
- 上下文按路径加载,不靠整包硬灌。
- 计算公式只保留一份原文,其它地方引用编号。
- 过滤规则与关联规则写到同一工程粒度(列 / ON 键)。
- 复制目录可以,复制业务算法不行(交易 ↔ 履约尤其如此)。
- 用错因分布指导迭代,而不是用「我觉得」。
仍未自动解决的事
- 取数对了,不等于会做「销量为什么掉了」的归因分析;两套能力如何共享知识要单独设计。(石油现场:「产量为什么掉了」同理。)
- 线上表结构变更会导致文档「沉默过期」,需要元数据对比。
- 用户体感还包括解释是否清楚、交互是否顺,不只是 SQL 对错。
模型会继续变强,但说明书是否分层、口径是否唯一、跨库是否门禁、改完是否可测,仍然决定你的系统能不能在真实企业里活过第三个月。
附录 目录树
my-askdata-skill/
SKILL.md
references/
00-meta/
doc-boundaries.md
id-index.md
10-route/
skill-routing.md
intent-routing.md
clarifications.md
table-fit.md
20-domain/
metrics-and-exceptions.md
scope-filters.md
joins.md
30-schema/
schema-index.md
schema-by-prefix/
tables.json
40-qa/
golden-queries.md
scripts/
execute_sql.py
check_config.py
写给开发者的智能问数 Skill 维护手册
分层、消歧、回归:让 Agent 说明书别变成无法合并的屎山
面向:正在用 Cursor / Agent Skill 做 NL2SQL、企业问数的开发与架构同学
(例子优先用电商/物流等通用场景,石油现场作为对照附在后面)
阅读时间:大约一刻钟
你可能已经会让模型「写出能跑的 SQL」了。
这篇文章想聊的是下一步更难受、也更值钱的事:怎么把 Skill 知识库写成可维护的工程资产——尤其当你手里不止一个业务库(比如生产数据一套、工程技术又一套),还要挂在同一个助手上时。
1. 我们真正卡住的地方,往往不是「模型会不会写 SELECT」
搭问数 Skill 的第一周通常很爽:扔进表结构,加两句约束,连上只读库,演示能出数。
难受从第二个月开始:
- 用户随口问「这个产品卖了多少」,交易库 Skill 和履约库 Skill 都能各自查一版数,系统却答成用户不要的那一种;
- 数据库里表和字段描述长得像,智能体检索时分不清,找错表找错字段,查出来的不是用户想要的。
- 同一个计算公式被多处文件引用,改一处漏两处;
- 目录拆了,链接还指着旧路径,Agent 读到两套互相打架的说明书;
- 改完规则只能靠人工抽几问,说不清到底变好了还是变坏了。
换句话说:瓶颈从「生成 SQL」转移到了「知识怎么组织、决策怎么可调试、改完怎么验收」。
这种同词异义不是石油独有。先用大家更熟的「销量」把机制说清,再回到现场:
用户问「这个产品卖了多少」,至少可能是两回事——
下单量:购物车里点了购买、生成了订单(还没付款也可能算进去);
成交量:钱已经付清、才算真正卖掉。
听起来都是「销量」,背后却是两套统计、两张表、两套算法;答错一种,业务侧会觉得系统「胡说八道」。
石油现场也一样:「产了多少油」可能指试油阶段的折算日产(工程技术库),也可能指投产后井口日产(生产数据库)——同词异义,只是词换成了「产油」。
本文不写指标百科,只讲编写方法:目录怎么分、每层写多细、跨库怎么拦、错了怎么归因。
2. 从「能演示」到「能维护」:常见崩法
2.1 起步包长什么样
多数团队一开始只有三样东西:
- 表结构说明(整份或按前缀切开)
- 偏长的
SKILL.md - 只读执行脚本
这也是我们做初版时的样子:单库、问题涉及的表不多、问法固定时,把字段备注描述清楚,就足够证明——约束写清楚,模型可以生成可用 SQL。
这段起步包我们自己踩了大约两个月:内部评测能跑通,但迟迟拿不到客户侧验证,就不知道该往哪改——没有真实反馈,迭代等于空转。工期拉长的主因不是「写不动」,而是验不了、不敢大改。
2.2 复杂度上升后的五类故障
§1 那几条痛点,拆开看就是下面五类:
口径复制粘贴。
同一个「销售额」,在 metrics、WHERE 说明、样例题里写了三种算法,改一处漏两处,线上表现像随机数。
说明书自相矛盾。
被引用的文件更换地方了,入口没改,导致无法直接找到该文件;
明细当汇总。
没有「先用汇总表、明细必须限流」的硬约束,模型把全平台几百万条订单明细一把拉出来再口算加总——数据量一大,算术幻觉就来了。
多 Skill 抢答。
两个问数 Skill 同时挂着时,用户随口一句「卖了多少」「货怎么样了」,两边都能圆上,不能靠模型临场猜该进哪扇门。
常见撞车说法可以先记成对照表(写进两边的 routing):
| 用户随口说 | Skill A(如下单/交易侧)可能指… | Skill B(如发货/履约侧)可能指… |
|---|---|---|
| 卖了多少 / 销量 | 下单量、成交金额 | 已出库件数、妥投量 |
| 货到哪了 | 订单物流状态字段(若交易库有镜像) | 仓储发运、在途、签收 |
| 退了多少 | 退款金额 | 退货入库量 |
| 查一下这个单 / 这个货 | 订单号、买家信息 | 运单号、仓位库存 |
不同部门用的数据源不一致,挂的 Skill 也不是同一个,不能指望用户每次手动指定。
石油现场同理:「产了多少油」在生产库和工程技术库之间也会撞车,机制一样,只是词换成了产量/注气/措施。
没有回归语言。
团队只会说「感觉不准」,不会说「本轮失败里 30% 是选表,还是选字段失败」。
2.3 转折点
后来反馈通路打通、开始按错因改知识之后,分层架构(入口 / 路由 / 领域 / 字典 + 回归)大约半个月就从实践里定型了——比起步包那两个月短很多,因为这时候已经知道「改哪一层、用什么题验收」。
根因可以压成一句:
把本该写成说明书需要规则与分层文档的东西,全部丢给模型「临场发挥」。
模型适合理解自然语言、组织回答;对于查询数据对准确率有要求的不适合在无规则时稳定完成「进哪个系统、选哪张表、用哪个算法」这种分类题。
所以要把 Skill 当成小型后端:入口、路由、领域规则、字典、测试,各管一段。
3. Skill 内部怎么分层(写到能落 SQL)
「统一」不等于只做一个 Skill。
更稳妥的目标是:每个问数 Skill 内部工作流一致、知识分层、关键路由可追踪;生产库和工程库可以各做一个 Skill,但必须先解决「进哪扇门」即用哪个skill。
下面以电商取数为例说一层一层怎么写,石油现场对照附在括号里。
3.1 四层分工
| 层 | 典型文件 | 写到什么粒度 |
|---|---|---|
| 入口 | SKILL.md |
固定步骤:定 Skill → 选表 → 读口径 → 自检 → 执行;只读;不贴计算公式 |
| 路由 | intent / clarifications / skill-routing | 口语 → 首选表 → 见指标编号;两种理解都合理则给 A/B;若已判定属于另一套业务库,本 Skill 不查数,只告诉用户去用对应 Skill |
| 领域规则 | metrics、WHERE 说明、JOIN 说明 | 指标唯一写全;过滤写到列;关联写到 ON 键 |
| 字典与测试 | schema 分片、golden、评测题 | 字段有什么;期望是什么;出现失败改哪个文件 |
上面表格里「去用对应 Skill」就是常说的转交,举个现场例子:
- 用户问「昨天出库了多少」→ 当前若在交易 Skill 里,应直接说:这题归履约 Skill,请改用那个;不要用订单表的发货状态字段硬凑一个数。
- 反过来,用户问「这单成交金额多少」→ 履约 Skill 应转给交易 Skill,不要用出库件数 × 单价硬算。
石油现场同理:在工程技术 Skill 里被问「开发井口昨天产了多少油」,应转给生产数据 Skill,别用试油日报字段硬凑。
注意:转交只要一句话指到正确 Skill;不要在转交时把对方怎么算(字段、公式)写进本包——那叫口径渗入影响后续计算查询。细节见第 5 章。
优化路由不必重写全部口径;补字段说明不必改工作流。这才叫分层,而不是「文件夹好看」。
3.2 目录示例
my-askdata-skill/
SKILL.md
references/
00-meta/ # 维护公约、编号总表
10-route/ # 跨系统边界、选表、澄清
20-domain/ # 口径、WHERE、JOIN
30-schema/ # 表与字段
40-qa/ # 回归样例
scripts/ # 脚本执行代码,或辅助工具
目录同时服务两件事:人维护时知道改哪;Agent 按需加载时知道读哪。
一次问答只应装入当前系统、当前候选表相关文档,而不是整包说明书。
3.3 系统内选表:先定库,再按映射与优先级选表
同词异义在企业取数里很常见(电商的「销量」「货到哪了」「退款」,石油的「产量」「注气」「措施」),所以我们把选表拆成两步,都落在可改的规则文档里,而不是靠模型临场猜:
- 先定业务库:交易还是履约(石油里是生产数据还是工程技术;写在
skill-routing;两可则澄清,已能判定属另一库则转交); - 再在本库内选表:查「问题类型 → 推荐表」映射(写在 intent / table-fit);
- 附优先级:月度汇总类问题先走月度汇总表;单笔订单明细只用于点查、异常名单,且必须限流(石油里:油田/区块月汇总优先,单井日明细限流)。
这样做的直接好处是可追问、可改规则:「为什么选了这张表?」能指到某一行映射;选错了就改那一行,而不是调一句玄学 Prompt。
3.4 统一步骤(质量基线)
建议所有问数 Skill 共用同一套节奏:
- 前置检查(时间、只读、权限)
- 定库:生产 or 工程技术;属另一库则转交;两可则先给跨库澄清选项
- 按需加载本库知识
- 本域澄清(未说清才问):如下单/成交、当日/累计、已付/待付(石油里:试油/修井、日产/累计、设计/实钻);用户已钉死则跳过
- 库内选表 + 读口径 + 写 SQL + 自检
- 执行 + 按返回结果解释(附来源表与过滤条件)
步骤一致,评测才有共同标尺;否则 A 模块爱澄清、B 模块直接出 SQL,评分无法横向比较。定库前后两处澄清的分工,见第 5.1 节。
4. 知识怎么写:唯一源、同粒度、可引用
4.1 指标只写一处
「怎么算」的完整说明,只放在口径文档(metrics)里;入口、路由、样例题里不要再抄一遍公式,只写一行引用,例如:
见 M01·下单量
见 M02·成交量
为什么要两个编号?因为用户都说「卖了多少」,背后却是下单量和成交量两套算法(见 §1)。
若只写一个糊成一团的「销量」,改漏、答错都查不清。
所以:同名不同算法,就拆成两个编号;回答时也要说清楚本次用的是哪一个。
石油里的「产油」同理——试油阶段的折算日产、投产后的井口日产,也应是两个编号,别混称「产量」不声明。(对应电商里:下单量、成交量拆成两个编号。)
对开发同学来说,编号不是炫技,只是约定:改算法只改一处,别处靠编号找到它。
4.2 WHERE 与 JOIN 必须一样具体
| 类型 | 合格写法 | 不合格写法 |
|---|---|---|
| 过滤(精确) | 「订单号 SO202401」→ 订单号列精确匹配;「某日成交」→ 用成交日期列 | 「订单号模糊匹配一下」;用创建日期冒充成交日期 |
| 过滤(范围) | 「华东大区」→ 按大区/组织规则展开(写清用哪张关联表) | 用订单号 LIKE 'HD%' 冒充华东全量 |
| 关联 | 订单表 JOIN 用户表 ON 用户ID;写清内连/左连 |
「订单和用户表关联一下」 |
再补一句给非石油同学:
订单表里往往存的是内部用户 ID,用户却说手机号——所以要先连用户表,用手机号换 ID。石油现场同理:试油日报存内部井 ID,用户说井号(如 FY210H),要先连井基础表换 ID。都是「业务表要 JOIN 维度表才能按用户嘴里的字段查」这一类工程问题。
4.3 澄清只给选项,例外只管边界
澄清:2~3 个选项,例如
- A. 下单量(交易库,看订单表)
- B. 成交量(交易库,看支付表)
或已经确认是交易语境,但没说清:
- A. 看某天的成交额
- B. 看年初至今累计
石油现场对应:A. 试油求产(工程技术库)B. 开发井口日产(生产数据库);进库后再问 A. 当天折算日产 B. 该层累计。
转交时只说「请用生产数据 / 工程技术 Skill」,不要把对方计算公式抄进本包。
4.4 表文档写「有什么」,口径文档写「怎么算」
字段列表服务于选列;计算公式服务于选算法。混在一起,改字段注释时容易误伤业务规则。
字段是否存在,以数据库元数据查询为准,不拿「中文长得像」当证据。
举个通俗例子:一张销售明细表里既有「当日销售额」,又有「年初至今累计销售额」。
用户问「昨天卖了多少」,却拿累计字段去答,数字会差得离谱——列没选错语法,但答非所问。
项目实践中石油日报里「日产油」和「累产油」并存,也是同一类坑。
4.5 新系统借鉴旧 Skill:只借壳,不借肉
把生产库 Skill 的写法搬到工程技术库时:
| 可以抄结构 | 必须重写内容 |
|---|---|
| 目录、步骤、自检形态、评测框架 | 连接配置、表映射、全部指标与 SQL 模板 |
| 编号指针写法、澄清文档形态 | WHERE/JOIN 规则、回归题 |
自检句:删掉生产库特有的表名和算法后,工程技术包是否还能独立回答试油/钻井类问题?反过来亦然。
5. 多 Skill 并列:先关门禁,再进库选表
5.1 顺序不能反(含澄清)
完整一点应是:
问句
→ 定 Skill(交易 or 履约)
├─ 已能判定属另一库 → 转交,结束
└─ 两库都像 → 先澄清(给 A/B,如:下单量 vs 成交量)
→ 进入本库后:本域澄清(用户没说清才问;已钉死则跳过)
例如:下单还是成交?当天还是累计?已付还是待付?订单号精确还是模糊?
→ 以下接 §3.4 第 4 步起:库内选表 → 读口径 → 自检 → 执行
两处澄清不要混:
| 时机 | 问什么 | 举例 |
|---|---|---|
| 定库之前 | 进哪个 Skill | A. 下单量(交易)B. 已出库件数(履约) |
| 进库之后 | 本库内怎么收窄 | A. 当天成交额 B. 年初至今累计;或 A. 下单 B. 退款 |
库都没定就生成 SQL,属于提前答题;本域条件没钉死就直接汇总,也容易答非所问。
5.2 对照表要写在 routing 里
把第 2.2 节那张对照表写进两边 Skill 的 skill-routing,并且对称:
- 交易侧遇到「出库了没、在途多少、仓库还剩多少」→ 转交履约/仓储 Skill;
- 仓储侧遇到「成交金额、是否已付款、退款到账了没」→ 转交交易 Skill。
石油落地时同样对称即可:生产侧遇到试油日报/钻井/录井 → 转交工程技术;工程侧遇到井口日产/核实/措施增油 → 转交生产数据。机制相同,只是对照表里的词换成现场说法。
对照表的价值是:让模型少猜,让开发者改规则有落点。
5.3 对称铁律
两边 Skill 都要写:
- 不执行对方库 SQL
- 不用近似字段冒充(尤其禁止用「下单量」冒充「成交量」,或用「出库件数」冒充「成交件数」)
- 转交一句话,不讲对方算法
- 不把对方指标编号粘进本包 metrics
6. 回归:把「感觉不准」翻译成「改哪个文件」
6.1 最小评测闭环
题库批量提问 → 记录 SQL/用表/是否澄清/是否执行成功 → 对照期望 → 出通过率,并做错因统计。
样例题可以很土、很现场,例如:
- 「订单 SO202401 成交金额多少」(应进交易库、带成交日期)
- 「这个买家下过几单」(交易库用户维度,不必硬联物流表)
- 「华东大区昨天卖了多少」(未说清下单还是成交 → 应澄清)
- 「这批货出库了没」(交易库应转交履约,不得用订单状态硬答)
石油现场对应一组:试油日报产油、开钻完钻日期、哈得昨天产量(应澄清)、开发井口日产(工程库应转交)。
6.2 四类错因
| 错因 | 开发动作 |
|---|---|
| 选表错 | 改路由映射、适用/不适用说明 |
| SQL 错 | 补字段确认、修模板、更新表结构文档 |
| 口径错 | 改 metrics / WHERE / JOIN(列选错、日期列用错也算) |
| 该问没问 | 补澄清与跨系统对照 |
知识或路由变更后跑冒烟;合并前跑扩大回归。
评测脚手架可共用,题目按系统分目录,别拿生产库的题测工程库。
6.3 执行前自检(示例)
- Schema 前缀正确,无串库表名
- 订单号优先精确匹配;禁止用订单号前缀模糊冒充全量(石油里:井号精确,禁止用前缀
LIKE冒充全油田) - 列已做元数据确认(成交额 vs 累计、成交日期 vs 创建日期;石油里:日产 vs 累产、日报日期 vs 创建日期)
- 指标钉死条件已写入
- 单笔/批量明细已限流,或先走汇总表(石油里:单井日明细限流)
- JOIN 键正确(常见:订单表
用户ID= 用户表用户ID;石油里:业务表井ID= 井基础表井ID) - 仅只读
失败就报失败,禁止用「分析报告」口吻补造数字。
7. 我们认的几条工程原则
- 分类决策交给规则,语言理解留给模型。
- 上下文按路径加载,不靠整包硬灌。
- 计算公式只保留一份原文,其它地方引用编号。
- 过滤规则与关联规则写到同一工程粒度(列 / ON 键)。
- 复制目录可以,复制业务算法不行(交易 ↔ 履约尤其如此)。
- 用错因分布指导迭代,而不是用「我觉得」。
仍未自动解决的事
- 取数对了,不等于会做「销量为什么掉了」的归因分析;两套能力如何共享知识要单独设计。(石油现场:「产量为什么掉了」同理。)
- 线上表结构变更会导致文档「沉默过期」,需要元数据对比。
- 用户体感还包括解释是否清楚、交互是否顺,不只是 SQL 对错。
模型会继续变强,但说明书是否分层、口径是否唯一、跨库是否门禁、改完是否可测,仍然决定你的系统能不能在真实企业里活过第三个月。
附录 目录树
my-askdata-skill/
SKILL.md
references/
00-meta/
doc-boundaries.md
id-index.md
10-route/
skill-routing.md
intent-routing.md
clarifications.md
table-fit.md
20-domain/
metrics-and-exceptions.md
scope-filters.md
joins.md
30-schema/
schema-index.md
schema-by-prefix/
tables.json
40-qa/
golden-queries.md
scripts/
execute_sql.py
check_config.py
写给开发者的智能问数 Skill 维护手册
分层、消歧、回归:让 Agent 说明书别变成无法合并的屎山
面向:正在用 Cursor / Agent Skill 做 NL2SQL、企业问数的开发与架构同学
(例子优先用电商/物流等通用场景,石油现场作为对照附在后面)
阅读时间:大约一刻钟
你可能已经会让模型「写出能跑的 SQL」了。
这篇文章想聊的是下一步更难受、也更值钱的事:怎么把 Skill 知识库写成可维护的工程资产——尤其当你手里不止一个业务库(比如生产数据一套、工程技术又一套),还要挂在同一个助手上时。
1. 我们真正卡住的地方,往往不是「模型会不会写 SELECT」
搭问数 Skill 的第一周通常很爽:扔进表结构,加两句约束,连上只读库,演示能出数。
难受从第二个月开始:
- 用户随口问「这个产品卖了多少」,交易库 Skill 和履约库 Skill 都能各自查一版数,系统却答成用户不要的那一种;
- 数据库里表和字段描述长得像,智能体检索时分不清,找错表找错字段,查出来的不是用户想要的。
- 同一个计算公式被多处文件引用,改一处漏两处;
- 目录拆了,链接还指着旧路径,Agent 读到两套互相打架的说明书;
- 改完规则只能靠人工抽几问,说不清到底变好了还是变坏了。
换句话说:瓶颈从「生成 SQL」转移到了「知识怎么组织、决策怎么可调试、改完怎么验收」。
这种同词异义不是石油独有。先用大家更熟的「销量」把机制说清,再回到现场:
用户问「这个产品卖了多少」,至少可能是两回事——
下单量:购物车里点了购买、生成了订单(还没付款也可能算进去);
成交量:钱已经付清、才算真正卖掉。
听起来都是「销量」,背后却是两套统计、两张表、两套算法;答错一种,业务侧会觉得系统「胡说八道」。
石油现场也一样:「产了多少油」可能指试油阶段的折算日产(工程技术库),也可能指投产后井口日产(生产数据库)——同词异义,只是词换成了「产油」。
本文不写指标百科,只讲编写方法:目录怎么分、每层写多细、跨库怎么拦、错了怎么归因。
2. 从「能演示」到「能维护」:常见崩法
2.1 起步包长什么样
多数团队一开始只有三样东西:
- 表结构说明(整份或按前缀切开)
- 偏长的
SKILL.md - 只读执行脚本
这也是我们做初版时的样子:单库、问题涉及的表不多、问法固定时,把字段备注描述清楚,就足够证明——约束写清楚,模型可以生成可用 SQL。
这段起步包我们自己踩了大约两个月:内部评测能跑通,但迟迟拿不到客户侧验证,就不知道该往哪改——没有真实反馈,迭代等于空转。工期拉长的主因不是「写不动」,而是验不了、不敢大改。
2.2 复杂度上升后的五类故障
§1 那几条痛点,拆开看就是下面五类:
口径复制粘贴。
同一个「销售额」,在 metrics、WHERE 说明、样例题里写了三种算法,改一处漏两处,线上表现像随机数。
说明书自相矛盾。
被引用的文件更换地方了,入口没改,导致无法直接找到该文件;
明细当汇总。
没有「先用汇总表、明细必须限流」的硬约束,模型把全平台几百万条订单明细一把拉出来再口算加总——数据量一大,算术幻觉就来了。
多 Skill 抢答。
两个问数 Skill 同时挂着时,用户随口一句「卖了多少」「货怎么样了」,两边都能圆上,不能靠模型临场猜该进哪扇门。
常见撞车说法可以先记成对照表(写进两边的 routing):
| 用户随口说 | Skill A(如下单/交易侧)可能指… | Skill B(如发货/履约侧)可能指… |
|---|---|---|
| 卖了多少 / 销量 | 下单量、成交金额 | 已出库件数、妥投量 |
| 货到哪了 | 订单物流状态字段(若交易库有镜像) | 仓储发运、在途、签收 |
| 退了多少 | 退款金额 | 退货入库量 |
| 查一下这个单 / 这个货 | 订单号、买家信息 | 运单号、仓位库存 |
不同部门用的数据源不一致,挂的 Skill 也不是同一个,不能指望用户每次手动指定。
石油现场同理:「产了多少油」在生产库和工程技术库之间也会撞车,机制一样,只是词换成了产量/注气/措施。
没有回归语言。
团队只会说「感觉不准」,不会说「本轮失败里 30% 是选表,还是选字段失败」。
2.3 转折点
后来反馈通路打通、开始按错因改知识之后,分层架构(入口 / 路由 / 领域 / 字典 + 回归)大约半个月就从实践里定型了——比起步包那两个月短很多,因为这时候已经知道「改哪一层、用什么题验收」。
根因可以压成一句:
把本该写成说明书需要规则与分层文档的东西,全部丢给模型「临场发挥」。
模型适合理解自然语言、组织回答;对于查询数据对准确率有要求的不适合在无规则时稳定完成「进哪个系统、选哪张表、用哪个算法」这种分类题。
所以要把 Skill 当成小型后端:入口、路由、领域规则、字典、测试,各管一段。
3. Skill 内部怎么分层(写到能落 SQL)
「统一」不等于只做一个 Skill。
更稳妥的目标是:每个问数 Skill 内部工作流一致、知识分层、关键路由可追踪;生产库和工程库可以各做一个 Skill,但必须先解决「进哪扇门」即用哪个skill。
下面以电商取数为例说一层一层怎么写,石油现场对照附在括号里。
3.1 四层分工
| 层 | 典型文件 | 写到什么粒度 |
|---|---|---|
| 入口 | SKILL.md |
固定步骤:定 Skill → 选表 → 读口径 → 自检 → 执行;只读;不贴计算公式 |
| 路由 | intent / clarifications / skill-routing | 口语 → 首选表 → 见指标编号;两种理解都合理则给 A/B;若已判定属于另一套业务库,本 Skill 不查数,只告诉用户去用对应 Skill |
| 领域规则 | metrics、WHERE 说明、JOIN 说明 | 指标唯一写全;过滤写到列;关联写到 ON 键 |
| 字典与测试 | schema 分片、golden、评测题 | 字段有什么;期望是什么;出现失败改哪个文件 |
上面表格里「去用对应 Skill」就是常说的转交,举个现场例子:
- 用户问「昨天出库了多少」→ 当前若在交易 Skill 里,应直接说:这题归履约 Skill,请改用那个;不要用订单表的发货状态字段硬凑一个数。
- 反过来,用户问「这单成交金额多少」→ 履约 Skill 应转给交易 Skill,不要用出库件数 × 单价硬算。
石油现场同理:在工程技术 Skill 里被问「开发井口昨天产了多少油」,应转给生产数据 Skill,别用试油日报字段硬凑。
注意:转交只要一句话指到正确 Skill;不要在转交时把对方怎么算(字段、公式)写进本包——那叫口径渗入影响后续计算查询。细节见第 5 章。
优化路由不必重写全部口径;补字段说明不必改工作流。这才叫分层,而不是「文件夹好看」。
3.2 目录示例
my-askdata-skill/
SKILL.md
references/
00-meta/ # 维护公约、编号总表
10-route/ # 跨系统边界、选表、澄清
20-domain/ # 口径、WHERE、JOIN
30-schema/ # 表与字段
40-qa/ # 回归样例
scripts/ # 脚本执行代码,或辅助工具
目录同时服务两件事:人维护时知道改哪;Agent 按需加载时知道读哪。
一次问答只应装入当前系统、当前候选表相关文档,而不是整包说明书。
3.3 系统内选表:先定库,再按映射与优先级选表
同词异义在企业取数里很常见(电商的「销量」「货到哪了」「退款」,石油的「产量」「注气」「措施」),所以我们把选表拆成两步,都落在可改的规则文档里,而不是靠模型临场猜:
- 先定业务库:交易还是履约(石油里是生产数据还是工程技术;写在
skill-routing;两可则澄清,已能判定属另一库则转交); - 再在本库内选表:查「问题类型 → 推荐表」映射(写在 intent / table-fit);
- 附优先级:月度汇总类问题先走月度汇总表;单笔订单明细只用于点查、异常名单,且必须限流(石油里:油田/区块月汇总优先,单井日明细限流)。
这样做的直接好处是可追问、可改规则:「为什么选了这张表?」能指到某一行映射;选错了就改那一行,而不是调一句玄学 Prompt。
3.4 统一步骤(质量基线)
建议所有问数 Skill 共用同一套节奏:
- 前置检查(时间、只读、权限)
- 定库:生产 or 工程技术;属另一库则转交;两可则先给跨库澄清选项
- 按需加载本库知识
- 本域澄清(未说清才问):如下单/成交、当日/累计、已付/待付(石油里:试油/修井、日产/累计、设计/实钻);用户已钉死则跳过
- 库内选表 + 读口径 + 写 SQL + 自检
- 执行 + 按返回结果解释(附来源表与过滤条件)
步骤一致,评测才有共同标尺;否则 A 模块爱澄清、B 模块直接出 SQL,评分无法横向比较。定库前后两处澄清的分工,见第 5.1 节。
4. 知识怎么写:唯一源、同粒度、可引用
4.1 指标只写一处
「怎么算」的完整说明,只放在口径文档(metrics)里;入口、路由、样例题里不要再抄一遍公式,只写一行引用,例如:
见 M01·下单量
见 M02·成交量
为什么要两个编号?因为用户都说「卖了多少」,背后却是下单量和成交量两套算法(见 §1)。
若只写一个糊成一团的「销量」,改漏、答错都查不清。
所以:同名不同算法,就拆成两个编号;回答时也要说清楚本次用的是哪一个。
石油里的「产油」同理——试油阶段的折算日产、投产后的井口日产,也应是两个编号,别混称「产量」不声明。(对应电商里:下单量、成交量拆成两个编号。)
对开发同学来说,编号不是炫技,只是约定:改算法只改一处,别处靠编号找到它。
4.2 WHERE 与 JOIN 必须一样具体
| 类型 | 合格写法 | 不合格写法 |
|---|---|---|
| 过滤(精确) | 「订单号 SO202401」→ 订单号列精确匹配;「某日成交」→ 用成交日期列 | 「订单号模糊匹配一下」;用创建日期冒充成交日期 |
| 过滤(范围) | 「华东大区」→ 按大区/组织规则展开(写清用哪张关联表) | 用订单号 LIKE 'HD%' 冒充华东全量 |
| 关联 | 订单表 JOIN 用户表 ON 用户ID;写清内连/左连 |
「订单和用户表关联一下」 |
再补一句给非石油同学:
订单表里往往存的是内部用户 ID,用户却说手机号——所以要先连用户表,用手机号换 ID。石油现场同理:试油日报存内部井 ID,用户说井号(如 FY210H),要先连井基础表换 ID。都是「业务表要 JOIN 维度表才能按用户嘴里的字段查」这一类工程问题。
4.3 澄清只给选项,例外只管边界
澄清:2~3 个选项,例如
- A. 下单量(交易库,看订单表)
- B. 成交量(交易库,看支付表)
或已经确认是交易语境,但没说清:
- A. 看某天的成交额
- B. 看年初至今累计
石油现场对应:A. 试油求产(工程技术库)B. 开发井口日产(生产数据库);进库后再问 A. 当天折算日产 B. 该层累计。
转交时只说「请用生产数据 / 工程技术 Skill」,不要把对方计算公式抄进本包。
4.4 表文档写「有什么」,口径文档写「怎么算」
字段列表服务于选列;计算公式服务于选算法。混在一起,改字段注释时容易误伤业务规则。
字段是否存在,以数据库元数据查询为准,不拿「中文长得像」当证据。
举个通俗例子:一张销售明细表里既有「当日销售额」,又有「年初至今累计销售额」。
用户问「昨天卖了多少」,却拿累计字段去答,数字会差得离谱——列没选错语法,但答非所问。
项目实践中石油日报里「日产油」和「累产油」并存,也是同一类坑。
4.5 新系统借鉴旧 Skill:只借壳,不借肉
把生产库 Skill 的写法搬到工程技术库时:
| 可以抄结构 | 必须重写内容 |
|---|---|
| 目录、步骤、自检形态、评测框架 | 连接配置、表映射、全部指标与 SQL 模板 |
| 编号指针写法、澄清文档形态 | WHERE/JOIN 规则、回归题 |
自检句:删掉生产库特有的表名和算法后,工程技术包是否还能独立回答试油/钻井类问题?反过来亦然。
5. 多 Skill 并列:先关门禁,再进库选表
5.1 顺序不能反(含澄清)
完整一点应是:
问句
→ 定 Skill(交易 or 履约)
├─ 已能判定属另一库 → 转交,结束
└─ 两库都像 → 先澄清(给 A/B,如:下单量 vs 成交量)
→ 进入本库后:本域澄清(用户没说清才问;已钉死则跳过)
例如:下单还是成交?当天还是累计?已付还是待付?订单号精确还是模糊?
→ 以下接 §3.4 第 4 步起:库内选表 → 读口径 → 自检 → 执行
两处澄清不要混:
| 时机 | 问什么 | 举例 |
|---|---|---|
| 定库之前 | 进哪个 Skill | A. 下单量(交易)B. 已出库件数(履约) |
| 进库之后 | 本库内怎么收窄 | A. 当天成交额 B. 年初至今累计;或 A. 下单 B. 退款 |
库都没定就生成 SQL,属于提前答题;本域条件没钉死就直接汇总,也容易答非所问。
5.2 对照表要写在 routing 里
把第 2.2 节那张对照表写进两边 Skill 的 skill-routing,并且对称:
- 交易侧遇到「出库了没、在途多少、仓库还剩多少」→ 转交履约/仓储 Skill;
- 仓储侧遇到「成交金额、是否已付款、退款到账了没」→ 转交交易 Skill。
石油落地时同样对称即可:生产侧遇到试油日报/钻井/录井 → 转交工程技术;工程侧遇到井口日产/核实/措施增油 → 转交生产数据。机制相同,只是对照表里的词换成现场说法。
对照表的价值是:让模型少猜,让开发者改规则有落点。
5.3 对称铁律
两边 Skill 都要写:
- 不执行对方库 SQL
- 不用近似字段冒充(尤其禁止用「下单量」冒充「成交量」,或用「出库件数」冒充「成交件数」)
- 转交一句话,不讲对方算法
- 不把对方指标编号粘进本包 metrics
6. 回归:把「感觉不准」翻译成「改哪个文件」
6.1 最小评测闭环
题库批量提问 → 记录 SQL/用表/是否澄清/是否执行成功 → 对照期望 → 出通过率,并做错因统计。
样例题可以很土、很现场,例如:
- 「订单 SO202401 成交金额多少」(应进交易库、带成交日期)
- 「这个买家下过几单」(交易库用户维度,不必硬联物流表)
- 「华东大区昨天卖了多少」(未说清下单还是成交 → 应澄清)
- 「这批货出库了没」(交易库应转交履约,不得用订单状态硬答)
石油现场对应一组:试油日报产油、开钻完钻日期、哈得昨天产量(应澄清)、开发井口日产(工程库应转交)。
6.2 四类错因
| 错因 | 开发动作 |
|---|---|
| 选表错 | 改路由映射、适用/不适用说明 |
| SQL 错 | 补字段确认、修模板、更新表结构文档 |
| 口径错 | 改 metrics / WHERE / JOIN(列选错、日期列用错也算) |
| 该问没问 | 补澄清与跨系统对照 |
知识或路由变更后跑冒烟;合并前跑扩大回归。
评测脚手架可共用,题目按系统分目录,别拿生产库的题测工程库。
6.3 执行前自检(示例)
- Schema 前缀正确,无串库表名
- 订单号优先精确匹配;禁止用订单号前缀模糊冒充全量(石油里:井号精确,禁止用前缀
LIKE冒充全油田) - 列已做元数据确认(成交额 vs 累计、成交日期 vs 创建日期;石油里:日产 vs 累产、日报日期 vs 创建日期)
- 指标钉死条件已写入
- 单笔/批量明细已限流,或先走汇总表(石油里:单井日明细限流)
- JOIN 键正确(常见:订单表
用户ID= 用户表用户ID;石油里:业务表井ID= 井基础表井ID) - 仅只读
失败就报失败,禁止用「分析报告」口吻补造数字。
7. 我们认的几条工程原则
- 分类决策交给规则,语言理解留给模型。
- 上下文按路径加载,不靠整包硬灌。
- 计算公式只保留一份原文,其它地方引用编号。
- 过滤规则与关联规则写到同一工程粒度(列 / ON 键)。
- 复制目录可以,复制业务算法不行(交易 ↔ 履约尤其如此)。
- 用错因分布指导迭代,而不是用「我觉得」。
仍未自动解决的事
- 取数对了,不等于会做「销量为什么掉了」的归因分析;两套能力如何共享知识要单独设计。(石油现场:「产量为什么掉了」同理。)
- 线上表结构变更会导致文档「沉默过期」,需要元数据对比。
- 用户体感还包括解释是否清楚、交互是否顺,不只是 SQL 对错。
模型会继续变强,但说明书是否分层、口径是否唯一、跨库是否门禁、改完是否可测,仍然决定你的系统能不能在真实企业里活过第三个月。
附录 目录树
my-askdata-skill/
SKILL.md
references/
00-meta/
doc-boundaries.md
id-index.md
10-route/
skill-routing.md
intent-routing.md
clarifications.md
table-fit.md
20-domain/
metrics-and-exceptions.md
scope-filters.md
joins.md
30-schema/
schema-index.md
schema-by-prefix/
tables.json
40-qa/
golden-queries.md
scripts/
execute_sql.py
check_config.py
写给开发者的智能问数 Skill 维护手册
分层、消歧、回归:让 Agent 说明书别变成无法合并的屎山
面向:正在用 Cursor / Agent Skill 做 NL2SQL、企业问数的开发与架构同学
(例子优先用电商/物流等通用场景,石油现场作为对照附在后面)
阅读时间:大约一刻钟
你可能已经会让模型「写出能跑的 SQL」了。
这篇文章想聊的是下一步更难受、也更值钱的事:怎么把 Skill 知识库写成可维护的工程资产——尤其当你手里不止一个业务库(比如生产数据一套、工程技术又一套),还要挂在同一个助手上时。
1. 我们真正卡住的地方,往往不是「模型会不会写 SELECT」
搭问数 Skill 的第一周通常很爽:扔进表结构,加两句约束,连上只读库,演示能出数。
难受从第二个月开始:
- 用户随口问「这个产品卖了多少」,交易库 Skill 和履约库 Skill 都能各自查一版数,系统却答成用户不要的那一种;
- 数据库里表和字段描述长得像,智能体检索时分不清,找错表找错字段,查出来的不是用户想要的。
- 同一个计算公式被多处文件引用,改一处漏两处;
- 目录拆了,链接还指着旧路径,Agent 读到两套互相打架的说明书;
- 改完规则只能靠人工抽几问,说不清到底变好了还是变坏了。
换句话说:瓶颈从「生成 SQL」转移到了「知识怎么组织、决策怎么可调试、改完怎么验收」。
这种同词异义不是石油独有。先用大家更熟的「销量」把机制说清,再回到现场:
用户问「这个产品卖了多少」,至少可能是两回事——
下单量:购物车里点了购买、生成了订单(还没付款也可能算进去);
成交量:钱已经付清、才算真正卖掉。
听起来都是「销量」,背后却是两套统计、两张表、两套算法;答错一种,业务侧会觉得系统「胡说八道」。
石油现场也一样:「产了多少油」可能指试油阶段的折算日产(工程技术库),也可能指投产后井口日产(生产数据库)——同词异义,只是词换成了「产油」。
本文不写指标百科,只讲编写方法:目录怎么分、每层写多细、跨库怎么拦、错了怎么归因。
2. 从「能演示」到「能维护」:常见崩法
2.1 起步包长什么样
多数团队一开始只有三样东西:
- 表结构说明(整份或按前缀切开)
- 偏长的
SKILL.md - 只读执行脚本
这也是我们做初版时的样子:单库、问题涉及的表不多、问法固定时,把字段备注描述清楚,就足够证明——约束写清楚,模型可以生成可用 SQL。
这段起步包我们自己踩了大约两个月:内部评测能跑通,但迟迟拿不到客户侧验证,就不知道该往哪改——没有真实反馈,迭代等于空转。工期拉长的主因不是「写不动」,而是验不了、不敢大改。
2.2 复杂度上升后的五类故障
§1 那几条痛点,拆开看就是下面五类:
口径复制粘贴。
同一个「销售额」,在 metrics、WHERE 说明、样例题里写了三种算法,改一处漏两处,线上表现像随机数。
说明书自相矛盾。
被引用的文件更换地方了,入口没改,导致无法直接找到该文件;
明细当汇总。
没有「先用汇总表、明细必须限流」的硬约束,模型把全平台几百万条订单明细一把拉出来再口算加总——数据量一大,算术幻觉就来了。
多 Skill 抢答。
两个问数 Skill 同时挂着时,用户随口一句「卖了多少」「货怎么样了」,两边都能圆上,不能靠模型临场猜该进哪扇门。
常见撞车说法可以先记成对照表(写进两边的 routing):
| 用户随口说 | Skill A(如下单/交易侧)可能指… | Skill B(如发货/履约侧)可能指… |
|---|---|---|
| 卖了多少 / 销量 | 下单量、成交金额 | 已出库件数、妥投量 |
| 货到哪了 | 订单物流状态字段(若交易库有镜像) | 仓储发运、在途、签收 |
| 退了多少 | 退款金额 | 退货入库量 |
| 查一下这个单 / 这个货 | 订单号、买家信息 | 运单号、仓位库存 |
不同部门用的数据源不一致,挂的 Skill 也不是同一个,不能指望用户每次手动指定。
石油现场同理:「产了多少油」在生产库和工程技术库之间也会撞车,机制一样,只是词换成了产量/注气/措施。
没有回归语言。
团队只会说「感觉不准」,不会说「本轮失败里 30% 是选表,还是选字段失败」。
2.3 转折点
后来反馈通路打通、开始按错因改知识之后,分层架构(入口 / 路由 / 领域 / 字典 + 回归)大约半个月就从实践里定型了——比起步包那两个月短很多,因为这时候已经知道「改哪一层、用什么题验收」。
根因可以压成一句:
把本该写成说明书需要规则与分层文档的东西,全部丢给模型「临场发挥」。
模型适合理解自然语言、组织回答;对于查询数据对准确率有要求的不适合在无规则时稳定完成「进哪个系统、选哪张表、用哪个算法」这种分类题。
所以要把 Skill 当成小型后端:入口、路由、领域规则、字典、测试,各管一段。
3. Skill 内部怎么分层(写到能落 SQL)
「统一」不等于只做一个 Skill。
更稳妥的目标是:每个问数 Skill 内部工作流一致、知识分层、关键路由可追踪;生产库和工程库可以各做一个 Skill,但必须先解决「进哪扇门」即用哪个skill。
下面以电商取数为例说一层一层怎么写,石油现场对照附在括号里。
3.1 四层分工
| 层 | 典型文件 | 写到什么粒度 |
|---|---|---|
| 入口 | SKILL.md |
固定步骤:定 Skill → 选表 → 读口径 → 自检 → 执行;只读;不贴计算公式 |
| 路由 | intent / clarifications / skill-routing | 口语 → 首选表 → 见指标编号;两种理解都合理则给 A/B;若已判定属于另一套业务库,本 Skill 不查数,只告诉用户去用对应 Skill |
| 领域规则 | metrics、WHERE 说明、JOIN 说明 | 指标唯一写全;过滤写到列;关联写到 ON 键 |
| 字典与测试 | schema 分片、golden、评测题 | 字段有什么;期望是什么;出现失败改哪个文件 |
上面表格里「去用对应 Skill」就是常说的转交,举个现场例子:
- 用户问「昨天出库了多少」→ 当前若在交易 Skill 里,应直接说:这题归履约 Skill,请改用那个;不要用订单表的发货状态字段硬凑一个数。
- 反过来,用户问「这单成交金额多少」→ 履约 Skill 应转给交易 Skill,不要用出库件数 × 单价硬算。
石油现场同理:在工程技术 Skill 里被问「开发井口昨天产了多少油」,应转给生产数据 Skill,别用试油日报字段硬凑。
注意:转交只要一句话指到正确 Skill;不要在转交时把对方怎么算(字段、公式)写进本包——那叫口径渗入影响后续计算查询。细节见第 5 章。
优化路由不必重写全部口径;补字段说明不必改工作流。这才叫分层,而不是「文件夹好看」。
3.2 目录示例
my-askdata-skill/
SKILL.md
references/
00-meta/ # 维护公约、编号总表
10-route/ # 跨系统边界、选表、澄清
20-domain/ # 口径、WHERE、JOIN
30-schema/ # 表与字段
40-qa/ # 回归样例
scripts/ # 脚本执行代码,或辅助工具
目录同时服务两件事:人维护时知道改哪;Agent 按需加载时知道读哪。
一次问答只应装入当前系统、当前候选表相关文档,而不是整包说明书。
3.3 系统内选表:先定库,再按映射与优先级选表
同词异义在企业取数里很常见(电商的「销量」「货到哪了」「退款」,石油的「产量」「注气」「措施」),所以我们把选表拆成两步,都落在可改的规则文档里,而不是靠模型临场猜:
- 先定业务库:交易还是履约(石油里是生产数据还是工程技术;写在
skill-routing;两可则澄清,已能判定属另一库则转交); - 再在本库内选表:查「问题类型 → 推荐表」映射(写在 intent / table-fit);
- 附优先级:月度汇总类问题先走月度汇总表;单笔订单明细只用于点查、异常名单,且必须限流(石油里:油田/区块月汇总优先,单井日明细限流)。
这样做的直接好处是可追问、可改规则:「为什么选了这张表?」能指到某一行映射;选错了就改那一行,而不是调一句玄学 Prompt。
3.4 统一步骤(质量基线)
建议所有问数 Skill 共用同一套节奏:
- 前置检查(时间、只读、权限)
- 定库:生产 or 工程技术;属另一库则转交;两可则先给跨库澄清选项
- 按需加载本库知识
- 本域澄清(未说清才问):如下单/成交、当日/累计、已付/待付(石油里:试油/修井、日产/累计、设计/实钻);用户已钉死则跳过
- 库内选表 + 读口径 + 写 SQL + 自检
- 执行 + 按返回结果解释(附来源表与过滤条件)
步骤一致,评测才有共同标尺;否则 A 模块爱澄清、B 模块直接出 SQL,评分无法横向比较。定库前后两处澄清的分工,见第 5.1 节。
4. 知识怎么写:唯一源、同粒度、可引用
4.1 指标只写一处
「怎么算」的完整说明,只放在口径文档(metrics)里;入口、路由、样例题里不要再抄一遍公式,只写一行引用,例如:
见 M01·下单量
见 M02·成交量
为什么要两个编号?因为用户都说「卖了多少」,背后却是下单量和成交量两套算法(见 §1)。
若只写一个糊成一团的「销量」,改漏、答错都查不清。
所以:同名不同算法,就拆成两个编号;回答时也要说清楚本次用的是哪一个。
石油里的「产油」同理——试油阶段的折算日产、投产后的井口日产,也应是两个编号,别混称「产量」不声明。(对应电商里:下单量、成交量拆成两个编号。)
对开发同学来说,编号不是炫技,只是约定:改算法只改一处,别处靠编号找到它。
4.2 WHERE 与 JOIN 必须一样具体
| 类型 | 合格写法 | 不合格写法 |
|---|---|---|
| 过滤(精确) | 「订单号 SO202401」→ 订单号列精确匹配;「某日成交」→ 用成交日期列 | 「订单号模糊匹配一下」;用创建日期冒充成交日期 |
| 过滤(范围) | 「华东大区」→ 按大区/组织规则展开(写清用哪张关联表) | 用订单号 LIKE 'HD%' 冒充华东全量 |
| 关联 | 订单表 JOIN 用户表 ON 用户ID;写清内连/左连 |
「订单和用户表关联一下」 |
再补一句给非石油同学:
订单表里往往存的是内部用户 ID,用户却说手机号——所以要先连用户表,用手机号换 ID。石油现场同理:试油日报存内部井 ID,用户说井号(如 FY210H),要先连井基础表换 ID。都是「业务表要 JOIN 维度表才能按用户嘴里的字段查」这一类工程问题。
4.3 澄清只给选项,例外只管边界
澄清:2~3 个选项,例如
- A. 下单量(交易库,看订单表)
- B. 成交量(交易库,看支付表)
或已经确认是交易语境,但没说清:
- A. 看某天的成交额
- B. 看年初至今累计
石油现场对应:A. 试油求产(工程技术库)B. 开发井口日产(生产数据库);进库后再问 A. 当天折算日产 B. 该层累计。
转交时只说「请用生产数据 / 工程技术 Skill」,不要把对方计算公式抄进本包。
4.4 表文档写「有什么」,口径文档写「怎么算」
字段列表服务于选列;计算公式服务于选算法。混在一起,改字段注释时容易误伤业务规则。
字段是否存在,以数据库元数据查询为准,不拿「中文长得像」当证据。
举个通俗例子:一张销售明细表里既有「当日销售额」,又有「年初至今累计销售额」。
用户问「昨天卖了多少」,却拿累计字段去答,数字会差得离谱——列没选错语法,但答非所问。
项目实践中石油日报里「日产油」和「累产油」并存,也是同一类坑。
4.5 新系统借鉴旧 Skill:只借壳,不借肉
把生产库 Skill 的写法搬到工程技术库时:
| 可以抄结构 | 必须重写内容 |
|---|---|
| 目录、步骤、自检形态、评测框架 | 连接配置、表映射、全部指标与 SQL 模板 |
| 编号指针写法、澄清文档形态 | WHERE/JOIN 规则、回归题 |
自检句:删掉生产库特有的表名和算法后,工程技术包是否还能独立回答试油/钻井类问题?反过来亦然。
5. 多 Skill 并列:先关门禁,再进库选表
5.1 顺序不能反(含澄清)
完整一点应是:
问句
→ 定 Skill(交易 or 履约)
├─ 已能判定属另一库 → 转交,结束
└─ 两库都像 → 先澄清(给 A/B,如:下单量 vs 成交量)
→ 进入本库后:本域澄清(用户没说清才问;已钉死则跳过)
例如:下单还是成交?当天还是累计?已付还是待付?订单号精确还是模糊?
→ 以下接 §3.4 第 4 步起:库内选表 → 读口径 → 自检 → 执行
两处澄清不要混:
| 时机 | 问什么 | 举例 |
|---|---|---|
| 定库之前 | 进哪个 Skill | A. 下单量(交易)B. 已出库件数(履约) |
| 进库之后 | 本库内怎么收窄 | A. 当天成交额 B. 年初至今累计;或 A. 下单 B. 退款 |
库都没定就生成 SQL,属于提前答题;本域条件没钉死就直接汇总,也容易答非所问。
5.2 对照表要写在 routing 里
把第 2.2 节那张对照表写进两边 Skill 的 skill-routing,并且对称:
- 交易侧遇到「出库了没、在途多少、仓库还剩多少」→ 转交履约/仓储 Skill;
- 仓储侧遇到「成交金额、是否已付款、退款到账了没」→ 转交交易 Skill。
石油落地时同样对称即可:生产侧遇到试油日报/钻井/录井 → 转交工程技术;工程侧遇到井口日产/核实/措施增油 → 转交生产数据。机制相同,只是对照表里的词换成现场说法。
对照表的价值是:让模型少猜,让开发者改规则有落点。
5.3 对称铁律
两边 Skill 都要写:
- 不执行对方库 SQL
- 不用近似字段冒充(尤其禁止用「下单量」冒充「成交量」,或用「出库件数」冒充「成交件数」)
- 转交一句话,不讲对方算法
- 不把对方指标编号粘进本包 metrics
6. 回归:把「感觉不准」翻译成「改哪个文件」
6.1 最小评测闭环
题库批量提问 → 记录 SQL/用表/是否澄清/是否执行成功 → 对照期望 → 出通过率,并做错因统计。
样例题可以很土、很现场,例如:
- 「订单 SO202401 成交金额多少」(应进交易库、带成交日期)
- 「这个买家下过几单」(交易库用户维度,不必硬联物流表)
- 「华东大区昨天卖了多少」(未说清下单还是成交 → 应澄清)
- 「这批货出库了没」(交易库应转交履约,不得用订单状态硬答)
石油现场对应一组:试油日报产油、开钻完钻日期、哈得昨天产量(应澄清)、开发井口日产(工程库应转交)。
6.2 四类错因
| 错因 | 开发动作 |
|---|---|
| 选表错 | 改路由映射、适用/不适用说明 |
| SQL 错 | 补字段确认、修模板、更新表结构文档 |
| 口径错 | 改 metrics / WHERE / JOIN(列选错、日期列用错也算) |
| 该问没问 | 补澄清与跨系统对照 |
知识或路由变更后跑冒烟;合并前跑扩大回归。
评测脚手架可共用,题目按系统分目录,别拿生产库的题测工程库。
6.3 执行前自检(示例)
- Schema 前缀正确,无串库表名
- 订单号优先精确匹配;禁止用订单号前缀模糊冒充全量(石油里:井号精确,禁止用前缀
LIKE冒充全油田) - 列已做元数据确认(成交额 vs 累计、成交日期 vs 创建日期;石油里:日产 vs 累产、日报日期 vs 创建日期)
- 指标钉死条件已写入
- 单笔/批量明细已限流,或先走汇总表(石油里:单井日明细限流)
- JOIN 键正确(常见:订单表
用户ID= 用户表用户ID;石油里:业务表井ID= 井基础表井ID) - 仅只读
失败就报失败,禁止用「分析报告」口吻补造数字。
7. 我们认的几条工程原则
- 分类决策交给规则,语言理解留给模型。
- 上下文按路径加载,不靠整包硬灌。
- 计算公式只保留一份原文,其它地方引用编号。
- 过滤规则与关联规则写到同一工程粒度(列 / ON 键)。
- 复制目录可以,复制业务算法不行(交易 ↔ 履约尤其如此)。
- 用错因分布指导迭代,而不是用「我觉得」。
仍未自动解决的事
- 取数对了,不等于会做「销量为什么掉了」的归因分析;两套能力如何共享知识要单独设计。(石油现场:「产量为什么掉了」同理。)
- 线上表结构变更会导致文档「沉默过期」,需要元数据对比。
- 用户体感还包括解释是否清楚、交互是否顺,不只是 SQL 对错。
模型会继续变强,但说明书是否分层、口径是否唯一、跨库是否门禁、改完是否可测,仍然决定你的系统能不能在真实企业里活过第三个月。
附录 目录树
my-askdata-skill/
SKILL.md
references/
00-meta/
doc-boundaries.md
id-index.md
10-route/
skill-routing.md
intent-routing.md
clarifications.md
table-fit.md
20-domain/
metrics-and-exceptions.md
scope-filters.md
joins.md
30-schema/
schema-index.md
schema-by-prefix/
tables.json
40-qa/
golden-queries.md
scripts/
execute_sql.py
check_config.py
写给开发者的智能问数 Skill 维护手册
分层、消歧、回归:让 Agent 说明书别变成无法合并的屎山
面向:正在用 Cursor / Agent Skill 做 NL2SQL、企业问数的开发与架构同学
(例子优先用电商/物流等通用场景,石油现场作为对照附在后面)
阅读时间:大约一刻钟
你可能已经会让模型「写出能跑的 SQL」了。
这篇文章想聊的是下一步更难受、也更值钱的事:怎么把 Skill 知识库写成可维护的工程资产——尤其当你手里不止一个业务库(比如生产数据一套、工程技术又一套),还要挂在同一个助手上时。
1. 我们真正卡住的地方,往往不是「模型会不会写 SELECT」
搭问数 Skill 的第一周通常很爽:扔进表结构,加两句约束,连上只读库,演示能出数。
难受从第二个月开始:
- 用户随口问「这个产品卖了多少」,交易库 Skill 和履约库 Skill 都能各自查一版数,系统却答成用户不要的那一种;
- 数据库里表和字段描述长得像,智能体检索时分不清,找错表找错字段,查出来的不是用户想要的。
- 同一个计算公式被多处文件引用,改一处漏两处;
- 目录拆了,链接还指着旧路径,Agent 读到两套互相打架的说明书;
- 改完规则只能靠人工抽几问,说不清到底变好了还是变坏了。
换句话说:瓶颈从「生成 SQL」转移到了「知识怎么组织、决策怎么可调试、改完怎么验收」。
这种同词异义不是石油独有。先用大家更熟的「销量」把机制说清,再回到现场:
用户问「这个产品卖了多少」,至少可能是两回事——
下单量:购物车里点了购买、生成了订单(还没付款也可能算进去);
成交量:钱已经付清、才算真正卖掉。
听起来都是「销量」,背后却是两套统计、两张表、两套算法;答错一种,业务侧会觉得系统「胡说八道」。
石油现场也一样:「产了多少油」可能指试油阶段的折算日产(工程技术库),也可能指投产后井口日产(生产数据库)——同词异义,只是词换成了「产油」。
本文不写指标百科,只讲编写方法:目录怎么分、每层写多细、跨库怎么拦、错了怎么归因。
2. 从「能演示」到「能维护」:常见崩法
2.1 起步包长什么样
多数团队一开始只有三样东西:
- 表结构说明(整份或按前缀切开)
- 偏长的
SKILL.md - 只读执行脚本
这也是我们做初版时的样子:单库、问题涉及的表不多、问法固定时,把字段备注描述清楚,就足够证明——约束写清楚,模型可以生成可用 SQL。
这段起步包我们自己踩了大约两个月:内部评测能跑通,但迟迟拿不到客户侧验证,就不知道该往哪改——没有真实反馈,迭代等于空转。工期拉长的主因不是「写不动」,而是验不了、不敢大改。
2.2 复杂度上升后的五类故障
§1 那几条痛点,拆开看就是下面五类:
口径复制粘贴。
同一个「销售额」,在 metrics、WHERE 说明、样例题里写了三种算法,改一处漏两处,线上表现像随机数。
说明书自相矛盾。
被引用的文件更换地方了,入口没改,导致无法直接找到该文件;
明细当汇总。
没有「先用汇总表、明细必须限流」的硬约束,模型把全平台几百万条订单明细一把拉出来再口算加总——数据量一大,算术幻觉就来了。
多 Skill 抢答。
两个问数 Skill 同时挂着时,用户随口一句「卖了多少」「货怎么样了」,两边都能圆上,不能靠模型临场猜该进哪扇门。
常见撞车说法可以先记成对照表(写进两边的 routing):
| 用户随口说 | Skill A(如下单/交易侧)可能指… | Skill B(如发货/履约侧)可能指… |
|---|---|---|
| 卖了多少 / 销量 | 下单量、成交金额 | 已出库件数、妥投量 |
| 货到哪了 | 订单物流状态字段(若交易库有镜像) | 仓储发运、在途、签收 |
| 退了多少 | 退款金额 | 退货入库量 |
| 查一下这个单 / 这个货 | 订单号、买家信息 | 运单号、仓位库存 |
不同部门用的数据源不一致,挂的 Skill 也不是同一个,不能指望用户每次手动指定。
石油现场同理:「产了多少油」在生产库和工程技术库之间也会撞车,机制一样,只是词换成了产量/注气/措施。
没有回归语言。
团队只会说「感觉不准」,不会说「本轮失败里 30% 是选表,还是选字段失败」。
2.3 转折点
后来反馈通路打通、开始按错因改知识之后,分层架构(入口 / 路由 / 领域 / 字典 + 回归)大约半个月就从实践里定型了——比起步包那两个月短很多,因为这时候已经知道「改哪一层、用什么题验收」。
根因可以压成一句:
把本该写成说明书需要规则与分层文档的东西,全部丢给模型「临场发挥」。
模型适合理解自然语言、组织回答;对于查询数据对准确率有要求的不适合在无规则时稳定完成「进哪个系统、选哪张表、用哪个算法」这种分类题。
所以要把 Skill 当成小型后端:入口、路由、领域规则、字典、测试,各管一段。
3. Skill 内部怎么分层(写到能落 SQL)
「统一」不等于只做一个 Skill。
更稳妥的目标是:每个问数 Skill 内部工作流一致、知识分层、关键路由可追踪;生产库和工程库可以各做一个 Skill,但必须先解决「进哪扇门」即用哪个skill。
下面以电商取数为例说一层一层怎么写,石油现场对照附在括号里。
3.1 四层分工
| 层 | 典型文件 | 写到什么粒度 |
|---|---|---|
| 入口 | SKILL.md |
固定步骤:定 Skill → 选表 → 读口径 → 自检 → 执行;只读;不贴计算公式 |
| 路由 | intent / clarifications / skill-routing | 口语 → 首选表 → 见指标编号;两种理解都合理则给 A/B;若已判定属于另一套业务库,本 Skill 不查数,只告诉用户去用对应 Skill |
| 领域规则 | metrics、WHERE 说明、JOIN 说明 | 指标唯一写全;过滤写到列;关联写到 ON 键 |
| 字典与测试 | schema 分片、golden、评测题 | 字段有什么;期望是什么;出现失败改哪个文件 |
上面表格里「去用对应 Skill」就是常说的转交,举个现场例子:
- 用户问「昨天出库了多少」→ 当前若在交易 Skill 里,应直接说:这题归履约 Skill,请改用那个;不要用订单表的发货状态字段硬凑一个数。
- 反过来,用户问「这单成交金额多少」→ 履约 Skill 应转给交易 Skill,不要用出库件数 × 单价硬算。
石油现场同理:在工程技术 Skill 里被问「开发井口昨天产了多少油」,应转给生产数据 Skill,别用试油日报字段硬凑。
注意:转交只要一句话指到正确 Skill;不要在转交时把对方怎么算(字段、公式)写进本包——那叫口径渗入影响后续计算查询。细节见第 5 章。
优化路由不必重写全部口径;补字段说明不必改工作流。这才叫分层,而不是「文件夹好看」。
3.2 目录示例
my-askdata-skill/
SKILL.md
references/
00-meta/ # 维护公约、编号总表
10-route/ # 跨系统边界、选表、澄清
20-domain/ # 口径、WHERE、JOIN
30-schema/ # 表与字段
40-qa/ # 回归样例
scripts/ # 脚本执行代码,或辅助工具
目录同时服务两件事:人维护时知道改哪;Agent 按需加载时知道读哪。
一次问答只应装入当前系统、当前候选表相关文档,而不是整包说明书。
3.3 系统内选表:先定库,再按映射与优先级选表
同词异义在企业取数里很常见(电商的「销量」「货到哪了」「退款」,石油的「产量」「注气」「措施」),所以我们把选表拆成两步,都落在可改的规则文档里,而不是靠模型临场猜:
- 先定业务库:交易还是履约(石油里是生产数据还是工程技术;写在
skill-routing;两可则澄清,已能判定属另一库则转交); - 再在本库内选表:查「问题类型 → 推荐表」映射(写在 intent / table-fit);
- 附优先级:月度汇总类问题先走月度汇总表;单笔订单明细只用于点查、异常名单,且必须限流(石油里:油田/区块月汇总优先,单井日明细限流)。
这样做的直接好处是可追问、可改规则:「为什么选了这张表?」能指到某一行映射;选错了就改那一行,而不是调一句玄学 Prompt。
3.4 统一步骤(质量基线)
建议所有问数 Skill 共用同一套节奏:
- 前置检查(时间、只读、权限)
- 定库:生产 or 工程技术;属另一库则转交;两可则先给跨库澄清选项
- 按需加载本库知识
- 本域澄清(未说清才问):如下单/成交、当日/累计、已付/待付(石油里:试油/修井、日产/累计、设计/实钻);用户已钉死则跳过
- 库内选表 + 读口径 + 写 SQL + 自检
- 执行 + 按返回结果解释(附来源表与过滤条件)
步骤一致,评测才有共同标尺;否则 A 模块爱澄清、B 模块直接出 SQL,评分无法横向比较。定库前后两处澄清的分工,见第 5.1 节。
4. 知识怎么写:唯一源、同粒度、可引用
4.1 指标只写一处
「怎么算」的完整说明,只放在口径文档(metrics)里;入口、路由、样例题里不要再抄一遍公式,只写一行引用,例如:
见 M01·下单量
见 M02·成交量
为什么要两个编号?因为用户都说「卖了多少」,背后却是下单量和成交量两套算法(见 §1)。
若只写一个糊成一团的「销量」,改漏、答错都查不清。
所以:同名不同算法,就拆成两个编号;回答时也要说清楚本次用的是哪一个。
石油里的「产油」同理——试油阶段的折算日产、投产后的井口日产,也应是两个编号,别混称「产量」不声明。(对应电商里:下单量、成交量拆成两个编号。)
对开发同学来说,编号不是炫技,只是约定:改算法只改一处,别处靠编号找到它。
4.2 WHERE 与 JOIN 必须一样具体
| 类型 | 合格写法 | 不合格写法 |
|---|---|---|
| 过滤(精确) | 「订单号 SO202401」→ 订单号列精确匹配;「某日成交」→ 用成交日期列 | 「订单号模糊匹配一下」;用创建日期冒充成交日期 |
| 过滤(范围) | 「华东大区」→ 按大区/组织规则展开(写清用哪张关联表) | 用订单号 LIKE 'HD%' 冒充华东全量 |
| 关联 | 订单表 JOIN 用户表 ON 用户ID;写清内连/左连 |
「订单和用户表关联一下」 |
再补一句给非石油同学:
订单表里往往存的是内部用户 ID,用户却说手机号——所以要先连用户表,用手机号换 ID。石油现场同理:试油日报存内部井 ID,用户说井号(如 FY210H),要先连井基础表换 ID。都是「业务表要 JOIN 维度表才能按用户嘴里的字段查」这一类工程问题。
4.3 澄清只给选项,例外只管边界
澄清:2~3 个选项,例如
- A. 下单量(交易库,看订单表)
- B. 成交量(交易库,看支付表)
或已经确认是交易语境,但没说清:
- A. 看某天的成交额
- B. 看年初至今累计
石油现场对应:A. 试油求产(工程技术库)B. 开发井口日产(生产数据库);进库后再问 A. 当天折算日产 B. 该层累计。
转交时只说「请用生产数据 / 工程技术 Skill」,不要把对方计算公式抄进本包。
4.4 表文档写「有什么」,口径文档写「怎么算」
字段列表服务于选列;计算公式服务于选算法。混在一起,改字段注释时容易误伤业务规则。
字段是否存在,以数据库元数据查询为准,不拿「中文长得像」当证据。
举个通俗例子:一张销售明细表里既有「当日销售额」,又有「年初至今累计销售额」。
用户问「昨天卖了多少」,却拿累计字段去答,数字会差得离谱——列没选错语法,但答非所问。
项目实践中石油日报里「日产油」和「累产油」并存,也是同一类坑。
4.5 新系统借鉴旧 Skill:只借壳,不借肉
把生产库 Skill 的写法搬到工程技术库时:
| 可以抄结构 | 必须重写内容 |
|---|---|
| 目录、步骤、自检形态、评测框架 | 连接配置、表映射、全部指标与 SQL 模板 |
| 编号指针写法、澄清文档形态 | WHERE/JOIN 规则、回归题 |
自检句:删掉生产库特有的表名和算法后,工程技术包是否还能独立回答试油/钻井类问题?反过来亦然。
5. 多 Skill 并列:先关门禁,再进库选表
5.1 顺序不能反(含澄清)
完整一点应是:
问句
→ 定 Skill(交易 or 履约)
├─ 已能判定属另一库 → 转交,结束
└─ 两库都像 → 先澄清(给 A/B,如:下单量 vs 成交量)
→ 进入本库后:本域澄清(用户没说清才问;已钉死则跳过)
例如:下单还是成交?当天还是累计?已付还是待付?订单号精确还是模糊?
→ 以下接 §3.4 第 4 步起:库内选表 → 读口径 → 自检 → 执行
两处澄清不要混:
| 时机 | 问什么 | 举例 |
|---|---|---|
| 定库之前 | 进哪个 Skill | A. 下单量(交易)B. 已出库件数(履约) |
| 进库之后 | 本库内怎么收窄 | A. 当天成交额 B. 年初至今累计;或 A. 下单 B. 退款 |
库都没定就生成 SQL,属于提前答题;本域条件没钉死就直接汇总,也容易答非所问。
5.2 对照表要写在 routing 里
把第 2.2 节那张对照表写进两边 Skill 的 skill-routing,并且对称:
- 交易侧遇到「出库了没、在途多少、仓库还剩多少」→ 转交履约/仓储 Skill;
- 仓储侧遇到「成交金额、是否已付款、退款到账了没」→ 转交交易 Skill。
石油落地时同样对称即可:生产侧遇到试油日报/钻井/录井 → 转交工程技术;工程侧遇到井口日产/核实/措施增油 → 转交生产数据。机制相同,只是对照表里的词换成现场说法。
对照表的价值是:让模型少猜,让开发者改规则有落点。
5.3 对称铁律
两边 Skill 都要写:
- 不执行对方库 SQL
- 不用近似字段冒充(尤其禁止用「下单量」冒充「成交量」,或用「出库件数」冒充「成交件数」)
- 转交一句话,不讲对方算法
- 不把对方指标编号粘进本包 metrics
6. 回归:把「感觉不准」翻译成「改哪个文件」
6.1 最小评测闭环
题库批量提问 → 记录 SQL/用表/是否澄清/是否执行成功 → 对照期望 → 出通过率,并做错因统计。
样例题可以很土、很现场,例如:
- 「订单 SO202401 成交金额多少」(应进交易库、带成交日期)
- 「这个买家下过几单」(交易库用户维度,不必硬联物流表)
- 「华东大区昨天卖了多少」(未说清下单还是成交 → 应澄清)
- 「这批货出库了没」(交易库应转交履约,不得用订单状态硬答)
石油现场对应一组:试油日报产油、开钻完钻日期、哈得昨天产量(应澄清)、开发井口日产(工程库应转交)。
6.2 四类错因
| 错因 | 开发动作 |
|---|---|
| 选表错 | 改路由映射、适用/不适用说明 |
| SQL 错 | 补字段确认、修模板、更新表结构文档 |
| 口径错 | 改 metrics / WHERE / JOIN(列选错、日期列用错也算) |
| 该问没问 | 补澄清与跨系统对照 |
知识或路由变更后跑冒烟;合并前跑扩大回归。
评测脚手架可共用,题目按系统分目录,别拿生产库的题测工程库。
6.3 执行前自检(示例)
- Schema 前缀正确,无串库表名
- 订单号优先精确匹配;禁止用订单号前缀模糊冒充全量(石油里:井号精确,禁止用前缀
LIKE冒充全油田) - 列已做元数据确认(成交额 vs 累计、成交日期 vs 创建日期;石油里:日产 vs 累产、日报日期 vs 创建日期)
- 指标钉死条件已写入
- 单笔/批量明细已限流,或先走汇总表(石油里:单井日明细限流)
- JOIN 键正确(常见:订单表
用户ID= 用户表用户ID;石油里:业务表井ID= 井基础表井ID) - 仅只读
失败就报失败,禁止用「分析报告」口吻补造数字。
7. 我们认的几条工程原则
- 分类决策交给规则,语言理解留给模型。
- 上下文按路径加载,不靠整包硬灌。
- 计算公式只保留一份原文,其它地方引用编号。
- 过滤规则与关联规则写到同一工程粒度(列 / ON 键)。
- 复制目录可以,复制业务算法不行(交易 ↔ 履约尤其如此)。
- 用错因分布指导迭代,而不是用「我觉得」。
仍未自动解决的事
- 取数对了,不等于会做「销量为什么掉了」的归因分析;两套能力如何共享知识要单独设计。(石油现场:「产量为什么掉了」同理。)
- 线上表结构变更会导致文档「沉默过期」,需要元数据对比。
- 用户体感还包括解释是否清楚、交互是否顺,不只是 SQL 对错。
模型会继续变强,但说明书是否分层、口径是否唯一、跨库是否门禁、改完是否可测,仍然决定你的系统能不能在真实企业里活过第三个月。
附录 目录树
my-askdata-skill/
SKILL.md
references/
00-meta/
doc-boundaries.md
id-index.md
10-route/
skill-routing.md
intent-routing.md
clarifications.md
table-fit.md
20-domain/
metrics-and-exceptions.md
scope-filters.md
joins.md
30-schema/
schema-index.md
schema-by-prefix/
tables.json
40-qa/
golden-queries.md
scripts/
execute_sql.py
check_config.py
更多推荐



所有评论(0)