openclaw-amem 1.4.0 → 1.4.2

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.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # openclaw-amem
2
2
 
3
3
  <p align="center">
4
- <img src="https://raw.githubusercontent.com/heichaowo/amem/main/docs/public/logo.webp" width="120" alt="amem logo" />
4
+ <img src="https://raw.githubusercontent.com/amemhq/amem/main/docs/public/logo.webp" width="120" alt="amem logo" />
5
5
  </p>
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](../../LICENSE)
@@ -16,11 +16,11 @@ Runs on a small model — `gpt-4o-mini`, `haiku`, a local Ollama. No Python.
16
16
 
17
17
  中文走 [jieba](https://github.com/messense/node-jieba) 分词,提示词有完整中文版(`AMEM_PROMPT_LOCALE=zh`),embedding 模型本身多语言。
18
18
 
19
- Requires a local [Qdrant](https://qdrant.tech). Implements [A-MEM](https://arxiv.org/abs/2502.12110) (arXiv 2502.12110); the engine itself is [`@heichaowo/amem-core`](../amem-core).
19
+ Requires a local [Qdrant](https://qdrant.tech). Implements [A-MEM](https://arxiv.org/abs/2502.12110) (arXiv 2502.12110); the engine itself is [`@amemhq/core`](../amem-core).
20
20
 
21
21
  > 📖 Full guides, architecture & references: **[amem.owo.lc](https://amem.owo.lc)**.
22
22
 
23
- ⭐ Useful? [Star it on GitHub](https://github.com/heichaowo/amem).
23
+ ⭐ Useful? [Star it on GitHub](https://github.com/amemhq/amem).
24
24
 
25
25
  ## Highlights
26
26
 
@@ -31,7 +31,7 @@ Requires a local [Qdrant](https://qdrant.tech). Implements [A-MEM](https://arxiv
31
31
  - 🔐 **Per-agent isolation** — private by default; explicit `owner`/`readers`/`writers`; Mode A (shared collection) or Mode B (dedicated collection).
32
32
  - 🀄 **Chinese-optimized** & local embeddings (Transformers.js, 384-dim) — no Python, no external embedding API.
33
33
 
34
- → Full feature list & internals: **[amem-core README](../amem-core)** · **[docs](https://amem.owo.lc)**.
34
+ → Full feature list & internals: **[@amemhq/core README](../amem-core)** · **[docs](https://amem.owo.lc)**.
35
35
 
36
36
  ## Requirements
37
37
 
@@ -46,7 +46,7 @@ Requires a local [Qdrant](https://qdrant.tech). Implements [A-MEM](https://arxiv
46
46
 
47
47
  ```bash
48
48
  # From ClawHub (recommended)
49
- openclaw plugins install clawhub:@heichaowo/openclaw-amem
49
+ openclaw plugins install clawhub:openclaw-amem
50
50
 
51
51
  # From npm
52
52
  openclaw plugins install openclaw-amem
@@ -141,7 +141,7 @@ pnpm --filter openclaw-amem test # vitest (needs Qdrant on :6333)
141
141
 
142
142
  ## Docs & References
143
143
 
144
- Full guides, architecture, and academic references: **[amem.owo.lc](https://amem.owo.lc)** · engine: **[amem-core](../amem-core)** · paper: [A-MEM (arXiv:2502.12110)](https://arxiv.org/abs/2502.12110).
144
+ Full guides, architecture, and academic references: **[amem.owo.lc](https://amem.owo.lc)** · engine: **[@amemhq/core](../amem-core)** · paper: [A-MEM (arXiv:2502.12110)](https://arxiv.org/abs/2502.12110).
145
145
 
146
146
  ## License
147
147
 
package/dist/index.js CHANGED
@@ -56,6 +56,12 @@ var init_config = __esm({
56
56
  function getEmbeddingModel() {
57
57
  return process.env.AMEM_EMBED_MODEL?.trim() || DEFAULT_EMBEDDING_MODEL;
58
58
  }
59
+ function getEmbeddingPooling() {
60
+ const explicit = process.env.AMEM_EMBED_POOLING?.trim().toLowerCase();
61
+ if (explicit === "mean" || explicit === "cls") return explicit;
62
+ const basename2 = getEmbeddingModel().split("/").pop()?.toLowerCase() ?? "";
63
+ return CLS_POOLED_MODELS.has(basename2) ? "cls" : "mean";
64
+ }
59
65
  async function getExtractor() {
60
66
  const wanted = getEmbeddingModel();
61
67
  if (extractor && loadedModelName === wanted) return extractor;
@@ -76,21 +82,25 @@ async function getEmbeddingDim() {
76
82
  cachedDim = probe.length;
77
83
  return cachedDim;
78
84
  }
79
- function meanPoolingNormalize(output, attentionMask) {
85
+ function poolNormalize(output, attentionMask, mode) {
80
86
  const seqLen = output.length;
81
87
  const dim = output[0].length;
82
88
  const pooled = new Array(dim).fill(0);
83
- let maskSum = 0;
84
- for (let i = 0; i < seqLen; i++) {
85
- const m = attentionMask[i];
86
- maskSum += m;
89
+ if (mode === "cls") {
90
+ for (let j = 0; j < dim; j++) pooled[j] = output[0][j];
91
+ } else {
92
+ let maskSum = 0;
93
+ for (let i = 0; i < seqLen; i++) {
94
+ const m = attentionMask[i];
95
+ maskSum += m;
96
+ for (let j = 0; j < dim; j++) {
97
+ pooled[j] += output[i][j] * m;
98
+ }
99
+ }
87
100
  for (let j = 0; j < dim; j++) {
88
- pooled[j] += output[i][j] * m;
101
+ pooled[j] /= Math.max(maskSum, 1e-9);
89
102
  }
90
103
  }
91
- for (let j = 0; j < dim; j++) {
92
- pooled[j] /= Math.max(maskSum, 1e-9);
93
- }
94
104
  let norm = 0;
95
105
  for (const v of pooled) norm += v * v;
96
106
  norm = Math.sqrt(norm);
@@ -98,7 +108,8 @@ function meanPoolingNormalize(output, attentionMask) {
98
108
  }
99
109
  async function encode(text) {
100
110
  const ext = await getExtractor();
101
- const result = await ext(text, { pooling: "mean", normalize: true });
111
+ const pooling = getEmbeddingPooling();
112
+ const result = await ext(text, { pooling, normalize: true });
102
113
  if (result && result.data) {
103
114
  return Array.from(result.data);
104
115
  }
@@ -114,7 +125,7 @@ async function encode(text) {
114
125
  }
115
126
  raw.push(row);
116
127
  }
117
- return meanPoolingNormalize(raw, new Array(seqLen).fill(1));
128
+ return poolNormalize(raw, new Array(seqLen).fill(1), pooling);
118
129
  }
119
130
  throw new Error("Unexpected embedding output shape");
120
131
  }
@@ -129,7 +140,7 @@ function cosineSimilarity(a, b) {
129
140
  for (let i = 0; i < a.length; i++) dot += a[i] * b[i];
130
141
  return dot;
131
142
  }
132
- var pipeline, extractor, loadedModelName, cachedDim, DEFAULT_EMBEDDING_MODEL;
143
+ var pipeline, extractor, loadedModelName, cachedDim, DEFAULT_EMBEDDING_MODEL, CLS_POOLED_MODELS;
133
144
  var init_embedding = __esm({
134
145
  "../amem-core/src/embedding.ts"() {
135
146
  "use strict";
@@ -138,6 +149,19 @@ var init_embedding = __esm({
138
149
  loadedModelName = null;
139
150
  cachedDim = null;
140
151
  DEFAULT_EMBEDDING_MODEL = "Xenova/paraphrase-multilingual-MiniLM-L12-v2";
152
+ CLS_POOLED_MODELS = /* @__PURE__ */ new Set([
153
+ "bge-m3",
154
+ "bge-base-zh-v1.5",
155
+ "bge-small-zh-v1.5",
156
+ "bge-base-en-v1.5",
157
+ "bge-small-en-v1.5",
158
+ "bge-large-en-v1.5",
159
+ "gte-multilingual-base",
160
+ "gte-modernbert-base",
161
+ "gte-large-en-v1.5",
162
+ "snowflake-arctic-embed-m",
163
+ "snowflake-arctic-embed-l"
164
+ ]);
141
165
  }
142
166
  });
143
167
 
@@ -2395,6 +2419,7 @@ __export(src_exports, {
2395
2419
  generateReviewBatch: () => generateReviewBatch,
2396
2420
  getEmbeddingDim: () => getEmbeddingDim,
2397
2421
  getEmbeddingModel: () => getEmbeddingModel,
2422
+ getEmbeddingPooling: () => getEmbeddingPooling,
2398
2423
  getNote: () => getNote,
2399
2424
  invalidateNote: () => invalidateNote,
2400
2425
  isModelLoaded: () => isModelLoaded,
@@ -2,7 +2,7 @@
2
2
  "id": "openclaw-amem",
3
3
  "name": "amem",
4
4
  "description": "Catches memories that contradict each other. Notes rewrite themselves as new ones arrive, link into a graph, and stay separated per agent and per person. Runs on a small model. Requires a local Qdrant. 中文走 jieba 分词,提示词有中文版。",
5
- "version": "1.4.0",
5
+ "version": "1.4.2",
6
6
  "kind": "memory",
7
7
  "openclaw": {
8
8
  "compat": {
@@ -39,6 +39,7 @@
39
39
  "AMEM_LLM_TIMEOUT",
40
40
  "AMEM_CRUD_UPDATE_MIN_SIM",
41
41
  "AMEM_EMBED_MODEL",
42
+ "AMEM_EMBED_POOLING",
42
43
  "AMEM_COLLECTION",
43
44
  "AMEM_DATA_DIR",
44
45
  "AMEM_EVO_COUNTER_PATH",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-amem",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Catches memories that contradict each other. Notes rewrite themselves as new ones arrive, link into a graph, and stay separated per agent and per person. Runs on a small model. Requires a local Qdrant. 中文走 jieba 分词,提示词有中文版。",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -16,19 +16,19 @@
16
16
  }
17
17
  },
18
18
  "dependencies": {
19
- "@anthropic-ai/sdk": "^0.112.1",
19
+ "@anthropic-ai/sdk": "^0.112.5",
20
20
  "@huggingface/transformers": "^4.2.0",
21
21
  "@node-rs/jieba": "^2.0.1",
22
22
  "@qdrant/js-client-rest": "^1.18.0",
23
- "@types/uuid": "^11.0.0",
24
23
  "openai": "^6.48.0",
25
24
  "uuid": "^14.0.0"
26
25
  },
27
26
  "devDependencies": {
28
27
  "@eslint/js": "^10.0.1",
29
28
  "@types/node": "^26.1.1",
29
+ "@types/uuid": "^11.0.0",
30
30
  "eslint": "^10.7.0",
31
- "prettier": "^3.9.5",
31
+ "prettier": "^3.9.6",
32
32
  "tsup": "^8.4.0",
33
33
  "tsx": "^4.23.1",
34
34
  "typescript": "^6.0.3",
@@ -41,12 +41,12 @@
41
41
  },
42
42
  "repository": {
43
43
  "type": "git",
44
- "url": "git+https://github.com/heichaowo/amem.git",
44
+ "url": "git+https://github.com/amemhq/amem.git",
45
45
  "directory": "packages/openclaw-amem"
46
46
  },
47
47
  "homepage": "https://amem.owo.lc",
48
48
  "bugs": {
49
- "url": "https://github.com/heichaowo/amem/issues"
49
+ "url": "https://github.com/amemhq/amem/issues"
50
50
  },
51
51
  "keywords": [
52
52
  "openclaw",