上下文窗口
窗口是一份预算,不是一只桶。系统提示、历史、资料、工具结果、输出额度都在里面抢位置,超了它会安静地丢掉东西。
第二章收在选型上;这一章换一个更根本的问题:你们自己的业务、文档、内部概念,不在它的语料里——它不知道的事,从哪来。第一站是容量上限。上下文窗口是一次请求能装下的全部内容的上限,按 Token 计量。它是一个预算,不是一只桶——盯着它的东西比多数人以为的要多,而装不下的时候,它不会告诉你丢了什么。context-window-wiki
读完你能回答:
- 一次请求里,哪些东西在抢同一块空间?
- 超限之后两种结局分别是什么,哪一种更麻烦?
- 为什么窗口变大不能解决「全塞进去」的问题?
- 截断规则该写在哪一步,为什么必须显式?
一次请求里有五个去处
很多人默认窗口里装的就是「一来一回的对话」。实际上一份请求要同时容下五样:
- 系统提示。产品的设定和规则,每一轮都要重发,位置和长度基本固定。
- 历史对话。之前所有的来回,持续增长。
- 检索到的资料。检索塞进来的片段,往往是最大的一块。
- 工具结果。Agent 场景里,每次工具返回都堆进来,这是最容易失控的增长源。
- 留给输出的额度。这一块最常被忘。
把它们分开看,你会发现前四样都属于输入,性质却完全不同:系统提示是常量,历史对话单调增长,检索资料由你这次放多少决定,工具结果取决于 Agent 跑了几步。这四样里只有一样是你每次都能主动控制的,剩下的都在自己长。
留给输出的那块,要最先扣出来
还有一条值得单独展开:输出同样要占窗口。 输入如果已经贴到上限,留给它写字的空间就所剩无几。所以排预算的顺序应该反过来——先把输出该占的份额留足,余下的才算输入可用的部分。
还有一个地方容易搞错:标称的上下文长度数的是 token,不是汉字个数。同一个数字,中文实际能放进去的往往略多,代码则通常比按字数估算的更少——要准数只能实测。所以「还剩多少空间」这件事,凭体感估是没有用的,得有实测的换算。
装不下的时候,默认动作是丢掉开头
结局分两种,落到哪一种,看平台也看你自己的实现。
一种是请求直接报错。 这反而算好结局——问题摆在明面上,你至少能处理。
另一种麻烦得多:最前面的内容被静默裁掉。 不少框架和产品为了让请求发得出去,会自动裁掉开头那一段。
麻烦在于,开头那一段常常正是最要紧的——最初写下的规矩、任务原本的描述、用户一开始交代的背景。这些一丢,模型的表现就开始走偏,而且不会有任何提示。你的感受只是「它今天好像有点笨」,却查不出缘由。
所以有一条实践纪律:先弄清你用的框架在装不下时究竟做了什么。 它是抛错退出,还是替你裁掉一部分?如果裁,从哪一端下手?这些动作留下记录没有?答案决定了一件事——将来出了问题,你有没有线索可查。
这里要强调的是:丢掉什么,通常是由你的截断规则决定的,不是由模型决定的。你不写规则,框架就替你写一条默认的,而默认规则一般不区分「重要」和「冗长」。所以规则必须显式写出来,并且能回答三件事:裁哪一头、保留多少、有没有记录。
窗口再大,也只是把这道坎往后推
现在标称上百万 token 的窗口已经很常见,于是有人觉得「全都塞进去」就把问题解决了。并没有。 原因有三。
一、塞得下不等于看得清。 内容一长,中间那一段会被明显略过——内容摆在什么位置最容易被读到。把一整本手册送进去,真正起作用的可能只有开头和收尾。lost-in-middle
二、贵。 上下文里的每一段,每一轮都要重新发一遍、重新计一次费。一份长资料来回聊十轮,输入量就翻了十倍。长窗口的账单涨得很快,放在 Agent 这种多轮循环里尤其明显。
三、慢。 输入越长,第一个字出来的等待越久。这一点用户能直接察觉。
于是「窗口够大就全塞」这个念头同时被三件事否掉:它未必读得到,读得到也要按轮付钱,还要用户先等一会儿。反过来才对:只放确实用得上的那几段——这也正是 RAG 要解决的问题。检索不只是把资料找出来,它还负责把不相关的挡在外面,只留下真正相关的那几段。
按这个顺序扣,然后记下实际用量
分的时候按顺序扣,顺序本身就有意义:
先扣输出额度,参照你允许的最长回答来估,然后多留一点余量。再扣系统提示,这是固定值,算一次就行。再扣工具结果的典型量,如果你做的是 Agent,这一块经常比资料还大。剩下的才在历史对话和检索资料之间分。
然后定几条规则:
- 检索资料给一个硬上限。按段数和总长度两个维度卡,不要只卡段数——段有长有短。
- 历史对话超过阈值就压缩。怎么压、压掉什么,压缩那一节展开。
- 工具结果要能截断。把结构化结果转成摘要再放进去,比原样堆进去省得多。
最后一条:把「实际用了多少」打点记录下来。 这份数据价值很高——哪个功能最费、用量在往哪个方向走、距离撞上上限还有多远,都从它里面看得出来。多数团队要等到线上开始报错才意识到这件事,而那时候已经晚了。
窗口只是容器,容器里怎么摆还有第二层讲究:同样的内容放在不同位置,被用上的概率不一样。那是内容摆在什么位置最容易被读到要处理的问题。而这份预算里真正在抢位置的来源,比这里列的五样更多——上下文里到底装了什么把它们逐一列了出来,每一类都该有自己的保留规则。
