libsql-search 0.5.0 → 0.7.0

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/docs/PROVIDERS.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # Embedding Providers
2
2
 
3
- `libsql-search` currently supports five embedding providers:
3
+ `libsql-search` currently supports six embedding providers:
4
4
 
5
5
  - `local`
6
6
  - `cloudflare`
7
7
  - `mistral`
8
8
  - `gemini`
9
9
  - `openai`
10
+ - `openai-compatible`
10
11
 
11
12
  Use the same provider and dimensions for both indexing and querying. A mismatch
12
13
  between stored vectors and query vectors will break search quality or fail at
@@ -16,10 +17,19 @@ query time.
16
17
 
17
18
  ```ts
18
19
  interface EmbeddingOptions {
19
- provider?: "local" | "cloudflare" | "mistral" | "gemini" | "openai";
20
+ provider?:
21
+ | "local"
22
+ | "cloudflare"
23
+ | "mistral"
24
+ | "gemini"
25
+ | "openai"
26
+ | "openai-compatible";
20
27
  apiKey?: string;
21
28
  accountId?: string;
22
29
  apiToken?: string;
30
+ baseUrl?: string;
31
+ model?: string;
32
+ batchSize?: number;
23
33
  dimensions?: number;
24
34
  maxLength?: number;
25
35
  intent?: "document" | "query";
@@ -29,16 +39,20 @@ interface EmbeddingOptions {
29
39
  ```
30
40
 
31
41
  - `provider` defaults to `"local"`
32
- - `dimensions` defaults to `768` for the library's default local provider.
33
- Provider-specific defaults can differ; Gemini defaults to `3072`.
42
+ - `dimensions` defaults to `384` for the library's default local provider.
43
+ Provider-specific defaults can differ; Cloudflare and Mistral use `1024`,
44
+ and Gemini defaults to `3072`.
34
45
  - `maxLength` defaults to `8000`
35
46
  - `intent` can be `"document"` or `"query"`; indexing defaults to
36
47
  `"document"` and search defaults to `"query"` unless explicitly set
37
48
  - `timeoutMs` defaults to `30000`
38
49
  - `apiKey` is used by Mistral, Gemini, and OpenAI and falls back to
39
- `MISTRAL_API_KEY`, `GEMINI_API_KEY`, or `OPENAI_API_KEY`
50
+ `MISTRAL_API_KEY`, `GEMINI_API_KEY`, or `OPENAI_API_KEY`. For
51
+ `openai-compatible`, `apiKey` is optional and never falls back to
52
+ `OPENAI_API_KEY`.
40
53
  - `accountId` and `apiToken` are used by Cloudflare and fall back to
41
54
  `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN`
55
+ - `baseUrl`, `model`, and `batchSize` are used by `openai-compatible`
42
56
 
43
57
  ## Provider Contract
44
58
 
@@ -46,7 +60,13 @@ Each provider exposes immutable metadata:
46
60
 
47
61
  ```ts
48
62
  interface EmbeddingProviderMetadata {
49
- name: "local" | "cloudflare" | "mistral" | "gemini" | "openai";
63
+ name:
64
+ | "local"
65
+ | "cloudflare"
66
+ | "mistral"
67
+ | "gemini"
68
+ | "openai"
69
+ | "openai-compatible";
50
70
  model: string;
51
71
  dimensions: number;
52
72
  batch: {
@@ -87,7 +107,8 @@ vectors plus provider, model, dimensions, and intent. The compatibility helpers
87
107
 
88
108
  Cloudflare, Mistral, Gemini, and OpenAI clients are scoped to their current
89
109
  options. They are not cached globally across different credentials or
90
- configurations. The local Xenova model can be cached by model name.
110
+ configurations. The local Hugging Face Transformers pipeline is loaded lazily
111
+ and cached by model name.
91
112
 
92
113
  Hosted provider failures are reported with bounded provider/status/request-id
93
114
  context and without raw upstream bodies, credentials, Authorization headers, or
@@ -98,24 +119,26 @@ full URLs with query strings.
98
119
  Provider value: `local`
99
120
 
100
121
  The local provider loads `Xenova/all-MiniLM-L6-v2` through
101
- `@xenova/transformers`.
122
+ `@huggingface/transformers`.
102
123
 
103
124
  ```ts
104
125
  embeddingOptions: {
105
126
  provider: "local",
106
- dimensions: 768,
107
127
  }
108
128
  ```
109
129
 
110
130
  Notes:
111
131
 
112
- - the model emits 384 dimensions and `libsql-search` pads or truncates to your
113
- requested size
114
- - metadata reports the requested output dimensions
132
+ - the model emits 384 dimensions, and local vectors are validated at exactly
133
+ 384 finite numbers
134
+ - `dimensions: 384` is accepted explicitly; any other local dimension is
135
+ rejected before the runtime is imported or loaded
136
+ - metadata reports 384 dimensions
115
137
  - batch metadata is `{ mode: "sequential" }`
116
- - the first run downloads the model and can take longer on a fresh machine
138
+ - the first run downloads and caches the model and can take longer on a fresh
139
+ machine
117
140
  - no API key is required
118
- - this remains the default provider for backward compatibility and offline use
141
+ - this remains the default provider for offline use
119
142
 
120
143
  ## Cloudflare Workers AI
121
144
 
@@ -225,19 +248,95 @@ Behavior:
225
248
  - batch metadata is `{ mode: "native", maxSize: 2048 }`
226
249
  - use the same dimension count in `createTable()`
227
250
 
251
+ ## OpenAI-Compatible Endpoints
252
+
253
+ Provider value: `openai-compatible`
254
+
255
+ Use this provider for trusted OpenAI-compatible embedding services such as
256
+ Hugging Face Text Embeddings Inference (TEI) or an internal gateway. This is an
257
+ optional escape hatch; `local` remains the default offline provider, and the
258
+ named hosted providers above are still preferred when their fixed adapters fit.
259
+
260
+ ```ts
261
+ embeddingOptions: {
262
+ provider: "openai-compatible",
263
+ baseUrl: "http://localhost:8080/v1",
264
+ model: "BAAI/bge-large-en-v1.5",
265
+ dimensions: 1024,
266
+ batchSize: 32,
267
+ }
268
+ ```
269
+
270
+ If your endpoint requires bearer auth, pass `apiKey` explicitly:
271
+
272
+ ```ts
273
+ embeddingOptions: {
274
+ provider: "openai-compatible",
275
+ baseUrl: "https://embeddings.example.com/v1",
276
+ apiKey: process.env.EMBEDDINGS_API_KEY,
277
+ model: "BAAI/bge-large-en-v1.5",
278
+ dimensions: 1024,
279
+ }
280
+ ```
281
+
282
+ Behavior:
283
+
284
+ - `baseUrl`, `model`, and `dimensions` are required
285
+ - `baseUrl` is the API base, such as `http://localhost:8080/v1`; the library
286
+ sends requests to `/embeddings` below that base
287
+ - a base URL that already ends in `/embeddings` is used as-is
288
+ - only absolute `http` and `https` URLs are accepted
289
+ - URL usernames, passwords, query strings, and fragments are rejected
290
+ - `apiKey` is optional; blank keys are ignored and no `Authorization` header is
291
+ sent
292
+ - `OPENAI_API_KEY` is never read for this provider
293
+ - `batchSize` defaults to `32`, matching TEI's conservative client batch size;
294
+ larger input arrays are split into sequential outbound requests and returned
295
+ in the original input order
296
+ - requests send `{ input, model, dimensions, encoding_format: "float" }`
297
+ - responses must use the standard OpenAI embeddings shape with indexed
298
+ `data[]` items; each response chunk must include unique contiguous indices
299
+ - batch metadata is `{ mode: "native" }`; the internal outbound chunk size is
300
+ not reported as `batch.maxSize`
301
+
302
+ Security boundary:
303
+
304
+ - treat `baseUrl` as trusted server-side configuration only
305
+ - never pass user-supplied request values directly into `baseUrl`
306
+ - use HTTPS for remote endpoints
307
+ - credentials are not sent across redirects
308
+ - non-2xx response bodies are not read, and errors avoid echoing API keys or
309
+ configured endpoint URLs
310
+
311
+ TEI exposes an OpenAI-compatible base at `/v1`, so a local TEI server usually
312
+ uses:
313
+
314
+ ```ts
315
+ embeddingOptions: {
316
+ provider: "openai-compatible",
317
+ baseUrl: "http://localhost:8080/v1",
318
+ model: "BAAI/bge-large-en-v1.5",
319
+ dimensions: 1024,
320
+ }
321
+ ```
322
+
323
+ This library does not call TEI's native `/embed` endpoint.
324
+
228
325
  ## Dimension Guidelines
229
326
 
230
- - `local` defaults to `768`
327
+ - `local` is fixed at `384`
231
328
  - `cloudflare` is fixed at `1024`
232
329
  - `mistral` is fixed at `1024`
233
- - local embeddings are padded from 384 to your target size
234
330
  - Gemini defaults to `3072` and accepts explicit dimensions from `128` through
235
331
  `3072`; use `768`, `1536`, or `3072` unless you have a specific reason
236
332
  - OpenAI can be used at 1536 or 3072, or another supported OpenAI dimension
237
333
  value you explicitly set
334
+ - `openai-compatible` requires you to set the dimension count that your
335
+ endpoint/model actually returns
238
336
 
239
- If you switch provider or dimensions for an existing table, recreate the table
240
- or rebuild the index into a separate table so stored vectors stay consistent.
337
+ If you switch provider, endpoint, model, or dimensions for an existing table,
338
+ recreate the table or rebuild the index into a separate table so stored vectors
339
+ stay consistent.
241
340
 
242
341
  Existing Gemini indexes created with `text-embedding-004` must be fully
243
342
  re-embedded for `gemini-embedding-2`, even if you keep `dimensions: 768`,
@@ -245,3 +344,14 @@ because both the model and query/document input formatting changed. If you move
245
344
  to the new 3072-dimensional default, create a new table or recreate the vector
246
345
  table first; `indexContent()` clears rows but does not change the `F32_BLOB`
247
346
  width. A separate table is safer because rebuilds are not transactional.
347
+
348
+ Existing local indexes created with the older padded-local behavior usually have
349
+ `F32_BLOB(768)` rows containing the 384 model values followed by zero padding.
350
+ The current local contract stores the native 384-dimensional model output. To
351
+ migrate, create or recreate a `F32_BLOB(384)` table and run a full re-index
352
+ before querying it. Using the same model ID avoids an intentional model-space
353
+ change, but bit-identical vectors are not promised across runtime, model
354
+ revision, dtype, pooling, or normalization changes; validate search quality and
355
+ re-index when those details change.
356
+
357
+ Routine unit tests mock the local runtime and do not download the model.
package/docs/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  This directory holds the longer-form reference material for `libsql-search`.
4
4
  Start with the page that matches the job you are doing:
5
5
 
6
- - [Provider guide](./PROVIDERS.md): local, Cloudflare, Mistral, Gemini, and
7
- OpenAI embedding options, dimensions, and API key behavior
6
+ - [Provider guide](./PROVIDERS.md): local, hosted, and OpenAI-compatible
7
+ embedding options, dimensions, and API key behavior
8
8
  - [API reference](./API.md): exported functions, option shapes, and result data
9
9
  - [Integration examples](./INTEGRATIONS.md): Astro and Next.js server-side usage
10
10
  - [Indexing and operations](./INDEXING.md): content layout, rebuild scripts,
@@ -1,11 +1,12 @@
1
1
  # Troubleshooting: Transitive `sharp` Install Errors
2
2
 
3
- `libsql-search` does not directly depend on `sharp`. If you see an install error
4
- mentioning `sharp`, it is coming from another dependency in your application or
5
- toolchain.
3
+ `libsql-search` does not directly import `sharp`, but local embeddings use
4
+ `@huggingface/transformers`, which currently brings in `sharp` as a transitive
5
+ runtime dependency. If you see an install error mentioning `sharp`, it is
6
+ usually a native-package install or approval issue.
6
7
 
7
- This page exists because the error can show up in environments that also use
8
- `libsql-search`, and it is easy to misattribute the failure to this package.
8
+ This page exists because the error can show up before your application reaches
9
+ any `libsql-search` code.
9
10
 
10
11
  ## Typical Error
11
12
 
@@ -48,7 +49,7 @@ in `pnpm-workspace.yaml` with `onlyBuiltDependencies`.
48
49
 
49
50
  ## Relation To `libsql-search`
50
51
 
51
- - local embeddings use `@xenova/transformers`
52
+ - local embeddings use `@huggingface/transformers`
52
53
  - the first local embedding run may download a model at runtime
53
54
  - that runtime model download is separate from a pnpm native-module install
54
55
  failure
@@ -15,3 +15,5 @@ Common operational checks:
15
15
  - after upgrading an existing Gemini index, fully re-embed with
16
16
  `gemini-embedding-2`; for 3072-dimensional Gemini indexes, recreate the table
17
17
  or use a new table name before rebuilding
18
+ - after upgrading an existing local 768-dimensional padded index, create or
19
+ recreate a 384-dimensional table and fully re-index before querying it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libsql-search",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Semantic search for static sites using libSQL/Turso with multi-provider embeddings",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.34.5",
@@ -63,7 +63,7 @@
63
63
  "@libsql/client": "^0.15.0"
64
64
  },
65
65
  "dependencies": {
66
- "@xenova/transformers": "^2.17.2",
66
+ "@huggingface/transformers": "4.2.0",
67
67
  "gray-matter": "^4.0.3"
68
68
  },
69
69
  "devDependencies": {