UNPKG

@tencentdb-agent-memory/memory-tencentdb

Version:

Four-layer local memory system plugin for OpenClaw — auto-captures, structures, and profiles conversational knowledge using local LLM + SQLite vector search (L0→L1→L2→L3 pipeline)

412 lines (336 loc) 22.1 kB
# @tencentdb-agent-memory/memory-tencentdb **Four-layer memory system plugin for [OpenClaw](https://github.com/openclaw/openclaw).** 为 AI Agent 提供长期记忆能力。通过 L0→L1→L2→L3 四层渐进式管线,自动将对话内容提炼为结构化记忆、场景块和用户画像。支持纯本地 SQLite 和远端腾讯云向量数据库(TCVDB)两种存储后端。 ## ✨ 核心功能 - **L0 — 对话录制**:自动捕获每轮对话原始消息,IMemoryStore + JSONL 双写 - **L1 — 记忆提取**:由 LLM 从对话中提取结构化记忆,支持向量去重与冲突检测 - **L2 — 场景归纳**:基于 L1 记忆自动归纳场景块(Scene Block),由 LLM 增量提取 - **L3 — 用户画像**:基于场景块自动生成/更新用户画像(Persona) - **自动召回(Auto-Recall)**:对话开始前自动注入相关记忆和用户画像到上下文 - **多后端存储**:支持 `sqlite`(本地 SQLite + sqlite-vec)和 `tcvdb`(腾讯云向量数据库,服务端 embedding + hybridSearch) - **BM25 稀疏向量**:内置 BM25 编码器(tcvdb-text),支持中英文混合搜索 - **关键词+向量混合搜索**:hybrid(关键词 + 向量 RRF 融合)搜索策略 - **语义搜索工具**:Agent 可调用 `tdai_memory_search`(L1 记忆搜索)和 `tdai_conversation_search`(L0 对话搜索) - **Seed CLI**`openclaw memory-tdai seed` 命令,支持导入历史对话数据(详见 [CLI 文档](src/cli/README.md)) - **Session 隔离**:不同渠道/Agent 的对话独立调度、独立提取 - **本地数据清理**:可配置 L0/L1 数据保留天数,定时自动清理过期文件 - **Manifest 元数据**:数据目录自动生成 `.metadata/manifest.json`,记录 store 绑定信息和 seed 运行记录 - **支持零配置**:支持零配置工作,简单易用 ## 🏗️ 关键原理 ``` 对话开始 → Auto-Recall: 向量/混合搜索相关记忆 + 加载 Persona → 注入系统上下文 对话结束 → Auto-Capture (L0): 录制对话消息 → IMemoryStore (SQLite/TCVDB) + JSONL 双写 → Pipeline Scheduler: 达到 N 轮后按序触发 L1 → L2 → L3 ├── L1: LLM 提取结构化记忆 + 向量去重 → 写入 JSONL + IMemoryStore ├── L2: LLM 归纳场景块 → Markdown 文件 └── L3: LLM 生成/更新用户画像 → persona.md ``` ### 数据目录结构 ``` <pluginDataDir>/ ├── conversations/ — L0 每日 JSONL 分片(每行一条消息) ├── records/ — L1 每日 JSONL 分片(提取的记忆) ├── scene_blocks/ — L2 场景块 .md 文件 ├── vectors.db — SQLite + vec0 向量数据库(仅 storeBackend=sqlite) ├── .metadata/ │ ├── manifest.json — 数据目录元数据(store 绑定、seed 信息) │ └── checkpoint.json └── .backup/ — 滚动备份(persona, scene_blocks) ``` ## 📋 前置依赖 | 依赖 | 版本要求 | 说明 | | ------------------------------------------------------------ | --------------- | ------------------------------------------------------------ | | [OpenClaw](https://github.com/nicepkg/openclaw) | `>= 2026.3.13` | 宿主框架,提供插件 SDK 及 Gateway 运行环境 | | [Node.js](https://nodejs.org/) | `>= 22.16.0` | 运行时环境 | | [`node-llama-cpp`](https://github.com/withcatai/node-llama-cpp) | `^3.16.2` | 本地 embedding 模型(GGUF 格式),提供离线向量化能力(仅 sqlite 后端需要) | | [`sqlite-vec`](https://github.com/asg017/sqlite-vec) | `0.1.7-alpha.2` | SQLite 向量搜索扩展(仅 sqlite 后端需要) | | [`tcvdb-text`](../../../packages/tcvdb-text) | `workspace:*` | BM25 稀疏向量编码器,支持中英文分词(仅 tcvdb 后端需要) | > 默认场景下无需安装 `node-llama-cpp`。如需启用本地 embedding,再在宿主环境手动安装该包。 ## 📦 安装 ```bash # 安装插件 openclaw plugins install @tencentdb-agent-memory/memory-tencentdb # 更新插件 openclaw plugins update memory-tencentdb # 卸载插件 openclaw plugins uninstall memory-tencentdb ``` 安装完成后,**重启 Gateway** 使插件生效: ```bash openclaw gateway restart ``` ## ⚙️ 配置 插件配置位于 `~/.openclaw/openclaw.json``memory-tencentdb` 字段下。**所有字段均有合理默认值,零配置即可使用。** ### 最小配置 安装启用后即为该状态(默认使用本地 SQLite 后端): ```json { "memory-tencentdb": { "enabled": true } } ``` > **⚠️ 重要:`allowPromptInjection` 必须为 `true`** > > 本插件通过 `before_prompt_build` hook 在对话开始前将召回的记忆注入系统上下文。 > OpenClaw v2026.4.5+ 新增了 `allowPromptInjection` 安全控制,当该选项设为 `false` 时, > `before_prompt_build` hook 将被**完全阻止注册**,导致记忆召回静默失效(不会报错,仅有 warn 日志)。 > > 请确保 `openclaw.json` 中**不要**将该插件的 `allowPromptInjection` 设为 `false`: > > ```jsonc > // ❌ 错误配置 — 会导致记忆召回完全失效 > { > "plugins": { > "entries": { > "memory-tencentdb": { > "hooks": { "allowPromptInjection": false } > } > } > } > } > > ``` ### TCVDB 后端配置 使用腾讯云向量数据库作为存储后端: ```json { "memory-tencentdb": { "storeBackend": "tcvdb", "tcvdb": { "url": "http://your-vdb-instance:8100", "apiKey": "your-api-key", "database": "my_memory_db", "alias": "生产环境" } } } ``` ### 完整配置 用户可按需配置,提升使用体验: ```json { "memory-tencentdb": { "mode": "local", "storeBackend": "sqlite", "server": { "url": "http://127.0.0.1:8420", "apiKey": "local", "instanceId": "default" }, "capture": { "enabled": true, "excludeAgents": ["bench-judge-*"], "l0l1RetentionDays": 90, "allowAggressiveCleanup": false, "cleanTime": "03:00" }, "extraction": { "enabled": true, "enableDedup": true, "maxMemoriesPerSession": 20, "model": "provider/model-name" }, "persona": { "triggerEveryN": 50, "maxScenes": 15, "backupCount": 3, "sceneBackupCount": 10, "model": "provider/model-name" }, "pipeline": { "everyNConversations": 5, "enableWarmup": true, "l1IdleTimeoutSeconds": 600, "l2DelayAfterL1Seconds": 10, "l2MinIntervalSeconds": 900, "l2MaxIntervalSeconds": 3600, "sessionActiveWindowHours": 24 }, "recall": { "enabled": true, "maxResults": 5, "maxCharsPerMemory": 0, "maxTotalRecallChars": 0, "scoreThreshold": 0.3, "strategy": "hybrid", "timeoutMs": 5000 }, "embedding": { "enabled": true, "provider": "none", "baseUrl": "https://your-embedding-endpoint/v1", "apiKey": "your-api-key", "model": "text-embedding-3-small", "dimensions": 1536, "sendDimensions": true, "conflictRecallTopK": 5, "maxInputChars": 5000, "timeoutMs": 10000, "recallTimeoutMs": 3000, "captureTimeoutMs": 15000 }, "tcvdb": { "url": "http://your-vdb-instance:8100", "username": "root", "apiKey": "your-api-key", "database": "my_memory_db", "alias": "生产环境", "embeddingModel": "bge-large-zh", "timeout": 10000, "caPemPath": "/path/to/ca.pem" }, "bm25": { "enabled": true, "language": "zh" }, "llm": { "enabled": false, "baseUrl": "https://api.openai.com/v1", "apiKey": "your-api-key", "model": "gpt-4o", "maxTokens": 4096, "timeoutMs": 120000 } } } ``` ### 配置说明 #### mode — 接入模式 | 字段 | 类型 | 默认值 | 说明 | | ------ | ------ | --------- | ------------------------------------------------------------ | | `mode` | string | `"local"` | OpenClaw 接入模式:`local` / `function`(默认,本地进程内运行)或 `client` / `gateway` / `remote`(轻量客户端模式,连接外部 Memory Gateway) | #### server — Gateway 连接配置(仅 client 模式) | 字段 | 类型 | 默认值 | 说明 | | ------------ | ------ | ------------------------- | --------------------------------------------- | | `url` | string | `"http://127.0.0.1:8420"` | Memory Gateway URL | | `apiKey` | string | `"local"` | Gateway 认证 API Key | | `instanceId` | string | `"default"` | 记忆实例 ID(HTTP header `x-tdai-service-id`) | #### storeBackend — 存储后端(仅 local 模式) | 字段 | 类型 | 默认值 | 说明 | | -------------- | ------ | ---------- | ------------------------------------------------------------ | | `storeBackend` | string | `"sqlite"` | 存储后端:`sqlite`(本地 SQLite + sqlite-vec)或 `tcvdb`(腾讯云向量数据库) | #### capture — 对话捕获 (L0) | 字段 | 类型 | 默认值 | 说明 | | ------------------------ | -------- | --------- | ------------------------------------------------------------ | | `enabled` | boolean | `true` | 是否启用自动对话捕获 | | `excludeAgents` | string[] | `[]` | Agent 排除 glob 模式列表,匹配的 agent 不参与捕获/召回/调度 | | `l0l1RetentionDays` | number | `0` | L0/L1 本地文件保留天数。`0` = 不清理;非 0 时需 >= 3(除非开启 `allowAggressiveCleanup`) | | `allowAggressiveCleanup` | boolean | `false` | 是否允许 1-2 天的高风险清理配置 | | `cleanTime` | string | `"03:00"` | 每日清理执行时间(HH:mm 格式) | #### extraction — 记忆提取 (L1) | 字段 | 类型 | 默认值 | 说明 | | ----------------------- | ------- | --------------------- | ------------------------------------------------------------ | | `enabled` | boolean | `true` | 是否启用后台记忆提取 | | `enableDedup` | boolean | `true` | 启用 L1 智能去重(基于向量相似度或关键词进行冲突检测) | | `maxMemoriesPerSession` | number | `20` | 单次 L1 提取每 session 最大记忆条数 | | `model` | string | *(OpenClaw 默认模型)* | 提取使用模型(格式:`provider/model`),未填写时使用 OpenClaw 默认模型 | #### pipeline — 管线调度 (L1→L2→L3) | 字段 | 类型 | 默认值 | 说明 | | -------------------------- | ------- | ------ | ------------------------------------------------------------ | | `everyNConversations` | number | `5` | 每 N 轮对话触发一次 L1 批处理 | | `enableWarmup` | boolean | `true` | Warm-up 模式:新 session 从 1 轮触发开始,每次 L1 后翻倍(1→2→4→...→N) | | `l1IdleTimeoutSeconds` | number | `600` | 用户停止对话后多久触发 L1(秒) | | `l2DelayAfterL1Seconds` | number | `10` | L1 完成后延迟多久触发 L2(秒) | | `l2MinIntervalSeconds` | number | `900` | 同一 session 两次 L2 的最小间隔(秒) | | `l2MaxIntervalSeconds` | number | `3600` | 活跃 session 的 L2 最大轮询间隔(秒) | | `sessionActiveWindowHours` | number | `24` | 超过此时间不活跃的 session 停止 L2 轮询 | #### recall — 记忆召回 | 字段 | 类型 | 默认值 | 说明 | | --------------------- | ------- | ---------- | ------------------------------------------------------------ | | `enabled` | boolean | `true` | 是否启用对话前自动召回 | | `maxResults` | number | `5` | 召回最大结果数 | | `maxCharsPerMemory` | number | `0` | 单条 L1 记忆注入的最大字符数;`0` = 不限制 | | `maxTotalRecallChars` | number | `0` | 本轮 auto-recall 注入的 L1 记忆总字符预算;`0` = 不限制 | | `scoreThreshold` | number | `0.3` | 最低分数阈值 | | `strategy` | string | `"hybrid"` | 搜索策略:`keyword`(关键词)、`embedding`(向量)、`hybrid`(混合 RRF 融合,推荐) | | `timeoutMs` | number | `5000` | 整体召回超时(毫秒)。超时后跳过记忆注入并输出 warn 日志,避免阻塞用户对话 | #### embedding — 向量搜索(仅 sqlite 后端) | 字段 | 类型 | 默认值 | 说明 | | -------------------- | ------- | -------- | ------------------------------------------------------------ | | `enabled` | boolean | `true` | 是否启用向量搜索(若 `provider="none"`,则实际会被禁用) | | `provider` | string | `"none"` | Embedding 服务提供者:`none` 表示禁用向量;其他值(如 `openai``deepseek`)按 OpenAI 兼容远端服务处理 | | `proxyUrl` | string | — | 本地代理地址(仅 `provider=qclaw` 时必填)。配置后 embedding 请求通过代理转发,原始 baseUrl 作为 `Remote-URL` 头传递 | | `baseUrl` | string | — | API Base URL(远端模式必填) | | `apiKey` | string | — | API Key(远端模式必填) | | `model` | string | — | 模型名称(远端模式必填) | | `dimensions` | number | — | 向量维度(远端模式必填,需与模型匹配) | | `sendDimensions` | boolean | `true` | 是否在请求体中携带 `dimensions` 字段。设为 `false` 以适配 BGE-M3 等不支持自定义维度的固定维度模型 | | `conflictRecallTopK` | number | `5` | 冲突检测时召回 Top-K 数 | | `maxInputChars` | number | `5000` | Embedding 输入文本最大字符数,超出时截断并打印警告日志 | | `timeoutMs` | number | `10000` | 单次 embedding API 调用超时(毫秒)。超时后中止,不重试 | | `recallTimeoutMs` | number | — | recall 路径 embedding 超时(毫秒),覆盖 `timeoutMs`。用户等待中,建议设短(如 3000) | | `captureTimeoutMs` | number | — | capture 路径 embedding 超时(毫秒),覆盖 `timeoutMs`。后台运行,可设长(如 15000) | #### tcvdb — 腾讯云向量数据库(仅 storeBackend=tcvdb) | 字段 | 类型 | 默认值 | 说明 | | ---------------- | ------ | ---------------- | ------------------------------------------------ | | `url` | string | — | 实例 URL(必填,如 `http://10.0.1.1:8100`) | | `username` | string | `"root"` | 账户名 | | `apiKey` | string | — | API Key(必填) | | `database` | string | — | 数据库名(未填写时根据实例 ID 自动生成) | | `alias` | string | — | 用户友好别名(可选,记录在 manifest 中便于识别) | | `embeddingModel` | string | `"bge-large-zh"` | 服务端 embedding 模型 | | `timeout` | number | `10000` | 请求超时(毫秒) | | `caPemPath` | string | — | CA 证书 PEM 文件路径(HTTPS 连接时使用) | #### bm25 — BM25 稀疏向量编码 | 字段 | 类型 | 默认值 | 说明 | | ---------- | ------- | ------ | ------------------------------------------- | | `enabled` | boolean | `true` | 是否启用 BM25 稀疏向量编码 | | `language` | string | `"zh"` | 分词语言:`zh`(中文 jieba)或 `en`(英文) | #### persona — 场景归纳与用户画像 (L2/L3) | 字段 | 类型 | 默认值 | 说明 | | ------------------ | ------ | --------------------- | ------------------------------------------------------------ | | `triggerEveryN` | number | `50` | 每 N 条新记忆触发一次画像生成 | | `maxScenes` | number | `15` | 最大场景块数量 | | `backupCount` | number | `3` | 画像备份保留数量 | | `sceneBackupCount` | number | `10` | 场景块备份保留数量 | | `model` | string | *(OpenClaw 默认模型)* | L2/L3 使用模型(格式:`provider/model`),未填写时使用 OpenClaw 默认模型 | #### report — 指标上报 | 字段 | 类型 | 默认值 | 说明 | | --------- | ------- | --------- | ----------------------------------------------------------- | | `enabled` | boolean | `false` | 是否启用指标上报(通过 Gateway 日志输出结构化 METRIC JSON) | | `type` | string | `"local"` | 上报方式:`local` 表示通过 logger 输出结构化 JSON 日志 | #### llm — 独立 LLM 配置 开启后 L1/L2/L3 提取绕过 OpenClaw 内置模型,改用指定的 OpenAI-compatible API 直接调用。默认关闭(使用 OpenClaw 宿主模型)。 | 字段 | 类型 | 默认值 | 说明 | | ----------- | ------- | ---------------------------- | --------------------------------------------------- | | `enabled` | boolean | `false` | 是否启用独立 LLM 模式。关闭时使用 OpenClaw 宿主模型 | | `baseUrl` | string | `"https://api.openai.com/v1"` | OpenAI-compatible API 地址 | | `apiKey` | string | — | API Key | | `model` | string | `"gpt-4o"` | 模型名称(如 `gpt-4o``deepseek-v3`) | | `maxTokens` | number | `4096` | 最大输出 token 数 | | `timeoutMs` | number | `120000` | 请求超时(毫秒) | ## 🖥️ CLI 命令 插件提供 `openclaw memory-tdai` 命令空间,支持以下子命令: ### `seed` — 导入历史对话数据 将历史对话 JSON 文件导入到记忆管线中,完整执行 L0→L1→L2→L3 流程。 ```bash openclaw memory-tdai seed --input conversations.json [--output-dir ./output] [--config seed-config.json] [--yes] ``` 详细用法、输入格式和配置覆盖机制请参阅 [CLI 文档](src/cli/README.md)。 ## 🔧 Agent 工具 插件注册了两个 Agent 可调用的工具: ### `tdai_memory_search` 搜索用户的 L1 结构化长期记忆。 | 参数 | 类型 | 必填 | 说明 | | ------- | ------ | ---- | ------------------------------------------------------ | | `query` | string | ✅ | 搜索查询 | | `limit` | number | — | 返回结果上限(默认 5,最大 20) | | `type` | string | — | 按记忆类型过滤:`persona` / `episodic` / `instruction` | | `scene` | string | — | 按场景名过滤 | ### `tdai_conversation_search` 搜索 L0 原始对话历史。 | 参数 | 类型 | 必填 | 说明 | | ------------- | ------ | ---- | ------------------------------- | | `query` | string | ✅ | 搜索查询 | | `limit` | number | — | 返回结果上限(默认 5,最大 20) | | `session_key` | string | — | 按 session 过滤 | ## 📁 数据与日志 - **数据目录**`~/.openclaw/memory-tdai/`(自动创建) - **元数据**`.metadata/manifest.json`(store 绑定、seed 运行记录) - **Gateway 日志**:插件运行日志通过 `[memory-tdai]` 前缀标记,可在 Gateway 日志中搜索查看 - **配置文件**`~/.openclaw/openclaw.json` ## 📄 License [MIT](LICENSE)