第十八章:上下文(Context)与记忆
学习目标
- 理解上下文窗口的概念和限制
- 掌握上下文的组成和管理策略
- 了解Agent记忆系统的类型和作用
- 能够计算上下文窗口的token消耗
前置要求
建议先学习第十一章:大语言模型(LLM)详解,了解LLM的基本原理和Token概念。
什么是上下文(Context)?
上下文(Context)是指LLM在一次对话中能够"看到"的所有信息。它包括系统提示、用户消息、助手回复和历史对话等内容。上下文决定了LLM"知道什么"来回答当前问题。
上下文窗口(Context Window)
每个LLM都有一个上下文窗口大小限制,以Token数量衡量。超出窗口的信息会被"遗忘"。常见模型的上下文窗口:
- GPT-4o:128K tokens
- GPT-4o-mini:128K tokens
- Claude 3.5 Sonnet:200K tokens
- Qwen2.5-72B:128K tokens
- GLM-4:128K tokens
- 早期GPT-3.5:4K / 16K tokens
上下文的组成
系统提示
定义AI的角色和行为规则
用户消息
当前用户的输入内容
助手回复
AI之前的回答内容
历史对话
之前的对话记录
上下文管理策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 滑动窗口 | 保留最近N轮对话,丢弃更早的 | 简单对话场景 |
| 摘要压缩 | 将早期对话摘要后保留,释放空间 | 长对话场景 |
| 选择性保留 | 根据相关性选择保留重要信息 | 信息密度高的对话 |
| 外部记忆 | 将信息存储到外部数据库,按需检索 | Agent和复杂应用 |
Agent记忆系统
对于AI Agent来说,记忆系统比简单的对话历史更加复杂,需要支持不同类型和不同时效的记忆。
记忆类型
| 记忆类型 | 持续时间 | 存储位置 | 特点 |
|---|---|---|---|
| 短期记忆(工作记忆) | 当前会话 | 上下文窗口 | 容量有限,会话结束即消失 |
| 长期记忆 | 跨会话持久 | 向量数据库/文件 | 容量大,可跨会话访问 |
| 情景记忆 | 特定事件 | 结构化存储 | 记录特定事件和经历 |
| 程序性记忆 | 永久 | 工具/技能配置 | 存储"如何做事"的知识 |
记忆的作用
- 保持连贯性:让Agent记住之前的对话和决策,避免重复询问
- 积累经验:从历史交互中学习,逐步提升任务完成质量
- 个性化:记住用户偏好和习惯,提供个性化服务
- 协作支持:在多Agent协作中共享信息和状态
记忆存储技术
- 向量数据库:存储语义记忆,支持相似度检索(Chroma、Milvus)
- 关系数据库:存储结构化信息(用户档案、任务记录)
- 键值存储:存储简单的配置和状态(Redis)
- 文件系统:存储长期文档和日志
上下文窗口计算示例
理解上下文窗口的token消耗对于优化LLM应用非常重要。以下是一个具体的计算示例:
Token计算示例
假设使用一个上下文窗口为 8K tokens 的模型:
- 系统提示词:约 200 tokens("你是一个AI助手,擅长回答技术问题...")
- 用户当前消息:约 50 tokens("请解释什么是Transformer架构")
- 历史对话(10轮):
- 每轮用户消息平均:~30 tokens
- 每轮助手回复平均:~150 tokens
- 10轮总计:10 x (30 + 150) = 1800 tokens
- 预留生成空间:1024 tokens(给模型生成回答留出空间)
总消耗:200 + 50 + 1800 + 1024 = 3074 tokens
剩余空间:8192 - 3074 = 5118 tokens
如果历史对话增加到50轮:50 x 180 = 9000 tokens,就会超出8K窗口,需要使用滑动窗口或摘要策略。
import tiktoken
def count_tokens(text, model="gpt-4o-mini"):
"""计算文本的token数量"""
encoding = tiktoken.encoding_for_model(model)
return len(encoding.encode(text))
# 计算各部分token消耗
system_prompt = "你是一个专业的AI学习助手,擅长用简单易懂的语言解释复杂的技术概念。"
user_message = "请解释什么是Transformer架构?"
system_tokens = count_tokens(system_prompt)
user_tokens = count_tokens(user_message)
print(f"系统提示:{system_tokens} tokens")
print(f"用户消息:{user_tokens} tokens")
print(f"当前总消耗:{system_tokens + user_tokens} tokens")
# 模拟10轮历史对话
history_tokens = 10 * (30 + 150) # 每轮约180 tokens
reserved_for_output = 1024
total = system_tokens + user_tokens + history_tokens + reserved_for_output
print(f"含历史对话总消耗:{total} tokens")
print(f"8K窗口剩余:{8192 - total} tokens")
本章小结
- 上下文是LLM在一次对话中能"看到"的所有信息,上下文窗口大小以Token数量衡量,超出部分会被遗忘。
- 上下文由系统提示、用户消息、助手回复和历史对话组成,管理策略包括滑动窗口、摘要压缩、选择性保留和外部记忆。
- Agent记忆系统分为短期记忆(当前会话)、长期记忆(跨会话持久)、情景记忆(特定事件)和程序性记忆(技能知识)四种类型。
- 合理计算和管理token消耗是优化LLM应用的关键,需要为模型输出预留足够空间,同时控制历史对话的长度。
练习题
-
以下哪种上下文管理策略最适合长对话场景?
A. 滑动窗口
B. 摘要压缩
C. 不做任何管理
D. 直接清空历史答案:B。摘要压缩将早期对话内容压缩为简短摘要,既保留了重要信息,又释放了上下文窗口空间,最适合长对话场景。
-
Agent的"长期记忆"通常存储在哪里?
A. 上下文窗口中
B. 向量数据库或文件中
C. LLM的参数中
D. 临时变量中答案:B。长期记忆需要跨会话持久保存,通常存储在向量数据库、关系数据库或文件系统中,而不是会话级的上下文窗口中。
-
如果一个模型的上下文窗口是8K tokens,系统提示用了200 tokens,预留输出1024 tokens,那么历史对话最多可以使用多少tokens?
A. 8192 tokens
B. 1024 tokens
C. 6968 tokens
D. 7168 tokens答案:C。可用空间 = 8192 - 200(系统提示)- 1024(预留输出)= 6968 tokens。