什么是上下文窗口

当你和 ChatGPT 对话时,模型能"记住"的信息量是有限的。这个限制就是上下文窗口(Context Window)。

GPT-3.5:   4,096 tokens  ≈ 3,000 字
GPT-4:     8,192 / 32,768 tokens
Claude 3:  200,000 tokens
Gemini 1.5: 1,000,000 tokens

1 个 token ≈ 0.75 个英文单词 ≈ 0.5 个中文字。所以上下文窗口决定了模型一次能处理多少文本。

为什么上下文窗口是瓶颈

长文档处理

假设你要分析一份 100 页的合同(约 50,000 字)。如果模型的上下文窗口只有 8K tokens,你就得分段喂给它:

问题:第37页的条款和第2页的定义矛盾吗?
模型:(只看到了第36-40页)我无法回答这个问题。

多轮对话遗忘

在长对话中,早期的信息会逐渐被"挤出"上下文窗口:

用户(第1轮):我叫张三,生日是3月15日
用户(第50轮):今天几号?
模型:今天是2025年1月20日
用户:那我的生日还有多久?
模型:我没有你的生日信息。

代码库理解

让模型理解整个代码库时,上下文窗口就是硬限制:

一个中等规模的代码库:~500,000 行代码
GPT-4 的上下文窗口:~32K tokens ≈ ~20,000 字
差距:25 倍

为什么它也是机遇

RAG:检索增强生成

与其把所有信息塞进上下文窗口,不如让模型按需检索:

用户问题 → 检索相关文档片段 → 塞入上下文窗口 → 生成回答

这就像人类查资料:你不需要把整个图书馆装进脑子里,只需要找到相关的几页。

稀疏注意力

传统 Transformer 的注意力机制是 O(n²) 的——序列长度翻倍,计算量翻四倍。

稀疏注意力只计算部分位置对之间的注意力:

局部窗口:每个位置只关注附近的 k 个位置
全局标记:设置几个"哨兵"位置,所有位置都关注它们
混合模式:局部 + 全局

Flash Attention 等优化把实际可用的上下文窗口从理论值推进了一大步。

长上下文训练

位置编码的外推是另一个关键。模型在 4K 长度上训练,但推理时可能需要处理 32K 的输入。

RoPE(旋转位置编码):
- 训练时用 base frequency = 10,000
- 推理时调整 frequency scaling,可以外推到 128K+

分块处理

对于超长文本,可以用分块策略:

def process_long_document(document, chunk_size=4000):
    chunks = split_document(document, chunk_size)
    summaries = []

    for chunk in chunks:
        summary = model.summarize(chunk)
        summaries.append(summary)

    # 最后用摘要生成最终回答
    final = model.process(summaries)
    return final

这就是所谓的 Map-Reduce 模式:先分块处理(Map),再合并结果(Reduce)。

上下文窗口的经济学

更长的上下文窗口意味着更高的计算成本:

输入 token 价格(GPT-4o):
- 前 128K tokens: $2.50 / 1M tokens
- 超过 128K tokens: $10.00 / 1M tokens

处理一个 100K token 的文档,成本是处理 10K token 文档的 10 倍。

所以,上下文窗口的管理本质上是一个成本优化问题

实际应用中的策略

1. 信息压缩

def compress_context(messages, max_tokens=4000):
    """保留最近的对话,压缩早期的对话"""
    recent = messages[-5:]  # 最近5轮保留完整
    older = messages[:-5]

    compressed = summarize_conversation(older)
    return [SystemMessage(compressed)] + recent

2. 选择性注入

不是所有信息都值得放进上下文窗口:

用户问:这个函数的时间复杂度是多少?

不需要:整个代码库
需要:这个函数的代码 + 它调用的几个函数

3. 缓存策略

# 对于重复使用的系统提示,可以缓存 KV
kv_cache = model.encode(system_prompt)

# 后续调用时直接使用缓存,不需要重新计算
response = model.generate(
    user_input, 
    past_key_values=kv_cache
)

未来展望

上下文窗口还在不断增长。但更大的窗口不一定更好:

  • 注意力稀释:窗口越大,每个位置分到的注意力越少
  • 信息过载:模型可能被无关信息干扰
  • 成本上升:处理更长序列需要更多计算资源

真正的突破可能不在于更大的窗口,而在于更智能的信息管理——让模型学会什么值得记住,什么可以忘记。

就像人类大脑一样:我们不会记住每一次呼吸,但会记住初吻。