如果你刚开始接触大模型 API,大概率很快就会碰到一个词:上下文窗口。模型突然“忘了前面说过什么”、输出写到一半断掉、请求报错、费用莫名变高,这些问题很多时候都和它有关。

简单说,上下文窗口就是模型在一次 API 请求里最多能处理的 token 总量

再说得准确一点,它不是模型的长期记忆,而是模型在这次请求中“临时能看到多少内容”。对初级开发者来说,最重要的是记住这句话:

上下文窗口 = 输入内容 + 模型输出内容共同占用的 token 预算。

理解了这一点,后面很多 API 调用问题都会变得清楚很多。

先把结论说清楚:上下文窗口不是“记忆”,而是单次请求的 token 上限

不少人会把上下文窗口理解成“模型能记住多少东西”。这个说法方便入门,但其实不太严谨。

更准确的说法应该是:

上下文窗口决定了模型在当前这一次请求中最多能看到多少内容,并不表示模型会永久记住这些内容。

比如你和模型聊了 10 轮,它还能回答第 1 轮提到的信息,并不是因为 API 自动帮你记住了历史,而是因为你的应用把前面的对话内容又重新传给了模型。

如果历史消息没有传进去,模型通常并不知道你们之前聊过什么。

所以,在大模型 API 里,上下文窗口更像是一个“临时工作台”:

  • 工作台越大,一次能摆上的资料就越多;
  • 但东西堆得太多,也容易乱;
  • 下一次请求时,如果你不把资料重新放上去,模型就看不到之前的内容。

上下文窗口里到底放了哪些东西?

很多新手会以为,只有用户输入的问题才会占用上下文窗口。其实并不是这样。

一次大模型 API 请求中,可能进入上下文窗口的内容有很多,比如:

  • system prompt,也就是系统提示词;
  • developer message,开发者指令;
  • user message,用户这次输入的问题;
  • 前面的历史对话;
  • RAG 检索出来的知识片段;
  • 工具调用返回的结果;
  • 文件、PDF、图片解析后的文本;
  • function calling / tools 的描述信息;
  • 模型接下来要生成的回答。

可以用这个公式来理解:

[系统提示词] + [历史对话] + [当前问题] + [检索资料] + [工具结果] + [模型输出]
= 本次请求消耗的上下文窗口

也就是说,不只是 prompt 会算 token,模型生成出来的答案同样会占用这个总预算

Token、上下文窗口、最大输出长度有什么不同?

想搞懂上下文窗口,得先把几个容易混淆的概念分开。很多 API 调用问题,其实都是因为把它们当成了一回事。

概念 含义 谁决定 常见误解
Token 模型处理文本的基本单位 tokenizer / 模型 以为 token 就等于字数
上下文窗口 单次请求最多能处理的 token 总量 模型 / 平台 以为可以靠参数随便调大
输入 token 你传给模型的内容 开发者控制 只算用户问题,忘了历史和资料
输出 token 模型生成的内容 模型生成,开发者可设置上限 以为输出不占上下文
max_tokens / max_output_tokens 最大输出长度限制 开发者设置 误以为这是上下文窗口大小

这里有一个特别常见的坑:

max_tokensmax_completion_tokensmax_output_tokens 这类参数,通常控制的是“最多输出多少 token”,而不是把模型的上下文窗口变大。

如果一个模型本身只支持 32K 上下文,你不能把 max_tokens 设置成 128K,就让它变成 128K 模型。

上下文窗口通常由模型和平台决定。开发者真正能做的事情主要是:

  • 选择上下文更长或更短的模型;
  • 控制输入 token 数量;
  • 给模型输出预留足够空间;
  • 不要把无关内容一股脑塞进请求里。

为什么 128K 上下文不等于输入 128K 再输出 128K?

这是调用大模型 API 时非常容易踩的坑。

假设某个模型的上下文窗口是 128K,通常它的意思是:

输入 token + 输出 token ≤ 128K

而不是:

输入 128K + 输出 128K

举个例子就很好理解:

模型上下文窗口:128K
输入内容:120K
预留输出:8K
总计:128K

这种请求理论上已经接近上限了。

但如果你已经输入了 128K 内容,又要求模型再输出 8K,那就很可能超限。因为窗口已经被输入占满,模型没有剩余空间继续生成答案。

另外,不同平台还可能有自己的额外限制,比如:

  • 最大输入 token 限制;
  • 最大输出 token 限制;
  • 文件上传并解析后的长度限制;
  • 工具调用结果的长度限制;
  • 应用层自动截断策略。

所以实际开发时,不能只看“这个模型支持多少上下文”这个宣传数字,还要认真看对应 API 文档里的具体限制。

超过上下文窗口会怎样?API 里常见这几种情况

超过上下文窗口,并不一定只表现为“模型忘了”。在 API 场景里,常见表现大概有下面几类。

1. 请求直接失败

最明显的情况就是 API 直接返回错误,例如:

context length exceeded
maximum context length exceeded
input is too long

这说明本次请求的输入内容,再加上你预留的输出空间,已经超过模型能处理的范围了。

2. 历史消息被自动截断

有些聊天产品或者封装好的 SDK,会自动只保留最近几轮对话,把更早的内容丢掉。

用户看到的结果就是:模型突然“失忆”了。

但真正原因并不是模型的记忆消失,而是早期对话已经没有再进入上下文窗口。

3. 输出被截断

如果你给输出留的空间太少,模型可能写到一半就停了。

比如你让模型写一份详细报告,但最大输出 token 设置得很小,就可能出现这些情况:

  • 结尾突然断掉;
  • 列表还没写完;
  • JSON 没有闭合;
  • 代码只生成了前半段。

4. 回答质量变差

上下文越长,并不代表回答一定越好。把大量无关资料都塞进 prompt,反而可能让模型:

  • 忽略真正关键的信息;
  • 被噪音内容干扰;
  • 对中间位置的信息关注不够;
  • 生成一段看起来完整、但其实不太准确的回答。

对 API 开发来说,重点不是“把窗口塞满”,而是“把最相关的上下文放进去”。

5. 成本和延迟上升

输入 token 越多,通常费用越高,响应也会更慢。尤其是在 RAG、Agent、工具调用这类场景里,检索片段、工具描述、工具返回结果,都会不断增加上下文占用。

长上下文当然有价值,但它不是免费的。

多轮对话里,模型为什么会“忘记”之前说过的话?

大多数大模型 API 本身是无状态的。也就是说,每次请求都像是一次新的调用。你需要把必要的历史消息传给模型,它才知道前面发生了什么。

一个典型的多轮对话请求可能长这样:

[
  {"role": "system", "content": "你是一个客服助手"},
  {"role": "user", "content": "我想查询订单"},
  {"role": "assistant", "content": "请提供订单号"},
  {"role": "user", "content": "订单号是 123456"}
]

如果下一次请求你只传:

[
  {"role": "user", "content": "那什么时候发货?"}
]

模型就不知道“那”到底指的是哪个订单。

但如果你把所有历史都无限追加进去,随着对话越来越长,token 也会越来越多,迟早会超过上下文窗口。所以,多轮对话一定要做上下文管理。

常见做法主要有下面几种。

1. 保留最近 N 轮对话

这是最简单直接的方法。比如只保留最近 5 轮或 10 轮聊天。

它的好处是实现起来很轻,适合普通聊天机器人。缺点也很明显:早期的重要信息可能会被丢掉。

2. 给旧对话做摘要

把早期对话压缩成一段摘要,只保留真正重要的信息,比如:

  • 用户目标;
  • 已经确认过的需求;
  • 用户偏好;
  • 重要结论;
  • 还没完成的事项。

这种方式很适合客服、个人助理、Agent 这类需要长时间跟进任务的场景。

3. 使用结构化记忆

把长期信息存到数据库里,比如用户画像、项目配置、历史订单、任务状态等。每次请求时,只取和当前问题有关的信息放进上下文。

这种方式更适合生产级应用,也更容易控制成本和效果。

长文档和 RAG 场景下,怎么用好上下文窗口?

长上下文模型确实能让开发者一次放入更多资料,但这不代表应该把所有内容都塞进 prompt。

在文档问答、知识库问答、合同审查、代码分析这些场景里,更推荐配合下面这些方法:

  • 分块,也就是 chunking;
  • 向量检索;
  • rerank 重排序;
  • 摘要压缩;
  • 按章节处理;
  • map-reduce 总结;
  • 只放入和问题最相关的片段。

比如在 RAG 场景中,如果你把 top_k 设置得很大,检索出 30 个片段后全部塞进上下文,结果可能不仅更贵,准确率还会下降。更合理的做法是控制片段数量和长度,再通过 rerank 提高相关性。

场景 推荐做法
几千字文章总结 可以直接放入上下文
几十页 PDF 问答 分块 + 检索
百页合同审查 分章节处理 + 抽取关键条款
多文件代码库分析 文件索引 + 局部上下文
长期客服记录 摘要 + 结构化用户信息

处理长文档的核心,显然不是“窗口够不够大”,而是“模型当前拿到的信息是不是足够相关”。

调用大模型 API 时,怎么估算 token 预算?

一个比较实用的估算方式是:

总 token ≈ 系统提示词 + 历史消息 + 当前输入 + 外部资料 + 工具结果 + 预留输出

示例一:32K 模型,预算基本可控

模型上下文窗口:32,000 tokens

系统提示词:800
历史对话:5,000
用户问题:300
RAG 检索资料:18,000
工具返回结果:2,000
预留输出:2,000

总计:28,100 tokens

这个请求可以发,但剩余空间不算多。如果后续工具结果继续增加,就可能逼近上限。

示例二:16K 模型,请求明显超限

模型上下文窗口:16,000 tokens

系统提示词:1,000
历史对话:8,000
用户上传文档:12,000
预留输出:2,000

总计:23,000 tokens

这个请求已经超过窗口了。你需要裁剪历史、压缩文档、分段处理,或者换一个上下文窗口更大的模型。

中文 token 可以粗略按“1 个汉字约等于 1 个 token”来估算,但这只是经验值。实际情况还会受到 tokenizer、标点、英文、数字和格式影响。更准确的结果,还是要看 tokenizer 或 API 返回的 usage 信息。

上下文窗口是不是越大越好?

不一定。

长上下文的优势很明显:可以一次放入更多历史、文档、代码和工具结果。但它也有成本:

  • 输入费用通常更高;
  • 响应延迟可能增加;
  • 无关信息会干扰回答;
  • 模型不一定能完美关注所有细节;
  • 大窗口模型通常资源消耗更高;
  • RAG 塞太多片段,反而可能降低准确率。

对 API 开发来说,最重要的不是永远选择最大窗口,而是让模型看到“足够且相关”的信息。

一个很简单的判断方式是:

如果当前任务不需要同时阅读大量资料,就没必要为了大窗口牺牲成本和速度。

不同任务该选多大的上下文窗口?

具体窗口大小要以模型官方文档为准。这里给的是选择思路,不是固定标准。

任务 是否需要长上下文 建议
简单问答 通常不需要 选低成本、低延迟模型即可
改写、翻译、文案生成 通常不需要 控制 prompt 长度
多轮客服 需要中等窗口 保留近期对话,摘要旧历史
PDF 总结 可能需要 用长窗口,或分段总结
知识库问答 不一定 优先优化检索质量
代码分析 通常有帮助 文件检索 + 局部上下文
Agent 工具调用 需要预留空间 压缩工具描述和工具结果

选模型时,不要只盯着上下文窗口这个数字,还要一起考虑:

  • 最大输出长度;
  • 价格;
  • 延迟;
  • 是否支持工具调用;
  • 是否返回 token usage;
  • 是否适合你的具体任务。

新手开发者使用上下文窗口的 10 条建议

第一,先查官方文档。确认模型的上下文上限、最大输出限制,以及各个参数到底是什么意思。

第二,不要把 max_tokens 当成上下文窗口。它通常只是控制最大输出长度,并不会改变模型本身的上下文能力。

第三,永远给输出预留 token。不要把整个窗口都拿来放输入,否则很容易超限,或者导致回答不完整。

第四,请求前最好估算一下 token。至少要把系统提示词、历史消息、文档内容、工具结果和输出预算都算进去。

第五,不要无限追加历史对话。多轮聊天一定要做裁剪、摘要,或者把重要信息结构化存储。

第六,旧对话要及时总结。保留任务目标、用户偏好、关键结论这些信息,而不是原封不动保存所有聊天记录。

第七,RAG 不要塞太多无关片段。合理控制 top_k、片段长度和相关性,比盲目增加内容更重要。

第八,长文档优先分块处理。超长 PDF、合同、代码库这类内容,不建议直接整体塞进 prompt。

第九,生产环境要监控 token、费用和延迟。最好记录输入 token、输出 token、响应耗时和异常情况。

第十,要设计超限后的降级策略。比如自动摘要、减少检索结果、提示用户分段上传,或者切换到更大上下文窗口的模型。

常见问题 FAQ

Q1:上下文窗口和 max_tokens 是一回事吗?

不是。上下文窗口是模型单次请求能处理的总 token 上限;max_tokensmax_output_tokens 这类参数,通常限制的是最大输出长度。

Q2:大模型 API 会自动记住上一次对话吗?

通常不会。多数 API 是无状态的。应用需要自己保存历史消息,并在下一次请求时重新传给模型。

Q3:为什么用了大上下文模型,还是感觉它忘了内容?

可能原因有很多,比如应用端截断了历史、输入内容太长、关键信息在中间位置、无关内容太多、平台还有额外限制,或者根本没有把历史消息传入 API。

Q4:中文 token 怎么估算?

粗略估算时,可以按 1 个汉字约等于 1 个 token 来算。但实际结果会受到 tokenizer、标点、英文、数字和格式影响。准确数据最好看 tokenizer 或 API usage。

Q5:长上下文模型能替代 RAG 吗?

不能完全替代。长上下文适合一次性放入更多内容,RAG 更适合从大量外部知识中找出相关内容。很多生产场景里,两者会结合使用。

Q6:上下文窗口满了怎么办?

可以裁剪历史、摘要旧内容、减少检索片段、压缩工具结果、分块处理文档,或者选择上下文窗口更大的模型。

总结一下:大模型上下文窗口不是长期记忆,也不是 max_tokens 参数。它本质上是一次大模型 API 请求里的总 token 预算。 新手开发者只要搞清楚“输入和输出共享同一个窗口”,再做好 token 估算、历史管理和长文档分块,就能避开大多数和上下文有关的坑。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐