制造业 BI 自然语言查询:业务直接问"为什么毛利下滑"

Claude 中文知识站 Lv4

客户是一家华东的机械制造企业,2025 年营收 20 亿左右,5000 多号员工。他们 IT 体系其实挺齐全的——有数仓、有 Tableau、有自研的业务中台,但 CIO 跟我说:「我们业务人员就是用不来这些工具。」

我在他们公司蹲了一周,亲眼看到以下场景:

  • 销售副总想看「上季度哪个型号毛利下滑」,发邮件给 BI 团队,等两天拿到一张 Tableau 链接,发现维度不对,再发邮件,又等一天
  • 生产经理想看「上月某客户的交付准时率」,打电话给 IT,IT 说「你去 BI 门户搜一下」,生产经理说「我搜不到」
  • BI 团队 8 个人,60% 的时间在接临时需求,根本没空做真正的数据建模

典型的「工具都有,但链路不通」。我的任务是做一个 Agent,让业务人员直接用自然语言问问题。

初版翻车:schema 根本装不下

第一版我想得挺简单:业务问题 → 丢给 Claude → 生成 SQL → 执行 → 返回结果。经典的 Text2SQL。

拿到他们数仓文档一看我就懵了:47 个业务域、1283 张表、超过 2 万个字段

光把核心表的 schema 拼成 prompt 就 340K token,还没算字段注释、业务口径说明。context window 直接炸。

我第一反应是「那就塞个最相关的 schema」,但问题是:业务问问题的时候,他自己都不知道哪张表最相关。他问的是「这个月 A 客户订单情况」,背后可能涉及订单表、报价表、合同表、发货表、回款表五张主表,外加十几张维度表。

这个时候我才意识到,这不是一个 Text2SQL 问题,这是一个多阶段工程问题

架构:业务域切分 + 检索 + 验证执行 + 归因二次分析

改版之后整个链路变成四层:

层一:业务域切分 + schema 检索

把 1283 张表按业务域切分成 47 组(销售域、生产域、采购域、财务域、仓储域……)。每个域做一份「schema 摘要」,包含这个域的核心业务概念、关键表、常用字段、业务口径。

用户问问题进来,先让 Claude 判断「这个问题涉及哪几个业务域」,然后只把这几个域的 schema 摘要注入 context。如果涉及具体表,再做二次检索拉详细字段。

这个思路其实就是分层 RAG,Context 检索与 Rerank 里有讲过类似的分层检索模式。

层二:SQL 生成

拿到相关 schema 之后,让 Sonnet 生成 SQL。这里我做了几个约束:

  • 强制 JSON 输出,包含 sqldialecttables_usedassumptions 四个字段(参考 Prompt JSON Schema
  • assumptions 字段必须列出所有歧义假设(比如「我假设『毛利』是指销售毛利,不含税费」)
  • 不允许跨业务域 join,跨域必须拆成多个子查询

层三:验证执行

SQL 生成完不直接执行,要先过三道:

  1. EXPLAIN 分析:跑一次 EXPLAIN,看执行计划。如果预估扫描行数超过 1 亿,直接拒绝,要求 Claude 重写
  2. 成本估算:数仓按扫描量计费(他们用的是基于 Trino 的自研平台),超过 2.5 元的查询要业务二次确认
  3. 采样验证:先用 LIMIT 100 跑一次,让 Claude 判断结果是否合理(比如金额字段全是 0 明显不对),合理才放大查询

第一版没这些保护,有次一个业务员问「过去三年所有订单明细」,直接生成了个 SELECT * FROM order_detail 全表扫描 3.7 亿行,平台告警打爆我的 Slack。

最大的坑:业务问的是归因,不是 SQL

这个坑是上线一个月之后才发现的。

业务副总问:「上季度哪个型号毛利下滑得最狠?」

我的 Agent 返回:

1
2
3
型号 A:毛利率 23.4%,环比下降 8.7%
型号 B:毛利率 18.2%,环比下降 6.3%
...

副总看了一眼:「我知道 A 下滑了,我问你为什么。」

我当时就懵了。业务人员问「下滑得最狠」的潜台词是归因,不是 ranking。他要的是:「A 型号 Q1 毛利下滑 8.7%,主因是原材料涨价占了 5.2 个点,另外是华南区域打折促销占了 2.8 个点。」

这是一个多步分析任务,不是单次 SQL。

改版我加了一个「归因层」:

  1. 先识别用户问题类型(ranking / 归因 / 对比 / 趋势)
  2. 如果是归因类,自动分解成多个子查询(整体下滑幅度、按维度拆分、按时间拆分、同比对比)
  3. 把多个子查询结果合并,让 Opus 做归因分析
  4. 用自然语言解读输出

归因这一层必须用 Opus,Sonnet 做出来的归因经常是罗列数字,缺深度推理。这里的取舍思路我写过 CoT vs Direct,归因分析必须走 CoT。

度量:业务自查率从 7% 涨到 64%

上线三个月的数据:

  • 业务自查率:7% → 64%(从月活 1200 次业务问询中能独立完成的比例)
  • BI 团队临时需求量:月均 340 条 → 月均 87 条,降 74%
  • 平均响应时长:人工需求 1.7 天 → Agent 34 秒
  • 业务 NPS:从 -12 涨到 +41

BI 团队的角色也变了。原来 8 个人疲于奔命做需求,现在改成:

  • 3 个人维护业务域 schema 摘要和口径字典
  • 3 个人做复杂分析和建模
  • 2 个人做数据治理

BI 经理跟我说:「终于有时间做正经事了。」

成本:月账单 $918.44

拉了 3 月数据:

  • 总调用次数 36847(含验证、归因、多次重试)
  • 平均单次问题消耗 3.2 次调用(含一次 schema 检索、一次 SQL 生成、一次归因)
  • 模型分布:Haiku 41%(分类、schema 检索)、Sonnet 47%(SQL 生成、验证)、Opus 12%(归因分析)
  • 月账单 $918.44

平均单次业务问题 $0.027。相比人工处理一条需求的成本(估算 380 元/条,含 BI 工程师工时),降幅超过 99%。

Prompt caching 在这个场景特别有效。47 个业务域的 schema 摘要是固定的,我把高频的 12 个域的 schema 全部做 caching,命中率 78%,省了接近一半的 prompt 成本。具体配置可以看 Prompt Caching 深度指南

踩过的其他坑

坑一:口径不统一。「销售额」在销售部门指含税销售额,在财务部门指不含税。第一版 Claude 经常用错口径。后来在每个业务域摘要里加了「口径字典」,SQL 生成前强制注入。

坑二:业务术语。「毛茬产品」「粗加工件」「头批料」这些词在 schema 里根本不存在,但业务张口就来。我做了个业务术语 → 字段映射表,问题里出现业务黑话时先做转译。

坑三:时间歧义。「上季度」对财务是自然季度,对销售是考核季度(他们的销售考核季是 3 月 1 日到 5 月 31 日这样错位的)。必须在 prompt 里明确时间语义。

坑四:权限。财务数据不是所有人能看,原来 BI 平台靠列权限控制。Agent 得把用户身份透传下去,SQL 生成时带上权限过滤条件。这块涉及一些安全边界,可以参考 MCP Security Best Practice 的思路。

还没解决的

  • 多维下钻:用户问「北京区域销售情况」,然后追问「那朝阳区呢」,跨轮的维度下钻还不够自然
  • 可视化:现在只返回表格和文字,没有图表。业务副总说「能不能直接给我一张图」
  • 异常检测:用户不知道问什么的时候,Agent 没法主动说「你可能想看下 A 型号的异常下滑」

Q3 准备把可视化这块集成进来。


BI 自然语言查询不是 Text2SQL 那么简单
真正的难点在于 schema 治理、业务口径、归因分析这三座山。我在 检索重排策略 里讲过分层 RAG 怎么搭,在 Agent SDK 生产部署 里有完整的多步 Agent 样板。
  • 标题: 制造业 BI 自然语言查询:业务直接问"为什么毛利下滑"
  • 作者: Claude 中文知识站
  • 创建于 : 2026-04-18 19:38:00
  • 更新于 : 2026-04-19 14:12:00
  • 链接: https://claude.cocoloop.cn/posts/industry-bi-natural-language-query/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论