AI 数据探索 Agent多轮对话式的数据分析和一次性 SQL 的区别大家好我是朱大喜。你有没有这样的感觉取数不难难的是知道自己该取什么数。今天聊聊 AI Agent 怎么把一次性 SQL升级为多轮对话式探索让数据分析从人适应工具变成工具理解人。一、帮我查一下和帮我想一下的区别传统数据分析的典型流程是这样的老板最近用户留存怎么样查一下。 分析师好的。写 SQL SELECT dt, retention_d7 FROM dws.user_retention_daily WHERE dt BETWEEN 20260701 AND 20260712 ORDER BY dt; 留存率 58%...62%...55%...咦 老板有什么异常吗 分析师再写 SQL SELECT channel, retention_d7 FROM dws.user_retention_daily WHERE dt 20260712 GROUP BY channel; ANDROID 62%, IOS 48%iOS 留存掉了 老板为什么 分析师再写 SQL SELECT * FROM dwd.app_crash_log WHERE dt 20260712 AND platform IOS ...这个过程里每一步的分析都依赖于上一步的结果。传统 SQL 是一次买卖Agent 是一段对话。为什么传统模式的上下文传递成本比看起来高得多表面上每次只多写了一行 SQL但真正消耗精力的是数据解读的接力。上一个 SQL 返回了一组数字人需要消化这些数字12% 的跌幅算不算异常然后把它翻译成下一个问题可能是渠道问题还是产品问题最后再翻译成 SQL。这个数字→问题→SQL的翻译循环每一步都有信息损耗——人会选择性关注某些数据、忽略另一些然后基于不完整的认知提出下一个问题。Agent 的价值就在于打破了这个人脑转译的瓶颈。graph LR subgraph 传统模式: 线性SQL A[问题1] -- B[SQL1] C[问题2] -- D[SQL2] E[问题3] -- F[SQL3] B -.-|人工传递上下文| C D -.-|人工传递上下文| E end subgraph Agent模式: 对话式探索 G[用户: 留存怎么样?] -- H[Agent: 查总览] H -- I[Agent自主: 有没有异常?] I -- J[发现 iOS 留存掉了] J -- K[Agent自主: 为什么掉?] K -- L[下钻渠道/版本/地区] L -- M[Agent: 给你分析报告] end style F fill:#faa,stroke:#333 style M fill:#afa,stroke:#333二、Agent 的核心能力不是会写 SQL而是会思考数据探索 Agent 和普通 Chat-to-SQL 工具的区别在于它多了三个能力能力一上下文记忆Agent 记得你上一轮查了什么不需要每次都重新描述业务背景用户: 查一下上周的 GMV Agent: 上周 GMV 为 3,280 万环比下降 5.2%。 用户: 按渠道拆一下 Agent: (它知道按渠道拆指的是按渠道拆上周 GMV不是拆去年的) APP 端 2,150 万持平H5 端 680 万↓18%小程序端 450 万↓8% 用户: H5 为什么降这么多 Agent: (它知道你在追问 H5 下降的原因自动下钻) 正在分析 H5 端流量来源和转化漏斗... H5 端自然搜索流量减少 32%投放流量增加但转化率下降。 进一步排查H5 页面加载时长从 2.1s 增加到 4.8s。 建议检查 H5 CDN 节点状态。这个对话里Agent 每一步都在利用前几步构建的上下文——它知道拆的是 GMVH5是非 APP 渠道为什么降需要看流量来源和转化漏斗。为什么上下文记忆不只是存对话历史这么简单如果你只是把前几轮的问题和回答原样塞进 PromptLLM 容易陷入惯性跟随——它看到你说H5 为什么降就会顺着 H5 这个关键词一直往下查而忽略了可能更重要的横向对比比如 APP 端虽然 GMV 持平但转化率也在降只是被流量增长掩盖了。好的上下文记忆应该是结构化的分析状态当前分析到了哪一层、排除了哪些假设、还剩下哪些方向没查、已发现的关键数字是多少。这比纯文本历史更有分析感。能力二自主探索路径Agent 不是被动回答问题而是主动追问自己没有把握的事情# Agent 的内部推理逻辑简化版 class DataExplorationAgent: 数据探索 Agent 的核心逻辑 为什么需要自主探索而不是被动等待指令 大多数人问问题的时候并不清楚自己的分析路径 他们需要的是一个会追问的分析师而不是一个哑巴查询工具 def __init__(self, llm_client, sql_executor): self.llm llm_client self.sql sql_executor # 对话历史每次对话都保留 self.conversation_history [] # 当前分析任务的数据上下文 self.data_context {} def explore(self, user_question: str) - str: 开始一轮数据探索 不是简单地翻译成 SQL 然后返回结果 而是一个理解 → 查询 → 判断是否足够 → 不够就继续查的循环 # 第一步理解用户意图 规划分析路径 plan self.llm.plan_analysis(user_question, self.conversation_history) # 第二步执行查询可能多轮 for step in plan.steps: # 生成 SQL sql self.llm.generate_sql( step.intent, self.data_context, # 当前已知的数据上下文 self.conversation_history # 完整对话历史 ) # 执行查询 result self.sql.execute(sql) # 关键判断当前结果是否足够回答问题 if self._need_deeper_analysis(result, step.intent): # 不够自主生成下一步探索 next_step self._generate_follow_up(result) plan.steps.append(next_step) # 更新数据上下文让后续步骤知道已有的信息 self.data_context[step.name] result # 第三步综合所有探索结果生成最终回答 return self.llm.synthesize_report(self.data_context, user_question) def _need_deeper_analysis(self, result, intent) - bool: 判断是否需要进一步分析 几个典型触发条件 1. 结果中有显著异常如指标突然下跌超过阈值 2. 结果只是表面现象没有回答为什么 3. 用户原始问题暗示需要多维度分析 # 示例如果发现某个渠道的指标异常偏离 if result.has_anomalous_segment(threshold0.2): return True # 需要下钻 return False能力三结果翻译能力Agent 的最终输出不是数字和表格而是一段有逻辑链条的分析报告def format_analysis_report(exploration_result: dict) - str: 把数据探索结果翻译成人类语言 为什么需要翻译 原始数据是7月12日 iOS留存率 48%上月同期 62% 翻译后是iOS 留存掉了 14 个百分点初步判断和两天前的版本更新有关 后者才是一线业务人员能用的信息 summary f ## 数据探索报告 **核心发现** {exploration_result[core_finding]} **变化趋势** {exploration_result[trend_summary]} **异常归因** for attr in exploration_result[attributions]: summary f- {attr[dimension]}: {attr[explanation]}\n summary f **建议下一步** {exploration_result[recommendations]} **数据底稿** 可以根据以下 SQL 复现本次分析 sql {exploration_result[source_sql]}return summary## 三、Agent 的架构怎么设计三层结构 mermaid graph TB subgraph 用户交互层 A[自然语言问题] -- B[意图理解模块br/LLM] end subgraph 规划执行层 B -- C[分析路径规划器] C -- D{路径完备?} D --|否| E[生成下一步查询] E -- F[SQL生成器] F -- G[执行引擎br/Spark/ClickHouse] G -- H[结果解析器] H -- D D --|是| I[综合分析器] end subgraph 知识底座 J[表结构知识库br/字段含义/血缘] K[业务指标字典br/GMV...,留存...] L[历史分析案例br/Query → Report] end F -.- J H -.- K I -.- L I -- M[最终报告] style C fill:#afa,stroke:#333 style I fill:#afa,stroke:#333这个架构的巧妙之处在于规划执行层是一个循环——结果解析器发现信息不够时会自动回到路径规划器生成下一轮查询。这个循环一直持续到综合分析器认为现在信息足够给一个靠谱的结论了。四、落地避坑指南坑一SQL 生成不靠谱怎么办让 Agent 自己写生产级 SQL 确实有风险。实践中我们加了三层校验def safe_execute_sql(generated_sql: str, schema_info: dict) - dict: 安全执行 AI 生成的 SQL 为什么不能直接运行 AI 生成的 SQL AI 有时候会编字段名、用不存在的表、写天量扫描的查询 # 校验一字段名白名单 for field in extract_fields(generated_sql): if field not in schema_info[known_fields]: # 字段不在表里尝试模糊匹配 suggestion fuzzy_match(field, schema_info[known_fields]) return {error: f字段 {field} 不存在你是想查 {suggestion} 吗} # 校验二必须带分区条件 if WHERE not in generated_sql.upper(): return {error: 查询必须带 WHERE 条件限制分区请加上 dt ... } # 校验三预估扫描量 # 为什么限制扫描量防止一个查询扫全表几百 TB estimated_bytes estimate_scan_bytes(generated_sql) if estimated_bytes 10 * 1024**3: # 超过 10GB return {error: f预估扫描 {estimated_bytes/1024**3:.1f}GB请缩小时间范围或加过滤条件} # 通过校验安全执行 return execute(generated_sql)坑二Agent 说我分析完了但其实是糊弄AI 有时候会在信息不足的情况下强行给结论。解决办法是设定分析完成度的最低标准def check_analysis_completeness(report: dict) - bool: 检查分析是否真的完成了 为什么需要这个检查 LLM 有时会说根据目前的信息原因是A 但其实它根本没有去看 A 相关的数据 checks [ # 每个结论是否都有数据支撑 all(claim.get(evidence_sql) for claim in report[claims]), # 是否有异常但没有归因 not (report[has_anomaly] and not report[attributions]), # 覆盖的维度是否足够 len(report[dimensions_analyzed]) report[min_dimensions], ] return all(checks)坑三用户期望 Management 过高很多人以为 Agent 是扔进去一个问题自动出来完整报告。实际上 Agent 最擅长的是辅助探索不是替代分析师的判断。在团队落地时我们采用**Agent 初筛 分析师确认**的模式Agent 产出的不是最终报告而是 1. 异常指标列表带置信度 2. 初步归因假设需要分析师验证 3. 进一步分析的 SQL 建议分析师可以直接运行 分析师要做的是 1. 确认 Agent 的发现是否合理 2. 补充 Agent 遗漏的业务知识比如这次下降是因为大促结束 3. 最终决策五、总结 踩坑提醒Agent 在没有元数据时会脑补表结构如果你的元数据字典里缺少某张表的字段说明LLM 不会说我不知道而是会用它在训练数据里见过的类似表名来猜测字段。比如它看到order_detail就默认有order_status、user_id、amount这些字段哪怕你的表根本不是这个结构。解决方法是把字段白名单校验设为必过的硬门槛——只要生成的 SQL 里包含任何不在已知字段列表里的名字就拒绝执行并提示未知字段。分析循环必须有最大轮次上限Agent 的_need_deeper_analysis判断是基于数据特征的但如果阈值设得太敏感或者数据里有周期性波动被误判为异常Agent 就会陷入发现异常 → 下钻 → 又发现异常 → 继续下钻的死循环。生产环境必须设置max_rounds建议 5-8 轮和单次查询的超时30 秒超过上限就强制输出当前已知信息而非继续深挖。多轮对话 token 累积会冲淡早期上下文如果你用 LangChain 的ConversationBufferMemory原样塞入所有历史10 轮对话后 token 数轻松超过 4000LLM 倾向于只看最近几轮说话的内容对最早的业务背景一问三不知。建议用摘要记忆SummarizationMemory或只保留结构化分析状态而不是全量文本。多轮对话式数据探索 Agent 的核心价值不是替代写 SQL而是把探索过程中的衔接成本降为零。传统模式下每一次接下来查什么都需要人来做决策和编写 SQLAgent 模式下这些中间步骤全部自动化。落地建议不要一上来就追求全自动从异常检测 自动归因开始让 Agent 替你做发现异常 → 下钻归因这件事。等你信任了 Agent 的 SQL 生成能力再逐步放开从问题到报告的端到端流程。技术栈上LangChain 的 Agent 框架 公司的 SQL 查询引擎 LLM 服务是当前最成熟的组合。记住一点Agent 的能力上限取决于你给它喂了多好的元数据表结构、业务指标定义、历史分析案例。下篇我们来聊聊数据仓库的分层架构ODS-DWD-DWS-ADS 每一层到底该做什么不该做什么