开始之前
needlehaystack 包需要 Python 3.12 或更新版本,PyPI 上的版本是 2.0.0。第一个演示不需要 API 密钥。要测真实模型,就把 OPENAI_API_KEY 或 ANTHROPIC_API_KEY 写进 .env 文件。
本课程的第一课什么是上下文工程,列出了每次调用时上下文里装着什么。这一课讲的是,这堆内容越来越多时,准确率会怎样。
用大海捞针测试量出上下文腐化
先在你用的模型上把它量出来。大海捞针测试,是把一条事实(针)藏进一大段填充文字(大海)里,再让模型把它找出来。深度指这条事实在上下文中的位置,顶部是 0%,底部是 100%。
这个测试背后的开源工具叫 niah,它在一张长度和深度的网格上逐格测试,每一格写一行结果。下面的命令来自它的 README。
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- 用
pip install needlehaystack安装。 - 运行
niah demo --fake。它用进程内的假模型,跑 2 种长度乘 3 种深度的网格,写出results.jsonl,不用密钥就能检查整条流程。 - 用
niah reconstruct results.jsonl --row 0还原模型看到的内容。每行结果只存一份配方,不存全文,这条命令会把它还原成一模一样的上下文。 - 把
ANTHROPIC_API_KEY写进.env,运行niah demo --provider anthropic。工具会自己读取.env。 - 把 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 设成你的应用会发送的长度,扫描结果才能回答你自己提示词的问题。
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% 之间。
论文把这种形状叫作 U 形:两头最好,中间最差。
落到你写的提示词上,就是把答案所依赖的那条事实放在开头或结尾附近,不要埋在一大段粘贴内容的中间。
来源:Hugging Face Papers: Lost in the Middle: How Language Models Use Long Contexts (2026年11月6日 查阅)
为什么通过大海捞针测试还不够
对大多数模型来说,找出一句话已经不难了,所以新的测试把难度加了上去。2025 年的基准测试 NoLiMa,让“针”和问题之间没有一个相同的词。模型要把两者联系起来,就得知道,比如说,森佩尔歌剧院在德累斯顿。
在这篇论文的最新版本里,13 个号称支持至少 128K token 的模型中,有 11 个在 32K 长度时跌到不足短上下文成绩的一半。GPT-4o 从 99.3% 降到 69.7%(见 NoLiMa)。
NVIDIA 的 RULER 在 2024 年也发现了同样的落差。按它的最新版本,测的 17 个模型在普通大海捞针测试上几乎都接近满分,可一旦任务需要多根针、追踪或汇总,只有一半在 32K 长度时还能保持令人满意的表现。
OpenAI 的 GPT-4.1 提示词指南说,这个模型在大海捞针测试上一直到 1M token 的上限都表现很好。指南同时提醒,要找出的条目越多,或者任务需要掌握整个上下文的状态,比如图搜索,表现就可能下降。
Chroma 在 2025 年 7 月的技术报告题为 Context Rot: How Increasing Input Tokens Impacts LLM Performance。它的复现代码包含三个实验:按意思而不是按字面匹配的针、来自 LongMemEval 的长聊天记录问答,以及照抄一串重复的词。README 这样概括结论:即使任务很简单,模型表现也会随输入长度变化。
原因在于 Transformer 读取内容的方式,Anthropic 的上下文工程指南做了解释。每个 token 都会关注其他所有 token,n 个 token 就有 n² 对关系,上下文越长,固定的注意力预算就摊得越薄。
模型在训练中见到的短序列也比长序列多。指南说,结果是一道缓坡,而不是一下子掉下悬崖。
长上下文里该把什么挡在外面
在智能体里,越堆越多的主要是工具输出和旧回合。
2026 年 6 月的一项研究,看了四个开源模型做长时间网页搜索的过程,发现累积的上下文越多,模型越常直接放弃,或者给出没把握的答案。把这些上下文删光,这两种情况几乎消失,但没跑完的任务变多了(见论文)。所以要有计划地删,而不是一次删光。
压缩和记忆工具有单独的一课,智能体记忆,按需载入工具和文件则是按需载入上下文的内容。
下表只给出简要做法,清除旧结果、记笔记和按需载入,这两课会讲得更深入。
| 越堆越多的内容 | 怎么处理 | 出处 |
|---|---|---|
| 智能体已经用完的工具调用结果 | 清掉。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 发布了他对 GPT-4-128K 的测试结果。
他把一句关于旧金山的话藏进 Paul Graham 的文章里,测了 15 种深度和 15 种长度,最长到 128K token。超过 73K token 后,回忆能力开始下降,放在 7% 到 50% 深度之间的事实最常被漏掉。放在最开头的事实,在每种长度下都能找到。
他当时的建议今天依然适用:上下文越少,准确率越高,而且没有哪条事实一定能被找出来。他的代码库后来成了第一节里的 niah 工具。
Niels Rogge 为 Hugging Face 的 Transformers 库贡献了大约 50 个模型架构。他在 2026 年 3 月的一篇文章里,讲了自己怎样用 OpenAI 的 Codex 应用移植一个视频模型,当时用的是 GPT-5.3 Codex。
智能体读取并更新一个 progress.md 文件,他前后让它继续了大约十次。Codex 的压缩让他一直待在同一个对话里;换成别的工具,他就会重新开始,就像下面引用的那样。写出上下文腐化报告的 Chroma,也在自己的 YouTube 频道上用视频讲解了这项研究。
通常,编码智能体一用到上下文窗口的 60%,我就得重开一个对话,因为过了这个点模型就是会变笨,这个问题叫作上下文腐化。

X 官方嵌入卡片的截图,拍摄于 2026-11-06,时间为 UTC。X 用“显示更多”截断了原帖。点击截图可到 X 上打开原帖。
常见错误
- 把模型宣传的窗口大小,当成它能好好工作的长度。
- 用和问题有相同词语的针做测试,再指望换一种说法的事实也能拿到同样的分数。
- 把答案所依赖的那条事实,埋在一大段粘贴内容的中间。
- 一个智能体会话一直开着,跨越好几个不相干的任务。
- 一次把历史删得干干净净,智能体连自己做到哪一步都忘了。
自己试一试
- 运行
niah demo --fake,再运行niah reconstruct results.jsonl --row 0,在还原出来的上下文里找到那根针。 - 复制运行配置,把
model指向你用的模型,把context_lengths设成你的应用会发送的长度。 - 同样的长度,先用
single跑一次,再用multi跑一次,比较两次的分数。 - 记下你的智能体答案开始下滑时的输入长度,并计划在那之前从笔记重新开始。
自测一下
在 Lost in the Middle 研究里,20 篇文档中,GPT-3.5-Turbo 在哪种情况下表现最差?
查看答案
B. 答案在中间附近 答案在第 10 篇时,正确率跌到 53.8%,比完全不给文档时的 56.1% 还低。
为什么一个模型在经典的大海捞针测试上拿高分,却仍会漏掉你文档里的事实?
查看答案
A. 针常常和问题有相同的词,靠字面匹配就能找到 NoLiMa 去掉了这种字面重合,13 个模型里有 11 个在 32K 时跌到不足短上下文成绩的一半。
哪条 niah 命令不需要 API 密钥就能跑完整的演示扫描?
查看答案
C. niah demo --fake README 的快速上手部分,用 niah demo --fake 对进程内的假模型运行扫描。
一个智能体在同一个会话里做完了三个任务,答案开始变差。下一步更好的做法是什么?
查看答案
D. 把进度存进笔记文件,再开一个读取它的新会话 新会话丢掉了过时的 token,笔记文件把下一步需要的内容带过去。
常见问题
大模型的上下文腐化是什么?
就是输入变长时准确率的下滑,即使所有内容都装得进窗口也会发生。因为下滑是渐进的,没有哪个 token 数能标出它从哪里开始,所以要在你自己的模型、你自己的长度上量一量。
1M token 的上下文窗口能解决上下文腐化吗?
不能,不过新模型撑得更久。Anthropic 在 2026 年 2 月报告,Claude Opus 4.6 在 MRCR v2 测试的 8 根针、1M token 版本上得分 76%,而 Sonnet 4.5 只有 18.5%。两个分数都不是满分。
长提示词里,指令该放在哪里?
OpenAI 的 GPT-4.1 指南建议在所给上下文的开头和结尾各放一次;如果只放一次,放在上下文上方比放在下方效果好。Anthropic 2023 年的长上下文提示词文章则强调把指令放在末尾,所以两种顺序都用你自己的扫描测一测。
上下文腐化和幻觉是一回事吗?
不是,不过一个可能引出另一个。幻觉是自信地给出错误答案。上下文腐化则是正确的事实就在提示词里,模型却漏掉或用错了它。AI 幻觉那一课讲的是前者。
资料来源
- Hugging Face Papers: Lost in the Middle: How Language Models Use Long Contexts https://huggingface.co/papers/2307.03172
- Hugging Face Papers: NoLiMa: Long-Context Evaluation Beyond Literal Matching https://huggingface.co/papers/2502.05167
- Hugging Face Papers: RULER, What's the Real Context Size of Your Long-Context Language Models? https://huggingface.co/papers/2404.06654
- Hugging Face Papers: Diagnosing and Mitigating Context Rot in Long-horizon Search https://huggingface.co/papers/2606.29718
- GitHub: chroma-core/context-rot https://github.com/chroma-core/context-rot
- GitHub: Needle In A Haystack (niah) README https://github.com/gkamradt/needle-in-a-haystack
- PyPI: needlehaystack https://pypi.org/project/needlehaystack/
- Anthropic Engineering: Effective context engineering for AI agents https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
- Anthropic Engineering: Writing effective tools for agents https://www.anthropic.com/engineering/writing-tools-for-agents
- Anthropic Engineering: Introducing advanced tool use on the Claude Developer Platform https://www.anthropic.com/engineering/advanced-tool-use
- Anthropic: Introducing Claude Opus 4.6 https://www.anthropic.com/news/claude-opus-4-6
- Anthropic: Prompt engineering for Claude's long context window https://www.anthropic.com/news/prompting-long-context
- OpenAI Cookbook: GPT-4.1 prompting guide https://developers.openai.com/cookbook/examples/gpt4-1_prompting_guide
- X: Greg Kamradt, pressure testing GPT-4-128K with long context recall https://x.com/GregKamradt/status/1722386725635580292
- 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
- YouTube (Chroma): Context Rot: How Increasing Input Tokens Impacts LLM Performance https://www.youtube.com/watch?v=TUjQuC4ugak

