@eltjs/embedding 0.1.0 → 0.1.2

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
@@ -31,6 +31,7 @@ new ComputedDataset({
31
31
  - The output column `vector` holds a unit vector of float32 values in the byte order of the platform. This is the form that `VectorSearch` of `@zukhruf/embeddings` reads, so the cosine similarity of two vectors is their dot product.
32
32
  - The identity of each row is the provider and the id of the model. When you change the model, the next refresh makes every vector again.
33
33
  - The rule sends 64 rows to `embedMany` at a time. When the model refuses a call, each row of that call is stored as `failed` with the error, and the next refresh asks again. The load does not fail.
34
+ - A vector with no usable length, because it is all zeros or holds a value that is not finite, has no unit vector. Its row is stored as `failed` with the error, the other rows of the call stay `computed`, and the next refresh asks again.
34
35
  - To search, declare a view that gives `id` and `vector`, and give its name to `VectorSearch`. A search by publish date, such as `nearest`, also needs `published_at`. A query without a date range does not.
35
36
 
36
37
  ## Give the model its prompts
package/dist/embedding.js CHANGED
@@ -57,9 +57,7 @@ export class Embedding extends Rule {
57
57
  values: [...texts],
58
58
  abortSignal: signal,
59
59
  });
60
- return embeddings.map((embedding) => ({
61
- value: { vector: unitVector(embedding) },
62
- }));
60
+ return embeddings.map(unitVector);
63
61
  }
64
62
  catch (failure) {
65
63
  if (signal?.aborted)
@@ -71,7 +69,16 @@ export class Embedding extends Rule {
71
69
  }
72
70
  }
73
71
  }
72
+ // A vector with no usable length has no unit vector: the division gives NaN,
73
+ // which a search would rank as an answer. The row fails, and the next refresh
74
+ // asks again.
74
75
  function unitVector(embedding) {
75
76
  const length = Math.hypot(...embedding);
76
- return new Uint8Array(Float32Array.from(embedding, (value) => value / length).buffer);
77
+ if (length === 0 || !Number.isFinite(length))
78
+ return { error: `The model answered a vector of length ${length}.` };
79
+ return {
80
+ value: {
81
+ vector: new Uint8Array(Float32Array.from(embedding, (value) => value / length).buffer),
82
+ },
83
+ };
77
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eltjs/embedding",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A rule of an elt computed dataset: it gives each loaded row a vector of its text, made by an AI SDK embedding model, so a search can find rows by meaning.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -40,16 +40,13 @@
40
40
  "node": ">=24"
41
41
  },
42
42
  "dependencies": {
43
- "@eltjs/elt": "^0.1.0"
43
+ "@eltjs/elt": "^0.1.2",
44
+ "ai": "^7.0.165"
44
45
  },
45
46
  "devDependencies": {
46
47
  "@ai-sdk/provider": "^4.0.37",
47
- "@eltjs/elt-sqlite": "^0.1.0",
48
+ "@eltjs/elt-sqlite": "^0.1.2",
48
49
  "@zukhruf/sqlite-open": "^0.8.10",
49
- "@zukhruf/testing": "^0.8.10",
50
- "ai": "^7.0.165"
51
- },
52
- "peerDependencies": {
53
- "ai": "^7.0.148"
50
+ "@zukhruf/testing": "^0.8.10"
54
51
  }
55
52
  }