mem-os-python 1.6.27__py3-none-any.whl
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.
- mem_os_python-1.6.27.dist-info/METADATA +1032 -0
- mem_os_python-1.6.27.dist-info/RECORD +253 -0
- mem_os_python-1.6.27.dist-info/WHEEL +4 -0
- mem_os_python-1.6.27.dist-info/entry_points.txt +2 -0
- mem_os_python-1.6.27.dist-info/licenses/LICENSE +21 -0
- memos/__init__.py +16 -0
- memos/_js/adapters/anthropic.d.ts +279 -0
- memos/_js/adapters/anthropic.d.ts.map +1 -0
- memos/_js/adapters/anthropic.js +348 -0
- memos/_js/adapters/anthropic.js.map +1 -0
- memos/_js/adapters/base.d.ts +10 -0
- memos/_js/adapters/base.d.ts.map +1 -0
- memos/_js/adapters/base.js +2 -0
- memos/_js/adapters/base.js.map +1 -0
- memos/_js/adapters/openai.d.ts +264 -0
- memos/_js/adapters/openai.d.ts.map +1 -0
- memos/_js/adapters/openai.js +342 -0
- memos/_js/adapters/openai.js.map +1 -0
- memos/_js/apps/explorer.d.ts +244 -0
- memos/_js/apps/explorer.d.ts.map +1 -0
- memos/_js/apps/explorer.js +738 -0
- memos/_js/apps/explorer.js.map +1 -0
- memos/_js/citations.d.ts +65 -0
- memos/_js/citations.d.ts.map +1 -0
- memos/_js/citations.js +143 -0
- memos/_js/citations.js.map +1 -0
- memos/_js/cli-browse.d.ts +3 -0
- memos/_js/cli-browse.d.ts.map +1 -0
- memos/_js/cli-browse.js +129 -0
- memos/_js/cli-browse.js.map +1 -0
- memos/_js/cli-completion.d.ts +31 -0
- memos/_js/cli-completion.d.ts.map +1 -0
- memos/_js/cli-completion.js +340 -0
- memos/_js/cli-completion.js.map +1 -0
- memos/_js/cli-help.d.ts +18 -0
- memos/_js/cli-help.d.ts.map +1 -0
- memos/_js/cli-help.js +357 -0
- memos/_js/cli-help.js.map +1 -0
- memos/_js/cli.d.ts +28 -0
- memos/_js/cli.d.ts.map +1 -0
- memos/_js/cli.js +2880 -0
- memos/_js/cli.js.map +1 -0
- memos/_js/compression.d.ts +25 -0
- memos/_js/compression.d.ts.map +1 -0
- memos/_js/compression.js +319 -0
- memos/_js/compression.js.map +1 -0
- memos/_js/confidence-machine.d.ts +99 -0
- memos/_js/confidence-machine.d.ts.map +1 -0
- memos/_js/confidence-machine.js +222 -0
- memos/_js/confidence-machine.js.map +1 -0
- memos/_js/context-pack.d.ts +506 -0
- memos/_js/context-pack.d.ts.map +1 -0
- memos/_js/context-pack.js +1435 -0
- memos/_js/context-pack.js.map +1 -0
- memos/_js/contradictions.d.ts +160 -0
- memos/_js/contradictions.d.ts.map +1 -0
- memos/_js/contradictions.js +255 -0
- memos/_js/contradictions.js.map +1 -0
- memos/_js/dashboard.d.ts +30 -0
- memos/_js/dashboard.d.ts.map +1 -0
- memos/_js/dashboard.js +302 -0
- memos/_js/dashboard.js.map +1 -0
- memos/_js/ebbinghaus.d.ts +29 -0
- memos/_js/ebbinghaus.d.ts.map +1 -0
- memos/_js/ebbinghaus.js +32 -0
- memos/_js/ebbinghaus.js.map +1 -0
- memos/_js/embedding-queue.d.ts +190 -0
- memos/_js/embedding-queue.d.ts.map +1 -0
- memos/_js/embedding-queue.js +316 -0
- memos/_js/embedding-queue.js.map +1 -0
- memos/_js/embeddings.d.ts +187 -0
- memos/_js/embeddings.d.ts.map +1 -0
- memos/_js/embeddings.js +633 -0
- memos/_js/embeddings.js.map +1 -0
- memos/_js/entity-extraction.d.ts +54 -0
- memos/_js/entity-extraction.d.ts.map +1 -0
- memos/_js/entity-extraction.js +325 -0
- memos/_js/entity-extraction.js.map +1 -0
- memos/_js/entity-index.d.ts +93 -0
- memos/_js/entity-index.d.ts.map +1 -0
- memos/_js/entity-index.js +165 -0
- memos/_js/entity-index.js.map +1 -0
- memos/_js/event-memory.d.ts +147 -0
- memos/_js/event-memory.d.ts.map +1 -0
- memos/_js/event-memory.js +290 -0
- memos/_js/event-memory.js.map +1 -0
- memos/_js/external-import.d.ts +98 -0
- memos/_js/external-import.d.ts.map +1 -0
- memos/_js/external-import.js +669 -0
- memos/_js/external-import.js.map +1 -0
- memos/_js/fidelity.d.ts +367 -0
- memos/_js/fidelity.d.ts.map +1 -0
- memos/_js/fidelity.js +911 -0
- memos/_js/fidelity.js.map +1 -0
- memos/_js/graph-expansion.d.ts +119 -0
- memos/_js/graph-expansion.d.ts.map +1 -0
- memos/_js/graph-expansion.js +213 -0
- memos/_js/graph-expansion.js.map +1 -0
- memos/_js/graph-mermaid.d.ts +13 -0
- memos/_js/graph-mermaid.d.ts.map +1 -0
- memos/_js/graph-mermaid.js +32 -0
- memos/_js/graph-mermaid.js.map +1 -0
- memos/_js/graph.d.ts +170 -0
- memos/_js/graph.d.ts.map +1 -0
- memos/_js/graph.js +482 -0
- memos/_js/graph.js.map +1 -0
- memos/_js/harness.d.ts +63 -0
- memos/_js/harness.d.ts.map +1 -0
- memos/_js/harness.js +93 -0
- memos/_js/harness.js.map +1 -0
- memos/_js/importance.d.ts +118 -0
- memos/_js/importance.d.ts.map +1 -0
- memos/_js/importance.js +144 -0
- memos/_js/importance.js.map +1 -0
- memos/_js/index.d.ts +51 -0
- memos/_js/index.d.ts.map +1 -0
- memos/_js/index.js +53 -0
- memos/_js/index.js.map +1 -0
- memos/_js/mcp.d.ts +58 -0
- memos/_js/mcp.d.ts.map +1 -0
- memos/_js/mcp.js +1853 -0
- memos/_js/mcp.js.map +1 -0
- memos/_js/memory.d.ts +1762 -0
- memos/_js/memory.d.ts.map +1 -0
- memos/_js/memory.js +6283 -0
- memos/_js/memory.js.map +1 -0
- memos/_js/procedural.d.ts +74 -0
- memos/_js/procedural.d.ts.map +1 -0
- memos/_js/procedural.js +125 -0
- memos/_js/procedural.js.map +1 -0
- memos/_js/project-config.d.ts +68 -0
- memos/_js/project-config.d.ts.map +1 -0
- memos/_js/project-config.js +59 -0
- memos/_js/project-config.js.map +1 -0
- memos/_js/proof-of-forgetting.d.ts +57 -0
- memos/_js/proof-of-forgetting.d.ts.map +1 -0
- memos/_js/proof-of-forgetting.js +80 -0
- memos/_js/proof-of-forgetting.js.map +1 -0
- memos/_js/provenance.d.ts +122 -0
- memos/_js/provenance.d.ts.map +1 -0
- memos/_js/provenance.js +182 -0
- memos/_js/provenance.js.map +1 -0
- memos/_js/quarantine-commands.d.ts +23 -0
- memos/_js/quarantine-commands.d.ts.map +1 -0
- memos/_js/quarantine-commands.js +42 -0
- memos/_js/quarantine-commands.js.map +1 -0
- memos/_js/quarantine.d.ts +120 -0
- memos/_js/quarantine.d.ts.map +1 -0
- memos/_js/quarantine.js +873 -0
- memos/_js/quarantine.js.map +1 -0
- memos/_js/redact.d.ts +12 -0
- memos/_js/redact.d.ts.map +1 -0
- memos/_js/redact.js +26 -0
- memos/_js/redact.js.map +1 -0
- memos/_js/repl.d.ts +57 -0
- memos/_js/repl.d.ts.map +1 -0
- memos/_js/repl.js +295 -0
- memos/_js/repl.js.map +1 -0
- memos/_js/rerank-local.d.ts +61 -0
- memos/_js/rerank-local.d.ts.map +1 -0
- memos/_js/rerank-local.js +210 -0
- memos/_js/rerank-local.js.map +1 -0
- memos/_js/retain-filter.d.ts +98 -0
- memos/_js/retain-filter.d.ts.map +1 -0
- memos/_js/retain-filter.js +232 -0
- memos/_js/retain-filter.js.map +1 -0
- memos/_js/retrieval.d.ts +265 -0
- memos/_js/retrieval.d.ts.map +1 -0
- memos/_js/retrieval.js +1018 -0
- memos/_js/retrieval.js.map +1 -0
- memos/_js/revert.d.ts +77 -0
- memos/_js/revert.d.ts.map +1 -0
- memos/_js/revert.js +252 -0
- memos/_js/revert.js.map +1 -0
- memos/_js/scope.d.ts +30 -0
- memos/_js/scope.d.ts.map +1 -0
- memos/_js/scope.js +71 -0
- memos/_js/scope.js.map +1 -0
- memos/_js/semantic-screen.d.ts +152 -0
- memos/_js/semantic-screen.d.ts.map +1 -0
- memos/_js/semantic-screen.js +290 -0
- memos/_js/semantic-screen.js.map +1 -0
- memos/_js/session-hooks.d.ts +127 -0
- memos/_js/session-hooks.d.ts.map +1 -0
- memos/_js/session-hooks.js +482 -0
- memos/_js/session-hooks.js.map +1 -0
- memos/_js/storage/sqlite.d.ts +427 -0
- memos/_js/storage/sqlite.d.ts.map +1 -0
- memos/_js/storage/sqlite.js +2428 -0
- memos/_js/storage/sqlite.js.map +1 -0
- memos/_js/sync.d.ts +213 -0
- memos/_js/sync.d.ts.map +1 -0
- memos/_js/sync.js +389 -0
- memos/_js/sync.js.map +1 -0
- memos/_js/tamper-log.d.ts +98 -0
- memos/_js/tamper-log.d.ts.map +1 -0
- memos/_js/tamper-log.js +327 -0
- memos/_js/tamper-log.js.map +1 -0
- memos/_js/temporal.d.ts +92 -0
- memos/_js/temporal.d.ts.map +1 -0
- memos/_js/temporal.js +536 -0
- memos/_js/temporal.js.map +1 -0
- memos/_js/time-travel.d.ts +38 -0
- memos/_js/time-travel.d.ts.map +1 -0
- memos/_js/time-travel.js +46 -0
- memos/_js/time-travel.js.map +1 -0
- memos/_js/timestamp-format.d.ts +18 -0
- memos/_js/timestamp-format.d.ts.map +1 -0
- memos/_js/timestamp-format.js +52 -0
- memos/_js/timestamp-format.js.map +1 -0
- memos/_js/triple-extraction.d.ts +31 -0
- memos/_js/triple-extraction.d.ts.map +1 -0
- memos/_js/triple-extraction.js +116 -0
- memos/_js/triple-extraction.js.map +1 -0
- memos/_js/types.d.ts +2474 -0
- memos/_js/types.d.ts.map +1 -0
- memos/_js/types.js +20 -0
- memos/_js/types.js.map +1 -0
- memos/_js/updater.d.ts +95 -0
- memos/_js/updater.d.ts.map +1 -0
- memos/_js/updater.js +268 -0
- memos/_js/updater.js.map +1 -0
- memos/_js/version.d.ts +17 -0
- memos/_js/version.d.ts.map +1 -0
- memos/_js/version.js +34 -0
- memos/_js/version.js.map +1 -0
- memos/_js/vision/clip-query-cache.d.ts +58 -0
- memos/_js/vision/clip-query-cache.d.ts.map +1 -0
- memos/_js/vision/clip-query-cache.js +79 -0
- memos/_js/vision/clip-query-cache.js.map +1 -0
- memos/_js/vision/clip.d.ts +113 -0
- memos/_js/vision/clip.d.ts.map +1 -0
- memos/_js/vision/clip.js +224 -0
- memos/_js/vision/clip.js.map +1 -0
- memos/_js/vision/fake-clip.d.ts +55 -0
- memos/_js/vision/fake-clip.d.ts.map +1 -0
- memos/_js/vision/fake-clip.js +122 -0
- memos/_js/vision/fake-clip.js.map +1 -0
- memos/_js/vision/index.d.ts +15 -0
- memos/_js/vision/index.d.ts.map +1 -0
- memos/_js/vision/index.js +13 -0
- memos/_js/vision/index.js.map +1 -0
- memos/_js/vision/store.d.ts +137 -0
- memos/_js/vision/store.d.ts.map +1 -0
- memos/_js/vision/store.js +383 -0
- memos/_js/vision/store.js.map +1 -0
- memos/adapters/__init__.py +0 -0
- memos/adapters/crewai.py +385 -0
- memos/adapters/langchain.py +301 -0
- memos/adapters/ollama.py +396 -0
- memos/server/__init__.py +0 -0
- memos/server/main.py +547 -0
- memos/server/routes.py +360 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ─── Local cross-encoder reranking ──────────────────────────────────────────
|
|
3
|
+
*
|
|
4
|
+
* In-process alternative to the HTTP `/rerank` endpoint path in
|
|
5
|
+
* `MemOS.applyRerank`. Loads a sequence-classification cross-encoder
|
|
6
|
+
* (default `Xenova/bge-reranker-base`, ~280 MB) through
|
|
7
|
+
* `@huggingface/transformers` (falling back to `@xenova/transformers`),
|
|
8
|
+
* scores `[query, document]` pairs, and returns sigmoid-squashed relevance
|
|
9
|
+
* scores in [0,1].
|
|
10
|
+
*
|
|
11
|
+
* Design rules (same as the endpoint path):
|
|
12
|
+
* - Opt-in only: nothing here runs unless `experimental.rerank` selects the
|
|
13
|
+
* local provider (or `MEMOS_RERANK_LOCAL=1`).
|
|
14
|
+
* - Any failure — missing package, model download failure, inference
|
|
15
|
+
* error — returns `null` so the caller keeps the fused ranking. A broken
|
|
16
|
+
* reranker degrades quality, never availability.
|
|
17
|
+
* - The model is loaded once per (model, dtype) and reused; the download
|
|
18
|
+
* happens on first use, so the first reranked query pays for it.
|
|
19
|
+
*/
|
|
20
|
+
import { createRequire } from "node:module";
|
|
21
|
+
export const DEFAULT_LOCAL_RERANK_MODEL = "Xenova/bge-reranker-base";
|
|
22
|
+
/** Default quantization for local rerank inference. q8 is ~4x faster on CPU. */
|
|
23
|
+
export const DEFAULT_LOCAL_RERANK_DTYPE = "q8";
|
|
24
|
+
// ─── test seam ──────────────────────────────────────────────────────────────
|
|
25
|
+
let testLoader = null;
|
|
26
|
+
/** Test-only override for the model loader (stubbed inference, no download). */
|
|
27
|
+
export function __setLocalRerankLoaderForTests(loader) {
|
|
28
|
+
testLoader = loader;
|
|
29
|
+
}
|
|
30
|
+
const modelCache = new Map();
|
|
31
|
+
let warnedMissingPackage = false;
|
|
32
|
+
/**
|
|
33
|
+
* Tokenize (query, doc) pairs for the cross-encoder. Tries the fast batched
|
|
34
|
+
* path first; some tokenizers (XLM-R family in transformers.js v4) throw on
|
|
35
|
+
* batched pair input (`text.replace is not a function`), in which case we
|
|
36
|
+
* fall back to per-pair tokenization with manual padding. Exported for tests.
|
|
37
|
+
*/
|
|
38
|
+
export async function tokenizePairsForRerank(tokenizer, pairs, maxLength) {
|
|
39
|
+
try {
|
|
40
|
+
return await tokenizer(pairs, {
|
|
41
|
+
padding: true,
|
|
42
|
+
truncation: true,
|
|
43
|
+
max_length: maxLength,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
const allIds = [];
|
|
48
|
+
const allMasks = [];
|
|
49
|
+
for (const [q, d] of pairs) {
|
|
50
|
+
const t = await tokenizer(q, {
|
|
51
|
+
text_pair: d,
|
|
52
|
+
truncation: true,
|
|
53
|
+
max_length: maxLength,
|
|
54
|
+
});
|
|
55
|
+
allIds.push(Array.from(t["input_ids"].data));
|
|
56
|
+
allMasks.push(Array.from(t["attention_mask"].data));
|
|
57
|
+
}
|
|
58
|
+
const ml = Math.max(...allIds.map((a) => a.length));
|
|
59
|
+
const B = pairs.length;
|
|
60
|
+
const padId = BigInt(tokenizer.pad_token_id ?? 1);
|
|
61
|
+
const inputIds = new BigInt64Array(B * ml);
|
|
62
|
+
const attnMask = new BigInt64Array(B * ml);
|
|
63
|
+
allIds.forEach((arr, i) => {
|
|
64
|
+
for (let j = 0; j < ml; j++) {
|
|
65
|
+
inputIds[i * ml + j] = j < arr.length ? BigInt(arr[j]) : padId;
|
|
66
|
+
attnMask[i * ml + j] = j < arr.length ? BigInt(allMasks[i][j]) : 0n;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
input_ids: { type: "int64", data: inputIds, dims: [B, ml] },
|
|
71
|
+
attention_mask: { type: "int64", data: attnMask, dims: [B, ml] },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function defaultLoader(model, dtype, maxLength) {
|
|
76
|
+
const key = `${model}::${dtype}::${maxLength}`;
|
|
77
|
+
let cached = modelCache.get(key);
|
|
78
|
+
if (!cached) {
|
|
79
|
+
cached = (async () => {
|
|
80
|
+
// Both packages are optional peer deps. We load them with
|
|
81
|
+
// `createRequire` (not dynamic `import()`): the ESM entry of
|
|
82
|
+
// `@huggingface/transformers` v4 does a named import from the CJS
|
|
83
|
+
// `onnxruntime-common` that Node's ESM loader rejects, while the
|
|
84
|
+
// CJS build loads fine.
|
|
85
|
+
const require = createRequire(import.meta.url);
|
|
86
|
+
let spec = null;
|
|
87
|
+
let resolved = null;
|
|
88
|
+
for (const candidate of [
|
|
89
|
+
"@huggingface/transformers",
|
|
90
|
+
"@xenova/transformers",
|
|
91
|
+
]) {
|
|
92
|
+
try {
|
|
93
|
+
resolved = require(candidate);
|
|
94
|
+
spec = candidate;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// try the next package
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (!resolved || !spec) {
|
|
102
|
+
if (!warnedMissingPackage) {
|
|
103
|
+
warnedMissingPackage = true;
|
|
104
|
+
console.warn("[memos] local rerank unavailable: neither @huggingface/transformers " +
|
|
105
|
+
"nor @xenova/transformers is installed — keeping fused ranking. " +
|
|
106
|
+
"Install one of them to enable local reranking.");
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const tokenizer = await resolved.AutoTokenizer.from_pretrained(model);
|
|
112
|
+
const mdl = await resolved.AutoModelForSequenceClassification.from_pretrained(model, { dtype });
|
|
113
|
+
// Raw InferenceSession: transformers.js v4 wraps input tensors in a
|
|
114
|
+
// way the installed onnxruntime-native binding rejects
|
|
115
|
+
// ("Tensor.location must be a string" — version skew between the
|
|
116
|
+
// wrapper and onnxruntime-node 1.30). Driving the session directly
|
|
117
|
+
// with tensors built from the package's OWN onnxruntime copy avoids
|
|
118
|
+
// the skew entirely.
|
|
119
|
+
const session = mdl.sessions?.["model"] ?? mdl.session;
|
|
120
|
+
if (!session) {
|
|
121
|
+
throw new Error("no inference session exposed on the loaded model");
|
|
122
|
+
}
|
|
123
|
+
const ortRequire = createRequire(require.resolve(spec));
|
|
124
|
+
const ort = ortRequire("onnxruntime-node");
|
|
125
|
+
const inputNames = session.inputNames;
|
|
126
|
+
return {
|
|
127
|
+
async scorePairs(pairs) {
|
|
128
|
+
const batch = await tokenizePairsForRerank(tokenizer, pairs, maxLength);
|
|
129
|
+
const feeds = {};
|
|
130
|
+
const batchDims = batch["input_ids"]?.dims;
|
|
131
|
+
for (const name of inputNames) {
|
|
132
|
+
let t = batch[name];
|
|
133
|
+
if (!t && name === "token_type_ids" && batchDims) {
|
|
134
|
+
// BERT-style models expect segment ids; tokenizers for
|
|
135
|
+
// single-pair cross-encoders sometimes omit them (all zeros
|
|
136
|
+
// is correct for [query, doc] pairs).
|
|
137
|
+
const size = batchDims.reduce((a, b) => a * b, 1);
|
|
138
|
+
t = {
|
|
139
|
+
type: "int64",
|
|
140
|
+
data: new BigInt64Array(size),
|
|
141
|
+
dims: [...batchDims],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (!t)
|
|
145
|
+
continue;
|
|
146
|
+
feeds[name] = new ort.Tensor(t.type, t.data, t.dims);
|
|
147
|
+
}
|
|
148
|
+
const out = await session.run(feeds);
|
|
149
|
+
const logits = out["logits"] ?? out[Object.keys(out)[0]];
|
|
150
|
+
if (!logits)
|
|
151
|
+
throw new Error("model returned no outputs");
|
|
152
|
+
const data = logits.data;
|
|
153
|
+
const rowSize = logits.dims.length >= 2
|
|
154
|
+
? logits.dims[logits.dims.length - 1]
|
|
155
|
+
: 1;
|
|
156
|
+
const result = [];
|
|
157
|
+
for (let i = 0; i < pairs.length; i += 1) {
|
|
158
|
+
result.push(Number(data[i * rowSize]));
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
console.error("[memos] local rerank model failed to load " +
|
|
166
|
+
`("${model}", dtype "${dtype}") — keeping fused ranking:`, err instanceof Error ? err.message : String(err));
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
})();
|
|
170
|
+
modelCache.set(key, cached);
|
|
171
|
+
}
|
|
172
|
+
return cached;
|
|
173
|
+
}
|
|
174
|
+
function sigmoid(x) {
|
|
175
|
+
return 1 / (1 + Math.exp(-x));
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Score each document against the query with the local cross-encoder.
|
|
179
|
+
* Returns sigmoid-squashed scores in input order, or `null` when the
|
|
180
|
+
* reranker is unavailable — the caller must keep the fused ranking.
|
|
181
|
+
*/
|
|
182
|
+
export async function scorePairsLocal(query, docs, opts = {}) {
|
|
183
|
+
if (docs.length === 0)
|
|
184
|
+
return [];
|
|
185
|
+
const model = opts.model ?? DEFAULT_LOCAL_RERANK_MODEL;
|
|
186
|
+
const dtype = opts.dtype ?? DEFAULT_LOCAL_RERANK_DTYPE;
|
|
187
|
+
const maxLength = opts.maxLength ?? 512;
|
|
188
|
+
const loader = testLoader ?? defaultLoader;
|
|
189
|
+
let loaded;
|
|
190
|
+
try {
|
|
191
|
+
loaded = await loader(model, dtype, maxLength);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
if (!loaded)
|
|
197
|
+
return null;
|
|
198
|
+
try {
|
|
199
|
+
const pairs = docs.map((doc) => [query, doc]);
|
|
200
|
+
const logits = await loaded.scorePairs(pairs);
|
|
201
|
+
if (logits.length !== docs.length)
|
|
202
|
+
return null;
|
|
203
|
+
return logits.map(sigmoid);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
console.error("[memos] local rerank inference failed — keeping fused ranking:", err instanceof Error ? err.message : String(err));
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=rerank-local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rerank-local.js","sourceRoot":"","sources":["../src/rerank-local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retain pre-filter for MemOS memory writes (v1.6.26).
|
|
3
|
+
*
|
|
4
|
+
* Hermes-style signal gate (cf. NousResearch/hermes-agent #16834): a cheap
|
|
5
|
+
* local classifier that decides whether a piece of content is worth storing in
|
|
6
|
+
* long-term memory before the write happens. Without this, every turn —
|
|
7
|
+
* including low-signal acknowledgements, chit-chat, and retries — enters
|
|
8
|
+
* memory and later bloats context-packs, costing retrieval tokens and diluting
|
|
9
|
+
* relevance ranking.
|
|
10
|
+
*
|
|
11
|
+
* Default mode is a ZERO-LLM-CALL local classifier (keeps MemOS fast and
|
|
12
|
+
* local). The *decision* is conservative-first: a write is skipped only
|
|
13
|
+
* on positive evidence of noise (empty content, pure acknowledgements,
|
|
14
|
+
* fragments, near-duplicates of existing same-scope memories) — when in
|
|
15
|
+
* doubt the memory is kept, because a false skip silently loses user
|
|
16
|
+
* data. The *score* (0–1) separately estimates signal density from
|
|
17
|
+
* length, entity/code presence, action verbs, and novelty, and is
|
|
18
|
+
* reported for debugging/telemetry. An optional custom classifier can
|
|
19
|
+
* be injected via `setRetainClassifier()`.
|
|
20
|
+
*
|
|
21
|
+
* @module @mem-os/sdk/retain-filter
|
|
22
|
+
*/
|
|
23
|
+
/** Inputs the retain gate uses to make its decision. */
|
|
24
|
+
export interface RetainInput {
|
|
25
|
+
/** The content proposed for storage. */
|
|
26
|
+
content: string;
|
|
27
|
+
/**
|
|
28
|
+
* Existing memory content in the same namespace (for novelty detection).
|
|
29
|
+
* Optional; when absent, novelty is assumed maximal.
|
|
30
|
+
*/
|
|
31
|
+
existingContent?: string[];
|
|
32
|
+
}
|
|
33
|
+
/** The gate's verdict plus the score that drove it. */
|
|
34
|
+
export interface RetainDecision {
|
|
35
|
+
/** True = store the content. */
|
|
36
|
+
retain: boolean;
|
|
37
|
+
/** Signal-density score in [0, 1]. Higher = more worth storing. */
|
|
38
|
+
score: number;
|
|
39
|
+
/** Human-readable reason for the decision (for debugging). */
|
|
40
|
+
reason: string;
|
|
41
|
+
}
|
|
42
|
+
/** Score at or above which content is retained. */
|
|
43
|
+
declare const RETAIN_THRESHOLD = 0.3;
|
|
44
|
+
/**
|
|
45
|
+
* Does this content read as a correction of something already stored?
|
|
46
|
+
*
|
|
47
|
+
* The gate's near-duplicate rule exists to stop *identical restatements*
|
|
48
|
+
* from re-entering memory. A negation/retraction ("user no longer lives in
|
|
49
|
+
* Berlin", "switched from vim to neovim") is deliberately NOT a duplicate —
|
|
50
|
+
* it is the update the confidence lifecycle exists to process, and it
|
|
51
|
+
* arrives sharing most of its tokens with the memory it retracts (a
|
|
52
|
+
* retraction necessarily names the same subject). Dropping it as a
|
|
53
|
+
* "near-duplicate" is how a retraction silently never reaches the
|
|
54
|
+
* confidence machine, leaving the old belief in place at full weight.
|
|
55
|
+
* This check reuses the SAME signal list as `classifyEvidence` so the gate
|
|
56
|
+
* and the state machine cannot drift apart.
|
|
57
|
+
*/
|
|
58
|
+
export declare function carriesContradictionSignal(content: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Max token overlap of `content` against any entry of `existingContent`
|
|
61
|
+
* (0–1). Tokens are lowercase alphanumeric words longer than 2 chars.
|
|
62
|
+
*/
|
|
63
|
+
export declare function maxTokenOverlap(content: string, existingContent: string[]): number;
|
|
64
|
+
/**
|
|
65
|
+
* Default local classifier: scores content on signal density (0-1).
|
|
66
|
+
*
|
|
67
|
+
* Components:
|
|
68
|
+
* - Length floor: tiny content scores ~0.
|
|
69
|
+
* - Signal density: entities / code refs / numbers per 100 chars.
|
|
70
|
+
* - Action / preference verbs: factual statements score higher.
|
|
71
|
+
* - Low-signal penalty: pure acknowledgements score ~0.
|
|
72
|
+
* - Novelty: down-weight content that duplicates existing memory.
|
|
73
|
+
*
|
|
74
|
+
* No LLM call, no I/O — runs in well under 1ms.
|
|
75
|
+
*/
|
|
76
|
+
export declare function scoreRetain(input: RetainInput): number;
|
|
77
|
+
/**
|
|
78
|
+
* Decide whether to retain (store) content. Default uses the local
|
|
79
|
+
* classifier; callers can inject a custom classifier via
|
|
80
|
+
* `setRetainClassifier()`.
|
|
81
|
+
*
|
|
82
|
+
* Conservative-first contract (the accuracy gate): a write is skipped
|
|
83
|
+
* ONLY on positive evidence of noise —
|
|
84
|
+
* 1. empty content,
|
|
85
|
+
* 2. a pure acknowledgement ("ok", "thanks", "ok ok ok", …),
|
|
86
|
+
* 3. a fragment with almost no alphanumeric content ("...", "k"),
|
|
87
|
+
* 4. a near-duplicate of an existing same-scope memory.
|
|
88
|
+
* Everything else is retained. When in doubt, keep the memory — a
|
|
89
|
+
* false skip silently loses user data, while a false keep only costs a
|
|
90
|
+
* little storage. `score` still reports the signal-density estimate
|
|
91
|
+
* from `scoreRetain` for debugging/telemetry.
|
|
92
|
+
*/
|
|
93
|
+
export declare function shouldRetain(input: RetainInput): RetainDecision;
|
|
94
|
+
export declare function setRetainClassifier(classifier?: (input: RetainInput) => RetainDecision): void;
|
|
95
|
+
/** Decide whether to retain, using the custom classifier if installed. */
|
|
96
|
+
export declare function decideRetain(input: RetainInput): RetainDecision;
|
|
97
|
+
export { RETAIN_THRESHOLD };
|
|
98
|
+
//# sourceMappingURL=retain-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retain-filter.d.ts","sourceRoot":"","sources":["../src/retain-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,mDAAmD;AACnD,QAAA,MAAM,gBAAgB,MAAM,CAAC;AA+C7B;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGnE;AAKD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,EAAE,GACxB,MAAM,CAqBR;AAeD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAmCtD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,CA0C/D;AAQD,wBAAgB,mBAAmB,CACjC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,cAAc,GAClD,IAAI,CAEN;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,CAG/D;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retain pre-filter for MemOS memory writes (v1.6.26).
|
|
3
|
+
*
|
|
4
|
+
* Hermes-style signal gate (cf. NousResearch/hermes-agent #16834): a cheap
|
|
5
|
+
* local classifier that decides whether a piece of content is worth storing in
|
|
6
|
+
* long-term memory before the write happens. Without this, every turn —
|
|
7
|
+
* including low-signal acknowledgements, chit-chat, and retries — enters
|
|
8
|
+
* memory and later bloats context-packs, costing retrieval tokens and diluting
|
|
9
|
+
* relevance ranking.
|
|
10
|
+
*
|
|
11
|
+
* Default mode is a ZERO-LLM-CALL local classifier (keeps MemOS fast and
|
|
12
|
+
* local). The *decision* is conservative-first: a write is skipped only
|
|
13
|
+
* on positive evidence of noise (empty content, pure acknowledgements,
|
|
14
|
+
* fragments, near-duplicates of existing same-scope memories) — when in
|
|
15
|
+
* doubt the memory is kept, because a false skip silently loses user
|
|
16
|
+
* data. The *score* (0–1) separately estimates signal density from
|
|
17
|
+
* length, entity/code presence, action verbs, and novelty, and is
|
|
18
|
+
* reported for debugging/telemetry. An optional custom classifier can
|
|
19
|
+
* be injected via `setRetainClassifier()`.
|
|
20
|
+
*
|
|
21
|
+
* @module @mem-os/sdk/retain-filter
|
|
22
|
+
*/
|
|
23
|
+
import { CONTRADICTION_SIGNALS } from "./confidence-machine.js";
|
|
24
|
+
/** Minimum content length (in chars) to consider storing. */
|
|
25
|
+
const MIN_LENGTH = 15;
|
|
26
|
+
/** Score at or above which content is retained. */
|
|
27
|
+
const RETAIN_THRESHOLD = 0.3;
|
|
28
|
+
// Action / signal verbs — presence pushes the score up.
|
|
29
|
+
const ACTION_VERBS = /\b(?:prefers?|wants?|needs?|likes?|dislikes?|uses?|chose|chooses|set|configured?|created?|added?|removed?|updated?|installed?|deployed?|named|called|works?|lives?|located?|built|built with|wrote|fixed|decided|chose|switched|migrated|adopted|disabled|enabled|changed|replaced)\b/gi;
|
|
30
|
+
const ENTITY_SIGNALS = [
|
|
31
|
+
/`[^`]+`/g, // code refs
|
|
32
|
+
/(?:[\w./-]+\.(?:ts|tsx|js|jsx|py|go|rs|md|json|yaml|yml|toml))/g, // file paths
|
|
33
|
+
/https?:\/\/[^\s,)]+/g, // urls
|
|
34
|
+
/\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)+\b/g, // proper nouns / concepts
|
|
35
|
+
/\b\d+(?:\.\d+)?(?:%|ms|s|usd|\$|x)\b/gi, // numbers with units
|
|
36
|
+
];
|
|
37
|
+
// Low-signal acknowledgement phrases — pure noise, not worth storing.
|
|
38
|
+
// Anchored: the whole content must be an acknowledgement.
|
|
39
|
+
const LOW_SIGNAL_PATTERNS = /^(?:ok|okay|sure|got it|understood|done|will do|sure thing|sounds good|great|perfect|thanks|thank you|yep|yup|no problem|of course|absolutely|right|correct|exactly|yes|no|maybe|sure|hi|hello|hey|lol|haha|k|kk|cool|nice|wow)[.!?]?$/i;
|
|
40
|
+
// Individual acknowledgement words — used to catch repeated acks
|
|
41
|
+
// ("ok ok ok", "thanks thanks") that the anchored phrase pattern misses.
|
|
42
|
+
const ACK_WORDS = /^(?:ok|okay|sure|got|it|understood|done|will|do|thing|sounds|good|great|perfect|thanks|thank|you|yep|yup|no|problem|of|course|absolutely|right|correct|exactly|yes|maybe|hi|hello|hey|lol|haha|k|kk|cool|nice|wow)$/i;
|
|
43
|
+
/**
|
|
44
|
+
* Strip trailing sentence punctuation.
|
|
45
|
+
*
|
|
46
|
+
* Hand-rolled rather than `/[.!?]+$/g`: that pattern is UNANCHORED, so the
|
|
47
|
+
* engine retries it at every offset in a long punctuation run, each retry
|
|
48
|
+
* backtracking through the rest of the run — quadratic on input like
|
|
49
|
+
* `"!!!!!…!x"` (CodeQL js/polynomial-redos). A single left-to-right scan
|
|
50
|
+
* is linear and behaves identically.
|
|
51
|
+
*/
|
|
52
|
+
function stripTrailingPunctuation(s, alsoComma = false) {
|
|
53
|
+
let end = s.length;
|
|
54
|
+
while (end > 0) {
|
|
55
|
+
const c = s.charCodeAt(end - 1);
|
|
56
|
+
// "." (46), "!" (33), "?" (63), "," (44 when alsoComma)
|
|
57
|
+
if (c !== 46 && c !== 33 && c !== 63 && !(alsoComma && c === 44))
|
|
58
|
+
break;
|
|
59
|
+
end--;
|
|
60
|
+
}
|
|
61
|
+
return end === s.length ? s : s.slice(0, end);
|
|
62
|
+
}
|
|
63
|
+
/** Near-duplicate threshold: token overlap at/above this is a duplicate. */
|
|
64
|
+
const DUPLICATE_OVERLAP = 0.85;
|
|
65
|
+
/**
|
|
66
|
+
* Does this content read as a correction of something already stored?
|
|
67
|
+
*
|
|
68
|
+
* The gate's near-duplicate rule exists to stop *identical restatements*
|
|
69
|
+
* from re-entering memory. A negation/retraction ("user no longer lives in
|
|
70
|
+
* Berlin", "switched from vim to neovim") is deliberately NOT a duplicate —
|
|
71
|
+
* it is the update the confidence lifecycle exists to process, and it
|
|
72
|
+
* arrives sharing most of its tokens with the memory it retracts (a
|
|
73
|
+
* retraction necessarily names the same subject). Dropping it as a
|
|
74
|
+
* "near-duplicate" is how a retraction silently never reaches the
|
|
75
|
+
* confidence machine, leaving the old belief in place at full weight.
|
|
76
|
+
* This check reuses the SAME signal list as `classifyEvidence` so the gate
|
|
77
|
+
* and the state machine cannot drift apart.
|
|
78
|
+
*/
|
|
79
|
+
export function carriesContradictionSignal(content) {
|
|
80
|
+
const lower = content.toLowerCase();
|
|
81
|
+
return CONTRADICTION_SIGNALS.some((w) => lower.includes(w));
|
|
82
|
+
}
|
|
83
|
+
/** Minimum alphanumeric characters for content to be storable at all. */
|
|
84
|
+
const MIN_SIGNAL_CHARS = 4;
|
|
85
|
+
/**
|
|
86
|
+
* Max token overlap of `content` against any entry of `existingContent`
|
|
87
|
+
* (0–1). Tokens are lowercase alphanumeric words longer than 2 chars.
|
|
88
|
+
*/
|
|
89
|
+
export function maxTokenOverlap(content, existingContent) {
|
|
90
|
+
const tokens = new Set(content
|
|
91
|
+
.toLowerCase()
|
|
92
|
+
.split(/[^a-z0-9]+/i)
|
|
93
|
+
.filter((w) => w.length > 2));
|
|
94
|
+
if (tokens.size === 0)
|
|
95
|
+
return 0;
|
|
96
|
+
let maxOverlap = 0;
|
|
97
|
+
for (const existing of existingContent.slice(0, 20)) {
|
|
98
|
+
const exTokens = new Set(existing
|
|
99
|
+
.toLowerCase()
|
|
100
|
+
.split(/[^a-z0-9]+/i)
|
|
101
|
+
.filter((w) => w.length > 2));
|
|
102
|
+
let overlap = 0;
|
|
103
|
+
for (const t of tokens)
|
|
104
|
+
if (exTokens.has(t))
|
|
105
|
+
overlap++;
|
|
106
|
+
maxOverlap = Math.max(maxOverlap, overlap / tokens.size);
|
|
107
|
+
}
|
|
108
|
+
return maxOverlap;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Count distinct signal indicators in the content.
|
|
112
|
+
*/
|
|
113
|
+
function countSignals(content) {
|
|
114
|
+
let count = 0;
|
|
115
|
+
for (const pattern of ENTITY_SIGNALS) {
|
|
116
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
117
|
+
const matches = content.match(regex);
|
|
118
|
+
if (matches)
|
|
119
|
+
count += new Set(matches).size;
|
|
120
|
+
}
|
|
121
|
+
return count;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Default local classifier: scores content on signal density (0-1).
|
|
125
|
+
*
|
|
126
|
+
* Components:
|
|
127
|
+
* - Length floor: tiny content scores ~0.
|
|
128
|
+
* - Signal density: entities / code refs / numbers per 100 chars.
|
|
129
|
+
* - Action / preference verbs: factual statements score higher.
|
|
130
|
+
* - Low-signal penalty: pure acknowledgements score ~0.
|
|
131
|
+
* - Novelty: down-weight content that duplicates existing memory.
|
|
132
|
+
*
|
|
133
|
+
* No LLM call, no I/O — runs in well under 1ms.
|
|
134
|
+
*/
|
|
135
|
+
export function scoreRetain(input) {
|
|
136
|
+
const { content, existingContent = [] } = input;
|
|
137
|
+
if (!content || content.trim().length < MIN_LENGTH)
|
|
138
|
+
return 0;
|
|
139
|
+
// Hard penalty for pure acknowledgement turns.
|
|
140
|
+
if (LOW_SIGNAL_PATTERNS.test(content.trim()))
|
|
141
|
+
return 0.05;
|
|
142
|
+
let score = 0;
|
|
143
|
+
// Signal density.
|
|
144
|
+
const signalCount = countSignals(content);
|
|
145
|
+
const density = Math.min(1, signalCount / 3); // 3+ signals → max density
|
|
146
|
+
score += density * 0.45;
|
|
147
|
+
// Action / preference verbs (factual statements worth remembering).
|
|
148
|
+
const verbMatches = content.match(ACTION_VERBS) ?? [];
|
|
149
|
+
const verbDensity = Math.min(1, new Set(verbMatches.map((v) => v.toLowerCase())).size / 2);
|
|
150
|
+
score += verbDensity * 0.3;
|
|
151
|
+
// Length appropriateness.
|
|
152
|
+
const len = content.trim().length;
|
|
153
|
+
score += len >= 25 && len <= 500 ? 0.15 : 0.05;
|
|
154
|
+
// Novelty: down-weight near-duplicates of existing memory.
|
|
155
|
+
if (existingContent.length > 0) {
|
|
156
|
+
score += (1 - maxTokenOverlap(content, existingContent)) * 0.1;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
score += 0.1;
|
|
160
|
+
}
|
|
161
|
+
return Math.min(1, score);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Decide whether to retain (store) content. Default uses the local
|
|
165
|
+
* classifier; callers can inject a custom classifier via
|
|
166
|
+
* `setRetainClassifier()`.
|
|
167
|
+
*
|
|
168
|
+
* Conservative-first contract (the accuracy gate): a write is skipped
|
|
169
|
+
* ONLY on positive evidence of noise —
|
|
170
|
+
* 1. empty content,
|
|
171
|
+
* 2. a pure acknowledgement ("ok", "thanks", "ok ok ok", …),
|
|
172
|
+
* 3. a fragment with almost no alphanumeric content ("...", "k"),
|
|
173
|
+
* 4. a near-duplicate of an existing same-scope memory.
|
|
174
|
+
* Everything else is retained. When in doubt, keep the memory — a
|
|
175
|
+
* false skip silently loses user data, while a false keep only costs a
|
|
176
|
+
* little storage. `score` still reports the signal-density estimate
|
|
177
|
+
* from `scoreRetain` for debugging/telemetry.
|
|
178
|
+
*/
|
|
179
|
+
export function shouldRetain(input) {
|
|
180
|
+
const score = scoreRetain(input);
|
|
181
|
+
const content = input.content ?? "";
|
|
182
|
+
const trimmed = content.trim();
|
|
183
|
+
if (trimmed.length === 0) {
|
|
184
|
+
return { retain: false, score, reason: "empty content" };
|
|
185
|
+
}
|
|
186
|
+
if (LOW_SIGNAL_PATTERNS.test(trimmed)) {
|
|
187
|
+
return { retain: false, score, reason: "low-signal acknowledgement" };
|
|
188
|
+
}
|
|
189
|
+
// Repeated acks the anchored phrase pattern misses ("ok ok ok").
|
|
190
|
+
const words = trimmed
|
|
191
|
+
.slice(0, stripTrailingPunctuation(trimmed).length)
|
|
192
|
+
.split(/\s+/)
|
|
193
|
+
.filter(Boolean);
|
|
194
|
+
if (words.length > 0 &&
|
|
195
|
+
words.every((w) => ACK_WORDS.test(stripTrailingPunctuation(w, true)))) {
|
|
196
|
+
return { retain: false, score, reason: "low-signal acknowledgement" };
|
|
197
|
+
}
|
|
198
|
+
const signalChars = trimmed.replace(/[^a-z0-9]/gi, "").length;
|
|
199
|
+
if (signalChars < MIN_SIGNAL_CHARS) {
|
|
200
|
+
return { retain: false, score, reason: "too short" };
|
|
201
|
+
}
|
|
202
|
+
const existing = input.existingContent ?? [];
|
|
203
|
+
if (existing.length > 0 &&
|
|
204
|
+
maxTokenOverlap(content, existing) >= DUPLICATE_OVERLAP &&
|
|
205
|
+
// A retraction necessarily overlaps the memory it retracts — it names
|
|
206
|
+
// the same subject. Never skip one of those as a "duplicate", or the
|
|
207
|
+
// contradiction never reaches the confidence machine.
|
|
208
|
+
!carriesContradictionSignal(trimmed)) {
|
|
209
|
+
return {
|
|
210
|
+
retain: false,
|
|
211
|
+
score,
|
|
212
|
+
reason: "near-duplicate of existing memory",
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return { retain: true, score, reason: "no noise evidence — retained" };
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Optional pluggable classifier. When set, `shouldRetain` delegates to it.
|
|
219
|
+
* Pass undefined to restore the default local classifier.
|
|
220
|
+
*/
|
|
221
|
+
let customClassifier = null;
|
|
222
|
+
export function setRetainClassifier(classifier) {
|
|
223
|
+
customClassifier = classifier ?? null;
|
|
224
|
+
}
|
|
225
|
+
/** Decide whether to retain, using the custom classifier if installed. */
|
|
226
|
+
export function decideRetain(input) {
|
|
227
|
+
if (customClassifier)
|
|
228
|
+
return customClassifier(input);
|
|
229
|
+
return shouldRetain(input);
|
|
230
|
+
}
|
|
231
|
+
export { RETAIN_THRESHOLD };
|
|
232
|
+
//# sourceMappingURL=retain-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retain-filter.js","sourceRoot":"","sources":["../src/retain-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAuBhE,6DAA6D;AAC7D,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,mDAAmD;AACnD,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,wDAAwD;AACxD,MAAM,YAAY,GAChB,yRAAyR,CAAC;AAE5R,MAAM,cAAc,GAAG;IACrB,UAAU,EAAE,YAAY;IACxB,iEAAiE,EAAE,aAAa;IAChF,sBAAsB,EAAE,OAAO;IAC/B,qCAAqC,EAAE,0BAA0B;IACjE,wCAAwC,EAAE,qBAAqB;CAChE,CAAC;AAEF,sEAAsE;AACtE,0DAA0D;AAC1D,MAAM,mBAAmB,GACvB,yOAAyO,CAAC;AAE5O,iEAAiE;AACjE,yEAAyE;AACzE,MAAM,SAAS,GACb,sNAAsN,CAAC;AAEzN;;;;;;;;GAQG;AACH,SAAS,wBAAwB,CAAC,CAAS,EAAE,SAAS,GAAG,KAAK;IAC5D,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;IACnB,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAChC,wDAAwD;QACxD,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;YAAE,MAAM;QACxE,GAAG,EAAE,CAAC;IACR,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,4EAA4E;AAC5E,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,yEAAyE;AACzE,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,eAAyB;IAEzB,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,OAAO;SACJ,WAAW,EAAE;SACb,KAAK,CAAC,aAAa,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAC/B,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,QAAQ,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CACtB,QAAQ;aACL,WAAW,EAAE;aACb,KAAK,CAAC,aAAa,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAC/B,CAAC;QACF,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAC;QACvD,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,OAAe;IACnC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,OAAO;YAAE,KAAK,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,KAAkB;IAC5C,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAEhD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,UAAU;QAAE,OAAO,CAAC,CAAC;IAE7D,+CAA+C;IAC/C,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1D,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,kBAAkB;IAClB,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,2BAA2B;IACzE,KAAK,IAAI,OAAO,GAAG,IAAI,CAAC;IAExB,oEAAoE;IACpE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC1B,CAAC,EACD,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAC1D,CAAC;IACF,KAAK,IAAI,WAAW,GAAG,GAAG,CAAC;IAE3B,0BAA0B;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC;IAClC,KAAK,IAAI,GAAG,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAE/C,2DAA2D;IAC3D,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,IAAI,CAAC,CAAC,GAAG,eAAe,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,GAAG,GAAG,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,KAAK,IAAI,GAAG,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAE/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC;IACxE,CAAC;IACD,iEAAiE;IACjE,MAAM,KAAK,GAAG,OAAO;SAClB,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;SAClD,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,OAAO,CAAC,CAAC;IACnB,IACE,KAAK,CAAC,MAAM,GAAG,CAAC;QAChB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EACrE,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAC;IACxE,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC;IAC9D,IAAI,WAAW,GAAG,gBAAgB,EAAE,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACvD,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC;IAC7C,IACE,QAAQ,CAAC,MAAM,GAAG,CAAC;QACnB,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,iBAAiB;QACvD,sEAAsE;QACtE,qEAAqE;QACrE,sDAAsD;QACtD,CAAC,0BAA0B,CAAC,OAAO,CAAC,EACpC,CAAC;QACD,OAAO;YACL,MAAM,EAAE,KAAK;YACb,KAAK;YACL,MAAM,EAAE,mCAAmC;SAC5C,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,IAAI,gBAAgB,GAAoD,IAAI,CAAC;AAE7E,MAAM,UAAU,mBAAmB,CACjC,UAAmD;IAEnD,gBAAgB,GAAG,UAAU,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,KAAkB;IAC7C,IAAI,gBAAgB;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACrD,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|