第 15 章《记忆与 Dream 整合》· nanobot Dream 记忆整合源码深度解析:真实 git diff 当 commit message

本文回答什么问题:nanobot 怎么从消息流提取长期记忆?MEMORY.md 怎么生成?Dream 后台任务是什么?git diff 当 commit message 是怎么实现的?

目标读者 :LLM Agent 开发者 / 想自定义记忆机制的工程师

预计阅读时间 :12 分钟

源码版本 :GitHub HKUDS/nanobot main 分支主线代码(仓库相对路径)

MemoryStore + Consolidator(nanobot/agent/memory.py)负责把短期消息流提炼成长期记忆。本章聚焦"Dream 后台任务"和"git diff 当 commit message"这两个特色设计。

1. 整体定位:为什么需要 Memory

SessionManager 存的是"原始消息流"------线性增长,1 周 1000 条消息。Memory 解决:

  • 提炼关键事实("用户偏好 dark mode" / "项目用 Python 3.11")
  • 跨 session 共享(同一用户多个 chat_id 共用记忆)
  • 压缩 System Prompt 占用(详见第 12 章 8 段中的 memory)

核心要点速查(建议收藏)

  • 核心文件 :nanobot/agent/memory.py(约 250 行)+ nanobot/session/goal_state.py(目标状态)
  • 存储位置 :~/.nanobot/memory/MEMORY.md(全局记忆)+ 每个 workspace 的 MEMORY.md
  • Dream 后台任务 :每 30 分钟跑一次(Config.dream_interval)
  • 生成方式:LLM 提取关键事实 → 写入 MEMORY.md → git commit(用真实 diff)
  • commit message = 上次 commit 之后的实际 git diff(不是 AI 生成的描述!)

2. MemoryStore

python 复制代码
class MemoryStore:
    def __init__(self, workspace: Path):
        self.path = workspace / "MEMORY.md"
        self._lock = asyncio.Lock()

    async def read(self) -> str:
        if not self.path.exists():
            return ""
        return self.path.read_text(encoding="utf-8")

    async def write(self, content: str) -> None:
        # 原子写
        tmp = self.path.with_suffix(".tmp")
        async with self._lock:
            tmp.write_text(content, encoding="utf-8")
            tmp.replace(self.path)

关键 :asyncio.Lock 防止 Dream 任务 + 写入并发冲突。

3. Consolidator(Dream 后台任务)

python 复制代码
class Consolidator:
    """每 30 分钟跑一次,从消息流提炼长期记忆。"""

    def __init__(self, sessions: SessionManager, memory: MemoryStore, llm: LLMProvider):
        self.sessions = sessions
        self.memory = memory
        self.llm = llm

    async def consolidate(self) -> None:
        # 1. 取上次 consolidate 后的所有新消息
        last_checkpoint = self._last_consolidate_time()
        new_messages = await self.sessions.get_after(last_checkpoint, limit=500)

        if not new_messages:
            return

        # 2. 调 LLM 提炼
        prompt = f"""以下是新的对话历史,提炼出 5-10 条关键事实,每条 ≤ 50 字。
        只输出事实清单,不要其他内容。\n\n{format_messages(new_messages)}"""
        facts = await self.llm.chat([Message(role="user", content=prompt)])

        # 3. 合并到现有 MEMORY.md
        old = await self.memory.read()
        new = old + "\n\n## " + datetime.now().strftime("%Y-%m-%d") + "\n\n" + facts.content

        # 4. 写文件 + git commit
        await self.memory.write(new)
        await self._git_commit()

4. 真实 git diff 当 commit message

python 复制代码
async def _git_commit(self) -> None:
    if not self.memory.path.parent.exists():
        return

    # 检查是否在 git 仓库
    if not (self.memory.path.parent / ".git").exists():
        return  # 用户没 init git,跳过

    # 用真实 diff 做 commit message
    diff = subprocess.check_output(
        ["git", "diff", "HEAD", "--", "MEMORY.md"],
        cwd=self.memory.path.parent,
        encoding="utf-8",
    )
    if not diff.strip():
        return

    subprocess.run(["git", "add", "MEMORY.md"], cwd=self.memory.path.parent, check=True)
    subprocess.run(
        ["git", "commit", "-m", diff],  # 真实 diff 当 message
        cwd=self.memory.path.parent,
        check=True,
    )

为什么用真实 diff 而不是 LLM 生成的描述?

  • 真实性 :git log 看的是真实改了啥,不是 AI 编的故事
  • 可审计 :看 git log -p MEMORY.md 一目了然------事实是怎么进化的
  • 省 token:不调 LLM 生成 message

5. 实战:启用 Dream

bash 复制代码
# ~/.nanobot/memory/ 初始化 git
mkdir -p ~/.nanobot/memory
cd ~/.nanobot/memory
git init

# config.yaml
memory:
  dream_interval_seconds: 1800  // 默认 30 分钟
  dream_facts_limit: 10         // 每次提炼 ≤ 10 条事实

重启 gateway 后,Dream 任务自动后台运行。

6. 实战:手动触发

bash 复制代码
# CLI 触发一次 consolidate
nanobot config --consolidate-memory

或者 WebUI "Dream now" 按钮。

7. 4 个常见误区

误区 1 · Dream 任务会消耗很多 token?

A:每次最多提炼 500 条新消息 → LLM 一次 chat ~ 2000 tokens。30 分钟一次,日耗 ~ 100k tokens(约 $0.2-0.5)。

误区 2 · MEMORY.md 会无限增长?

A :!建议每周手动 git log -p 看变化,删除过期事实。或者用 nanobot config --prune-memory

误区 3 · git init 忘了怎么办?

A :nanobot install --init-memory-git 一键初始化。

误区 4 · 多 workspace 共享 MEMORY.md?

A :------每个 workspace 独立 MEMORY.md。要共享用 Config.memory_shared_path 全局覆盖。

8. 小结

  • Dream 后台任务 每 30 分钟跑一次
  • 关键模块:MEMORY.md 存在 workspace 内
  • 设计要点**:git commit 用真实 diff 当 message
  • 常见坑**:手动触发 nanobot config --consolidate-memory

本文要点速查

  1. 3 个组件 见 §2-4:MemoryStore / Consolidator / Dream
  2. 真实 git diff 见 §4(特色设计!)
  3. 4 个误区 见 §7
  4. 下一步:第 16 章《自动压缩 AutoCompact》------ 长会话怎么摘要

按角色推荐

  • LLM Agent 开发者:必读(理解记忆机制必读)
  • 系统架构师:必读(Dream 后台 + git commit 设计必读)
  • LLM Provider 适配者:选读
  • 聊天通道开发者:选读
  • Tool / MCP 工具开发者:选读

下一步

  • 第 16 章《自动压缩 AutoCompact》 ------ session 满了怎么自动摘要(主题群"Agent 核心",第 3 周)

tags :#nanobot #AI Agent #LLM #Python #源码解析 #记忆 #Dream #git

相关推荐
orient.lu18 小时前
第 14 章《会话管理 SessionManager》· 会话管理怎么做?SessionManager 原子写 + fsync 持久化实战(nanobot)
session·nanobot
liulilittle1 天前
LLM 推理引擎与内核系统工程原理
c++·ai·llm·内存·memory·core·kernel
zzz_23687 天前
TencentDB-Agent-Memory 深度解析:让多个 Agent 共享项目经验的记忆中枢
java·开发语言·jvm·人工智能·agent·memory·tencent db
UWA9 天前
隐藏视频变“常驻刺客”,VideoPlayer与“N/A”纹理该怎么查
人工智能·性能优化·音视频·memory·cpu·游戏开发
来日方长。。。。long11 天前
橙皮书共读|Hermes Agent(二)深度拆解五大核心支柱:自进化智能体的运行内核
memory·自我进化·harmes
knqiufan25 天前
AI 情报局:用 PowerMem + SeekDB 做一个多 Agent 记忆小游戏
memory·seekdb·deepagents·powermem
chanalbert1 个月前
Agent 工程化指南(二):记忆与规划 — 让 Agent “记得住“且“做得对“
agent·memory·rag·mcp
一个处女座的程序猿1 个月前
Agent之Memory:claude-mem的简介、安装和使用方法、案例应用之详细攻略
agent·memory·claude-mem
UWA1 个月前
资源回收“两头堵”:RUUA调了会卡,不调内存又涨
性能优化·memory·游戏开发