---
author: QinIndexCode
tags: AI, Agent, 上下文, LLM
---

## 2026-03-23 Agent的上下文处理

---

## 引言

Agent 是基于 LLM 完成任务的系统，而上下文管理直接决定它能不能正确理解和执行任务。

上下文处理不是把所有历史记录一股脑塞给 LLM，而是要根据任务性质和上下文类型选择处理方式。对话轮次一多，上下文会持续膨胀，全量传递会带来几个直接问题：

- **Token 消耗过大**：成本急剧上升
- **响应延迟增加**：模型处理时间变长
- **信息噪音干扰**：关键信息被淹没
- **上下文窗口溢出**：超出模型限制

所以，上下文策略是 Agent 工程里绕不开的一环。

---

## 上下文处理的常见方式

### 1. 上下文缓存

缓存是最基础也最有效的手段：把频繁使用的上下文预先算好存起来，避免重复处理。

**实现方式：**

```python
class ContextCache:
    def __init__(self, max_size=100):
        self.cache = {}
        self.max_size = max_size
    
    def get(self, key):
        return self.cache.get(key)
    
    def set(self, key, value):
        if len(self.cache) >= self.max_size:
            # LRU 淘汰策略
            oldest_key = next(iter(self.cache))
            del self.cache[oldest_key]
        self.cache[key] = value
```

**应用场景：**
- 系统提示词（System Prompt）缓存
- 常用工具描述缓存
- 用户偏好设置缓存
- RAG 检索结果的缓存

**注意事项：**
- 需要合理的缓存失效策略
- 注意缓存一致性问题
- 对于动态变化的内容要谨慎使用

---

### 2. 上下文压缩

压缩的目标，是在不丢关键信息的前提下减少上下文的 Token 数量。

**常用压缩技术：**

| 技术 | 原理 | 适用场景 |
|------|------|----------|
| 语义压缩 | 提取核心语义，去除冗余表达 | 长对话历史 |
| 结构化压缩 | 将非结构化文本转为结构化格式 | 工具调用结果 |
| 截断压缩 | 保留最近 N 轮对话 | 简单对话场景 |
| 蒸馏压缩 | 用小模型生成压缩版本 | 大规模文档 |

**示例：语义压缩**

```
原始上下文（150 tokens）：
"用户在 3 月 15 日询问了关于 Python 异步编程的问题，我详细解释了 async/await 
的用法，并提供了三个示例代码。用户表示理解了，然后问了一个关于 asyncio 库的
问题，我解释了事件循环的概念..."

压缩后（30 tokens）：
"对话主题：Python 异步编程；已解答：async/await、asyncio；用户状态：理解"
```

**实现要点：**
- 压缩比与信息保留需要权衡
- 关键决策点信息不能丢失
- 可使用 LLM 辅助压缩（但需考虑成本）

---

### 3. 上下文摘要

摘要和压缩类似，但它不只是提取关键点，更强调生成一段连贯的总结性描述。

**摘要层级结构：**

| 层级 | 名称 | 描述 |
|------|------|------|
| 第一层 | 全局摘要 | 整个会话的核心目标与进展 |
| 第二层 | 阶段摘要 | 最近 N 轮对话的总结 |
| 第三层 | 原始对话 | 最近 3-5 轮的完整上下文 |

**摘要触发策略：**
- **轮次触发**：每 N 轮对话生成一次摘要
- **长度触发**：上下文超过阈值时触发
- **阶段触发**：完成一个子任务后触发

**代码示例：**

```python
def should_summarize(messages, threshold=4000):
    total_tokens = sum(estimate_tokens(m) for m in messages)
    return total_tokens > threshold

def summarize_context(messages, llm):
    summary_prompt = f"""
    请总结以下对话的核心内容：
    
    对话历史：
    {format_messages(messages)}
    
    请用简洁的语言总结：
    1. 用户的核心需求
    2. 已完成的工作
    3. 待解决的问题
    """
    return llm.generate(summary_prompt)
```

---

### 4. 上下文筛选

筛选指的是根据当前任务的相关性，动态决定哪些上下文值得放进窗口。

**筛选维度：**

1. **时间相关性**：优先保留最近的对话
2. **主题相关性**：保留与当前任务相关的历史
3. **重要性权重**：保留关键决策和结果
4. **用户关注度**：保留用户明确提及的内容

**基于向量检索的筛选：**

```python
from sentence_transformers import SentenceTransformer
import numpy as np

class ContextSelector:
    def __init__(self, model_name='all-MiniLM-L6-v2'):
        self.model = SentenceTransformer(model_name)
    
    def select_relevant(self, query, history, top_k=5):
        # 编码查询
        query_embedding = self.model.encode(query)
        
        # 编码历史上下文
        history_embeddings = self.model.encode(history)
        
        # 计算相似度
        similarities = np.dot(history_embeddings, query_embedding)
        
        # 选择最相关的 top_k
        top_indices = np.argsort(similarities)[-top_k:][::-1]
        return [history[i] for i in top_indices]
```

**筛选策略组合：**

```
最终上下文 = 最近3轮对话 + 相关历史(检索) + 关键决策(标记) + 系统提示
```

---

## 最佳实践

### 分层上下文管理

```
Level 1: 系统级（始终保留）
    └── 系统提示、工具定义、安全规则

Level 2: 会话级（摘要保留）
    └── 会话目标、关键决策、重要结果

Level 3: 阶段级（压缩保留）
    └── 当前任务相关历史

Level 4: 即时级（完整保留）
    └── 最近 2-3 轮对话
```

### 动态调整策略

```python
class AdaptiveContextManager:
    def __init__(self):
        self.strategies = {
            'simple': SimpleTruncation(),
            'moderate': CompressionStrategy(),
            'complex': SummaryStrategy(),
        }
    
    def select_strategy(self, task_complexity, context_length):
        if context_length < 2000:
            return self.strategies['simple']
        elif task_complexity == 'high':
            return self.strategies['complex']
        else:
            return self.strategies['moderate']
```

---

## 总结

上下文处理是 Agent 架构的核心挑战之一。做得好的收益很直接：

1. **降低成本**：少花冤枉 Token
2. **提升性能**：响应更快
3. **提高质量**：模型的注意力集中在关键信息上
4. **扩展能力**：支撑更长的对话和更复杂的任务

实际应用里通常是多种策略组合使用、按场景动态切换。另外一个趋势是：随着上下文窗口越来越大，处理的重点已经从"怎么塞进去"变成"怎么组织得更有效"。
