AI Agent 的记忆系统怎么设计?从短期记忆到长期记忆,我踩过的 6 个坑

适合正在开发 AI Agent、想让 Agent "记住"历史对话和用户偏好的开发者。
本文讲解 AI Agent 记忆系统的 3 层架构设计,附 Python 实现代码。

为什么 Agent 需要记忆

没有记忆的 AI Agent 就像一个每天失忆的人——你今天告诉它"我喜欢简洁的写作风格",明天它就忘了,又写一堆废话。

记忆系统解决的核心问题:

问题 没有记忆 有记忆
用户偏好 每次重新交代 自动记住
历史上下文 只看当前对话 能回忆过去
知识积累 每次从零开始 持续学习
个性化 千人一面 越用越懂你

记忆系统的 3 层架构

┌─────────────────────────────────────┐
│         长期记忆(Long-term)         │  用户画像、偏好、历史知识
├─────────────────────────────────────┤
│         工作记忆(Working)           │  当前任务的上下文
├─────────────────────────────────────┤
│         感官记忆(Sensory)           │  最近几轮对话原文
└─────────────────────────────────────┘

感官记忆:最近几轮对话

最简单的记忆,就是把最近 N 轮对话原文塞进 prompt。

class SensoryMemory:
    """感官记忆:保存最近 N 轮对话"""

    def __init__(self, max_turns=10):
        self.history = []
        self.max_turns = max_turns

    def add(self, role, content):
        self.history.append({"role": role, "content": content})
        # 超过上限,删除最早的
        if len(self.history) > self.max_turns * 2:
            self.history = self.history[-self.max_turns * 2:]

    def get_context(self):
        """返回最近的对话历史"""
        return self.history

    def clear(self):
        self.history = []

问题:对话越来越长,token 超限。10 轮对话可能就占了 3000 token。

工作记忆:当前任务上下文

工作记忆保存当前正在做的事情的关键信息,不是对话原文,而是摘要

class WorkingMemory:
    """工作记忆:当前任务的关键信息摘要"""

    def __init__(self):
        self.summary = ""
        self.current_task = ""
        self.key_facts = []

    def update(self, task, facts):
        """更新工作记忆"""
        self.current_task = task
        self.key_facts = facts
        self.summary = f"当前任务: {task}\n关键信息: {', '.join(facts)}"

    def get_context(self):
        """返回工作记忆上下文"""
        if not self.summary:
            return ""
        return f"[工作记忆]\n{self.summary}"

    def add_fact(self, fact):
        """添加一个关键信息"""
        if fact not in self.key_facts:
            self.key_facts.append(fact)
            self.summary = f"当前任务: {self.current_task}\n关键信息: {', '.join(self.key_facts)}"

长期记忆:用户画像和历史知识

长期记忆存在外部存储(数据库/文件),包含用户偏好、历史交互总结、学到的知识。

import json
from pathlib import Path

class LongTermMemory:
    """长期记忆:持久化存储用户画像和历史知识"""

    def __init__(self, storage_path="memory.json"):
        self.path = Path(storage_path)
        self.data = self._load()

    def _load(self):
        if self.path.exists():
            return json.loads(self.path.read_text(encoding="utf-8"))
        return {"user_profile": {}, "preferences": [], "learned": []}

    def _save(self):
        self.path.write_text(json.dumps(self.data, ensure_ascii=False, indent=2), encoding="utf-8")

    def add_preference(self, key, value):
        """记录用户偏好"""
        self.data["preferences"] = [p for p in self.data["preferences"] if p["key"] != key]
        self.data["preferences"].append({"key": key, "value": value})
        self._save()

    def add_learned(self, knowledge):
        """记录学到的知识"""
        if knowledge not in self.data["learned"]:
            self.data["learned"].append(knowledge)
            self._save()

    def get_context(self):
        """返回长期记忆上下文"""
        parts = []
        if self.data["preferences"]:
            prefs = [f"{p['key']}: {p['value']}" for p in self.data["preferences"]]
            parts.append(f"[用户偏好]\n" + "\n".join(prefs))
        if self.data["learned"]:
            parts.append(f"[历史知识]\n" + "\n".join(self.data["learned"][-10:]))  # 最近 10 条
        return "\n\n".join(parts)

3 层记忆组合使用

class AgentMemory:
    """Agent 记忆系统:3 层组合"""

    def __init__(self):
        self.sensory = SensoryMemory(max_turns=10)
        self.working = WorkingMemory()
        self.long_term = LongTermMemory()

    def add_turn(self, role, content):
        """添加一轮对话"""
        self.sensory.add(role, content)

    def build_prompt(self, system_prompt):
        """组装完整的 prompt,包含所有记忆层"""
        messages = [{"role": "system", "content": system_prompt}]

        # 长期记忆(放在 system prompt 里)
        lt_ctx = self.long_term.get_context()
        if lt_ctx:
            messages[0]["content"] += f"\n\n{lt_ctx}"

        # 工作记忆
        wk_ctx = self.working.get_context()
        if wk_ctx:
            messages[0]["content"] += f"\n\n{wk_ctx}"

        # 感官记忆(最近对话)
        messages.extend(self.sensory.get_context())

        return messages

    def learn_from_conversation(self):
        """从对话中提取值得记住的信息"""
        # 简化实现:让 LLM 总结对话中的关键信息
        recent = self.sensory.get_context()
        if len(recent) < 4:
            return

        summary_prompt = f"""从以下对话中提取值得长期记住的信息(用户偏好、关键知识)。
只输出 JSON 格式:
{{"preferences": [{{"key": "xxx", "value": "xxx"}}], "learned": ["xxx"]}}

对话:
{json.dumps(recent[-6:], ensure_ascii=False)}"""

        # 调用 LLM 提取(这里简化处理)
        # result = local_chat(summary_prompt)
        # parsed = json.loads(result)
        # for p in parsed.get("preferences", []):
        #     self.long_term.add_preference(p["key"], p["value"])
        pass

使用示例

# 初始化
memory = AgentMemory()

# 模拟对话
memory.add_turn("user", "帮我写一篇关于 Python 的文章,风格要口语化")
memory.add_turn("assistant", "好的,我来写一篇口语化的 Python 文章...")
memory.add_turn("user", "不错,但代码注释太少了")
memory.add_turn("assistant", "明白了,以后代码我会加更多注释")

# 记住用户偏好
memory.long_term.add_preference("写作风格", "口语化")
memory.long_term.add_preference("代码要求", "需要详细注释")

# 下次对话时,Agent 自动知道用户的偏好
messages = memory.build_prompt("你是一个技术写作助手")
# messages 会包含:[系统提示 + 用户偏好 + 工作记忆 + 最近对话]

记忆压缩:对话太长怎么办

对话超过 20 轮后,token 会超限。这时候需要压缩:把旧对话总结成摘要,只保留最近几轮原文。

def compress_history(history, keep_recent=6):
    """压缩对话历史:旧的总结成摘要,最近的保留原文"""
    if len(history) <= keep_recent:
        return history

    old = history[:-keep_recent]
    recent = history[-keep_recent:]

    # 让 LLM 总结旧对话
    old_text = json.dumps(old, ensure_ascii=False)
    summary_prompt = f"用 100 字总结这段对话的要点:\n{old_text}"
    summary = local_chat(summary_prompt)

    # 用摘要替代旧对话
    compressed = [{"role": "system", "content": f"[历史摘要] {summary}"}]
    compressed.extend(recent)

    return compressed

踩坑记录

坑 1:记忆太多,prompt 超限

症状:长期记忆存了几百条,全部塞进 prompt 直接超 token 限制。

原因:没有限制记忆的长度。

解决:长期记忆只取最近 10 条,偏好只取 top 5 最重要的。

坑 2:记忆过时

症状:用户 3 个月前说"我喜欢蓝色",现在说"我喜欢红色",Agent 还是推荐蓝色。

原因:旧偏好没有被更新,新旧共存。

解决:偏好用 key-value 结构,同 key 的自动覆盖旧值。

坑 3:记忆冲突

症状:用户说"我喜欢简洁",但后来又说"这篇文章太短了,要详细点"。两个偏好矛盾。

原因:没有冲突检测和解决机制。

解决:新偏好优先。或者在 prompt 里告诉 Agent"如果偏好有冲突,以最新的为准"。

坑 4:从对话中自动提取记忆不准

症状:让 LLM 自动总结对话中的关键信息,经常提取错误或者遗漏。

原因:LLM 的总结能力有限,尤其是长对话。

解决:不要完全自动,关键偏好让用户手动确认。或者用更简单的规则提取(正则匹配关键词)。

坑 5:隐私问题

症状:Agent 记住了用户的敏感信息(手机号、地址),存在文件里不安全。

原因:没有做敏感信息过滤。

解决:提取记忆时加一层过滤,手机号、身份证号等不存入长期记忆。

坑 6:多用户记忆混淆

症状:同一个 Agent 服务多个用户,把 A 的偏好用在了 B 身上。

原因:记忆没有按用户隔离。

解决:每个用户一个独立的记忆文件/数据库,按 user_id 隔离。

总结

3 条核心经验:

  1. 3 层记忆各司其职。感官记忆管最近对话,工作记忆管当前任务,长期记忆管用户画像。不要混在一起。

  2. 记忆要压缩。对话超过 20 轮就总结旧的,只保留最近几轮原文。否则 token 会爆。

  3. 新偏好覆盖旧偏好。用户今天说的比 3 个月前说的更重要。用 key-value 结构自动覆盖。


你在开发 AI Agent 时遇到过记忆相关的问题吗?评论区交流。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐