当 AI 开始成为新的数据查询入口时,很多团队都会遇到同一种困惑:为什么它已经能写出一条语法正确的 SQL,却还是给不出业务上正确的答案?
问题往往不在 SQL 语法,也不只是模型能力。真正缺失的是那些写在资深分析师脑中、散落在报表和脚本里、却没有被数据库结构表达出来的信息。
例如,“销售额”到底是商品标价、优惠后金额、实际支付金额,还是确认收入?一张订单表应当如何连接客户表?哪些测试账号必须从每一份内部报表中排除?仅凭表名和字段名,很难让任何人或模型稳定地推断出这些答案。
上一篇我们讨论了:AI 生成查询时,缺的到底是什么信息。今天我们继续向前一步,探讨这些信息不能在查询时临时猜,那应该在哪里被定义、由谁定义、以什么形式存在。
镜舟给出的答案是:把它们写成一份进入数据库执行路径的信息契约(Information Contract),也就是 Semantic View。
一份可用的语义定义需要包含什么?
给字段补几句注释,不足以支撑 AI 生成业务正确的查询。一份可用的语义定义,需要把“正确查询依赖的事实”逐项写清楚:
查询时会遇到的问题 | 定义时需要准备的内容 | 由谁确认 |
|---|---|---|
用户说的“销售额”对应哪个字段 | 指标表达式、同义词 | 懂业务的人 |
两张表之间怎么关联 | RELATIONSHIPS 声明的关系 | 建模者,系统按声明展开 |
一行数据代表什么粒度 | 表的 PRIMARY KEY 声明 | 人声明,系统据此使用 |
哪些规则每次查询都要生效 | 视图级 FILTER | 业务负责人 |
用户的自然语言怎么对应数据取值 | SYNONYMS、SAMPLE_VALUES | 人准备,或系统采样后确认 |
谁能看这份数据、怎么审计 | 视图上的权限声明与 EXPLAIN INLINE | 系统按已有权限体系执行 |
Semantic View 直接可以复用数据库已有的行列权限和审计能力,权限设在视图上而不是散落在每个下游工具里,谁能查什么、查过什么,都能在一个地方核实。
这张表把AI大模型的判断的时机从“查询时临场推断”转移到了“定义时提前确认”。当然,AI 仍然要理解问题:判断用户在问趋势、品牌还是某个具体指标,选择合适的维度和过滤条件。但它不需要再从物理字段里猜 amount 和 real_amount 哪个是业务要的金额,也不需要临时决定两张表该怎么连。
人的判断没有被替代,在更重要的阶段发挥作用:确认“实际支付金额”该如何计算,声明一行记录的粒度,确定哪些数据要被固定排除。一旦做出这些判断,就不再只存在于某一次对话、某段 Prompt 或某份手工 SQL 里,而是成为可以被反复调用的定义。
Semantic View:一次定义,处处复用
Semantic View 本身是数据库中的一等对象,可以在其中声明逻辑表、主键、关系、维度和指标,也可以附加同义词、示例值和面向 AI 的生成提示。
用上一篇里的钓鱼装备消费场景继续说明。t_item 记录每次购买,t_item_type 是分类维表,t_item_brand 是品牌维表:
CREATE OR REPLACE SEMANTIC VIEW sv_fishing_item_spend
TABLES (
items AS t_item PRIMARY KEY (id)
WITH SYNONYMS = ('fishing gear spend', 'purchase record')
COMMENT = 'one row = one purchase',
item_types AS t_item_type PRIMARY KEY (id),
brands AS t_item_brand PRIMARY KEY (id)
)
RELATIONSHIPS (
item_to_type AS items (item_type) REFERENCES item_types (id),
item_to_brand AS items (brand) REFERENCES brands (id)
)
DIMENSIONS (
items.buy_year AS YEAR(items.buy_date)
WITH SYNONYMS = ('purchase year', 'year'),
brands.item_brand_name AS brands.item_brand
WITH SYNONYMS = ('brand', 'make')
SAMPLE_VALUES = ['Woding', 'Handing', 'Liuzhiqiang']
)
METRICS (
items.total_real_spend AS SUM(items.real_amount)
WITH SYNONYMS = ('total amount paid'),
items.purchase_count AS COUNT(items.id)
)
AI_SQL_GENERATION 'For spend use total_real_spend; for counts use purchase_count.';这份定义里,RELATIONSHIPS 声明之后,后续查询不需要再手写 Join;METRICS 定义之后,查询不需要重新指定该聚合哪个字段;SYNONYMS 和 SAMPLE_VALUES 是给语言模型用的,帮它把“品牌”“year”这类自然语言词汇对应到具体的语义元素上,真正的计算仍然由 RELATIONSHIPS 和 METRICS 里定义的字段表达式完成;AI_SQL_GENERATION 则是直接写给 AI 的生成提示,用于消解字段命名上的歧义(比如 amount 和 real_amount 该用哪个)。
AI 与 BI 统一口径,无需各自维护
有了这份定义,“2024 年每个品牌实际花了多少钱,买了多少次”这个问题,可以直接用语义查询表达:
SELECT * FROM SEMANTIC_VIEW(
sv_fishing_item_spend
DIMENSIONS brands.item_brand_name
METRICS items.total_real_spend, items.purchase_count
WHERE items.buy_year = 2024
ORDER BY items.total_real_spend DESC
) AS sv;这条查询仍然是 SQL,但调用者只需要指定维度、指标、过滤和排序,不需要重复编写 Join 和聚合表达式。
Semantic View 也可以作为一张扁平化的宽表直接读取,这样不了解语义查询语法的 BI 工具,也能连接并复用同一套维度和指标定义:
SELECT items__buy_month, items__total_real_spend
FROM sv_fishing_item_spend
WHERE items__buy_year = 2024;一份定义,两种访问方式,AI Agent 和 BI 工具消费的是同一套指标口径,不需要各自维护一份。
结果可核验:支持逐行查找根因
语义查询不是一个黑盒承诺。需要核实时,可以用 EXPLAIN INLINE 查看展开后的真实 SQL:
EXPLAIN INLINE
SELECT * FROM SEMANTIC_VIEW(
sv_fishing_item_spend
DIMENSIONS brands.item_brand_name
METRICS items.total_real_spend
WHERE items.buy_year = 2024
) AS sv;返回结果:
SELECT `brands`.`item_brand` AS `item_brand_name`,
SUM(`items`.`real_amount`) AS `total_real_spend`
FROM `test`.`t_item` AS `items`
LEFT JOIN `test`.`t_item_type` AS `item_types` ON `items`.`item_type` = `item_types`.`id`
LEFT JOIN `test`.`t_item_brand` AS `brands` ON `items`.`brand` = `brands`.`id`
WHERE YEAR(`items`.`buy_date`) = 2024
GROUP BY 1;审查者看到的是实际使用了哪个字段、按什么关系连接、如何过滤和聚合,这也是“SQL 输入,SQL 输出”这条原则的具体体现,让可信度建立在可检查的执行过程上。
三层分工:系统执行、AI 理解、人确认
Semantic View 是数据库内与数据本身绑定的一等对象。通过一个完整业务问题的回答:理解问题 → 找到对应业务口径 → 把口径展开为可执行 SQL → 把结果变成人能理解的回答。这四个环节分别由三个不同层级承担,也对应不同的能力。
在镜舟 MIP(MirrorShip Intelligence Platform)里,这三层的分工是:
层级 | 产品 | 核心能力 | 负责回答的问题 |
|---|---|---|---|
L3 | MirrorPilot | 理解意图、规划分析、生成语义查询、解释结果 | “怎么分析” |
L2 | MirrorMind | 指标/维度/关系/口径 + 例外规则/缩写/背景 | “业务语义是什么” |
L1 | MirrorData | Semantic View 管理、SQL 展开、权限与优化 | “怎么算得对、算得快” |
在这个架构里,Semantic View 的职责是 MirrorData 内部、直接与 MirrorMind 交接的那一层对象,把已经确认、能够形式化的部分交给系统稳定地消费,而“判断这个数字对业务意味着什么的”过程,留给 Context 和人。
同时,这份契约只对已定义的语义范围负责。遇到新的业务域、还没确认的口径,或者需要多步推理的问题,仍然需要 AI 的生成能力和人的审核。
下一篇将进一步讨论:查询准确性从何而来,以及 Semantic View 如何界定自己的职责边界。
