@amemhq/core 1.0.0 → 1.0.1

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/dist/index.d.cts CHANGED
@@ -16,6 +16,19 @@ declare function configure(opts: {
16
16
  declare const DEFAULT_EMBEDDING_MODEL = "Xenova/paraphrase-multilingual-MiniLM-L12-v2";
17
17
  /** Which model this process embeds with. */
18
18
  declare function getEmbeddingModel(): string;
19
+ /** How token embeddings are collapsed into one sentence vector. */
20
+ type PoolingMode = 'mean' | 'cls';
21
+ /**
22
+ * Which pooling this process uses: `AMEM_EMBED_POOLING`, else the model's known
23
+ * mode, else `mean`.
24
+ *
25
+ * Getting this wrong does not fail. `encode()` returns a normalized vector of the
26
+ * right width either way, and search keeps working because notes and queries are
27
+ * embedded by the same function — it just retrieves worse than the model can,
28
+ * with nothing to indicate it. That is why the mode is resolved rather than
29
+ * assumed.
30
+ */
31
+ declare function getEmbeddingPooling(): PoolingMode;
19
32
  /**
20
33
  * The vector width this model produces, measured rather than looked up.
21
34
  *
@@ -499,4 +512,4 @@ declare function llmCrudDecision(userText: string, assistantText: string, existi
499
512
  content: string;
500
513
  }>): Promise<MemoryOperation[]>;
501
514
 
502
- export { type AgentAmemConfig, type AmemPluginConfig, type ConflictMode, type ConflictSweepResult, DEFAULT_CRUD_UPDATE_MIN_SIM, DEFAULT_EMBEDDING_MODEL, EmbeddingDimensionMismatchError, type EvolutionEntry, type LlmConfig, type LowQualityItem, type LowQualityReason, type MemoryNote, type MemoryOperation, type MigrateResult, type QueryResult, type SearchResult, type StorageContext, addEpisodic, addMemory, canRead, canWrite, checkQuality, configure, configureLlm, conflictSweep, consolidateMemories, createStorageContext, deleteNote, encode, ensureCollection, generateReviewBatch, getEmbeddingDim, getEmbeddingModel, getNote, invalidateNote, isModelLoaded, isPlausibleUpdateTarget, listMemories, listNotes, llmCrudDecision, loadModel, mergeSimilarNotes, migrateCollection, patchNotePayload, pingQdrant, resolveCrudUpdateMinSim, scanLowQuality, searchMemory, updateNote };
515
+ export { type AgentAmemConfig, type AmemPluginConfig, type ConflictMode, type ConflictSweepResult, DEFAULT_CRUD_UPDATE_MIN_SIM, DEFAULT_EMBEDDING_MODEL, EmbeddingDimensionMismatchError, type EvolutionEntry, type LlmConfig, type LowQualityItem, type LowQualityReason, type MemoryNote, type MemoryOperation, type MigrateResult, type PoolingMode, type QueryResult, type SearchResult, type StorageContext, addEpisodic, addMemory, canRead, canWrite, checkQuality, configure, configureLlm, conflictSweep, consolidateMemories, createStorageContext, deleteNote, encode, ensureCollection, generateReviewBatch, getEmbeddingDim, getEmbeddingModel, getEmbeddingPooling, getNote, invalidateNote, isModelLoaded, isPlausibleUpdateTarget, listMemories, listNotes, llmCrudDecision, loadModel, mergeSimilarNotes, migrateCollection, patchNotePayload, pingQdrant, resolveCrudUpdateMinSim, scanLowQuality, searchMemory, updateNote };
package/dist/index.d.ts CHANGED
@@ -16,6 +16,19 @@ declare function configure(opts: {
16
16
  declare const DEFAULT_EMBEDDING_MODEL = "Xenova/paraphrase-multilingual-MiniLM-L12-v2";
17
17
  /** Which model this process embeds with. */
18
18
  declare function getEmbeddingModel(): string;
19
+ /** How token embeddings are collapsed into one sentence vector. */
20
+ type PoolingMode = 'mean' | 'cls';
21
+ /**
22
+ * Which pooling this process uses: `AMEM_EMBED_POOLING`, else the model's known
23
+ * mode, else `mean`.
24
+ *
25
+ * Getting this wrong does not fail. `encode()` returns a normalized vector of the
26
+ * right width either way, and search keeps working because notes and queries are
27
+ * embedded by the same function — it just retrieves worse than the model can,
28
+ * with nothing to indicate it. That is why the mode is resolved rather than
29
+ * assumed.
30
+ */
31
+ declare function getEmbeddingPooling(): PoolingMode;
19
32
  /**
20
33
  * The vector width this model produces, measured rather than looked up.
21
34
  *
@@ -499,4 +512,4 @@ declare function llmCrudDecision(userText: string, assistantText: string, existi
499
512
  content: string;
500
513
  }>): Promise<MemoryOperation[]>;
501
514
 
502
- export { type AgentAmemConfig, type AmemPluginConfig, type ConflictMode, type ConflictSweepResult, DEFAULT_CRUD_UPDATE_MIN_SIM, DEFAULT_EMBEDDING_MODEL, EmbeddingDimensionMismatchError, type EvolutionEntry, type LlmConfig, type LowQualityItem, type LowQualityReason, type MemoryNote, type MemoryOperation, type MigrateResult, type QueryResult, type SearchResult, type StorageContext, addEpisodic, addMemory, canRead, canWrite, checkQuality, configure, configureLlm, conflictSweep, consolidateMemories, createStorageContext, deleteNote, encode, ensureCollection, generateReviewBatch, getEmbeddingDim, getEmbeddingModel, getNote, invalidateNote, isModelLoaded, isPlausibleUpdateTarget, listMemories, listNotes, llmCrudDecision, loadModel, mergeSimilarNotes, migrateCollection, patchNotePayload, pingQdrant, resolveCrudUpdateMinSim, scanLowQuality, searchMemory, updateNote };
515
+ export { type AgentAmemConfig, type AmemPluginConfig, type ConflictMode, type ConflictSweepResult, DEFAULT_CRUD_UPDATE_MIN_SIM, DEFAULT_EMBEDDING_MODEL, EmbeddingDimensionMismatchError, type EvolutionEntry, type LlmConfig, type LowQualityItem, type LowQualityReason, type MemoryNote, type MemoryOperation, type MigrateResult, type PoolingMode, type QueryResult, type SearchResult, type StorageContext, addEpisodic, addMemory, canRead, canWrite, checkQuality, configure, configureLlm, conflictSweep, consolidateMemories, createStorageContext, deleteNote, encode, ensureCollection, generateReviewBatch, getEmbeddingDim, getEmbeddingModel, getEmbeddingPooling, getNote, invalidateNote, isModelLoaded, isPlausibleUpdateTarget, listMemories, listNotes, llmCrudDecision, loadModel, mergeSimilarNotes, migrateCollection, patchNotePayload, pingQdrant, resolveCrudUpdateMinSim, scanLowQuality, searchMemory, updateNote };
package/dist/index.js CHANGED
@@ -18,6 +18,25 @@ var DEFAULT_EMBEDDING_MODEL = "Xenova/paraphrase-multilingual-MiniLM-L12-v2";
18
18
  function getEmbeddingModel() {
19
19
  return process.env.AMEM_EMBED_MODEL?.trim() || DEFAULT_EMBEDDING_MODEL;
20
20
  }
21
+ var CLS_POOLED_MODELS = /* @__PURE__ */ new Set([
22
+ "bge-m3",
23
+ "bge-base-zh-v1.5",
24
+ "bge-small-zh-v1.5",
25
+ "bge-base-en-v1.5",
26
+ "bge-small-en-v1.5",
27
+ "bge-large-en-v1.5",
28
+ "gte-multilingual-base",
29
+ "gte-modernbert-base",
30
+ "gte-large-en-v1.5",
31
+ "snowflake-arctic-embed-m",
32
+ "snowflake-arctic-embed-l"
33
+ ]);
34
+ function getEmbeddingPooling() {
35
+ const explicit = process.env.AMEM_EMBED_POOLING?.trim().toLowerCase();
36
+ if (explicit === "mean" || explicit === "cls") return explicit;
37
+ const basename2 = getEmbeddingModel().split("/").pop()?.toLowerCase() ?? "";
38
+ return CLS_POOLED_MODELS.has(basename2) ? "cls" : "mean";
39
+ }
21
40
  async function getExtractor() {
22
41
  const wanted = getEmbeddingModel();
23
42
  if (extractor && loadedModelName === wanted) return extractor;
@@ -38,21 +57,25 @@ async function getEmbeddingDim() {
38
57
  cachedDim = probe.length;
39
58
  return cachedDim;
40
59
  }
41
- function meanPoolingNormalize(output, attentionMask) {
60
+ function poolNormalize(output, attentionMask, mode) {
42
61
  const seqLen = output.length;
43
62
  const dim = output[0].length;
44
63
  const pooled = new Array(dim).fill(0);
45
- let maskSum = 0;
46
- for (let i = 0; i < seqLen; i++) {
47
- const m = attentionMask[i];
48
- maskSum += m;
64
+ if (mode === "cls") {
65
+ for (let j = 0; j < dim; j++) pooled[j] = output[0][j];
66
+ } else {
67
+ let maskSum = 0;
68
+ for (let i = 0; i < seqLen; i++) {
69
+ const m = attentionMask[i];
70
+ maskSum += m;
71
+ for (let j = 0; j < dim; j++) {
72
+ pooled[j] += output[i][j] * m;
73
+ }
74
+ }
49
75
  for (let j = 0; j < dim; j++) {
50
- pooled[j] += output[i][j] * m;
76
+ pooled[j] /= Math.max(maskSum, 1e-9);
51
77
  }
52
78
  }
53
- for (let j = 0; j < dim; j++) {
54
- pooled[j] /= Math.max(maskSum, 1e-9);
55
- }
56
79
  let norm = 0;
57
80
  for (const v of pooled) norm += v * v;
58
81
  norm = Math.sqrt(norm);
@@ -60,7 +83,8 @@ function meanPoolingNormalize(output, attentionMask) {
60
83
  }
61
84
  async function encode(text) {
62
85
  const ext = await getExtractor();
63
- const result = await ext(text, { pooling: "mean", normalize: true });
86
+ const pooling = getEmbeddingPooling();
87
+ const result = await ext(text, { pooling, normalize: true });
64
88
  if (result && result.data) {
65
89
  return Array.from(result.data);
66
90
  }
@@ -76,7 +100,7 @@ async function encode(text) {
76
100
  }
77
101
  raw.push(row);
78
102
  }
79
- return meanPoolingNormalize(raw, new Array(seqLen).fill(1));
103
+ return poolNormalize(raw, new Array(seqLen).fill(1), pooling);
80
104
  }
81
105
  throw new Error("Unexpected embedding output shape");
82
106
  }
@@ -2278,6 +2302,7 @@ export {
2278
2302
  generateReviewBatch,
2279
2303
  getEmbeddingDim,
2280
2304
  getEmbeddingModel,
2305
+ getEmbeddingPooling,
2281
2306
  getNote,
2282
2307
  invalidateNote,
2283
2308
  isModelLoaded,