@zukhruf/embeddings 0.0.0-stage → 0.3.47
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/LICENSE +21 -0
- package/README.md +76 -2
- package/dist/collection.d.ts +32 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +159 -0
- package/dist/collection.js.map +1 -0
- package/dist/dimension-mismatch-error.d.ts +6 -0
- package/dist/dimension-mismatch-error.d.ts.map +1 -0
- package/dist/dimension-mismatch-error.js +13 -0
- package/dist/dimension-mismatch-error.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/schema.d.ts +3 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +17 -0
- package/dist/schema.js.map +1 -0
- package/dist/unknown-document-error.d.ts +5 -0
- package/dist/unknown-document-error.d.ts.map +1 -0
- package/dist/unknown-document-error.js +10 -0
- package/dist/unknown-document-error.js.map +1 -0
- package/dist/vector.d.ts +10 -0
- package/dist/vector.d.ts.map +1 -0
- package/dist/vector.js +38 -0
- package/dist/vector.js.map +1 -0
- package/package.json +49 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ezzabuzaid
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,77 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @zukhruf/embeddings
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A program that compares texts by meaning needs a vector for each text, and the model call that makes the vector is slow. This package keeps the vectors of documents in a SQLite database. An upsert calls the model only for new or changed text. A search gives the nearest documents of a document, by exact cosine similarity, from the documents published near it. This kind of package is also known as a vector store.
|
|
4
|
+
|
|
5
|
+
The words in these documents have one meaning each. See the glossary in [CONTEXT.md](./CONTEXT.md).
|
|
6
|
+
|
|
7
|
+
## Use it
|
|
8
|
+
|
|
9
|
+
This project is an experiment. It uses `node:sqlite` and an embedding model of the [AI SDK](https://ai-sdk.dev). The package does not start a model or a server. Give it a model that is ready.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @zukhruf/embeddings ai
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
17
|
+
|
|
18
|
+
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
19
|
+
|
|
20
|
+
import { Collection } from '@zukhruf/embeddings';
|
|
21
|
+
|
|
22
|
+
const local = createOpenAICompatible({
|
|
23
|
+
name: 'llama.cpp',
|
|
24
|
+
baseURL: 'http://127.0.0.1:8080/v1',
|
|
25
|
+
});
|
|
26
|
+
using database = new DatabaseSync('embeddings.sqlite');
|
|
27
|
+
const collection = new Collection({
|
|
28
|
+
database,
|
|
29
|
+
model: local.embeddingModel('embeddinggemma'),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
await collection.upsert([
|
|
33
|
+
{
|
|
34
|
+
id: 'a',
|
|
35
|
+
text: 'Storm closes the port',
|
|
36
|
+
publishedAt: new Date('2026-10-20'),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'b',
|
|
40
|
+
text: 'Port shut as storm hits',
|
|
41
|
+
publishedAt: new Date('2026-10-21'),
|
|
42
|
+
},
|
|
43
|
+
{ id: 'c', text: 'Port opens again', publishedAt: new Date('2026-11-30') },
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
collection.nearest('a', { k: 10, withinDays: 7 }); // [{ id: 'b', similarity: … }]
|
|
47
|
+
collection.similarity('a', 'c');
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## API
|
|
51
|
+
|
|
52
|
+
- `new Collection({ database, model })`. The caller opens and closes `database`. The collection makes its table `embedding_document` in it. `model` is an AI SDK embedding model object.
|
|
53
|
+
- `upsert(documents)` stores each document. It calls the model, through `embedMany`, only for a document whose text or model changed. It stores the new publish date of each document.
|
|
54
|
+
- `nearest(id, { k, withinDays })` gives at most `k` neighbours of the document, with the highest similarity first. A neighbour has a publish date at most `withinDays` days before or after the publish date of the document. Equal similarities sort by id.
|
|
55
|
+
- `neighbourGraph({ from, to, k, withinDays })` gives an iterator of `[id, neighbours]` entries, one for each document published from `from` to `to`, in the order of the publish dates and then of the ids. The neighbours of each entry are equal to the result of `nearest(id, { k, withinDays })`. A document outside the range has no entry, but it can be a neighbour of a document in the range. The call reads and decodes each vector one time ([ADR 0004](./docs/adr/0004-a-neighbour-graph-decodes-each-vector-once.md)). Use it when you need the neighbours of many documents.
|
|
56
|
+
- `similarity(a, b)` gives the cosine similarity of two stored documents.
|
|
57
|
+
|
|
58
|
+
## Errors
|
|
59
|
+
|
|
60
|
+
- `UnknownDocumentError`: `nearest` or `similarity` got an id that the collection does not store.
|
|
61
|
+
- `DimensionMismatchError`: the model gave a vector with a dimension that is not the dimension of the stored vectors. The upsert stores none of its documents. To change to a model with another dimension, upsert all documents in one call.
|
|
62
|
+
|
|
63
|
+
## Limits
|
|
64
|
+
|
|
65
|
+
- One database holds one collection.
|
|
66
|
+
- The collection stores the vector of the text, not the text. The caller chooses the text, for example a title and the first sentences.
|
|
67
|
+
- A document has one vector. A long text gives one mean vector, and its details become a small part of it.
|
|
68
|
+
- The search reads each document in the window ([ADR 0001](./docs/adr/0001-search-compares-each-document-in-the-window.md)). A window of many thousand documents is slow. A neighbour graph decodes each vector once, but it still calculates a similarity for each pair of documents in a window.
|
|
69
|
+
- After a model change, upsert all documents again ([ADR 0002](./docs/adr/0002-the-hash-includes-the-model.md)).
|
|
70
|
+
|
|
71
|
+
## Decisions
|
|
72
|
+
|
|
73
|
+
- [ADR 0001: A search compares each document in the window, with no index](./docs/adr/0001-search-compares-each-document-in-the-window.md)
|
|
74
|
+
- [ADR 0002: The hash includes the model](./docs/adr/0002-the-hash-includes-the-model.md)
|
|
75
|
+
- [ADR 0003: All vectors of a collection have one dimension](./docs/adr/0003-all-vectors-of-a-collection-have-one-dimension.md)
|
|
76
|
+
- [ADR 0004: A neighbour graph decodes each vector once](./docs/adr/0004-a-neighbour-graph-decodes-each-vector-once.md)
|
|
77
|
+
- [Code copied from @deepagents/retrieval](./docs/copied-from-deepagents-retrieval.md)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import { type EmbeddingModel } from 'ai';
|
|
3
|
+
export type Document = {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly text: string;
|
|
6
|
+
readonly publishedAt: Date;
|
|
7
|
+
};
|
|
8
|
+
export type Neighbour = {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly similarity: number;
|
|
11
|
+
};
|
|
12
|
+
export type CollectionOptions = {
|
|
13
|
+
readonly database: DatabaseSync;
|
|
14
|
+
readonly model: Exclude<EmbeddingModel, string>;
|
|
15
|
+
};
|
|
16
|
+
export declare class Collection {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(options: CollectionOptions);
|
|
19
|
+
upsert(documents: readonly Document[]): Promise<void>;
|
|
20
|
+
nearest(id: string, options: {
|
|
21
|
+
readonly k: number;
|
|
22
|
+
readonly withinDays: number;
|
|
23
|
+
}): Neighbour[];
|
|
24
|
+
neighbourGraph(options: {
|
|
25
|
+
readonly from: Date;
|
|
26
|
+
readonly to: Date;
|
|
27
|
+
readonly k: number;
|
|
28
|
+
readonly withinDays: number;
|
|
29
|
+
}): IteratorObject<[string, Neighbour[]]>;
|
|
30
|
+
similarity(a: string, b: string): number;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,KAAK,cAAc,EAAa,MAAM,IAAI,CAAC;AAWpD,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAE9B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAGhC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;CACjD,CAAC;AAKF,qBAAa,UAAU;;gBAIT,OAAO,EAAE,iBAAiB;IAQhC,MAAM,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAsD3D,OAAO,CACL,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3D,SAAS,EAAE;IAoBd,cAAc,CAAC,OAAO,EAAE;QACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;QACpB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;QAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;KAC7B,GAAG,cAAc,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAgCzC,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM;CAqDzC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { embedMany } from 'ai';
|
|
3
|
+
import { transaction } from '@zukhruf/sqlite-transaction';
|
|
4
|
+
import { DimensionMismatchError } from "./dimension-mismatch-error.js";
|
|
5
|
+
import { collectionSchema } from "./schema.js";
|
|
6
|
+
import { UnknownDocumentError } from "./unknown-document-error.js";
|
|
7
|
+
import { UnitVector } from "./vector.js";
|
|
8
|
+
const DAY_MS = 86_400_000;
|
|
9
|
+
// The embeddings of documents, one vector for each document, in a SQLite
|
|
10
|
+
// database. A search compares the document with each document published
|
|
11
|
+
// inside the window, with no index (docs/adr/0001).
|
|
12
|
+
export class Collection {
|
|
13
|
+
#database;
|
|
14
|
+
#model;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.#database = options.database;
|
|
17
|
+
this.#model = options.model;
|
|
18
|
+
collectionSchema.apply(this.#database);
|
|
19
|
+
}
|
|
20
|
+
// Embeds the documents whose text or model changed since their last upsert,
|
|
21
|
+
// and stores the publish date of each document.
|
|
22
|
+
async upsert(documents) {
|
|
23
|
+
const stored = this.#database.prepare('SELECT "hash" FROM "embedding_document" WHERE "id" = ?');
|
|
24
|
+
const hashed = documents.map((document) => ({
|
|
25
|
+
document,
|
|
26
|
+
hash: this.#hash(document.text),
|
|
27
|
+
}));
|
|
28
|
+
const { changed = [], unchanged = [] } = Object.groupBy(hashed, ({ document, hash }) => stored.get(document.id)?.hash === hash ? 'unchanged' : 'changed');
|
|
29
|
+
const vectors = await this.#embed(changed.map(({ document }) => document.text));
|
|
30
|
+
transaction(this.#database, () => {
|
|
31
|
+
const write = this.#database.prepare(`INSERT INTO "embedding_document" ("id", "hash", "published_at", "vector") VALUES (?, ?, ?, ?)
|
|
32
|
+
ON CONFLICT ("id") DO UPDATE SET "hash" = excluded."hash", "published_at" = excluded."published_at", "vector" = excluded."vector"`);
|
|
33
|
+
for (const [index, { document, hash }] of changed.entries()) {
|
|
34
|
+
const vector = vectors[index];
|
|
35
|
+
if (vector === undefined)
|
|
36
|
+
throw new Error(`The model gave ${vectors.length} embeddings for ${changed.length} texts.`);
|
|
37
|
+
write.run(document.id, hash, document.publishedAt.getTime(), vector.toBlob());
|
|
38
|
+
}
|
|
39
|
+
const move = this.#database.prepare('UPDATE "embedding_document" SET "published_at" = ? WHERE "id" = ?');
|
|
40
|
+
for (const { document } of unchanged)
|
|
41
|
+
move.run(document.publishedAt.getTime(), document.id);
|
|
42
|
+
this.#checkDimension(changed.map(({ document }) => document.id), vectors);
|
|
43
|
+
}, { mode: 'immediate' });
|
|
44
|
+
}
|
|
45
|
+
// The k documents most similar to the document, by cosine similarity, from
|
|
46
|
+
// those published at most withinDays before or after it. The document
|
|
47
|
+
// itself is not one of them. Equal similarities sort by id.
|
|
48
|
+
nearest(id, options) {
|
|
49
|
+
const { vector, publishedAt } = this.#read(id);
|
|
50
|
+
const window = options.withinDays * DAY_MS;
|
|
51
|
+
const candidates = this.#database
|
|
52
|
+
.prepare('SELECT "id", "vector" FROM "embedding_document" WHERE "published_at" BETWEEN ? AND ? AND "id" != ?')
|
|
53
|
+
.all(publishedAt - window, publishedAt + window, id)
|
|
54
|
+
.map((row) => ({
|
|
55
|
+
id: String(row.id),
|
|
56
|
+
vector: UnitVector.fromBlob(blob(row.vector)),
|
|
57
|
+
}));
|
|
58
|
+
return ranked(vector, candidates, options.k);
|
|
59
|
+
}
|
|
60
|
+
// The k nearest neighbours of each document published from `from` to `to`.
|
|
61
|
+
// Each entry is what nearest gives for the document with the same k and
|
|
62
|
+
// withinDays. The call reads and decodes each vector once
|
|
63
|
+
// (docs/adr/0004). The entries come in the order of the publish dates, then
|
|
64
|
+
// of the ids.
|
|
65
|
+
neighbourGraph(options) {
|
|
66
|
+
const from = options.from.getTime();
|
|
67
|
+
const to = options.to.getTime();
|
|
68
|
+
const window = options.withinDays * DAY_MS;
|
|
69
|
+
const documents = this.#database
|
|
70
|
+
.prepare('SELECT "id", "published_at", "vector" FROM "embedding_document" WHERE "published_at" BETWEEN ? AND ? ORDER BY "published_at", "id"')
|
|
71
|
+
.all(from - window, to + window)
|
|
72
|
+
.map((row) => ({
|
|
73
|
+
id: String(row.id),
|
|
74
|
+
publishedAt: Number(row.published_at),
|
|
75
|
+
vector: UnitVector.fromBlob(blob(row.vector)),
|
|
76
|
+
}));
|
|
77
|
+
return documents
|
|
78
|
+
.values()
|
|
79
|
+
.filter(({ publishedAt }) => publishedAt >= from && publishedAt <= to)
|
|
80
|
+
.map((document) => [
|
|
81
|
+
document.id,
|
|
82
|
+
ranked(document.vector, documents.filter((other) => other.id !== document.id &&
|
|
83
|
+
Math.abs(other.publishedAt - document.publishedAt) <= window), options.k),
|
|
84
|
+
]);
|
|
85
|
+
}
|
|
86
|
+
// The cosine similarity of two stored documents.
|
|
87
|
+
similarity(a, b) {
|
|
88
|
+
return this.#read(a).vector.cosine(this.#read(b).vector);
|
|
89
|
+
}
|
|
90
|
+
// No texts make no call to the model.
|
|
91
|
+
async #embed(texts) {
|
|
92
|
+
if (texts.length === 0)
|
|
93
|
+
return [];
|
|
94
|
+
const { embeddings } = await embedMany({
|
|
95
|
+
model: this.#model,
|
|
96
|
+
values: texts,
|
|
97
|
+
});
|
|
98
|
+
return embeddings.map((embedding) => UnitVector.normalize(embedding));
|
|
99
|
+
}
|
|
100
|
+
// The model is part of the hash, so a new model embeds the text again.
|
|
101
|
+
#hash(text) {
|
|
102
|
+
return createHash('sha256')
|
|
103
|
+
.update(JSON.stringify([this.#model.provider, this.#model.modelId, text]))
|
|
104
|
+
.digest('hex');
|
|
105
|
+
}
|
|
106
|
+
#read(id) {
|
|
107
|
+
const row = this.#database
|
|
108
|
+
.prepare('SELECT "vector", "published_at" FROM "embedding_document" WHERE "id" = ?')
|
|
109
|
+
.get(id);
|
|
110
|
+
if (row === undefined)
|
|
111
|
+
throw new UnknownDocumentError(id);
|
|
112
|
+
return {
|
|
113
|
+
vector: UnitVector.fromBlob(blob(row.vector)),
|
|
114
|
+
publishedAt: Number(row.published_at),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// Before the upsert, each stored vector has one dimension. The new vectors
|
|
118
|
+
// must have the dimension of a vector that the upsert did not replace, and
|
|
119
|
+
// of each other.
|
|
120
|
+
#checkDimension(replaced, vectors) {
|
|
121
|
+
const [first] = vectors;
|
|
122
|
+
if (first === undefined)
|
|
123
|
+
return;
|
|
124
|
+
const kept = this.#database
|
|
125
|
+
.prepare('SELECT length("vector") AS "bytes" FROM "embedding_document" WHERE "id" NOT IN (SELECT "value" FROM json_each(?)) LIMIT 1')
|
|
126
|
+
.get(JSON.stringify(replaced));
|
|
127
|
+
const expected = kept === undefined
|
|
128
|
+
? first.dimension
|
|
129
|
+
: Number(kept.bytes) / Float32Array.BYTES_PER_ELEMENT;
|
|
130
|
+
for (const vector of vectors)
|
|
131
|
+
if (vector.dimension !== expected)
|
|
132
|
+
throw new DimensionMismatchError(expected, vector.dimension);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// The k candidates most similar to the vector. Equal similarities sort by id.
|
|
136
|
+
function ranked(vector, candidates, k) {
|
|
137
|
+
return candidates
|
|
138
|
+
.map((candidate) => ({
|
|
139
|
+
id: candidate.id,
|
|
140
|
+
similarity: vector.cosine(candidate.vector),
|
|
141
|
+
}))
|
|
142
|
+
.toSorted((left, right) => right.similarity - left.similarity || compareIds(left.id, right.id))
|
|
143
|
+
.slice(0, k);
|
|
144
|
+
}
|
|
145
|
+
// Compares by code unit, not by locale, so the order is the same on every
|
|
146
|
+
// machine.
|
|
147
|
+
function compareIds(left, right) {
|
|
148
|
+
if (left < right)
|
|
149
|
+
return -1;
|
|
150
|
+
if (left > right)
|
|
151
|
+
return 1;
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
function blob(value) {
|
|
155
|
+
if (!(value instanceof Uint8Array))
|
|
156
|
+
throw new TypeError('A stored vector must be a BLOB.');
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dimension-mismatch-error.d.ts","sourceRoot":"","sources":["../src/dimension-mismatch-error.ts"],"names":[],"mappings":"AAEA,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAQ7C"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// The model gave a vector whose dimension is not the dimension of the vectors
|
|
2
|
+
// that the collection stores.
|
|
3
|
+
export class DimensionMismatchError extends Error {
|
|
4
|
+
expected;
|
|
5
|
+
actual;
|
|
6
|
+
constructor(expected, actual) {
|
|
7
|
+
super(`The collection stores vectors of dimension ${expected}, and the model gave a vector of dimension ${actual}. Upsert every document again with the new model, in one call.`);
|
|
8
|
+
this.name = 'DimensionMismatchError';
|
|
9
|
+
this.expected = expected;
|
|
10
|
+
this.actual = actual;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=dimension-mismatch-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dimension-mismatch-error.js","sourceRoot":"","sources":["../src/dimension-mismatch-error.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8BAA8B;AAC9B,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACtC,QAAQ,CAAS;IACjB,MAAM,CAAS;IAExB,YAAY,QAAgB,EAAE,MAAc;QAC1C,KAAK,CACH,8CAA8C,QAAQ,8CAA8C,MAAM,gEAAgE,CAC3K,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { Collection, type CollectionOptions, type Document, type Neighbour, } from './collection.ts';
|
|
2
|
+
export { DimensionMismatchError } from './dimension-mismatch-error.ts';
|
|
3
|
+
export { UnknownDocumentError } from './unknown-document-error.ts';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,GAIX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAKpD,eAAO,MAAM,gBAAgB,aAc5B,CAAC"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Declaration } from '@zukhruf/sqlite-drift';
|
|
2
|
+
// The documents of a collection. Every row derives from a caller's document
|
|
3
|
+
// and the model, so a stale table is replaced with its rows: the next upsert
|
|
4
|
+
// of the caller embeds the documents again (docs/adr/0003).
|
|
5
|
+
export const collectionSchema = new Declaration([
|
|
6
|
+
`CREATE TABLE embedding_document (
|
|
7
|
+
id TEXT PRIMARY KEY,
|
|
8
|
+
-- sha256 of the model's provider and id and the text (docs/adr/0002).
|
|
9
|
+
hash TEXT NOT NULL,
|
|
10
|
+
-- Milliseconds since the Unix epoch.
|
|
11
|
+
published_at INTEGER NOT NULL,
|
|
12
|
+
-- A unit vector of float32 values, in the byte order of the platform.
|
|
13
|
+
vector BLOB NOT NULL
|
|
14
|
+
) STRICT`,
|
|
15
|
+
`CREATE INDEX embedding_document_published_at ON embedding_document (published_at)`,
|
|
16
|
+
], { rows: 'replace' });
|
|
17
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,4EAA4E;AAC5E,6EAA6E;AAC7E,4DAA4D;AAC5D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,WAAW,CAC7C;IACE;;;;;;;;SAQK;IACL,mFAAmF;CACpF,EACD,EAAE,IAAI,EAAE,SAAS,EAAE,CACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown-document-error.d.ts","sourceRoot":"","sources":["../src/unknown-document-error.ts"],"names":[],"mappings":"AACA,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;gBAER,EAAE,EAAE,MAAM;CAKvB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// The collection stores no document with this id.
|
|
2
|
+
export class UnknownDocumentError extends Error {
|
|
3
|
+
id;
|
|
4
|
+
constructor(id) {
|
|
5
|
+
super(`The collection stores no document with the id ${id}.`);
|
|
6
|
+
this.name = 'UnknownDocumentError';
|
|
7
|
+
this.id = id;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=unknown-document-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown-document-error.js","sourceRoot":"","sources":["../src/unknown-document-error.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,EAAE,CAAS;IAEpB,YAAY,EAAU;QACpB,KAAK,CAAC,iDAAiD,EAAE,GAAG,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;CACF"}
|
package/dist/vector.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class UnitVector {
|
|
2
|
+
#private;
|
|
3
|
+
private constructor();
|
|
4
|
+
static normalize(values: readonly number[]): UnitVector;
|
|
5
|
+
static fromBlob(blob: Uint8Array): UnitVector;
|
|
6
|
+
get dimension(): number;
|
|
7
|
+
toBlob(): Uint8Array;
|
|
8
|
+
cosine(other: UnitVector): number;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=vector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector.d.ts","sourceRoot":"","sources":["../src/vector.ts"],"names":[],"mappings":"AAEA,qBAAa,UAAU;;IAGrB,OAAO;IAKP,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU;IAavD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU;IAI7C,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,MAAM,IAAI,UAAU;IAWpB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM;CAQlC"}
|
package/dist/vector.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// A unit vector of float32 values. A dot product of two unit vectors is their
|
|
2
|
+
// cosine similarity.
|
|
3
|
+
export class UnitVector {
|
|
4
|
+
#values;
|
|
5
|
+
constructor(values) {
|
|
6
|
+
this.#values = values;
|
|
7
|
+
}
|
|
8
|
+
// Divides each value by the length of the vector.
|
|
9
|
+
static normalize(values) {
|
|
10
|
+
const length = Math.sqrt(values.reduce((sum, value) => sum + value * value, 0));
|
|
11
|
+
if (length === 0 || !Number.isFinite(length))
|
|
12
|
+
throw new RangeError(`An embedding must have a finite length that is not zero. Its length is ${length}.`);
|
|
13
|
+
return new UnitVector(Float32Array.from(values, (value) => value / length));
|
|
14
|
+
}
|
|
15
|
+
// The bytes that SQLite gives are copied, because a Float32Array needs an
|
|
16
|
+
// offset that is a multiple of 4.
|
|
17
|
+
static fromBlob(blob) {
|
|
18
|
+
return new UnitVector(new Float32Array(Uint8Array.from(blob).buffer));
|
|
19
|
+
}
|
|
20
|
+
get dimension() {
|
|
21
|
+
return this.#values.length;
|
|
22
|
+
}
|
|
23
|
+
toBlob() {
|
|
24
|
+
return new Uint8Array(this.#values.buffer, this.#values.byteOffset, this.#values.byteLength);
|
|
25
|
+
}
|
|
26
|
+
// An indexed loop: an entries() iterator with destructuring made the
|
|
27
|
+
// nearest search of each document in a window of 1,001 documents about two
|
|
28
|
+
// times slower.
|
|
29
|
+
cosine(other) {
|
|
30
|
+
const values = this.#values;
|
|
31
|
+
const others = other.#values;
|
|
32
|
+
let sum = 0;
|
|
33
|
+
for (let index = 0; index < values.length; index++)
|
|
34
|
+
sum += (values[index] ?? 0) * (others[index] ?? 0);
|
|
35
|
+
return sum;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=vector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector.js","sourceRoot":"","sources":["../src/vector.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,qBAAqB;AACrB,MAAM,OAAO,UAAU;IACZ,OAAO,CAAe;IAE/B,YAAoB,MAAoB;QACtC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,kDAAkD;IAClD,MAAM,CAAC,SAAS,CAAC,MAAyB;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CACtB,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CACtD,CAAC;QACF,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC1C,MAAM,IAAI,UAAU,CAClB,0EAA0E,MAAM,GAAG,CACpF,CAAC;QACJ,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,0EAA0E;IAC1E,kCAAkC;IAClC,MAAM,CAAC,QAAQ,CAAC,IAAgB;QAC9B,OAAO,IAAI,UAAU,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,UAAU,CACnB,IAAI,CAAC,OAAO,CAAC,MAAM,EACnB,IAAI,CAAC,OAAO,CAAC,UAAU,EACvB,IAAI,CAAC,OAAO,CAAC,UAAU,CACxB,CAAC;IACJ,CAAC;IAED,qEAAqE;IACrE,2EAA2E;IAC3E,gBAAgB;IAChB,MAAM,CAAC,KAAiB;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7B,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE;YAChD,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/embeddings",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.47",
|
|
4
|
+
"description": "A collection of document embeddings in SQLite. It embeds only new or changed text through an AI SDK embedding model, and finds the nearest documents of a document by exact cosine similarity inside a publish-date window.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/JanuaryLabs/zukhruf",
|
|
9
|
+
"directory": "packages/embeddings"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/JanuaryLabs/zukhruf/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/JanuaryLabs/zukhruf/tree/main/packages/embeddings#readme",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"embeddings",
|
|
17
|
+
"vector-search",
|
|
18
|
+
"nearest-neighbour",
|
|
19
|
+
"cosine-similarity",
|
|
20
|
+
"sqlite",
|
|
21
|
+
"node-sqlite",
|
|
22
|
+
"ai-sdk"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
".": {
|
|
28
|
+
"@zukhruf/source": "./src/index.ts",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"!dist/spec/**",
|
|
37
|
+
"!**/*.tsbuildinfo",
|
|
38
|
+
"!**/*.test.*"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@zukhruf/sqlite-drift": "^0.3.47",
|
|
45
|
+
"@zukhruf/sqlite-transaction": "^0.3.47",
|
|
46
|
+
"ai": "^7.0.154"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@zukhruf/testing": "^0.3.47"
|
|
50
|
+
}
|
|
51
|
+
}
|