@loreai/core 0.15.0 → 0.17.0
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 +11 -0
- package/dist/bun/agents-file.d.ts +13 -1
- package/dist/bun/agents-file.d.ts.map +1 -1
- package/dist/bun/config.d.ts +20 -1
- package/dist/bun/config.d.ts.map +1 -1
- package/dist/bun/data.d.ts +174 -0
- package/dist/bun/data.d.ts.map +1 -0
- package/dist/bun/db.d.ts +65 -0
- package/dist/bun/db.d.ts.map +1 -1
- package/dist/bun/distillation.d.ts +49 -6
- package/dist/bun/distillation.d.ts.map +1 -1
- package/dist/bun/embedding-vendor.d.ts +66 -0
- package/dist/bun/embedding-vendor.d.ts.map +1 -0
- package/dist/bun/embedding-worker-types.d.ts +66 -0
- package/dist/bun/embedding-worker-types.d.ts.map +1 -0
- package/dist/bun/embedding-worker.d.ts +16 -0
- package/dist/bun/embedding-worker.d.ts.map +1 -0
- package/dist/bun/embedding-worker.js +100 -0
- package/dist/bun/embedding-worker.js.map +7 -0
- package/dist/bun/embedding.d.ts +91 -8
- package/dist/bun/embedding.d.ts.map +1 -1
- package/dist/bun/git.d.ts +47 -0
- package/dist/bun/git.d.ts.map +1 -0
- package/dist/bun/gradient.d.ts +19 -1
- package/dist/bun/gradient.d.ts.map +1 -1
- package/dist/bun/index.d.ts +9 -6
- package/dist/bun/index.d.ts.map +1 -1
- package/dist/bun/index.js +13205 -11259
- package/dist/bun/index.js.map +4 -4
- package/dist/bun/lat-reader.d.ts +1 -1
- package/dist/bun/lat-reader.d.ts.map +1 -1
- package/dist/bun/ltm.d.ts.map +1 -1
- package/dist/bun/markdown.d.ts +11 -0
- package/dist/bun/markdown.d.ts.map +1 -1
- package/dist/bun/prompt.d.ts +1 -1
- package/dist/bun/prompt.d.ts.map +1 -1
- package/dist/bun/recall.d.ts +53 -0
- package/dist/bun/recall.d.ts.map +1 -1
- package/dist/bun/search.d.ts +29 -0
- package/dist/bun/search.d.ts.map +1 -1
- package/dist/bun/temporal.d.ts +2 -0
- package/dist/bun/temporal.d.ts.map +1 -1
- package/dist/bun/types.d.ts +15 -0
- package/dist/bun/types.d.ts.map +1 -1
- package/dist/bun/worker-model.d.ts +15 -80
- package/dist/bun/worker-model.d.ts.map +1 -1
- package/dist/node/agents-file.d.ts +13 -1
- package/dist/node/agents-file.d.ts.map +1 -1
- package/dist/node/config.d.ts +20 -1
- package/dist/node/config.d.ts.map +1 -1
- package/dist/node/data.d.ts +174 -0
- package/dist/node/data.d.ts.map +1 -0
- package/dist/node/db.d.ts +65 -0
- package/dist/node/db.d.ts.map +1 -1
- package/dist/node/distillation.d.ts +49 -6
- package/dist/node/distillation.d.ts.map +1 -1
- package/dist/node/embedding-vendor.d.ts +66 -0
- package/dist/node/embedding-vendor.d.ts.map +1 -0
- package/dist/node/embedding-worker-types.d.ts +66 -0
- package/dist/node/embedding-worker-types.d.ts.map +1 -0
- package/dist/node/embedding-worker.d.ts +16 -0
- package/dist/node/embedding-worker.d.ts.map +1 -0
- package/dist/node/embedding-worker.js +100 -0
- package/dist/node/embedding-worker.js.map +7 -0
- package/dist/node/embedding.d.ts +91 -8
- package/dist/node/embedding.d.ts.map +1 -1
- package/dist/node/git.d.ts +47 -0
- package/dist/node/git.d.ts.map +1 -0
- package/dist/node/gradient.d.ts +19 -1
- package/dist/node/gradient.d.ts.map +1 -1
- package/dist/node/index.d.ts +9 -6
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +13205 -11259
- package/dist/node/index.js.map +4 -4
- package/dist/node/lat-reader.d.ts +1 -1
- package/dist/node/lat-reader.d.ts.map +1 -1
- package/dist/node/ltm.d.ts.map +1 -1
- package/dist/node/markdown.d.ts +11 -0
- package/dist/node/markdown.d.ts.map +1 -1
- package/dist/node/prompt.d.ts +1 -1
- package/dist/node/prompt.d.ts.map +1 -1
- package/dist/node/recall.d.ts +53 -0
- package/dist/node/recall.d.ts.map +1 -1
- package/dist/node/search.d.ts +29 -0
- package/dist/node/search.d.ts.map +1 -1
- package/dist/node/temporal.d.ts +2 -0
- package/dist/node/temporal.d.ts.map +1 -1
- package/dist/node/types.d.ts +15 -0
- package/dist/node/types.d.ts.map +1 -1
- package/dist/node/worker-model.d.ts +15 -80
- package/dist/node/worker-model.d.ts.map +1 -1
- package/dist/types/agents-file.d.ts +13 -1
- package/dist/types/agents-file.d.ts.map +1 -1
- package/dist/types/config.d.ts +20 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/data.d.ts +174 -0
- package/dist/types/data.d.ts.map +1 -0
- package/dist/types/db.d.ts +65 -0
- package/dist/types/db.d.ts.map +1 -1
- package/dist/types/distillation.d.ts +49 -6
- package/dist/types/distillation.d.ts.map +1 -1
- package/dist/types/embedding-vendor.d.ts +66 -0
- package/dist/types/embedding-vendor.d.ts.map +1 -0
- package/dist/types/embedding-worker-types.d.ts +66 -0
- package/dist/types/embedding-worker-types.d.ts.map +1 -0
- package/dist/types/embedding-worker.d.ts +16 -0
- package/dist/types/embedding-worker.d.ts.map +1 -0
- package/dist/types/embedding.d.ts +91 -8
- package/dist/types/embedding.d.ts.map +1 -1
- package/dist/types/git.d.ts +47 -0
- package/dist/types/git.d.ts.map +1 -0
- package/dist/types/gradient.d.ts +19 -1
- package/dist/types/gradient.d.ts.map +1 -1
- package/dist/types/index.d.ts +9 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lat-reader.d.ts +1 -1
- package/dist/types/lat-reader.d.ts.map +1 -1
- package/dist/types/ltm.d.ts.map +1 -1
- package/dist/types/markdown.d.ts +11 -0
- package/dist/types/markdown.d.ts.map +1 -1
- package/dist/types/prompt.d.ts +1 -1
- package/dist/types/prompt.d.ts.map +1 -1
- package/dist/types/recall.d.ts +53 -0
- package/dist/types/recall.d.ts.map +1 -1
- package/dist/types/search.d.ts +29 -0
- package/dist/types/search.d.ts.map +1 -1
- package/dist/types/temporal.d.ts +2 -0
- package/dist/types/temporal.d.ts.map +1 -1
- package/dist/types/types.d.ts +15 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/worker-model.d.ts +15 -80
- package/dist/types/worker-model.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/agents-file.ts +87 -4
- package/src/config.ts +68 -5
- package/src/curator.ts +2 -2
- package/src/data.ts +768 -0
- package/src/db.ts +386 -7
- package/src/distillation.ts +178 -35
- package/src/embedding-vendor.ts +102 -0
- package/src/embedding-worker-types.ts +82 -0
- package/src/embedding-worker.ts +185 -0
- package/src/embedding.ts +607 -61
- package/src/git.ts +144 -0
- package/src/gradient.ts +174 -17
- package/src/index.ts +20 -0
- package/src/lat-reader.ts +5 -11
- package/src/ltm.ts +17 -44
- package/src/markdown.ts +15 -0
- package/src/prompt.ts +1 -2
- package/src/recall.ts +401 -70
- package/src/search.ts +71 -1
- package/src/temporal.ts +42 -35
- package/src/types.ts +15 -0
- package/src/worker-model.ts +17 -363
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding worker thread — runs fastembed/ONNX inference off the main thread.
|
|
3
|
+
*
|
|
4
|
+
* This file is the entry point for a `node:worker_threads` Worker spawned by
|
|
5
|
+
* `LocalProvider` in `embedding.ts`. It owns the `FlagEmbedding` ONNX model
|
|
6
|
+
* and processes embed requests sequentially from a priority queue. Moving
|
|
7
|
+
* inference here keeps the main thread's event loop free — HTTP requests,
|
|
8
|
+
* SSE streams, and session APIs are no longer blocked during embedding.
|
|
9
|
+
*
|
|
10
|
+
* Communication uses `parentPort` message passing with structured clone.
|
|
11
|
+
* Float32Array vectors are sent back directly (Bun preserves identity).
|
|
12
|
+
*
|
|
13
|
+
* @see embedding-worker-types.ts for the message protocol.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
17
|
+
import type {
|
|
18
|
+
WorkerInbound,
|
|
19
|
+
WorkerOutbound,
|
|
20
|
+
WorkerInitData,
|
|
21
|
+
EmbedRequest,
|
|
22
|
+
} from "./embedding-worker-types";
|
|
23
|
+
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// workerData
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
const { modelName, vendorModel } = workerData as WorkerInitData;
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Model lifecycle — lazy init on first embed request
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
/** The fastembed model, typed to the subset of methods we use. */
|
|
35
|
+
type FastembedModel = {
|
|
36
|
+
queryEmbed(text: string): Promise<number[]>;
|
|
37
|
+
passageEmbed(texts: string[], batchSize?: number): AsyncGenerator<number[][]>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
let model: FastembedModel | null = null;
|
|
41
|
+
let initPromise: Promise<void> | null = null;
|
|
42
|
+
let initFailed = false;
|
|
43
|
+
let initError: string | null = null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Ensure the fastembed model is loaded. Lazy — first call triggers the
|
|
47
|
+
* dynamic import + FlagEmbedding.init(), subsequent calls return immediately.
|
|
48
|
+
* On failure, marks the worker as permanently broken and posts `init-error`.
|
|
49
|
+
*/
|
|
50
|
+
async function ensureModel(): Promise<FastembedModel> {
|
|
51
|
+
if (model) return model;
|
|
52
|
+
if (initFailed) throw new Error(initError ?? "fastembed init previously failed");
|
|
53
|
+
|
|
54
|
+
if (!initPromise) {
|
|
55
|
+
initPromise = (async () => {
|
|
56
|
+
const fastembed = await import("fastembed");
|
|
57
|
+
const { EmbeddingModel, FlagEmbedding } = fastembed;
|
|
58
|
+
|
|
59
|
+
let m: unknown;
|
|
60
|
+
if (vendorModel) {
|
|
61
|
+
// Binary mode: use pre-extracted model files.
|
|
62
|
+
m = await FlagEmbedding.init({
|
|
63
|
+
model: EmbeddingModel.CUSTOM,
|
|
64
|
+
modelAbsoluteDirPath: vendorModel.modelAbsoluteDirPath,
|
|
65
|
+
modelName: vendorModel.modelName,
|
|
66
|
+
});
|
|
67
|
+
} else {
|
|
68
|
+
// npm mode: resolve model name against fastembed's enum.
|
|
69
|
+
const enumValue = (EmbeddingModel as Record<string, string>)[modelName];
|
|
70
|
+
m = await FlagEmbedding.init({
|
|
71
|
+
model: enumValue ?? modelName,
|
|
72
|
+
} as { model: typeof EmbeddingModel.BGESmallENV15 });
|
|
73
|
+
}
|
|
74
|
+
model = m as FastembedModel;
|
|
75
|
+
})().catch((err) => {
|
|
76
|
+
initFailed = true;
|
|
77
|
+
initError = err instanceof Error ? err.message : String(err);
|
|
78
|
+
initPromise = null;
|
|
79
|
+
// Notify main thread — all pending + future requests should fail.
|
|
80
|
+
post({ type: "init-error", error: initError });
|
|
81
|
+
throw err;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await initPromise;
|
|
86
|
+
if (!model) throw new Error("model init completed but model is null");
|
|
87
|
+
return model;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Priority queue — high-priority (recall) jumps ahead of normal (backfill)
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
const queue: EmbedRequest[] = [];
|
|
95
|
+
let processing = false;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Enqueue an embed request. High-priority requests are inserted after any
|
|
99
|
+
* existing high-priority items but before all normal-priority items (FIFO
|
|
100
|
+
* within each priority level). Triggers drain if not already running.
|
|
101
|
+
*/
|
|
102
|
+
function enqueue(msg: EmbedRequest): void {
|
|
103
|
+
if (msg.priority === "high") {
|
|
104
|
+
// Insert after the last "high" item — keeps FIFO within high priority.
|
|
105
|
+
let insertAt = 0;
|
|
106
|
+
while (insertAt < queue.length && queue[insertAt].priority === "high") {
|
|
107
|
+
insertAt++;
|
|
108
|
+
}
|
|
109
|
+
queue.splice(insertAt, 0, msg);
|
|
110
|
+
} else {
|
|
111
|
+
queue.push(msg);
|
|
112
|
+
}
|
|
113
|
+
drain();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Process queued requests one at a time. ONNX inference is synchronous
|
|
118
|
+
* inside the NAPI call, so parallelism within the worker buys nothing.
|
|
119
|
+
* The queue gives us a natural point to interleave high-priority requests
|
|
120
|
+
* between normal-priority batches.
|
|
121
|
+
*/
|
|
122
|
+
async function drain(): Promise<void> {
|
|
123
|
+
if (processing) return;
|
|
124
|
+
processing = true;
|
|
125
|
+
|
|
126
|
+
while (queue.length > 0) {
|
|
127
|
+
const req = queue.shift()!;
|
|
128
|
+
await processEmbed(req);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
processing = false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Embed processing
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
async function processEmbed(req: EmbedRequest): Promise<void> {
|
|
139
|
+
try {
|
|
140
|
+
const m = await ensureModel();
|
|
141
|
+
|
|
142
|
+
let vectors: Float32Array[];
|
|
143
|
+
|
|
144
|
+
if (req.inputType === "query" && req.texts.length === 1) {
|
|
145
|
+
// Single query — use queryEmbed for better quality.
|
|
146
|
+
const vec = await m.queryEmbed(req.texts[0]);
|
|
147
|
+
vectors = [new Float32Array(vec)];
|
|
148
|
+
} else {
|
|
149
|
+
// Batch document embedding via async generator.
|
|
150
|
+
vectors = [];
|
|
151
|
+
for await (const batch of m.passageEmbed(req.texts)) {
|
|
152
|
+
for (const vec of batch) {
|
|
153
|
+
vectors.push(new Float32Array(vec));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
post({ type: "result", id: req.id, vectors });
|
|
159
|
+
} catch (err) {
|
|
160
|
+
// Don't re-post init-error — it was already sent in ensureModel().
|
|
161
|
+
if (!initFailed) {
|
|
162
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
163
|
+
post({ type: "error", id: req.id, error: msg });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Message handling
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
function post(msg: WorkerOutbound): void {
|
|
173
|
+
parentPort!.postMessage(msg);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
parentPort!.on("message", (msg: WorkerInbound) => {
|
|
177
|
+
switch (msg.type) {
|
|
178
|
+
case "embed":
|
|
179
|
+
enqueue(msg);
|
|
180
|
+
break;
|
|
181
|
+
case "shutdown":
|
|
182
|
+
process.exit(0);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
});
|