首页 / 文章

为何人工智能分析代理需要语义层而非原始SQL

针对原始表的文本转SQL功能会自行创建度量标准并忽略访问规则。通过MCP提供的类似Cube的语义层,则能为AI智能体赋予受业务规则约束的含义。

发布者:REACTAPP.TOP阅读约 12 分钟2739 词

来源: The Semantic Layer for AI Agents: How to Stop LLMs From Inventing Metrics

让人工智能分析工具编写SQL是快速生成令人惊叹的演示效果的最好方法。但若这些SQL直接作用于没有业务背景的原始仓库表,也会最快带来风险。出问题的地方不在语法,而在含义。

以“收入”这个词为例,我们需要明确它涵盖的内容:

  • 是毛收入还是净收入?
  • 是否已扣除退款?
  • 哪一列日期用于确定季度?
  • “活跃客户”是指下单时活跃,还是今天仍然活跃?
  • 适用哪种区域映射规则?
  • 采用哪种货币转换规则?
  • 该用户是否有权限查看该客户的数据?

原始的文本转SQL方法恰恰在这些问题上会出错。模型虽然能生成有效的SQL语句,数据库也能毫无问题地执行它,但结果数值仍可能错误。正因如此,分析工具需要在自身与业务数据之间添加一个语义层。Cube就是这类层的一个优秀示例,下文将以它作为实际案例进行说明。

模式本身不承载意义

文本转SQL是个不错的想法,它能让开发人员、分析人员及业务用户更快地开展工作。但数据仓库的模式往往无法承载人们所期望的意义。

表格包含诸如amount、status、created_at、customer_type、region_id和currency这样的列,但业内没人会用那种方式提问。没人会问“按region_id分组且status为‘paid’时的sum(amount)”。他们询问的是上个季度南印度的企业营收增长了多少。

那句话背后其实隐藏着诸多决策。什么是收入?什么才算企业客户?哪个日期标志着一个季度的开始?南印度地区该如何划分?退款和已取消的订单是否需要剔除?应适用哪种货币规则?提问者能看到哪些信息?模型可以对这些问题逐一做出猜测。不过,猜测并不能替代规范化的管理流程。如果客服的回答与控制面板显示的内容不一致,人们就会不再信任它。如果它使用了错误的表格数据,虽然数值看似合理,但实际上是错误的。如果它无视访问规则,答案就会导致数据泄露。

因此,真正的问题不在于模型是否能够编写SQL代码,而在于它是否根本应该去创造业务逻辑。

语义层的作用

语义层位于原始数据与数据使用者之间,负责将技术性的数据库结构转换为规范化的业务概念。它定义了指标、度量标准、维度、关联关系、分组、层次结构、访问规则、缓存规则、预聚合结果以及用于查询这些数据的 API,而非直接暴露表和列。

具体而言,orders.amount、customers.type、orders.created_at 和 refunds.amount 会分别转化为“收入”、“企业客户”、“订单日期”和“调整后的退款收入”。工作人员需要这样的术语体系。没有语义层时,工作人员需根据数据结构自行推断;有了语义层后,则可依据经过审批的定义开展工作。虽然工作人员仍可能出错,但由于无需再从原始表中重新构建指标定义,分析结果出现错误的一个主要原因便消失了。

这其实是一个类别而非单一产品。Cube、dbt的Semantic Layer(基于MetricFlow构建)以及Looker的LookML都在各自的生态系统中解决着相同的问题。此处重点介绍Cube,是因为它为分析代理提供的功能极为完善,不过架构比品牌更为重要。

为何Cube是绝佳的示例

Cube不仅仅是一个仪表板层。一个经过统一管理的模型可以为BI工具、嵌入式分析功能、API以及AI代理提供数据支持,而这些功能都是通过立方体、度量值、维度、连接、分段、层次结构、预聚合结果以及访问策略构建而成的。这些正是分析代理所需的精确构建要素。

其对设计的描述很好地概括了核心理念:分析代理并不直接查询数据仓库,而是查询语义层,而运行时则充当代理与数据仓库之间的防护机制。

比较每种方式向模型提供的数据。如果是原始表格,模型只能看到列名而无法获取其他信息;若是语义层,则模型还能收到已确认的概念、每个概念背后的计算逻辑、它们之间的关联关系、当前用户可操作的内容以及安全的查询方式。每次提问都重新发现业务逻辑是浪费资源的行为,因此智能体应查询已存储有这些信息的层。

连接与意义:MCP的适用场景

MCP是将人工智能助手与外部工具及数据相连的常用方式,但连接并不等同于理解。即便通过MCP让智能体直接访问原始仓库表格,它仍需自行推断其中的意义,这实际上只是问题换了个包装而已。

一种更有效的模式是让智能体通过语义层来获取信息:

AI agent
→ MCP client
→ semantic-layer MCP server (e.g. Cube's)
→ semantic layer (governed metrics, dimensions, joins, policies)
→ data warehouse

MCP负责处理访问请求,而语义层则负责解析含义。智能体不应询问数据库需要关联哪些表才能计算收入,而应向语义层请求已获批的收入指标及可使用的维度。

由于该领域发展迅速,很容易夸大其词,因此有两点需要注意。属于Cube Cloud的一部分、通过HTTPS及OAuth连接的官方Cube MCP服务器,与通过Smithery等渠道分发的社区版Cube MCP服务器有所不同,两者的信任度、支持力度及维护方式也存在差异,实际生产环境应选择官方的、受规范管理的方案。此外,原生MCP支持是近期才出现的功能,建立在这些产品多年来所提供的REST、SQL和GraphQL API之上。虽然它能正常工作,但属于2025到2026年的功能特性,使用时需根据实际运行的版本进行核对。

端到端更安全的架构

完整组合后的流程如下:

user question
→ AI analytics agent
→ MCP / tool call
→ semantic layer (approved metrics, dimensions, joins, segments, policies)
→ data warehouse
→ governed result
→ agent explanation

该智能体无法直接操作原始数据,它只能通过受控的接口来操作数据,这样团队就可以控制哪些指标存在、哪些维度有效、数据连接如何实现、允许使用哪些过滤条件、谁能够查看哪些行数据、答案是来自缓存还是预聚合数据,以及如何通过 API 提供查询功能。这比让模型直接编写 SQL 并期望业务逻辑能够正确实现要好得多。

实际案例:营收增长

假设需要查询上个季度的企业营收增长情况。在没有语义层的情况下,智能体需要自行推断哪个表存储营收数据、这些数据是毛营收、净营收、已确认营收还是已记账营收、是否需要排除退款金额、企业账户如何识别、哪个时间列代表上个季度、是否需要货币转换,以及该用户是否可以查看所有细分数据。虽然 SQL 语句可以执行,但执行并不等同于结果正确。

有了语义层之后,这些答案早已存在。收入是经过认可的度量指标,企业客户是经过认可的细分群体,订单日期是经过认可的时间维度,退款逻辑只需定义一次,访问策略则会根据请求者身份来应用。客服人员并非自行创造度量指标,而是调用已有的认可指标。这便将自然语言SQL生成与受规则约束的智能分析区分开来。

直接访问仓库可能会出什么问题

直接访问会让客服人员有太多主观猜测的空间,由此产生的错误也是可以预见的:

  • 度量指标错误:收入的计算方式与财务仪表板不同。
  • 连接错误:查询虽然能运行,但连接操作会导致行重复或记录丢失。
  • 缺少过滤条件:已取消的订单、测试账户、已删除的记录以及内部用户仍会包含在结果中。
  • 权限泄露:某个合法查询会返回该用户本不应看到的来自客户、团队或区域的数据。
  • 过时的逻辑:数据结构发生了变化,但代理程序仍沿用旧有的处理方式。
  • 看似合理的错误答案:在最糟糕的情况下,那些看似准确的数值实际上却是错误的。
  • 用于回答业务问题的代理程序需要比SQL生成机制更强的约束机制,它们需要语义层面的限制。

    在不暴露原始表结构的情况下使用SQL

    放弃灵活性并非实施治理的代价。成熟的语义层可以让SQL接口保持开放,但其指向的是受管控的对象而非物理表。在Cube的SQL API中,每个数据立方体或视图都表现为一个表,而其中的度量值、维度及分段则表现为列。由于它采用了Postgres的通信协议和语法,几乎所有支持Postgres的客户端都能与其连接。

    工具和代理仍保留SQL风格的查询方式,但模型决定了可查询的内容。代理不会直接遍历原始表格,而是使用经过审批的指标和维度进行操作,这种务实的方式更接近实际生产环境中的分析流程。

    访问规则与指标同样重要

    对于对话型代理而言,访问控制至关重要,因为聊天界面会引发各种开放式问题。当有人输入“按客户显示收入”时,系统必须知道该用户可以查看哪些客户、适用哪个区域或租户,以及是允许显示客户级详细信息还是仅返回汇总数据。

    Cube在语义层中应用访问策略和行级安全机制。这样的设计是有意为之:不应让任何人依赖智能体在未经提示的情况下自动回忆所有规则。在提示中写入“绝不对未经授权的数据进行披露”只是一种请求,而让该层限制特定用户查看某些行、维度及度量指标则是强制措施。强制措施的效果更为显著,且存在于数据层而非提示中。

    性能方面:缓存与预聚合

    对话式分析是一个迭代过程。用户可能先要求按地区查看收入,再按产品细分,接着与上季度对比,最后仅限企业客户的数据。如果每一步都转化为新的复杂数据仓库查询,延迟和成本就会迅速上升。

    Cube 的预聚合与缓存功能由其 CubeStore 引擎处理,可加快常见的分析查询速度。有报告称,将数据汇总操作移至 Cube 的存储系统中后,仓库成本大致降低了一半。因此,对于重复出现的问题,语义层除了具备治理功能外,还起到了提升性能的作用。

    该模式的优势体现

    那些需要回答有关收入、客户群体、产品使用情况、面向客户的分析功能、运营仪表板、关键绩效指标或指标解释等问题的系统,能从中获得最大收益,任何自助式商业智能场景也是如此。

    在已有重复定义的情况下,该模式的收益最为显著。只需一次性构建 ARR、MRR、收入、客户流失率、客户留存率、活跃用户数、转化率、毛利率、工单处理时间以及功能采用率等模型,后续所有系统都可以直接复用这些模型,而无需在每次查询内容变化时都重新计算。

    团队需注意的要点

    这一切都不是魔法,治理措施必须是实质性的,而非仅仅是个名义。不完善的模型会让智能体陷入困境。错误的指标定义虽然能实现治理,但得出的数据却是错误的。过于宽泛的访问策略仍会导致数据过度暴露。充斥着令人困惑的近似重复指标的模型会让智能体选错指标。而如果无法判断数据更新时间,答案看似最新,实际可能基于过时的数据。

    因此,关键问题不在于是否存在语义层,而在于该层是否足够完善,能让智能体安全地使用。模型必须要有文档记录、版本控制、经过测试、具备访问权限管理且易于理解,要与人们已信任的控制面板保持一致,与数据质量检查相衔接,并明确说明数据的更新状态及限制。薄弱的层会导致智能体给出低质量的答案。

    从原始SQL到受治理的分析

    不同方法之间的区别在于智能体能看到什么以及什么可能出错:

    • 纯文本转SQL:智能体只能看到仓库的表和列,主要风险在于人为设计的业务逻辑。
    • SQL加上架构文档:有所改进,但连接操作和指标仍容易被误用。
    • 仅使用语义层:智能体依据定义好的指标、维度、关系和规则工作,更安全,质量由背后的模型保障。
    • 语义层加上MCP:将受管控的分析功能以智能体工具的形式呈现,目前是最适合受控人工智能分析的方案。

    文本转SQL仍然有用,但在业务分析中应基于受管控的语义层而非对原始架构的猜测来执行。

    智能体接触业务数据前的检查清单

    • 首先将核心指标放入语义层中。
    • 明确列出哪些维度及连接是合法的。
    • 在该层实施访问策略和行级规则。
    • 在原本使用原始表格的位置提供受管控的 API。
    • 仅通过经过审批的官方工具通过 MCP 访问该层。
    • 记录每个智能体查询及其生成的 SQL 语句。
    • 为每个答案附带其背后指标的定义。
    • 在每个响应中说明数据的新鲜度。
    • 重新输入常见的业务查询,并将结果与可信的仪表板进行对比。
    • 禁止直接访问敏感的仓库表格。
    • 规定当请求的指标没有定义时该如何处理。
    • 让智能体学会回复“未定义”而非临时编造答案。
    • 像处理代码一样对指标定义进行版本控制。
    • 使用真实用户角色测试访问规则。
    • 注意那些会出错或产生模糊结果的查询。

    最重要的规则是:当某个指标未被定义时,智能体不应自行编造,而应请求进一步说明或表明该指标不可用。

    给产品团队的建议

    在将完整的仓库架构提供给新的分析智能体之前,先暂停并解决几项问题。明确它应回答的业务问题、已批准的指标、有效的维度以及安全的连接方式。确定谁可以查看哪些内容、数据需要保持多新鲜、哪些答案需要附带定义或引用,以及哪些查询必须被拒绝。只有这样,才能将经过筛选的信息呈现给智能体。

    Cube是一种构建数据表面的方法,而dbt Semantic Layer、LookML和MetricFlow则从其他角度解决相同的问题。其中的核心启示与具体产品无关——在处理业务数据之前,系统必须具备受管控的业务语义。

    核心要点

    将AI分析仅仅视为文本转SQL的任务是本末倒置的,因为语义管控才是更困难的部分。即便能够直接操作原始仓库表并写出完全有效的SQL语句,若使用虚构的指标、错误的连接方式、跳过访问规则,或是生成与仪表板数据矛盾的结果,依然会得到错误的业务结论。语义层通过引入经过审批的指标、维度、连接逻辑、策略及API,取代了需要人工解读的原始数据结构。MCP负责建立连接,语义层则提供数据含义,而受管控的分析系统需要两者兼备。

    相关阅读

  • 使用 Redis 为 LLM Agent 实现语义缓存:降低成本与延迟 — 语义缓存如何减少 LLM 的使用成本与延迟:嵌入向量、阈值设置、Redis 与 RedisVL、精度调优,以及如何在 Agent 工作流中实现子问题缓存。
  • 现代 AI 的运作原理:LLM、提示词设计、RAG、Agent 与 MCP 详解 — 用通俗语言解读 AI 技术栈:LLM 如何预测字符、四种提示词技巧、结合嵌入向量的 RAG 技术、ReAct Agent 循环机制,以及 MCP 的功能。
  • 实用笔记:MTG Bench——为何要在《万智牌》上测试大语言模型 —— 对《实用笔记:MTG Bench——为何要在《万智牌》上测试大语言模型》的详细操作指南:为采用该模式的团队提供的接口定义、校验规则以及可直接插入的代码片段。
  • 实用笔记:用于图结构RAG提取的本地大语言模型:2026年中期重新基准测试 —— 对《实用笔记:用于图结构RAG提取的本地大语言模型:2026年中期重新基准测试》的详细操作指南:为采用该模式的团队提供的接口定义、校验规则以及可直接插入的代码片段。
  • 深入理解LLM:使用MLX通过纯Python实现Qwen3-0.6B的推理 — 用约200行Python代码,通过MLX逐步实现LLM推理功能,涵盖分词器、RMSNorm、RoPE、分组查询注意力机制、SwiGLU、KV缓存以及采样过程。
  • 无需LLM,利用pgvector和Node.js在PostgreSQL中实现语义搜索 — 通过pgvector、MiniLM嵌入模型及Node.js在PostgreSQL中构建基于语义的搜索功能,涉及令牌、分块、向量、IVFFlat索引、距离运算符以及分数解读方法。
  • 16种RAG架构对比:哪种模式适合哪种问题 —— 梳理了从标准及混合检索到智能体、图结构及联邦式设计等四类层级中的16种RAG架构模式,并给出了逐月的构建顺序。
  • 利用本体与知识图谱解决半导体文档中的RAG问题 —— 介绍了一组基于DITA的EDA文档如何构建RDF/OWL本体、Neo4j图结构以及受本体约束的检索机制,从而将后续查询量减少了30%。
  • 停止让大语言模型编写HTML:用于AI报告的语义JSON组件 — 为何有一支团队将AI生成的报告从原始HTML转换为由确定性代码渲染的受限JSON格式,以及为何语义组件优于布局原语。