Text2SQL 与 ChatBI 落地实战:语义层、多轮追问与可信结果校验 摘要9-29/01 把知识库做成受治理的产品本文把同一套底座接到数据分析场景让问一句话出一张表也走上受治理的轨道。核心是用语义层呼应 SuperSonic屏蔽物理表复杂度、用多轮状态维护接 9-28/02 上下文工程承接追问、用SQL 可信校验EXPLAIN 干跑 / 行数异常 / 禁 DML把工具做成一个经 9-25 网关与 9-26 护栏的只读工具最后用 9-26 法官评测量化生成的 SQL 对不对。ChatBI 的生死线是’生成的 SQL 能不能跑、跑出来信不信得过’——语义层降低幻觉、校验层拦住危险二者缺一不可。一句话结论把对话式数据分析当成受约束的 SQL 生成服务——语义层把自然语言映射到业务口径、多轮上下文承接追问、校验层在真实执行前拦掉危险与错误、法官评测量化正确性让业务人员问得出口、信得过数。1. 为什么 NL2SQL “demo 很香、上线很痛”直接让模型对着几百张物理表生成 SQL三个必翻车点痛点表现解法schema 太复杂表名/字段名晦涩模型猜错 join语义层封装歧义上个月销售额口径不一语义指标统一定义安全生成DELETE、跨库扫全表执行前校验 只读9-27/01 的 RAG 解决知识查得到ChatBI 解决数据问得动——前者喂事实后者喂数仓底层都靠同一个受治理平台。2. 语义层把物理表翻译成业务语言呼应 SuperSonicSuperSonic 这类 Headless BI 的核心价值就是物理模型 → 语义模型的映射。NL2SQL 在语义层之上生成模型只看到订单.成交额用户.活跃天这种业务口径而非t_ord.f_amt和t_usr.d_active。# 语义层定义SuperSonic 风格datasets:-name:订单table:dw.fact_orderdimensions:-name:城市# 业务口径expr:city_code# 物理字段-name:下单日期expr:dtmeasures:-name:成交额expr:sum(f_amt)agg:SUM-name:订单数expr:count(1)metrics:-name:客单价expr:成交额 / 订单数# 口径统一定义避免每人算一遍层责任收益物理层真实表/字段—语义层维度/指标/口径屏蔽复杂度、统一口径生成层NL → 语义 SQL模型只见业务语言语义层复用 9-25 网关的租户隔离不同租户的销售额可以指向不同物理表却暴露同一业务口径。3. 多轮对话状态接 9-28/02 上下文工程“上个月销售额多少”“那华北呢”“同比呢”——追问必须靠对话状态承接这正是 9-28/02 上下文工程的用武之地把上一轮的生成 SQL / 筛选条件 / 时间窗口塞进上下文下一轮基于它改写而非凭空来。classChatBIState:def__init__(self):self.history[]# 9-28/02 的 History 来源self.last_sqlNone# 上一轮语义 SQLself.slots{}# 已解析的时间/维度/指标defresolve(self,utterance):# 把新话术 历史 slots 一起喂给模型做指代消解promptbuild_ctx(self.history,self.slots,utterance)sql,new_slotsnl2sql(prompt,semantic_layer)self.slots.update(new_slots)self.last_sqlsql self.history.append((utterance,sql))returnsql上下文要素来自作用历史 SQL9-28/02 History承接那华北呢已填 slots状态机时间/维度复用语义层第 2 节约束生成空间4. 可信校验执行前的三道闸生成 SQL 不能直接甩给数仓。执行前必须过三道闸把它做成 9-28/01 里隔离运行的只读工具defsafe_execute(sql,db):parsedparse(sql)# 闸 1禁 DML / DDLifparsed.typenotin(SELECT,WITH):raiseBlocked(只允许只读查询)# 闸 2禁跨库 / 系统表iftouches_forbidden_table(parsed):raiseBlocked(触及受限表)# 闸 3EXPLAIN 干跑估行数防全表扫plandb.explain(sql)est_rowsplan.estimated_rowsifest_rows1_000_000:raiseBlocked(f预估扫描{est_rows}行疑似全表扫)returndb.run(sql,readonlyTrue)闸拦什么失败动作禁 DMLDELETE/UPDATE/INSERT直接拒绝禁越权表跨租户/系统表拒绝EXPLAIN 行数全表扫/笛卡尔积拒绝或要求加 limit这一工具经 9-25 网关路由只读实例、受 9-26 出站护栏约束结果脱敏与 9-28/01 的沙箱理念完全一致模型能查数据但碰不到写权限。5. 结果叙事从表格到洞察SQL 跑出结果只是开始业务人员要的是洞察。把表格转成自然语言 自动图表异常检测环比/同比突变自动高亮归因指标下跌自动拆分维度贡献图表按维度自动选柱状/折线/饼图接前端渲染。defnarrate(result_df,question):insightllm_summarize(question,result_df)# 自然语言洞察chartauto_chart_select(result_df)# 自动选图return{text:insight,chart:chart,rows:result_df}6. 评测生成的 SQL 对不对接 9-26 法官评测ChatBI 的正确性必须可量化。两层评测可执行性SQL 能否在语义层 数仓跑通第 4 节闸语义正确性用 9-26 的法官评测把问题 标准 SQL与生成 SQL 的执行结果比对让法官判断语义等价。评测项方法接执行成功率闸通过率9-28/01 工具结果一致性标准 vs 生成结果比对9-26 法官口径命中指标是否用语义层定义第 2 节低分样本回流 9-20 RLVR / 9-23 CI 门禁形成生成 → 评测 → 改提示词/语义层的闭环。7. 小结数据也走上受治理轨道至此平台的能力面从知识9-29/01扩展到数据语义层屏蔽物理复杂度、统一口径呼应 SuperSonic多轮状态承接追问接 9-28/02 上下文SQL 校验把它做成只读工具接 9-25 网关 / 9-26 护栏 / 9-28/01 沙箱法官评测算正确性接 9-26。下一站9-29/03不再加新能力而是把前面所有花钱的地方——9-20 KV、9-25 缓存与路由、9-26 引擎、9-25 配额——收口成企业级 LLM FinOps回答老板最关心的问题“这平台到底值不值”。常见问题FAQQ1语义层和直接在 prompt 里塞 schema 有什么区别Aprompt 塞 schema 时模型面对几百张晦涩物理表join 和口径极易错语义层只暴露业务口径成交额/客单价并统一定义指标公式既降幻觉又保证全公司一个算法。Q2多轮追问崩了怎么办A状态机里保留 last_sql 和可解析 slots崩时回退到上一轮有效 SQL 重新改写而不是直接凭空生成同时限制对话轮数上限过长则提示重新开始一个分析。Q3EXPLAIN 干跑在所有数仓都支持吗A主流都支持PostgreSQL/MySQL/ClickHouse/Hive 均有 EXPLAIN但估算行数的字段名不同需按引擎适配对不支持的引擎退化为强制 LIMIT 超时熔断。Q4ChatBI 能写数据回写吗A生产默认只读。若业务确实需要如把这批客户标记为高价值必须走独立写通道 人工二次确认 9-25 网关审计绝不与查询通道混用。Q5结果叙事会引入新的幻觉吗A会。所以叙事模型只被允许描述已返回的数据不许编造未出现的数字并附原始表格供核对异常归因用确定性规则而非自由生成。Q6语义层怎么和 RAG 知识库9-29/01配合A语义层定义指标口径知识库存指标背后的业务说明/负责人ChatBI 回答时可引用知识库文档作为口径出处二者在 9-25 网关下共享同一租户权限。Q7评测集怎么来A从真实对话日志抽典型问题 专家标注标准 SQL沉淀为 9-25 黄金集每次语义层或提示词变更都跑回归接 9-23 CI 门禁。参考资料本专栏 9-29《企业级 RAG 知识库产品化实战》共享的权限与治理底座本专栏 9-28《上下文工程实战》多轮对话的状态维护本专栏 9-28《函数调用与工具执行沙箱实战》只读工具与隔离运行本专栏 9-25《统一 LLM 推理网关实战》租户隔离与工具路由本专栏 9-26《LLM-as-Judge 自动化评测流水线》SQL 语义正确性评测腾讯 SuperSonic 开源项目文档Headless BI 与语义层建模2026