数据Agent的上下文工程:从翻车到可信的完整方案

发布时间:2026/10/20 3:16:55
数据Agent的上下文工程:从翻车到可信的完整方案 最近帮某团队复查他们内部的数据 Agent翻车翻得非常典型一个看起来任务很简单的分析助手问它上季度各品类销售波动原因结果它一本正经地给出了五条结论每条都用了不存在的字段名还把 GMV 口径算错甚至连只看自营商品这个约束都忘了。更让人头疼的是这 Agent 换了大模型之后照样翻车——这就说明问题根本不在模型能力上。这类现象我这两年在不同团队里见过太多次了。做数据方向的朋友大概率都有同感Agent 本身不难跑通难的是让它稳定输出可信的数据结论。而大部分团队在调优时第一反应是换更强的模型、写更长的 prompt、塞更多的背景资料结果往往事倍功半。真正缺的其实是一层东西——上下文。我说的上下文不是对话历史那种上下文而是面向数据任务的一整套领域事实层表结构、字段口径、业务规则、数据质量快照、历史执行反馈。这一层没搭好模型再聪明也是无米下锅。这篇文章我会从一次真实翻车案例讲起拆一拆数据 Agent 为什么在这件事上这么脆弱然后给出一套可以直接落地的上下文装配层设计方案最后聊聊怎么把它变成可持续维护的基础设施。适合正在做数据 Agent、BI 自然语言查询、数据分析助手的团队参考也适合准备入门这类项目的人理解问题全貌。1. 看似模型不行其实是上下文没给够一次数据 Agent 翻车经历1.1 从换模型开始的错误自救那个团队最开始的做法和大多数人一样遇到 Agent 答错先怀疑模型不够强。他们从开源小模型一路换到当时能拿到的最强商用模型现象确实有改善但远达不到可信的程度——有些问题这次答对了下次同样的问题换了个问法又错了有些问题换个日期范围结论就南辕北辙。这种薛定谔的正确率非常折磨人。团队成员一度认为是提示词写得不到位于是把公司数据平台的使用文档、甚至整个数据库的建表语句都塞进 system prompt 里结果上下文被撑到几万 token效果反而更不稳定了。我去复查的时候先做了一件很简单的事把每次请求实际发给模型的内容完整打印出来。不看不知道一看问题全暴露了——建表语句确实塞进去了但排在 1800 多行产品说明日志的后面。模型真正开始生成 SQL 时那些关键的表结构信息早就被淹没了注意力根本覆盖不到。这还没算上字段注释里的口径描述跟实际业务规则完全对不上的情况。1.2 翻车的四类典型症状把过去看到的失败案例归归类数据 Agent 的翻车基本逃不出下面几种症状典型表现直觉判断实际根因字段幻觉SQL 里用了不存在的列名表 join 逻辑混乱模型不行没注入可信 schema模型只能靠训练记忆猜口径漂移同一指标在不同问题里口径不一致甚至自创口径推理能力弱缺少统一指标口径定义Agent 不知道唯一解释是什么约束遗忘前面说过只看自营第二轮就忘了记忆太短任务约束没有结构化进入上下文只是对话里的一句话无据编造对一个下降品类强行给出天气影响之类的解释幻觉缺少数据侧证据链模型只能用常识补这四类症状看起来五花八门但顺着根因往深挖一层你会发现它们全部指向同一个问题Agent 在生成回答时手里没有一份关于这批数据的权威事实清单。1.3 为什么换模型解决不了这类问题这里需要把道理讲透。模型的知识来自训练语料而训练语料里不可能包含你公司的表结构、指标口径和业务规则。举个例子模型可能知道GMV这个词在电商语境下的大致含义但它不可能知道你们公司的 GMV 是按订单创建时间算还是按支付时间算要不要扣退款。你可能觉得那就把口径写进 prompt 里呗。对这就是上下文的作用。但问题在于数据任务的上下文不是写一段说明文字那么简单它需要结构、优先级、新鲜度和可校验性。闲聊场景里上下文只是背景但数据场景里上下文是唯一的事实来源错一点都不行。换模型之所以经常无效是因为你换的只是推理引擎但燃料——事实上下文——还是缺的。引擎再好没有燃料照样熄火。2. 数据任务对上下文的苛刻程度远超普通聊天场景2.1 对话型任务与数据型任务的根本差异普通聊天 Agent 的任务是语义合理即可数据 Agent 的任务是结果可验证、可复现。这两个目标对上下文的要求完全是两个量级。对话场景里用户问推荐一本编程书模型答非所问顶多算体验不好数据场景里用户问上季度华东区 GMV 环比为什么下滑Agent 一旦用了错误字段或者错误口径产出的就是一个看似合理但错误的数据结论。这种错误一旦被业务方当成决策依据后果是不可控的。所以数据 Agent 的上下文必须承担一个更重的职责约束生成空间。它不是给模型提供背景知识而是要明确告诉模型哪些字段是真实存在的、哪些口径是唯一的、哪些规则是必须遵守的。这才叫上下文。2.2 数据语义的高密度一个字段背后藏着六层信息做数据分析的人都知道一个字段名从来不是字面那么简单。拿最常见的orders.amount举例这个字段背后至少藏着六个问题金额单位是元还是分含不含税是下单金额、支付金额还是结算金额退款单算不算负数统计时间用下单时间、支付时间还是发货时间是否区分自营和第三方商家这些信息不会出现在字段名里也不会出现在模型训练数据里。它们只存在于数据字典、指标口径文档和业务老员工的脑子里。普通对话上下文完全承载不了这种高密度语义。如果你只是把字段名和注释原样丢给模型它大概率会用自己的常识补全那些缺失的判断补出来的还特别自信。这也就是数据 Agent 最常见的翻车姿势模型不是不会 SQL而是它的常识和你的业务事实根本不是一回事。2.3 数据是活物静态 prompt 喂不出动态真相还有一点经常被忽略数据是活的。表结构会加字段、枚举值会新增、历史数据会重刷、指标口径会因为业务调整而变化。你上个月写的口径说明这个月可能就已经过时了。而模型的参数是静态的prompt 里的文字也是静态的。如果你把上下文当成写一次就完事的配置那么 Agent 必然会随着时间推移逐步失真。真正可用的数据上下文需要有一个程序化的装配过程每次提问都去拉最新的表结构、跑最新的数据快照、读取最新的规则配置然后组装成一个结构化的上下文包。这也是为什么我说数据 Agent 缺的不是模型而是上下文工程它是动态的、程序化的、可维护的不是写死的提示词。3. 把一次真实翻车拆开看症状、排查链路和根因3.1 任务背景与看似正常的表现为了把问题讲具体我拿模拟项目 X 来复现整个排查过程。背景是一家零售电商平台内部做了一个经营分析 Agent核心能力是回答管理层的数据问题并自动生成分析报告。第一次测试任务是这样分析上季度各品类 GMV 波动原因找出哪些品类拖了后腿给出建议。Agent 的答复大意是有三个品类 GMV 环比下降明显其中家居日用下降 32%推测原因包括季节性因素、某大促活动分流、以及消费者偏好变化。建议是优化选品、增加促销投放。表面看结构完整、逻辑流畅但仔细一查全是问题。3.2 症状拆解三个错误一个比一个隐蔽第一个错误是字段幻觉。Agent 生成的 SQL 里 JOIN 了一个store_sales_detail表但真实表名是shop_order_flow。更离谱的是它还 SELECT 了一个叫category_growth_rate的字段实际这个字段只存在于某个被废弃的宽表里。第二个错误是口径问题。Agent 算 GMV 用的是支付成功订单金额但公司统一指标口径是订单创建金额扣除退款。两者在促销场景下差异非常大因为很多用户下单后不支付或退款支付口径会明显低于创建口径。第三个错误是约束遗忘。任务描述里明确写了分析范围为自营商品但 Agent 生成的 SQL 里没有加任何business_type过滤条件把第三方商家的数据也卷进来了。业务方如果照单全收会做出完全错误的判断。3.3 完整排查链路我到底是怎么找到根因的我不打算直接给结论把当时的排查链路完整写出来大家可以照这个思路去排自己的问题。第一步复现并缩小范围。先用同样的任务跑三次记录下来每次生成的 SQL 和最终答复。发现三次结果里 JOIN 的表名各不相同但都属于看起来存在的表——这说明模型在猜而且猜得还挺自信。第二步换模型对照实验。同样的问题换另一个更强模型跑字段幻觉依然存在只是幻的字段不一样。这一步基本排除模型推理能力不足这个假设。第三步检查实际发送的 prompt。把 Agent 框架打印出来的请求体拉出来看发现建表语句确实注入到了 system prompt但前面被塞了三大段产品介绍文档、几十条历史聊天记录、还有一大段不知道哪来的数据治理规范。真正的 schema 信息排到了第 1800 多行。第四步验证注意力问题。我把 schema 信息单独抽出来放到 system prompt 最前面并删掉无关内容。同一任务再跑一次字段幻觉大幅减少但口径问题依旧存在——原因是字段注释里只写了订单金额没有明确的口径定义模型还是用自己的常识补了。第五步验证约束传递。我在 prompt 里把仅限自营从对话历史挪到一个单独的任务约束区块并且加粗强调。再跑测试SQL 里终于出现了business_type self-operated条件。第六步加入反馈回灌。前面所有测试里SQL 执行报错信息是没有传回给模型的。我在工具层加了一步把报错信息和真实表结构做一个比对把表不存在、字段不存在这类错误格式化后回传让模型基于反馈修正自己的 SQL。这一步之后字段幻觉基本消失。3.4 根因总结上下文装配失序、缺失、断裂把链路走完结论非常清晰。这个 Agent 翻车不是某一个环节坏了而是三个层面的上下文处理都有问题第一是装配失序有用的 schema 信息排得太靠后被无关内容稀释。这好比你把菜谱塞在一堆报纸最底下厨师翻到一半就放弃开始凭经验做菜。第二是事实缺失字段注释里没有口径定义。模型不是故意算错 GMV是没人告诉它正确的算法是什么。第三是反馈断裂工具执行失败的信息没有回到生成链路里模型犯了错却不知道下一次继续犯同样的错。这三层问题没有一个是靠换模型能解决的。它们全部指向同一个答案你需要专门给 Agent 建一层上下文装配机制。4. 给 Agent 补上上下文装配层一份可直接照抄的设计方案4.1 五类上下文每一层解决一类翻车在模拟项目 X 的修复过程中我把数据 Agent 的上下文拆成了五类每一类对应解决前面提到的一类翻车问题。第一类是任务上下文。它的作用是明确这次要解决什么问题、有哪些硬性约束。比如分析范围、时间范围、对比基准、要输出的表格格式。这层解决约束遗忘问题核心做法是把用户提问里的约束条件结构化提取出来而不是埋在对话历史自然语言里。第二类是静态元数据上下文。包括表结构、字段注释、主外键关系、表间 join 关系。这层解决字段幻觉问题核心做法是动态拉取真实的 schema 信息而不是凭模型的记忆。第三类是规则上下文。包括指标口径定义、业务规则、数据权限边界。这层解决口径漂移问题核心做法是把口径文档转成机器可读的规则卡片。第四类是数据快照上下文。包括当前数据量、缺失率、去重率、枚举值分布、近期异常波动。这层解决无据编造问题——模型说某个品类下降明显必须能指向真实数据佐证。第五类是执行反馈上下文。包括上一步工具调用的结果、SQL 报错信息、校验失败原因。这层解决蒙眼开车问题让模型能从错误中自我修正。4.2 装配顺序先事实后推断先约束后发散五类上下文都有了接下来关键是怎么拼、按什么顺序拼。我摸索出一个行之有效的原则先事实后推断先约束后发散。具体来说装配顺序应该是任务摘要和约束清单告诉模型你要干嘛、不能干嘛数据快照摘要告诉模型当前数据长什么样、有没有异常规则卡片告诉模型这些指标的口径是什么不许自己发挥静态 schema告诉模型可以用哪些表、哪些字段历史执行反馈告诉模型之前踩过哪些坑这次规避掉对话历史仅作参考放在最后这么排序的原因很实际越靠前的内容越容易被模型严格执行。任务约束和口径规则放在前面模型会把这些当成不可违反的前提schema 放中间模型把它当成事实词典对话历史放最后相当于告诉它过去的话只是背景参考不是硬性约束。4.3 元数据注入的三个实操细节把上面五类上下文落地的过程中有三个细节是必须注意的不然方案会废掉。细节一不要全量注入 schema要用检索式装配。数据平台动辄几百张表全塞进去既费 token 又稀释注意力。正确做法是先解析用户问题提取关键词然后通过 embedding 检索相关的表和字段限制在 5 到 10 张表以内。这就好比给分析师的不是整个档案室而是和本次任务相关的悬着红标签的五份文件。细节二规则卡片必须带唯一标识和优先级。同一个指标在文档里可能有多个描述如果有冲突上下文里必须明确标注以公司统一口径为准。我见过一种很有效的做法给每条规则加level字段取值是company_standard、department_standard、temporary。模型在生成时如果发现不同来源的规则冲突可以直接识别优先级而不是随机选一个。细节三数据快照必须是当天的。如果 Agent 分析的是最近七天的数据那么上下文里注入的数据分布快照也必须是最近七天跑出来的不能拿一周前的静态文件。这个听起来简单但自动化起来有很多坑调度怎么触发、跑挂了怎么办、要不要降级策略。我的建议是先做成定时任务每天早上生成一次 JSON 快照失败自动重跑一次仍失败就跳过并写日志——宁可没有快照也不要把过期快照当新鲜的喂给模型。4.4 一段可参考的装配层伪代码为了方便大家理解我写一段简化过的装配逻辑技术栈无关重点看结构。# context_assembler.py —— 简化示意 class ContextAssembler: def __init__(self, schema_registry, rule_registry, profile_service, memory_service): self.schema_registry schema_registry self.rule_registry rule_registry self.profile_service profile_service self.memory_service memory_service def assemble(self, question: str, constraints: list[str]): # 1. 解析问题提取涉及的表/字段关键词 related_tables self.schema_registry.search_tables(question) # 2. 拉取真实 schema 信息不是模型记忆里的 schema schema_ctx self.schema_registry.fetch_schemas(related_tables) # 3. 拉取当天数据快照 snapshot_ctx self.profile_service.get_daily_snapshot(related_tables) # 4. 匹配指标口径规则 rule_ctx self.rule_registry.match_rules(question) # 5. 提取历史相似任务的失败教训 feedback_ctx self.memory_service.top_k(question, k3) # 6. 按优先级渲染成上下文包 sections [ self.render_task(constraints), self.render_snapshot(snapshot_ctx), self.render_rules(rule_ctx), self.render_schema(schema_ctx), self.render_feedback(feedback_ctx), ] return \n\n.join(sections)关键点有两个schema_registry必须是真实的元数据注册中心而不是静态文件profile_service必须产出当天快照而不是复用旧数据。这两个基础服务建议在 Agent 项目启动的第一天就同步搭建。4.5 工具校验环从让模型判断到让系统拦截最后补一个非常容易忽略但极其重要的组件——工具校验环。前面拆解时提到执行反馈断裂是翻车的重要根因。修复思路是在模型和工具之间加一层校验器。以 SQL Agent 为例在模型生成 SQL 后、真正执行之前先做一次静态校验用 SQL 解析器检查所有表名、字段名是否存在于 schema 注册表中检查类型是否匹配比如日期字段不能直接做数值运算检查是否使用了被禁止的列比如权限外的敏感字段如果校验失败把具体的错误信息格式化回传给模型让它重新生成。这一层的好处是它不依赖模型自己发现错误而是用确定性规则先行拦截。模型生成时仍然可能犯错但有了这层护栏错误不会直接流入执行环境而是转换成模型可理解的修正信号。我在模拟项目 X 里实测加上这一层之后SQL 首轮执行成功率从 45% 左右提升到了 80% 以上。更关键的是整个系统的行为变得稳定可预期了。5. 上下文不是写好一次就完事评估、维护与监控5.1 给上下文建一套金标问题集上下文装配层建好之后很多人容易进入另一个误区以为方案没问题就再也不管了。数据 Agent 的上下文化和代码一样需要持续回归测试。我建议从项目一开始就建一套金标问题集包含 20 到 30 个已经人工核实过答案的问题覆盖最常见的业务场景和最容易翻车的坑至少包含几个需要正确口径的指标问题、几个需要多表 join 的问题、几个带约束条件的问题、几个需要识别异常数据的问题。每次调整上下文装配逻辑、修改规则卡片、更新 schema 注入策略之后都用这套金标问题集跑一遍全量回归。哪个问题答错了对比之前的结果就能立刻看出这次改动引入了什么偏差。这套东西看起来笨但它是整个项目长期稳定性的定海神针。没有它你会陷入修好一个 bug 引入另一个 bug的循环。5.2 上下文覆盖率清单每类信息是否到位除了金标问题集我还会定期检查一个上下文覆盖率清单。这个清单的目的不是看功能正常而是看每一轮任务里模型到底有没有获得足够的信息来完成判断。我用的检查项是这样的检查项说明判定方式字段覆盖影响 SQL 中每个字段是否在上下文中存在对应说明校验器自动比对口径覆盖回答涉及每个指标是否有一条唯一口径定义规则匹配率约束覆盖用户每次提出的限定条件是否结构化写入了任务模块人工抽查反馈覆盖工具调用失败信息是否回灌到下一轮生成日志检查新鲜度数据快照是否为当天生成schema 是否为最新版本时间戳比对这个清单每个月手工检一次加上每次出问题时的复盘基本能保证上下文层不会悄悄腐烂。5.3 上下文漂移当事实变化时系统怎么知道数据团队有个日常痛点表结构变了、字段下线了、枚举值调整了但 Agent 不知道。它还会按旧 schema 生成 SQL然后一直报错。解决这个问题需要在 schema 注册中心加一个版本感知机制。每次元数据变化自动重新生成上下文包而不是复用旧缓存。同时在装配层里给每条 schema 信息带上version和updated_at字段。模型生成 SQL 后校验器如果发现某个字段已经下线会给出明确提示store_sales_detail.category_growth_rate字段已于 2025-01-15 下线请改用shop_order_flow.category_rate。这样就把Agent 默默用旧知识撒谎变成系统明确报告事实变更了。团队每天只需要扫一眼变更日志就知道 Agent 的行为为什么可能会变。5.4 几个我踩过之后才明白的坑最后分享几个我在实际落地时踩过的坑都是文档里不会写的东西。第一个坑是上下文越多越好的错觉。有一次我把所有元数据都塞了进去结果模型开始纠结两个口径互相矛盾的注释反而把原本简单的问题复杂化了。后来我把上下文当成必要的约束而不是背景阅读材料才恢复正常。第二个坑是只注入不校验。刚开始我天真地以为只要 schema 注入到位模型就不会再用错字段。后来发现模型偶尔还是会写出不存在的字段因为模型在生成长 SQL 时太顺了顺着顺着就开始用训练记忆里的表名。所以工具层的静态校验无论如何都不能省。第三个坑是上下文包不带版本号。早期出现过一个事故某天下线一个字段后Agent 回答全乱了但大家不知道是哪个版本引入的花了两天去排查。之后我要求所有上下文包都带版本号每次改动都有记录回滚也就变成一条命令的事。数据 Agent 这个方向真正的门槛不在于把模型接进来而在于你能否为它构建起一个准确、新鲜、可维护的领域上下文底座。模型只是一台优秀的推理引擎但它对你们的业务一无所知——它知道的每一条关于你业务的事实都得靠这个上下文层一点一点喂进去。我把这套上下文装配层跑通之后最大的体会是不要把上下文工程当成提示词技巧它是一个有版本、有测试、有监控的软件基础设施。你对待它的方式应该像对待数据仓库里最核心的维度表一样认真。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询