# 上下文腐化：为什么上下文越长，AI 的答案越差

> 上下文腐化，是指模型的输入越长，准确率越低，而且在上下文窗口远没占满时就开始了。放在长输入中间的事实更容易被漏掉，比找出一句话更难的任务也会更早出错。对付它的办法是少发内容：少接工具，剪短工具结果，再用笔记开启新的会话。

Mindket 编辑部 · 发布于 2026-11-06 · 更新于 2026-11-06 · https://mindket.com/cn/learn/context-engineering/context-rot

## 要点

- 在你实际发送的输入长度上测出准确率从哪里开始下滑，别只信宣传的窗口大小。
- 把答案所依赖的那条事实放在提示词的开头或结尾附近。
- 测试时用和问题措辞不同的事实。
- 长时间运行的智能体，在跑偏之前就从笔记文件重新开始。

## 开始之前

`needlehaystack` 包需要 Python 3.12 或更新版本，[PyPI](https://pypi.org/project/needlehaystack/) 上的版本是 2.0.0。第一个演示不需要 API 密钥。要测真实模型，就把 `OPENAI_API_KEY` 或 `ANTHROPIC_API_KEY` 写进 `.env` 文件。

本课程的第一课[什么是上下文工程](https://mindket.com/cn/learn/context-engineering/what-is-context-engineering)，列出了每次调用时上下文里装着什么。这一课讲的是，这堆内容越来越多时，准确率会怎样。

## 用大海捞针测试量出上下文腐化

先在你用的模型上把它量出来。大海捞针测试，是把一条事实（针）藏进一大段填充文字（大海）里，再让模型把它找出来。深度指这条事实在上下文中的位置，顶部是 0%，底部是 100%。

这个测试背后的开源工具叫 `niah`，它在一张长度和深度的网格上逐格测试，每一格写一行结果。下面的命令来自它的 [README](https://github.com/gkamradt/needle-in-a-haystack)。

````bash
pip install needlehaystack
niah demo --fake          # no API key, ~1s, proves the install works
niah reconstruct results.jsonl --row 0

niah demo --provider anthropic            # needs ANTHROPIC_API_KEY

niah validate my-run.yaml         # parse + resolve, no model calls
niah run      my-run.yaml         # actually run the sweep, append to JSONL
````

1. 用 `pip install needlehaystack` 安装。
2. 运行 `niah demo --fake`。它用进程内的假模型，跑 2 种长度乘 3 种深度的网格，写出 `results.jsonl`，不用密钥就能检查整条流程。
3. 用 `niah reconstruct results.jsonl --row 0` 还原模型看到的内容。每行结果只存一份配方，不存全文，这条命令会把它还原成一模一样的上下文。
4. 把 `ANTHROPIC_API_KEY` 写进 `.env`，运行 `niah demo --provider anthropic`。工具会自己读取 `.env`。
5. 把 README 里的模型配置复制到 `configs/models/` 下，文件名要和运行配置里 `model` 那一行一致（示例就是 `configs/models/anthropic-opus-4-medium.yaml`），然后在包含 `configs/` 的文件夹里，用 `niah validate my-run.yaml` 检查，再用 `niah run my-run.yaml` 运行。

## 一次扫描改变了哪些变量

README 里的示例运行配置，在 2,000 到 32,000 个 token 之间取 8 种上下文长度，在 0% 到 100% 之间取十一个深度点，每一格跑三个随机种子。

sigmoid 间隔会把更多深度点放在上下文的顶部和底部附近。`model` 这一行指向 `configs/models/` 下的一个文件，里面是发给 SDK 的请求设置。

它的任务类型是 `uuid_chain`：把 A 指向 B、B 指向 C 这样的链接散布在上下文里，只问 A 对应的值，却不说出这条链。模型得自己找出每一跳，这比单纯查找考得更多。

另外几种内置任务是 `single`、`multi` 和 `uuid`。把 `model` 指向你实际上线的模型，把 `context_lengths` 设成你的应用会发送的长度，扫描结果才能回答你自己提示词的问题。

````yaml
run_name: "uuid-chain-opus"
model: "anthropic-opus-4-medium"   # resolved against configs/models/

task:
  type: "uuid_chain"
  chain_length: 5

haystack:
  type: "files"
  path: "PaulGrahamEssays"

sweep:
  context_lengths: {min: 2000, max: 32000, num: 8,  scale: "linear"}
  depth_percents:  {min: 0,    max: 100,   num: 11, scale: "sigmoid"}
  seeds: [1, 2, 3]

runner:
  concurrency: 2
  retries: 2
  resume: true

store:
  type: "jsonl"
  path: "results/uuid-chain-opus.jsonl"
````

## 长输入的中间部分容易丢

位置和长度一样要紧。在 2023 年的一项研究里，Nelson Liu 和同事给模型 20 篇检索到的文档和一个问题，答案只在其中一篇里，然后把这篇文档从第一篇一路移到最后一篇。

答案在第一篇时，GPT-3.5-Turbo 的正确率是 75.8%，在最后一篇时是 63.2%。

放在第 10 篇时，它跌到 53.8%，比完全不给文档时的 56.1% 还低。Claude 1.3 的曲线平一些，在 55.9% 到 60.1% 之间。

[论文](https://huggingface.co/papers/2307.03172)把这种形状叫作 U 形：两头最好，中间最差。

落到你写的提示词上，就是把答案所依赖的那条事实放在开头或结尾附近，不要埋在一大段粘贴内容的中间。

**GPT-3.5-Turbo 的正确率，按答案在 20 篇文档中的位置** 回答正确的问题比例，出自论文中 20 篇文档的表格。金色那一条是中间位置。

- 答案在第 1 篇: 75.8%
- 第 5 篇: 57.2%
- 第 10 篇: **53.8%**
- 第 15 篇: 55.4%
- 第 20 篇: 63.2%
- 不给文档（闭卷）: 56.1%

来源：[Hugging Face Papers: Lost in the Middle: How Language Models Use Long Contexts](https://huggingface.co/papers/2307.03172) (2026-11-06 查阅)

## 为什么通过大海捞针测试还不够

对大多数模型来说，找出一句话已经不难了，所以新的测试把难度加了上去。2025 年的基准测试 NoLiMa，让“针”和问题之间没有一个相同的词。模型要把两者联系起来，就得知道，比如说，森佩尔歌剧院在德累斯顿。

在这篇论文的最新版本里，13 个号称支持至少 128K token 的模型中，有 11 个在 32K 长度时跌到不足短上下文成绩的一半。GPT-4o 从 99.3% 降到 69.7%（见 [NoLiMa](https://huggingface.co/papers/2502.05167)）。

NVIDIA 的 [RULER](https://huggingface.co/papers/2404.06654) 在 2024 年也发现了同样的落差。按它的最新版本，测的 17 个模型在普通大海捞针测试上几乎都接近满分，可一旦任务需要多根针、追踪或汇总，只有一半在 32K 长度时还能保持令人满意的表现。

OpenAI 的 [GPT-4.1 提示词指南](https://developers.openai.com/cookbook/examples/gpt4-1_prompting_guide)说，这个模型在大海捞针测试上一直到 1M token 的上限都表现很好。指南同时提醒，要找出的条目越多，或者任务需要掌握整个上下文的状态，比如图搜索，表现就可能下降。

Chroma 在 2025 年 7 月的技术报告题为 Context Rot: How Increasing Input Tokens Impacts LLM Performance。它的[复现代码](https://github.com/chroma-core/context-rot)包含三个实验：按意思而不是按字面匹配的针、来自 LongMemEval 的长聊天记录问答，以及照抄一串重复的词。README 这样概括结论：即使任务很简单，模型表现也会随输入长度变化。

原因在于 Transformer 读取内容的方式，Anthropic 的[上下文工程指南](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)做了解释。每个 token 都会关注其他所有 token，n 个 token 就有 n² 对关系，上下文越长，固定的注意力预算就摊得越薄。

模型在训练中见到的短序列也比长序列多。指南说，结果是一道缓坡，而不是一下子掉下悬崖。

## 长上下文里该把什么挡在外面

在智能体里，越堆越多的主要是工具输出和旧回合。

2026 年 6 月的一项研究，看了四个开源模型做长时间网页搜索的过程，发现累积的上下文越多，模型越常直接放弃，或者给出没把握的答案。把这些上下文删光，这两种情况几乎消失，但没跑完的任务变多了（见[论文](https://huggingface.co/papers/2606.29718)）。所以要有计划地删，而不是一次删光。

压缩和记忆工具有单独的一课，[智能体记忆](https://mindket.com/cn/learn/context-engineering/agent-memory)，按需载入工具和文件则是[按需载入上下文](https://mindket.com/cn/learn/context-engineering/just-in-time-context)的内容。

下表只给出简要做法，清除旧结果、记笔记和按需载入，这两课会讲得更深入。

| 越堆越多的内容 | 怎么处理 | 出处 |
| --- | --- | --- |
| 智能体已经用完的工具调用结果 | 清掉。Anthropic 把清理旧工具结果称为最轻量的压缩方式之一。 | Anthropic：Effective context engineering for AI agents |
| 很长的工具输出 | 分页、过滤或截断。Claude Code 默认把一次工具响应限制在 25,000 个 token。 | Anthropic：Writing effective tools for agents |
| 当前任务从不调用的工具 | 少接几个服务器，或者等某一步需要时再载入工具。 | Anthropic：Effective context engineering for AI agents 和 Introducing advanced tool use |
| 连着做了好几个任务的会话 | 把进度写进文件，再开一个读取这个文件的新会话。 | Niels Rogge 发在 Hugging Face 博客上的文章 |

## Greg Kamradt 的大海捞针测试和 Niels Rogge 的 60% 习惯

大多数长上下文报告引用的大海捞针测试，最早是 X 上的一条帖子。2023-11-08，如今担任 ARC Prize 主席的 Greg Kamradt [发布了](https://x.com/GregKamradt/status/1722386725635580292)他对 GPT-4-128K 的测试结果。

他把一句关于旧金山的话藏进 Paul Graham 的文章里，测了 15 种深度和 15 种长度，最长到 128K token。超过 73K token 后，回忆能力开始下降，放在 7% 到 50% 深度之间的事实最常被漏掉。放在最开头的事实，在每种长度下都能找到。

他当时的建议今天依然适用：上下文越少，准确率越高，而且没有哪条事实一定能被找出来。他的代码库后来成了第一节里的 `niah` 工具。

Niels Rogge 为 Hugging Face 的 Transformers 库贡献了大约 50 个模型架构。他在 2026 年 3 月的一篇[文章](https://huggingface.co/blog/nielsr/contributing-to-transformers-with-codex)里，讲了自己怎样用 OpenAI 的 Codex 应用移植一个视频模型，当时用的是 GPT-5.3 Codex。

智能体读取并更新一个 `progress.md` 文件，他前后让它继续了大约十次。Codex 的压缩让他一直待在同一个对话里；换成别的工具，他就会重新开始，就像下面引用的那样。写出上下文腐化报告的 Chroma，也在自己的 YouTube 频道上用视频讲解了这项研究。

> 通常，编码智能体一用到上下文窗口的 60%，我就得重开一个对话，因为过了这个点模型就是会变笨，这个问题叫作上下文腐化。
>
> Niels Rogge, 为 Hugging Face Transformers 贡献了约 50 个模型，引文为译文, [Hugging Face](https://huggingface.co/blog/nielsr/contributing-to-transformers-with-codex) (2026-11-06 查阅)

[![Greg Kamradt（@GregKamradt）2023 年 11 月 8 日在 X 上发帖：对 GPT-4-128K 的长上下文回忆做压力测试。128K token 的上下文很棒，但表现到底怎样？我想弄清楚，于是做了一次“大海捞针”分析。](https://mindket.com/blog/shots/x-gregkamradt-needle-in-a-haystack.webp?v=2b13df15fc53)](https://x.com/GregKamradt/status/1722386725635580292)

Greg Kamradt 在 X 上，2023 年 11 月 8 日

[Context Rot: How Increasing Input Tokens Impacts LLM Performance](https://www.youtube.com/watch?v=TUjQuC4ugak)

Chroma 的 YouTube 频道上的视频。

> X 官方嵌入卡片的截图，拍摄于 2026-11-06，时间为 UTC。X 用“显示更多”截断了原帖。点击截图可到 X 上打开原帖。

## 常见错误

- 把模型宣传的窗口大小，当成它能好好工作的长度。
- 用和问题有相同词语的针做测试，再指望换一种说法的事实也能拿到同样的分数。
- 把答案所依赖的那条事实，埋在一大段粘贴内容的中间。
- 一个智能体会话一直开着，跨越好几个不相干的任务。
- 一次把历史删得干干净净，智能体连自己做到哪一步都忘了。

## 自己试一试

- 运行 `niah demo --fake`，再运行 `niah reconstruct results.jsonl --row 0`，在还原出来的上下文里找到那根针。
- 复制运行配置，把 `model` 指向你用的模型，把 `context_lengths` 设成你的应用会发送的长度。
- 同样的长度，先用 `single` 跑一次，再用 `multi` 跑一次，比较两次的分数。
- 记下你的智能体答案开始下滑时的输入长度，并计划在那之前从笔记重新开始。

## 自测一下

1. 在 Lost in the Middle 研究里，20 篇文档中，GPT-3.5-Turbo 在哪种情况下表现最差？

   A. 答案在第一篇文档里
   B. 答案在中间附近
   C. 答案在最后一篇文档里

   答案：B。 答案在第 10 篇时，正确率跌到 53.8%，比完全不给文档时的 56.1% 还低。

2. 为什么一个模型在经典的大海捞针测试上拿高分，却仍会漏掉你文档里的事实？

   A. 针常常和问题有相同的词，靠字面匹配就能找到
   B. 大海捞针测试只用很短的上下文
   C. 大海捞针测试不带系统提示词
   D. 你的文档总是超过 1M token

   答案：A。 NoLiMa 去掉了这种字面重合，13 个模型里有 11 个在 32K 时跌到不足短上下文成绩的一半。

3. 哪条 niah 命令不需要 API 密钥就能跑完整的演示扫描？

   A. niah run my-run.yaml
   B. niah validate my-run.yaml
   C. niah demo --fake
   D. niah reconstruct results.jsonl --row 0

   答案：C。 README 的快速上手部分，用 niah demo --fake 对进程内的假模型运行扫描。

4. 一个智能体在同一个会话里做完了三个任务，答案开始变差。下一步更好的做法是什么？

   A. 把完整历史粘贴给窗口更大的模型
   B. 调高 max_tokens
   C. 在每条消息里重复指令
   D. 把进度存进笔记文件，再开一个读取它的新会话

   答案：D。 新会话丢掉了过时的 token，笔记文件把下一步需要的内容带过去。

## 常见问题

### 大模型的上下文腐化是什么？

就是输入变长时准确率的下滑，即使所有内容都装得进窗口也会发生。因为下滑是渐进的，没有哪个 token 数能标出它从哪里开始，所以要在你自己的模型、你自己的长度上量一量。

### 1M token 的上下文窗口能解决上下文腐化吗？

不能，不过新模型撑得更久。Anthropic 在 2026 年 2 月[报告](https://www.anthropic.com/news/claude-opus-4-6)，Claude Opus 4.6 在 MRCR v2 测试的 8 根针、1M token 版本上得分 76%，而 Sonnet 4.5 只有 18.5%。两个分数都不是满分。

### 长提示词里，指令该放在哪里？

OpenAI 的 GPT-4.1 指南建议在所给上下文的开头和结尾各放一次；如果只放一次，放在上下文上方比放在下方效果好。Anthropic 2023 年的[长上下文提示词文章](https://www.anthropic.com/news/prompting-long-context)则强调把指令放在末尾，所以两种顺序都用你自己的扫描测一测。

### 上下文腐化和幻觉是一回事吗？

不是，不过一个可能引出另一个。幻觉是自信地给出错误答案。上下文腐化则是正确的事实就在提示词里，模型却漏掉或用错了它。[AI 幻觉](https://mindket.com/cn/learn/ai-basics/ai-hallucinations)那一课讲的是前者。

## 资料来源

- [Hugging Face Papers: Lost in the Middle: How Language Models Use Long Contexts](https://huggingface.co/papers/2307.03172) (2026-11-06 查阅)
- [Hugging Face Papers: NoLiMa: Long-Context Evaluation Beyond Literal Matching](https://huggingface.co/papers/2502.05167) (2026-11-06 查阅)
- [Hugging Face Papers: RULER, What's the Real Context Size of Your Long-Context Language Models?](https://huggingface.co/papers/2404.06654) (2026-11-06 查阅)
- [Hugging Face Papers: Diagnosing and Mitigating Context Rot in Long-horizon Search](https://huggingface.co/papers/2606.29718) (2026-11-06 查阅)
- [GitHub: chroma-core/context-rot](https://github.com/chroma-core/context-rot) (2026-11-06 查阅)
- [GitHub: Needle In A Haystack (niah) README](https://github.com/gkamradt/needle-in-a-haystack) (2026-11-06 查阅)
- [PyPI: needlehaystack](https://pypi.org/project/needlehaystack/) (2026-11-06 查阅)
- [Anthropic Engineering: Effective context engineering for AI agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents) (2026-11-06 查阅)
- [Anthropic Engineering: Writing effective tools for agents](https://www.anthropic.com/engineering/writing-tools-for-agents) (2026-11-06 查阅)
- [Anthropic Engineering: Introducing advanced tool use on the Claude Developer Platform](https://www.anthropic.com/engineering/advanced-tool-use) (2026-11-06 查阅)
- [Anthropic: Introducing Claude Opus 4.6](https://www.anthropic.com/news/claude-opus-4-6) (2026-11-06 查阅)
- [Anthropic: Prompt engineering for Claude's long context window](https://www.anthropic.com/news/prompting-long-context) (2026-11-06 查阅)
- [OpenAI Cookbook: GPT-4.1 prompting guide](https://developers.openai.com/cookbook/examples/gpt4-1_prompting_guide) (2026-11-06 查阅)
- [X: Greg Kamradt, pressure testing GPT-4-128K with long context recall](https://x.com/GregKamradt/status/1722386725635580292) (2026-11-06 查阅)
- [Hugging Face blog: Niels Rogge, How I contributed a new model to the Transformers library using Codex](https://huggingface.co/blog/nielsr/contributing-to-transformers-with-codex) (2026-11-06 查阅)
- [YouTube (Chroma): Context Rot: How Increasing Input Tokens Impacts LLM Performance](https://www.youtube.com/watch?v=TUjQuC4ugak) (2026-11-06 查阅)

[浏览 MCP 服务器](https://mindket.com/cn/mcp-servers)
