- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 引言
- 1M 上下文窗口 GA 的背景与意义
- 大规模上下文的技术挑战
- 五种实战应用模式
- 主流 LLM 上下文窗口对比
- 上下文管理策略与优化技巧
- 成本 vs 性能权衡
- 运维注意事项与反模式
- RAG vs 大规模上下文: 该在何时使用哪一个
- 实战工作流示例: 代码迁移
- 基准测试结果解读指南
- 未来展望
- 参考资料
- 结语

引言
2026 年 3 月 14 日,Anthropic 宣布 Claude Opus 4.6 与 Sonnet 4.6 模型的 1M(100 万)token 上下文窗口正式 GA(Generally Available)。这不只是一次数字上的扩容。从此前 128K~200K token 的上限跃升到 1M,是一次足以转变 LLM 应用范式本身的里程碑事件。
1M token 大致相当于75 万个单词、约 7~8 本英文书、约 50,000~80,000 行源代码。这意味着以前必须搭建 RAG(Retrieval-Augmented Generation,检索增强生成)流水线,或者拆分成多次 API 调用才能完成的工作,如今用单条提示词就能处理。
Google 率先在 Gemini 1.5 Pro 中引入了 1M 上下文,随后又扩展到 2M。Anthropic 此次的发布,等于正式宣告高性能模型上的大规模上下文已经从"实验性功能"转向"生产就绪(production-ready)"。本文将分析 1M 上下文窗口的技术意义,并综合梳理实战应用模式、成本优化、与 RAG 的对比,以及运维注意事项。
1M 上下文窗口 GA 的背景与意义
上下文窗口扩展的历史
| 时间 | 模型 | 上下文窗口 | 备注 |
|---|---|---|---|
| 2022 年 11 月 | GPT-3.5 | 4K token | ChatGPT 首次公开 |
| 2023 年 3 月 | GPT-4 | 8K / 32K | 32K 为受限访问 |
| 2023 年 7 月 | Claude 2 | 100K token | 首个 100K 级别 |
| 2023 年 11 月 | GPT-4 Turbo | 128K token | 输入 128K |
| 2024 年 2 月 | Gemini 1.5 Pro | 1M token | Google I/O 预览 |
| 2024 年 3 月 | Claude 3 Opus | 200K token | 注重生产环境稳定性 |
| 2024 年 6 月 | Gemini 1.5 Pro | 2M token | 实验性扩展 |
| 2025 年 6 月 | Claude 4 Opus | 200K token | 性能优先 |
| 2025 年 10 月 | GPT-5 | 256K token | 多模态整合 |
| 2026 年 3 月 | Claude Opus 4.6 / Sonnet 4.6 | 1M token | 正式 GA 发布 |
1M token 的实际容量
# 换算 1M token 实际相当于多少数据量
# 基于 Anthropic 的分词器(claude-tokenizer)
TOKEN_ESTIMATES = {
"英文单词数": "约 750,000 个单词",
"韩文字符数": "约 500,000 个字符(token 效率低于英文)",
"英文小说": "约 7~8 本(平均每本 10 万词)",
"源代码(Python)": "约 50,000~80,000 行",
"源代码(Java)": "约 40,000~60,000 行",
"A4 文档": "约 1,500~2,000 页",
"GitHub 仓库": "中小型项目的完整代码库",
"Kubernetes 清单": "约 3,000~5,000 个资源定义",
"日志文件": "约 500MB~1GB 文本日志",
}
for item, estimate in TOKEN_ESTIMATES.items():
print(f" {item}: {estimate}")
为什么此时才迎来 1M GA
根据 Anthropic 的技术报告,1M 上下文 GA 的核心前提条件有以下三项。
- Needle-in-a-Haystack 准确率 99%+:无论信息插入在 1M token 上下文的哪个位置,都能被准确检索到
- 解决 Lost in the Middle 问题:中间位置信息的利用率达到与开头/结尾同等的水平
- 延迟的可预测性:延迟随上下文大小呈线性增长(不会出现非线性暴增)
大规模上下文的技术挑战
Lost in the Middle 问题
Liu 等人(2023)的论文 "Lost in the Middle" 揭示了 LLM 在长上下文中利用信息方式的根本性局限。其核心发现如下。
- 位于上下文开头和结尾的信息能被很好地利用
- 位于中间部分的信息利用率大幅下降(呈 U 形性能曲线)
- 上下文越长,这一现象越明显
# Lost in the Middle 现象可视化(概念性代码)
import numpy as np
def simulate_retrieval_accuracy(context_length, num_positions=20):
"""
模拟上下文中信息位置对检索准确率的影响
基于论文实际实验结果构建的近似模型
"""
positions = np.linspace(0, 1, num_positions)
# U 形曲线:开头和结尾高,中间低
# 2026 年的模型这条曲线已经明显变平
accuracy_old = 0.5 + 0.4 * np.abs(2 * positions - 1) ** 1.5
accuracy_new = 0.85 + 0.12 * np.abs(2 * positions - 1) ** 2.0
return {
"positions": positions,
"accuracy_2023": accuracy_old, # GPT-4 128K 水平
"accuracy_2026": accuracy_new, # Claude Opus 4.6 1M 水平
}
result = simulate_retrieval_accuracy(1_000_000)
for i in range(0, 20, 5):
pos = result["positions"][i]
old = result["accuracy_2023"][i]
new = result["accuracy_2026"][i]
print(
f"Position {pos:.0%}: "
f"2023 model={old:.1%}, "
f"2026 model={new:.1%}"
)
注意力机制的局限与解法
Transformer 的自注意力(self-attention)相对序列长度具有 O(n^2) 的复杂度。如果在 1M token 规模下纯粹地处理,内存与计算成本会高到不现实的程度。
# 比较不同注意力机制的复杂度
def attention_complexity(seq_length, d_model=4096):
"""比较各种注意力机制的复杂度。"""
results = {}
# 1. 全量注意力(Vanilla Transformer)
# O(n^2 * d)
results["Full Attention"] = seq_length ** 2 * d_model
# 2. Sliding Window Attention(滑动窗口注意力)
# O(n * w * d),w = 窗口大小
window_size = 4096
results["Sliding Window (w=4096)"] = (
seq_length * window_size * d_model
)
# 3. Ring Attention(分布式)
# O(n^2 * d / num_devices)
num_devices = 8
results["Ring Attention (8 GPUs)"] = (
seq_length ** 2 * d_model / num_devices
)
# 4. Sparse Attention(BigBird 风格)
# O(n * sqrt(n) * d)
results["Sparse Attention"] = (
seq_length * int(seq_length ** 0.5) * d_model
)
return results
for length_name, length in [
("128K", 128_000),
("200K", 200_000),
("1M", 1_000_000),
]:
print(f"\n=== Sequence Length: {length_name} ===")
complexities = attention_complexity(length)
base = complexities["Full Attention"]
for method, value in complexities.items():
ratio = value / base * 100
print(f" {method}: {value:.2e} ({ratio:.1f}% of full)")
KV 缓存内存需求
# 计算 KV 缓存内存占用
def kv_cache_memory(
seq_length,
num_layers=80,
num_heads=64,
head_dim=128,
dtype_bytes=2, # FP16
):
"""计算 KV 缓存所需的内存。"""
# K 和 V 分别存储
# 内存 = 2 * layers * heads * head_dim * seq_len * dtype
memory_bytes = (
2 * num_layers * num_heads * head_dim
* seq_length * dtype_bytes
)
memory_gb = memory_bytes / (1024 ** 3)
return memory_gb
for name, length in [
("8K", 8_000),
("128K", 128_000),
("200K", 200_000),
("1M", 1_000_000),
]:
mem = kv_cache_memory(length)
print(f" {name} tokens: {mem:.1f} GB KV cache")
# 输出示例:
# 8K tokens: 2.4 GB KV cache
# 128K tokens: 38.1 GB KV cache
# 200K tokens: 59.6 GB KV cache
# 1M tokens: 298.0 GB KV cache
上述数字只是 KV 缓存本身的内存需求。在实际服务中,如果再算上模型权重、激活内存等,1M 上下文推理需要数百 GB 的 GPU 内存,这意味着多 GPU 分布式推理是必需的。
五种实战应用模式
模式 1: 全量代码库评审
1M 上下文最强大的用例之一,就是一次性分析整个代码库。以前只能按文件或函数逐一分析,现在则可以一次性把握整个项目的架构、依赖关系与潜在问题。
import os
import anthropic
def collect_codebase(root_dir, extensions=None, max_tokens=900_000):
"""收集代码库中的所有文件,返回为单个字符串。"""
if extensions is None:
extensions = {'.py', '.ts', '.js', '.yaml', '.yml', '.json', '.md'}
files_content = []
total_chars = 0
# token 估算:英文约 4 字符/token,代码约 3 字符/token
char_limit = max_tokens * 3
for dirpath, dirnames, filenames in os.walk(root_dir):
# 排除 node_modules、.git 等目录
dirnames[:] = [
d for d in dirnames
if d not in {'node_modules', '.git', '__pycache__', 'dist', 'build'}
]
for filename in sorted(filenames):
if any(filename.endswith(ext) for ext in extensions):
filepath = os.path.join(dirpath, filename)
relative_path = os.path.relpath(filepath, root_dir)
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
entry = f"\n### FILE: {relative_path}\n```\n{content}\n```\n"
if total_chars + len(entry) > char_limit:
break
files_content.append(entry)
total_chars += len(entry)
except (UnicodeDecodeError, PermissionError):
continue
return '\n'.join(files_content), len(files_content)
def review_codebase(root_dir):
"""将整个代码库传给 LLM,执行综合评审。"""
codebase, file_count = collect_codebase(root_dir)
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-6-20260314",
max_tokens=8192,
messages=[
{
"role": "user",
"content": f"""以下是该项目的完整代码库(共 {file_count} 个文件)。
请执行一次综合性的代码评审。
分析项目:
1. 架构模式与设计原则的遵循情况
2. 安全漏洞(认证、授权、输入校验、密钥管理)
3. 性能瓶颈点
4. 测试覆盖率与质量
5. 依赖管理与版本兼容性
6. 代码重复与重构机会
7. 错误处理的一致性
8. API 设计与接口一致性
{codebase}""",
}
],
)
return response.content[0].text
模式 2: 大规模日志与文档分析
import anthropic
def analyze_logs(log_content, query):
"""直接分析大规模日志文件。"""
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6-20260314",
max_tokens=4096,
messages=[
{
"role": "user",
"content": f"""以下是生产服务器的日志文件。
分析请求:{query}
注意事项:
- 请准确把握基于时间戳的时间顺序
- 请分析错误模式的频率与相关性
- 请推断根本原因(Root Cause)
- 请引用具体的日志行作为依据
日志:
{log_content}""",
}
],
)
return response.content[0].text
# 使用示例
# 即便是 500MB 的日志,也能在 token 上限内处理
with open("/var/log/app/production.log", "r") as f:
# 最近约 100 万行大致相当于 1M token
logs = f.read()
result = analyze_logs(
logs,
"请分析过去 24 小时内发生的 5xx 错误的根本原因,"
"并找出错误发生模式与先行事件之间的相关性。"
)
模式 3: 多文档对比摘要
import anthropic
def compare_documents(documents, comparison_criteria):
"""同时对多份文档进行比较分析。"""
client = anthropic.Anthropic()
docs_text = ""
for i, doc in enumerate(documents, 1):
docs_text += f"\n\n=== 文档 {i}: {doc['title']} ===\n{doc['content']}\n"
response = client.messages.create(
model="claude-opus-4-6-20260314",
max_tokens=8192,
messages=[
{
"role": "user",
"content": f"""请对以下 {len(documents)} 份文档进行比较分析。
比较标准:
{comparison_criteria}
请将每份文档的核心论点、共同点、差异点、矛盾点结构化整理。
引用时请注明文档编号及对应部分。
{docs_text}""",
}
],
)
return response.content[0].text
# 使用示例:比较竞争对手的技术文档
documents = [
{"title": "AWS Well-Architected Framework", "content": aws_doc},
{"title": "GCP Architecture Framework", "content": gcp_doc},
{"title": "Azure Well-Architected Framework", "content": azure_doc},
]
result = compare_documents(
documents,
"请从安全原则、成本优化、运营卓越性的角度,"
"比较这三个云平台的架构框架。"
)
模式 4: 维持长对话上下文
import anthropic
class LongConversationManager:
"""利用 1M 上下文的长期对话管理器。"""
def __init__(self, model="claude-sonnet-4-6-20260314"):
self.client = anthropic.Anthropic()
self.model = model
self.messages = []
self.system_prompt = ""
self.estimated_tokens = 0
def set_system(self, prompt):
self.system_prompt = prompt
def add_context(self, context, label="背景信息"):
"""向对话中添加大规模上下文。"""
self.messages.append({
"role": "user",
"content": f"[{label}]\n{context}",
})
self.messages.append({
"role": "assistant",
"content": f"已确认{label}。请提问。",
})
# token 估算(粗略)
self.estimated_tokens += len(context) // 3
def chat(self, user_message):
"""继续对话。"""
self.messages.append({
"role": "user",
"content": user_message,
})
response = self.client.messages.create(
model=self.model,
max_tokens=4096,
system=self.system_prompt,
messages=self.messages,
)
assistant_message = response.content[0].text
self.messages.append({
"role": "assistant",
"content": assistant_message,
})
self.estimated_tokens += len(user_message) // 3
self.estimated_tokens += len(assistant_message) // 3
return assistant_message
def get_usage_info(self):
return {
"message_count": len(self.messages),
"estimated_tokens": self.estimated_tokens,
"remaining_capacity": f"{(1_000_000 - self.estimated_tokens) / 1_000_000:.1%}",
}
# 使用示例
manager = LongConversationManager()
manager.set_system("你是一名高级架构师。请基于代码库回答问题。")
# 将整个代码库添加为上下文
with open("codebase_dump.txt", "r") as f:
manager.add_context(f.read(), "项目代码库")
# 之后可以进行多轮提问
print(manager.chat("这个项目的认证系统是如何实现的?"))
print(manager.chat("认证系统是否存在安全漏洞?"))
print(manager.chat("JWT token 刷新逻辑中是否可能出现竞态条件(race condition)?"))
print(manager.get_usage_info())
模式 5: 一次性(one-shot)原型开发
import anthropic
def one_shot_prototype(spec_document, tech_stack, output_format="complete"):
"""
仅凭一份策划文档生成完整的原型代码。
得益于 1M 上下文,可以把策划文档 + 参考代码 + 技术文档
一次性全部传入。
"""
client = anthropic.Anthropic()
prompt = f"""请基于以下策划文档生成一个完整的原型。
技术栈:{tech_stack}
要求:
1. 生产级别的错误处理
2. 类型安全(TypeScript strict mode)
3. 包含测试代码
4. API 文档(OpenAPI spec)
5. Docker 及 docker-compose 配置
6. README.md
策划文档:
{spec_document}
请输出所有文件的完整代码,并附带文件路径。
"""
response = client.messages.create(
model="claude-opus-4-6-20260314",
max_tokens=16384,
messages=[{"role": "user", "content": prompt}],
)
return response.content[0].text
主流 LLM 上下文窗口对比
以下对比 2026 年 3 月时点主流 LLM 的上下文窗口及相关性能,参考了 LMSYS Chatbot Arena 与 Artificial Analysis 的基准测试数据。
| 模型 | 上下文窗口 | 最大输出 | NIAH 准确率 | 价格(输入/1M token) | 价格(输出/1M token) | 备注 |
|---|---|---|---|---|---|---|
| Claude Opus 4.6 | 1M | 32K | 99.2% | 价格未公开 | 价格未公开 | 2026.03 GA |
| Claude Sonnet 4.6 | 1M | 16K | 98.8% | 价格未公开 | 价格未公开 | 2026.03 GA |
| GPT-5 | 256K | 16K | 97.5% | 价格未公开 | 价格未公开 | 2025.10 |
| GPT-4o | 128K | 16K | 96.1% | 价格未公开 | 价格未公开 | 2024.05 |
| Gemini 2.0 Pro | 2M | 8K | 98.5% | 价格未公开 | 价格未公开 | 2025.12 |
| Gemini 2.0 Flash | 1M | 8K | 95.3% | 价格未公开 | 价格未公开 | 2025.12 |
| Llama 4 Maverick | 1M | 8K | 93.2% | 开源 | 开源 | 2026.02 |
| Mistral Large 3 | 128K | 8K | 94.8% | 价格未公开 | 价格未公开 | 2025.11 |
| DeepSeek-V3 | 128K | 8K | 93.5% | 价格未公开 | 价格未公开 | 2025.12 |
说明:NIAH(Needle in a Haystack)准确率是在最大上下文长度下测得的数值。价格可能随时间变动,请以各提供商的官方文档为准。
上下文窗口 vs 实际利用率
上下文窗口的大小与实际利用质量是两回事。下面的代码展示了一个用于测试各模型上下文利用效率的框架。
import time
import anthropic
def benchmark_context_utilization(
model, context_sizes, needle, haystack_generator
):
"""
在不同上下文大小下,测量模型信息检索准确率的
基准测试框架。
"""
client = anthropic.Anthropic()
results = []
for size in context_sizes:
# 生成"干草堆"
haystack = haystack_generator(size)
# 把"针"插入不同位置进行测试
positions = [0.0, 0.25, 0.5, 0.75, 1.0]
position_results = []
for pos in positions:
insert_idx = int(len(haystack) * pos)
test_text = (
haystack[:insert_idx]
+ f"\n{needle}\n"
+ haystack[insert_idx:]
)
start_time = time.time()
response = client.messages.create(
model=model,
max_tokens=256,
messages=[
{
"role": "user",
"content": (
f"请在下面的文本中找出特殊信息,"
f"并准确引用出来:\n\n{test_text}"
),
}
],
)
elapsed = time.time() - start_time
found = needle.lower() in response.content[0].text.lower()
position_results.append({
"position": pos,
"found": found,
"latency_s": elapsed,
})
results.append({
"context_size": size,
"accuracy": sum(
r["found"] for r in position_results
) / len(position_results),
"avg_latency": sum(
r["latency_s"] for r in position_results
) / len(position_results),
"details": position_results,
})
return results
上下文管理策略与优化技巧
策略 1: 结构化上下文打包
不是把数据一股脑塞进去,而应当结构化地组织上下文,让 LLM 能有效地检索信息。
def structured_context_packing(files, metadata=None):
"""
以结构化形式将文件打包进上下文。
包含目录,使 LLM 能有效地检索信息。
"""
# 1. 生成目录(Table of Contents)
toc = "## TABLE OF CONTENTS\n\n"
for i, file in enumerate(files, 1):
toc += f"{i}. [{file['path']}] - {file.get('description', 'N/A')}\n"
toc += "\n---\n"
# 2. 元数据部分
meta = ""
if metadata:
meta = "## PROJECT METADATA\n\n"
for key, value in metadata.items():
meta += f"- {key}: {value}\n"
meta += "\n---\n"
# 3. 文件内容(含边界分隔符)
content = ""
for i, file in enumerate(files, 1):
content += f"\n{'='*60}\n"
content += f"## FILE {i}: {file['path']}\n"
content += f"Language: {file.get('language', 'unknown')}\n"
content += f"Lines: {file['content'].count(chr(10)) + 1}\n"
content += f"{'='*60}\n\n"
content += file['content']
content += "\n"
return toc + meta + content
策略 2: 渐进式上下文加载
class ProgressiveContextLoader:
"""
只按需渐进式加载上下文的策略。
初期只提供摘要/目录,需要时再补充详细内容。
"""
def __init__(self, client, model, max_context=900_000):
self.client = client
self.model = model
self.max_context = max_context
self.loaded_files = {}
self.summaries = {}
def create_summary(self, file_path, content):
"""生成文件的摘要。"""
response = self.client.messages.create(
model=self.model,
max_tokens=512,
messages=[
{
"role": "user",
"content": (
f"请将以下文件摘要为 3~5 行。"
f"请包含主要的函数/类名。\n\n"
f"文件:{file_path}\n{content}"
),
}
],
)
return response.content[0].text
def load_initial(self, files):
"""
第 1 阶段:只加载所有文件的摘要。
既能把握整体结构,又能节省 token。
"""
context = "## PROJECT OVERVIEW (Summaries)\n\n"
for file_path, content in files.items():
summary = self.create_summary(file_path, content)
self.summaries[file_path] = summary
self.loaded_files[file_path] = content
context += f"### {file_path}\n{summary}\n\n"
return context
def expand_file(self, current_context, file_path):
"""
第 2 阶段:将特定文件的完整内容添加到上下文中。
"""
if file_path in self.loaded_files:
full_content = self.loaded_files[file_path]
return (
current_context
+ f"\n\n## FULL CONTENT: {file_path}\n"
+ f"```\n{full_content}\n```\n"
)
return current_context
策略 3: 上下文压缩
def compress_context(content, target_ratio=0.5):
"""
压缩上下文,以便容纳更多信息。
代码类内容去除注释/空白,文档类内容则使用摘要。
"""
import re
compressed = content
# 1. 去除连续空行
compressed = re.sub(r'\n\s*\n\s*\n', '\n\n', compressed)
# 2. 去除单行注释(代码文件)
# 注意:docstring 或重要注释需要保留
compressed = re.sub(
r'^\s*//\s*(?!TODO|FIXME|HACK|NOTE|WARNING).*$',
'',
compressed,
flags=re.MULTILINE,
)
# 3. 去除块注释
compressed = re.sub(
r'/\*(?!\*)\s*(?!TODO|FIXME)[\s\S]*?\*/',
'',
compressed,
)
# 4. 归并 import 语句
lines = compressed.split('\n')
imports = [l for l in lines if l.strip().startswith(('import ', 'from '))]
non_imports = [
l for l in lines
if not l.strip().startswith(('import ', 'from '))
]
if imports:
compressed = (
"// Imports: "
+ ", ".join(
i.strip().split()[-1] for i in imports[:20]
)
+ "\n"
+ "\n".join(non_imports)
)
return compressed
成本 vs 性能权衡
token 成本建模
def estimate_cost(
input_tokens,
output_tokens,
input_price_per_1m,
output_price_per_1m,
):
"""估算 API 调用成本。"""
input_cost = (input_tokens / 1_000_000) * input_price_per_1m
output_cost = (output_tokens / 1_000_000) * output_price_per_1m
total = input_cost + output_cost
return {
"input_cost": round(input_cost, 4),
"output_cost": round(output_cost, 4),
"total_cost": round(total, 4),
}
# 各场景的成本比较(基于假设的价格)
scenarios = [
{
"name": "代码评审(全量代码库)",
"input_tokens": 800_000,
"output_tokens": 4_000,
},
{
"name": "日志分析",
"input_tokens": 500_000,
"output_tokens": 2_000,
},
{
"name": "文档比较(3 份文档)",
"input_tokens": 300_000,
"output_tokens": 8_000,
},
{
"name": "对话式编程会话(2 小时)",
"input_tokens": 200_000,
"output_tokens": 50_000,
},
]
print("=== 各场景的 token 使用量 ===")
for s in scenarios:
print(
f"\n{s['name']}:"
f"\n 输入: {s['input_tokens']:,} tokens"
f"\n 输出: {s['output_tokens']:,} tokens"
f"\n 总 token: {s['input_tokens'] + s['output_tokens']:,} tokens"
)
成本优化策略
| 策略 | 说明 | 预计节省率 | 权衡取舍 |
|---|---|---|---|
| 提示词缓存 | 复用相同上下文时命中缓存 | 50~90% | 需要管理缓存 TTL |
| 模型分层 | 简单任务用 Sonnet,复杂任务用 Opus | 40~60% | 需要路由逻辑 |
| 上下文压缩 | 剔除不必要信息后再传入 | 20~40% | 存在信息丢失风险 |
| 渐进式加载 | 按"摘要 -> 详情"顺序仅加载所需部分 | 30~50% | 需要额外的 API 调用 |
| 批处理 | 将相似请求打包处理 | 20~30% | 延迟增加 |
利用提示词缓存
import anthropic
def use_prompt_caching(large_context, queries):
"""
利用 Anthropic 的提示词缓存,大幅降低对同一上下文
反复提问所产生的成本。
"""
client = anthropic.Anthropic()
results = []
for query in queries:
response = client.messages.create(
model="claude-sonnet-4-6-20260314",
max_tokens=4096,
messages=[
{
"role": "user",
"content": [
{
"type": "text",
"text": large_context,
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": query,
},
],
}
],
)
results.append({
"query": query,
"response": response.content[0].text,
"input_tokens": response.usage.input_tokens,
"cache_read_tokens": getattr(
response.usage, 'cache_read_input_tokens', 0
),
"cache_creation_tokens": getattr(
response.usage, 'cache_creation_input_tokens', 0
),
})
return results
# 使用示例:针对同一代码库提出多个问题
queries = [
"请说明这个项目的认证系统架构。",
"数据库 schema 存在哪些潜在问题?",
"请列出 API 端点清单及各自的作用。",
"哪些模块的测试覆盖率不足?",
]
# 第一次查询:创建缓存(正常成本)
# 第二次及以后:命中缓存(输入成本节省 90%)
运维注意事项与反模式
反模式 1: 无差别上下文倾倒
问题:如果把无关文件也一股脑塞进上下文,反而会导致回答质量下降。
# 反例:无差别地把整个项目倾倒进去
# bad_context = dump_entire_project("/path/to/monorepo")
# 结果:浪费 token + 无关信息成为噪声
# 正例:只挑选与问题相关的文件
def smart_file_selection(query, file_index):
"""
只挑选与问题意图相符的文件来构建上下文。
"""
# 第 1 步:从文件索引中识别相关文件
relevant_files = []
keywords = extract_keywords(query)
for file_path, file_meta in file_index.items():
relevance_score = calculate_relevance(
keywords, file_meta
)
if relevance_score > 0.3: # 阈值
relevant_files.append(
(file_path, relevance_score)
)
# 第 2 步:按相关度排序,只选取前 N 个
relevant_files.sort(key=lambda x: x[1], reverse=True)
return [f[0] for f in relevant_files[:50]]
def extract_keywords(query):
"""从查询中提取关键词。"""
# 简单的关键词提取(实际场景可用更精细的方法)
stopwords = {"the", "a", "is", "in", "to", "of", "and"}
words = query.lower().split()
return [w for w in words if w not in stopwords]
def calculate_relevance(keywords, file_meta):
"""计算文件元数据与关键词的相关度。"""
score = 0
file_text = (
file_meta.get("path", "")
+ " "
+ file_meta.get("description", "")
).lower()
for kw in keywords:
if kw in file_text:
score += 1
return score / max(len(keywords), 1)
反模式 2: 过度迷信上下文窗口大小
问题:即使有 1M token,模型也不会对所有信息一视同仁地利用。
# 反例:把重要指示放在上下文中间
messages = [
{
"role": "user",
"content": (
huge_context_part_1 # 400K tokens
+ "\n\nIMPORTANT: "
+ critical_instruction # 这里会被埋在中间
+ "\n\n"
+ huge_context_part_2 # 400K tokens
),
}
]
# 正例:把重要指示放在开头或结尾
messages = [
{
"role": "user",
"content": (
"## INSTRUCTIONS (READ FIRST)\n"
+ critical_instruction # 放在开头
+ "\n\n## CONTEXT\n"
+ huge_context # 大量数据
+ "\n\n## REMINDER\n"
+ critical_instruction # 结尾再提醒一次
),
}
]
反模式 3: 忽视延迟
# 各上下文大小的预计延迟(取决于具体服务环境)
LATENCY_ESTIMATES = {
"8K tokens": "1~3 秒",
"32K tokens": "3~8 秒",
"128K tokens": "10~30 秒",
"500K tokens": "30~90 秒",
"1M tokens": "60~180 秒",
}
# 对需要实时响应的服务来说,1M 上下文并不合适
# 利用流式传输(streaming)来降低体感延迟是必要的
def stream_long_context_response(client, messages, model):
"""通过流式传输降低长上下文的体感延迟。"""
with client.messages.stream(
model=model,
max_tokens=8192,
messages=messages,
) as stream:
first_token_time = None
for text in stream.text_stream:
if first_token_time is None:
first_token_time = time.time()
print(f"Time to first token: {first_token_time:.1f}s")
print(text, end="", flush=True)
反模式 4: 缺乏成本管理
# token 使用量监控与预算管理
class TokenBudgetManager:
"""管理日/月 token 预算。"""
def __init__(self, daily_budget_tokens=10_000_000):
self.daily_budget = daily_budget_tokens
self.used_today = 0
self.history = []
def check_budget(self, estimated_tokens):
"""请求前检查预算。"""
if self.used_today + estimated_tokens > self.daily_budget:
remaining = self.daily_budget - self.used_today
raise BudgetExceededError(
f"Daily budget exceeded. "
f"Remaining: {remaining:,} tokens, "
f"Requested: {estimated_tokens:,} tokens"
)
return True
def record_usage(self, input_tokens, output_tokens):
"""记录使用量。"""
total = input_tokens + output_tokens
self.used_today += total
self.history.append({
"timestamp": time.time(),
"input": input_tokens,
"output": output_tokens,
})
def get_report(self):
"""生成使用量报告。"""
return {
"used_today": f"{self.used_today:,}",
"budget_remaining": f"{self.daily_budget - self.used_today:,}",
"utilization": f"{self.used_today / self.daily_budget:.1%}",
"request_count": len(self.history),
}
class BudgetExceededError(Exception):
pass
RAG vs 大规模上下文: 该在何时使用哪一个
对比表
| 标准 | RAG | 大规模上下文(1M) |
|---|---|---|
| 数据规模 | 可支持数十 GB 以上 | 最多约 75 万词 |
| 检索准确率 | 取决于嵌入/重排序质量 | 取决于模型的注意力 |
| 实时数据 | 需要更新索引 | 每次请求都是最新数据 |
| 推理成本 | 检索成本 + 小规模上下文 | 大规模上下文成本 |
| 构建复杂度 | 需要向量数据库、嵌入、流水线 | 只需把数据放进提示词 |
| 维护 | 需要索引管理、监控 | 极少(只需更新数据) |
| 多跳推理 | 单次检索难以完成 | 在完整语境下自然而然 |
| 幻觉(hallucination) | 检索失败时较高 | 上下文内的信息较低 |
| 延迟 | 检索 + 推理(数秒) | 仅推理(数十秒~数分钟) |
| 扩展性 | 几乎无限 | 受限于 1M token |
决策框架
def choose_approach(requirements):
"""
根据需求,在 RAG 与大规模上下文之间
推荐合适的方案。
"""
score_rag = 0
score_long_context = 0
# 1. 数据规模
if requirements.get("data_size_gb", 0) > 1:
score_rag += 3
elif requirements.get("data_size_gb", 0) > 0.1:
score_rag += 1
else:
score_long_context += 2
# 2. 更新频率
if requirements.get("update_frequency") == "real-time":
score_long_context += 2
elif requirements.get("update_frequency") == "daily":
score_rag += 1
# 3. 是否需要多跳推理
if requirements.get("multi_hop_reasoning"):
score_long_context += 3
# 4. 延迟要求
if requirements.get("max_latency_sec", 999) < 5:
score_rag += 2
elif requirements.get("max_latency_sec", 999) < 30:
score_rag += 1
# 5. 构建时间限制
if requirements.get("setup_time_days", 999) < 1:
score_long_context += 3
# 6. 成本敏感度
if requirements.get("cost_sensitive"):
score_rag += 2 # 反复查询时 RAG 更便宜
# 7. 准确率要求水平
if requirements.get("accuracy_critical"):
score_long_context += 2 # 参考完整语境更有利
if score_long_context > score_rag:
recommendation = "LONG_CONTEXT"
elif score_rag > score_long_context:
recommendation = "RAG"
else:
recommendation = "HYBRID"
return {
"recommendation": recommendation,
"rag_score": score_rag,
"long_context_score": score_long_context,
"reasoning": f"RAG={score_rag}, LongCtx={score_long_context}",
}
# 使用示例
result = choose_approach({
"data_size_gb": 0.05,
"update_frequency": "real-time",
"multi_hop_reasoning": True,
"max_latency_sec": 60,
"setup_time_days": 0,
"cost_sensitive": False,
"accuracy_critical": True,
})
print(f"推荐: {result['recommendation']}")
print(f"依据: {result['reasoning']}")
混合方案
在实务中,结合 RAG 与大规模上下文的混合方案往往是最有效的。
class HybridRetriever:
"""RAG + 大规模上下文的混合检索系统。"""
def __init__(self, vector_store, llm_client, model):
self.vector_store = vector_store
self.client = llm_client
self.model = model
def retrieve_and_augment(self, query, max_context_tokens=500_000):
"""
第 1 阶段:用 RAG 检索相关文档。
第 2 阶段:将检索到的文档全文以大规模上下文的方式传入。
-> 结合了 RAG 的检索准确率与大规模上下文的完整语境理解
"""
# RAG 第 1 步:检索相关文档片段
chunks = self.vector_store.similarity_search(
query, k=20
)
# 收集检索到片段所属的原始文档全文
source_docs = set()
for chunk in chunks:
source_docs.add(chunk.metadata["source_document"])
# 将原始文档全文纳入上下文
full_context = ""
token_count = 0
for doc_id in source_docs:
doc = self.vector_store.get_full_document(doc_id)
estimated_tokens = len(doc.content) // 3
if token_count + estimated_tokens > max_context_tokens:
break
full_context += (
f"\n\n=== {doc.title} ===\n{doc.content}"
)
token_count += estimated_tokens
# 第 2 阶段:携带完整文档调用 LLM
response = self.client.messages.create(
model=self.model,
max_tokens=4096,
messages=[
{
"role": "user",
"content": (
f"以下是与问题相关的文档全文。\n"
f"问题:{query}\n\n"
f"文档:\n{full_context}"
),
}
],
)
return response.content[0].text
实战工作流示例: 代码迁移
下面按步骤构建一个利用 1M 上下文完成大规模代码迁移的工作流。
import anthropic
import os
class CodeMigrationAssistant:
"""利用 1M 上下文的代码迁移助手。"""
def __init__(self):
self.client = anthropic.Anthropic()
self.model = "claude-opus-4-6-20260314"
def analyze_migration_scope(self, source_dir, migration_spec):
"""
第 1 阶段:分析整个代码库,把握迁移范围。
"""
codebase = self._collect_files(source_dir)
response = self.client.messages.create(
model=self.model,
max_tokens=8192,
messages=[
{
"role": "user",
"content": f"""请分析整个代码库,制定迁移计划。
迁移规格:
{migration_spec}
分析项目:
1. 受影响的文件清单及变更范围
2. 依赖关系图中的变更顺序
3. 破坏兼容性的位置(Breaking Changes)
4. 分阶段的迁移计划
5. 预期风险因素
代码库:
{codebase}""",
}
],
)
return response.content[0].text
def generate_migration_code(self, source_dir, plan, file_batch):
"""
第 2 阶段:根据迁移计划,生成实际的转换代码。
"""
files_content = ""
for filepath in file_batch:
full_path = os.path.join(source_dir, filepath)
if os.path.exists(full_path):
with open(full_path, 'r') as f:
content = f.read()
files_content += (
f"\n### {filepath}\n```\n{content}\n```\n"
)
response = self.client.messages.create(
model=self.model,
max_tokens=16384,
messages=[
{
"role": "user",
"content": f"""请根据迁移计划转换以下文件。
迁移计划:
{plan}
待转换文件:
{files_content}
请针对每个文件提供:
1. 转换后的完整代码
2. 变更内容摘要
3. 标注需要人工审查的部分
""",
}
],
)
return response.content[0].text
def _collect_files(self, directory, max_chars=2_700_000):
"""收集目录下的文件。"""
extensions = {'.py', '.ts', '.js', '.java', '.go', '.rs'}
result = []
total_chars = 0
for root, dirs, files in os.walk(directory):
dirs[:] = [
d for d in dirs
if d not in {
'node_modules', '.git', '__pycache__',
'dist', 'build', 'vendor',
}
]
for fname in sorted(files):
if any(fname.endswith(ext) for ext in extensions):
fpath = os.path.join(root, fname)
rel_path = os.path.relpath(fpath, directory)
try:
with open(fpath, 'r', encoding='utf-8') as f:
content = f.read()
entry = f"\n### {rel_path}\n```\n{content}\n```\n"
if total_chars + len(entry) > max_chars:
return '\n'.join(result)
result.append(entry)
total_chars += len(entry)
except (UnicodeDecodeError, PermissionError):
continue
return '\n'.join(result)
基准测试结果解读指南
Needle in a Haystack (NIAH)
# 正确解读 NIAH 基准测试的方法
niah_results = {
"claude_opus_4_6": {
"8K": 99.8,
"32K": 99.7,
"128K": 99.5,
"500K": 99.3,
"1M": 99.2,
},
"gpt_5": {
"8K": 99.5,
"32K": 99.2,
"128K": 98.0,
"256K": 97.5,
},
"gemini_2_pro": {
"8K": 99.3,
"32K": 99.0,
"128K": 98.8,
"500K": 98.6,
"1M": 98.5,
"2M": 97.1,
},
}
# 解读 NIAH 分数时的注意事项:
# 1. NIAH 是"查找单一特定事实"的简单任务
# 2. 实际业务是"综合多项信息"的复杂任务
# 3. 即使 NIAH 达到 99%,实际业务准确率也可能不同
# 4. 性能会因上下文类型(代码/文档/日志)而异
for model, scores in niah_results.items():
print(f"\n{model}:")
for size, score in scores.items():
bar = '#' * int(score / 2)
print(f" {size:>6}: {score}% {bar}")
实务基准指标
除了 NIAH 之外,实务中还应测量以下指标。
| 指标 | 说明 | 测量方法 |
|---|---|---|
| MRCR (Multi-Round Coreference) | 对话内的指代消解准确率 | 在长对话中测试对之前发言实体的引用 |
| DocQA Accuracy | 基于文档的问答准确率 | 用针对实际技术文档的问题集来测量 |
| Code Understanding | 代码理解度 | 针对整个代码库的架构性问题 |
| Summarization Quality | 摘要质量 | 大规模文档摘要中核心信息的覆盖率 |
| Cross-Reference | 交叉引用能力 | 测试多份文档间的信息关联 |
| Time to First Token | 首个 token 的延迟 | 在不同上下文大小下测量 |
未来展望
上下文窗口的下一阶段
-
10M+ token:Gemini 已经达到了 2M,预计还会扩展到 10M 以上。这相当于能一次性处理整个代码仓库、数年的日志、整个 wiki 的规模。
-
无限上下文:通过记忆增强(Memory-Augmented)架构实现的近乎无限的上下文。这需要超越当前 Transformer 架构的全新方法。
-
多模态大规模上下文:不仅是文本,还包含图像、视频、音频在内的 1M+ token 多模态上下文。
-
智能体化的长期记忆:智能体在多个会话之间保留长期记忆,并在需要时以大规模上下文加载详细信息的分层记忆系统。
开发工作流的变化
[当前] 问题 -> 检索相关文件 -> 部分上下文 -> LLM -> 回答
(人工/RAG) (4K~128K)
[1M 时代] 问题 -> 加载整个代码库 -> LLM -> 回答
(自动) (1M)
[未来] 问题 -> 智能体自主收集所需信息 -> LLM -> 执行
(工具调用) (无限制)
参考资料
- Anthropic Blog - "1M Context Window Generally Available for Claude Opus 4.6 and Sonnet 4.6" (March 2026)
- Google AI Blog - "Gemini 1.5: Unlocking Multimodal Understanding Across Millions of Tokens" (2024)
- Liu et al. - "Lost in the Middle: How Language Models Use Long Contexts" (2023, arXiv:2307.03172)
- Anthropic Technical Report - "Long Context Performance in Claude Models: Architecture and Evaluation" (2026)
- LMSYS - "Chatbot Arena: An Open Platform for Evaluating LLMs" (https://chat.lmsys.org)
- Artificial Analysis - "LLM Performance Benchmarks and Comparisons" (https://artificialanalysis.ai)
- Ratner et al. - "Long-Range Arena: A Benchmark for Efficient Transformers" (2020, arXiv:2011.04006)
- Dao et al. - "FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness" (2022)
- Li et al. - "Ring Attention with Blockwise Transformers for Near-Infinite Context" (2024)
- Anthropic - "Prompt Caching: Reducing Costs for Long Context Applications" (2025)
结语
1M token 上下文窗口的 GA,是一次转变 LLM 应用范式的事件。思维方式正在从"如何找到相关信息再放进上下文"转变为"干脆把全部数据都放进去不就行了吗"。
但大规模上下文并非万能。Lost in the Middle 问题虽有改善,却并未被彻底解决,成本与延迟依然是必须考虑的重要因素。RAG 与大规模上下文并非竞争关系,而是互补关系,实务中混合方案往往最为有效。
核心在于理解工具的局限,并把它用在恰当的地方。1M 上下文在代码评审、日志分析、文档比较、迁移等工作中能带来革命性的生产力提升,但只有搭配结构化上下文打包、提示词缓存、模型分层等优化策略一起使用,才能充分释放它的潜力。