上下文窗口
问题
LLM 的上下文窗口是什么?长上下文是如何实现的?上下文越长越好吗?
答案
上下文窗口(Context Window) 是 LLM 一次能"看到"和处理的最大 Token 数量——包括输入和输出。
一、上下文窗口演进
| 模型 | 上下文窗口 | 年份 |
|---|---|---|
| GPT-2 | 1024 | 2019 |
| GPT-3 | 2048 → 4096 | 2020 |
| GPT-3.5 | 4096 → 16K | 2023 |
| GPT-4 | 8K → 128K | 2023 |
| Claude 3 | 200K | 2024 |
| Gemini 1.5 Pro | 1M → 2M | 2024 |
| GPT-4.1 | 1M | 2025 |
二、长上下文的技术基础
位置编码外推
上下文窗口受限于位置编码——模型在训练位置之外的编码可能无效。
| 方法 | 原理 | 效果 |
|---|---|---|
| ABF | 增大 RoPE base 频率 | LLaMA 3(128K) |
| YaRN | NTK 内插 + 温度缩放 | Mistral(128K) |
| Position Interpolation | 线性内插到更长位置 | LLaMA Long |
| 可学习偏置 | ALiBi 在注意力分数加距离偏置 | BLOOM |
长上下文训练
仅扩展位置编码不够——还需要在长序列上继续训练:
- 逐步外推:先 8K → 32K → 128K → 1M
- 长文本数据:需要收集足够的长文档训练数据
- 高效注意力:Flash Attention、Ring Attention 降低显存
三、长上下文 vs RAG
| 对比 | 长上下文 | RAG |
|---|---|---|
| 信息量 | 受限于窗口大小(1M Token ≈ 750K 字) | 理论上无限 |
| 准确率 | 简单直接 | 取决于检索质量 |
| 成本 | 输入越长越贵 | 只检索相关片段,Token 少 |
| 延迟 | Prefill 长,TTFT 高 | 检索耗时 + 短 Prefill |
| 实时性 | 只看窗口内容 | 可检索实时数据 |
| 适用场景 | 长文档分析、代码仓库 | 海量文档、知识库 |
实际选择
- 文档 < 200 页:直接放入长上下文
- 文档 > 200 页或持续更新:用 RAG 检索
- 最佳方案:RAG + 长上下文结合——检索出相关片段后放入大窗口
四、Lost in the Middle
2023 年研究发现:即使模型的上下文窗口很大,对中间位置信息的利用能力明显弱于开头和结尾。
上下文位置: [开头 ★★★] [中间 ★☆☆] [结尾 ★★★]
信息检索能力: 高 低 高
这意味着:
- 重要信息应放在开头或结尾
- 长上下文不意味着所有信息都被充分利用
- NIAH(Needle in a Haystack)测试经常用来评估这个能力
五、上下文窗口的成本
长上下文的 Prefill 阶段是 复杂度(Flash Attention 优化后 IO 是 ,但计算仍是 ):
| 输入长度 | Prefill 延迟 | KV Cache | API 成本(GPT-4o) |
|---|---|---|---|
| 1K | ~50ms | 微小 | $0.0025 |
| 10K | ~200ms | ~1GB | $0.025 |
| 100K | ~5s | ~10GB | $0.25 |
| 1M | ~60s+ | ~100GB | $2.50 |
常见面试问题
Q1: 上下文窗口和模型"记忆"的区别?
答案:
- 上下文窗口:当前对话中模型能"看到"的 Token 范围——临时的短期记忆
- 模型参数:预训练中学到的知识——永久的长期记忆
- 模型没有跨对话的记忆——每次对话都是全新的(除非应用层实现了记忆系统)
Q2: 为什么要同时用 RAG 和长上下文?
答案:
- 长上下文放入所有文档太贵(1M Token = $2.5/次)
- RAG 检索精度可能不够(可能漏掉相关信息)
- 最佳方案:RAG 先检索 top-K 相关片段(~10K Token),放入长上下文(~100K)让模型综合分析——RAG 降低成本,长上下文保证质量
Q3: NIAH 测试是什么?
答案: Needle in a Haystack(大海捞针)测试:在超长文本("干草堆")中插入一个特定信息("针"),要求模型准确检索出来。变化针的位置和文本长度,测试模型在不同位置和长度下的检索能力。GPT-4.1 和 Gemini 2.5 Pro 在 1M Token 范围内几乎能 100% 通过。