课程0基础Agent开发课 / Agent基础 / Agent的记忆系统-短期记忆与长期记忆
— 13 min read

Agent的记忆系统-短期记忆与长期记忆

LLM 有一个基本的物理限制:上下文窗口(Context Window)。模型在每次推理时只能"看到"有限数量的 token——GPT-4o 是 128k,Claude 是 200k,即便是最大的模型也有上限。

Agent 的记忆系统:短期记忆与长期记忆

为什么 Agent 需要记忆:上下文窗口的根本限制

LLM 有一个基本的物理限制:上下文窗口(Context Window)。模型在每次推理时只能"看到"有限数量的 token——GPT-4o 是 128k,Claude 是 200k,即便是最大的模型也有上限。

这个限制带来了一个严重问题:Agent 的"记忆"天然是有界的

如果把所有历史信息都塞进上下文,很快就会撑爆窗口。如果只保留最近的对话,早期的关键信息就会丢失。一个用户在第 1 轮告诉 Agent "我是 Java 工程师",第 50 轮问"帮我写一个示例"时,Agent 如果因为上下文窗口限制已经"忘记"了用户的技术背景,给出的代码就会南辕北辙。

记忆是解决上下文窗口限制的根本方案

如果把上下文窗口比作人的"工作记忆"(短期、有限、高速),那么 Agent 需要的是:

  • 能长期保存的存储(像人类的长期记忆)
  • 能按需检索的机制(而不是把所有东西都塞进工作记忆)
  • 能区分"当前任务需要"和"背景知识"的智能(按重要性分配有限的上下文空间)

这就是记忆系统要解决的问题。设计好的记忆系统,Agent 才能从一个"会话孤岛"变成一个真正意义上的持续存在的助手。

Agent 记忆系统架构

图:Agent 的三层记忆架构——短期记忆(当前对话上下文,在上下文窗口内)、长期记忆(向量数据库持久化存储)、工具记忆(工具调用结果缓存),三者协同让 Agent 突破上下文窗口限制。


本章介绍 Agent 的记忆架构,包括四种记忆类型及其实现方式,以及记忆检索策略的设计决策。

没有长期记忆的 Agent,每次都从零开始。它没有成长,没有积累,永远是第一天上班的样子。记忆系统是 Agent 从"工具"变成"助手"的关键差异。

人类记忆的四种类型

认知科学把人类记忆分成几个层次,LLM-based Agent 的记忆设计几乎和这个框架一一对应。理解这个对应关系,能帮助我们在做技术选型时找到正确的参照系——不是从"有哪些存储方案"出发,而是从"这种记忆的特性是什么"出发。

感知记忆(Sensory Memory)

持续时间极短,不到一秒。视觉输入先进入感知记忆,如果持续关注,才会进入工作记忆。

对应 Agent:当前 token 输入,模型正在处理的即时信息,也就是当前这一次推理的输入。处理完就消失了。

工作记忆(Working Memory)

短期内能主动处理的信息,容量有限(著名的"7±2"规则)。心算 37×48 的时候用的就是工作记忆,它保持中间结果,处理完就清空。

对应 Agent:当前对话的完整上下文,整个任务执行过程中的状态。在 LangGraph(LangChain 旗下的 Agent 工作流框架,用图结构管理有状态的 Agent 执行过程)里,这就是 State 对象。

情节记忆(Episodic Memory)

具体事件的记忆。"上周三下午讨论了架构方案"——这是情节记忆。它记录的是"什么时候、什么地点、发生了什么"。

对应 Agent:过去执行任务的具体记录,"上次处理这类财报分析时,先搜索了行业数据,发现效果不好,后来改成直接读 PDF 更准确"。存储在向量数据库里,按语义相似性检索。

语义记忆(Semantic Memory)

通用知识和规则,不依赖具体情境。"Python 的 GIL 锁会阻止多线程真正并行"——这是语义记忆。

对应 Agent:外部知识库,RAG 文档,公司内部的技术文档、规范、FAQ。也存储在向量数据库里,但内容是结构化知识,不是个人经历。

四种记忆的实现

用户输入

感知记忆
当前 token 输入

工作记忆
对话历史 + 任务状态
LangGraph State

Agent 推理

需要历史经验?

情节记忆
向量数据库
语义检索

需要外部知识?

语义记忆
RAG 知识库
向量检索

行动执行

保存到情节记忆

工作记忆:LangGraph State

工作记忆是 Agent 执行任务时的运行时状态。在代码里,它对应一个在整个任务生命周期内持续存在的状态对象。

python
from typing import TypedDict, Annotated, List
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_core.messages import HumanMessage, AIMessage

class AgentState(TypedDict):
    # 对话历史(工作记忆的核心)
    messages: Annotated[List, add_messages]
    # 当前任务的中间结果
    task_context: dict
    # 已执行的步骤记录
    steps_taken: List[str]
    # 最终结果
    final_result: str

def create_agent_graph():
    graph = StateGraph(AgentState)

    def think_node(state: AgentState) -> AgentState:
        # 工作记忆在整个执行过程中持续传递
        messages = state["messages"]
        context = state.get("task_context", {})
        steps = state.get("steps_taken", [])

        # 模型能看到完整的对话历史和任务状态
        print(f"当前已执行步骤:{steps}")
        print(f"工作记忆中的消息数:{len(messages)}")

        return state

    graph.add_node("think", think_node)
    graph.add_edge(START, "think")
    graph.add_edge("think", END)

    return graph.compile()

情节记忆:向量数据库存储经验

情节记忆让 Agent 能从过去的经历中学习。每次完成任务,把执行过程和结果存下来;下次遇到类似任务,先检索相关经验。代码中使用 ChromaDB(一个轻量级的开源向量数据库,适合本地开发和原型验证)存储经验记录。

python
from openai import OpenAI
import chromadb
import json
from datetime import datetime

client = OpenAI()
chroma_client = chromadb.Client()
collection = chroma_client.get_or_create_collection(name="agent_episodes")

def save_episode(task: str, approach: str, result: str, quality_score: float):
    """保存一次任务执行经历到情节记忆"""
    episode = {
        "task": task,
        "approach": approach,
        "result_summary": result,
        "quality_score": quality_score,
        "timestamp": datetime.now().isoformat()
    }

    # 用任务描述作为向量化内容,方便语义检索
    collection.add(
        documents=[task],
        metadatas=[episode],
        ids=[f"episode_{datetime.now().timestamp()}"]
    )
    print(f"已保存执行经历,质量评分:{quality_score}")

def retrieve_relevant_episodes(current_task: str, n_results: int = 3) -> List[dict]:
    """检索与当前任务相似的历史经历"""
    results = collection.query(
        query_texts=[current_task],
        n_results=n_results
    )

    episodes = []
    if results["metadatas"]:
        for metadata in results["metadatas"][0]:
            episodes.append(metadata)

    return episodes

def agent_with_episodic_memory(task: str) -> str:
    # 先检索相关历史经验
    past_episodes = retrieve_relevant_episodes(task)

    memory_context = ""
    if past_episodes:
        memory_context = "以下是处理类似任务的历史经验:\n"
        for ep in past_episodes:
            score = ep.get("quality_score", 0)
            approach = ep.get("approach", "")
            # 只参考质量高的经验
            if score >= 0.7:
                memory_context += f"- 任务类型:{ep['task'][:50]}...\n"
                memory_context += f"  采用方案:{approach}\n"
                memory_context += f"  质量评分:{score}\n\n"

    messages = [
        {
            "role": "system",
            "content": f"你是一个有经验的分析助手。{memory_context}"
        },
        {"role": "user", "content": task}
    ]

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )
    result = response.choices[0].message.content

    # 执行完成后,保存这次经历
    save_episode(
        task=task,
        approach="直接分析 + 历史经验参考",
        result=result[:200],
        quality_score=0.8  # 实际场景应该由 Critic 评分
    )

    return result

语义记忆:RAG 知识库

语义记忆是 Agent 的"外脑",存放它需要但不可能全放进上下文的知识。

python
import chromadb
from openai import OpenAI

client = OpenAI()
chroma_client = chromadb.Client()
knowledge_base = chroma_client.get_or_create_collection(name="semantic_memory")

def add_knowledge(content: str, source: str, category: str):
    """向知识库添加内容"""
    knowledge_base.add(
        documents=[content],
        metadatas=[{"source": source, "category": category}],
        ids=[f"doc_{hash(content)}"]
    )

def retrieve_knowledge(query: str, n_results: int = 3) -> str:
    """从知识库检索相关内容"""
    results = knowledge_base.query(
        query_texts=[query],
        n_results=n_results
    )

    if not results["documents"] or not results["documents"][0]:
        return ""

    retrieved_docs = []
    for doc, metadata in zip(results["documents"][0], results["metadatas"][0]):
        retrieved_docs.append(f"[来源:{metadata['source']}]\n{doc}")

    return "\n\n---\n\n".join(retrieved_docs)

# 预先加载公司内部知识
add_knowledge(
    content="代码审查时,关注以下高风险模式:1. SQL 拼接(SQL 注入风险)2. 未加密的敏感数据存储 3. 未验证的用户输入直接传递给命令行",
    source="安全规范文档 v2.1",
    category="security"
)

def rag_agent(question: str) -> str:
    # 从语义记忆检索相关知识
    relevant_knowledge = retrieve_knowledge(question)

    messages = [
        {
            "role": "system",
            "content": f"你是一个代码审查专家。\n\n参考知识:\n{relevant_knowledge}"
        },
        {"role": "user", "content": question}
    ]

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages
    )
    return response.choices[0].message.content

记忆的存储层次

记忆存在哪里,直接决定了它的容量和访问速度:

存储层次 典型实现 容量 访问方式 适用场景
In-context Prompt 文本 受 context window 限制 直接访问 当前任务关键信息
内存缓存 Redis、Python dict 中等 极快 会话级状态
向量数据库 ChromaDB、Pinecone(一种全托管的云向量数据库服务) 近乎无限 语义检索 长期记忆、知识库
关系型数据库 PostgreSQL、MySQL 无限 精确查询 结构化历史记录

记忆检索:什么时候用语义检索,什么时候用精确查询

这是一个经常被忽视的设计决策。

用语义检索:当不知道确切的查询词,需要找"意思相近"的内容。比如检索"和现在这个任务类似的历史经验",或者"关于这个技术问题的相关文档"。

用精确查询:当有明确的 key 或 ID,或者需要结构化过滤。比如"查询用户 ID 12345 上周的所有操作记录",或者"找出所有质量评分大于 0.8 的执行记录"。

实际系统里通常两者结合:先语义检索缩小范围,再精确过滤。

python
def smart_memory_retrieval(query: str, min_quality: float = 0.7) -> list:
    """结合语义检索和精确过滤"""
    # 第一步:语义检索,找相似内容
    results = collection.query(
        query_texts=[query],
        n_results=10  # 先多拿一些
    )

    if not results["metadatas"]:
        return []

    # 第二步:精确过滤,只保留高质量的
    filtered = [
        metadata for metadata in results["metadatas"][0]
        if metadata.get("quality_score", 0) >= min_quality
    ]

    # 按质量评分排序
    filtered.sort(key=lambda x: x.get("quality_score", 0), reverse=True)

    return filtered[:3]  # 最多返回 3 条

记忆系统是 Agent 从"工具"变成"助手"的关键

没有记忆的 Agent 是工具:每次调用都是独立的,没有上下文,没有个性,没有积累。

有了记忆的 Agent 才算助手:它知道用户的习惯,记得上次的决策,能从失败中学习,会随时间变得更懂用户。

这是 Agent 真正落地商业场景的关键能力。一个代码审查 Agent,第一周可能漏掉一些项目特定的代码规范,但如果有情节记忆,第二周它就会记住"这个项目要特别注意这几类问题"。一个客服 Agent,如果能记住客户的历史问题和偏好,给出的答案会完全不同。

记忆系统的设计是 Agent 工程里最容易被忽视,也是最值得投入的部分。

本页目录