@delali/narsil 0.2.4-next.50 → 0.2.4-next.52
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 +27 -25
- package/dist/{capabilities-JrVQOwi4.d.ts → capabilities-CuTSXvbN.d.ts} +2 -2
- package/dist/{chunk-BEIK3EOZ.mjs → chunk-2FO7KZ6K.mjs} +5468 -3837
- package/dist/{chunk-XE6XR2OE.mjs → chunk-3GWP2TO6.mjs} +1 -1
- package/dist/{chunk-KMMJMDUA.mjs → chunk-3L4U6EJQ.mjs} +15 -10
- package/dist/{chunk-MHE7YWAU.mjs → chunk-72AXTIBW.mjs} +2 -2
- package/dist/{chunk-CV5H7XL7.mjs → chunk-EY2ULUMT.mjs} +30 -7
- package/dist/chunk-IFBKLBGB.mjs +7 -0
- package/dist/{chunk-WYJXSLER.mjs → chunk-POWOTUKJ.mjs} +7 -1
- package/dist/chunk-T62YOSGS.mjs +4280 -0
- package/dist/chunk-U36IDJN7.mjs +366 -0
- package/dist/{chunk-ND34I3SV.mjs → chunk-ULJ36FK4.mjs} +3502 -2383
- package/dist/{chunk-RP23PWMV.mjs → chunk-WFKIGEBY.mjs} +3 -3
- package/dist/{chunk-CMVG2UEF.mjs → chunk-WM7IS45M.mjs} +55 -517
- package/dist/chunk-Y3L5MDRV.mjs +96 -0
- package/dist/{chunk-ZHUQKZBE.mjs → chunk-YPYULM5E.mjs} +20 -4
- package/dist/chunk-ZJ4CSAB2.mjs +13 -0
- package/dist/chunk-ZT5BRDFW.mjs +513 -0
- package/dist/{client-CBOVHdjp.d.ts → client-BMJWVxOP.d.ts} +5 -5
- package/dist/client.d.ts +8 -8
- package/dist/{config-OON7IJ_B.d.ts → config-BcYZkdMw.d.ts} +2 -2
- package/dist/{config-Czh2YNDi.d.ts → config-qMLpi5T4.d.ts} +2 -2
- package/dist/direct-executor-UJC36S2D.mjs +12 -0
- package/dist/distribution/coordinator/etcd.d.ts +2 -2
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution.d.ts +8 -8
- package/dist/distribution.mjs +30 -15
- package/dist/{engine-9PtFY50q.d.ts → engine-zhms1qId.d.ts} +2 -2
- package/dist/index.browser.mjs +12845 -7766
- package/dist/index.d.ts +9 -21
- package/dist/index.mjs +13 -12
- package/dist/{memory-Bzd5xcEW.d.ts → memory-OmgkX_Z2.d.ts} +11 -1
- package/dist/persistence/durability/checkpoint-worker.d.ts +138 -3
- package/dist/persistence/durability/checkpoint-worker.mjs +31 -17
- package/dist/react.d.ts +6 -6
- package/dist/{schema-BqRx9t4E.d.ts → schema-OSWaaZzx.d.ts} +30 -6
- package/dist/serialization/crc32-worker.mjs +2 -1
- package/dist/server.d.ts +10 -10
- package/dist/server.mjs +80 -36
- package/dist/simd-DW5AtJ6B.d.ts +41 -0
- package/dist/{tasks-Bn4R1NPN.d.ts → tasks-DiF1c9v2.d.ts} +20 -1
- package/dist/{thread-PZLEO6JL.mjs → thread-TLCX43WV.mjs} +129 -41
- package/dist/{types-DXPxaXPO.d.ts → types-LEzMyjVX.d.ts} +1 -1
- package/dist/vector/search-worker.d.ts +292 -128
- package/dist/vector/search-worker.mjs +70 -54
- package/dist/workers/entry.mjs +10 -7
- package/package.json +52 -31
- package/dist/brute-force-DbHYCTc3.d.ts +0 -8
- package/dist/chunk-CBLS46IE.mjs +0 -10
- package/dist/chunk-PIWKZPP7.mjs +0 -64
- package/dist/chunk-PMBHH44R.mjs +0 -492
- package/dist/chunk-X6YZO4MQ.mjs +0 -1572
- package/dist/direct-executor-OREXU72C.mjs +0 -12
- package/dist/vector/hnsw-build-worker.d.ts +0 -105
- package/dist/vector/hnsw-build-worker.mjs +0 -123
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { validateRequiredFields } from './chunk-ZT5BRDFW.mjs';
|
|
2
|
+
import { ErrorCodes, NarsilError } from './chunk-P4ELXVJQ.mjs';
|
|
3
|
+
|
|
4
|
+
// src/narsil/internals.ts
|
|
5
|
+
var engineCores = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
function bindEngineCore(engine, core) {
|
|
7
|
+
engineCores.set(engine, core);
|
|
8
|
+
}
|
|
9
|
+
function engineCoreOf(engine) {
|
|
10
|
+
return engineCores.get(engine);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/distribution/constants.ts
|
|
14
|
+
var WIRE_BATCH_BUDGET = {
|
|
15
|
+
maxCount: 1e3,
|
|
16
|
+
maxBytes: 8388608,
|
|
17
|
+
overheadBytes: 256
|
|
18
|
+
};
|
|
19
|
+
var MAX_PARTITION_COUNT = 65536;
|
|
20
|
+
var MAX_REPLICATION_FACTOR = 255;
|
|
21
|
+
|
|
22
|
+
// src/engine/embed.ts
|
|
23
|
+
function assertDocumentCarriesMappedVectors(document, embeddingConfig, adapterName) {
|
|
24
|
+
for (const targetField of Object.keys(embeddingConfig.fields)) {
|
|
25
|
+
const existing = resolveFieldValue(document, targetField);
|
|
26
|
+
if (existing === void 0 || existing === null) {
|
|
27
|
+
throw new NarsilError(
|
|
28
|
+
ErrorCodes.EMBEDDING_CONFIG_INVALID,
|
|
29
|
+
adapterName ? `The index embeds "${targetField}" via adapter "${adapterName}", which is not registered on this engine. Register the adapter or supply the vector on the document.` : `The index embeds "${targetField}" automatically but no embedding adapter is bound. Bind an adapter or supply the vector on the document.`,
|
|
30
|
+
adapterName ? { field: targetField, adapter: adapterName } : { field: targetField }
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function validateVector(vector, targetField, expectedDimensions) {
|
|
36
|
+
if (!(vector instanceof Float32Array)) {
|
|
37
|
+
throw new NarsilError(
|
|
38
|
+
ErrorCodes.EMBEDDING_FAILED,
|
|
39
|
+
`Adapter returned ${typeof vector} for field "${targetField}", expected Float32Array`,
|
|
40
|
+
{ field: targetField, returnedType: typeof vector }
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (vector.length !== expectedDimensions) {
|
|
44
|
+
throw new NarsilError(
|
|
45
|
+
ErrorCodes.EMBEDDING_DIMENSION_MISMATCH,
|
|
46
|
+
`Adapter returned ${vector.length}-dimensional vector for field "${targetField}", expected ${expectedDimensions}`,
|
|
47
|
+
{ field: targetField, expected: expectedDimensions, actual: vector.length }
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
for (let i = 0; i < vector.length; i++) {
|
|
51
|
+
if (Number.isNaN(vector[i])) {
|
|
52
|
+
throw new NarsilError(
|
|
53
|
+
ErrorCodes.EMBEDDING_FAILED,
|
|
54
|
+
`Adapter returned vector with NaN at index ${i} for field "${targetField}"`,
|
|
55
|
+
{ field: targetField, index: i }
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return vector;
|
|
60
|
+
}
|
|
61
|
+
function resolveFieldValue(document, path) {
|
|
62
|
+
if (!path.includes(".")) return document[path];
|
|
63
|
+
const segments = path.split(".");
|
|
64
|
+
let current = document;
|
|
65
|
+
for (const segment of segments) {
|
|
66
|
+
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
67
|
+
current = current[segment];
|
|
68
|
+
}
|
|
69
|
+
return current;
|
|
70
|
+
}
|
|
71
|
+
function setFieldValue(document, path, value) {
|
|
72
|
+
if (!path.includes(".")) {
|
|
73
|
+
document[path] = value;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const segments = path.split(".");
|
|
77
|
+
let current = document;
|
|
78
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
79
|
+
let next = current[segments[i]];
|
|
80
|
+
if (next === null || next === void 0 || typeof next !== "object") {
|
|
81
|
+
next = {};
|
|
82
|
+
current[segments[i]] = next;
|
|
83
|
+
}
|
|
84
|
+
current = next;
|
|
85
|
+
}
|
|
86
|
+
current[segments[segments.length - 1]] = value;
|
|
87
|
+
}
|
|
88
|
+
function deleteFieldValue(document, path) {
|
|
89
|
+
if (!path.includes(".")) {
|
|
90
|
+
delete document[path];
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const segments = path.split(".");
|
|
94
|
+
let current = document;
|
|
95
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
96
|
+
const next = current[segments[i]];
|
|
97
|
+
if (next === null || next === void 0 || typeof next !== "object") return;
|
|
98
|
+
current = next;
|
|
99
|
+
}
|
|
100
|
+
delete current[segments[segments.length - 1]];
|
|
101
|
+
}
|
|
102
|
+
function collectSourceText(document, sourceFields, targetField, documentIndex) {
|
|
103
|
+
const sources = Array.isArray(sourceFields) ? sourceFields : [sourceFields];
|
|
104
|
+
const parts = [];
|
|
105
|
+
for (const source of sources) {
|
|
106
|
+
const value = resolveFieldValue(document, source);
|
|
107
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
108
|
+
if (typeof value !== "string") {
|
|
109
|
+
throw new NarsilError(
|
|
110
|
+
ErrorCodes.DOC_VALIDATION_FAILED,
|
|
111
|
+
`Embedding source field "${source}" must be a string, got ${typeof value}`,
|
|
112
|
+
{ field: source, targetField }
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
parts.push(value);
|
|
116
|
+
}
|
|
117
|
+
if (parts.length === 0) {
|
|
118
|
+
const details = { field: targetField };
|
|
119
|
+
if (documentIndex !== void 0) {
|
|
120
|
+
details.documentIndex = documentIndex;
|
|
121
|
+
}
|
|
122
|
+
throw new NarsilError(
|
|
123
|
+
ErrorCodes.EMBEDDING_NO_SOURCE,
|
|
124
|
+
`All source fields for embedding target "${targetField}" are missing or empty`,
|
|
125
|
+
details
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return parts.join("\n");
|
|
129
|
+
}
|
|
130
|
+
function wrapAdapterError(err, targetField) {
|
|
131
|
+
if (err instanceof NarsilError) return err;
|
|
132
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
133
|
+
return new NarsilError(ErrorCodes.EMBEDDING_FAILED, `Embedding failed for field "${targetField}": ${message}`, {
|
|
134
|
+
field: targetField,
|
|
135
|
+
cause: message
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async function embedDocumentFields(document, embeddingConfig, adapter, signal) {
|
|
139
|
+
const embeddedFields = /* @__PURE__ */ new Set();
|
|
140
|
+
try {
|
|
141
|
+
for (const [targetField, sourceFields] of Object.entries(embeddingConfig.fields)) {
|
|
142
|
+
const existing = resolveFieldValue(document, targetField);
|
|
143
|
+
if (existing !== void 0 && existing !== null) continue;
|
|
144
|
+
const text = collectSourceText(document, sourceFields, targetField);
|
|
145
|
+
let vector;
|
|
146
|
+
try {
|
|
147
|
+
const raw = await adapter.embed(text, "document", signal);
|
|
148
|
+
vector = validateVector(raw, targetField, adapter.dimensions);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
throw wrapAdapterError(err, targetField);
|
|
151
|
+
}
|
|
152
|
+
setFieldValue(document, targetField, vector);
|
|
153
|
+
embeddedFields.add(targetField);
|
|
154
|
+
}
|
|
155
|
+
} catch (err) {
|
|
156
|
+
for (const field of embeddedFields) {
|
|
157
|
+
deleteFieldValue(document, field);
|
|
158
|
+
}
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
return embeddedFields;
|
|
162
|
+
}
|
|
163
|
+
var SOURCE_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
164
|
+
ErrorCodes.EMBEDDING_NO_SOURCE,
|
|
165
|
+
ErrorCodes.DOC_VALIDATION_FAILED
|
|
166
|
+
]);
|
|
167
|
+
function isDocumentSourceError(err) {
|
|
168
|
+
return err instanceof NarsilError && SOURCE_FAILURE_CODES.has(err.code);
|
|
169
|
+
}
|
|
170
|
+
async function embedBatchDocumentFields(documents, embeddingConfig, adapter, signal) {
|
|
171
|
+
const embedded = /* @__PURE__ */ new Map();
|
|
172
|
+
const failed = /* @__PURE__ */ new Map();
|
|
173
|
+
try {
|
|
174
|
+
for (const [targetField, sourceFields] of Object.entries(embeddingConfig.fields)) {
|
|
175
|
+
const needsEmbedding = [];
|
|
176
|
+
for (let i = 0; i < documents.length; i++) {
|
|
177
|
+
if (failed.has(i)) continue;
|
|
178
|
+
const doc = documents[i];
|
|
179
|
+
const existing = resolveFieldValue(doc, targetField);
|
|
180
|
+
if (existing !== void 0 && existing !== null) continue;
|
|
181
|
+
try {
|
|
182
|
+
const text = collectSourceText(doc, sourceFields, targetField, i);
|
|
183
|
+
needsEmbedding.push({ docIndex: i, text });
|
|
184
|
+
} catch (err) {
|
|
185
|
+
if (isDocumentSourceError(err)) {
|
|
186
|
+
failed.set(i, err);
|
|
187
|
+
} else {
|
|
188
|
+
throw err;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (needsEmbedding.length === 0) continue;
|
|
193
|
+
const texts = needsEmbedding.map((entry) => entry.text);
|
|
194
|
+
let vectors;
|
|
195
|
+
try {
|
|
196
|
+
if (adapter.embedBatch) {
|
|
197
|
+
vectors = await adapter.embedBatch(texts, "document", signal);
|
|
198
|
+
} else {
|
|
199
|
+
vectors = [];
|
|
200
|
+
const concurrency = 8;
|
|
201
|
+
for (let start = 0; start < texts.length; start += concurrency) {
|
|
202
|
+
const chunk = texts.slice(start, start + concurrency);
|
|
203
|
+
const chunkResults = await Promise.all(chunk.map((t) => adapter.embed(t, "document", signal)));
|
|
204
|
+
vectors.push(...chunkResults);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} catch (err) {
|
|
208
|
+
throw wrapAdapterError(err, targetField);
|
|
209
|
+
}
|
|
210
|
+
if (vectors.length !== needsEmbedding.length) {
|
|
211
|
+
throw new NarsilError(
|
|
212
|
+
ErrorCodes.EMBEDDING_FAILED,
|
|
213
|
+
`Adapter returned ${vectors.length} vectors for ${needsEmbedding.length} inputs on field "${targetField}"`,
|
|
214
|
+
{ field: targetField, expected: needsEmbedding.length, actual: vectors.length }
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
for (let j = 0; j < needsEmbedding.length; j++) {
|
|
218
|
+
const { docIndex } = needsEmbedding[j];
|
|
219
|
+
const validated = validateVector(vectors[j], targetField, adapter.dimensions);
|
|
220
|
+
setFieldValue(documents[docIndex], targetField, validated);
|
|
221
|
+
let fieldSet = embedded.get(docIndex);
|
|
222
|
+
if (!fieldSet) {
|
|
223
|
+
fieldSet = /* @__PURE__ */ new Set();
|
|
224
|
+
embedded.set(docIndex, fieldSet);
|
|
225
|
+
}
|
|
226
|
+
fieldSet.add(targetField);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
} catch (err) {
|
|
230
|
+
for (const [docIndex, fields] of embedded) {
|
|
231
|
+
for (const field of fields) {
|
|
232
|
+
deleteFieldValue(documents[docIndex], field);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
return { embedded, failed };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/engine/mutations/insert-admission.ts
|
|
241
|
+
function providedDocId(document) {
|
|
242
|
+
const id = document.id;
|
|
243
|
+
return typeof id === "string" && id.length > 0 ? id : void 0;
|
|
244
|
+
}
|
|
245
|
+
function asBatchInsertError(err) {
|
|
246
|
+
return err instanceof NarsilError ? err : new NarsilError(ErrorCodes.DOC_VALIDATION_FAILED, String(err));
|
|
247
|
+
}
|
|
248
|
+
function admitInsert(ctx, indexName, manager, docId, pendingAdmitted = 0) {
|
|
249
|
+
if (!ctx.isRebalancing(indexName)) {
|
|
250
|
+
manager.assertCapacity(pendingAdmitted);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const bufferedState = ctx.bufferedDocState(indexName, docId);
|
|
254
|
+
const exists = bufferedState !== void 0 ? bufferedState === "present" : manager.has(docId);
|
|
255
|
+
if (exists) {
|
|
256
|
+
throw new NarsilError(ErrorCodes.DOC_ALREADY_EXISTS, `Document "${docId}" already exists`, { docId });
|
|
257
|
+
}
|
|
258
|
+
manager.assertCapacity(
|
|
259
|
+
ctx.pendingRebalanceWrites(indexName) + pendingAdmitted,
|
|
260
|
+
ctx.rebalanceTargetPartitionCount(indexName)
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
function collectRequiredFieldFailures(documents, chunkStart, chunkEnd, required, chunkFailedIndexes, failed) {
|
|
264
|
+
for (let i = chunkStart; i < chunkEnd; i++) {
|
|
265
|
+
try {
|
|
266
|
+
validateRequiredFields(documents[i], required);
|
|
267
|
+
} catch (err) {
|
|
268
|
+
chunkFailedIndexes.add(i);
|
|
269
|
+
failed.push({ docId: providedDocId(documents[i]) ?? "", error: asBatchInsertError(err) });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function embedChunkDocuments(entry, documents, chunkStart, chunkEnd, signal, chunkFailedIndexes, failed) {
|
|
274
|
+
if (entry.config.embedding === void 0) return;
|
|
275
|
+
if (entry.embeddingAdapter === null) {
|
|
276
|
+
for (let i = chunkStart; i < chunkEnd; i++) {
|
|
277
|
+
if (chunkFailedIndexes.has(i)) continue;
|
|
278
|
+
try {
|
|
279
|
+
assertDocumentCarriesMappedVectors(
|
|
280
|
+
documents[i],
|
|
281
|
+
entry.config.embedding,
|
|
282
|
+
entry.embeddingAdapterName
|
|
283
|
+
);
|
|
284
|
+
} catch (err) {
|
|
285
|
+
chunkFailedIndexes.add(i);
|
|
286
|
+
failed.push({
|
|
287
|
+
docId: providedDocId(documents[i]) ?? "",
|
|
288
|
+
error: err instanceof NarsilError ? err : new NarsilError(ErrorCodes.EMBEDDING_FAILED, String(err))
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const embeddableSlice = [];
|
|
295
|
+
const embeddableOriginalIndexes = [];
|
|
296
|
+
for (let i = chunkStart; i < chunkEnd; i++) {
|
|
297
|
+
if (chunkFailedIndexes.has(i)) continue;
|
|
298
|
+
embeddableSlice.push(documents[i]);
|
|
299
|
+
embeddableOriginalIndexes.push(i);
|
|
300
|
+
}
|
|
301
|
+
if (embeddableSlice.length === 0) return;
|
|
302
|
+
try {
|
|
303
|
+
const embedResult = await embedBatchDocumentFields(
|
|
304
|
+
embeddableSlice,
|
|
305
|
+
entry.config.embedding,
|
|
306
|
+
entry.embeddingAdapter,
|
|
307
|
+
signal
|
|
308
|
+
);
|
|
309
|
+
for (const [sliceIndex, error] of embedResult.failed) {
|
|
310
|
+
const originalIdx = embeddableOriginalIndexes[sliceIndex];
|
|
311
|
+
chunkFailedIndexes.add(originalIdx);
|
|
312
|
+
failed.push({ docId: providedDocId(documents[originalIdx]) ?? "", error });
|
|
313
|
+
}
|
|
314
|
+
} catch (err) {
|
|
315
|
+
const embeddingError = err instanceof NarsilError ? err : new NarsilError(ErrorCodes.EMBEDDING_FAILED, String(err));
|
|
316
|
+
for (const originalIdx of embeddableOriginalIndexes) {
|
|
317
|
+
chunkFailedIndexes.add(originalIdx);
|
|
318
|
+
failed.push({ docId: providedDocId(documents[originalIdx]) ?? "", error: embeddingError });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/engine/resolve-vector-text.ts
|
|
324
|
+
async function resolveVectorText(params, embeddingAdapter, signal, embeddingAdapterName) {
|
|
325
|
+
if (!params.vector) return params;
|
|
326
|
+
if (params.vector.text === void 0 && params.vector.value === void 0) return params;
|
|
327
|
+
if (params.vector.value !== void 0 && params.vector.text === void 0) return params;
|
|
328
|
+
if (params.vector.text !== void 0 && params.vector.value !== void 0) {
|
|
329
|
+
throw new NarsilError(ErrorCodes.EMBEDDING_CONFIG_INVALID, "Vector query cannot have both 'text' and 'value'");
|
|
330
|
+
}
|
|
331
|
+
if (!embeddingAdapter) {
|
|
332
|
+
throw new NarsilError(
|
|
333
|
+
ErrorCodes.EMBEDDING_CONFIG_INVALID,
|
|
334
|
+
embeddingAdapterName ? `Vector query with 'text' needs embedding adapter "${embeddingAdapterName}", which is not registered on this engine. Register it with registerEmbeddingAdapter or supply a raw vector.` : "Vector query with 'text' requires an embedding adapter on the index or instance",
|
|
335
|
+
embeddingAdapterName ? { adapter: embeddingAdapterName } : void 0
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
if (typeof params.vector.text !== "string") {
|
|
339
|
+
throw new NarsilError(
|
|
340
|
+
ErrorCodes.DOC_VALIDATION_FAILED,
|
|
341
|
+
`Vector query 'text' must be a string, got ${typeof params.vector.text}`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
if (params.vector.text.length === 0) {
|
|
345
|
+
throw new NarsilError(ErrorCodes.DOC_VALIDATION_FAILED, "Vector query 'text' must not be empty");
|
|
346
|
+
}
|
|
347
|
+
const raw = await embeddingAdapter.embed(params.vector.text, "query", signal);
|
|
348
|
+
if (!(raw instanceof Float32Array)) {
|
|
349
|
+
throw new NarsilError(
|
|
350
|
+
ErrorCodes.EMBEDDING_FAILED,
|
|
351
|
+
`Adapter returned ${typeof raw} for query embedding, expected Float32Array`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
if (raw.length !== embeddingAdapter.dimensions) {
|
|
355
|
+
throw new NarsilError(
|
|
356
|
+
ErrorCodes.EMBEDDING_DIMENSION_MISMATCH,
|
|
357
|
+
`Adapter returned ${raw.length}-dimensional vector for query, expected ${embeddingAdapter.dimensions}`,
|
|
358
|
+
{ expected: embeddingAdapter.dimensions, actual: raw.length }
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
const resolved = { ...params.vector, value: Array.from(raw) };
|
|
362
|
+
delete resolved.text;
|
|
363
|
+
return { ...params, vector: resolved };
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR, WIRE_BATCH_BUDGET, admitInsert, asBatchInsertError, assertDocumentCarriesMappedVectors, bindEngineCore, collectRequiredFieldFailures, embedChunkDocuments, embedDocumentFields, engineCoreOf, providedDocId, resolveVectorText };
|