OpenClaw 记忆系统方案:L0/L1/L2 分层 + BM25 检索
背景
在没有结构化记忆系统之前,每次 session 都要消耗大量 token 重新建立上下文。这篇文章总结了我在 OpenClaw 上构建的轻量级记忆系统方案,可以直接移植到其他 OpenClaw 部署。
整体架构
记忆系统采用 L0/L1/L2 三层分级,配合 TTL 标签自动管理生命周期:
memory/
├── .abstract ← L0 根索引(每次 session 必读)
├── YYYY-MM-DD.md ← L2 原始日志(每天一文件)
├── insights/
│ └── YYYY-MM.md ← L1 月度提炼(L2 压缩后产物)
├── lessons/
│ └── operational-lessons.jsonl ← 运维教训(机器可读)
├── SESSION-STATE.md ← 当前 session 缓冲区
└── archive/ ← 过期 P1/P2 归档TTL 标签规则:
- [P0] — 永久保留
- [P1|expire:YYYY-MM-DD] — 90 天
- [P2|expire:YYYY-MM-DD] — 30 天
BM25 全文检索(qmd)
核心检索工具是 qmd,基于 BM25,无需 GPU,本地纯离线运行。
安装
# 需要 bun 环境
curl -fsSL https://bun.sh/install | bash
bun install -g qm-daemon
# wrapper(让 qmd 在 PATH 里)
mkdir -p ~/.local/bin
cat > ~/.local/bin/qmd << 'EOF'
#!/bin/bash
exec bun run $(which qm-daemon) "$@"
EOF
chmod +x ~/.local/bin/qmd初始化 collection
export PATH="$HOME/.local/bin:$PATH"
qmd collection create daily-logs ~/.openclaw/workspace/memory
qmd index daily-logs日常用法
qmd search "关键词" # BM25 全文检索
qmd status # 查看索引状态⚠️ 只用 qmd search(BM25),不要用 qmd embed / qmd query。后者依赖 CPU WASM 跑 GGUF 模型,在无 GPU 机器上极慢,不可用。
💡 如果部署机器有 GPU(如 RTX 3090):可以考虑开启 vector search(qmd embed + qmd query),设置 QMD_EMBED_MODEL=hf:your-gguf-model。GPU 上 embedding 速度可用,BM25 仍是推荐默认,vector 作为补充语义检索。
AGENTS.md 记忆检索协议
在 AGENTS.md 的"Every Session"部分注入以下协议,让 agent 每次启动时自动按层检索:
## 🧠 Memory Retrieval Protocol
1. Read memory/.abstract → get topic map + retrieval hints (L0)
2. Identify relevant topics → decide which files to open
3. Use qmd BM25 search → qmd search "keyword" for targeted snippets
4. Open full L1/L2 files only → when snippets are insufficient
5. After session: write new facts → memory/YYYY-MM-DD.md (L2)
6. Periodically: compact L2→L1 → insights/YYYY-MM.md + refresh .abstract
7. Respect lifecycle tags → P0=永久, P1=90天, P2=30天; archive expired自动维护 Cron
两个定期任务维持记忆系统健康运行:
memory-janitor(每天 03:00):扫描 P1/P2 过期标签,移入 archive/,刷新 .abstract。
qmd-index-refresh(每 6 小时):重建 BM25 索引,保持检索新鲜。
用 OpenClaw cron 创建 janitor 示例:
{
"schedule": { "kind": "cron", "expr": "0 3 * * *", "tz": "Asia/Shanghai" },
"payload": {
"kind": "agentTurn",
"message": "Run memory janitor: scan memory/ for expired P1/P2 entries, move them to memory/archive/, then regenerate memory/.abstract."
},
"sessionTarget": "isolated"
}MEMORY.md 长期记忆结构
MEMORY.md 是经过提炼的长期记忆,结构示例:
# MEMORY.md - Long-Term Memory (P0)
## 关键信息 [P0]
...
## 模型配置 [P0]
...
## 活跃系统 [P1|expire:YYYY-MM-DD]
...
## 里程碑
...注意:只在 main session(直接对话)加载,不在群聊/Discord 等共享场合加载,避免个人信息泄露。
关键决策与教训
- BM25 优先,不跑 embedding:无 GPU 机器上 CPU WASM 极慢,不可用
- L0/L1/L2 分层:控制每次 session 的 token 消耗,避免全量加载
- .abstract 作为入口:session 启动只读一个小文件,按需展开
- P0/P1/P2 TTL:自动清理陈旧信息,防止记忆腐烂
- qmd 只认
hf:GGUF 格式:不支持 OpenAI 兼容 API endpoint,这是踩过的坑 - 大 session 本身就是没有结构化记忆的代价:12w token 的 session 是反面教材
总结
这套方案无外部服务依赖,纯本地运行,可以直接迁移到任何跑 OpenClaw 的机器。有 GPU 的机器还可以进一步开启 vector search 提升语义检索质量。