@lunora/ai 1.0.0-alpha.15 → 1.0.0-alpha.151
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 +20 -9
- package/dist/create.d.mts +51 -0
- package/dist/create.d.ts +51 -0
- package/dist/create.mjs +1 -0
- package/dist/index.d.mts +112 -3
- package/dist/index.d.ts +112 -3
- package/dist/index.mjs +1 -3
- package/dist/packem_shared/AI_DEFAULT_EMBEDDING_MODEL_ENV-IwcHZiKj.mjs +1 -0
- package/dist/packem_shared/DEFAULT_MODEL_PRICES-BFR_sIAK.mjs +1 -0
- package/dist/packem_shared/USAGE_ATTRIBUTE-xg4XtTw9.mjs +1 -0
- package/dist/packem_shared/VECTORIZE_CAPABILITIES-l9ceRO5j.mjs +1 -0
- package/dist/packem_shared/batchReranker-Bc38FBLH.mjs +1 -0
- package/dist/packem_shared/bm25-9q0Avwi-.mjs +1 -0
- package/dist/packem_shared/bm25LexicalStore-DMUzAL0O.mjs +1 -0
- package/dist/packem_shared/concurrent-C6nqBv41.mjs +1 -0
- package/dist/packem_shared/contentHash-BIn6ECP8.mjs +1 -0
- package/dist/packem_shared/createAi-DlKGnlHR.mjs +1 -0
- package/dist/packem_shared/defineRag-gjKfV0c0.mjs +8 -0
- package/dist/packem_shared/defineRagSource-Q3f3niU8.mjs +1 -0
- package/dist/packem_shared/fixedWindowChunks-C461ahRE.mjs +1 -0
- package/dist/packem_shared/hybridRank-B4skyCLx.mjs +1 -0
- package/dist/packem_shared/markdownChunker-iW8V4klY.mjs +5 -0
- package/dist/packem_shared/matchesMetadataFilter-BbIOyA5g.mjs +1 -0
- package/dist/packem_shared/ragSyncTriggers-D933fCwt.mjs +1 -0
- package/dist/packem_shared/sql-D5aqEMCY.mjs +1 -0
- package/dist/packem_shared/sqlLexicalStore-DQiteyUn.mjs +1 -0
- package/dist/packem_shared/sqliteVectorStore-f24ySqtJ.mjs +1 -0
- package/dist/packem_shared/types.d-BXqvdqrj.d.mts +614 -0
- package/dist/packem_shared/types.d-BXqvdqrj.d.ts +614 -0
- package/dist/rag/index.d.mts +1214 -6
- package/dist/rag/index.d.ts +1214 -6
- package/dist/rag/index.mjs +1 -5
- package/package.json +13 -16
- package/dist/packem_shared/bm25LexicalStore-Q28z6fbO.mjs +0 -118
- package/dist/packem_shared/contentHash-Cgz5KRGD.mjs +0 -92
- package/dist/packem_shared/createAi-CYxQuvEL.mjs +0 -55
- package/dist/packem_shared/defineRag-BwrgePLE.mjs +0 -402
- package/dist/packem_shared/fixedWindowChunks-J-WfQDw9.mjs +0 -26
- package/dist/packem_shared/hybridRank-DPC9c2ON.mjs +0 -20
- package/dist/packem_shared/types.d-C6dA8LCy.d.mts +0 -28
- package/dist/packem_shared/types.d-C6dA8LCy.d.ts +0 -28
package/dist/rag/index.mjs
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { default as defineRag } from '../packem_shared/defineRag-BwrgePLE.mjs';
|
|
3
|
-
export { contentHash, guessMimeTypeFromExtension } from '../packem_shared/contentHash-Cgz5KRGD.mjs';
|
|
4
|
-
export { default as hybridRank } from '../packem_shared/hybridRank-DPC9c2ON.mjs';
|
|
5
|
-
export { default as bm25LexicalStore } from '../packem_shared/bm25LexicalStore-Q28z6fbO.mjs';
|
|
1
|
+
import{default as o}from"../packem_shared/fixedWindowChunks-C461ahRE.mjs";import{markdownChunker as a,sentenceChunker as f,tokenChunker as n}from"../packem_shared/markdownChunker-iW8V4klY.mjs";import{default as x}from"../packem_shared/defineRag-gjKfV0c0.mjs";import{contentHash as p,guessMimeTypeFromExtension as i}from"../packem_shared/contentHash-BIn6ECP8.mjs";import{hybridRank as d}from"../packem_shared/hybridRank-B4skyCLx.mjs";import{default as k}from"../packem_shared/bm25LexicalStore-DMUzAL0O.mjs";import{default as h}from"../packem_shared/matchesMetadataFilter-BbIOyA5g.mjs";import{batchReranker as g,scoreReranker as C}from"../packem_shared/batchReranker-Bc38FBLH.mjs";import{defineRagSource as E}from"../packem_shared/defineRagSource-Q3f3niU8.mjs";import{sqlLexicalStore as T}from"../packem_shared/sqlLexicalStore-DQiteyUn.mjs";import{sqliteVectorStore as y}from"../packem_shared/sqliteVectorStore-f24ySqtJ.mjs";import{ragSyncTriggers as q}from"../packem_shared/ragSyncTriggers-D933fCwt.mjs";import{VECTORIZE_CAPABILITIES as A,vectorizeStore as F}from"../packem_shared/VECTORIZE_CAPABILITIES-l9ceRO5j.mjs";export{A as VECTORIZE_CAPABILITIES,g as batchReranker,k as bm25LexicalStore,p as contentHash,x as defineRag,E as defineRagSource,o as fixedWindowChunks,i as guessMimeTypeFromExtension,d as hybridRank,a as markdownChunker,h as matchesMetadataFilter,q as ragSyncTriggers,C as scoreReranker,f as sentenceChunker,T as sqlLexicalStore,y as sqliteVectorStore,n as tokenChunker,F as vectorizeStore};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/ai",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.151",
|
|
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",
|
|
@@ -43,6 +43,10 @@
|
|
|
43
43
|
"types": "./dist/index.d.ts",
|
|
44
44
|
"import": "./dist/index.mjs"
|
|
45
45
|
},
|
|
46
|
+
"./create": {
|
|
47
|
+
"types": "./dist/create.d.ts",
|
|
48
|
+
"import": "./dist/create.mjs"
|
|
49
|
+
},
|
|
46
50
|
"./rag": {
|
|
47
51
|
"types": "./dist/rag/index.d.ts",
|
|
48
52
|
"import": "./dist/rag/index.mjs"
|
|
@@ -53,21 +57,14 @@
|
|
|
53
57
|
"access": "public"
|
|
54
58
|
},
|
|
55
59
|
"dependencies": {
|
|
56
|
-
"@
|
|
57
|
-
"ai": "
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"@
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
"peerDependenciesMeta": {
|
|
65
|
-
"@ai-sdk/anthropic": {
|
|
66
|
-
"optional": true
|
|
67
|
-
},
|
|
68
|
-
"@ai-sdk/openai": {
|
|
69
|
-
"optional": true
|
|
70
|
-
}
|
|
60
|
+
"@ai-sdk/anthropic": "4.0.71",
|
|
61
|
+
"@ai-sdk/google": "4.0.87",
|
|
62
|
+
"@ai-sdk/openai": "4.0.83",
|
|
63
|
+
"@ai-sdk/provider-utils": "5.0.53",
|
|
64
|
+
"@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
|
|
65
|
+
"@lunora/wire": "1.0.0-alpha.3",
|
|
66
|
+
"ai": "7.0.127",
|
|
67
|
+
"workers-ai-provider": "4.0.0"
|
|
71
68
|
},
|
|
72
69
|
"engines": {
|
|
73
70
|
"node": "^22.15.0 || >=24.11.0"
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
const BM25_K1 = 1.5;
|
|
2
|
-
const BM25_B = 0.75;
|
|
3
|
-
const TOKEN_PATTERN = /[a-z0-9]+/g;
|
|
4
|
-
const tokenize = (text) => text.toLowerCase().match(TOKEN_PATTERN) ?? [];
|
|
5
|
-
const isPrimitiveFilter = (filter) => Object.values(filter).every((value) => value === null || typeof value !== "object");
|
|
6
|
-
const filterWarned = /* @__PURE__ */ new WeakSet();
|
|
7
|
-
const bm25LexicalStore = () => {
|
|
8
|
-
const namespaces = /* @__PURE__ */ new Map();
|
|
9
|
-
const stateFor = (namespace = "") => {
|
|
10
|
-
let state = namespaces.get(namespace);
|
|
11
|
-
if (!state) {
|
|
12
|
-
state = { documents: /* @__PURE__ */ new Map(), postings: /* @__PURE__ */ new Map(), totalLength: 0 };
|
|
13
|
-
namespaces.set(namespace, state);
|
|
14
|
-
}
|
|
15
|
-
return state;
|
|
16
|
-
};
|
|
17
|
-
const removeDocument = (namespace, id) => {
|
|
18
|
-
const state = stateFor(namespace);
|
|
19
|
-
const existing = state.documents.get(id);
|
|
20
|
-
if (!existing) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
for (const term of existing.termFrequency.keys()) {
|
|
24
|
-
const posting = state.postings.get(term);
|
|
25
|
-
if (posting) {
|
|
26
|
-
posting.delete(id);
|
|
27
|
-
if (posting.size === 0) {
|
|
28
|
-
state.postings.delete(term);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
state.totalLength -= existing.length;
|
|
33
|
-
state.documents.delete(id);
|
|
34
|
-
};
|
|
35
|
-
const store = {
|
|
36
|
-
index: (chunks, options) => {
|
|
37
|
-
const state = stateFor(options.namespace);
|
|
38
|
-
for (const chunk of chunks) {
|
|
39
|
-
removeDocument(options.namespace, chunk.id);
|
|
40
|
-
const tokens = tokenize(chunk.text);
|
|
41
|
-
if (tokens.length === 0) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
const termFrequency = /* @__PURE__ */ new Map();
|
|
45
|
-
for (const token of tokens) {
|
|
46
|
-
termFrequency.set(token, (termFrequency.get(token) ?? 0) + 1);
|
|
47
|
-
}
|
|
48
|
-
for (const [term, frequency] of termFrequency) {
|
|
49
|
-
let posting = state.postings.get(term);
|
|
50
|
-
if (!posting) {
|
|
51
|
-
posting = /* @__PURE__ */ new Map();
|
|
52
|
-
state.postings.set(term, posting);
|
|
53
|
-
}
|
|
54
|
-
posting.set(chunk.id, frequency);
|
|
55
|
-
}
|
|
56
|
-
state.documents.set(chunk.id, { length: tokens.length, termFrequency, text: chunk.text });
|
|
57
|
-
state.totalLength += tokens.length;
|
|
58
|
-
}
|
|
59
|
-
return Promise.resolve();
|
|
60
|
-
},
|
|
61
|
-
remove: (ids, options) => {
|
|
62
|
-
for (const id of ids) {
|
|
63
|
-
removeDocument(options.namespace, id);
|
|
64
|
-
}
|
|
65
|
-
return Promise.resolve();
|
|
66
|
-
},
|
|
67
|
-
search: (query, options) => {
|
|
68
|
-
if (options.filter && Object.keys(options.filter).length > 0 && !isPrimitiveFilter(options.filter)) {
|
|
69
|
-
if (!filterWarned.has(store)) {
|
|
70
|
-
filterWarned.add(store);
|
|
71
|
-
console.warn(
|
|
72
|
-
"[@lunora/ai/rag] bm25LexicalStore cannot evaluate a metadata filter (it stores no metadata);\nthe lexical leg is skipped for filtered queries. Fold the RLS dimension into `namespace`,\nor plug a filter-aware RagLexicalStore, to keep a lexical leg under metadata-based RLS."
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
return Promise.resolve([]);
|
|
76
|
-
}
|
|
77
|
-
const state = stateFor(options.namespace);
|
|
78
|
-
const documentCount = state.documents.size;
|
|
79
|
-
if (documentCount === 0) {
|
|
80
|
-
return Promise.resolve([]);
|
|
81
|
-
}
|
|
82
|
-
const queryTerms = [...new Set(tokenize(query))];
|
|
83
|
-
if (queryTerms.length === 0) {
|
|
84
|
-
return Promise.resolve([]);
|
|
85
|
-
}
|
|
86
|
-
const averageLength = state.totalLength / documentCount;
|
|
87
|
-
const scores = /* @__PURE__ */ new Map();
|
|
88
|
-
for (const term of queryTerms) {
|
|
89
|
-
const posting = state.postings.get(term);
|
|
90
|
-
if (!posting) {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
const documentFrequency = posting.size;
|
|
94
|
-
const idf = Math.log(1 + (documentCount - documentFrequency + 0.5) / (documentFrequency + 0.5));
|
|
95
|
-
for (const [id, frequency] of posting) {
|
|
96
|
-
const document = state.documents.get(id);
|
|
97
|
-
if (!document) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
const denominator = frequency + BM25_K1 * (1 - BM25_B + BM25_B * document.length / averageLength);
|
|
101
|
-
const contribution = idf * (frequency * (BM25_K1 + 1) / denominator);
|
|
102
|
-
scores.set(id, (scores.get(id) ?? 0) + contribution);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const matches = [...scores.entries()].map(([id, score]) => {
|
|
106
|
-
return {
|
|
107
|
-
id,
|
|
108
|
-
score,
|
|
109
|
-
text: state.documents.get(id)?.text ?? ""
|
|
110
|
-
};
|
|
111
|
-
});
|
|
112
|
-
return Promise.resolve(matches.toSorted((a, b) => b.score - a.score).slice(0, options.topK));
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
return store;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
export { bm25LexicalStore as default };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
const DOT_PREFIX_RE = /^\.+/u;
|
|
2
|
-
const EXTENSION_MIME_MAP = {
|
|
3
|
-
// Images
|
|
4
|
-
avif: "image/avif",
|
|
5
|
-
bmp: "image/bmp",
|
|
6
|
-
gif: "image/gif",
|
|
7
|
-
ico: "image/x-icon",
|
|
8
|
-
jpeg: "image/jpeg",
|
|
9
|
-
jpg: "image/jpeg",
|
|
10
|
-
png: "image/png",
|
|
11
|
-
svg: "image/svg+xml",
|
|
12
|
-
tiff: "image/tiff",
|
|
13
|
-
tif: "image/tiff",
|
|
14
|
-
webp: "image/webp",
|
|
15
|
-
// Video
|
|
16
|
-
avi: "video/x-msvideo",
|
|
17
|
-
mkv: "video/x-matroska",
|
|
18
|
-
mov: "video/quicktime",
|
|
19
|
-
mp4: "video/mp4",
|
|
20
|
-
mpeg: "video/mpeg",
|
|
21
|
-
mpg: "video/mpeg",
|
|
22
|
-
webm: "video/webm",
|
|
23
|
-
wmv: "video/x-ms-wmv",
|
|
24
|
-
// Audio
|
|
25
|
-
aac: "audio/aac",
|
|
26
|
-
flac: "audio/flac",
|
|
27
|
-
m4a: "audio/mp4",
|
|
28
|
-
mp3: "audio/mpeg",
|
|
29
|
-
ogg: "audio/ogg",
|
|
30
|
-
opus: "audio/opus",
|
|
31
|
-
wav: "audio/wav",
|
|
32
|
-
wma: "audio/x-ms-wma",
|
|
33
|
-
// Documents (office / PDF)
|
|
34
|
-
csv: "text/csv",
|
|
35
|
-
doc: "application/msword",
|
|
36
|
-
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
37
|
-
odp: "application/vnd.oasis.opendocument.presentation",
|
|
38
|
-
ods: "application/vnd.oasis.opendocument.spreadsheet",
|
|
39
|
-
odt: "application/vnd.oasis.opendocument.text",
|
|
40
|
-
pdf: "application/pdf",
|
|
41
|
-
ppt: "application/vnd.ms-powerpoint",
|
|
42
|
-
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
43
|
-
rtf: "application/rtf",
|
|
44
|
-
xls: "application/vnd.ms-excel",
|
|
45
|
-
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
46
|
-
// Text / markup
|
|
47
|
-
css: "text/css",
|
|
48
|
-
html: "text/html",
|
|
49
|
-
htm: "text/html",
|
|
50
|
-
ini: "text/plain",
|
|
51
|
-
json: "application/json",
|
|
52
|
-
js: "text/javascript",
|
|
53
|
-
mjs: "text/javascript",
|
|
54
|
-
md: "text/markdown",
|
|
55
|
-
jsx: "text/javascript",
|
|
56
|
-
ts: "text/typescript",
|
|
57
|
-
tsx: "text/typescript",
|
|
58
|
-
txt: "text/plain",
|
|
59
|
-
xml: "application/xml",
|
|
60
|
-
yaml: "application/x-yaml",
|
|
61
|
-
yml: "application/x-yaml",
|
|
62
|
-
// Archives / binaries
|
|
63
|
-
"7z": "application/x-7z-compressed",
|
|
64
|
-
bz2: "application/x-bzip2",
|
|
65
|
-
gz: "application/gzip",
|
|
66
|
-
jar: "application/java-archive",
|
|
67
|
-
rar: "application/vnd.rar",
|
|
68
|
-
tar: "application/x-tar",
|
|
69
|
-
zip: "application/zip",
|
|
70
|
-
// Fonts
|
|
71
|
-
otf: "font/otf",
|
|
72
|
-
ttf: "font/ttf",
|
|
73
|
-
woff: "font/woff",
|
|
74
|
-
woff2: "font/woff2",
|
|
75
|
-
// Other common
|
|
76
|
-
bin: "application/octet-stream",
|
|
77
|
-
epub: "application/epub+zip",
|
|
78
|
-
exe: "application/vnd.microsoft.portable-executable",
|
|
79
|
-
iso: "application/x-iso9660-image",
|
|
80
|
-
sql: "application/sql",
|
|
81
|
-
toml: "application/toml"
|
|
82
|
-
};
|
|
83
|
-
const guessMimeTypeFromExtension = (extension) => {
|
|
84
|
-
const normalizedExtension = extension.replace(DOT_PREFIX_RE, "").toLowerCase();
|
|
85
|
-
return EXTENSION_MIME_MAP[normalizedExtension] ?? "application/octet-stream";
|
|
86
|
-
};
|
|
87
|
-
const contentHash = async (data) => {
|
|
88
|
-
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
89
|
-
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
export { contentHash, guessMimeTypeFromExtension };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
import { createWorkersAI } from 'workers-ai-provider';
|
|
3
|
-
|
|
4
|
-
const buildProvider = (binding, gateway) => createWorkersAI({ binding, gateway });
|
|
5
|
-
const createAi = (options) => {
|
|
6
|
-
const { binding, defaultEmbeddingModel, defaultModel, gateway, provider } = options;
|
|
7
|
-
if (!provider && !binding) {
|
|
8
|
-
throw new LunoraError("INTERNAL", "@lunora/ai: createAi requires a `binding` (env.AI) or a pre-built `provider`");
|
|
9
|
-
}
|
|
10
|
-
const workersai = provider ?? buildProvider(binding, gateway);
|
|
11
|
-
const model = (input) => {
|
|
12
|
-
if (input === void 0) {
|
|
13
|
-
if (!defaultModel) {
|
|
14
|
-
throw new LunoraError("INTERNAL", "@lunora/ai: no model supplied and no `defaultModel` configured — pass a model id or an AI SDK model");
|
|
15
|
-
}
|
|
16
|
-
return workersai(defaultModel);
|
|
17
|
-
}
|
|
18
|
-
return typeof input === "string" ? workersai(input) : input;
|
|
19
|
-
};
|
|
20
|
-
const resolveEmbeddingModel = (modelId) => {
|
|
21
|
-
const factory = workersai.textEmbeddingModel;
|
|
22
|
-
if (typeof factory !== "function") {
|
|
23
|
-
throw new LunoraError(
|
|
24
|
-
"INTERNAL",
|
|
25
|
-
"@lunora/ai: the Workers AI provider does not expose `textEmbeddingModel`; pass an AI SDK EmbeddingModel (e.g. from @ai-sdk/openai) to embed()"
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
return factory.call(workersai, modelId);
|
|
29
|
-
};
|
|
30
|
-
const embeddingModel = (input) => {
|
|
31
|
-
if (typeof input === "object") {
|
|
32
|
-
return input;
|
|
33
|
-
}
|
|
34
|
-
const modelId = input ?? defaultEmbeddingModel;
|
|
35
|
-
if (!modelId) {
|
|
36
|
-
throw new LunoraError(
|
|
37
|
-
"INTERNAL",
|
|
38
|
-
"@lunora/ai: no embedding model supplied and no `defaultEmbeddingModel` configured — pass an embedding model id or an AI SDK EmbeddingModel"
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
return resolveEmbeddingModel(modelId);
|
|
42
|
-
};
|
|
43
|
-
const run = async (modelId, inputs, runOptions) => {
|
|
44
|
-
if (!binding) {
|
|
45
|
-
throw new LunoraError(
|
|
46
|
-
"INTERNAL",
|
|
47
|
-
"@lunora/ai: ai.run requires the `binding` (env.AI) — it is unavailable when only a custom `provider` was supplied"
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
return binding.run(modelId, inputs, runOptions);
|
|
51
|
-
};
|
|
52
|
-
return { embeddingModel, model, run, workersai };
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export { createAi as default };
|