大型语言模型 (LLM) 在人工智能领域扮演着越来越重要的角色。为了更好地理解和应用 LLM,我们需要深入了解其核心概念。本文将聚焦于 Token、最大输出长度和上下文长度这三个关键概念,帮助读者扫清理解障碍,从而更有效地利用 LLM 技术。
Token:LLM 的基本处理单元
Token
是大型语言模型 (LLM) 处理自然语言文本时的基本单位,可以将其理解为模型能够识别和处理的最小语义单位。 尽管可以粗略地将 Token 类比为 “字” 或 “词”,但更准确地说,Token 是模型进行文本分析和生成的基础 building block。
在实际应用中,Token 与字数之间存在着一定的换算关系。 一般而言:
- 1 个英文字符 ≈ 0.3 个 Token
- 1 个中文字符 ≈ 0.6 个 Token
因此,我们可以近似地认为,通常情况下一个汉字可以被视为一个 Token
。
正如上图所示,当我们将文本输入 LLM 时,模型首先会将文本切分成 Token 序列,然后再对这些 Token 序列进行处理,最终生成我们期望的输出结果。 下图生动地展示了文本 Token 化的过程:
最大输出长度(输出限制):模型单次生成文本的上限
以 DeepSeek
系列模型为例,我们可以观察到不同型号的模型都设定了最大输出长度的限制。
上图中,deepseek-chat
模型对应 DeepSeek-V3
版本,而 deepseek-reasoner
模型则对应 DeepSeek-R1
版本。 无论是推理模型 R1 还是对话模型 V3,它们的最大输出长度都被设定为 8K
。
考虑到一个汉字约等于一个 Token 的近似换算关系,8K
的最大输出长度可以被理解为: 模型在单次交互中最多能够生成约 8000 个汉字。
最大输出长度的概念相对直观易懂,它限定了模型在每次响应中能够产生的最大文本量。 一旦达到这个限制,模型将无法继续生成更多的内容。
上下文长度 (Context Window):模型记忆的范围
上下文长度,在技术领域也被称为 Context Window
, 是理解 LLM 能力的关键参数。 我们继续以 DeepSeek
模型为例进行说明:
如图所示,无论是推理模型还是对话模型,DeepSeek
的 Context Window
均为 64K
。 那么,64K
的上下文长度究竟意味着什么呢?
要理解上下文长度,我们需要先明确其定义。 上下文窗口 (Context Window) 指的是大型语言模型 (LLM) 在单次推理过程中能够处理的最大 Token 数量总和。 这个总和包括两个部分:
(1) 输入部分: 用户提供的所有输入信息,例如提示词 (Prompt)、历史对话记录、以及任何附加的文档内容等。
(2) 输出部分: 模型当前正在生成和返回的回复内容。
简而言之,当我们与 LLM 进行一次交互时,从我们输入问题开始,到模型给出回复结束,这整个过程被称为 “单次推理”。 在这次推理过程中,所有输入和输出的文本内容 (以 Token 计数) 总和不能超过 Context Window
的限制,对于 DeepSeek
模型而言,这个限制就是 64K
, 约合 6 万多个汉字。
您可能想知道,那么输入内容是否有限制呢? 答案是肯定的。 正如前文所述,模型的上下文长度为 64K,而最大输出长度为 8K。 因此,在单轮对话中,输入内容的最大 Token 数量理论上为上下文长度减去最大输出长度,即 64K - 8K = 56K。 总结来说,在一次问答交互中,用户最多可以输入约 5 万 6 千字的内容,模型最多输出约 8 千字。
多轮对话的上下文处理机制
在实际应用中,我们经常会与 LLM 进行多轮对话。 那么,多轮对话又是如何处理上下文的呢? 以 DeepSeek
为例,当发起多轮对话时,服务端默认不保存用户的对话上下文。 这意味着,在每次新的对话请求中,用户需要将包括历史对话记录在内的所有内容拼接在一起,作为输入信息传递给 API。
为了更清晰地说明多轮对话的机制,以下是一个使用 DeepSeek API 进行多轮对话的 Python 代码示例:
from openai import OpenAI
client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")
# Round 1
messages = [{"role": "user", "content": "What's the highest mountain in the world?"}]
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages
)
messages.append(response.choices[0].message)
print(f"Messages Round 1: {messages}")
# Round 2
messages.append({"role": "user", "content": "What is the second?"})
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages
)
messages.append(response.choices[0].message)
print(f"Messages Round 2: {messages}")
在第一轮对话请求时,传递给 API 的 messages 参数内容如下:
[
{"role": "user", "content": "What's the highest mountain in the world?"}
]
在第二轮对话请求时,需要:
(1) 将上一轮对话中模型的输出添加到 messages 列表的末尾;
(2) 将用户的新提问也添加到 messages 列表的末尾。
因此,在第二轮对话中,传递给 API 的 messages 参数将包含以下内容:
[
{"role": "user", "content": "What's the highest mountain in the world?"},
{"role": "assistant", "content": "The highest mountain in the world is Mount Everest."},
{"role": "user", "content": "What is the second?"}
]
由此可见,多轮对话的本质是将历史对话记录 (包括用户的输入和模型的输出) 拼接在最新的用户输入之前,然后将拼接后的完整对话内容一次性提交给 LLM。
这意味着,在多轮对话的场景下,每一轮对话的 Context Window 并非始终保持 64K 不变,而是会随着对话轮数的增加而逐渐减小。 例如,如果第一轮对话的输入和输出总共使用了 32K Token,那么在第二轮对话中,可用的 Context Window 就只剩下 32K 了。 其原理与上述分析的上下文长度限制一致。
您可能还有疑问: 如果按照这种机制,每轮对话的输入和输出都很长,那么岂不是用不了几轮对话就会超出模型限制? 但实际使用中,即使进行多轮对话,模型也似乎能够正常响应。
这是一个非常好的问题, 这就引出了另一个关键概念: “上下文截断”。
上下文截断:应对超长对话的策略
当我们使用基于 LLM 的产品 (例如 DeepSeek、智谱清言 等) 时,服务提供商通常不会直接将 Context Window 的硬性限制暴露给用户,而是采用 “上下文截断” (Context Truncation) 策略,以实现对超长文本的处理。
举例来说,假设模型原生支持的 Context Window 为 64K。 如果用户在多轮对话中累积的输入和输出 Token 数量已经达到或接近 64K, 此时用户再发起新的请求 (例如,新的输入为 2K Token), 就会超出 Context Window 的限制。 在这种情况下,服务端通常会保留最近的 64K Token (包括最新的输入), 而丢弃最早的一部分对话历史**。 对于用户而言,他们最新输入的内容会被保留,而最早的输入 (甚至输出) 则会被模型 “遗忘”。**
这就是为什么在进行多轮对话时,尽管我们仍然可以得到模型的正常回复,但模型有时会出现 “失忆” 的情况。 因为 Context Window 的容量是有限的,模型无法记住所有历史对话信息,只能 “记住最近的,遗忘久远的”。
需要强调的是,“上下文截断” 是一种在工程层面实施的策略,而非模型本身固有的能力**。 用户在使用时通常不会感知到截断过程的存在,因为服务端在后台完成了这一操作。**
总结一下,关于上下文长度、最大输出长度和上下文截断,我们可以得到以下结论:
- 上下文窗口 (例如 64K) 是模型处理单次请求的硬性限制, 输入和输出的 Token 总数之和不能超过这个限制。
- 服务端通过上下文截断策略来管理多轮对话中的超长文本, 允许用户在多轮对话中突破 Context Window 的限制,但这会牺牲模型的长期记忆能力。
- 上下文窗口的限制通常是服务提供商为了控制成本或降低风险而设置的策略, 与模型本身的技术能力并非完全等同。
各模型参数对比:OpenAI & Anthropic
不同模型厂商对于最大输出长度和上下文长度的参数设置有所不同。 下图以 OpenAI 和 Anthropic 为例,展示了部分模型的参数配置:
图中 “Context Tokens” 代表上下文长度,“Output Tokens” 代表最大输出长度。
技术原理:限制背后的原因
为什么 LLM 要设置最大输出长度和上下文长度的限制呢? 从技术角度来看,这涉及到模型架构和计算资源的约束。 简而言之,上下文窗口的限制是由以下关键因素决定的:
(1) 位置编码的范围: Transformer 模型依赖位置编码 (例如 RoPE、ALiBi) 为每个 Token 赋予位置信息,位置编码的设计范围直接决定了模型能够处理的最大序列长度。
(2) 自注意力机制的计算方式: 在生成每一个新的 Token 时,模型需要计算该 Token 与所有历史 Token (包括输入和已生成的输出) 之间的注意力权重。 因此,序列的总长度受到严格限制。 此外,KV Cache 的显存占用与序列总长度呈正相关,超出上下文窗口长度可能导致显存溢出或计算错误。
典型应用场景与应对策略
理解最大输出长度和上下文长度的概念及其背后的技术原理至关重要。 掌握这些知识后,用户在使用大模型工具时应制定相应的策略,以提升使用效率和效果。 以下列举了几种典型的应用场景,并给出了相应的应对策略:
- 短输入 + 长输出
- 应用场景: 用户输入少量 Token (例如 1K), 希望模型生成长篇内容,例如文章、故事等。
- 参数配置: 在 API 调用时,可以将 max_tokens 参数设置为较大的值,例如 63,000 (需确保输入 Token 数量与 max_tokens 之和不超过 Context Window 限制,例如 1K + 63K ≤ 64K)。
- 潜在风险: 模型输出的内容可能因为质量检测 (例如重复性过高、包含敏感词等) 而被提前终止。
- 长输入 + 短输出
- 应用场景: 用户输入长篇文档 (例如 60K Token), 要求模型进行摘要、信息提取等处理,生成简短的输出结果。
- 参数配置: 可以将 max_tokens 参数设置为较小的值,例如 4,000 (例如 60K + 4K ≤ 64K)。
- 潜在风险: 如果模型实际需要的输出 Token 数量超过 max_tokens 的设定值,则需要对输入文档进行压缩处理 (例如提取关键段落、减少冗余信息等), 以确保输出结果的完整性。
- 多轮对话管理
- 规则: 在多轮对话过程中,需要注意累积的输入和输出 Token 总数不能超过 Context Window 的限制 (超出部分会被截断)。
- 示例:
(1) 第 1 轮对话: 用户输入 10K tokens,模型输出 10K tokens,累计 20K tokens。
(2) 第 2 轮对话: 用户输入 30K tokens,模型输出 14K tokens,累计 64K tokens。
(3) 第 3 轮对话: 用户新输入 5K tokens,服务端将截断最早的 5K tokens,保留最近的 59K tokens 历史记录,加上新的 5K tokens 输入,总计 64K tokens。
通过理解 Token、最大输出长度和上下文长度这三个核心概念,并根据具体的应用场景制定合理的策略,我们可以更有效地驾驭 LLM 技术,充分发挥其潜力。