You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

9.9 KiB

mem0-integration Skill

功能概述

为 OpenClaw 提供基于 mem0 + Qdrant 的对话记忆系统 (Memory Layer 4),包括:

  • Pre-Hook 语义检索注入(对话前自动召回相关记忆)
  • Post-Hook 异步写入(对话后智能筛选并存储记忆)
  • 三级可见性隔离 (public / project / private)
  • 记忆衰减 (expiration_date: 7d / 30d / permanent)
  • 智能写入过滤(跳过无价值对话)
  • Layer 3 FTS5 本地全文检索 fallback(Qdrant 不可达时接管)
  • 冷启动记忆预加载(新会话自动注入最近上下文)

架构全景文档: docs/MEMORY_ARCHITECTURE.md


文件结构

skills/mem0-integration/
├── SKILL.md                     # 本文档 — 开发者参考
├── openclaw.plugin.json         # OpenClaw 插件声明 (lifecycle hook)
├── skill.json                   # Skill 元数据
├── index.js                     # JS 入口,桥接 OpenClaw Gateway ↔ Python
│
│   ── 核心运行时 ──
├── mem0_client.py               # 核心客户端:初始化、检索、写入、队列、缓存
├── openclaw_interceptor.py      # Pre/Post-Hook 拦截器(Gateway 调用入口)
├── session_init.py              # 冷启动记忆预加载
│
│   ── 配置 ──
├── config.yaml                  # mem0 全局配置(Qdrant / LLM / Embedder / Cache)
├── project_registry.yaml        # Agent-项目归属关系(决定 project 级可见性)
│
│   ── 辅助工具 ──
├── local_search.py              # Layer 3: SQLite FTS5 本地全文检索 fallback
├── memory_cleanup.py            # 月度记忆统计与清理脚本
├── migrate_to_single_collection.py  # 从旧多 Collection 迁移到单库融合架构
├── recover_memories.py          # 记忆恢复工具 v1
├── recover_memories_v2.py       # 记忆恢复工具 v2
│
│   ── 旧版 / 命令 ──
├── commands.py                  # /memory 命令处理
├── openclaw_commands.py         # OpenClaw 原生命令扩展
├── mem0_integration.py          # 旧版集成入口(已被 mem0_client.py 取代)
│
│   ── 测试 ──
├── test_mem0.py                 # mem0 单元测试
├── test_integration.py          # 集成测试
└── test_production.py           # 生产环境测试

环境变量

API 端点与密钥(优先级链)

变量名 用途 优先级 来源
LLM_BASE_URL LLM/Embedding API 端点 最高 .env(OneAPI 网关)
LLM_API_KEY API 密钥 最高 .env(OneAPI token)
OPENAI_BASE_URL 备选端点(已有环境变量) 次之
MEM0_DASHSCOPE_API_KEY 备选密钥(DashScope 直连) 次之
DASHSCOPE_API_KEY 备选密钥 最低

代码在模块加载时自动按优先级链解析,设置 OPENAI_API_BASE / OPENAI_BASE_URL / OPENAI_API_KEY,供 mem0 SDK 读取。当前生产配置由 .env 中的 LLM_BASE_URL + LLM_API_KEY 驱动,指向本地 OneAPI 网关。

模型配置

变量名 用途 优先级 默认值
MEM0_LLM_MODEL 记忆提取/合并用 LLM 最高
LLM_MODEL_ID 备选 LLM 模型名 次之 qwen-plus
MEM0_EMBEDDER_MODEL Embedding 模型名 最高
EMBEDDING_MODEL_ID 备选 Embedding 模型名 次之 text-embedding-v4

当前生产值(来自 .env):LLM = MiniMax-M2.5,Embedder = text-embedding-v4(1024 维)。

Qdrant 连接

变量名 用途 默认值
MEM0_QDRANT_HOST Qdrant 地址 localhost
MEM0_QDRANT_PORT Qdrant 端口 6333

两个模型的分工

模型 用途 调用时机
LLM(MiniMax-M2.5) 从对话中提取有价值的记忆,去重/合并已有记忆,生成结构化摘要 Post-Hook 写入时(后台异步)
Embedder(text-embedding-v4) 将文本转成 1024 维向量,写入 Qdrant;Pre-Hook 检索时同样用于向量化查询 读写均需

核心模块说明

mem0_client.py — 核心客户端

类: Mem0Client

  • _init_memory() — 初始化 mem0 Memory 实例(Qdrant + DashScope Embedder 1024 维)
  • start() — 启动异步写入队列的后台 worker(必须在 event loop 中调用)
  • pre_hook_search() — Pre-Hook: 三阶段检索(public → project → private → legacy fallback),带缓存和超时
  • post_hook_add() — Post-Hook: 智能过滤 + 自动分类(memory_type / visibility)+ 入队
  • _execute_write() — 后台异步写入 Qdrant,附带 metadata 和 expiration_date

类: AsyncMemoryQueue

  • 基于 collections.deque 的有界异步队列
  • 后台 worker 每秒轮询,批量处理

全局实例: mem0_client = Mem0Client() — 模块加载时自动创建

openclaw_interceptor.py — 拦截器

Gateway 调用入口。从 context dict 中提取 user_idagent_idvisibilityproject_idmemory_type,桥接到 mem0_client

local_search.py — Layer 3 FTS5 Fallback

基于 SQLite FTS5 的本地全文检索,Qdrant 不可达时接管。

  • CJK 字符逐字拆分 + ASCII 单词保持完整(过滤标点噪音)
  • 每个 Agent 维护独立的 FTS5 索引文件
  • rebuild_index() 扫描 MEMORY.md + memory/*.md + 共享核心文件

开发者注意事项

mem0 filter 格式

mem0 search()filters 参数使用扁平 dict,多个条件为隐式 AND:

# 正确: 扁平 dict (mem0 Python SDK)
filters={"visibility": "private", "agent_id": "main"}

# 错误: 嵌套 AND (Qdrant 原生 API 语法,mem0 不支持)
filters={"AND": [{"visibility": "private"}, {"agent_id": "main"}]}

直接操作 Qdrant (如 memory_cleanup.py) 时使用原生 Filter 对象:

from qdrant_client.models import Filter, FieldCondition, MatchValue
Filter(must=[FieldCondition(key="visibility", match=MatchValue(value="public"))])

mem0 add() 的 agent_id

mem0.add() 必须同时传递 agent_id 作为顶层参数和 metadata 字段:

self.local_memory.add(
    messages=messages,
    user_id=user_id,
    agent_id=agent_id,        # 顶层: mem0 内部索引用
    metadata={
        "agent_id": agent_id,  # metadata: 自定义 filter 查询用
        "visibility": "private",
        ...
    }
)

原因: mem0 的 search(agent_id=...) 匹配顶层字段;search(filters={"agent_id": ...}) 匹配 metadata 字段。两处都写入确保两种检索路径均能命中。

FTS5 中文分词

local_search.py 使用字符级分词(非 jieba),仅保留 CJK 统一表意文字 (U+4E00–U+9FFF) 和 ASCII 字母数字:

  • 输入 "你好,world!" → 输出 "你 好 world"
  • 标点、emoji、特殊符号被过滤,避免 FTS5 索引噪音
  • 搜索精度低于 jieba 词级分词,但零依赖、零内存开销

可见性自动分类

_classify_visibility() 返回 (visibility, project_id) 元组,支持三级自动推断:

  1. public:对话含 所有人 / 通知 / 全局 / 公告 / 大家 / 集群 等关键词
  2. project:对话匹配 project_registry.yaml 中 agent 所属项目的 name/description 关键词(如 广告素材advert情感陪伴life
  3. private:默认回退

项目关键词在首次调用时从 project_registry.yaml 动态提取并缓存,修改注册表后重启生效。

记忆写入过滤规则

以下对话自动跳过写入:

  1. 用户消息长度 < 5 字符
  2. 匹配 SKIP_PATTERNS: 好的、收到、OK、嗯、行、没问题、感谢、谢谢 等
  3. / 开头的系统命令

命令

通过 Telegram 使用:

/memory add <内容>       # 手动添加记忆
/memory search <关键词>   # 搜索记忆
/memory list             # 列出所有记忆
/memory delete <ID>      # 删除记忆
/memory status           # 查看状态

依赖

mem0ai          # 核心记忆管理
qdrant-client   # Qdrant 向量数据库客户端
pyyaml          # YAML 配置解析

更新记录

v2.2 (2026-03-16)

  • 架构: mem0 LLM + Embedder 全面切换到 OneAPI 网关路由,不再直连 DashScope
  • 环境变量: API 端点和密钥改为优先读取 LLM_BASE_URL / LLM_API_KEY(与 OpenClaw Agent 配置对齐);同时支持 LLM_MODEL_ID / EMBEDDING_MODEL_ID 覆盖模型名
  • Layer 3 自动 Fallback: Qdrant 不可达时(_init_memory() 失败或所有检索 phase 均报错),自动切换到 LocalSearchFallback FTS5 本地检索,无需手动干预
  • 可见性自动分类: _classify_visibility() 现支持三级推断(public / project / private),从 project_registry.yaml 动态提取项目关键词实现 project 级自动归档
  • memory_cleanup.py 修复: 修复死代码导致 per-type 保留策略失效;修复过期判断使用 expiration_date 而非 timestamp;修复 PointIdsList 调用格式;移除无关的 DashScope 初始化
  • 自动清理 cron: /etc/cron.d/mem0-cleanup 每天凌晨 3:00 UTC 自动执行 --executeexpiration_date 过期强制执行

v2.1 (2026-03-01)

  • 修复: _execute_search filter 格式从 Qdrant 嵌套语法改为 mem0 扁平 dict
  • 修复: _execute_write 补充 agent_id 顶层参数
  • 修复: session_init.py 补充 OPENAI_API_BASE 环境变量
  • 修复: local_search.py 中文分词过滤标点噪音
  • 清理: 移除未使用的 import (Optional, os, re)

v2.0 (2026-02-28)

  • 新增: 三级可见性 (public / project / private) + 三阶段检索
  • 新增: 记忆衰减 (expiration_date)
  • 新增: 智能写入过滤
  • 新增: 项目注册表 (project_registry.yaml)
  • 新增: Layer 3 SQLite FTS5 本地全文检索
  • 新增: 月度清理脚本 (memory_cleanup.py)
  • 安全: 所有 API Key 改为环境变量

v1.0 (2026-02-22)

  • 初始版本: mem0 + Qdrant 基础集成