上下文窗口满了,会怎样

用本地 Qwen3 1.7B 和云端 Claude Sonnet 5.5 实测:上下文窗口装的是什么;满了以后,本地 Ollama 默认读之前丢一次旧消息、写满了再丢一次,云端 Claude 直接报错;以及输入越长,为什么等得越久、花得越多。

模型基础上下文窗口Token延迟计费2026-10-08

文字稿约 2300 字 · 按画面章节整理

Agent 每一轮,都把全部历史再发一遍

上一期我们看到,Agent 每一轮,都要把全部历史再发一遍,输入越滚越长。可模型一次能看的内容,是有上限的。满了,会怎样?

实验:先说一个暗号,聊十轮,再问它

我们做了个实验。对话一开头,先告诉模型一个暗号:青松。接着,跟它聊了十轮杭州旅行,最后问它:暗号是什么?窗口够大的时候,它答:青松。窗口小一点,它一本正经地回答:带父母去杭州的三天行程安排。没有报错,它自己也不知道,漏看了什么。

今天,我们用本地的小模型和云端的 Claude,实测上下文窗口满了,会发生什么。

打个比方:顾问的桌子

之前打过一个比方:模型就像一位关在房间里的顾问,记性特别差,所以客户端每次都得把全部内容,从门缝递进去。可他的桌子,就这么大。递进去的每一页纸,加上他正在写的回答,都得摊在这张桌子上。桌子摆满了,再多一页,就放不下了。这张桌子,就叫上下文窗口,英文是 Context Window:一次请求里,模型能看到的全部内容,按 token 来计数。

桌上摆着什么:全部算进窗口

桌上都摆着什么?Claude 的文档列得很清楚:系统提示词,工具定义,全部的历史消息,包括工具返回的结果,还有这一次的新问题。另外,模型这次要写的回答,连同它的思考,也算在里面。所以,输入和回答,共用这一张桌子。

桌子有多大

桌子有多大?Claude Sonnet 5.5 的窗口,是一百万个 token。本地的 Qwen3 1.7B,Ollama 给它标的上限,是 40960 个。可实际用多大,要看运行它的 Ollama 怎么设。Ollama 的文档写着:显存不到 24 GiB,默认窗口只有 4096;我们这台 Mac,Ollama 认的显存是 28.1 GiB,默认给的是 32768。同一个模型,换一台电脑,窗口就可能小八倍。

十二次请求,每次输入的 token 数

回到刚才的实验。这是十二次请求,每一次输入的 token 数。第一次,只有 42 个;之后每聊一轮,都要把上一轮的回答和新问题,加进去。到第十次,涨到了 4756 个,越过了 4096 这条线;最后问暗号的那一次,是 6600 个。

窗口 4,096:读之前,Ollama 丢掉了哪些消息

在 32768 的窗口里,6600 个 token 全都放得下,它答对了。换成 4096 的窗口,同样的请求,Ollama 只读进了 4086 个。读之前,它先丢掉了最早的 13 条消息,暗号就在第一条里。系统提示词留着,最近的 10 条消息也留着。就连一问一答,都被拆开了:第 7 轮的问题丢了,回答还在。可这样一塞,留给回答的位置,只剩 10 个 token。

写满了:Ollama 又丢了一次

回答写到第 10 个 token,窗口就满了,Ollama 又悄悄丢了一次。它的运行日志里,记着这一笔:只留最开头的 4 个 token,后面的 4091 个,丢掉一半,2045 个。这一次,系统提示词也丢了。丢完,它接着往下写,又写了 42 个 token,写出来的,就是:带父母去杭州的三天行程安排。它没看到暗号,就从剩下的内容里,抓了最后一轮回答里的一个加粗标题。整个过程没有报错,done_reason 写的还是 stop。

这两次丢弃,都是默认开着的

这两次丢弃,都是默认开着的。请求里把 truncate 设成 false,旧消息就不丢了,读之前直接报错:请求有 6600 个 token,超过了窗口的 4096 个。把 shift 设成 false,写满了也不再丢,回答写到第 10 个 token,就停了,停止原因是 length。只写出了半句:你一开始告诉我的暗号是。可见,那个错的暗号,是第二次丢弃以后,才写出来的。

云端实测:Claude Sonnet 5.5

云端的 Claude,又会怎么处理?我们把这段对话复制了很多遍,凑出 1179941 个字符,一次发给 Claude Sonnet 5.5。请求被退了回来,状态码 400。错误信息说:提示词太长了,有 1160279 个 token,超过了上限一百万。它不替你删,直接拒绝,一个字也没有生成。

回答也占桌子

那回答写满了呢?输入放得下,可回答写着写着,桌子满了。本地的 Ollama,是丢掉一半,接着写;按 Claude 的文档,它不丢,回答停在半路,停止原因一栏写着:超出了模型的上下文窗口。

输入越长,首字时间越长

就算窗口没满,输入太长,也有代价。先看时间。还是本地的 Qwen3,窗口固定在 32768,输入从 1038 个 token,一路加到 32668 个,每次测首字时间:从发出请求,到第一个字出来。1038 个,0.87 秒;3962 个,3.40 秒;32668 个,60.62 秒。从 1038 到 3962,输入每翻一倍,时间也差不多翻一倍;越往后,涨得越快:从 16237 到 32668,输入翻一倍,时间变成了三倍多。在这台电脑上,这个小模型,输入涨了 31 倍多,首字时间涨了将近 70 倍。就像那位顾问:桌上的纸越多,他每读一页,要回头对照的就越多。

输入越长,越贵

再看钱。刚才那段对话,最后一次请求,输入是 6600 个 token。可十二次请求加起来,输入一共有 31524 个,是它的 4.8 倍:因为每一轮,前面的全部内容,都要再发一遍。按 token 计费,每发一遍,都要算钱。以 Claude Sonnet 5.5 为例,输入每一百万个 token,2 美元;输入接近一百万个 token,发一次,光输入就差不多 2 美元。缓存能打折:命中缓存的部分,只按 5% 算;可它不省地方,照样占着窗口。

上下文窗口,记住三句话

总结三句话。第一,窗口是一次请求里,模型能看到的全部 token,输入和回答共用。第二,满了:本地跑的 Ollama,默认会悄悄地丢掉一部分内容,读之前丢,写满了再丢;云端的 Claude,直接报错。第三,没满也有代价:输入越长,等得越久,花得越多。

聊长对话之前,记住四件事

聊长对话之前,记住四件事。本地跑模型,先查一下窗口设了多大;读进的 token 数,正好卡在窗口大小附近,就要怀疑,前面被丢掉了;给回答留出位置:输入加上最长的回答,别超过窗口;宁可报错,也别悄悄丢:在 Ollama 的请求里,可以把 truncate 和 shift,都关掉。

今天我们看了,上下文窗口满了,会怎样。下一期:同一个问题,为什么每次回答都不一样?