☰
ChatBI+Agent实战:从Text-to-SQL到智能问数架构
2026/10/5 2:43:32 网站建设 项目流程

简介:这是一份2024年ChatBI与Agent实战手册,共134页,汇集平安人寿、滴滴、喜马拉雅、腾讯、快手、阿里巴巴、网易等企业的真实落地案例,适合数据分析、大模型应用与商业智能方向的技术人员及管理者阅读。整套资源为单个PDF文件,大小9.33MB,目前已有433人学习下载。内容围绕ChatBI的立项背景、整体架构、技术方案与实施效果展开,重点覆盖自然语言交互下的SQL生成、对话式取数、智能报表、数据分析自动化等关键场景,也包含各公司在部署大模型、进行模型调优与跨部门协作时遇到的挑战和解决思路。从目录可见八大案例各自独立成章,如平安人寿大模型智能化报表、滴滴智能数据分析、腾讯ABI工程、快手BI+AI探索、阿里巴巴数据消费场景AI Agent等,既能帮助读者理解ChatBI的产品设计逻辑,也为自研智能分析平台提供可参考的技术路径。

1. ChatBI+Agent是什么:一张“问数”的请求,背后跑着一整套Agent

业务方敲过来一句话:“帮我看看华东区上季度毛利率为什么掉了3个点。”传统BI给的是报表,而2024年大家真正想要的ChatBI,是让系统直接给原因——能多轮追问、能临时改口径、能自动对比同期。做到这一层靠的不是把自然语言翻成SQL,而是背后一整条Agent链路:意图澄清、工具编排、SQL生成、结果校验、权限拦截。这本《2024 ChatBI+Agent实战手册》用八大案例、134页的体量,把ChatBI从“能跑demo”推向了“能扛业务”,案例里反复出现的不是某个模型的Prompt技巧,而是Agent架构怎么设计、工具怎么暴露、边角坑怎么填。这篇笔记我按自己落地ChatBI项目的经验,把这条链路拆成能照做的方案,讲清楚为什么Agent是ChatBI的必选项,参数怎么设,以及哪些坑值得提前绕开。

2. Agent在ChatBI中的角色:从“翻译SQL”到“代你查数”的三次升级

ChatBI的核心链路人人都能说一句:用户自然语言 → 意图理解 → SQL生成 → 执行 → 可视化 → 追问。但把这条链路放进真实业务里,就会发现每一步都有分支:问题含糊要不要反问,多表关联选哪张主表,指标口径冲突听谁的,SQL执行报错要不要修正。这些分支凑在一起,就是一个典型的“规划-执行-反思”循环,而把这个循环真正跑起来的东西,就是Agent。

2.1 Text-to-SQL是骨架,但Agent解决的不是“写SQL”

我在很长一段时间里把ChatBI等同于Text-to-SQL,这也是大多数团队入局的第一个误区。Text-to-SQL模型确实能处理单表、简单聚合、明确口径的查询,训练数据里这类样本也最多。但真实BI场景难在表多、口径杂、问法不标准:一套数仓上百张表,字段命名靠猜,“销售额”在销售部和财务部是两套算法,业务人员提问时默认你知道他们说的是哪个“毛利”。

这时候Agent解决的不是“把自然语言变成SQL”这一件事,而是“在信息不完备的情况下,把查询拆成可执行的动作序列”。比如“华东区毛利率为什么掉了”,合理的动作是:先确认时间范围、再查华东区毛利率走势、找到拐点月份、下钻到品类或渠道、和去年同期对比。这是四五个动作组合起来的任务链,不是一条SQL能回答的,而Agent的规划能力恰好接管了这一层。

2.2 三个介入点:意图澄清、工具编排、结果校验

我一般会在ChatBI链路里给Agent设三个介入点,这也是手册里八大案例反复踩到的位置:

第一个是意图澄清。用户说“看一下最近的情况”,Agent要判断“最近”是近7天还是近30天,表里有没有对应的时间分区。与其让模型猜,不如在进入SQL生成前加一道确认节点,把“时间范围、维度、指标、对比基准”四项关键参数抽出来,缺失就反问一次。多这轮对话,SQL准确率能提一大截,代价只是多两秒延迟。

第二个是工具编排。Agent不应该直接操纵SQL字符串,而是面向一组BI工具做编排:列出可用表和字段的工具、执行只读查询的工具、渲染图表的工具。工具编排的好处是权限、审计、会话管理都有了统一收口点,Prompt里只告诉Agent“你能做什么”,不教它怎么写具体SQL。

第三个是结果校验。SQL执行成功不等于答案正确,Agent需要在返回前做一次合理性核查:列名是否真实存在、聚合口径是否和指标字典一致、结果是否有明显量级异常。校验不过就带着错误信息回到SQL生成节点重试,这是整个ChatBI+Agent体系里最容易被省略、却最影响信任感的一环。

2.3 单模型直出SQL为什么翻车:一个反直觉的结论

很多人被ChatBI的极简demo迷惑:拿一张员工表,问“平均工资多少”,模型写的SQL分毫不差。于是团队直接把这个方案套到数仓上,结果一上线就翻车。原因不是模型不够聪明,而是直出SQL模式本质上是一锤子买卖:没有反馈回路,SQL写错了就错了,用户看不到执行过程,只会觉得“AI在胡说”。

反直觉的结论是:Agent并没有让模型变得更聪明,它只是把错误放进了可循环的闭环里。SQL报错就读取报错信息重新生成,结果异常就回到校验节点调整口径,多轮追问则把上一轮的SQL和结论作为上下文带入下一轮。这个“允许犯错并自我修正”的循环,才是ChatBI能在生产环境活下来的关键。后面第三章的代码就是围绕这个循环搭的。

3. 从零搭一个最小ChatBI+Agent系统:用LangGraph把链路跑通

聊完原理,直接看怎么落地。2024年做ChatBI+Agent,绕不开框架与编排这一关。我的建议是:低延时的单步查询可以裸调模型API,但只要涉及多表、多轮、工具调用,就得上带状态的编排框架。

3.1 选型:为什么用LangGraph而不是裸调API或写死流程

三种常见做法我都试过:裸调API、固定工作流、图编排框架。裸调API的问题在于分支逻辑全写在业务代码里,每加一个工具就要改一遍判断逻辑;固定工作流(比如只做“提问→生成SQL→执行→返回”)扛不住意图分支,用户想对比同期时工作流直接断掉;LangGraph这类图编排框架把每个环节定义成节点,节点之间用条件边连接,执行状态由框架维护,天然适合ChatBI这种“走到哪一步不确定”的场景。

LangGraph的另一个优势是自带状态管理和Trace能力。ChatBI的每个请求都要能回溯:用户问的什么、Agent选了哪个工具、生成的SQL长什么样、报错信息是什么。没有这种可观测性,后面想优化Prompt都不知道该看哪里。我选择LangGraph的核心理由就是它能把这些信息自动串联起来。

3.2 最小Agent核心代码:规划、执行、修正的循环

下面给出一段可用于生产骨架的LangGraph ChatBI Agent核心代码。它把链路拆成四个节点:意图规划、SQL生成、SQL执行、结果应答,并加了“执行失败自动回退到SQL生成”的条件边。

# -*- coding: utf-8 -*- # chatbi_agent.py # 依赖:langgraph, langchain-core, sqlalchemy, openai 兼容客户端 from typing import TypedDict, Literal from langgraph.graph import StateGraph, START, END class AgentState(TypedDict): query: str # 用户原始问题 plan: dict # 意图澄清后的执行计划 sql: str # 当前 SQL error: str # 执行报错信息 result: str # 查询结果摘要 answer: str # 最终中文回答 def plan_node(state: AgentState) -> AgentState: """节点1:意图澄清与工具选择。 这里只做结构化的参数抽取,不生成SQL。 常见实现是用LLM配合工具参数定义,抽取出: time_range, metrics, dimensions, compare_base 四项。 """ query = state["query"] plan = extract_plan_with_llm(query) # 伪代码:调用LLM抽取结构化参数 return {"plan": plan} def sql_gen_node(state: AgentState) -> AgentState: """节点2:根据plan和元数据生成SQL。 error字段非空时,会把报错信息一起带给模型,让它修正。 """ error = state.get("error", "") sql = generate_sql_with_llm(state["plan"], previous_error=error) return {"sql": sql, "error": ""} def sql_exec_node(state: AgentState) -> AgentState: """节点3:执行只读SQL。注意这里必须做SQL白名单校验, 只放行SELECT,禁止UPDATE/DELETE/DDL。 """ sql = state["sql"] ok, result, err = run_readonly_query(sql, row_limit=200) if not ok: return {"error": err, "result": ""} return {"result": summarize_result(result)} def answer_node(state: AgentState) -> AgentState: """节点4:把结果转成自然语言回答,并附上生成过的SQL供追溯。""" answer = build_answer_with_llm(state["result"], state["query"]) return {"answer": answer} def should_retry(state: AgentState) -> Literal["sql_gen_node", "answer_node"]: """条件边:执行失败就回SQL生成节点重写;成功则进回答节点。""" return "sql_gen_node" if state.get("error") else "answer_node" # 组装图:START -> plan -> sql_gen -> sql_exec -> 条件判断 -> answer -> END g = StateGraph(AgentState) g.add_node("plan_node", plan_node) g.add_node("sql_gen_node", sql_gen_node) g.add_node("sql_exec_node", sql_exec_node) g.add_node("answer_node", answer_node) g.add_edge(START, "plan_node") g.add_edge("plan_node", "sql_gen_node") g.add_edge("sql_gen_node", "sql_exec_node") g.add_conditional_edges("sql_exec_node", should_retry, {"sql_gen_node": "sql_gen_node", "answer_node": "answer_node"}) g.add_edge("answer_node", END) app = g.compile()

代码逻辑说明:这个图把前面说的“规划-执行-修正”循环落成了四个节点。plan_node只负责抽参数,不碰SQL,这一步保证了Agent不会在问题模糊时瞎猜;sql_gen_node接收上一步的plan,以及可能存在的上轮报错error,把“修正”变成了模型输入的上下文;sql_exec_node承担的是执行和校验职责,所有SQL都必须经过run_readonly_query这一道关卡,白名单过滤、行数限制、超时设置都收口在这里。should_retry是整段代码最关键的条件边:它决定了Agent是回到SQL生成节点继续改,还是流向最终回答。

参数说明:实际运行时有两个参数我建议优先调。一是row_limit,我一般设200行,避免SELECT * 把执行引擎压垮,同时让结果摘要可控;二是重试次数,LangGraph默认不会无限循环,但建议在sql_exec_node里显式计数,同一问题最多回退两次,两次还错就走“抱歉,我需要换个问法”的兜底回答。另外,所有LLM调用的温度建议统一设0,ChatBI场景要求确定性,不需要模型发挥。

3.3 必调参数:模型、温度、工具描述与上下文窗口

代码跑通只是第一步,这些参数直接决定ChatBI是“能用”还是“难用”:

参数我的建议说明
模型选型带工具调用能力的强推理模型2024年这个档位选择很多,本地化部署则优先看工具调用稳定性和中文指令遵循能力
温度0Text-to-SQL和参数抽取都要求确定性,任何随机性都会造成回答漂移
SQL超时10~30秒数据量大时让执行引擎先超时,而不是让用户干等
上下文窗口保留最近2轮对话 + 派生口径摘要把全部历史塞进Prompt只会稀释注意力,后面第四章细讲
工具描述每个不超过3句话描述应该写“什么时候用”,不是写“函数怎么实现”

这五个参数里,工具描述是最容易被忽视的。我见过有人在execute_sql工具描述里写长长的SQL语法示例,结果Agent被示例带偏,每次都套用那个模板。描述的正确写法是“该工具只读执行标准SQL,返回最多200行,适合做聚合查询”,剩下的让Agent自己判断。模型这一项我多说一句:2024年的经验是,ChatBI对推理链路的要求远高于对常识储备的要求,宁可选择一个工具调用稳定的小参数模型,也不要选一个会写SQL但老爱自作主张的大参数模型。

4. 八大案例背后的Agent设计模式:编排、工具与记忆的取舍

标题里说“八大案例共134页”,这八类案例形态各不相同,但按Agent的介入深度去归类,我发现它们全部落在三档模式里:单Agent直连、编排式多Agent、并行多Agent。每一种模式对应一类业务问题,也对应一套取舍。

4.1 八种案例归类:单Agent直连、编排式多Agent、并行多Agent

第一档是单Agent直连,适合“查个数”这类低复杂度问题:毛利是多少、本月订单量如何、某渠道占比多少。实现上就是第3章的图去掉plan分支,一个Agent拿着表结构和工具描述直接干活。优点是延迟低、成本低、出问题好排查;缺点是Agent的能力边界很窄,问法稍微绕一点就答非所问。我一般把这类请求设计成“轻量模式”,不走完整规划节点,省一次LLM调用。

第二档是编排式多Agent,适合口径复杂、需要多步推理的场景,手册里“毛利率异常归因”“渠道对比分析”都属于这一类。实现上是把意图路由、SQL生成、结果解释拆成三个专职Agent:路由Agent只判断问题类型,SQL Agent只干翻译,解释Agent只做结论。拆开的好处是每个Agent的Prompt可以写得很纯粹,权限和审计也按Agent维度收口,不像单Agent那样所有技能挤在一个上下文里。

第三档是并行多Agent,适合“同期对比”“多部门横向比较”这类天然可以分治的问题。做法是把对比任务拆成多个子查询,由多个子Agent并行执行,最后汇总到一个结论Agent上。这一档对系统要求最高,但收益也最明显:用户问“华东华北华南三个区上半年表现”,串行要跑三到五轮,并行可以把总耗时压到单次查询的量级。手册里这八类案例真正上生产环境的,几乎都是第二、三档的模式。

4.2 工具设计:让Agent“会用”你的BI平台而不是“乱用”

Agent的能力上限由工具决定,CTO和一线开发最容易在这里产生分歧。我的做法是给ChatBI Agent暴露四个工具,不多不少:list_tables用于罗列可用表,get_schema用于查看表结构和注释,execute_sql用于只读查询,render_chart用于生成图表配置。四个工具对应“找数据、看结构、查数据、展示数据”四个动作,Agent的规划能力刚好覆盖这个范围。

工具描述的字数我控制在三句话以内,而且第二句一定是“什么时候用”。比如get_schema的描述:“查看指定表的字段、类型和注释。当不确定列名或口径时使用,优先于execute_sql。”这种写法会让Agent在生成SQL前先确认字段,而不是猜列名。同时,我在工具层做了一道硬隔离:list_tables只返回当前用户权限范围内的表,execute_sql执行前自动注入行级过滤条件。不要指望Agent自己会遵守权限,那不在它的职责范围内,工具层拦不住的东西,Prompt写得再漂亮也没用。

4.3 Agent记忆:派生口径与多轮追问的上下文管理

ChatBI的多轮追问对Agent记忆是很大的考验。用户第一轮问“华东区毛利率”,第二轮说“同样口径看华南”,如果没有记忆,Agent不知道“同样口径”指什么;但如果把第一轮的所有中间产物都塞进第二轮,又容易撑爆上下文。我的方案是短时记忆加意图摘要两层结构:短时记忆保存最近两轮的query、SQL、结论;意图摘要单独存一份“会话内口径记录”,比如用户确认过的“毛利率=剔除退货后的毛利率”,每轮注入时优先携带摘要而不是原始对话。

这个方案解决了两个高频问题:一个是口径漂移,Agent在第三轮之后往往忘了第一轮确认过的过滤条件,强制注入摘要能兜住;另一个是上下文拥塞,BI问题往往带着长表名和长SQL,全部历史堆进去既费token又稀释注意力。记忆这块没有银弹,2024年的通用做法都类似,差别只在于摘要字段设计得粗还是细——我建议至少把“指标口径、时间范围、维度取值”这三类信息独立存储。

5. ChatBI+Agent避坑指南:五个让我翻车的真实场景

这条链路我前后落地过三个项目,踩过的坑比手册里的案例多得多。下面五条按“现象→原因→解决”写,每一条都是先用着别扭、后来定位到根因才解决的,希望能帮你省掉同样的排查时间。

现象根因对策
Agent越改越保守,简单问题被绕成三层子查询元数据塞太满,模型过度规划规划节点加“最小可用SQL”原则,监控SQL复杂度
同一个“销售额”,三个部门三种答案指标口径散落在文档里,模型只能猜维护指标字典,口径写进schema描述并每轮注入
普通用户查到了敏感维度权限只写在Prompt里,工具层默认放行execute_sql统一做行级权限改写和字段脱敏
并发一上来就超时每个请求都串行走完整LLM循环结果缓存、限制行数、SQL超时、并发熔断
SQL执行成功但数字是错的模型猜列名、混淆计量单位生成后做列名校验,执行后做量级对比

5.1 现象一:Agent越改越保守,简单问题被绕成三层子查询

导购问“本月销售额”,Agent先反问三个澄清问题,然后吐出一道带窗口函数和公共表表达式的SQL,执行耗时8秒,结果和报表中心对不上。排查时发现根因在系统提示词里塞了太多表关系复杂度的描述,模型被引导成“遇到问题先想复杂方案”。解决方式是给规划节点加了一条硬规则:“能用单表单次聚合解决时,禁止使用窗口函数和多层子查询”,并在每次生成SQL后记录语句复杂度,超过阈值就告警。这条规则上线后,简单查询的响应时间从8秒降到1秒以内,准确率反而升了,因为模型不再为了显得聪明而堆语法。

5.2 现象二:同一个“销售额”,三个部门三种答案

销售部问销售额,Agent给出含退款前的GMV;财务部问销售额,Agent给出净收入口径。两边拿着结果去对齐,数字对不上,直接投诉到数据团队。根因是“销售额”这个词在数仓里有多个字段,模型只看字段名根本分不清该选哪个。解决方式是建了一个指标字典,把“销售额”到具体字段、聚合方式、特殊过滤条件的映射写进每轮Prompt里,并让Agent在回答时标注“本数据口径为……”——口径写在回答里,矛盾就从“系统错了”变成“口径不同”,这是ChatBI能做成的关键习惯。

5.3 现象三:普通用户查到了敏感字段,权限成了摆设

这是我把agent安全重视起来的转折点。门店店长通过对话问出了全国各分店的成本明细,而他在BI平台里的角色本来只能看本店数据。排查发现Agent生成SQL时完全没有经过BI平台的权限接口,等于绕过了原有数据权限体系。解决方式是重新设计执行层:execute_sql接收SQL之前,先解析出涉及的表和维度,再根据当前用户角色自动改写SQL,追加行级过滤条件;同时对手机号、身份证这类字段默认脱敏。核心原则是:权限必须在工具执行层强制,不能依赖模型的自觉。

5.4 现象四:并发一上来就超时,AI Agent也有扛不住的时候

内部ChatBI上线第一天,市场部十几个人同时用,页面纷纷转圈,接口超时率到40%。当时所有人都问“AI Agent怎么扛并发”,我的排查结论是:瓶颈根本不在这两个字的AI上,而在每个请求都串行走了一遍“规划→SQL生成→执行→回答”的完整LLM链路,单次链路耗时2到5秒,十几个人同时来就直接击穿。解决措施分三层:第一层是SQL结果缓存,相同用户、相同语义、相同时间范围内直接命中缓存,这个收益最明显;第二层是把单次查询行数限制在200行、SQL执行超时定在20秒,避免慢查询拖死连接池;第三层才是并发控制,对LLM调用做信号量限流,超出的请求走排队提示。三层做完,同规模并发下的超时率降到5%以下。

5.5 现象五:SQL执行成功但数字是错的,幻觉隐藏在“正确”里

比报错更麻烦的是“成功”的幻觉SQL。用户问“Q3客单价”,Agent写出的SQL能跑通,但取的字段是“订单总额/订单数”,而业务方的客单价定义是“剔除退款后净收入/支付用户数”,结果差了近15%。排查根因是两处:一是模型看到“单价”字样就匹配了最像的字段,没有回看口径字典;二是执行后的校验只看了“有没有数据”,没看“数据合不合理”。解决方式是在SQL生成节点之后加了一道列名校验:把SQL里引用的所有列和指标字典做匹配,字段名与维度含义不一致就重新生成;同时执行后增加量级校验,把结果和上一周期同口径数值做对比,偏差超过阈值就标记异常。这两道关卡让幻觉SQL的占比降到了一个可以接受的水平。

6. 让ChatBI从“能跑”到“能信”的最后一公里:评测集与回归

系统上线能跑之后,真正的挑战变成“怎么改Prompt才不算改坏了”。2024年做Agent开发的人都懂这个痛点:每次调Prompt都像拆盲盒。我的解法是把Agent评测集构建放进日常节奏里——不是上线前应付一次性的演示用例,而是当作持续回归的基线。

6.1 手动测试阶段该结束了:Agent评测集的构建

评测集的来源是过去三个月的真实查询日志,挑出200到300条覆盖不同难度的Query,按“表数量、聚合复杂度、是否多轮、是否涉及口径辨析”四个维度打标签。每条Query要预先标注标准SQL和标准回答,作为判分参照。评判方式我用LLM as Judge加人工抽检结合:LLM按“工具选择是否合理、SQL结果与标准答案是否一致、回答是否覆盖用户意图”三项打分,每次改动后跑一遍全部case,分数对比即可量化是变好还是变坏。

6.2 把Trace和评分接到CI里:把“玄学”变成“回归”

评测集跑一次不难,难的是让它持续起作用。我把评测集接回了CI流程:每次修改Prompt、调整工具描述或换模型后,都要跑一次回归评分,分数低于历史最好值就不允许合并。同时给每个Agent请求配上trace_id,失败case能直接回放当时的规划、SQL生成和报错记录,定位问题从“猜”变成了“看日志”。这套流程跑了一个月后,团队再改Prompt时心里有底了,讨论也从“感觉应该没问题”变成了“上个月的case跑了几分”。

6.3 我的一个教训:改了Prompt忘了回归,上线两天被业务追着问

说一个我自己的教训:有一版优化为了拉低延迟,把意图澄清节点从两次反问改成一次默认猜测,觉得“大多数问题都猜得对”。因为没跑评测集就直接上线,结果两天内业务侧连续反馈“答非所问”,回看了一下Trace才发现,凡是涉及“同比”“环比”的复杂问题,少掉的那一次澄清正好带偏了时间范围。后来我把“新功能先补三条评测case再动代码”写进了开发规范,这个习惯帮我避掉了后续好几次上线翻车。做ChatBI+Agent,模型能力是一个变量,评测集才是那个让一切回归可控的锚点,建议你从第一天就把评测集建起来,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询