大模型技术全景(二十六):上下文窗口的大小边界与上下文腐烂


📚 本文收录于「流浪」的系列专栏

🐧 Linux系统 ⚙️ C++
📊 数据结构与算法 🐍 Python
🔗 LangChain & LangGraph 🗄️ MySQL 数据库
🌿 Git 工具 🌐 计算机网络
🤖 LLM 💯 大厂面试、八股
📚 学习筑基专栏

🏠 博客主页:流浪 | 📝 原创首发于 CSDN


上一篇用三个常见问题收了 RAG 的尾,其中第一个问题落在一句话上:长上下文解决的是「一次能读更多材料」,RAG 解决的是「从海量知识里筛选相关信息」 ,两者不是一回事。这句话要站得住,得把上下文窗口 本身拆开看------它到底有多大、里面装了些什么、为什么不能无限做大、塞满了会发生什么。本篇就把这块工作区从里到外讲一遍,最后再往下追一层:为什么窗口越大,里面的信息反而越容易「烂掉」。


一、上下文窗口是什么

1.1 上下文窗口是模型一次请求能看到的全部内容

  • 如果大模型是大脑,那么上下文窗口更像是它的「工作记忆」。
  • Context Window = AI 在一次请求中能处理的最大 Token 数量,它是模型在本次工作过程中能够「看到」的全部内容。
  • 超过这个限制之后,较早的内容可能无法被当前推理看到,表现出来的就是「忘记前面」。

窗口不是模型的记忆,是它这一次干活时摊在桌面上的那块地方,桌面就这么大,放不下的只能拿走。

1.2 这块地方要同时装下输入和输出

  • 上下文窗口的范围包含输入 + 输出:提示词、历史对话记录,以及模型生成的回复,所有这些内容的 Token 总数加起来,不能超过窗口的上限。
  • 一个 8k 上下文窗口的模型,你输入了 6k Token 的文本,那么理论上最多只能生成 2k Token 的回复;不过实际生成长度还会受到模型输出上限的限制,如果输出上限设置为 1k Token,那么最多只能生成 1k。
  • 另外,模型本身是无状态的,它不会自动记住上一次对话。所谓「记住」,其实是每次请求时都把相关历史对话重新放到上下文窗口里。

输入和输出抢的是同一块配额,所以「还能生成多长」从来不是单独算的,要先扣掉已经塞进去的部分。


二、上下文窗口为什么重要

2.1 三件事都直接取决于窗口大小

  • 处理长文本的能力:窗口越大,模型一次性能处理的文本就越长。例如在超大上下文窗口下,可以一次性处理《红楼梦》的大部分内容;而在较小窗口下,可能只能处理其中一部分章节。长合同、学术论文、代码仓库等也是同理。
  • 对话的连贯性:在聊天中,模型要记住之前聊过什么,就需要把之前的对话都放在窗口内。窗口越大,能容纳的历史对话轮次就越多,聊天就越连贯,越不容易「断片」。
  • 复杂任务的执行:对于「请根据这份 50 页的报告,总结出三个要点并回答相关问题」这样的任务,需要整个报告都在窗口内,模型才能「看到」全部信息。

窗口大小直接决定了一次能交给模型多少材料,这是它和 RAG 分工的硬件基础。

2.2 主流模型的窗口大小

模型系列 上下文窗口(Tokens) 来源
DeepSeek-V3.2 128,000 DeepSeek 文档
kimi-k2-0905-preview 256K Moonshot 文档
Qwen3-Max 262,144 阿里云 Model Studio
  • 这张表给的是成稿时的数值,各家模型的窗口一直在涨,用它做量级参照可以,别当成当前最新值背。
  • 真正要注意的是另一个数:标称窗口和「能稳定用好」的窗口并不是一回事,这一点在最后一章会展开。

窗口数字是标称容量,不等于有效容量,后者往往要打不小的折扣。


三、上下文窗口里到底装了什么

3.1 输入侧:模型「看到」的七类东西

  • 系统提示词(System Prompt):系统或开发者给出的指令,通常对用户隐藏,但会占用窗口。
  • 用户提示词(User Prompt):用户输入的内容,一般是具体业务需求或问题。
  • 对话历史:过往的消息记录,包括用户和模型之前的多轮对话。
  • RAG 检索信息:从外部知识库检索到的补充资料,会作为上下文拼接到提示词中,帮助模型回答。
  • 工具调用定义(Tool / Function Schema):工具的名称、功能描述、参数结构等信息,供模型判断何时调用工具、如何传参。
  • 工具返回结果:模型调用工具后,工具返回的内容也会进入上下文窗口,供模型继续参考。
  • 格式与结构开销:特殊字符、换行符、Markdown 标记、消息角色标记、JSON 结构等。这些看起来不起眼,但也会占用 Token。

工具越多、格式化越重,系统提示词和工具定义吃掉的比例就越大,留给业务材料的空间会被静默压缩。

3.2 输出侧:模型「生成」的两类东西

  • LLM 的回答:模型最终生成的回复内容,同样占用上下文窗口。
  • 思维链输出(Chain-of-Thought / Reasoning):模型在给出最终答案前,中间逐步的推理步骤。部分模型会展示这些内容,部分模型只展示最终答案;但只要是模型生成的,就会占用窗口。

真正留给「你的材料」的空间,比你以为的少得多------工具定义、格式开销、思维链都在抢同一块地。


四、上下文窗口为什么有上限

4.1 注意力的计算量随长度平方增长

  • Transformer 模型中的「注意力」操作需要计算序列中每一个 token 与其他每一个 token 之间的关系,这使得计算复杂度与上下文长度 L 呈 O(L²) 关系。简单说,上下文翻倍,计算量会变成原来的 4 倍。当长度达到数万甚至百万时,计算量会达到天文数字。
  • 这个平方关系可以拿小例子算一遍:如果序列里有 10 个字,每个字都要看其他 10 个字(包括自己),总共产 10×10 = 100 次计算。如果序列增加到 100 个字,总互动就变成了 100×100 = 10,000 次。

窗口做不大的第一道坎是算力:不是存不下,是算不动,长度翻倍代价是四倍。

4.2 KV 缓存与推理延迟是另外两道硬约束

  • 缓存瓶颈:模型在生成每个新 token 时,都需要记住之前所有 token 的「键」和「值」向量(即 KV 缓存),缓存的位置位于显存中。这个缓存的大小与 L 成正比。一个很长的对话可能需要几十 GB 的显存来存储缓存,远超单张 GPU 的承载能力。
  • 推理延迟增加:随着上下文变长,模型生成每个新 Token 时需要关注的所有历史 Token 变多,导致输出速度逐渐变慢。

第二道坎是显存,第三道坎是延迟:KV 缓存线性增长吃显存,注意力范围变大拖慢每一个 token 的生成。


五、超出上限会怎样

5.1 信息截断:先丢掉最前面的内容

  • 大多数模型在处理超长输入时,会直接丢弃超出窗口的最前面内容,只保留最后能放入窗口的部分。
  • 例如,一篇 50 页的论文,窗口只能容纳 30 页,模型会截断最前面的 20 页,只保留最后 30 页。此时如果问「论文第 1 页的核心观点是什么?」,模型无法回答,因为它已经看不到第 1 页。

截断是有方向性的:丢的是开头,留的是结尾,所以系统提示词和最早几轮对话最危险。

5.2 中间丢失:在窗口内也可能被忽略

  • 模型往往对文档开头和结尾的信息利用较好,而对文档中间部分的信息利用较差。即使中间部分在上下文窗口内,模型也可能忽略其中的细节,导致回答中间部分相关问题时表现下降。
  • 需要说明的是,这是一种常见的性能退化,但并非「无论问得多详细都一定忽略」。

装得进去不等于用得上:开头和结尾是注意力高地,中间是洼地,关键内容放到中间风险最大。

5.3 性能与响应异常:变慢、卡顿甚至报错

  • 随着上下文变长,KV Cache 占用显存增加,推理延迟会显著上升。如果显存不足,系统可能报错,或者使用交换内存导致速度急剧下降。原本秒回的请求,可能需要等待更长时间才能开始输出。
  • 网页端如果一次性处理超长文档,可能因为传输、内存占用和界面渲染压力过大而出现卡顿甚至崩溃,但这更多是前端资源限制,而不是「Token 渲染」本身。

超限的后果分三层:先丢内容,再丢中间,最后拖慢整体,前两层伤的是正确性。


六、上下文为什么会腐烂

6.1 上下文腐烂的本质是信噪比急剧下降

  • 最初业界认为可以用巨大的上下文窗口填满所有信息,但现实击碎了这种幻想。
  • 上下文腐烂指的是:当上下文中包含大量与当前任务无关的信息时,模型需要在更大的信息空间中寻找相关的内容,注意力资源被分散,容易出现关键信息遗漏、指令遵循能力下降以及推理质量下降等问题。
  • 比如你塞给它 100 万字的对话历史,里面 99% 是废话、重复、无关信息,模型看花了眼,注意力被稀释,该记住的关键信息(比如「用户要求用摄氏度而不是华氏度」)反而被淹没了。

腐烂不是信息过期,而是噪声把信号淹了,塞得越多越难找到真正要用的那一条。

6.2 三个学术现象:中间遗忘、注意力稀释、上下文干扰

  • Lost in the Middle(中间内容遗忘):当关键信息位于上下文窗口的正中间时,模型的召回率(准确率)会跌到最低点,甚至不如把关键信息放在开头(Primacy 效应)或结尾(Recency 效应)。
  • Attention Dilution(注意力稀释):当无关的废话越多,模型就必须把原本集中在「关键信息」上的概率权重,强行分给成千上万个无意义的词语(如「的、了、嗯、而且」)。
  • Context Interference(上下文干扰):无关信息不仅仅占位置,它们包含的语义特征在模型的向量空间中与有效信息产生了负向交互。可以这样对照:你给一群人开了个跨部门辩论会,第一个发言的人说「用户喜欢简洁答案」,第二个人说「用户是行业专家,需要详尽分析」,第三个人又说「用户今天赶时间,越快越好」,它们三个在会议室里互相打架。

无关内容不只是占位,它会主动和有效信息打架,这是上下文干扰和单纯「占地方」最大的区别。

6.3 腐烂的机理:注意力被迫压缩内部表征

  • 研究者将这种现象称为「上下文腐烂」(Context Rot)。它的本质不是「信息变旧了」,而是「信噪比(Signal-to-Noise Ratio)急剧下降」。
  • 当上下文膨胀时,模型的注意力头(Attention Heads)被迫分配大量权重去处理无关的噪音。结果就是,模型为了「看完」所有内容,不得不压缩信息的内部表征(Representation Compression),这种压缩过程会直接抹去细微但关键的用户偏好(比如你喜欢的摄氏度,或者用户名的大小写规则)。

窗口变大不等于信息变多,塞进去的噪声会反过来压掉真正关键的东西,这正是长上下文取代不了 RAG 的根因。


七、本篇小结

  • 上下文窗口是一块输入和输出共用配额的工作区,里面装的不只是你的问题,还有系统提示词、工具定义、工具返回、对话历史、格式开销和思维链。
  • 它不可能无限变大:注意力的计算量按长度平方增长,KV 缓存按长度线性吃显存,推理延迟随之上升。
  • 超了之后先截断开头、再忽略中间、最后整体变慢;而即便没超,塞满噪声也会让关键信息被注意力稀释掉。

理解了窗口的边界和腐烂机理,上一篇那个结论才算真正立住:长上下文解决的是一次能看多少,RAG 解决的是从海量知识里找什么。


八、文末面试题(全真题)

  1. 什么是上下文窗口?为什么它是大模型的一个根本约束?
    答: 上下文窗口是模型在一次前向传播中能处理的最大 token 数,之所以是根本约束,是因为自注意力要计算所有 token 之间的两两交互,时间和显存复杂度都是 O(n²)。
  • 窗口更大的好处是能处理更长的文档、维持更长的对话历史、在少样本提示里放更多示例,以及在 RAG 里塞进更多检索到的上下文。
  • 代价也很直接:上下文翻倍,注意力的计算量变成四倍;即便有 Flash Attention 这类优化,成本和延迟的约束依然存在。
  • 所以它不是存储上限,而是算力和延迟共同划出的一条硬边界。
    【真题·转述自 LLM Interview Questions for Senior Engineers (2026)(Algoroq)】
  1. 上下文窗口为什么会有上限?背后的三个成本分别是什么?
    答: 三个成本分别来自注意力计算、KV 缓存显存和推理延迟。
  • 计算成本:注意力是序列长度上的 O(n²),窗口翻倍计算量四倍,百万长度在朴素实现下根本算不动。
  • 显存成本:自回归生成时要为所有已处理 token 缓存 Key 和 Value,缓存随上下文长度线性增长;一个 8192 隐藏维度、128 层、128K 上下文的模型,光 KV 缓存就能吃掉 100 GB 以上的显存。
  • 延迟成本:随着上下文变长,生成一个新 token 要关注的历史 token 变多,输出速度逐渐下降。
    【真题·转述自 LLM Interview Questions for Senior Engineers (2026)(Algoroq·Challenges of long context 一节)】
  1. 什么是 Lost in the Middle?工程上怎么缓解?
    答: 它是这样一种现象:模型对长上下文开头和结尾的信息利用较好,对中间位置的信息关注明显不足,注意力呈现 U 型曲线。
  • 成因与位置编码和注意力机制中的近因偏差有关,结果就是放在中间的关键指令或检索文档经常被忽略。
  • 缓解办法很直接:把最相关的内容排到提示词的开头或者结尾,尤其是紧贴用户问题之前,而不是夹在系统提示词和问题中间。
  • 这也解释了一个常见故障:RAG 召回了完全正确的文档,却因为它被夹在中间而没有被模型采用。
    【真题·转述自 Context Window(Lost in the Middle 词条)】
  1. 标称 128K 的上下文窗口,实际能用满吗?
    答: 用不满,有效上下文通常远小于标称值,原因有四:注意力稀释、位置编码的外推限制、中间内容丢失,以及指令遵循能力随上下文变长而下降。
  • 注意力分布并不均匀:大约前 10% 和后 10% 的 token 能拿到较高注意力,中间 80% 的注意力显著偏低。
  • 各家公布的「大海捞针」评测也显示,上下文变长时检索准确率会下降,理想条件下大概在 70% 到 90% 之间,而生产环境不是理想条件。
  • 工程上的经验值是按标称值的 30% 到 50% 设告警线,超过就考虑压缩或重启上下文。
    【真题·转述自 Context Is All You Have: How LLM Attention Actually Works(Effective Context vs Advertised Context 一节)】
  1. 输入超过上下文窗口会怎样?有哪些处理办法?
    答: 最常见的是上下文截断,即按先进先出的方式丢掉序列最前面的 token,只保留能放进去的部分。
  • 风险在于,最先被淘汰的往往是系统提示词和早期的对话轮次,这会直接导致模型的「人设漂移」和指令丢失。
  • 替代方案有两类:一是滑动窗口注意力,二是先做上下文压缩,把较早的对话摘要掉再截断,比直接丢弃更保真。
  • 压缩和截断要分开看:压缩是在保留语义的前提下提高信息密度,截断是直接扔内容。
    【真题·转述自 Context Window(Context Window Truncation 与 Contextual Compression 词条)】
  1. 工程上怎么在有限的上下文窗口里提高信息密度?
    答: 核心思路是从「把所有东西都塞进去」改成「只把这次要用的放进去」,具体有几种常用手段。
  • 只保留相关的对话历史,而不是每次都把全部历史原样发出去;对较早的消息做摘要压缩。
  • 用 RAG 按需检索相关文档,而不是整库塞入;长文档先分块,只取命中的那几块。
  • 去掉重复内容、限制工具返回的数据量、用结构化提示词让模型更容易抓住重点,把长期信息放到外部存储按需取回。
  • 判断标准很朴素:这次回答到底需要哪些信息,就只放哪些信息。
    【真题·转述自 What Is a Context Window in an LLM? Beginner's Guide(How Developers Manage Context Windows 一节)】

💬 上下文这块地方最容易被浪费在「反正能塞下」上------工具定义、格式开销、思维链都在悄悄吃配额。你项目里是怎么盯上下文占用的、踩过哪些截断或中间丢失的坑,评论区聊聊。

相关推荐
桃西西呀1 小时前
LangGraph4j之八:条件边与动态路由
人工智能·llm·ai编程
桃西西呀1 小时前
LangGraph4j之九:自定义状态类型与自定义通道
人工智能·llm·ai编程
自养Agent2 小时前
MCP Server Boundary Audit Report
linux·服务器·人工智能·windows·大模型·llm
虎鲸不是鱼2 小时前
【虎鲸进化论 09】活下去:自启、守护、探活
人工智能·自动化·大模型·llm·自进化agent
code2cat4 小时前
【随笔】LLM裁判如何打分:先写评分标准,再用人工案例校准
java·人工智能·llm·agent·评估·langsmith
用户8314550980314 小时前
如一 Agent 架构解读(二十一):SubAgent 体系——封装、闭环与可交互
人工智能·llm
清如许.4 小时前
为什么 LLM 会产生幻觉?——token 级别的解释
人工智能·大模型·llm
范中勤5 小时前
LangGraph Checkpointer 封装(下):with 的双层上下文与 MemorySaver 为什么不用 with
python·大模型·llm·agent·langgraph
虎鲸不是鱼7 小时前
【虎鲸进化论 07】给 AI 装上手和脚:MCP 协议与“给 Agent 用的工具“设计
人工智能·自动化·大模型·llm·自进化agent