主题
AI 敢用 · NL2SQL 语义层
场景 业务同学想自助查数,但「让大模型直接写 SQL」在企业里落不了地:同一个「营收」今天算出一个数、明天算出另一个数;模型可能引用到无权限的表;写出来的 SQL 没人敢在生产数据上跑。问题不在模型不够聪明,而在口径和边界不能靠模型的临场发挥。
我们的做法:在自然语言和 SQL 之间放一层语义模型——指标怎么算、能按什么维度看、表之间怎么关联,由数据团队一次性定义;问数时大模型只负责理解意图,SQL 由编译器按定义确定性生成。整体架构一张图:

能干什么
| 你想做的事 | 在平台里长这样 |
|---|---|
| 用大白话查数 | 「AI 查数」页输入「各支付渠道的营收,从高到低」,直接得到可执行 SQL |
| 保证指标口径永远一致 | 口径在语义建模里定义一次,之后每次问数编译出的过滤条件都一样 |
| 一个词对应多个口径时不被瞎猜 | 平台反问「你要查哪个业务模型?」,点选后按所选口径生成 |
| 拿到 SQL 后马上看数 | 「一键查询」跳到数据查询页真实执行,或复制/填入编辑器自己改 |
| 好问法沉淀复用 | 「存为示例」把这轮问答存成 few-shot,以后同类问题答得更稳 |
| 没建语义模型的表也想问 | 自动回退到按表结构生成(schema linking),照样可用 |
亮点
- 口径由定义保证,不由模型现编——大模型只产出「查哪个指标、按什么分组」的结构化意图,SQL 是编译出来的,同一指标永远编出同一口径
- 歧义反问、候选可点——多个模型/指标/取值说不清时主动澄清,不随便给一个看着对的答案
- 只生成、不执行——生成的 SQL 拿到「数据查询」页执行,走和手写 SQL 完全相同的逐表鉴权与引擎校验,AI 路径不可能绕过安全边界
- 模型看不到你无权的表——候选表在进入模型视野前就按你的权限过滤
走一遍:从建口径到出数
第一步,把口径定义成语义模型。 数据团队在「语义建模」里声明:基表是哪张、指标怎么聚合、口径过滤是什么、有哪些维度、维表怎么 join。下面是「销售大盘」模型——「营收」的口径过滤(状态 <> '已退款')就固化在这里,还带同义词(收入、GMV)让业务的各种叫法都能对上:

第二步,业务同学大白话问数。 「AI 查数」页输入「各支付渠道的营收是多少?从高到低排」。这个空间里恰好有两个模型都定义了「营收」(经营口径与财务口径),平台不替你拍板,反问并给出可点候选:

第三步,选定模型,SQL 编译出来。 点「销售大盘」后生成 SQL:口径过滤被折进聚合(SUM(amount) FILTER (WHERE 状态 <> '已退款')),路径标着「语义层 (NL2MQL2SQL)」和「只读」,下方列出参考到的基表与维表,以及「口径由模型定义保证,非模型现编」的说明:

第四步,一键查询,真实出数。 跳到「数据查询」页执行——和手写 SQL 同一个入口,提交即做语法检查和逐表权限检查,几秒后拿到按营收降序的四个渠道:

换任何人、换任何问法再问一遍「营收」,只要选的是同一个模型,过滤条件分毫不差——这就是「口径由定义保证」的含义。
问得更复杂时
- ReAct 自主多步:表多、问题需要探查时可勾选,模型自己搜表、看列、取样本值、自校验后再产 SQL,适合大 schema 场景
- 带鉴权 EXPLAIN 自检:生成的 SQL 先经引擎 EXPLAIN 校验(只校验不取数),首版有错会据错自动修正一次
- 反馈闭环:「存为示例」的问答对,以及执行确认成功的查询,会回流为 few-shot 示例,让后续生成越来越贴合本空间的问法习惯
- 对话里也能问:AI 助手「工小数」收编了同一套能力——聊天时问口径、要 SQL,用的是同一份模型定义,见智能问答