上下文工程:为什么 Context Window 不是越大越好
▎开篇导语
2025 年主流大模型的 Context Window 已经突破 100 万 token。但一个反直觉的事实是:**单纯把上下文窗口做大,Agent 性能反而会下降。** 本文从工程实践出发,系统讲清楚「上下文工程」的核心原理、四大策略与落地最佳实践。
一、Context Window 不是万能药
很多团队以为「上下文窗口越大越好」,结果上线后问题百出:
| 现象 | 根因 |
|---|---|
| 模型「答非所问」 | 关键信息被淹没在长上下文中 |
| 推理成本暴涨 | 100K token 一次调用要几块钱 |
| 响应延迟飙升 | 长上下文推理时间非线性增长 |
| 模型「忘记」中间内容 | 「Lost in the Middle」现象 |
| 输出风格不稳定 | 多轮历史信息互相干扰 |
核心洞察: 上下文工程的目标不是「把所有信息塞进去」,而是**让对的信息在对的位置出现
二、Context Window 的物理限制
先把几个关键事实讲清楚:
① 注意力机制的二次方复杂度
Transformer 的自注意力计算量是 O(n²)——上下文长度翻倍,计算量变成 4 倍。
② Lost in the Middle 现象
Liu et al. 2023 在论文 [Lost in the Middle](https://arxiv.org/abs/2307.03172) 中证明:模型对上下文开头和结尾的信息记忆最强,中间部分最容易被忽略。
③ 位置编码外推困难
训练时用 8K 上下文,直接用 128K 推理,位置编码会失准,模型表现急剧下降。
三、上下文工程的四大核心策略
3.1 策略一:上下文压缩(Context Compression)
核心思想: 把长上下文压缩成短上下文,保留关键信息。
# compress.py
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
compress_prompt = ChatPromptTemplate.from_template("""
请把下面内容压缩到 200 字以内,保留关键事实、数据和结论:
{long_text}
压缩结果:
""")
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = compress_prompt | llm
def compress_context(text: str) -> str:
"""压缩长文本到 200 字以内"""
return chain.invoke({"long_text": text}).content
常见压缩方法:
① 抽取式压缩 — 用 TextRank / BERT 抽取关键句子
② 生成式压缩 — 用 LLM 自己总结
③ 结构化压缩 — 转为表格 / 列表形式
④ 滑动窗口压缩 — 只保留最近 N 轮对话
3.2 策略二:上下文分层(Context Layering)
核心思想: 把上下文分成多个层级,按需加载。
# 三层上下文架构
L1 核心层(永远加载): 500-2000 tokens
- 系统提示(System Prompt)
- 任务定义
- 关键约束
L2 任务层(按需加载): 2000-8000 tokens
- 当前任务相关历史
- 相关工具描述
- 当前对话上下文
L3 知识层(动态检索): 不限
- 历史对话
- 外部知识库
- 工具调用结果
工程实现:
- L1 写死在代码里
- L2 用内存缓存
- L3 用向量数据库(pgvector / Milvus / Qdrant)
3.3 策略三:上下文选择(Context Selection)
核心思想: 不是所有信息都要给模型,让它自己决定需要什么。
方法 A:ReAct 主动获取让 Agent 在需要时主动调工具获取信息:
@tool
def search_knowledge_base(query: str) -> str:
"""从知识库搜索相关内容。"""
# 实际接入向量数据库
results = vector_db.search(query, top_k=3)
return "\n".join([r.page_content for r in results])
方法 B:RAG 检索增强
# rag_pipeline.py
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
# 1. 构建向量库
vectorstore = Chroma.from_documents(
documents=docs,
embedding=OpenAIEmbeddings(),
persist_directory="./chroma_db"
)
# 2. 检索 Top-K 相关内容
def retrieve_context(query: str, k: int = 5) -> str:
docs = vectorstore.similarity_search(query, k=k)
return "\n\n".join([d.page_content for d in docs])
关键论文: Lewis et al. 2020, [Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks](https://arxiv.org/abs/2005.11401)
方法 C:Self-RAG
让模型自己判断是否需要检索——不需要就不检索,节省成本。
3.4 策略四:上下文优化(Context Optimization)
核心思想: 优化上下文的排列顺序和格式,让模型更容易抓到重点。关键原则:
① 重要信息放首尾 — 利用 Lost in the Middle 现象
② 结构化优于纯文本 — 表格 / 列表 / JSON 比大段文字更易处理
③ 指令与示例分离 — 指令放系统提示,示例放用户消息
④ 避免重复 — 同一信息不要在多个位置重复
⑤ 善用 XML/标签 — 让模型能清晰区分不同段落
# 优化后的 Prompt 结构示例
<system>
[角色与核心规则]
</system>
<user>
<task>[具体任务]</task>
<context>[相关背景]</context>
<constraints>[约束条件]</constraints>
<examples>[可选示例]</examples>
</user>
四、实战:构建一个生产级 Agent 上下文管理器
# context_manager.py
from typing import List, Dict
from langchain_openai import ChatOpenAI
from langchain.memory import ConversationSummaryBufferMemory
class ProductionContextManager:
"""生产级上下文管理器"""
def __init__(self, max_tokens: int = 8000):
self.max_tokens = max_tokens
self.llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 短期记忆:保留最近 5 轮完整对话
self.short_term = ConversationSummaryBufferMemory(
llm=self.llm,
max_token_limit=2000,
return_messages=True
)
# 长期记忆:向量数据库
self.long_term = None # 初始化为 None,按需加载
# 任务状态:当前任务相关信息
self.task_state: Dict = {}
def build_context(self, user_input: str) -> List[Dict]:
"""构建发送给 LLM 的完整上下文"""
# L1: 系统提示(永远在)
messages = [{
"role": "system",
"content": self._get_system_prompt()
}]
# L2: 短期记忆摘要 + 最近对话
short_summary = self.short_term.buffer
if short_summary:
messages.append({
"role": "system",
"content": f"对话历史摘要:{short_summary}"
})
# L3: 从长期记忆检索相关内容(如果启用了 RAG)
if self.long_term:
relevant = self._retrieve_relevant(user_input, top_k=3)
if relevant:
messages.append({
"role": "system",
"content": f"相关知识:\n{relevant}"
})
# L4: 当前任务状态
if self.task_state:
messages.append({
"role": "system",
"content": f"当前任务状态:{self.task_state}"
})
# L5: 用户当前输入
messages.append({"role": "user", "content": user_input})
# 检查总 token 数,超过则压缩
total_tokens = self._count_tokens(messages)
if total_tokens > self.max_tokens:
messages = self._compress_messages(messages)
return messages
def _get_system_prompt(self) -> str:
return """你是杰哥的专属 AI 助手。
- 回答简洁专业
- 优先用中文
- 复杂问题分步骤回答
"""
def _retrieve_relevant(self, query: str, top_k: int) -> str:
# 调用向量数据库
return ""
def _count_tokens(self, messages: List[Dict]) -> int:
# 用 tiktoken 计算
return len(str(messages)) // 2 # 粗略估算
def _compress_messages(self, messages: List[Dict]) -> List[Dict]:
# 压缩历史消息
return messages
五、上下文工程的常见陷阱
| 陷阱 | 现象 | 解决方案 |
|---|---|---|
| **上下文冗余** | 同一信息出现多次 | 单一来源原则 |
| **指令漂移** | 多轮后模型忘记初始指令 | 每轮重申核心指令 |
| **检索噪声** | RAG 检索到不相关内容 | 提高相似度阈值 + 重排序 |
| **上下文污染** | 错误信息被模型当真 | 验证 + 引用机制 |
| **Token 浪费** | 把整本书塞进上下文 | 增量加载 + 摘要 |
六、2026 年上下文工程趋势
① Context Caching — Anthropic / OpenAI 都支持缓存命中,成本直降 90%
② Infinite Context — 基于 RAG + 压缩,理论上无限上下文
③ Multi-Modal Context — 文本+图像+视频统一编码
④ Context Engineering 工具 — LangChain Context Engineering、LlamaIndex Agents
⑤ KV Cache 优化 — 通过前缀共享降低推理成本
七、总结
上下文工程是 Agent 系统的核心基础设施。核心要点:
① 不要迷信大窗口 — 质量和成本比窗口大小更重要
② 分层管理 — L1 核心 / L2 任务 / L3 知识
③ 按需加载 — ReAct / RAG / Self-RAG 灵活组合
④ 重要信息放首尾 — 避开 Lost in the Middle
⑤ 持续压缩 — 长期任务必须有上下文压缩机制
下一步学习建议:
- 读论文:[Lost in the Middle](https://arxiv.org/abs/2307.03172) / [RAG](https://arxiv.org/abs/2005.11401) / [Self-RAG](https://arxiv.org/abs/2310.11511)
- 做实战:用 LangChain 实现一个带上下文管理的对话 Agent
- 关注前沿:Context Caching、Infinite Context、KV Cache 优化
参考资料:
- [Lost in the Middle: How Language Models Use Long Contexts](https://arxiv.org/abs/2307.03172)
- [Retrieval-Augmented Generation](https://arxiv.org/abs/2005.11401)
- [Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection](https://arxiv.org/abs/2310.11511)
- [Anthropic Prompt Caching 文档](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching)
- [LangChain Context Engineering 实践](https://python.langchain.com/docs/concepts/lcel/)
更多推荐



所有评论(0)