把订单表、支付表和客户表的 Schema 交给模型,它很快就能写出一条可运行的 SQL。可当用户问“上个月收入是多少”,真正的问题才开始:收入是下单金额、实收、净收款还是财务确认收入?按下单时间还是确认时间?退款归属哪个月?
这些不是模型应该自由推断的常识,而是企业自己的业务合同。Agent 能力越强、执行链越长,一个错误定义被传播到报告和动作中的代价就越大。
Schema 描述数据的形状;语义层规定数据在什么条件下代表什么事实、允许怎样聚合。模型可以帮助发现冲突、起草定义,却不能替指标负责人决定口径。
语义层、本体和目录各管什么
资产目录回答“有什么、在哪里、谁负责”;语义层回答“怎么算、能按哪些维度分析”;业务本体回答客户、账户、订单等概念如何识别和关联。执行与治理系统则强制实施权限、预算和审计。
本体不一定要从复杂知识图谱起步。一个受治理的实体关系模型,能明确主键、基数、有效期和身份映射,就已经解决很多 Join 放大和概念混用问题。重要的是定义可引用、可版本化、可被查询编译或验证,而不是图画得多复杂。
六类语义资产缺一不可
| 资产 | 至少要明确 | 缺失后的典型错误 |
|---|---|---|
| 指标 | 公式、单位、时间口径、粒度、聚合、版本、负责人 | 把支付金额当确认收入;比率直接平均 |
| 实体 | 主键、唯一性、关系方向、基数、有效期 | 一对多 Join 放大金额;账户与客户混用 |
| 维度 | 层级、合法取值、适用指标、历史归属 | 用当前地区解释历史业绩 |
| 同义词 | 业务域、语言、候选概念与不可等同项 | 把营收、销售额和回款无条件合并 |
| 业务规则 | 状态过滤、币种、财务周期、用途、生效区间 | 测试订单进入正式报表 |
| 验证样例 | 问题、口径、查询、快照、预期结果、验证人 | 旧 SQL 被当成永久正确答案 |
这些资产可以分布在词汇表、指标服务、目录和样例库中,但必须通过稳定 ID 与版本关联。复制多份自然语言说明,通常只会制造新的漂移。
“收入”案例:先绑定定义,再写 SQL
假设团队同时维护交易总额、实收金额和财务确认收入。用户只说“收入”时,可靠流程是:
- 检查当前报表或会话是否已绑定某个指标;没有明确上下文就澄清。
- 将“上个月”转换为指定时区的具体区间,确定支付时间还是确认时间。
- 读取退款、税费、币种和内部账户排除规则。
- 先形成指标、维度、过滤与版本组成的语义计划,再编译查询。
一个最小指标契约可以长这样:
{
"metric_id": "commerce.period_net_receipts",
"version": "1.0",
"definition": "期间成功收款减期间成功退款",
"expression": "sum(receipt_cny) - sum(refund_cny)",
"time_fields": {"receipts": "paid_at", "refunds": "refunded_at"},
"timezone": "Asia/Shanghai",
"grain": "calendar_day",
"unit": "CNY",
"allowed_dimensions": ["channel"],
"missing_input_policy": "unknown_not_zero",
"effective_from": "2026-08-01",
"test_suite_ref": "tests/net-receipts-v1"
}
缺失输入记为未知,而不是零;退款与收款应先按兼容粒度聚合,再对齐计算,不能直接连接两张明细表造成乘积。最终答案还应带出采用的指标版本、时间字段、数据水位和限制。
语义如何进入运行链路
语义资产只有进入执行与验证,才不只是文档:
- 检索阶段根据业务域、实体和用途找到候选定义,冲突时保留多个候选。
- 规划阶段形成语义计划:指标 ID、版本、粒度、维度、过滤、关联和假设。
- 查询阶段由编译器或生成器把计划转成 SQL、DAX 或其他查询,并执行静态检查。
- 执行阶段重新实施权限、资源和用途限制;描述里的
policy_ref不能替代鉴权。 - 回答阶段展示关键口径和限制,让业务用户知道这个数字到底是什么。
Snowflake 语义视图与 Cortex Analyst展示了语义模型如何为自然语言查询提供表、关系、指标和验证样例。厂商配置说明了可落地形态,但不能证明某套定义适合另一家企业。
版本治理比“补充更多描述”更重要
口径变化必须有状态和生效区间。草稿、审核中、已发布、已废弃是不同状态;引用旧版本的报表不能静默切到新版本。兼容变更与破坏性变更也应区分:增加描述可能兼容,改变公式、时间字段或粒度通常需要新版本和影响分析。
已验证查询同样会失效。它应绑定语义版本、Schema 版本和数据快照,并记录验证人和不变量。所谓 Verified Query 不是复制一条历史 SQL,而是保存一个在明确条件下经过确认的问句—语义—查询关系。
用不变量和变形测试验收
仅对比一个查询结果不足以评估语义正确性。测试集应覆盖:
- 同义词与歧义词的澄清行为;
- 粒度和 Join 基数,防止金额放大;
- 时间边界、时区、财务周期和历史维度归属;
- 指标可加性,例如比率不能跨组直接平均;
- 未知、空集合和零值的区分;
- 版本变更后的兼容性与受影响查询;
- 权限不同用户是否仍得到合法口径下的结果。
还可以使用变形测试:扩大互斥时间区间时,可加指标应满足分段和;增加一个不相关过滤条件不应改变结果;交换维度展示顺序不应改变总量。它们比逐字比较 SQL 更接近业务事实。
从一个指标域开始
最稳妥的起点不是建设“企业全域本体”,而是挑一个高频决策域:整理 10–30 个关键指标、实体关系、时间与退款规则,再收集真实问法和错误案例。让 BI、Data Agent 和人工分析共同引用同一版本,观察冲突和返工是否减少。
语义层最终承担的是组织承诺:同一个词在同一上下文里,应得到可解释、可复算的同一个业务含义。没有这份承诺,模型越强,只会更快地把歧义包装成答案。