菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > AI创作与模型 > 2024从零打造AI Agent记忆功能新手必读实战指南
模型技术

2024从零打造AI Agent记忆功能新手必读实战指南

2026-05-30
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

为AIAgent设计记忆系统,实现用户信息、反馈与项目上下文的持久化存储。通过MemoryManager管

1. 开篇导读

上一篇文章我们搭建了一个可运行的最小化 AI Agent,但有一个棘手的问题:每次重启程序,Agent 瞬间丢失所有上下文,完全不知道用户是谁、有什么偏好。

从零打造 AI Agent (二)—— 让 AI 拥有记忆

本文正是为了解决这个痛点——为 Agent 植入持久化记忆系统,使其能在多轮会话间持续保留用户画像与关键信息。


2. 记忆系统架构设计

2.1 核心功能需求

设计记忆系统前,必须先明确必须满足的四大条件:

  1. 持久化存储:程序关闭后重启,记忆不会丢失
  2. 分类管理:用户信息、项目上下文、反馈纠错,各归其位
  3. 安全操作:追加模式比覆盖模式更稳妥,避免数据意外被抹除
  4. 动态加载:每次对话自动读取最新记忆,无需手动介入

2.2 文件组织方式

文件如何布局?直接看目录结构一目了然:

.claude/memory/
├── user.md       # 用户角色与偏好信息
├── feedback.md   # 用户反馈与纠正记录
└── project.md    # 项目上下文背景

2.3 文件格式选型

格式采用 frontmatter + Markdown 组合。既能保证人类可读性,又能承载结构化元数据:

---
name: user-role
description: 用户角色描述
metadata:
  type: user
---# 用户角色- 职业:后端开发者
- 技能:Go 语言
- 语言偏好:中文

3. 核心实现细节

3.1 MemoryManager 类

记忆管理的核心是 MemoryManager 类。它负责操控 .claude/memory/ 目录下的全部记忆文件:

class MemoryManager:
    """
    记忆管理器核心类
    负责 .claude/memory/ 目录下记忆文件的读写追加
    """    def __init__(self, memory_dir: str = ".claude/memory"):
        self.memory_dir = Path(memory_dir)
        self._ensure_memory_dir()    def load(self, memory_type: str) -> str | None:
        """加载指定类型的记忆内容"""
        path = self._get_memory_path(memory_type)
        if not path.exists():
            return None        content = path.read_text(encoding='utf-8')
        _, body = self._parse_frontmatter(content)
        return body.strip()    def append(self, memory_type: str, new_lines: str) -> bool:
        """追加新内容到现有记忆(保留原有记录)"""
        path = self._get_memory_path(memory_type)
        existing = path.read_text(encoding='utf-8')
        metadata, body = self._parse_frontmatter(existing)        # 拼接新内容到原有文本之后
        if body.strip():
            updated_body = f"{body.rstrip()}n{new_lines}"
        else:
            updated_body = new_lines        return self.sa ve(memory_type, metadata.get("name", memory_type),
                         metadata.get("description", ""), updated_body)

3.2 Frontmatter 解析逻辑

Frontmatter 的解析并不复杂,利用正则匹配即可实现:

def _parse_frontmatter(self, content: str) -> tuple[dict, str]:
    """解析 frontmatter 元数据与正文"""
    pattern = r'^---n(.*?)n---n(.*)$'
    match = re.match(pattern, content, re.DOTALL)    if match:
        frontmatter_text = match.group(1)
        body = match.group(2)
        metadata = {}        for line in frontmatter_text.split('n'):
            if ':' in line:
                key, value = line.split(':', 1)
                metadata[key.strip()] = value.strip().strip('"')        return metadata, body    return {}, content

4. 工具集成方案

4.1 新增三个记忆工具

为了让 Agent 能够操控记忆系统,需要注册三个工具。它们分工明确:

工具功能使用建议
read_memory读取记忆查询专用
write_memory覆盖记忆谨慎使用,会丢失旧数据
append_memory追加记忆首选方案

4.2 工具注册示例

工具注册代码简洁明晰,以 append_memory 为例:

# append_memory 工具(推荐使用)
registry.register(Tool(
    name="append_memory",
    description="将新内容追加到现有记忆(保留原有数据,推荐使用)",
    parameters={
        "type": {"type": "string", "description": "记忆类型: user, feedback, project"},
        "content": {"type": "string", "description": "要追加的内容"},
    },
    handler=ToolHandlers.append_memory
))

4.3 工具实现逻辑

每个工具的 handler 实现也清晰直观。例如 append_memory 核心逻辑就是调用 MemoryManagerappend 方法:

@staticmethod
def append_memory(params: dict) -> ToolResult:
    """追加内容到现有记忆(保留原有内容)"""
    memory_type = params.get("type", "user")
    new_lines = params.get("content", "")    if not new_lines:
        return ToolResult(success=False, error="追加内容不能为空")    mm = MemoryManager()
    success = mm.append(memory_type, new_lines)    if success:
        return ToolResult(success=True, content=f"内容已追加到 {memory_type} 记忆")
    return ToolResult(success=False, error=f"追加失败: {memory_type}")

5. 上下文集成策略

5.1 动态加载记忆至系统提示

记忆系统要想真正发挥价值,必须无缝集成到 Agent 的对话上下文中。通过 ContextManager 实现动态加载:

class ContextManager:
    def __init__(self, memory_dir: str = ".claude/memory"):
        self.memory = MemoryManager(memory_dir)
        self.base_system_prompt = """你是一个智能 AI Agent...
        重要规则:
        - 如果用户提供了重要的角色、偏好或反馈,使用 append_memory 工具追加到记忆中
        """    def get_system_prompt(self) -> str:
        """获取系统提示(携带当前记忆)"""
        memories = self.memory.load_all()
        memory_section = format_memories_for_system_prompt(memories)        if memory_section:
            return f"{self.base_system_prompt}nn{memory_section}"
        return self.base_system_prompt

5.2 记忆格式化处理

加载出的记忆需要做格式化,才能自然地嵌入到系统提示中:

def format_memories_for_system_prompt(memories: list[MemoryInfo]) -> str:
    """将记忆格式化为系统提示的一部分"""
    if not memories:
        return ""    sections = ["## 记忆n"]    for mem in memories:
        section = f"### {mem['type'].capitalize()} 记忆 ({mem['name']})n"
        if mem['description']:
            section += f"{mem['description']}nn"
        section += mem['content']
        sections.append(section)    return "nn".join(sections)

6. 踩坑与解决方案

6.1 问题:覆盖操作导致数据丢失

开发过程中踩了一个典型坑。先看现象:

用户: 我是后端开发者,擅长 Go 语言
用户: 我希望你用中文回复

结果记忆文件中只保留了“语言偏好:中文”,职业信息丢失。

根本原因很明确:write_memory 是覆盖模式,第二次调用直接抹掉了第一次的内容。

解决方案也很直接:

  1. 新增 append_memory 追加模式
  2. 在系统提示中强调“不要覆盖,请使用追加”
  3. append_memory 标记为推荐工具

追加模式的实现代码:

# 追加模式实现
def append(self, memory_type: str, new_lines: str) -> bool:
    existing = self.load(memory_type)
    if existing:
        new_content = f"{existing}n{new_lines}"
    else:
        new_content = new_lines
    return self.sa ve(memory_type, new_content)

7. 实际运行效果

7.1 测试对话流程

来看看实际跑起来的效果:

用户: 我是后端开发者,擅长 Go 语言
Agent: 已将您的职业信息记录到记忆中。
       [调用 append_memory(type="user", content="- 职业:后端开发者n- 技能:Go 语言")]用户: 我希望你用中文回复
Agent: 已记录您的语言偏好。
       [调用 append_memory(type="user", content="- 语言偏好:中文")]用户: 再加一条,我喜欢用 Tmux
Agent: 已记录。
       [调用 append_memory(type="user", content="- 工具偏好:Tmux")]

7.2 最终记忆文件

经过三轮对话,生成的记忆文件内容如下:

---
name: user-role
description: 用户角色描述
metadata:
  type: user
---# 用户角色- 职业:后端开发者
- 技能:Go 语言
- 语言偏好:中文
- 工具偏好:Tmux

可见所有信息都被完整保留,且每一条都是通过追加写入的。

7.3 重启验证

最关键的一步——重启程序,验证它是否还能记住:

$ python main.py用户: 你知道我是做什么的吗?
Agent: 根据我的记忆,您是一位后端开发者,擅长 Go 语言。
       您偏好使用中文交流,并且喜欢用 Tmux 作为终端工具。

成功了。即使程序重启,Agent 也能准确调取之前记录的所有信息。


8. 架构总览

最后,将整套系统的架构图展示出来,方便对照理解:

┌─────────────────────────────────────────────────────────┐
│                      Agent                              │
│                   (ReAct 核心循环)                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │LLMClient    │  │ToolRegistry │  │ContextManager   │  │
│  │(LLM 交互)   │  │(工具系统)   │  │(上下文管理)     │  │
│  └─────────────┘  └──────┬──────┘  └────────┬────────┘  │
│                          │                  │           │
│                          ▼                  │           │
│                   ┌─────────────┐           │           │
│                   │ToolHandlers │           │           │
│                   │+memory tools│           │           │
│                   └─────────────┘           │           │
│                                             ▼           │
│                    ┌─────────────────────────────────┐ │
│                    │         MemoryManager          │ │
│                    │   .claude/memory/*.md          │ │
│                    └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

围绕 ReAct 核心循环,ContextManagerMemoryManager 拉取记忆,并将其注入到系统提示中。ToolRegistry 则注册了三个记忆工具,供 Agent 在运行中随时读写。


9. 后续规划

记忆系统稳定运行后,接下来的里程碑是 Plan Mode——让 Agent 在执行复杂任务前,先学会制定和执行计划。这将显著提升它的自主决策能力与可靠性。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多