知识模块
🤖 Agent 知识模块
短期记忆

短期记忆

短期记忆是 Agent 记忆系统的"工作台",存储当前对话的上下文信息。它直接参与 LLM 推理,决定了 Agent 的即时响应能力和对话连贯性。


一、什么是短期记忆?

1.1 定义

短期记忆(Short-Term Memory) 是 Agent 在当前会话中维护的上下文信息集合,存储在 LLM 的 Context Window 中,随会话结束而消失。

1.2 核心特征

┌─────────────────────────────────────────────────────────────┐
│                    短期记忆核心特征                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  存储位置:LLM Context Window                        │   │
│  │  生命周期:会话期间                                   │   │
│  │  容量限制:受模型上下文窗口限制                       │   │
│  │  访问速度:极快,直接参与推理                         │   │
│  │  管理成本:每次请求都消耗 Token                       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  典型内容:                                                 │
│  • 系统提示词 (System Prompt)                               │
│  • 对话历史 (Conversation History)                          │
│  • 检索到的外部知识 (Retrieved Context)                     │
│  • 用户当前输入 (User Input)                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.3 与长期记忆的区别

维度短期记忆长期记忆
存储位置LLM Context Window外部存储(向量库/数据库)
生命周期会话期间永久
访问方式直接参与推理需要检索后注入
访问速度毫秒级百毫秒到秒级
容量受模型限制(4K-200K Token)理论无限
成本每次请求都消耗 Token检索成本 + 存储成本
内容当前对话相关历史知识、用户偏好

二、短期记忆的组成结构

2.1 上下文窗口结构

┌─────────────────────────────────────────────────────────────┐
│                    LLM Context Window 结构                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  System Prompt(系统提示词)                         │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │ You are a helpful assistant...              │   │   │
│  │  │ 用户偏好:喜欢简洁回答                        │   │   │
│  │  │ 当前任务:回答技术问题                        │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                           ↓                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Conversation History(对话历史)                    │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │ User: 什么是 RAG?                           │   │   │
│  │  │ Assistant: RAG 是检索增强生成...             │   │   │
│  │  │ User: 它有什么优势?                         │   │   │
│  │  │ Assistant: RAG 的优势包括...                 │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                           ↓                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Retrieved Context(检索上下文)                     │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │ [知识库检索结果]                             │   │   │
│  │  │ RAG 技术详解:...                            │   │   │
│  │  │ 向量数据库对比:...                          │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                           ↓                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Current User Input(当前用户输入)                  │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │ User: 能举个例子说明吗?                     │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  总 Token 数 = System + History + Retrieved + Input        │
│  不能超过模型的 Context Window 限制                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.2 各部分详解

系统提示词 (System Prompt)

系统提示词定义了 Agent 的角色和行为规范:

system_prompt = """
你是一个专业的技术问答助手。
 
## 角色定义
- 名字:小智
- 定位:技术领域的智能问答助手
- 风格:专业、简洁、友好
 
## 用户偏好
- 语言:中文
- 详细程度:简洁(优先给出结论)
- 代码风格:Python
 
## 行为规范
1. 回答技术问题时,先给出核心结论
2. 需要时补充详细解释和代码示例
3. 不确定时明确说明
"""

对话历史 (Conversation History)

对话历史是短期记忆的核心,包含多轮交互:

conversation_history = [
    {"role": "user", "content": "什么是向量数据库?"},
    {"role": "assistant", "content": "向量数据库是一种专门存储和检索向量数据的数据库..."},
    {"role": "user", "content": "有哪些主流产品?"},
    {"role": "assistant", "content": "主流向量数据库包括:\n1. Milvus\n2. Pinecone\n3. Chroma..."},
    {"role": "user", "content": "Chroma 怎么用?"}  # 当前问题
]

检索上下文 (Retrieved Context)

从长期记忆检索到的相关信息:

retrieved_context = """
[相关文档 1]
Chroma 是一个开源的向量数据库,支持本地运行...
 
[相关文档 2]
Chroma 基本用法:
```python
import chromadb
client = chromadb.Client()
collection = client.create_collection("my_collection")
collection.add(documents=["文档内容"], ids=["id1"])

"""


---

## 三、短期记忆管理

### 3.1 容量管理策略

┌─────────────────────────────────────────────────────────────┐ │ 短期记忆容量管理 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 问题:Context Window 有限,对话历史会不断增长 │ │ │ │ 解决方案: │ │ │ │ 1. 截断策略 (Truncation) │ │ ┌─────────────────────────────────────────────────┐ │ │ │ • 保留最近 N 轮对话 │ │ │ │ • 简单直接,但可能丢失重要上下文 │ │ │ │ • 适用于:对话历史不太重要场景 │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ 2. 滑动窗口 (Sliding Window) │ │ ┌─────────────────────────────────────────────────┐ │ │ │ • 保持 Token 总数不超过阈值 │ │ │ │ • 自动丢弃最早的对话 │ │ │ │ • 适用于:大多数对话场景 │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ 3. 摘要压缩 (Summarization) │ │ ┌─────────────────────────────────────────────────┐ │ │ │ • 将旧对话压缩为摘要 │ │ │ │ • 保留关键信息,减少 Token │ │ │ │ • 适用于:长对话、关键信息多的场景 │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ 4. 重要性筛选 (Importance Filtering) │ │ ┌─────────────────────────────────────────────────┐ │ │ │ • 评估每轮对话的重要性 │ │ │ │ • 保留高重要性对话,丢弃低重要性 │ │ │ │ • 适用于:对话质量要求高的场景 │ │ │ └─────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘


### 3.2 LangChain 中的实现

#### 基于窗口的记忆管理

```python
from langchain.memory import ConversationBufferWindowMemory
from langchain.chains import ConversationChain
from langchain_openai import OpenAI

# 只保留最近 5 轮对话
memory = ConversationBufferWindowMemory(k=5)

llm = OpenAI(temperature=0)
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True
)

# 多轮对话
conversation.predict(input="你好,我是小明")
conversation.predict(input="我想了解 Python")
conversation.predict(input="你记得我的名字吗?")  # 如果超过5轮可能不记得

基于摘要的记忆管理

from langchain.memory import ConversationSummaryMemory
from langchain_openai import OpenAI
 
# 自动将旧对话压缩为摘要
memory = ConversationSummaryMemory(llm=OpenAI(temperature=0))
 
llm = OpenAI(temperature=0)
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True
)
 
# 对话历史会被自动压缩
conversation.predict(input="我想学习机器学习")
conversation.predict(input="从哪里开始?")
conversation.predict(input="需要什么基础?")
 
# 查看当前记忆状态
print(memory.load_memory_variables({}))
# 输出类似:{'history': '用户想学习机器学习,询问了入门路径和所需基础...'}

基于Token限制的记忆管理

from langchain.memory import ConversationTokenBufferMemory
from langchain_openai import OpenAI
 
# 限制总 Token 数不超过 2000
memory = ConversationTokenBufferMemory(
    llm=OpenAI(temperature=0),
    max_token_limit=2000
)
 
llm = OpenAI(temperature=0)
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True
)
 
# 对话历史会自动截断以符合 Token 限制
for i in range(20):
    conversation.predict(input=f"这是第 {i+1} 轮对话")

3.3 自定义记忆管理

from typing import List, Dict
import tiktoken
 
class SmartMemoryManager:
    """智能短期记忆管理器"""
    
    def __init__(self, max_tokens: int = 4000, model: str = "gpt-3.5-turbo"):
        self.max_tokens = max_tokens
        self.encoding = tiktoken.encoding_for_model(model)
        self.history: List[Dict] = []
        self.summary: str = ""
    
    def count_tokens(self, text: str) -> int:
        """计算文本的 Token 数"""
        return len(self.encoding.encode(text))
    
    def add_message(self, role: str, content: str):
        """添加消息到历史"""
        self.history.append({"role": role, "content": content})
        self._manage_capacity()
    
    def _manage_capacity(self):
        """管理容量,确保不超过限制"""
        while self._estimate_total_tokens() > self.max_tokens:
            if len(self.history) > 2:
                # 移除最早的非系统消息
                self.history.pop(0)
            else:
                break
    
    def _estimate_total_tokens(self) -> int:
        """估算总 Token 数"""
        total = 0
        for msg in self.history:
            total += self.count_tokens(msg["content"])
        return total
    
    def get_context(self) -> List[Dict]:
        """获取当前上下文"""
        return self.history.copy()
    
    def compress_old_messages(self, keep_recent: int = 5):
        """压缩旧消息为摘要"""
        if len(self.history) <= keep_recent:
            return
        
        old_messages = self.history[:-keep_recent]
        recent_messages = self.history[-keep_recent:]
        
        # 将旧消息转为摘要(实际应用中调用 LLM)
        summary_text = "\n".join([
            f"{m['role']}: {m['content']}" 
            for m in old_messages
        ])
        self.summary = f"[历史摘要]\n{summary_text}"
        
        # 更新历史
        self.history = [
            {"role": "system", "content": self.summary}
        ] + recent_messages

四、短期记忆的应用场景

4.1 多轮对话

┌─────────────────────────────────────────────────────────────┐
│                    多轮对话示例                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  User: 我最近想学 Python                                    │
│  Assistant: 很好的选择!Python 适合初学者...                 │
│                                                             │
│  User: 应该从哪里开始?        ← 需要理解上下文              │
│  Assistant: 既然你想学 Python,建议从基础语法开始...         │
│                                                             │
│  User: 有推荐的教程吗?        ← 延续之前的话题              │
│  Assistant: 针对Python学习,我推荐...                       │
│                                                             │
│  【短期记忆的作用】                                          │
│  • 理解"应该"指的是学Python                                  │
│  • 理解"有推荐的教程"指的是Python教程                        │
│  • 保持对话主题的连贯性                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.2 指代消解

# 指代消解依赖短期记忆
conversation = [
    {"role": "user", "content": "什么是 RAG?"},
    {"role": "assistant", "content": "RAG 是检索增强生成技术..."},
    {"role": "user", "content": "它有什么优势?"},  # "它"指 RAG
    {"role": "assistant", "content": "RAG 的优势包括..."},
    {"role": "user", "content": "如何实现?"},  # 省略主语,仍是 RAG
]
 
# 没有短期记忆,LLM 无法理解"它"和省略主语

4.3 任务执行跟踪

┌─────────────────────────────────────────────────────────────┐
│                    任务执行跟踪示例                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Agent 正在执行数据分析任务:                                │
│                                                             │
│  Step 1: 读取数据文件 ✓                                     │
│          → 短期记忆:文件路径、数据结构                      │
│                                                             │
│  Step 2: 数据清洗 ✓                                         │
│          → 短期记忆:清洗规则、处理数量                      │
│                                                             │
│  Step 3: 数据分析 ⏳ (当前)                                  │
│          → 需要前两步的信息来决定分析方法                    │
│                                                             │
│  Step 4: 生成报告                                           │
│          → 需要所有步骤的结果                                │
│                                                             │
│  【短期记忆的作用】                                          │
│  • 跟踪任务进度                                              │
│  • 传递中间结果                                              │
│  • 支持任务回滚和恢复                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

五、短期记忆的优化技巧

5.1 Token 优化技巧

┌─────────────────────────────────────────────────────────────┐
│                    Token 优化技巧                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 精简系统提示词                                          │
│     ┌─────────────────────────────────────────────────┐    │
│     │ ❌ 冗长版本 (500+ tokens):                       │    │
│     │ 你是一个非常专业的、有多年经验的、知识渊博的...    │    │
│     │                                                   │    │
│     │ ✅ 精简版本 (50 tokens):                         │    │
│     │ 角色:技术问答助手                                │    │
│     │ 风格:专业、简洁                                  │    │
│     └─────────────────────────────────────────────────┘    │
│                                                             │
│  2. 压缩对话历史                                            │
│     ┌─────────────────────────────────────────────────┐    │
│     │ • 合并连续的同角色消息                            │    │
│     │ • 去除无关的寒暄                                  │    │
│     │ • 使用摘要替代长对话                              │    │
│     └─────────────────────────────────────────────────┘    │
│                                                             │
│  3. 按需加载检索上下文                                      │
│     ┌─────────────────────────────────────────────────┐    │
│     │ • 只检索与当前问题相关的内容                      │    │
│     │ • 限制检索结果数量                                │    │
│     │ • 压缩检索到的文档                                │    │
│     └─────────────────────────────────────────────────┘    │
│                                                             │
│  4. 使用更高效的编码                                        │
│     ┌─────────────────────────────────────────────────┐    │
│     │ • 中文使用中文 Tokenizer(如 GPT-4 的 cl100k)   │    │
│     │ • 避免使用过多英文缩写                            │    │
│     └─────────────────────────────────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

5.2 质量优化技巧

class QualityMemoryManager:
    """高质量短期记忆管理"""
    
    def __init__(self):
        self.history = []
        self.key_facts = {}  # 提取的关键事实
    
    def add_message(self, role: str, content: str):
        """添加消息,同时提取关键事实"""
        self.history.append({"role": role, "content": content})
        
        # 提取关键事实(简化示例)
        if role == "user":
            # 实际应用中可以用 LLM 提取
            key_fact = self._extract_key_fact(content)
            if key_fact:
                self.key_facts[len(self.history)] = key_fact
    
    def _extract_key_fact(self, content: str) -> str:
        """提取关键事实"""
        # 简化实现,实际应用中可用 LLM
        keywords = ["我想", "我需要", "我偏好", "请记住"]
        for kw in keywords:
            if kw in content:
                return content
        return None
    
    def get_context_for_inference(self, max_tokens: int = 4000):
        """获取推理用的上下文,优先保留关键信息"""
        context = []
        token_count = 0
        
        # 先添加关键事实摘要
        facts_summary = self._summarize_facts()
        context.append({"role": "system", "content": facts_summary})
        token_count += self._count_tokens(facts_summary)
        
        # 再添加最近对话
        for msg in reversed(self.history):
            msg_tokens = self._count_tokens(msg["content"])
            if token_count + msg_tokens > max_tokens:
                break
            context.insert(1, msg)  # 插入到系统提示后
            token_count += msg_tokens
        
        return context
    
    def _summarize_facts(self) -> str:
        """总结关键事实"""
        if not self.key_facts:
            return ""
        return "关键信息:" + "; ".join(self.key_facts.values())

六、面试高频问题

Q1: 短期记忆的容量限制是什么?如何解决?

答案要点

容量限制

  • 受 LLM Context Window 限制(4K-200K Token)
  • 包括系统提示、对话历史、检索上下文、当前输入
  • Token 数随对话增长而增加

解决方案

  1. 截断:保留最近 N 轮,丢弃更早的
  2. 滑动窗口:保持 Token 总数不超过阈值
  3. 摘要压缩:将旧对话压缩为摘要
  4. 重要性筛选:只保留高重要性对话
  5. 混合策略:摘要 + 最近对话

Q2: 为什么不能把所有信息都放进 Context Window?

答案要点

  1. 成本问题

    • 输入 Token 按量计费
    • 长上下文会显著增加 API 成本
  2. 注意力分散

    • 过多无关信息会稀释注意力
    • 模型可能"迷失"在长上下文中
  3. 推理质量下降

    • 实验表明,过长上下文会降低回答质量
    • "Lost in the Middle" 现象
  4. 响应延迟

    • 处理长上下文需要更多计算时间
    • 用户等待时间增加

Q3: ConversationBufferWindowMemory 和 ConversationSummaryMemory 有什么区别?

答案要点

特性BufferWindowSummary
保留方式保留最近 N 轮原文将旧对话压缩为摘要
信息完整性高(原文)低(摘要可能丢失细节)
Token 效率一般高(压缩后更少 Token)
适用场景短对话、需要精确上下文长对话、关注关键信息
成本较高(存储原文)较低(摘要后更少 Token)

Q4: 如何判断应该保留哪些对话历史?

答案要点

判断标准:
1. 重要性:包含关键决策、用户偏好的对话更重要
2. 相关性:与当前话题相关的对话更重要
3. 时效性:最近的对话通常更重要
4. 信息密度:信息量大的对话更重要

实现方式:
• 规则判断:基于关键词、句式规则
• LLM 评估:让 LLM 给对话打重要性分
• 向量相似度:与当前问题的相似度越高越重要
• 混合策略:综合多个维度打分

Q5: 长上下文模型(如 Claude 200K)还需要短期记忆管理吗?

答案要点

仍然需要,原因如下:

  1. 成本考量

    • 200K Token 的输入成本很高
    • 精准管理可显著降低成本
  2. 注意力问题

    • 长上下文仍有"Lost in the Middle"问题
    • 关键信息放在开头/结尾效果更好
  3. 无限历史

    • 用户与 Agent 交互历史可能超过任何窗口
    • 长期记忆 + 检索仍必要
  4. 响应效率

    • 处理 200K Token 比处理 10K Token 慢很多
    • 精简上下文提升响应速度

七、总结

核心概念回顾

概念定义关键要点
短期记忆Context Window 中的上下文信息直接参与推理,容量有限
上下文结构System + History + Retrieved + Input四部分组成完整上下文
容量管理确保不超过 Token 限制截断、滑动窗口、摘要压缩
质量优化保留重要信息,丢弃噪声重要性评估、关键事实提取

一句话总结

短期记忆是 Agent 的"工作台",通过合理的容量管理和质量优化,在有限 Context Window 内保持对话连贯性和推理质量。

设计口诀

短期记忆管理口诀:
容量有限要规划,系统历史加检索
滑动窗口保最近,摘要压缩存精华
重要信息优先留,无关噪声及时丢
长窗口虽好,成本质量都要顾

最后更新:2026年3月18日