@synth-coder/memhub 0.2.1 → 0.2.3

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.
Files changed (71) hide show
  1. package/.eslintrc.cjs +45 -45
  2. package/.factory/commands/opsx-apply.md +150 -0
  3. package/.factory/commands/opsx-archive.md +155 -0
  4. package/.factory/commands/opsx-explore.md +171 -0
  5. package/.factory/commands/opsx-propose.md +104 -0
  6. package/.factory/skills/openspec-apply-change/SKILL.md +156 -0
  7. package/.factory/skills/openspec-archive-change/SKILL.md +114 -0
  8. package/.factory/skills/openspec-explore/SKILL.md +288 -0
  9. package/.factory/skills/openspec-propose/SKILL.md +110 -0
  10. package/.github/workflows/ci.yml +74 -74
  11. package/.iflow/commands/opsx-apply.md +152 -152
  12. package/.iflow/commands/opsx-archive.md +157 -157
  13. package/.iflow/commands/opsx-explore.md +173 -173
  14. package/.iflow/commands/opsx-propose.md +106 -106
  15. package/.iflow/skills/openspec-apply-change/SKILL.md +156 -156
  16. package/.iflow/skills/openspec-archive-change/SKILL.md +114 -114
  17. package/.iflow/skills/openspec-explore/SKILL.md +288 -288
  18. package/.iflow/skills/openspec-propose/SKILL.md +110 -110
  19. package/.prettierrc +11 -11
  20. package/AGENTS.md +169 -26
  21. package/README.md +195 -195
  22. package/README.zh-CN.md +193 -193
  23. package/dist/src/contracts/mcp.js +34 -34
  24. package/dist/src/server/mcp-server.d.ts +8 -0
  25. package/dist/src/server/mcp-server.d.ts.map +1 -1
  26. package/dist/src/server/mcp-server.js +23 -2
  27. package/dist/src/server/mcp-server.js.map +1 -1
  28. package/dist/src/services/memory-service.d.ts +1 -0
  29. package/dist/src/services/memory-service.d.ts.map +1 -1
  30. package/dist/src/services/memory-service.js +125 -82
  31. package/dist/src/services/memory-service.js.map +1 -1
  32. package/docs/architecture-diagrams.md +368 -0
  33. package/docs/architecture.md +381 -349
  34. package/docs/contracts.md +190 -119
  35. package/docs/prompt-template.md +33 -79
  36. package/docs/proposals/mcp-typescript-sdk-refactor.md +568 -568
  37. package/docs/proposals/proposal-close-gates.md +58 -58
  38. package/docs/tool-calling-policy.md +101 -107
  39. package/docs/vector-search.md +306 -0
  40. package/package.json +59 -58
  41. package/src/contracts/index.ts +12 -12
  42. package/src/contracts/mcp.ts +222 -222
  43. package/src/contracts/schemas.ts +307 -307
  44. package/src/contracts/types.ts +410 -410
  45. package/src/index.ts +8 -8
  46. package/src/server/index.ts +5 -5
  47. package/src/server/mcp-server.ts +185 -161
  48. package/src/services/embedding-service.ts +114 -114
  49. package/src/services/index.ts +5 -5
  50. package/src/services/memory-service.ts +663 -621
  51. package/src/storage/frontmatter-parser.ts +243 -243
  52. package/src/storage/index.ts +6 -6
  53. package/src/storage/markdown-storage.ts +236 -236
  54. package/src/storage/vector-index.ts +160 -160
  55. package/src/utils/index.ts +5 -5
  56. package/src/utils/slugify.ts +63 -63
  57. package/test/contracts/schemas.test.ts +313 -313
  58. package/test/contracts/types.test.ts +21 -21
  59. package/test/frontmatter-parser-more.test.ts +94 -94
  60. package/test/server/mcp-server.test.ts +210 -169
  61. package/test/services/memory-service-edge.test.ts +248 -248
  62. package/test/services/memory-service.test.ts +278 -278
  63. package/test/storage/frontmatter-parser.test.ts +222 -222
  64. package/test/storage/markdown-storage.test.ts +216 -216
  65. package/test/storage/storage-edge.test.ts +238 -238
  66. package/test/storage/vector-index.test.ts +153 -153
  67. package/test/utils/slugify-edge.test.ts +94 -94
  68. package/test/utils/slugify.test.ts +68 -68
  69. package/tsconfig.json +25 -25
  70. package/tsconfig.test.json +8 -8
  71. package/vitest.config.ts +29 -29
@@ -1,58 +1,58 @@
1
- # Proposal: Close Remaining Quality Gates (Phase 2)
2
-
3
- ## Context
4
- Current implementation already has broad functionality and passing test suites, but quality gates are still blocked by:
5
-
6
- 1. ESLint configuration/type-aware parsing issues on test files
7
- 2. TypeScript typecheck errors in server and storage/service imports
8
- 3. Coverage gate failure on function coverage (<80%)
9
- 4. Project path inconsistency (`workspace/workspace/memhub`)
10
-
11
- ## Root Causes
12
- - ESLint `parserOptions.project` only pointed to `tsconfig.json`, while test files are not included there.
13
- - Some implementation details introduced strict-mode lint/type mismatches (`any` usage, fallthrough, readonly/no-unused issues).
14
- - Existing server tests focus on constants/contracts but not internal execution paths, leaving many functions uncovered.
15
- - Project was scaffolded under a nested directory.
16
-
17
- ## Plan of Record
18
-
19
- ### Step 1 — Fix static quality gates
20
- - Update ESLint type-aware project references to include test TS config.
21
- - Update `tsconfig.test.json` include set.
22
- - Fix strict lint/type issues in server/service/storage/utils modules.
23
-
24
- ### Step 2 — Raise function coverage to >=80%
25
- - Add focused tests for MCP server runtime paths:
26
- - JSON parsing failure path
27
- - invalid request path
28
- - method dispatch (`initialize`, `tools/list`, `tools/call`, unknown method)
29
- - error handling (`ServiceError`, validation-like error, generic error)
30
- - response/error serialization
31
- - log filtering behavior
32
- - Preserve existing passing behavior and avoid over-mocking core service logic.
33
-
34
- ### Step 3 — Validate full gate
35
- Run and require pass for:
36
- - `npm run lint`
37
- - `npm run typecheck`
38
- - `npm run test`
39
- - `npm run test:coverage` (global lines/functions/branches/statements >= 80)
40
-
41
- ### Step 4 — Normalize repository location
42
- - Move project to `C:\Users\cloud_user\.openclaw\workspace\memhub` (if missing).
43
- - Verify scripts still run from new root.
44
-
45
- ## Acceptance Criteria
46
- - No lint errors
47
- - No typecheck errors
48
- - All tests pass
49
- - Coverage thresholds all >= 80%
50
- - Repository available at normalized path
51
-
52
- ## Risks and Mitigations
53
- - **Risk:** Private method tests become brittle.
54
- - **Mitigation:** Test externally visible behavior and error contracts where possible; keep internals tests focused and minimal.
55
- - **Risk:** Path migration may break references.
56
- - **Mitigation:** Move whole directory atomically and rerun full gate.
57
- - **Risk:** Coverage improvements skew test value.
58
- - **Mitigation:** Prefer behavior-driven tests over shallow line-hitting.
1
+ # Proposal: Close Remaining Quality Gates (Phase 2)
2
+
3
+ ## Context
4
+ Current implementation already has broad functionality and passing test suites, but quality gates are still blocked by:
5
+
6
+ 1. ESLint configuration/type-aware parsing issues on test files
7
+ 2. TypeScript typecheck errors in server and storage/service imports
8
+ 3. Coverage gate failure on function coverage (<80%)
9
+ 4. Project path inconsistency (`workspace/workspace/memhub`)
10
+
11
+ ## Root Causes
12
+ - ESLint `parserOptions.project` only pointed to `tsconfig.json`, while test files are not included there.
13
+ - Some implementation details introduced strict-mode lint/type mismatches (`any` usage, fallthrough, readonly/no-unused issues).
14
+ - Existing server tests focus on constants/contracts but not internal execution paths, leaving many functions uncovered.
15
+ - Project was scaffolded under a nested directory.
16
+
17
+ ## Plan of Record
18
+
19
+ ### Step 1 — Fix static quality gates
20
+ - Update ESLint type-aware project references to include test TS config.
21
+ - Update `tsconfig.test.json` include set.
22
+ - Fix strict lint/type issues in server/service/storage/utils modules.
23
+
24
+ ### Step 2 — Raise function coverage to >=80%
25
+ - Add focused tests for MCP server runtime paths:
26
+ - JSON parsing failure path
27
+ - invalid request path
28
+ - method dispatch (`initialize`, `tools/list`, `tools/call`, unknown method)
29
+ - error handling (`ServiceError`, validation-like error, generic error)
30
+ - response/error serialization
31
+ - log filtering behavior
32
+ - Preserve existing passing behavior and avoid over-mocking core service logic.
33
+
34
+ ### Step 3 — Validate full gate
35
+ Run and require pass for:
36
+ - `npm run lint`
37
+ - `npm run typecheck`
38
+ - `npm run test`
39
+ - `npm run test:coverage` (global lines/functions/branches/statements >= 80)
40
+
41
+ ### Step 4 — Normalize repository location
42
+ - Move project to `C:\Users\cloud_user\.openclaw\workspace\memhub` (if missing).
43
+ - Verify scripts still run from new root.
44
+
45
+ ## Acceptance Criteria
46
+ - No lint errors
47
+ - No typecheck errors
48
+ - All tests pass
49
+ - Coverage thresholds all >= 80%
50
+ - Repository available at normalized path
51
+
52
+ ## Risks and Mitigations
53
+ - **Risk:** Private method tests become brittle.
54
+ - **Mitigation:** Test externally visible behavior and error contracts where possible; keep internals tests focused and minimal.
55
+ - **Risk:** Path migration may break references.
56
+ - **Mitigation:** Move whole directory atomically and rerun full gate.
57
+ - **Risk:** Coverage improvements skew test value.
58
+ - **Mitigation:** Prefer behavior-driven tests over shallow line-hitting.
@@ -1,107 +1,101 @@
1
- # Tool Calling Policy (STM-first)
2
-
3
- > 目标:让模型在每轮任务中稳定形成「先加载短期记忆,再产出,再回写记忆」的闭环。
4
-
5
- ## 一、调用时序(强约束)
6
-
7
- 1. **首轮调用 `memory_load`**(在响应用户前)
8
- - 用于加载当前会话/任务相关短期记忆(STM)
9
- - 若无命中,继续任务,不阻塞
10
-
11
- 2. **末轮调用 `memory_update`**(在本轮输出结束前)
12
- - 将本轮新增的关键上下文写回
13
- - 重点写入:决策、约束变更、待办变化、关键结论
14
-
15
- ---
16
-
17
- ## 二、STM 判据(3 轮复用原则)
18
-
19
- 若信息在未来 **3 轮** 内很可能被再次引用,则纳入 STM
20
-
21
- - 当前任务目标/范围
22
- - 新确认的约束条件
23
- - 待办项与状态变化(pending / done)
24
- - 临时变量、参数、文件路径、报错栈
25
- - 用户明确修正/改口(需求切换)
26
-
27
- 不满足则不强行写入,避免噪音。
28
-
29
- ---
30
-
31
- ## 三、建议工具定义(简化版)
32
-
33
- ## `memory_load`
34
- **作用**:统一“看记忆”,用于当前轮开头加载上下文。
35
-
36
- **建议入参**:
37
- - `session_id`(可选,推荐)
38
- - `date`(可选,默认今天)
39
- - `limit`(可选,默认 20
40
- - `tags`(可选)
41
- - `category`(可选)
42
- - `query`(可选)
43
- - `scope`(可选:`stm|all`,默认 `stm`)
44
-
45
- **建议返回**:
46
- - `items[]`(记忆条目)
47
- - `summary`(可选摘要)
48
- - `pending[]` / `done[]`(若可提取)
49
-
50
- ---
51
-
52
- ## `memory_update`
53
- **作用**:统一“写记忆”,用于当前轮末尾回写。
54
-
55
- **建议入参**:
56
- - `session_id`(可选;无则自动生成并返回)
57
- - `date`(可选,默认今天)
58
- - `mode`:`append|upsert`(默认 `append`)
59
- - `entry_type`:`decision|preference|knowledge|todo|state_change`
60
- - `title`
61
- - `content`
62
- - `tags[]`
63
- - `category`
64
- - `importance`(1-5)
65
-
66
- **建议返回**:
67
- - `id`
68
- - `session_id`
69
- - `file_path`
70
- - `created|updated`
71
-
72
- ---
73
-
74
- ## 四、并发与目录规范
75
-
76
- 为支持多个 CLI 同时写入,建议目录如下:
77
-
78
- ```text
79
- memories/
80
- YYYY-MM-DD/
81
- <session_uuid>/
82
- 2026-03-03T16-41-23.123Z-<slug>.md
83
- ```
84
-
85
- 说明:
86
- - 同一天按 `session_uuid` 分桶,避免并发冲突
87
- - 每条记录仍保留 YAML + Markdown 正文
88
- - `session_uuid` 可来自调用方;缺省由服务端生成
89
-
90
- ---
91
-
92
- ## 五、触发更新条件
93
-
94
- 在以下事件发生时,优先触发 `memory_update`:
95
-
96
- - 用户显式改需求(如“换个方案”)
97
- - 任务状态切换(分析 → 实现 / 实现 → 验证)
98
- - 新信息与既有 STM 冲突
99
- - 本轮产出形成可复用结论
100
-
101
- ---
102
-
103
- ## 六、设计原则
104
-
105
- - **STM 保留细节,不做过度抽象**
106
- - **LTM 另层抽取,不与 STM 混存**
107
- - **先 load,后 update,形成闭环**
1
+ # Tool Calling Policy (情境驱动)
2
+
3
+ > 目标:让记忆调用像人类一样自然——回忆由情境触发,记忆在无意识中形成。
4
+
5
+ ## 一、核心理念:从"时序驱动"到"情境驱动"
6
+
7
+ 人类的记忆规律:
8
+ - **回忆是触发的** — 不是按计划"现在是回忆时间",而是看到相关线索才想起
9
+ - **记忆是无意识的** — 重要的经历自然留下痕迹,不需要刻意"现在要记住"
10
+
11
+ 因此,MemHub 的工具调用不应是"首轮必调 load,末轮必调 update"的机械流程,而是根据情境自然触发。
12
+
13
+ ---
14
+
15
+ ## 二、触发式调用原则
16
+
17
+ ### `memory_load` 触发条件
18
+
19
+ 当出现以下情境时,调用 memory_load
20
+
21
+ - 用户提到过往经历("之前"、"记得吗"、"像上次那样")
22
+ - 遇到似曾相识的任务场景
23
+ - 需要参考用户偏好做决策
24
+ - 当前信息可能与过往冲突(用户纠正了你的假设)
25
+ - 不确定用户的既有偏好或约束
26
+
27
+ **不触发的情况**:
28
+ - 简单明确的操作("读取文件X"、"列出目录Y")
29
+ - 一次性任务,无需参考历史
30
+ - 当前上下文已足够
31
+
32
+ ### `memory_update` 触发条件
33
+
34
+ 当出现以下情境时,调用 memory_update:
35
+
36
+ - 发现用户偏好("我更喜欢..."、"不要用...")
37
+ - 做出了有理由的技术决策
38
+ - 纠正了一个误解或错误假设
39
+ - 用户显式要求记住("下次记住..."
40
+ - 项目上下文发生重要变化(技术栈、约束、团队规范)
41
+
42
+ **不触发的情况**:
43
+ - 简单的读写操作
44
+ - 临时性、一次性的信息
45
+ - 信息在短期内不会被复用
46
+
47
+ ---
48
+
49
+ ## 三、工具参考
50
+
51
+ ### `memory_load`
52
+
53
+ 按情境加载相关记忆,用于辅助当前任务。
54
+
55
+ **参数**:
56
+ - `query` — 搜索关键词或问题
57
+ - `tags` — 按标签过滤
58
+ - `category` — 按类别过滤
59
+ - `limit` — 返回数量限制
60
+
61
+ **返回**:
62
+ - `items[]` — 匹配的记忆条目
63
+
64
+ ### `memory_update`
65
+
66
+ 记录值得保留的信息,为未来对话提供上下文。
67
+
68
+ **参数**:
69
+ - `content` — 要记录的内容(必需)
70
+ - `title` — 简短标题
71
+ - `entryType` — 类型:`preference`(偏好)、`decision`(决策)、`context`(上下文)、`fact`(事实)
72
+ - `tags` — 标签数组
73
+ - `category` — 分类
74
+ - `importance` — 重要程度 1-5
75
+
76
+ **返回**:
77
+ - `id` — 记录 ID
78
+ - `created` — 是否新建
79
+
80
+ ---
81
+
82
+ ## 四、存储规范
83
+
84
+ 目录结构支持并发写入:
85
+
86
+ ```text
87
+ memories/
88
+ YYYY-MM-DD/
89
+ <session_uuid>/
90
+ 2026-03-03T16-41-23.123Z-<slug>.md
91
+ ```
92
+
93
+ 每条记录保留 YAML 元数据 + Markdown 正文。
94
+
95
+ ---
96
+
97
+ ## 五、设计原则
98
+
99
+ - **情境触发,而非时序强制** — 像人类记忆一样自然
100
+ - **有价值才记录** — 避免噪音,保留真正可复用的信息
101
+ - **偏好和决策优先** — 这些是最值得跨会话保留的内容
@@ -0,0 +1,306 @@
1
+ # 向量语义搜索
2
+
3
+ MemHub 集成了基于向量的语义搜索功能,使用本地 ONNX 模型实现智能记忆检索。
4
+
5
+ ## 概述
6
+
7
+ ### 为什么需要向量搜索?
8
+
9
+ 传统的关键词匹配存在以下限制:
10
+
11
+ - 无法理解语义相似性("架构" vs "设计")
12
+ - 无法处理同义词("偏好" vs "喜好")
13
+ - 无法进行模糊匹配("React 组件" vs "Component")
14
+
15
+ 向量语义搜索通过将文本转换为高维向量,计算语义相似度,提供更智能的检索体验。
16
+
17
+ ### 技术实现
18
+
19
+ - **Embedding 模型**: Xenova/all-MiniLM-L6-v2
20
+ - **向量维度**: 384
21
+ - **距离度量**: Cosine distance
22
+ - **向量数据库**: LanceDB
23
+ - **模型缓存**: `~/.cache/huggingface/`
24
+
25
+ ## 架构设计
26
+
27
+ ### 1. 分层架构
28
+
29
+ ```
30
+ ┌─────────────────────────────────────┐
31
+ │ Memory Service (业务层) │
32
+ │ - memoryLoad(query, tags, ...) │
33
+ └──────────────┬──────────────────────┘
34
+
35
+ ┌───────┴────────┐
36
+ │ │
37
+ ┌──────▼─────┐ ┌────▼────────┐
38
+ │ Embedding │ │ Vector │
39
+ │ Service │ │ Index │
40
+ │ (ONNX) │ │ (LanceDB) │
41
+ └────────────┘ └─────────────┘
42
+ ```
43
+
44
+ ### 2. 数据流
45
+
46
+ ```mermaid
47
+ sequenceDiagram
48
+ participant User
49
+ participant MemoryService
50
+ participant EmbeddingService
51
+ participant VectorIndex
52
+ participant MarkdownStorage
53
+
54
+ User->>MemoryService: memory_load(query="架构设计")
55
+ MemoryService->>EmbeddingService: embed("架构设计")
56
+ EmbeddingService-->>MemoryService: [0.1, 0.2, ..., 0.384]
57
+ MemoryService->>VectorIndex: search(vector, limit=20)
58
+ VectorIndex-->>MemoryService: [{id, _distance}, ...]
59
+ MemoryService->>MarkdownStorage: read([id1, id2, ...])
60
+ MarkdownStorage-->>MemoryService: [Memory, ...]
61
+ MemoryService-->>User: MemoryLoadOutput
62
+ ```
63
+
64
+ ## 使用方式
65
+
66
+ ### 1. 基本用法
67
+
68
+ ```typescript
69
+ // 语义搜索
70
+ const result = await memoryService.memoryLoad({
71
+ query: "如何实现用户认证",
72
+ limit: 10
73
+ });
74
+
75
+ // 返回语义最相关的记忆
76
+ console.log(result.items);
77
+ ```
78
+
79
+ ### 2. 混合搜索
80
+
81
+ ```typescript
82
+ // 语义搜索 + 元数据过滤
83
+ const result = await memoryService.memoryLoad({
84
+ query: "数据库优化",
85
+ tags: ["performance", "backend"],
86
+ category: "engineering",
87
+ limit: 10
88
+ });
89
+ ```
90
+
91
+ ### 3. 会话隔离
92
+
93
+ ```typescript
94
+ // 限定在特定会话中搜索
95
+ const result = await memoryService.memoryLoad({
96
+ query: "项目进度",
97
+ sessionId: "550e8400-e29b-41d4-a716-446655440000",
98
+ scope: "stm"
99
+ });
100
+ ```
101
+
102
+ ## 配置选项
103
+
104
+ ### 环境变量
105
+
106
+ ```bash
107
+ # 启用/禁用向量搜索(默认: true)
108
+ MEMHUB_VECTOR_SEARCH=true
109
+
110
+ # 存储路径(默认: ./memories)
111
+ MEMHUB_STORAGE_PATH=/path/to/memories
112
+ ```
113
+
114
+ ### 禁用向量搜索
115
+
116
+ 在测试环境或资源受限场景下,可以禁用向量搜索:
117
+
118
+ ```bash
119
+ MEMHUB_VECTOR_SEARCH=false
120
+ ```
121
+
122
+ 禁用后:
123
+ - `memory_load` 降级为纯元数据过滤
124
+ - `memory_update` 不更新向量索引
125
+ - 降低内存和磁盘占用
126
+
127
+ ## Embedding 服务
128
+
129
+ ### 模型特性
130
+
131
+ - **名称**: Xenova/all-MiniLM-L6-v2
132
+ - **大小**: ~23MB
133
+ - **语言**: 英文为主,支持多语言
134
+ - **性能**: 快速推理,适合实时搜索
135
+
136
+ ### 单例模式
137
+
138
+ ```typescript
139
+ class EmbeddingService {
140
+ private static instance: EmbeddingService | null = null;
141
+
142
+ static getInstance(): EmbeddingService {
143
+ if (!this.instance) {
144
+ this.instance = new EmbeddingService();
145
+ }
146
+ return this.instance;
147
+ }
148
+
149
+ async embed(text: string): Promise<number[]> {
150
+ // 返回 384 维归一化向量
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### 懒加载
156
+
157
+ 模型在首次使用时加载:
158
+
159
+ ```typescript
160
+ // 构造函数不加载模型
161
+ const service = EmbeddingService.getInstance();
162
+
163
+ // 首次调用 embed() 时加载模型
164
+ const vector = await service.embed("some text");
165
+
166
+ // 后续调用复用已加载的模型
167
+ const vector2 = await service.embed("another text");
168
+ ```
169
+
170
+ ## Vector Index
171
+
172
+ ### LanceDB 特性
173
+
174
+ - **嵌入式**: 无需独立服务,直接访问文件系统
175
+ - **高性能**: 基于 Apache Arrow 列式存储
176
+ - **ACID**: 支持事务和并发控制
177
+ - **可重建**: 可随时从 Markdown 重建索引
178
+
179
+ ### 索引结构
180
+
181
+ ```sql
182
+ CREATE TABLE memories (
183
+ id TEXT PRIMARY KEY,
184
+ vector FLOAT[384],
185
+ title TEXT,
186
+ category TEXT,
187
+ tags TEXT, -- JSON string
188
+ importance INT,
189
+ createdAt TEXT,
190
+ updatedAt TEXT
191
+ );
192
+ ```
193
+
194
+ ### 搜索算法
195
+
196
+ 1. **向量搜索**: 使用 COSINE 距离
197
+ 2. **Top-K**: 返回距离最小的 K 个结果
198
+ 3. **过滤**: 可结合 SQL WHERE 子句
199
+
200
+ ```typescript
201
+ // 搜索示例
202
+ const results = await table
203
+ .vectorSearch(queryVector)
204
+ .where("category = 'engineering'")
205
+ .limit(10)
206
+ .toArray();
207
+ ```
208
+
209
+ ## 重建索引
210
+
211
+ 如果向量索引损坏或需要重建:
212
+
213
+ ```typescript
214
+ // 1. 删除现有索引
215
+ rm -rf memories/.lancedb
216
+
217
+ // 2. 重新启动服务,索引会在下次写入时自动重建
218
+ // 或手动触发重建(TODO: 添加 CLI 命令)
219
+ ```
220
+
221
+ ## 性能优化
222
+
223
+ ### 1. 模型缓存
224
+
225
+ 模型下载后缓存在 `~/.cache/huggingface/`,避免重复下载。
226
+
227
+ ### 2. 向量缓存
228
+
229
+ LanceDB 自动缓存热门向量,提升搜索速度。
230
+
231
+ ### 3. 批量处理
232
+
233
+ 对于大量记忆条目,建议批量更新:
234
+
235
+ ```typescript
236
+ // TODO: 添加批量更新接口
237
+ await memoryService.batchUpdate(memories);
238
+ ```
239
+
240
+ ### 4. 异步更新
241
+
242
+ 向量索引更新在后台异步执行,不阻塞主流程:
243
+
244
+ ```typescript
245
+ // Markdown 写入完成立即返回
246
+ // 向量索引在后台更新
247
+ await memoryService.memoryUpdate(input);
248
+ ```
249
+
250
+ ## 错误处理
251
+
252
+ ### 降级策略
253
+
254
+ ```typescript
255
+ try {
256
+ // 尝试向量搜索
257
+ const results = await vectorIndex.search(vector, limit);
258
+ } catch (error) {
259
+ // 降级为文本搜索
260
+ console.warn('Vector search failed, falling back to text search');
261
+ const results = await markdownStorage.search(query, limit);
262
+ }
263
+ ```
264
+
265
+ ### 日志记录
266
+
267
+ ```typescript
268
+ // 成功
269
+ console.log('Vector search completed', { query, results: results.length });
270
+
271
+ // 失败
272
+ console.error('Vector search failed', { error: error.message });
273
+ ```
274
+
275
+ ## 限制与注意事项
276
+
277
+ ### 1. 语言支持
278
+
279
+ 当前模型主要针对英文优化,中文效果可能不如英文。
280
+
281
+ ### 2. 模型大小
282
+
283
+ 模型约 23MB,首次使用时需要下载。
284
+
285
+ ### 3. 内存占用
286
+
287
+ ONNX Runtime 需要额外内存(约 100-200MB)。
288
+
289
+ ### 4. 向量维度
290
+
291
+ 固定 384 维,无法更改。
292
+
293
+ ## 未来规划
294
+
295
+ - [ ] 支持多语言模型(中文优化)
296
+ - [ ] 添加模型管理 CLI 命令
297
+ - [ ] 支持自定义 embedding 模型
298
+ - [ ] 添加索引健康检查
299
+ - [ ] 支持向量维度配置
300
+ - [ ] 优化大批量索引构建
301
+
302
+ ## 参考资料
303
+
304
+ - [LanceDB 文档](https://lancedb.github.io/lancedb/)
305
+ - [Xenova Transformers](https://github.com/xenova/transformers.js)
306
+ - [all-MiniLM-L6-v2 模型](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2)