上下文窗口是什么,为什么大模型聊着聊着就忘了你说过的话

你打算给公司的后台系统加一个数据导出功能

打开对话框,跟模型从需求背景聊起

聊竞品是怎么做的,聊字段该怎么设计,聊导出文案要用什么口吻

两个小时过去,你们一起改出了三版方案

你觉得差不多了,发过去最后一句,按我们最开始说的风格改一下

它回了一段完全不对路的东西

口吻不是你早就定死的那个口吻,格式也不是你们反复对过的那个格式

你盯着屏幕愣了几秒,第一反应是它在装傻

它没有装傻

它只是看不见你两个小时前说过的话了

这背后站着每个用大模型的人都绕不开的一个东西,上下文窗口

这篇我们就把这件事从头到尾拆开讲清楚,主要包括四个部分

首先我们用「工作台面」这个类比,把上下文窗口是什么讲透

然后我们讲 token,看窗口的容量是怎么算出来的

接下来是失忆的真相,窗口满了之后,最早的内容去了哪里

最后我们讲工程师们的应对思路,也就是这两年很火的上下文工程

好,我们一个一个来

工作台面

那上下文窗口到底是什么呢

你可以把模型想象成一个在台面上干活的师傅

木匠也行,厨师也行,随便哪个都行

关键是,他每次干活的时候,能用的只有台面上摆着的这些东西

台面上摆了什么,他就看得见什么

台面外的东西,哪怕就堆在旁边的架子上,他也一概不知

模型的台面上摆的是什么呢

你的系统提示,你们聊过的历史对话,你刚发出去的这句新消息,还有产品临时贴进来的文档片段

每一轮回答,模型都是基于这一整摞东西生成的

这一摞东西的容量上限,就是上下文窗口

注意这里说的是每一轮

不是整个聊天加起来一共有一个窗口

而是每一次生成回答,你这一次拼出来的这一摞,不能超过窗口大小

聊天越长,这一摞就越厚

厚到超过上限的那一天,就是出事的那一天

这里有个特别容易想错的点

很多人以为模型像一个有长期记忆的人,聊天记录存在它脑子里的某个硬盘上,越聊越了解你

不是的

模型本身的参数在训练结束之后就冻住了,你跟它聊再多,也不会改动它的脑子一根毫毛

所谓连续聊天,其实是聊天软件在替你做一件笨事

我来给大家模拟一下整个过程

下一轮继续从头拼接

你发出新消息

程序把历史对话完整拼接一遍

连同新消息一起发给模型

模型在这轮台面上生成回答

回答追加进历史记录

100%

看最右边那个回环

每说一句话,背后做的都是同一件事,把你俩说过的话从头到尾拼一遍,整个塞给模型

模型不记得上一轮,它只是每次都重新读一遍台面上的全部内容

是不是很简单

但就是这么一个笨办法,撑起了你所有的连续对话

台面就是它的全部世界

这个设计还有个推论

你点开一个新对话,就是换了一张空台面

旧台面上的东西,不会自己跑到新台面上来

所以有时候你换个新窗口问模型,它对上一个窗口里聊的事一无所知,这不是 bug,是设计如此

两个窗口,两张台面,互相看不见

工程上管这个叫无状态

模型本身不保存任何一次对话

所有状态,也就是那张台面上摆的东西,全由调用它的程序负责拼装

理解了这一点,后面发生的一切就都好懂了

回到开头那个聊了两个小时的需求

你们聊的每一句话,都摞在这张台面上

只要台面够大,模型每次回答前,都能看见两小时前定下的风格要求

问题就出在,台面不是无限大的

那台面到底有多大,拿什么量呢

这就要说到 token 了

Token

为什么不直接用字数来量呢

因为模型看文字的方式跟人不一样

它不把句子看成一个个字,而是先把文字切碎成一小块一小块

切出来的每一块,就叫一个 token

中文里,一个字大约对应一到两个 token

注意,这是粗略的经验值,不同模型的切法不一样,别当精确公式背

常见的词组可能切得粗一点,生僻的词就切得碎一点

比如「机器学习」这四个字,在有的模型眼里是两三块,在有的模型眼里是四五块

模型不同,切刀不同

顺带一提,英文的切法和中文不太一样

常见的英文单词往往一个词就是一个 token,长单词会被拆成几截

所以同样一段意思,中英文占的 token 数不一样

这也是为什么中文用户对窗口大小更敏感一些,同样的内容,占的地方常常更大

我们拿一句话试试

今天天气真好,适合摸鱼

这十个字,切出来大概是十几个 token

一句很短的话就这个量级

一小时的聊天会是多大的数,你可以自己掂量一下

那为什么要这么切呢,直接按字或者按词不行吗

按字切,序列会变得特别长,模型读一句话要蹦很多步

按整词切,词表又会大到爆炸,稍微遇到个新词它就不认识

token 是这两头的折中,也是现在主流大模型的标准做法

模型生成的时候,就是一个 token 一个 token 往外蹦的

它预测的不是下一个字,是下一个 token

顺便,token 也是各家 API 计费的单位

你每发一句话,扣的不是字数钱,是 token 钱

输入算一份,输出也算一份

窗口里堆的历史越长,你这一轮要付的钱就越多,哪怕那些话你早就说过了

这也是为什么长对话越到后面越贵

窗口的大小,就是用 token 来量的

以某模型为例,我们假设一个窗口是十二万八千 token

声明一下,这是个纯示意的数字,各家模型的窗口大小经常变,从几万到上百万 token 的产品都出现过,具体数字不重要,重要的是量级感觉

我们拿这个示意数字,算一算开头那场聊天

中文认真聊天,一小时敲个五六千字很正常,这也是示意

两小时下来,加上模型自己回复的内容,轻轻松松奔着十几万 token 去了

台面上还摆着系统提示,可能还有你随手贴进去的表格和文档

很快就要顶到上限了

也就是说,当你发出那句按最开始风格改一下的时候

最早定下的风格要求,可能已经摆不进台面了

摆不进去会发生什么呢

好,token 就讲到这里,下面我们进入这篇最关键的部分,失忆的真相

截断

台面满了,最常见的处理方式特别朴素

把最早摆上去的东西撤下去,给新消息腾地方

这个过程叫截断

台面还装得下

被挤出

台面装满之后

功能细节

文案初稿

新消息

风格要求

功能细节

文案初稿

新消息

风格要求掉出台面 从此不可见

100%

看上面这张图的下半部分

新消息进来之后,最早那段风格要求被挤了出去

注意,被挤出去不是被打了个小标记,等会儿还能捞回来

是从模型的视野里彻底消失

你可以把台面想成会议室的白板

聊得越久,白板上写的东西越多,写满了要写新内容,只能擦掉最早写的

人没事,因为会议室里的人,脑子里还记着被擦掉的部分

但模型没有会议室外面的大脑

它的全部认知就是那块白板本身

白板上没有的,在它的世界里就等于没发生过

所以你让它按最开始说的风格改,它一脸懵

这个懵是真的

它不是记性差,也不是敷衍你,它压根看不见那句话

更微妙的是,它也不知道自己丢了东西

它看不见的内容,对它来说就不存在

所以它不会跟你说不好意思我忘了前面

它会一本正经地基于台面上还剩下的信息,往下接

你以为它嘴硬,其实它比谁都无辜

那你可能会想,我重开一个对话行不行

行,但那等于直接换一张新台面,从头开始

前面聊的所有上下文,包括还没被挤掉的那些,全都清零

两小时白聊

所以重开窗口解决不了失忆,只是把失忆提前到了第一秒

这里补一句实话

不同产品的处理方式不完全一样

有的硬截断,把最早的对话直接丢掉

有的会悄悄做压缩,把远处的对话缩成摘要

有的会在界面上提示你,这段对话太长,开启了新的一段

但不管哪种,最早的信息都以某种方式不在台面上了,结果是一致的

你可能还见过一个民间偏方

每隔一段时间,手动把关键要求重新贴一遍

比如聊到一小时的时候,把风格要求再发一次

这个偏方其实是对的

它相当于人为把快掉出台面的东西,重新搬回台面上

土是土了点,但原理上和工程师们做的历史压缩,是一回事

讲到这,失忆的真相就有了

不是模型健忘,是窗口有限

那你可能会想,这算什么难题,把窗口做到无限大不就完了

好问题

但这条路眼下走不通,原因藏在一个很美的机制里,注意力

注意力

模型读台面上的内容,不是从头到尾顺着扫一遍就完事

它有个动作

台面上的每个 token,都要跟其他所有 token 两两对一遍

判断谁跟谁有关系,关系有多强,然后按这个关系加权取信息

这个机制叫注意力,是现在所有主流大模型的骨架

为什么非得两两对呢,举个语言的例子

小明把书递给小红,她笑了

这个「她」指的是谁,光看这个字本身看不出来

得回头看前文的每个词,掂量谁跟「她」最相关

注意力做的就是这件事,每个词都要回头看清所有词

而且这个回头看的动作,对台面上每个位置都要做一遍

一个 token 要看所有 token,所有 token 都要看所有 token

这就是两两配对

窗口里的内容越多,配对的数量越多

直觉类比,会议室开会

会议室里每个人都要跟在座的所有人分别交换一次眼神

10 个人的会,眼神交换大约 45 对

100 个人的会,大约 4950 对

1000 个人的会,接近 50 万对

人每多十倍,眼神总量涨一百倍

这种涨法,就是平方级

1千个token 约百万次两两计算

2千个token 约四百万次

4千个token 约一千六百万次

8千个token 约六千四百万次

每翻一倍 涨四倍

100%

更扎心的是,这笔账每一轮都要重新算

还记得前面那张回环图吗

你每说一句话,程序都要把全部历史重新拼一遍发给模型

也就是说,聊天越长,每一轮的注意力计算量都在涨

不是匀速变慢,是越到后面越慢

看这张图的规律

窗口长度翻一倍,这部分计算量大约变成原来的四倍

再翻一倍,再乘四

推理时间跟着涨,费用跟着涨

这还只是账面的一头

另一头是显存

模型为了加速生成,会把已经读过的内容缓存成一种叫 KV cache 的东西

窗口越长,这份缓存越大,而显存是真金白银堆出来的

这一头我们不展开,记住结论就行

窗口越长,越贵,越慢

当然,这些年工程上有很多优化

注意力的稀疏化,长上下文的专门训练,各家也确实在把窗口一路做大

方向是真的,进步也是真的

但平方级的基本盘还在

而且实践里还有个更隐蔽的坑

窗口大了,不等于长文本里所有内容都读得一样好

研究者观察到一个现象,一长段材料摆在台面上,开头和结尾的内容模型把握得比较好,中间的部分容易被忽略

业界给这个现象起了个名字,叫 lost in the middle

所以窗口大小是个必要条件,不是充分条件

回到开头那两个小时

就算你换了个窗口号称特别大的模型,高强度聊天加上随手贴进来的文档表格,也随时可能触顶

就算没触顶,最开头那段风格要求,也可能正躺在模型最容易忽略的中间地带

指望窗口无限大来解决失忆,眼下不现实

那工程师们怎么办的呢

思路发生了一次大转向

这就是下面的重头戏,上下文工程

上下文工程

先试个最朴素的想法

既然台面会满,那把所有东西都硬塞进去,能塞多少塞多少

历史塞进去,文档塞进去,笔记塞进去

没错,窗口大的模型确实能让你这么挥霍一阵

但账单和速度马上教你做人

塞得越满,单轮越贵越慢

而且别忘了刚说的 lost in the middle,塞得越满,中间内容被忽略得越狠

看来硬塞是行不通的

我们是不是可以换个思路,不是把台面做大,而是认真经营这块有限的台面

每轮该摆什么,什么时候摆,摆多少

可以的

这套思路这两年有了个正式的名字,上下文工程,英文叫 Context Engineering

它的核心就一句话

把对的上下文,在对的时机,以对的形态,放进有限的窗口里

这个说法在 2025 年被业界反复提起

很多做应用的人甚至说,提示工程已经升级成了上下文工程

两者的区别在于

提示工程关心你怎么把一句话说好

上下文工程关心整个台面上进进出出的一切

窗口就这么大,每个位置都是真金白银,往里放什么,得像做预算一样精打细算

具体的手法,我们挑最常用的四个来讲

检索外挂

第一个手法,把大块材料搬出台面,需要的时候再拿回来

这就是 RAG 的思路,检索增强生成

文档不躺在台面上占地方,而是放在台面外的架子上

你聊到哪个话题,程序就按这个话题去架子上查,只把最相关的那几页摆上台面

这一轮用完,下一轮再按需取

类比厨房

厨师做一道菜,不会把整个冷库搬进厨房

而是这道菜要用什么,让帮厨去仓库取什么

台面永远只放当下这道菜要用的料

回到那个导出功能

你聊到字段设计,程序就去检索数据字典的相关部分

你聊到文案口吻,就去检索之前定过的文案规范

两个小时聊天里,每轮真正需要的历史和材料,其实没有那么多

其余的都待在架子上,等被点到名再上台

这样做还有个隐藏的好处

台面清爽了,模型的注意力就不用撒在一大堆无关内容上,答起来也更准

那检索器怎么知道架子上哪几页是相关的呢

一般是用向量相似度,把你的问题和每个片段都变成向量,算距离,挑最近的

这块的细节我们不展开,你只需要知道,它能在极短时间内把相关内容捞出来

历史压缩

第二个手法,把远处的对话压成摘要

完整原文放不下,那就放一份浓缩版

占的地方小了几个数量级,骨架还在

类比会议纪要

一个项目开了三个月周会,没人能逐字背出每次会上说了什么

但一份两页的纪要,能让你随时接上之前定过什么,砍掉过什么

纪要丢掉了细节,但保住了骨架

回到那两个小时

压缩之后可能就剩一段话,项目要做什么,定了哪版方案,风格上定了哪三条

你再说按我们最开始说的风格改

摘要里恰好躺着那三条

它就不懵了

压缩一般发生在后台,窗口快满的时候触发

把最远的一段对话收走,换成一段摘要

对用户来说是无感的,你只会觉得这个模型聊得久也不太忘事

其实不是它不忘,是有人在你看不见的地方替它记了笔记

补一句实话,压缩是有损的

摘要里漏掉的细节,等于永久丢失

哪些内容够格进摘要,哪些必须忍痛丢掉,这是上下文工程里真正的手艺活,也是最容易被做糊的地方

系统提示

第三个手法,也是最稳的一招

风格要求这种从头到尾都要遵守的东西,从一开始就不该放在聊天正文里随波逐流

直接写进系统提示

系统提示在每次拼装时都排在最前面,是最先放上台面的东西,也最不容易被后来的内容挤出去

回到那个场景

如果一开始就把口吻、格式、术语三条要求写进系统提示

两小时后你说按最开始说的风格改

模型低头就能看见,根本轮不到失忆登场

为什么排在前面的东西不容易被挤掉呢

因为拼装台面的时候,程序一般会优先保证系统提示在场

空间不够,先砍的是历史对话的中段

这就像白板上专门划了一块写规矩的区域,擦旧内容的时候,这块永远最后动

这也是为什么讲究的 AI 产品,会把用户画像和全局规则放在系统提示里

它相当于给台面钉了一块永远在最前面的提示牌

外部存储

第四个手法,给模型配一个台面外的笔记本

让模型在聊天过程中,主动把重要的东西用工具写出去,存成文件或者数据库

下次要用,再读回来

模型的记忆不靠台面硬扛,靠外挂

真实的产品已经在这么干了

像 Claude Code 这类编程工具,会把项目的约定写进一个说明文件,每次开工先读它

这样哪怕隔了几天重开会话,也接得上

台面换了一块又一块,笔记本一直在

这个思路再往前走一步,就是各种长期记忆功能

有的产品会在对话结束后,把值得记住的东西写进记忆库,下次自动带上

你感觉模型越来越懂你

其实是有人一直在替它记笔记

这个手法在 Agent 产品里尤其重要

Agent 一跑就是几十上百轮,中间产生的大量中间结果,全靠外部存储接着

台面只负责当下的思考,仓库负责长期的积累

好,四个手法讲完了

它们不是四选一的关系,成熟的系统是四件一起上

我们看一张整体架构图

你的新消息进来

先判断这轮需要什么

外部存储的笔记本

检索器去外部知识库查

取回相关的片段

系统提示 装着全局规则

拼装这一轮的台面

历史摘要 压缩后的远对话

大模型在有限台面上生成回答

重要结论写回外部存储

100%

看这张图的重点

中间那个「拼装这一轮的台面」是全场枢纽

四路信息汇进来,系统提示打头,历史摘要垫底,检索片段按需插入,新消息殿后

右边还有一个回环

生成完的重要结论,不留在台面上等死,写回外部存储

下一轮要用,再从左边进来

台面始终是小的,但外围的记忆体系是大的

到这里所有的机制就讲完了

我们把整个事情从头重走一遍

首先我们用工作台面建立了直觉

模型每次生成,能看见的只有这一轮拼起来摆在台面上的内容

它没有台面外的脑子

你所以为的连续聊天,是每轮把历史从头拼一遍重新发过去

然后我们讲了 token

模型处理文字的最小单位,也是计价和计量窗口的单位

中文一个字大约一到两个 token,粗略经验值,别背

接着是失忆的真相

台面有限,塞满之后最早的内容被截断挤出

模型不是健忘,是看不见,它甚至不知道自己丢了东西

再往下我们讲了为什么不做无限窗口

注意力的两两计算让计算量随长度平方级上涨,加上 KV cache 的显存压力,窗口越长越贵越慢

还有 lost in the middle,窗口长了也未必读得好

最后我们讲了上下文工程

思路从扩大台面,转向经营台面

检索外挂按需取料,历史压缩保住骨架,系统提示钉住全局规则,外部存储配上跨会话的笔记本

回到开头那个场景

你跟模型聊了两个小时的项目需求,让它按我们最开始说的风格改一下,它一脸懵

现在你知道它懵在哪了

那句话已经不在台面上了

你也知道该怎么办了

把风格要求从聊天正文里捞出来,写进系统提示

让远去的对话,进一份靠谱的摘要

它不是不重视你,它只是被台面的物理现实卡住了

而绕过这个现实的整套手艺,就叫上下文工程

到这里,上下文窗口的前世今生就算是讲清楚了。如果你想系统地学习这些内容,从大模型原理一路讲到 Agent、RAG 和模型部署,可以看看这门0基础Agent开发课,220 个课时,从零基础一路讲到生产部署。

评论区

暂无评论,快来抢沙发吧