第十八章:上下文(Context)与记忆

学习目标

  • 理解上下文窗口的概念和限制
  • 掌握上下文的组成和管理策略
  • 了解Agent记忆系统的类型和作用
  • 能够计算上下文窗口的token消耗

前置要求

建议先学习第十一章:大语言模型(LLM)详解,了解LLM的基本原理和Token概念。

上下文窗口与记忆管理概念图
图18-1 上下文窗口与记忆管理: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")

本章小结

  1. 上下文是LLM在一次对话中能"看到"的所有信息,上下文窗口大小以Token数量衡量,超出部分会被遗忘。
  2. 上下文由系统提示、用户消息、助手回复和历史对话组成,管理策略包括滑动窗口、摘要压缩、选择性保留和外部记忆。
  3. Agent记忆系统分为短期记忆(当前会话)、长期记忆(跨会话持久)、情景记忆(特定事件)和程序性记忆(技能知识)四种类型。
  4. 合理计算和管理token消耗是优化LLM应用的关键,需要为模型输出预留足够空间,同时控制历史对话的长度。

练习题

  1. 以下哪种上下文管理策略最适合长对话场景?

    A. 滑动窗口
    B. 摘要压缩
    C. 不做任何管理
    D. 直接清空历史

    答案:B。摘要压缩将早期对话内容压缩为简短摘要,既保留了重要信息,又释放了上下文窗口空间,最适合长对话场景。

  2. Agent的"长期记忆"通常存储在哪里?

    A. 上下文窗口中
    B. 向量数据库或文件中
    C. LLM的参数中
    D. 临时变量中

    答案:B。长期记忆需要跨会话持久保存,通常存储在向量数据库、关系数据库或文件系统中,而不是会话级的上下文窗口中。

  3. 如果一个模型的上下文窗口是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。