"上下文是 LLM 的'工作记忆',管理好它,就是管理好智能的边界。"
随着大语言模型上下文窗口的不断扩展(从早期的 4K 到如今的 1M+ tokens),如何有效利用这一能力成为提示工程的关键课题。长上下文带来了新的可能性,也带来了新的挑战:成本激增、注意力稀释、信息衰减等问题亟待解决。
本章将系统性地讲解上下文窗口管理的核心技术,从长上下文的有效利用到信息优先级管理,帮助您在成本与效果之间找到最佳平衡。
15.1 长上下文模型的利用策略(200K+ token 窗口)
15.1.1 长上下文模型概览
主流模型上下文窗口对比(截至 2025 年):
| 模型 | 上下文窗口 | 特点 |
|---|---|---|
| Claude Opus 4.6 | 1M tokens | 标准定价,无需特殊 header |
| Claude Sonnet 4.6 | 1M tokens | 标准定价 |
| GPT-4.1 | 1M tokens | OpenAI 首个百万级上下文模型 |
| Gemini 2.5 Pro | 1M tokens | 支持多模态长上下文 |
| Claude Sonnet 4.5 | 200K / 1M (beta) | 超 200K 需 beta header,加价 |
| Claude Haiku 4.5 | 200K tokens | 轻量级长上下文 |
Anthropic Models Overview, docs.anthropic.com/en/about-cl...
15.1.2 Anthropic 长上下文利用最佳实践
原则一:Just-in-Time 上下文策略
Anthropic 官方推荐的"即时加载"策略,而非预先加载所有数据:
python
# 不推荐:一次性加载所有文档
all_documents = load_all_docs() # 可能数十万 tokens
response = client.messages.create(
model="claude-opus-4-6",
messages=[{
"role": "user",
"content": f"基于这些文档回答问题:{all_documents}\n\n问题:{query}"
}]
)
# 推荐:按需加载
# 维护轻量级标识符(文件路径、存储查询、Web 链接等)
# 在运行时使用工具动态加载数据到上下文
def search_and_answer(query: str):
"""按需检索并回答"""
# 先进行轻量级搜索,找到相关文档标识符
relevant_doc_ids = search_index(query, top_k=5)
# 只加载相关文档
relevant_docs = [load_doc(doc_id) for doc_id in relevant_doc_ids]
# 构建提示
context = "\n\n".join(relevant_docs)
response = client.messages.create(
model="claude-opus-4-6",
messages=[{
"role": "user",
"content": f"参考文档:\n{context}\n\n问题:{query}"
}]
)
return response.content[0].text
原则二:混合策略(Hybrid Strategy)
最有效的 Agent 可能采用混合策略:
- 预先检索部分数据以提升速度
- 在其自主判断下进行进一步的自主探索
python
class HybridContextAgent:
"""混合上下文策略 Agent"""
def __init__(self):
# 预加载核心上下文(如 CLAUDE.md)
self.core_context = load_core_context()
# 定义动态加载工具
self.tools = [
{
"name": "search_docs",
"description": "搜索文档库",
"input_schema": {...}
},
{
"name": "read_file",
"description": "读取特定文件",
"input_schema": {...}
}
]
def run(self, task: str):
"""执行任务"""
# 初始提示包含核心上下文
messages = [
{
"role": "user",
"content": f"核心上下文:{self.core_context}\n\n任务:{task}"
}
]
# Agent 可以自主决定何时调用工具加载更多上下文
response = client.messages.create(
model="claude-opus-4-6",
messages=messages,
tools=self.tools
)
return response
原则三:渐进式披露(Progressive Disclosure)
允许 Agent 通过探索逐步发现相关上下文:
python
def progressive_disclosure(query: str, max_exploration: int = 5):
"""渐进式上下文发现"""
discovered_context = []
exploration_count = 0
while exploration_count < max_exploration:
# 基于已发现的上下文生成下一步探索方向
exploration_prompt = f"""
已发现的上下文:
{chr(10).join(discovered_context) if discovered_context else '无'}
原始查询:{query}
基于以上信息,你还需要了解什么?请生成一个搜索查询。
如果已有足够信息回答,请回复 "DONE"。
"""
next_query = generate_exploration_query(exploration_prompt)
if next_query.strip() == "DONE":
break
# 执行搜索
new_context = search_and_retrieve(next_query)
discovered_context.append(new_context)
exploration_count += 1
# 基于所有发现的上下文生成最终回答
final_prompt = f"""
发现的上下文:
{chr(10).join(discovered_context)}
问题:{query}
"""
return generate_answer(final_prompt)
Anthropic Effective Context Engineering, www.anthropic.com/engineering...
15.1.3 上下文感知(Context Awareness)
Claude Sonnet 4.6、Sonnet 4.5 和 Haiku 4.5 具备上下文感知能力。模型在对话开始时接收其总上下文窗口信息:
xml
<budget:token_budget>1000000</budget:token_budget>
每次工具调用后,Claude 接收剩余容量的更新:
xml
<system_warning>Token usage: 35000/1000000; 965000 remaining</system_warning>
这使得 Claude 能够精确使用上下文,坚持执行任务直到最后。
15.2 上下文窗口的物理限制与成本考量
15.2.1 "Lost in the Middle" 现象
核心发现:当相关信息放置在输入中间时,模型准确率可能下降超过 30%。
原因分析:
- 注意力预算有限:Transformer 的注意力机制产生 n² 的成对关系,长上下文使注意力被"拉伸变薄"
- 训练数据分布偏差:模型在训练时接触到的短序列比长序列更常见
- 位置编码限制:位置编码插值技术虽然允许处理更长序列,但在 token 位置理解上会有退化
U 型注意力曲线:
markdown
准确率
│
│ ╭────╮
│ ╱ ╲
│ ╱ 低 ╲
│ ╱ 准 确 ╲
│ ╱ 率 ╲
│ ╱ ╲
│╱ ╲
└─────────────────────
开头 中间 结尾
位置
应对策略:
- 将关键信息放在上下文的开头或结尾
- 使用重复或摘要技术强化中间信息
- 采用分块处理而非一次性处理超长文档
15.2.2 长上下文成本计算
Anthropic Claude 定价(每百万 token):
| 模型 | 基础输入 | 缓存命中 | 输出 |
|---|---|---|---|
| Claude Opus 4.6 | $5 | $0.50 | $25 |
| Claude Sonnet 4.6 | $3 | $0.30 | $15 |
| Claude Haiku 4.5 | $1 | $0.10 | $5 |
Claude Sonnet 4.5/4 长上下文加价(超 200K 输入 token):
| 类别 | <=200K 输入 | >200K 输入 |
|---|---|---|
| 输入 | $3/MTok | $6/MTok |
| 输出 | $15/MTok | $22.50/MTok |
成本计算示例:
python
def calculate_cost(
input_tokens: int,
output_tokens: int,
model: str = "claude-sonnet-4-6",
use_caching: bool = False,
cache_hit_ratio: float = 0.8
) -> dict:
"""计算 API 调用成本"""
# 定价表(每百万 token)
pricing = {
"claude-opus-4-6": {"input": 5, "output": 25},
"claude-sonnet-4-6": {"input": 3, "output": 15},
"claude-haiku-4-5": {"input": 1, "output": 5},
}
model_pricing = pricing.get(model, pricing["claude-sonnet-4-6"])
if use_caching:
# 缓存命中部分按 10% 计费
cached_tokens = int(input_tokens * cache_hit_ratio)
fresh_tokens = input_tokens - cached_tokens
input_cost = (
cached_tokens / 1_000_000 * model_pricing["input"] * 0.1 +
fresh_tokens / 1_000_000 * model_pricing["input"]
)
else:
input_cost = input_tokens / 1_000_000 * model_pricing["input"]
output_cost = output_tokens / 1_000_000 * model_pricing["output"]
return {
"input_cost": round(input_cost, 4),
"output_cost": round(output_cost, 4),
"total_cost": round(input_cost + output_cost, 4),
"input_tokens": input_tokens,
"output_tokens": output_tokens
}
# 示例:处理 500K token 文档
result = calculate_cost(
input_tokens=500_000,
output_tokens=4_000,
model="claude-sonnet-4-6",
use_caching=True,
cache_hit_ratio=0.9
)
print(f"输入成本: ${result['input_cost']}")
print(f"输出成本: ${result['output_cost']}")
print(f"总成本: ${result['total_cost']}")
# 使用缓存后:约 $0.15 输入 + $0.06 输出 = $0.21
# 不使用缓存:$1.50 输入 + $0.06 输出 = $1.56
15.2.3 成本优化策略
策略一:Prompt Caching(提示缓存)
Anthropic 的 Prompt Caching 可将重复使用的上下文成本降低 90%:
python
import anthropic
client = anthropic.Anthropic()
# 自动缓存(推荐)
response = client.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system="你是一个专业助手,记住我们的对话。",
messages=[
{"role": "user", "content": "My name is Alex. I work on ML."},
{
"role": "assistant",
"content": "Nice to meet you, Alex! How can I help?",
},
{"role": "user", "content": "What did I say I work on?"},
],
)
# 缓存行为:
# 请求1:System + User(1) + Asst(1) + User(2) -> 全部写入缓存
# 请求2:System + ... + User(2) + Asst(2) + User(3) -> System到User(2)从缓存读取
策略二:分块处理
python
def process_long_document(document: str, chunk_size: int = 100_000) -> list:
"""分块处理长文档"""
chunks = []
start = 0
while start < len(document):
end = min(start + chunk_size, len(document))
chunk = document[start:end]
chunks.append(chunk)
start = end
return chunks
def summarize_chunks(chunks: list[str]) -> str:
"""分别总结每个块,然后合并"""
summaries = []
for i, chunk in enumerate(chunks):
prompt = f"""总结以下文档片段(片段 {i+1}/{len(chunks)}):
{chunk}
摘要:"""
response = client.messages.create(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": prompt}],
max_tokens=1000
)
summaries.append(response.content[0].text)
# 合并摘要
final_prompt = f"""基于以下摘要生成整体总结:
{chr(10).join(summaries)}
整体总结:"""
final_response = client.messages.create(
model="claude-opus-4-6",
messages=[{"role": "user", "content": final_prompt}],
max_tokens=2000
)
return final_response.content[0].text
15.3 滑动窗口与摘要缓存策略
15.3.1 Anthropic Compaction(压缩)
Anthropic 提供了官方的 Compaction 功能(Beta),这是管理长运行对话的推荐策略。
核心机制:
- 检测输入 token 何时超过指定触发阈值
- 生成当前对话的摘要
- 创建包含摘要的
compaction块 - 使用压缩后的上下文继续响应
python
import anthropic
client = anthropic.Anthropic()
messages = []
def chat_with_compaction(user_message: str) -> str:
"""使用 Compaction 管理长对话"""
messages.append({"role": "user", "content": user_message})
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-6",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": 100000},
}
]
},
)
# 自动包含 compaction 块
messages.append({"role": "assistant", "content": response.content})
# 返回文本内容
return next(block.text for block in response.content if block.type == "text")
# 自定义摘要指令
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-6",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"instructions": """Focus on preserving code snippets,
variable names, and technical decisions.""",
}
]
},
)
总 Token 预算控制:
python
TRIGGER_THRESHOLD = 100_000
TOTAL_TOKEN_BUDGET = 3_000_000
n_compactions = 0
response = client.beta.messages.create(
betas=["compact-2026-01-12"],
model="claude-opus-4-6",
max_tokens=4096,
messages=messages,
context_management={
"edits": [
{
"type": "compact_20260112",
"trigger": {"type": "input_tokens", "value": TRIGGER_THRESHOLD},
"pause_after_compaction": True,
}
]
},
)
if response.stop_reason == "compaction":
n_compactions += 1
messages.append({"role": "assistant", "content": response.content})
# 估算总 token 消耗;超预算则提示收尾
if n_compactions * TRIGGER_THRESHOLD >= TOTAL_TOKEN_BUDGET:
messages.append({
"role": "user",
"content": "Please wrap up and summarize the final state.",
})
Anthropic Compaction, docs.anthropic.com/en/docs/bui...
15.3.2 Context Editing(上下文编辑)
Anthropic 提供了更细粒度的上下文编辑策略:
工具结果清除:
python
response = client.beta.messages.create(
model="claude-opus-4-6",
max_tokens=4096,
messages=[...],
tools=[...],
betas=["context-management-2025-06-27"],
context_management={
"edits": [
{
"type": "clear_tool_uses_20250919",
"trigger": {"type": "input_tokens", "value": 50000},
"keep": {"type": "tool_uses", "value": 5},
"clear_at_least": {"type": "input_tokens", "value": 5000},
"exclude_tools": ["web_search"],
},
]
},
)
思考块清除:
python
response = client.beta.messages.create(
model="claude-opus-4-6",
max_tokens=16000,
messages=[{"role": "user", "content": "Hello"}],
thinking={"type": "enabled", "budget_tokens": 10000},
context_management={
"edits": [
{
"type": "clear_thinking_20251015",
"keep": {"type": "thinking_turns", "value": 2},
}
]
},
)
Anthropic Context Editing, docs.anthropic.com/en/docs/bui...
15.3.3 滑动窗口实现
虽然 Anthropic 没有原生滑动窗口 API,但可以手动实现:
python
def sliding_window_chat(
messages: list,
max_tokens: int = 100_000,
keep_system: bool = True
) -> list:
"""滑动窗口上下文管理"""
client = anthropic.Anthropic()
# 计算当前 token 数
count = client.messages.count_tokens(
model="claude-sonnet-4-6",
messages=messages
)
# 如果超预算,移除旧消息
while count.input_tokens > max_tokens and len(messages) > 1:
# 保留系统消息(如果要求)
remove_idx = 1 if (keep_system and messages[0]["role"] == "system") else 0
messages.pop(remove_idx)
count = client.messages.count_tokens(
model="claude-sonnet-4-6",
messages=messages
)
return messages
# FIFO 滚动窗口(Claude.ai 使用的模式)
def fifo_window(messages: list, max_messages: int = 50) -> list:
"""先进先出消息窗口"""
if len(messages) <= max_messages:
return messages
# 保留系统消息
system_msgs = [m for m in messages if m["role"] == "system"]
other_msgs = [m for m in messages if m["role"] != "system"]
# 只保留最近的 max_messages 条
kept_msgs = other_msgs[-max_messages:]
return system_msgs + kept_msgs
15.4 信息优先级排序与关键信息保留
15.4.1 上下文工程框架
Anthropic 提出的完整上下文工程框架包含以下层次:
第一层:静态上下文(System Prompt + Tools)
- 系统提示应极其清晰、使用简单直接的语言
- 使用 XML 标签或 Markdown 标题组织不同部分
- 工具应自包含、健壮、用途清晰
- 策划最小可行的工具集
第二层:动态上下文检索(Just-in-Time Context)
- 维护轻量级标识符(文件路径、查询、链接)
- 运行时动态加载数据
- 渐进式披露:通过探索逐步发现
第三层:上下文生命周期管理(Context Lifecycle)
- Compaction:对话压缩和摘要
- 结构化笔记:Agent 自主记录关键信息
- 多 Agent 架构:分解复杂任务
第四层:跨会话持久化(Cross-Session Persistence)
- Memory Tool:外部持久化存储
- 文件系统:CLAUDE.md 等配置文件
- 多会话状态恢复设计
15.4.2 关键信息识别策略
策略一:基于位置的重要性
python
def position_based_priority(text: str, position: str = "both") -> str:
"""基于位置的信息优先级处理
position: "start" | "end" | "both" | "repeat"
"""
if position == "start":
# 将关键信息放在开头
return text
elif position == "end":
# 将关键信息放在结尾
return text
elif position == "both":
# 关键信息同时放在开头和结尾
key_info = extract_key_info(text)
return f"{key_info}\n\n{text}\n\n{key_info}"
elif position == "repeat":
# 在中间重复关键信息
key_info = extract_key_info(text)
chunks = split_into_chunks(text, n=3)
return f"{chunks[0]}\n\n{key_info}\n\n{chunks[1]}\n\n{key_info}\n\n{chunks[2]}"
策略二:基于语义的重要性评分
python
def semantic_importance_scoring(sentences: list[str], query: str) -> list[tuple]:
"""基于语义相似度的重要性评分"""
# 获取查询嵌入
query_embedding = get_embedding(query)
# 计算每个句子的重要性得分
scored_sentences = []
for sentence in sentences:
sentence_embedding = get_embedding(sentence)
similarity = cosine_similarity(query_embedding, sentence_embedding)
scored_sentences.append((sentence, similarity))
# 按重要性排序
scored_sentences.sort(key=lambda x: x[1], reverse=True)
return scored_sentences
def prioritize_by_semantics(
documents: list[str],
query: str,
top_k: int = 5
) -> str:
"""基于语义重要性重组文档"""
# 分割为句子
all_sentences = []
for doc in documents:
sentences = split_into_sentences(doc)
all_sentences.extend(sentences)
# 评分并排序
scored = semantic_importance_scoring(all_sentences, query)
# 选择最重要的句子
top_sentences = [s for s, _ in scored[:top_k]]
# 按原文顺序重组(保持连贯性)
# ...
return " ".join(top_sentences)
15.4.3 Memory Tool 结合上下文管理
python
# 使用 Memory Tool 持久化关键信息
response = client.beta.messages.create(
model="claude-opus-4-6",
max_tokens=4096,
messages=[...],
tools=[
{"type": "memory_20250818", "name": "memory"},
# 其他工具
],
betas=["context-management-2025-06-27"],
context_management={"edits": [{"type": "clear_tool_uses_20250919"}]},
)
# 当对话上下文接近清除阈值时,
# Claude 会收到自动警告以保存重要信息
15.5 长文档处理的提示词设计模式
15.5.1 长文档问答模式
模式一:整体阅读 + 针对性提问
python
def holistic_document_qa(document: str, question: str) -> str:
"""整体阅读文档后回答问题"""
prompt = f"""请仔细阅读以下文档,然后回答问题。
文档:
{document}
问题:{question}
回答要求:
1. 仅基于文档内容回答
2. 如果文档中没有相关信息,明确说明
3. 引用文档中的具体段落支持你的回答
回答:"""
response = client.messages.create(
model="claude-opus-4-6", # 使用最强模型处理长文档
messages=[{"role": "user", "content": prompt}],
max_tokens=4000
)
return response.content[0].text
模式二:分段处理 + 结果合并
python
def segmented_document_qa(document: str, question: str) -> str:
"""分段处理长文档"""
# 分块
chunks = chunk_document(document, chunk_size=50_000)
# 对每个块提问
chunk_answers = []
for i, chunk in enumerate(chunks):
prompt = f"""基于以下文档片段(片段 {i+1}/{len(chunks)})回答问题。
如果片段中没有相关信息,回复"无相关信息"。
片段:
{chunk}
问题:{question}
回答:"""
response = client.messages.create(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": prompt}],
max_tokens=1000
)
answer = response.content[0].text
if "无相关信息" not in answer:
chunk_answers.append(answer)
# 合并答案
if not chunk_answers:
return "文档中没有找到相关信息。"
merge_prompt = f"""基于以下从文档不同部分找到的答案,生成完整回答:
{chr(10).join([f'片段 {i+1}:{ans}' for i, ans in enumerate(chunk_answers)])}
问题:{question}
请整合以上信息,生成连贯、完整的回答:"""
final_response = client.messages.create(
model="claude-opus-4-6",
messages=[{"role": "user", "content": merge_prompt}],
max_tokens=2000
)
return final_response.content[0].text
15.5.2 长文档摘要模式
渐进式摘要:
python
def progressive_summarization(document: str) -> str:
"""渐进式文档摘要"""
# 第一层:分块摘要
chunks = chunk_document(document, chunk_size=50_000)
chunk_summaries = []
for chunk in chunks:
prompt = f"""总结以下文档片段(100字以内):
{chunk}
摘要:"""
response = client.messages.create(
model="claude-sonnet-4-6",
messages=[{"role": "user", "content": prompt}],
max_tokens=200
)
chunk_summaries.append(response.content[0].text)
# 第二层:合并摘要
combined = "\n\n".join(chunk_summaries)
prompt = f"""基于以下摘要生成整体文档总结(300字以内):
{combined}
整体总结:"""
response = client.messages.create(
model="claude-opus-4-6",
messages=[{"role": "user", "content": prompt}],
max_tokens=500
)
return response.content[0].text
15.5.3 Anthropic 长文档处理核心建议
- 不要盲目塞入更多上下文 ------ 更多上下文不等于更好性能,Context Rot 会导致准确率下降
- 使用 Just-in-Time 加载 ------ 按需加载相关部分,而非一次性加载全部
- 利用 Compaction ------ 对长对话和任务使用服务端压缩
- 使用 Prompt Caching ------ 对重复使用的系统提示和文档部分启用缓存,降低成本 90%
- 结合 RAG 和长上下文 ------ 用 RAG 做宽召回,用长上下文做深推理
- 关注信息位置 ------ 将关键信息放在上下文的开头或结尾
- 使用 Token 计数 API ------ 在发送前估算 token 使用量
python
# Token 计数示例
count_response = client.beta.messages.count_tokens(
betas=["compact-2026-01-12"],
model="claude-opus-4-6",
messages=messages,
context_management={"edits": [{"type": "compact_20260112"}]},
)
print(f"Current tokens: {count_response.input_tokens}")
print(f"Original tokens: {count_response.context_management.original_input_tokens}")
Anthropic Token Counting, docs.anthropic.com/en/docs/bui...
本章小结
核心概念回顾
| 概念 | 说明 |
|---|---|
| Context Rot | 上下文退化:随着 token 增加,模型回忆信息的能力下降 |
| Lost in the Middle | 中间位置信息被遗忘的现象 |
| Just-in-Time | 按需加载上下文,而非预加载全部 |
| Compaction | Anthropic 服务端自动摘要压缩 |
| Prompt Caching | 缓存重复上下文,降低 90% 成本 |
| Context Editing | 细粒度管理工具结果和思考块 |
关键要点
- 长上下文是把双刃剑:1M token 窗口带来新可能,但也带来成本和注意力挑战
- "Lost in the Middle"是架构限制:Transformer 的固有问题,需要通过位置策略应对
- Just-in-Time 优于预加载:按需检索比一次性塞入全部文档更有效
- 成本优化有手段:Prompt Caching、Compaction、分块处理可显著降低成本
- 信息位置很重要:关键信息放开头或结尾,避免被埋在中间
- 混合策略最有效:RAG + 长上下文、预加载 + 动态探索
技术选型指南
| 场景 | 推荐策略 |
|---|---|
| 单次长文档问答 | 整体处理(1M 窗口) |
| 多轮长对话 | Compaction + Caching |
| 成本敏感场景 | Prompt Caching + 分块 |
| 需要高准确率 | 关键信息放首尾 + 重复 |
| 探索性任务 | Just-in-Time + 渐进式披露 |
下一章预告:第16章将深入讲解"特定领域提示工程",探讨如何在法律、医疗、金融、教育等垂直领域设计专业的提示词。
参考来源:
| 来源 | 链接 |
|---|---|
| Anthropic Context Engineering Blog | www.anthropic.com/engineering... |
| Anthropic Context Windows | docs.anthropic.com/en/docs/bui... |
| Anthropic Compaction | docs.anthropic.com/en/docs/bui... |
| Anthropic Context Editing | docs.anthropic.com/en/docs/bui... |
| Anthropic Prompt Caching | docs.anthropic.com/en/docs/bui... |
| Anthropic Token Counting | docs.anthropic.com/en/docs/bui... |
| Anthropic Models Overview | docs.anthropic.com/en/about-cl... |
| Anthropic Pricing | docs.anthropic.com/en/about-cl... |
| OpenAI Models | platform.openai.com/docs/models |