移除哪块"上下文"最致命?—— 一次 AI Agent 上下文消融实验实录

我们用一个真实的跨国预算分析任务,把 Agent 上下文中的四个组件逐一"摘除",
观察它何时崩溃、何时变慢、以及最可怕的一种情况——看起来成功了,答案却是错的


一、引言:为什么上下文是 Agent 的生命线

和传统的一次性问答不同,AI Agent 是在一个循环里工作的:理解任务 → 调用工具 → 观察结果 → 再决策 → 再调用……直到产出最终答案。驱动这个循环的,不只是模型本身,更是喂给模型的那一长串上下文

  • 历史工具调用(我做过什么)
  • 推理过程(我当时的思考)
  • 工具调用命令(我要调用哪个工具、传什么参数)
  • 工具返回结果(刚才那一调用回传了什么)

这些组件各自值多少钱?哪个是"命根子"、哪个是"可选项"?回答这个问题不能靠猜,要靠消融实验(Ablation Study)——把组件一个一个拿掉,看 Agent 的表现如何变化。

本文基于《深入理解 AI Agent》第 1 章"实验 1-1 ★★:上下文的关键作用"的代码与思路,在 DeepSeek 模型上跑了一轮完整消融实验,下面是全部数据与解读。

二、实验设计

2.1 任务

一个跨国预算分析任务("Multinational Budget"),要求 Agent:

  1. 解析一份 PDF 财务报告;
  2. 通过货币换算工具把多币种数据统一为美元;
  3. 计算全球总支出、各区域占比;
  4. 按 8% 的比例做全员预算削减后,重新计算各项数字。

这是一个典型的多步 Agent 任务:外部数据获取(PDF)+ 工具计算 + 顺序依赖的推导,任何一步断掉都会影响最终结果。

2.2 模型与配置

  • 模型:DeepSeek(默认模型)
  • 基线与四个消融臂共 5 种上下文配置
配置 拿掉了什么 一句话含义
full(基线) 什么都不拿 完整上下文
no_history 历史工具调用 Agent 记不住自己做过什么
no_reasoning 推理过程 Agent 不再"想一步做一步"
no_tool_calls 工具调用命令 Agent 无法调用任何外部工具
no_tool_results 工具返回结果 Agent 发出调用,却看不到返回值("盲操作")

2.3 观察指标

  • 执行时间(execution_time):跑完(或放弃)花了多少秒
  • 迭代轮数(iterations):Agent 与模型来回了几轮
  • 工具调用次数(num_tool_calls):实际调用了多少次工具
  • 是否产出终态回答(has_final_answer / completed):有没有给出最终答案

⚠️ 一个重要的方法论提醒:本套件的 success 字段只表示"Agent 给出了一个终态回复",并不代表任务做对了。任务正确性必须用任务级的评分标准(rubric)单独核对。这一点在第四组实验里会变成血淋淋的教训。

三、结果一览

配置 执行时间 迭代轮数 工具调用 终态回答 最终答案正确性
完整上下文(基线) 23.74s 3 6 ✅ 正确($11,990,955.43)
① 无历史工具调用 41.69s 10 50 ❌ 未完成
② 无推理过程 23.49s 4 6 ✅ 正确(同上)
③ 无工具调用命令 62.67s 1 0 ❌ 未完成
④ 无工具返回结果 83.03s 6 10 ⚠️ "完成" 错误($11,951,000)

(完整原始数据见文末仓库中的 ablation_results.json

四、逐臂解读

4.1 ① 无历史记录:失忆症的代价是"重复劳动"

去掉历史工具调用后,Agent 变成了一个失忆症患者:它不记得自己刚刚解析过 PDF、也不记得已经查过汇率,于是:

  • 工具调用从基线的 6 次暴涨到 50 次(超过 8 倍);
  • 迭代了 10 轮仍然没有跑完,最终没有产出任何终态回答
  • 用时从 23.74s 膨胀到 41.69s。

解读:历史记录的价值不在"聪明",而在"不犯蠢"。没有它,Agent 每一步都从零开始,多步依赖任务(先用 PDF 结果、再算汇率、再汇总)会陷入无休止的重做循环。它是多步任务的连贯性保障

4.2 ② 无推理过程:本任务上几乎零影响

去掉推理过程后,Agent 表现与基线几乎完全一致:

  • 用时 23.49s(基线 23.74s);
  • 工具调用同为 6 次;
  • 最终答案与基线一字不差($11,990,955.43)。

解读:对这个任务来说,模型的"推理文本"是冗余的——不写思考过程,答案照样对,速度还略快。这提示我们:推理过程不是免费的午餐,也不是万灵药。当然,这只是一个任务、一个模型上的结论;在数学证明、长链条规划等复杂推理任务上,推理过程的价值可能会完全不同。

4.3 ③ 无工具调用命令:直接瘫痪

拿掉工具调用后,Agent 变成了一个"只能空谈的咨询师":0 次工具调用,只迭代了 1 轮就结束了,没有产出任何答案(用时 62.67s 主要耗在了单轮的长回复上)。

解读:这是最不意外的一组。这类任务的数据(PDF 内容、汇率)完全来自外部工具,砍掉工具等于砍掉了任务的地基。工具是硬依赖,没有商量的余地。

4.4 ④ 无工具返回结果:最危险的"成功" ⚠️

这是整场实验里最值得警惕的一组。Agent 可以发出工具调用,但看不到任何返回值——像一个蒙着眼睛开车的人:

  • 它花了 83.03s(全场最慢),迭代 6 轮、调用 10 次工具;
  • 协议层面它"完成了":completed=truesuccess=true、有终态回答;
  • 但答案错了:它给出总支出 ​11,951,000,而正确答案是 **11,990,955.43**,少了约 4 万美元(相对误差约 0.33%);
  • 各地区占比也全部跑偏(如美国 20.92% vs 正确的 20.85%,日本 20.99% vs 正确的 21.20%)。

解读:看不见结果,Agent 就会用"猜"来填补空白——它甚至会在盲区里重复调用(10 次 vs 基线的 6 次)来试图"蒙对"。最可怕的地方在于:这是一个表面健康的失败。如果你只看 success 标志,你会以为一切正常,然后把这个差 4 万美元的数字写进预算报告。

这正是实验报告里那句警告的含义:

"A terminal response is not evidence that the financial task was completed. Task-level claims require a separate evaluator."

协议完成 ≠ 任务完成。success 会撒谎,rubric 不会。

五、关键启示

启示 1:验收 Agent,必须用任务级评分标准

success=true 只证明"Agent 说了句结束语"。要判断它到底做没做对,必须有一个任务特定的 rubric——例如把最终答案与预期数值比对(本仓库的 run_experiment_1_1.py 就是这么做的:它把模型的回答与预计算的标准答案做数值核对)。第四组实验就是"无 rubric 验收"的完美反面教材。

启示 2:上下文裁剪的经济学——要省钱,先砍谁?

上下文越长越贵,生产环境里大家总想"裁剪"上下文省 token。这组实验给出的优先级建议是:

  1. 最不能砍:工具调用 + 工具返回结果。砍前者直接瘫痪,砍后者产出错误答案——省下的钱不够一次错误决策的损失。
  2. 谨慎保留:历史工具调用。砍掉它不会马上出错,但会让成本失控(50 次调用 vs 6 次),效率损失本身就是成本。
  3. 优先候选:推理过程。在本任务上几乎零损耗。若真要做上下文压缩,考虑对推理文本做摘要/截断,而不是直接删除历史与工具结果——删除是"截肢",摘要才是"减肥"。

启示 3:正确性比"跑完"更难测量,也更值钱

四组消融里,最贵的一组(83s、10 次调用)反而是错误的一组。"慢但错"比"快但没做完"危害更大,因为它会混入正常结果、污染下游决策。评估体系必须把"正确性"和"完成度"分开统计。

六、局限与后续工作

这份实验必须诚实地标注边界:

  1. 单任务、单模型、单次运行:结论来自一个任务(跨国预算)和一个模型(DeepSeek)的一次运行。LLM 输出有随机性,严谨起见应当多次重复取均值
  2. 推理过程"无用"的结论不能外推:本任务的推理依赖较浅;在复杂推理任务上,no_reasoning 可能表现出完全不同的结果;
  3. 缺少任务级 rubric 的自动评判:本套件记录了行为数据,但正确性核对目前依赖人工/独立脚本(run_experiment_1_1.py 提供了数值 rubric 的参考实现)。

后续可以做的方向:多模型横向对比、多任务重复实验、推理文本压缩(摘要 vs 截断)的消融、以及把 rubric 自动评分接入主流程。

七、复现指南

想亲手跑一遍?三步即可:

# 1. 获取代码
git clone https://github.com/Hanserwei/ai-agent-context-ablation.git
cd ai-agent-context-ablation

# 2. 配置 API Key
pip install -r requirements.txt
cp env.example .env
# 编辑 .env,填入任一 provider 的 API Key(如 DEEPSEEK_API_KEY)

# 3. 运行消融实验
python main.py --mode ablation

运行后会在当前目录生成:

  • ablation_results.json —— 每组配置的原始数据(时间、迭代、调用次数、终态回答)
  • ablation_study_report.md —— 自动生成的英文实验报告
  • ablation_study_results.png —— 可视化对比图

run_experiment_1_1.py 可以跑带任务级数值 rubric 的严谨版本(它会持久化每一次请求/响应,并核对最终答案是否正确)。

八、结语

一个看似简单的消融实验,暴露了 Agent 工程里最容易被忽视的真相:上下文组件之间是不平等的。工具调用与工具结果决定 Agent"能不能做对",历史记录决定"做得贵不贵",而推理过程在某些任务上只是锦上添花。

以及那条最值得写进团队检查清单的教训:永远不要用"它跑完了"替代"它做对了"来验收一个 Agent。


代码仓库

本文所有实验代码与完整结果数据均已开源:

📦 https://github.com/Hanserwei/ai-agent-context-ablation

(代码来源:https://github.com/bojieli/ai-agent-book/tree/main ,chapter1/context 目录,实验 1-1:上下文的关键作用)