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,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmbeddingQueue — bounded, retryable, event-emitting background worker
|
|
3
|
+
* pool for embedding generation.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: the previous MemOS engine called `provider.embed()` inline
|
|
6
|
+
* from `store()` and `update()`. For local-hash that costs nothing, but the
|
|
7
|
+
* moment a user points MemOS at Ollama, LM Studio, or any OpenAI-compatible
|
|
8
|
+
* endpoint, every write blocks for the full round-trip. This queue lets
|
|
9
|
+
* `store()` return as soon as the node is persisted, with the embedding work
|
|
10
|
+
* happening in the background under a bounded concurrency cap.
|
|
11
|
+
*
|
|
12
|
+
* Design:
|
|
13
|
+
* - One shared queue per MemOS instance.
|
|
14
|
+
* - `enqueue()` is fire-and-forget — returns a job id immediately.
|
|
15
|
+
* - Workers are pulled in FIFO order. Concurrency is bounded by
|
|
16
|
+
* `EmbeddingQueueConfig.concurrency` (default 2).
|
|
17
|
+
* - When `batchSize` > 1 and the provider implements `batchEmbed`,
|
|
18
|
+
* a worker drains up to `batchSize` pending jobs into one batched
|
|
19
|
+
* call; a failed batch falls back to per-job retries.
|
|
20
|
+
* - Failures are retried with exponential backoff up to `maxRetries`
|
|
21
|
+
* (default 3) before the job is marked `failed` and an
|
|
22
|
+
* `embedding:failed` event fires.
|
|
23
|
+
* - Backpressure: if `maxQueueSize` is exceeded, `enqueue()` throws
|
|
24
|
+
* instead of growing memory unbounded. Callers can `await flush()`
|
|
25
|
+
* to make room.
|
|
26
|
+
* - Lifecycle events: `embedding:queued`, `embedding:started`,
|
|
27
|
+
* `embedding:complete`, `embedding:failed`, `embedding:retry`.
|
|
28
|
+
*
|
|
29
|
+
* The queue does not know about storage. It only knows how to call the
|
|
30
|
+
* `EmbeddingProvider`. Persistence of the resulting vector is the
|
|
31
|
+
* responsibility of the caller (a `persist` callback) so this module
|
|
32
|
+
* stays storage-agnostic and easy to test.
|
|
33
|
+
*
|
|
34
|
+
* @module @memos/embedding-queue
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_CONCURRENCY = 2;
|
|
37
|
+
const DEFAULT_BATCH_SIZE = 1;
|
|
38
|
+
const DEFAULT_MAX_QUEUE_SIZE = 10_000;
|
|
39
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
40
|
+
const DEFAULT_RETRY_BACKOFF_MS = 250;
|
|
41
|
+
const DEFAULT_BATCH_LINGER_MS = 5;
|
|
42
|
+
/** Generate a short, unique job id without pulling in a uuid dep. */
|
|
43
|
+
function generateJobId() {
|
|
44
|
+
return `emb-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Bounded, retryable, non-blocking embedding queue.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const queue = new EmbeddingQueue({
|
|
52
|
+
* provider,
|
|
53
|
+
* concurrency: 4,
|
|
54
|
+
* onPersist: async (nodeId, vector, model) => {
|
|
55
|
+
* await storage.saveEmbedding(nodeId, vector, model);
|
|
56
|
+
* },
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* const jobId = queue.enqueue(node.id, text);
|
|
60
|
+
* await queue.flush();
|
|
61
|
+
* await queue.close();
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export class EmbeddingQueue {
|
|
65
|
+
provider;
|
|
66
|
+
concurrency;
|
|
67
|
+
batchSize;
|
|
68
|
+
maxQueueSize;
|
|
69
|
+
maxRetries;
|
|
70
|
+
retryBackoffMs;
|
|
71
|
+
batchLingerMs;
|
|
72
|
+
onPersist;
|
|
73
|
+
onStatusChange;
|
|
74
|
+
/** Pending jobs not yet picked up by a worker. */
|
|
75
|
+
pending = [];
|
|
76
|
+
/** Currently running job groups, by worker slot index. */
|
|
77
|
+
running;
|
|
78
|
+
/** Job index by id, for status queries. */
|
|
79
|
+
jobs = new Map();
|
|
80
|
+
/** Resolvers for `flush()` callers, resolved when the queue drains. */
|
|
81
|
+
drainWaiters = [];
|
|
82
|
+
/** Set true after `close()` so enqueue can reject and workers exit. */
|
|
83
|
+
closed = false;
|
|
84
|
+
/** Guards one-at-a-time deferred group pickup (see schedule()). */
|
|
85
|
+
scheduleQueued = false;
|
|
86
|
+
constructor(config) {
|
|
87
|
+
this.provider = config.provider;
|
|
88
|
+
this.concurrency = Math.max(1, config.concurrency ?? DEFAULT_CONCURRENCY);
|
|
89
|
+
this.batchSize = Math.max(1, config.batchSize ?? DEFAULT_BATCH_SIZE);
|
|
90
|
+
this.maxQueueSize = Math.max(1, config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE);
|
|
91
|
+
this.maxRetries = Math.max(0, config.maxRetries ?? DEFAULT_MAX_RETRIES);
|
|
92
|
+
this.retryBackoffMs = Math.max(0, config.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS);
|
|
93
|
+
this.batchLingerMs = Math.max(0, config.batchLingerMs ?? DEFAULT_BATCH_LINGER_MS);
|
|
94
|
+
this.onPersist = config.onPersist;
|
|
95
|
+
this.onStatusChange = config.onStatusChange;
|
|
96
|
+
this.running = new Array(this.concurrency).fill(null);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Enqueue an embedding job. Returns a job id immediately.
|
|
100
|
+
*
|
|
101
|
+
* @throws if the queue is full or has been closed.
|
|
102
|
+
*/
|
|
103
|
+
enqueue(nodeId, text) {
|
|
104
|
+
if (this.closed) {
|
|
105
|
+
throw new Error("EmbeddingQueue is closed.");
|
|
106
|
+
}
|
|
107
|
+
if (this.pending.length + this.activeCount() >= this.maxQueueSize) {
|
|
108
|
+
throw new Error(`EmbeddingQueue is full (${this.maxQueueSize} jobs). ` +
|
|
109
|
+
`Call await queue.flush() to make room.`);
|
|
110
|
+
}
|
|
111
|
+
const job = {
|
|
112
|
+
id: generateJobId(),
|
|
113
|
+
nodeId,
|
|
114
|
+
text,
|
|
115
|
+
status: "queued",
|
|
116
|
+
attempts: 0,
|
|
117
|
+
lastError: null,
|
|
118
|
+
enqueuedAt: Date.now(),
|
|
119
|
+
updatedAt: Date.now(),
|
|
120
|
+
vector: null,
|
|
121
|
+
model: null,
|
|
122
|
+
};
|
|
123
|
+
this.pending.push(job);
|
|
124
|
+
this.jobs.set(job.id, job);
|
|
125
|
+
this.notifyStatus(job, "queued", null);
|
|
126
|
+
this.schedule();
|
|
127
|
+
return job.id;
|
|
128
|
+
}
|
|
129
|
+
/** Number of jobs currently waiting or running. */
|
|
130
|
+
size() {
|
|
131
|
+
return this.pending.length + this.activeCount();
|
|
132
|
+
}
|
|
133
|
+
/** Number of jobs currently being processed. */
|
|
134
|
+
activeCount() {
|
|
135
|
+
let n = 0;
|
|
136
|
+
for (const group of this.running) {
|
|
137
|
+
if (group)
|
|
138
|
+
n += group.length;
|
|
139
|
+
}
|
|
140
|
+
return n;
|
|
141
|
+
}
|
|
142
|
+
/** Return a snapshot of a job by id, or null if unknown. */
|
|
143
|
+
getJob(id) {
|
|
144
|
+
const j = this.jobs.get(id);
|
|
145
|
+
return j ? { ...j } : null;
|
|
146
|
+
}
|
|
147
|
+
/** Return all jobs that are not in a terminal state. */
|
|
148
|
+
pendingJobs() {
|
|
149
|
+
const out = [];
|
|
150
|
+
for (const j of this.jobs.values()) {
|
|
151
|
+
if (j.status === "queued" ||
|
|
152
|
+
j.status === "running" ||
|
|
153
|
+
j.status === "retrying") {
|
|
154
|
+
out.push({ ...j });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Wait for the queue to drain. Resolves when both `pending` and
|
|
161
|
+
* `running` are empty. If the queue is already drained, resolves on
|
|
162
|
+
* the next microtask.
|
|
163
|
+
*/
|
|
164
|
+
async flush() {
|
|
165
|
+
if (this.size() === 0)
|
|
166
|
+
return;
|
|
167
|
+
await new Promise((resolve) => this.drainWaiters.push(resolve));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Permanently stop the queue. In-flight jobs are allowed to finish
|
|
171
|
+
* (and their persist callbacks run) but no new work is accepted.
|
|
172
|
+
*/
|
|
173
|
+
async close() {
|
|
174
|
+
this.closed = true;
|
|
175
|
+
await this.flush();
|
|
176
|
+
}
|
|
177
|
+
// --------------------------------------------------------------------------
|
|
178
|
+
// Internal
|
|
179
|
+
// --------------------------------------------------------------------------
|
|
180
|
+
notifyStatus(job, status, error) {
|
|
181
|
+
job.status = status;
|
|
182
|
+
job.updatedAt = Date.now();
|
|
183
|
+
job.lastError = error;
|
|
184
|
+
if (this.onStatusChange) {
|
|
185
|
+
try {
|
|
186
|
+
const result = this.onStatusChange(job.nodeId, status, error);
|
|
187
|
+
if (result && typeof result.then === "function") {
|
|
188
|
+
// Best-effort: do not await persistence callbacks in status notify.
|
|
189
|
+
result.catch(() => undefined);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Status-callback errors are non-fatal.
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Pull pending jobs into idle worker slots. The actual pickup is
|
|
199
|
+
* deferred by one microtask so a synchronous enqueue burst (e.g. an
|
|
200
|
+
* ingestion loop storing N memories back-to-back) coalesces into
|
|
201
|
+
* full `batchSize` groups instead of starting a half-empty group per
|
|
202
|
+
* enqueue.
|
|
203
|
+
*/
|
|
204
|
+
schedule() {
|
|
205
|
+
if (this.scheduleQueued)
|
|
206
|
+
return;
|
|
207
|
+
this.scheduleQueued = true;
|
|
208
|
+
// Coalescing linger: when the queue is fully idle, wait `batchLingerMs`
|
|
209
|
+
// before picking up work so rapid sequential enqueues (e.g. `await
|
|
210
|
+
// store()` in a loop) form full `batchSize` groups instead of one
|
|
211
|
+
// single-job group each. While workers are already busy, pending jobs
|
|
212
|
+
// accumulate on their own — pick those up immediately with no added
|
|
213
|
+
// latency. A linger of 0 restores the immediate microtask pickup.
|
|
214
|
+
const lingerIdle = this.batchLingerMs > 0 && this.activeCount() === 0;
|
|
215
|
+
if (!lingerIdle) {
|
|
216
|
+
queueMicrotask(() => {
|
|
217
|
+
this.scheduleQueued = false;
|
|
218
|
+
this.scheduleNow();
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
setTimeout(() => {
|
|
223
|
+
this.scheduleQueued = false;
|
|
224
|
+
this.scheduleNow();
|
|
225
|
+
}, this.batchLingerMs);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
scheduleNow() {
|
|
229
|
+
for (let i = 0; i < this.running.length; i += 1) {
|
|
230
|
+
if (this.running[i] !== null)
|
|
231
|
+
continue;
|
|
232
|
+
if (this.pending.length === 0)
|
|
233
|
+
break;
|
|
234
|
+
const group = this.pending.splice(0, this.batchSize);
|
|
235
|
+
this.running[i] = group;
|
|
236
|
+
// Fire-and-forget worker loop.
|
|
237
|
+
void this.runGroup(i, group);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async runGroup(slot, group) {
|
|
241
|
+
const canBatch = group.length > 1 && typeof this.provider.batchEmbed === "function";
|
|
242
|
+
if (!canBatch) {
|
|
243
|
+
for (const job of group) {
|
|
244
|
+
await this.runJobWithRetries(job);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
for (const job of group) {
|
|
249
|
+
this.notifyStatus(job, "running", null);
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const vectors = await this.provider.batchEmbed(group.map((job) => job.text));
|
|
253
|
+
for (const [index, job] of group.entries()) {
|
|
254
|
+
job.attempts = 1;
|
|
255
|
+
job.vector = vectors[index] ?? null;
|
|
256
|
+
job.model = this.provider.model;
|
|
257
|
+
if (this.onPersist) {
|
|
258
|
+
await this.onPersist(job.nodeId, job.vector, this.provider.model);
|
|
259
|
+
}
|
|
260
|
+
this.notifyStatus(job, "complete", null);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// The batch as a whole failed — fall back to the per-job retry
|
|
265
|
+
// path so one poisoned text cannot silently fail its whole group.
|
|
266
|
+
for (const job of group) {
|
|
267
|
+
job.attempts = 0;
|
|
268
|
+
await this.runJobWithRetries(job);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
this.running[slot] = null;
|
|
273
|
+
this.afterJob();
|
|
274
|
+
}
|
|
275
|
+
async runJobWithRetries(job) {
|
|
276
|
+
this.notifyStatus(job, "running", null);
|
|
277
|
+
let attempt = 0;
|
|
278
|
+
let lastError = null;
|
|
279
|
+
while (attempt <= this.maxRetries) {
|
|
280
|
+
attempt += 1;
|
|
281
|
+
job.attempts = attempt;
|
|
282
|
+
try {
|
|
283
|
+
const vector = await this.provider.embed(job.text);
|
|
284
|
+
job.vector = vector;
|
|
285
|
+
job.model = this.provider.model;
|
|
286
|
+
if (this.onPersist) {
|
|
287
|
+
await this.onPersist(job.nodeId, vector, this.provider.model);
|
|
288
|
+
}
|
|
289
|
+
this.notifyStatus(job, "complete", null);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
294
|
+
if (attempt > this.maxRetries)
|
|
295
|
+
break;
|
|
296
|
+
const delay = this.retryBackoffMs * Math.pow(2, attempt - 1);
|
|
297
|
+
this.notifyStatus(job, "retrying", lastError.message);
|
|
298
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
299
|
+
// Mark the next attempt as running so observers see the transition.
|
|
300
|
+
this.notifyStatus(job, "running", null);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
this.notifyStatus(job, "failed", lastError ? lastError.message : "unknown error");
|
|
304
|
+
}
|
|
305
|
+
/** After a worker slot frees, schedule the next pending job and
|
|
306
|
+
* resolve any flush() waiters that are now satisfied. */
|
|
307
|
+
afterJob() {
|
|
308
|
+
this.schedule();
|
|
309
|
+
if (this.size() === 0 && this.drainWaiters.length > 0) {
|
|
310
|
+
const waiters = this.drainWaiters.splice(0, this.drainWaiters.length);
|
|
311
|
+
for (const w of waiters)
|
|
312
|
+
w();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=embedding-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedding-queue.js","sourceRoot":"","sources":["../src/embedding-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import type { EmbeddingConfig, EmbeddingProvider, EmbeddingRuntimeInfo, EmbeddingVector } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Strip all trailing slash characters from a URL/base path without using a
|
|
4
|
+
* regular expression. Avoids a ReDoS-flagged `/+$/` pattern on user-supplied
|
|
5
|
+
* input (CodeQL js/regular-expression-polynomial-redos).
|
|
6
|
+
*/
|
|
7
|
+
export declare function stripTrailingSlashes(url: string): string;
|
|
8
|
+
export declare function normalizeVector(vector: EmbeddingVector): EmbeddingVector;
|
|
9
|
+
export declare function cosineSimilarity(a: ArrayLike<number>, b: ArrayLike<number>): number;
|
|
10
|
+
export declare class LocalHashEmbeddingProvider implements EmbeddingProvider {
|
|
11
|
+
readonly id = "local-hash";
|
|
12
|
+
readonly model: string;
|
|
13
|
+
readonly dimensions: number;
|
|
14
|
+
constructor(options?: {
|
|
15
|
+
dimensions?: number;
|
|
16
|
+
model?: string;
|
|
17
|
+
});
|
|
18
|
+
embed(text: string): Promise<EmbeddingVector>;
|
|
19
|
+
}
|
|
20
|
+
export declare class OllamaEmbeddingProvider implements EmbeddingProvider {
|
|
21
|
+
readonly id = "ollama";
|
|
22
|
+
readonly model: string;
|
|
23
|
+
readonly dimensions: number;
|
|
24
|
+
private readonly baseUrl;
|
|
25
|
+
private readonly queryPrefix;
|
|
26
|
+
private readonly documentPrefix;
|
|
27
|
+
constructor(options?: {
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
model?: string;
|
|
30
|
+
dimensions?: number;
|
|
31
|
+
/** Optional string prepended to QUERY text before embedding. Many
|
|
32
|
+
* retrieval models (Liquid E / e5, nomic with a prompt) are
|
|
33
|
+
* trained for an asymmetric query/document setting and expect an
|
|
34
|
+
* instruction on the query side, e.g. "query: ". Empty by default
|
|
35
|
+
* = backward compatible. */
|
|
36
|
+
queryPrefix?: string;
|
|
37
|
+
/** Optional string prepended to DOCUMENT text (the index-side
|
|
38
|
+
* content) before embedding, e.g. "document: " for Liquid
|
|
39
|
+
* LFM2.5-Embedding / e5. Applied by `embed()`/`batchEmbed()` but
|
|
40
|
+
* NOT by `embedQuery()`, which applies `queryPrefix` only. Empty
|
|
41
|
+
* by default = backward compatible. */
|
|
42
|
+
documentPrefix?: string;
|
|
43
|
+
});
|
|
44
|
+
private callEmbed;
|
|
45
|
+
embed(text: string): Promise<EmbeddingVector>;
|
|
46
|
+
/**
|
|
47
|
+
* Query embedding applies the configured `queryPrefix`, when set, so the
|
|
48
|
+
* retrieval question is embedded in the model's query mode. Documents are
|
|
49
|
+
* embedded WITHOUT the prefix (plain indexing text).
|
|
50
|
+
*/
|
|
51
|
+
embedQuery(text: string): Promise<EmbeddingVector>;
|
|
52
|
+
batchEmbed(texts: string[]): Promise<EmbeddingVector[]>;
|
|
53
|
+
embedDocuments(texts: string[]): Promise<EmbeddingVector[]>;
|
|
54
|
+
}
|
|
55
|
+
export declare class OpenAICompatibleEmbeddingProvider implements EmbeddingProvider {
|
|
56
|
+
readonly id = "openai-compatible";
|
|
57
|
+
readonly model: string;
|
|
58
|
+
readonly dimensions: number;
|
|
59
|
+
private readonly baseUrl;
|
|
60
|
+
private readonly apiKey;
|
|
61
|
+
private readonly queryPrefix;
|
|
62
|
+
private readonly documentPrefix;
|
|
63
|
+
constructor(options: {
|
|
64
|
+
baseUrl?: string;
|
|
65
|
+
apiKey?: string;
|
|
66
|
+
model?: string;
|
|
67
|
+
dimensions?: number;
|
|
68
|
+
/** Prepended to QUERY text by `embedQuery()`. Asymmetric retrieval
|
|
69
|
+
* models served over OpenAI-compatible endpoints (e.g. Liquid
|
|
70
|
+
* LFM2.5-Embedding via llama.cpp, e5 via vLLM) are trained with a
|
|
71
|
+
* query-side instruction — e.g. "query: " — and silently degrade
|
|
72
|
+
* without it. Empty by default = backward compatible. */
|
|
73
|
+
queryPrefix?: string;
|
|
74
|
+
/** Prepended to DOCUMENT text by `embed()`/`batchEmbed()` — e.g.
|
|
75
|
+
* "document: " for Liquid LFM2.5-Embedding / e5 index-side text.
|
|
76
|
+
* `embedQuery()` applies `queryPrefix` only. Empty by default. */
|
|
77
|
+
documentPrefix?: string;
|
|
78
|
+
});
|
|
79
|
+
private callEmbeddings;
|
|
80
|
+
embed(text: string): Promise<EmbeddingVector>;
|
|
81
|
+
embedQuery(text: string): Promise<EmbeddingVector>;
|
|
82
|
+
batchEmbed(texts: string[]): Promise<EmbeddingVector[]>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Voyage AI embedding provider.
|
|
86
|
+
*
|
|
87
|
+
* Voyage's `voyage-3` family is the strongest open-weight-class
|
|
88
|
+
* retrieval model we can hit over HTTP, and it's a common default
|
|
89
|
+
* for serious RAG work. The provider uses the public
|
|
90
|
+
* `https://api.voyageai.com/v1/embeddings` endpoint and Bearer auth.
|
|
91
|
+
*/
|
|
92
|
+
export declare class VoyageAIEmbeddingProvider implements EmbeddingProvider {
|
|
93
|
+
readonly id = "voyage";
|
|
94
|
+
readonly model: string;
|
|
95
|
+
readonly dimensions: number;
|
|
96
|
+
private readonly apiKey;
|
|
97
|
+
private readonly baseUrl;
|
|
98
|
+
constructor(options?: {
|
|
99
|
+
apiKey?: string;
|
|
100
|
+
model?: string;
|
|
101
|
+
dimensions?: number;
|
|
102
|
+
baseUrl?: string;
|
|
103
|
+
});
|
|
104
|
+
embed(text: string): Promise<EmbeddingVector>;
|
|
105
|
+
batchEmbed(texts: string[]): Promise<EmbeddingVector[]>;
|
|
106
|
+
private callEmbeddings;
|
|
107
|
+
}
|
|
108
|
+
export declare function createEmbeddingProvider(config: EmbeddingConfig | undefined): EmbeddingProvider;
|
|
109
|
+
/**
|
|
110
|
+
* Cohere embed-v3 embedding provider.
|
|
111
|
+
*
|
|
112
|
+
* Cohere's `embed-english-v3.0` (and its multilingual sibling) is a
|
|
113
|
+
* strong default for English retrieval. The provider hits
|
|
114
|
+
* `https://api.cohere.ai/v1/embed` and returns a normalized vector.
|
|
115
|
+
*/
|
|
116
|
+
export declare class CohereEmbeddingProvider implements EmbeddingProvider {
|
|
117
|
+
readonly id = "cohere";
|
|
118
|
+
readonly model: string;
|
|
119
|
+
readonly dimensions: number;
|
|
120
|
+
private readonly apiKey;
|
|
121
|
+
private readonly baseUrl;
|
|
122
|
+
private readonly inputType;
|
|
123
|
+
constructor(options?: {
|
|
124
|
+
apiKey?: string;
|
|
125
|
+
model?: string;
|
|
126
|
+
dimensions?: number;
|
|
127
|
+
baseUrl?: string;
|
|
128
|
+
inputType?: string;
|
|
129
|
+
});
|
|
130
|
+
embed(text: string): Promise<EmbeddingVector>;
|
|
131
|
+
batchEmbed(texts: string[]): Promise<EmbeddingVector[]>;
|
|
132
|
+
private callEmbed;
|
|
133
|
+
}
|
|
134
|
+
export declare class FastEmbedEmbeddingProvider implements EmbeddingProvider {
|
|
135
|
+
readonly id = "fastembed";
|
|
136
|
+
readonly model: string;
|
|
137
|
+
readonly dimensions: number;
|
|
138
|
+
private pipeline;
|
|
139
|
+
private resolved;
|
|
140
|
+
/**
|
|
141
|
+
* Set when the transformers pipeline could NOT be loaded and the
|
|
142
|
+
* deterministic local hash fallback is serving embeddings instead.
|
|
143
|
+
* Null while unresolved or when the real model loaded fine. Exposed
|
|
144
|
+
* via `getRuntimeInfo()` so benchmarks can detect — and optionally
|
|
145
|
+
* refuse to run on — the fallback.
|
|
146
|
+
*/
|
|
147
|
+
private fallbackReason;
|
|
148
|
+
constructor(options?: {
|
|
149
|
+
model?: string;
|
|
150
|
+
dimensions?: number;
|
|
151
|
+
});
|
|
152
|
+
/**
|
|
153
|
+
* Runtime resolution metadata. `fallbackActive` is only meaningful after
|
|
154
|
+
* the first `embed()` call (or an explicit probe) has triggered
|
|
155
|
+
* `resolve()`; before that it reports `false` with a null reason, which
|
|
156
|
+
* callers should read as "not yet known" rather than "no fallback".
|
|
157
|
+
*/
|
|
158
|
+
getRuntimeInfo(): EmbeddingRuntimeInfo;
|
|
159
|
+
/** Dimensions seen on the most recent embed/batchEmbed result. */
|
|
160
|
+
private lastObservedDimensions;
|
|
161
|
+
/**
|
|
162
|
+
* Lazily resolve the transformers pipeline. We use a dynamic import so
|
|
163
|
+
* the optional dep is only paid for when (and if) the user installs it.
|
|
164
|
+
* Any failure to load silently falls back to the local hash.
|
|
165
|
+
*
|
|
166
|
+
* Tries `@huggingface/transformers` (the maintained successor) first,
|
|
167
|
+
* then falls back to the abandoned `@xenova/transformers` for users who
|
|
168
|
+
* still have it installed.
|
|
169
|
+
*/
|
|
170
|
+
private resolve;
|
|
171
|
+
/**
|
|
172
|
+
* One-time loud warning when the local-hash fallback activates. Silent
|
|
173
|
+
* degradation is the worst plug-in experience: everything "works" but
|
|
174
|
+
* semantic search quietly returns garbage.
|
|
175
|
+
*/
|
|
176
|
+
private warnFallbackOnce;
|
|
177
|
+
embed(text: string): Promise<EmbeddingVector>;
|
|
178
|
+
batchEmbed(texts: string[]): Promise<EmbeddingVector[]>;
|
|
179
|
+
/**
|
|
180
|
+
* Deterministic feature-hash fallback. Produces a `dimensions`-long
|
|
181
|
+
* vector with the same shape (and L2 norm) as a real
|
|
182
|
+
* sentence-transformer embedding, so storage and ranking code is
|
|
183
|
+
* identical to the online path.
|
|
184
|
+
*/
|
|
185
|
+
private fallbackEmbed;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../src/embeddings.ts"],"names":[],"mappings":"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"}
|