memory-lancedb-pro 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README_CN.md ADDED
@@ -0,0 +1,406 @@
1
+ <div align="center">
2
+
3
+ # 🧠 memory-lancedb-pro
4
+
5
+ **[OpenClaw](https://github.com/openclaw/openclaw) 增强型 LanceDB 长期记忆插件**
6
+
7
+ 混合检索(Vector + BM25)· 跨编码器 Rerank · 多 Scope 隔离 · 管理 CLI
8
+
9
+ [![OpenClaw Plugin](https://img.shields.io/badge/OpenClaw-Plugin-blue)](https://github.com/openclaw/openclaw)
10
+ [![LanceDB](https://img.shields.io/badge/LanceDB-Vectorstore-orange)](https://lancedb.com)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
12
+
13
+ [English](README.md) | **简体中文**
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## 📺 视频教程
20
+
21
+ > **观看完整教程 — 涵盖安装、配置,以及混合检索的底层原理。**
22
+
23
+ [![YouTube Video](https://img.shields.io/badge/YouTube-立即观看-red?style=for-the-badge&logo=youtube)](https://youtu.be/MtukF1C8epQ)
24
+ 🔗 **https://youtu.be/MtukF1C8epQ**
25
+
26
+ [![Bilibili Video](https://img.shields.io/badge/Bilibili-立即观看-00A1D6?style=for-the-badge&logo=bilibili&logoColor=white)](https://www.bilibili.com/video/BV1zUf2BGEgn/)
27
+ 🔗 **https://www.bilibili.com/video/BV1zUf2BGEgn/**
28
+
29
+ ---
30
+
31
+ ## 为什么需要这个插件?
32
+
33
+ OpenClaw 内置的 `memory-lancedb` 插件仅提供基本的向量搜索。**memory-lancedb-pro** 在此基础上进行了全面升级:
34
+
35
+ | 功能 | 内置 `memory-lancedb` | **memory-lancedb-pro** |
36
+ |------|----------------------|----------------------|
37
+ | 向量搜索 | ✅ | ✅ |
38
+ | BM25 全文检索 | ❌ | ✅ |
39
+ | 混合融合(Vector + BM25) | ❌ | ✅ |
40
+ | 跨编码器 Rerank(Jina) | ❌ | ✅ |
41
+ | 时效性加成 | ❌ | ✅ |
42
+ | 时间衰减 | ❌ | ✅ |
43
+ | 长度归一化 | ❌ | ✅ |
44
+ | MMR 多样性去重 | ❌ | ✅ |
45
+ | 多 Scope 隔离 | ❌ | ✅ |
46
+ | 噪声过滤 | ❌ | ✅ |
47
+ | 自适应检索 | ❌ | ✅ |
48
+ | 管理 CLI | ❌ | ✅ |
49
+ | Session 记忆 | ❌ | ✅ |
50
+ | Task-aware Embedding | ❌ | ✅ |
51
+ | 任意 OpenAI 兼容 Embedding | 有限 | ✅(OpenAI、Gemini、Jina、Ollama 等) |
52
+
53
+ ---
54
+
55
+ ## 架构概览
56
+
57
+ ```
58
+ ┌─────────────────────────────────────────────────────────┐
59
+ │ index.ts (入口) │
60
+ │ 插件注册 · 配置解析 · 生命周期钩子 · 自动捕获/回忆 │
61
+ └────────┬──────────┬──────────┬──────────┬───────────────┘
62
+ │ │ │ │
63
+ ┌────▼───┐ ┌────▼───┐ ┌───▼────┐ ┌──▼──────────┐
64
+ │ store │ │embedder│ │retriever│ │ scopes │
65
+ │ .ts │ │ .ts │ │ .ts │ │ .ts │
66
+ └────────┘ └────────┘ └────────┘ └─────────────┘
67
+ │ │
68
+ ┌────▼───┐ ┌─────▼──────────┐
69
+ │migrate │ │noise-filter.ts │
70
+ │ .ts │ │adaptive- │
71
+ └────────┘ │retrieval.ts │
72
+ └────────────────┘
73
+ ┌─────────────┐ ┌──────────┐
74
+ │ tools.ts │ │ cli.ts │
75
+ │ (Agent API) │ │ (CLI) │
76
+ └─────────────┘ └──────────┘
77
+ ```
78
+
79
+ ### 文件说明
80
+
81
+ | 文件 | 用途 |
82
+ |------|------|
83
+ | `index.ts` | 插件入口。注册到 OpenClaw Plugin API,解析配置,挂载 `before_agent_start`(自动回忆)、`agent_end`(自动捕获)、`command:new`(Session 记忆)等钩子 |
84
+ | `openclaw.plugin.json` | 插件元数据 + 完整 JSON Schema 配置声明(含 `uiHints`) |
85
+ | `package.json` | NPM 包信息,依赖 `@lancedb/lancedb`、`openai`、`@sinclair/typebox` |
86
+ | `cli.ts` | CLI 命令实现:`memory list/search/stats/delete/delete-bulk/export/import/reembed/migrate` |
87
+ | `src/store.ts` | LanceDB 存储层。表创建 / FTS 索引 / Vector Search / BM25 Search / CRUD / 批量删除 / 统计 |
88
+ | `src/embedder.ts` | Embedding 抽象层。兼容 OpenAI API 的任意 Provider(OpenAI、Gemini、Jina、Ollama 等),支持 task-aware embedding(`taskQuery`/`taskPassage`) |
89
+ | `src/retriever.ts` | 混合检索引擎。Vector + BM25 → RRF 融合 → Jina Cross-Encoder Rerank → Recency Boost → Importance Weight → Length Norm → Time Decay → Hard Min Score → Noise Filter → MMR Diversity |
90
+ | `src/scopes.ts` | 多 Scope 访问控制。支持 `global`、`agent:<id>`、`custom:<name>`、`project:<id>`、`user:<id>` 等 Scope 模式 |
91
+ | `src/tools.ts` | Agent 工具定义:`memory_recall`、`memory_store`、`memory_forget`(核心)+ `memory_stats`、`memory_list`(管理) |
92
+ | `src/noise-filter.ts` | 噪声过滤器。过滤 Agent 拒绝回复、Meta 问题、寒暄等低质量记忆 |
93
+ | `src/adaptive-retrieval.ts` | 自适应检索。判断 query 是否需要触发记忆检索(跳过问候、命令、简单确认等) |
94
+ | `src/migrate.ts` | 迁移工具。从旧版 `memory-lancedb` 插件迁移数据到 Pro 版 |
95
+
96
+ ---
97
+
98
+ ## 核心特性
99
+
100
+ ### 1. 混合检索 (Hybrid Retrieval)
101
+
102
+ ```
103
+ Query → embedQuery() ─┐
104
+ ├─→ RRF 融合 → Rerank → 时效加成 → 重要性加权 → 过滤
105
+ Query → BM25 FTS ─────┘
106
+ ```
107
+
108
+ - **向量搜索**: 语义相似度搜索(cosine distance via LanceDB ANN)
109
+ - **BM25 全文搜索**: 关键词精确匹配(LanceDB FTS 索引)
110
+ - **融合策略**: Vector score 为基础,BM25 命中给予 15% 加成(非传统 RRF,经过调优)
111
+ - **可配置权重**: `vectorWeight`、`bm25Weight`、`minScore`
112
+
113
+ ### 2. 跨编码器 Rerank
114
+
115
+ - **Jina Reranker API**: `jina-reranker-v2-base-multilingual`(5s 超时保护)
116
+ - **混合评分**: 60% cross-encoder score + 40% 原始融合分
117
+ - **降级策略**: API 失败时回退到 cosine similarity rerank
118
+
119
+ ### 3. 多层评分管线
120
+
121
+ | 阶段 | 公式 | 效果 |
122
+ |------|------|------|
123
+ | **时效加成** | `exp(-ageDays / halfLife) * weight` | 新记忆分数更高(默认半衰期 14 天,权重 0.10) |
124
+ | **重要性加权** | `score *= (0.7 + 0.3 * importance)` | importance=1.0 → ×1.0,importance=0.5 → ×0.85 |
125
+ | **长度归一化** | `score *= 1 / (1 + 0.5 * log2(len/anchor))` | 防止长条目凭关键词密度霸占所有查询(锚点:500 字符) |
126
+ | **时间衰减** | `score *= 0.5 + 0.5 * exp(-ageDays / halfLife)` | 旧条目逐渐降权,下限 0.5×(60 天半衰期) |
127
+ | **硬最低分** | 低于阈值直接丢弃 | 移除不相关结果(默认 0.35) |
128
+ | **MMR 多样性** | cosine 相似度 > 0.85 → 降级 | 防止近似重复结果 |
129
+
130
+ ### 4. 多 Scope 隔离
131
+
132
+ - **内置 Scope 模式**: `global`、`agent:<id>`、`custom:<name>`、`project:<id>`、`user:<id>`
133
+ - **Agent 级访问控制**: 通过 `scopes.agentAccess` 配置每个 Agent 可访问的 Scope
134
+ - **默认行为**: Agent 可访问 `global` + 自己的 `agent:<id>` Scope
135
+
136
+ ### 5. 自适应检索
137
+
138
+ - 跳过不需要记忆的 query(问候、slash 命令、简单确认、emoji)
139
+ - 强制检索含记忆相关关键词的 query("remember"、"之前"、"上次"等)
140
+ - 支持 CJK 字符的更低阈值(中文 6 字符 vs 英文 15 字符)
141
+
142
+ ### 6. 噪声过滤
143
+
144
+ 在自动捕获和工具存储阶段同时生效:
145
+ - 过滤 Agent 拒绝回复("I don't have any information")
146
+ - 过滤 Meta 问题("do you remember")
147
+ - 过滤寒暄("hi"、"hello"、"HEARTBEAT")
148
+
149
+ ### 7. Session 记忆
150
+
151
+ - `/new` 命令触发时可保存上一个 Session 的对话摘要到 LanceDB
152
+ - 默认关闭(`enabled: false`),因为 OpenClaw 已有原生 .jsonl 会话保存
153
+ - 开启会导致大段摘要污染检索质量,建议仅在需要语义搜索历史会话时开启
154
+ - 可配置消息数量(默认 15 条)
155
+
156
+ ### 8. 自动捕获 & 自动回忆
157
+
158
+ - **Auto-Capture**(`agent_end` hook): 从对话中提取 preference/fact/decision/entity,去重后存储(每次最多 3 条)
159
+ - **Auto-Recall**(`before_agent_start` hook): 注入 `<relevant-memories>` 上下文(最多 3 条)
160
+
161
+ ---
162
+
163
+ ## 安装
164
+
165
+ ### 什么是 “OpenClaw workspace”?
166
+
167
+ 在 OpenClaw 中,**agent workspace(工作区)** 是 Agent 的工作目录(默认:`~/.openclaw/workspace`)。
168
+ 根据官方文档,workspace 是 OpenClaw 的 **默认工作目录(cwd)**,因此 **相对路径会以 workspace 为基准解析**(除非你使用绝对路径)。
169
+
170
+ > 说明:OpenClaw 的配置文件通常在 `~/.openclaw/openclaw.json`,与 workspace 是分开的。
171
+
172
+ **最常见的安装错误:** 把插件 clone 到别的目录,但在配置里仍然写 `"paths": ["plugins/memory-lancedb-pro"]`(这是**相对路径**)。OpenClaw 会去 workspace 下找 `plugins/memory-lancedb-pro`,导致加载失败,于是出现“安装位置不对”的反馈。
173
+
174
+ ### 方案 A(推荐):克隆到 workspace 的 `plugins/` 目录下
175
+
176
+ ```bash
177
+ # 1) 进入你的 OpenClaw workspace(默认:~/.openclaw/workspace)
178
+ # (可通过 agents.defaults.workspace 改成你自己的路径)
179
+ cd /path/to/your/openclaw/workspace
180
+
181
+ # 2) 把插件克隆到 workspace/plugins/ 下
182
+ git clone https://github.com/win4r/memory-lancedb-pro.git plugins/memory-lancedb-pro
183
+
184
+ # 3) 安装依赖
185
+ cd plugins/memory-lancedb-pro
186
+ npm install
187
+ ```
188
+
189
+ 然后在 OpenClaw 配置(`openclaw.json`)中使用相对路径:
190
+
191
+ ```json
192
+ {
193
+ "plugins": {
194
+ "load": {
195
+ "paths": ["plugins/memory-lancedb-pro"]
196
+ },
197
+ "entries": {
198
+ "memory-lancedb-pro": {
199
+ "enabled": true,
200
+ "config": {
201
+ "embedding": {
202
+ "apiKey": "${JINA_API_KEY}",
203
+ "model": "jina-embeddings-v5-text-small",
204
+ "baseURL": "https://api.jina.ai/v1",
205
+ "dimensions": 1024,
206
+ "taskQuery": "retrieval.query",
207
+ "taskPassage": "retrieval.passage",
208
+ "normalized": true
209
+ }
210
+ }
211
+ }
212
+ },
213
+ "slots": {
214
+ "memory": "memory-lancedb-pro"
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ ### 方案 B:插件装在任意目录,但配置里必须写绝对路径
221
+
222
+ ```json
223
+ {
224
+ "plugins": {
225
+ "load": {
226
+ "paths": ["/absolute/path/to/memory-lancedb-pro"]
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ### 重启
233
+
234
+ ```bash
235
+ openclaw gateway restart
236
+ ```
237
+
238
+ > **注意:** 如果之前使用了内置的 `memory-lancedb`,启用本插件时需同时禁用它。同一时间只能有一个 memory 插件处于活动状态。
239
+
240
+ ### 验证是否安装成功(推荐)
241
+
242
+ 1)确认插件已被发现/加载:
243
+
244
+ ```bash
245
+ openclaw plugins list
246
+ openclaw plugins info memory-lancedb-pro
247
+ ```
248
+
249
+ 2)如果发现异常,运行插件诊断:
250
+
251
+ ```bash
252
+ openclaw plugins doctor
253
+ ```
254
+
255
+ 3)确认 memory slot 已指向本插件:
256
+
257
+ ```bash
258
+ # 期望看到:plugins.slots.memory = "memory-lancedb-pro"
259
+ openclaw config get plugins.slots.memory
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 配置
265
+
266
+ <details>
267
+ <summary><strong>完整配置示例(点击展开)</strong></summary>
268
+
269
+ ```json
270
+ {
271
+ "embedding": {
272
+ "apiKey": "${JINA_API_KEY}",
273
+ "model": "jina-embeddings-v5-text-small",
274
+ "baseURL": "https://api.jina.ai/v1",
275
+ "dimensions": 1024,
276
+ "taskQuery": "retrieval.query",
277
+ "taskPassage": "retrieval.passage",
278
+ "normalized": true
279
+ },
280
+ "dbPath": "~/.openclaw/memory/lancedb-pro",
281
+ "autoCapture": true,
282
+ "autoRecall": true,
283
+ "retrieval": {
284
+ "mode": "hybrid",
285
+ "vectorWeight": 0.7,
286
+ "bm25Weight": 0.3,
287
+ "minScore": 0.3,
288
+ "rerank": "cross-encoder",
289
+ "rerankApiKey": "jina_xxx",
290
+ "rerankModel": "jina-reranker-v2-base-multilingual",
291
+ "candidatePoolSize": 20,
292
+ "recencyHalfLifeDays": 14,
293
+ "recencyWeight": 0.1,
294
+ "filterNoise": true,
295
+ "lengthNormAnchor": 500,
296
+ "hardMinScore": 0.35,
297
+ "timeDecayHalfLifeDays": 60
298
+ },
299
+ "enableManagementTools": false,
300
+ "scopes": {
301
+ "default": "global",
302
+ "definitions": {
303
+ "global": { "description": "共享知识库" },
304
+ "agent:discord-bot": { "description": "Discord 机器人私有" }
305
+ },
306
+ "agentAccess": {
307
+ "discord-bot": ["global", "agent:discord-bot"]
308
+ }
309
+ },
310
+ "sessionMemory": {
311
+ "enabled": false,
312
+ "messageCount": 15
313
+ }
314
+ }
315
+ ```
316
+
317
+ </details>
318
+
319
+ ### Embedding 提供商
320
+
321
+ 本插件支持 **任意 OpenAI 兼容的 Embedding API**:
322
+
323
+ | 提供商 | 模型 | Base URL | 维度 |
324
+ |--------|------|----------|------|
325
+ | **Jina**(推荐) | `jina-embeddings-v5-text-small` | `https://api.jina.ai/v1` | 1024 |
326
+ | **OpenAI** | `text-embedding-3-small` | `https://api.openai.com/v1` | 1536 |
327
+ | **Google Gemini** | `gemini-embedding-001` | `https://generativelanguage.googleapis.com/v1beta/openai/` | 3072 |
328
+ | **Ollama**(本地) | `nomic-embed-text` | `http://localhost:11434/v1` | 768 |
329
+
330
+ ---
331
+
332
+ ## CLI 命令
333
+
334
+ ```bash
335
+ # 列出记忆
336
+ openclaw memory list [--scope global] [--category fact] [--limit 20] [--json]
337
+
338
+ # 搜索记忆
339
+ openclaw memory search "query" [--scope global] [--limit 10] [--json]
340
+
341
+ # 查看统计
342
+ openclaw memory stats [--scope global] [--json]
343
+
344
+ # 按 ID 删除记忆(支持 8+ 字符前缀)
345
+ openclaw memory delete <id>
346
+
347
+ # 批量删除
348
+ openclaw memory delete-bulk --scope global [--before 2025-01-01] [--dry-run]
349
+
350
+ # 导出 / 导入
351
+ openclaw memory export [--scope global] [--output memories.json]
352
+ openclaw memory import memories.json [--scope global] [--dry-run]
353
+
354
+ # 使用新模型重新生成 Embedding
355
+ openclaw memory reembed --source-db /path/to/old-db [--batch-size 32] [--skip-existing]
356
+
357
+ # 从内置 memory-lancedb 迁移
358
+ openclaw memory migrate check [--source /path]
359
+ openclaw memory migrate run [--source /path] [--dry-run] [--skip-existing]
360
+ openclaw memory migrate verify [--source /path]
361
+ ```
362
+
363
+ ---
364
+
365
+ ## 数据库 Schema
366
+
367
+ LanceDB 表 `memories`:
368
+
369
+ | 字段 | 类型 | 说明 |
370
+ |------|------|------|
371
+ | `id` | string (UUID) | 主键 |
372
+ | `text` | string | 记忆文本(FTS 索引) |
373
+ | `vector` | float[] | Embedding 向量 |
374
+ | `category` | string | `preference` / `fact` / `decision` / `entity` / `other` |
375
+ | `scope` | string | Scope 标识(如 `global`、`agent:main`) |
376
+ | `importance` | float | 重要性分数 0-1 |
377
+ | `timestamp` | int64 | 创建时间戳 (ms) |
378
+ | `metadata` | string (JSON) | 扩展元数据 |
379
+
380
+ ---
381
+
382
+ ## 依赖
383
+
384
+ | 包 | 用途 |
385
+ |----|------|
386
+ | `@lancedb/lancedb` ≥0.26.2 | 向量数据库(ANN + FTS) |
387
+ | `openai` ≥6.21.0 | OpenAI 兼容 Embedding API 客户端 |
388
+ | `@sinclair/typebox` 0.34.48 | JSON Schema 类型定义(工具参数) |
389
+
390
+ ---
391
+
392
+ ## License
393
+
394
+ MIT
395
+
396
+ ---
397
+
398
+ ## Buy Me a Coffee
399
+
400
+ [!["Buy Me A Coffee"](https://storage.ko-fi.com/cdn/kofi2.png?v=3)](https://ko-fi.com/aila)
401
+
402
+ ## 我的微信群和微信二维码
403
+
404
+ <img src="https://github.com/win4r/AISuperDomain/assets/42172631/d6dcfd1a-60fa-4b6f-9d5e-1482150a7d95" width="186" height="300">
405
+ <img src="https://github.com/win4r/AISuperDomain/assets/42172631/7568cf78-c8ba-4182-aa96-d524d903f2bc" width="214.8" height="291">
406
+ <img src="https://github.com/win4r/AISuperDomain/assets/42172631/fefe535c-8153-4046-bfb4-e65eacbf7a33" width="207" height="281">