设计一个ChatBI/智能问数Agent,业务说一句话就能出数
本文目录
30秒版回答
我会把智能问数设计成六个环节:问题理解 → 语义召回 → 查询生成 → 校验 → 执行 → 解释与反馈。
关键设计有三点。第一,不让模型直接面对几千张物理表,而是面对一个精选的语义层:标准指标、维度和它们的口径定义,模型优先生成“指标 + 维度 + 过滤条件”的结构化查询,由语义层编译成 SQL。第二,生成之后必须校验:语法、权限、分区、成本,以及结果合理性。第三,结果必须可解释:返回数字的同时,告诉用户用的是哪个指标口径、什么时间范围、什么过滤条件,让业务能自己判断对不对。
评估上,我会用真实历史问题建一个评测集,按难度分层统计准确率,上线后把答错和用户纠正的问题回流进评测集,持续迭代。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
面试官:「我们想做一个智能问数产品,业务同学用自然语言提问,比如“上周华东区新客的复购率是多少”,系统直接给出数字和图表。如果让你来设计,你会怎么做?」
这是第二轮系统设计里出现频率最高的一道题,几乎所有在做数据智能的公司都会问。原因很简单:智能问数是数据团队最直接的 Agent 落地场景,而且它七分靠数据、三分靠模型。
很多候选人一上来就讲“用大模型生成 SQL”,然后就没了。这样回答会被追问到崩:表那么多模型怎么知道用哪张?口径谁定?SQL 错了怎么办?数字对不对谁负责?面试官想看的是一套从问题理解到结果可信的完整链路。
面试官在考什么
• 能否画出完整架构:意图理解、语义检索、SQL 生成、校验、执行、结果解释、反馈闭环。
• 是否意识到核心难点在数据而不在模型:口径、元数据、语义层决定上限。
• 是否有可信设计:结果可解释、可追溯,模型不确定时会澄清或拒答。
• 能否讲出评估和迭代方法:怎么知道准确率是多少,怎么持续提升。
展开一:整体架构
用户问题:"上周华东区新客的复购率是多少"
│
▼
① 问题理解:意图分类(查数/解释/闲聊)、时间解析(上周=?)、实体识别(华东区/新客)
│ 信息不足 → 澄清:"复购率按 30 日还是按自然月?"
▼
② 语义召回:从语义层召回候选指标/维度/枚举值 + 相似历史问答(few-shot)
▼
③ 查询生成:优先生成结构化查询(指标+维度+过滤),复杂问题再生成 SQL
▼
④ 校验:语法 / 权限 / 分区过滤 / 预估扫描量 / 口径一致性
▼
⑤ 执行:只读账号、超时、行数上限、结果缓存
▼
⑥ 解释与反馈:数字 + 图表 + 口径说明 + 生成的 SQL;用户点赞/纠错回流
这张图里,②语义召回和④校验是决定成败的两个环节,也是数据开发最能发挥价值的地方。模型能力是“发动机”,语义层是“地图”,校验是“刹车”,缺任何一个都不能上路。
展开二:为什么要先过语义层,而不是直接 Text-to-SQL
直接让模型写 SQL(Text-to-SQL)看起来最灵活,但在企业环境里有三个硬伤:表太多选不准、口径藏在 SQL 里没人能审、同一个问题每次生成的 SQL 可能不一样。
更稳妥的做法是两段式:模型只负责把自然语言翻译成结构化的查询意图,SQL 由语义层确定性地编译出来。这样口径完全由语义层控制,模型只是一个“翻译”。
// 模型输出:结构化查询意图(而不是直接写 SQL)
{
"metric": "repurchase_rate_30d", // 必须是语义层里已定义的指标
"dimensions": ["region"],
"filters": [
{"field": "region", "op": "=", "value": "华东"},
{"field": "user_type", "op": "=", "value": "新客"}
],
"time_range": {"start": "2026-09-28", "end": "2026-10-04"},
"time_grain": "week"
}
// 语义层负责:校验指标/维度是否存在、是否允许组合,再编译成 SQL
| 维度 | 直接 Text-to-SQL | 语义层 + 结构化意图 |
|---|---|---|
| 灵活性 | 高,任意 SQL | 受限于语义层已定义的指标和维度 |
| 口径一致性 | 差,每次可能不同 | 强,口径由语义层唯一定义 |
| 可审计性 | 需要人读懂 SQL | 意图结构清晰,业务也能看懂 |
| 准确率 | 表多、逻辑复杂时明显下降 | 常见指标问题准确率高且稳定 |
| 适用 | 探索式分析、长尾问题 | 高频标准指标问题(占大多数) |
实际系统通常是两者结合:高频标准问题走语义层,语义层覆盖不了的长尾问题降级到 Text-to-SQL,并且明确提示用户“这是基于明细表的探索性结果,口径未经认证”。
展开三:时间和实体解析,最容易翻车的地方
问数系统里,模型最容易出错的往往不是复杂 SQL,而是“上周”“昨天”“华东”“新客”这种看起来很简单的词。
• 时间:“上周”是自然周还是最近 7 天?周一开始还是周日开始?“昨天”按哪个时区?
• 枚举值:用户说“华东”,数据里可能存的是“华东大区”或者区域编码“EC”。
• 业务概念:“新客”是首单用户、注册 30 天内用户,还是当月首次活跃用户?
跨时区这一点我深有体会。我在某短剧出海公司做跨时区数据处理时,同一个“昨天”,按北京时间和按美国西海岸时间切日,差了十几个小时,数字完全对不上。所以在问数系统里,时间解析不能交给模型自由发挥,而要用确定性的规则:默认时区、默认周起始日写进配置,解析结果显式展示给用户。
# 时间解析走确定性规则,模型只负责识别"上周"这个短语
TIME_RULES = {"week_start": "MONDAY", "default_tz": "Asia/Shanghai"}
def resolve_time(phrase: str, now: datetime, site_tz: str | None):
tz = ZoneInfo(site_tz or TIME_RULES["default_tz"]) # 站点时区优先
today = now.astimezone(tz).date()
if phrase == "上周":
this_monday = today - timedelta(days=today.weekday())
return this_monday - timedelta(days=7), this_monday - timedelta(days=1)
if phrase == "昨天":
return today - timedelta(days=1), today - timedelta(days=1)
raise NeedClarify(f"无法确定时间范围:{phrase}") # 解析不了就澄清
# 枚举值:用维度值索引做模糊匹配,"华东" → region_code='EC'
展开四:结果可信——让业务能自己判断对不对
智能问数最大的风险不是“答不出来”,而是“一本正经地答错”。所以返回结果时必须附带“解释包”:
• 口径说明:用的是哪个认证指标,定义是什么(复购率 = 30 天内再次下单的新客数 / 新客数)。
• 查询条件:时间范围(2026-09-28 至 2026-10-04,北京时间)、过滤条件。
• 数据新鲜度:数据更新到哪一天,是否有延迟。
• 可展开的 SQL:给懂行的人核对。
• 置信提示:走的是认证指标还是探索性查询。
这几项看起来琐碎,但它们决定了业务敢不敢用这个系统。一个可解释的错误答案能被快速发现和纠正,一个不可解释的正确答案也没人敢信。
追问链
追问一:准确率怎么评估?做到多少可以上线?
我会从历史取数工单、群聊提问里收集真实问题,每个问题配上标准答案(标准的结构化意图或 SQL,以及执行结果)。评估时比较的是执行结果是否一致,而不是 SQL 文本是否一致,因为同一个结果可以有多种写法。
评测集要按难度分层:单指标单维度、多维度过滤、同比环比、多指标计算、需要澄清的模糊问题。上线标准不是一个笼统的数字,而是高频简单问题要非常高、复杂问题可以降级为“给出 SQL 让人确认”。另外“该澄清时澄清、该拒答时拒答”也要单独评估。
追问二:表有几千张,模型上下文放不下,怎么办?
不让模型看全部表。第一层,语义层只暴露经过认证的几十到几百个指标和维度;第二层,每次请求先根据问题检索最相关的指标、维度、枚举值和历史问答,只把 TopK 放进上下文;第三层,长尾问题需要查明细表时,也是先检索候选表,再把候选表的结构和样例数据给模型。这就是“先召回、再生成”的思路,和推荐系统一样。
追问三:用户纠错的数据怎么用起来?
纠错是最宝贵的数据。我会把它分成几类处理:如果是口径理解错,补充语义层的同义词和描述;如果是枚举值没匹配上,补充维度值别名;如果是SQL 逻辑错,把纠正后的问答对加入 few-shot 示例库和评测集。每次迭代后用评测集回归,确保改一个问题不会引入新问题。
加分说法 vs 减分说法
| ✔ 加分说法 | ✘ 减分说法 |
|---|---|
| 七分靠数据、三分靠模型,核心在语义层 | 用大模型直接生成 SQL 就行 |
| 模型生成结构化意图,SQL 由语义层编译 | 把所有表结构塞给模型 |
| 时间、枚举、业务概念用确定性规则解析 | 准确率靠换更强的模型解决 |
| 结果附带口径、条件、新鲜度和 SQL | 只返回一个数字,不给任何解释 |
| 评测按执行结果比对,按难度分层 | 没有评测集,靠感觉说效果不错 |
怎么挂到你的项目上
话术模板:“如果做智能问数,我会把重点放在数据侧:先把高频指标沉淀到语义层,让模型输出结构化查询意图,由语义层编译 SQL,保证口径一致。时间解析这类容易出错的地方我会用确定性规则,因为我之前做跨时区数据时吃过切日不一致的亏。”
如果你所在公司已经有指标平台或者数据字典,一定要讲出来:这就是智能问数最核心的资产。
总结
智能问数的设计题,要把重心放在语义层、校验和可解释上,而不是模型本身。记住六个环节和“模型是翻译、语义层是地图、校验是刹车”这个比喻,再用跨时区、枚举匹配这类真实的坑证明你做过数据,这道题就能答得很扎实。
下一篇深挖智能问数最大的痛点:Agent 查数总是用错表、算错口径,到底该怎么解决?
你们公司的智能问数上线了吗?业务用得多吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长