@lunora/ai 1.0.0-alpha.14 → 1.0.0-alpha.16

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 CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  <!-- END_PACKAGE_OG_IMAGE_PLACEHOLDER -->
12
12
 
13
+ > **Experimental** — this package is outside the Lunora 1.0 stability promise: its API may change in any release, without a major version bump.
14
+
13
15
  <br />
14
16
 
15
17
  <div align="center">
@@ -2,7 +2,6 @@ const BM25_K1 = 1.5;
2
2
  const BM25_B = 0.75;
3
3
  const TOKEN_PATTERN = /[a-z0-9]+/g;
4
4
  const tokenize = (text) => text.toLowerCase().match(TOKEN_PATTERN) ?? [];
5
- const isPrimitiveFilter = (filter) => Object.values(filter).every((value) => value === null || typeof value !== "object");
6
5
  const filterWarned = /* @__PURE__ */ new WeakSet();
7
6
  const bm25LexicalStore = () => {
8
7
  const namespaces = /* @__PURE__ */ new Map();
@@ -65,7 +64,7 @@ const bm25LexicalStore = () => {
65
64
  return Promise.resolve();
66
65
  },
67
66
  search: (query, options) => {
68
- if (options.filter && Object.keys(options.filter).length > 0 && !isPrimitiveFilter(options.filter)) {
67
+ if (options.filter && Object.keys(options.filter).length > 0) {
69
68
  if (!filterWarned.has(store)) {
70
69
  filterWarned.add(store);
71
70
  console.warn(
@@ -8,17 +8,40 @@ const concurrentMap = async (items, limit, function_) => {
8
8
  if (!Number.isInteger(limit) || limit < 1) {
9
9
  throw new RangeError("concurrentMap: `limit` must be a positive integer");
10
10
  }
11
+ if (items.length === 0) {
12
+ return [];
13
+ }
14
+ const effectiveLimit = Math.max(1, Math.min(limit, items.length));
11
15
  const results = Array.from({ length: items.length });
12
16
  let cursor = 0;
17
+ let failed = false;
18
+ let firstError;
13
19
  const worker = async () => {
14
- while (cursor < items.length) {
20
+ for (; ; ) {
21
+ if (failed) {
22
+ return;
23
+ }
15
24
  const index = cursor;
16
25
  cursor += 1;
17
- results[index] = await function_(items[index], index);
26
+ if (index >= items.length) {
27
+ return;
28
+ }
29
+ try {
30
+ results[index] = await function_(items[index], index);
31
+ } catch (error) {
32
+ if (!failed) {
33
+ failed = true;
34
+ firstError = error;
35
+ }
36
+ return;
37
+ }
18
38
  }
19
39
  };
20
- const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());
40
+ const workers = Array.from({ length: effectiveLimit }, () => worker());
21
41
  await Promise.all(workers);
42
+ if (failed) {
43
+ throw firstError;
44
+ }
22
45
  return results;
23
46
  };
24
47
 
@@ -322,13 +345,19 @@ const defineRag = (config) => {
322
345
  if (!textStore) {
323
346
  return chunks;
324
347
  }
325
- const texts = await textsByIds(
326
- chunks.map((chunk) => chunk.id),
327
- namespace
328
- );
348
+ const ids = chunks.map((chunk) => chunk.id);
349
+ const [texts, records] = await Promise.all([textsByIds(ids, namespace), context.vectors.getByIds(config.index, ids, namespace)]);
350
+ const fullMetadataById = new Map(records.map((record) => [record.id, record.metadata]));
329
351
  return chunks.flatMap((chunk) => {
330
352
  const text = texts.get(chunk.id);
331
- return text === void 0 ? [] : [{ ...chunk, text }];
353
+ if (text === void 0) {
354
+ return [];
355
+ }
356
+ const fullMetadata = fullMetadataById.get(chunk.id);
357
+ const rawImportance = fullMetadata?.[IMPORTANCE_KEY];
358
+ const importance = typeof rawImportance === "number" && rawImportance >= 0 && rawImportance <= 1 ? rawImportance : chunk.importance;
359
+ const score = chunk.score / chunk.importance * importance;
360
+ return [{ ...chunk, importance, metadata: userMetadataOf(fullMetadata) ?? chunk.metadata, score, text }];
332
361
  });
333
362
  };
334
363
  const retrieve = async (query, options) => {
@@ -347,6 +376,10 @@ const defineRag = (config) => {
347
376
  topK
348
377
  });
349
378
  let chunks = await hydrateFromStore(parseMatches(vectorResult, effectiveNamespace), effectiveNamespace);
379
+ const minScore = options?.minScore;
380
+ if (minScore !== void 0) {
381
+ chunks = chunks.filter((chunk) => chunk.score >= minScore);
382
+ }
350
383
  if (config.lexicalStore) {
351
384
  const lexicalMatches = await config.lexicalStore.search(query, {
352
385
  filter: effectiveFilter,
@@ -368,10 +401,6 @@ const defineRag = (config) => {
368
401
  chunks = [...hybridRank(chunks, lexicalChunks)];
369
402
  }
370
403
  chunks.sort((a, b) => b.score - a.score);
371
- const minScore = options?.minScore;
372
- if (minScore !== void 0) {
373
- chunks = chunks.filter((chunk) => chunk.score >= minScore);
374
- }
375
404
  chunks = [...await expandChunks(chunks, options, effectiveNamespace)];
376
405
  const sources = [];
377
406
  const seen = /* @__PURE__ */ new Set();
@@ -1,5 +1,5 @@
1
1
  export { default as fixedWindowChunks } from '../packem_shared/fixedWindowChunks-J-WfQDw9.mjs';
2
- export { default as defineRag } from '../packem_shared/defineRag-BwrgePLE.mjs';
2
+ export { default as defineRag } from '../packem_shared/defineRag-CH8wZ0d5.mjs';
3
3
  export { contentHash, guessMimeTypeFromExtension } from '../packem_shared/contentHash-Cgz5KRGD.mjs';
4
4
  export { default as hybridRank } from '../packem_shared/hybridRank-DPC9c2ON.mjs';
5
- export { default as bm25LexicalStore } from '../packem_shared/bm25LexicalStore-Q28z6fbO.mjs';
5
+ export { default as bm25LexicalStore } from '../packem_shared/bm25LexicalStore-BQzWLMqX.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/ai",
3
- "version": "1.0.0-alpha.14",
3
+ "version": "1.0.0-alpha.16",
4
4
  "description": "Workers AI helper for Lunora: provider-agnostic AI SDK access from functions, Workers AI by default",
5
5
  "keywords": [
6
6
  "ai",
@@ -53,7 +53,7 @@
53
53
  "access": "public"
54
54
  },
55
55
  "dependencies": {
56
- "@lunora/errors": "1.0.0-alpha.4",
56
+ "@lunora/errors": "1.0.0-alpha.5",
57
57
  "ai": "7.0.16",
58
58
  "workers-ai-provider": "3.3.1"
59
59
  },