设计给老板的「用嘴查数」系统(NL2SQL),准确率不够怎么兜底?
谁在问:数据团队、BI 平台组高频;面试官往往被「口径错但 SQL 能跑」坑过
口语化问法
- 老板想直接问『上个月华东区的复购率是多少』就出数,这个怎么做?
- NL2SQL 准确率到不了 100%,你怎么兜?
- 它生成的 SQL 能跑,但结果是错的,你怎么发现?
考察意图
这道题有一个和其他所有场景题都不同的地方,答不出来就到不了 80 分:
NL2SQL 的错误是静默的。 别的系统答不上来会说「不知道」,NL2SQL 会返回一个数——一个看起来完全正常、可以直接写进汇报的数。没有任何外部信号提示它错了,而使用者恰恰是最没有能力验证它的人(老板不会看 SQL)。
所以这道题的重心从来不在「怎么把 SQL 生成得更准」,在怎么让错误变得可见。其余考点:口径统一(语义层)、schema 规模、以及事后追责时的复盘能力。
参考答案
60 分答案(及格线)
把表结构和字段注释喂给模型,让它生成 SQL,执行后把结果返回,同时展示生成的 SQL 供核对。schema 太大就先做一次表检索,只把相关的表喂进去。准备一批 few-shot 示例提高准确率。加只读权限和超时限制,防止跑挂库。准确率不够的话可以让用户确认 SQL 再执行。
技术要素基本齐了,及格。问题在最后一句:「让用户确认 SQL」对老板这个用户是无效的——他不会看 SQL。整个方案的兜底建立在一个不存在的能力上。
90 分答案(有生产经验的回答)
① 先问四个问题:谁用——分析师(能看懂 SQL、能自己验证)还是业务负责人(不能)?这决定了兜底方式完全不同。数据量级和 schema 稳定性——几十张表还是几千张?有没有指标口径的统一定义——「活跃用户」在公司里有几个版本?错了的后果——是满足好奇心,还是要拿去开会做决策?
假设:用户是不看 SQL 的业务负责人、几百张表、口径散落在各个报表里、结果会被拿去做决策。
② 基线:先不做 NL2SQL。 把最常问的二三十个问题做成参数化模板(下拉选时间、区域、产品线),覆盖八成需求。这套东西准确率是 100%,因为 SQL 是人写好的。先摆基线,是为了把问题限定成「剩下那两成长尾值不值得用 NL2SQL 换正确性风险」——很多团队跳过这一步,最后发现自由问答里九成的问题其实就是那二三十个。
③ 加挂,每样说代价:
语义层(这是全场最值钱的一层,也是最多人漏掉的)。在物理表之上定义指标、维度和口径:「复购率」是什么公式、分母是谁、剔不剔退款、按下单时间还是支付时间。模型面对的是语义层而不是裸表。解决什么:把「SQL 写对了但口径用错了」这类最高发的错误从根上消掉。代价:语义层要人来定义和维护,且要和数据团队达成一致——这是组织工作不是技术工作,也是这个项目真正的工期所在。什么时候不该用:探索性分析场景,语义层反而会限制自由度。
schema 裁剪与检索:几百张表不能全塞。做法是先按表和字段的语义做一次检索,只把候选表的 DDL 与样例值喂进去。代价:检索错了表就全错,且这类错误很隐蔽;配套:把最终用到的表显式展示给用户,并对「本次用到了一张很少被使用的表」做提示。
执行前的确定性校验:SQL 静态检查(只读、无笛卡尔积、有时间过滤)、行数与代价预估、超时与结果行数上限。代价:会拦掉一些合法的复杂查询;收益:防止跑挂生产库,这条没有商量余地。
兜底四件套(本题核心,针对「用户无法验证」这个前提设计):
① 口径回译 用自然语言复述这次的计算口径:「复购率 = 30 天内二次支付用户 / 首购用户, 已剔除退款,按支付时间」——让不看 SQL 的人也能核对口径 ② 数据说明 展示数据更新时间、数据源表、以及本次结果的样本量 ③ 异常提示 与历史同期做比较,偏离超过阈值时明确标注「该结果与上月差异较大,建议核对」 ④ 置信降级 检索到的表把握不足、或问题含未定义指标时,不给数,给模板或转人工这四件套解决的都是同一件事:把静默错误变成有声错误。 其中口径回译最重要——它把验证任务从「看懂 SQL」降级成「确认一句中文」,而后者老板是能做的。
④ 评测:分两个指标,不能合并成一个「准确率」。
- 执行正确率:SQL 能跑且结果与标准答案一致。
- 口径正确率:即使结果数值对了,用的表和口径是否正确——这两个在 NL2SQL 里经常分离,一个查错了表但恰好数值接近的查询,前者算对、后者算错,而后者才是真风险。
- 评测集用黄金查询集:真实问题 + 人工写的标准 SQL + 标准结果,按问题类型分层(单表聚合 / 多表关联 / 时间窗口 / 嵌套与占比)。难度分层很重要——总准确率 85% 可能意味着单表 98%、多表关联 40%,而后者恰恰是高价值查询。
- 零成本信号:用户重问率、导出后手工改数的比例、以及结果被采纳率。
- 统计关照旧:黄金集通常只有一两百条,几个点的波动说明不了问题。
⑤ 演进:某类问题的口径正确率长期稳定 → 才把它从「需确认」放到「直接出数」;出现「用户反复问同一类问题」→ 沉淀成模板(这是最重要的一条:NL2SQL 的产出之一是发现该被固化的查询);出现「口径争议频繁」→ 该做的是治理语义层,不是调模型。退路:任何一次错数被用于决策,立刻把对应问题类型退回模板或人工。
追问链
「活跃用户」在公司里有三个定义,怎么处理?
期望不是模型问题,是治理问题:① 建语义层,定义收敛成唯一版本并标注适用范围;② 真有多个口径就别替用户选 —— 反问「登录口径还是下单口径」,或两个都给并标明差异;③ 语义层里没定义的指标一律拒绝计算,别让模型拼公式 —— 模型最擅长给未定义的东西编一个合理定义,这正是这里最危险的信号说出「未定义指标要拒绝而不是猜」→ 做过数据平台;答「用 few-shot 教会它我们的定义」→ 不知道口径会变、要治理SQL 能跑,结果也像模像样,但其实是错的,怎么发现?
期望① 口径回译给用户确认,把验证降成一句中文;② 交叉校验:对历史同期、对已知总量,偏离超阈值提示;③ 高风险问题生成两条不同写法的 SQL,不一致不出数;④ 展示样本量与更新时间;⑤ 手动跑一遍正确 SQL:对了是生成侧,不对是数据侧信号提「手动执行正确 SQL 切开生成侧与数据侧」→ 用的是标准归因树;提「各区域求和对总量」→ 真做过数据质量老板不会看 SQL,怎么让他相信这个数?
期望可验证性要做进他的能力范围:① 口径回译成一句中文,最有效;② 血缘简版:来自哪几张表、更新时间;③ 对比锚点:同期、上期、他熟悉的已知数(如总用户数),用常识判断量级;④ 追问入口:一键把口径与 SQL 转给数据同事复核。信任靠一次次可核对建立,早期别追求「一句话出数」信号说出「把验证降级到确认一句中文」→ 抓住了本题本质;只说「展示 SQL」→ 方案建立在用户不具备的能力上几百上千张表怎么办?全喂进去肯定不行。
期望① 两级检索:按表注释、字段注释、历史查询共现选候选表,再喂 DDL 与典型值;② 历史查询最靠谱:真人写过的 SQL 里的表组合胜过表注释;③ 裁剪保守,漏掉正确的表比多带几张危害大;④ 显式展示用到的表;⑤ 长期还是语义层:上千张物理表收敛成几十个业务实体,复杂度降一个数量级信号提出「历史查询的表共现比表注释更可靠」→ 做过真实数据平台;只说「向量检索表名」→ 会被表注释质量拖垮老板拿着一个错数在经营会上做了决策,事后追责,你怎么复盘、改什么?
期望① 止血:指标下线自助入口改人工出数,更正主动发不等人问 → ② 归因二分:手动跑正确 SQL,对了是生成侧(选错表、口径拼错、时间窗错位),不对是数据侧(同步延迟、口径变更、脏数据) → ③ 对四道闸点名:规格、验证、回滚、准入 → ④ 改进按成本排。定位没做进产品,就是设计的责任信号把责任推给「老板没核对」→ 出局;走得完「止血、归因、四道闸、成本排序、边界」五步 → 能主持复盘会
评分要点
- 明确指出 NL2SQL 的错误是静默的,重心在让错误可见而非提高生成准确率
- 基线是参数化模板,先覆盖八成高频需求
- 有语义层,且承认它是组织工作、是工期主要来源
- 未定义指标拒绝计算而不是让模型猜
- 兜底针对「用户无法验证」设计:口径回译、数据说明、异常提示、置信降级
- 评测拆成执行正确率 + 口径正确率,并按查询难度分层
- schema 裁剪用历史查询共现,且裁剪保守、显式展示用到的表
- 复盘能走止血 → 归因二分 → 四道闸 → 成本排序,并给出边界结论