@infino-ai/infino 0.1.0 → 0.1.1

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
@@ -144,18 +144,22 @@ vecs.vectorSearch("emb", queryVector, 10, {
144
144
 
145
145
  ## Hybrid search
146
146
 
147
- Combine BM25 and vector search in **one query** with the `hybrid_search` table
148
- function — a single pass over both indexes, fused inside the engine (no separate
147
+ Combine BM25 and vector search in **one call** a single pass over both
148
+ indexes, fused inside the engine with reciprocal-rank fusion (no separate
149
149
  reranker service, no two round-trips). Keyword-only search misses paraphrases;
150
150
  vector-only search misses exact terms — hybrid gets both. Results come back
151
- best-first with a fused `score`.
151
+ best-first with a fused `score` (higher is better).
152
152
 
153
153
  ```javascript
154
154
  const spec = new IndexSpec().fts("body").vector("emb", 384, 256, "cosine");
155
155
  const docs = db.createTable("docs", { body: "large_utf8", emb: { vector: 384 } }, spec);
156
156
  docs.append([{ body: "To cancel a subscription, open Settings then Billing.", emb: embed(/* … */) }]);
157
157
 
158
- // hybrid_search(table, text_col, query_text, vec_col, query_vec, k)
158
+ // hybridSearch(textColumn, textQuery, vectorColumn, vectorQuery, k, opts?)
159
+ docs.hybridSearch("body", "cancel subscription", "emb", embed("how do I stop my plan?"), 10);
160
+ // opts: { mode } tunes the BM25 side, { nprobe } the vector side.
161
+
162
+ // The same fusion is also a SQL table function, so it composes in a query:
159
163
  const qvec = embed("how do I stop my plan?").join(",");
160
164
  db.querySql(
161
165
  `SELECT _id, score FROM hybrid_search('docs', 'body', 'cancel subscription', 'emb', '${qvec}', 10)`,
@@ -226,24 +230,51 @@ docs.optimize({ targetSuperfileSizeMb: 256, minFillPercent: 50 });
226
230
 
227
231
  `connect` selects the backend from the URI:
228
232
 
229
- | URI | Backend |
230
- | --------------------- | ---------------------------------------- |
231
- | `./data`, `/abs/path` | Local filesystem |
232
- | `s3://bucket/prefix` | Amazon S3 / S3-compatible object storage |
233
- | `memory://` | In-process, ephemeral (testing) |
233
+ | URI | Backend |
234
+ | ------------------------ | ---------------------------------------- |
235
+ | `./data`, `/abs/path` | Local filesystem |
236
+ | `s3://bucket/prefix` | Amazon S3 / S3-compatible object storage |
237
+ | `az://container/prefix` | Azure Blob Storage |
238
+ | `memory://` | In-process, ephemeral (testing) |
234
239
 
235
- For S3-compatible stores that need an explicit endpoint and static credentials,
236
- pass them in `options` (omit to use ambient AWS credentials):
240
+ Credentials go in `storageOptions`, keyed by the standard `object_store` config
241
+ strings (`aws_*` / `azure_*` the same names the AWS and Azure SDKs use). Omit
242
+ them to use ambient cloud identity (IAM instance role / managed identity);
243
+ infino reads no credentials from the environment.
237
244
 
238
245
  ```javascript
246
+ // S3
239
247
  const db = connect("s3://bucket/prefix", {
240
- endpoint: "https://s3.example.com",
241
- region: "us-east-1",
242
- accessKey: "…",
243
- secretKey: "",
248
+ storageOptions: {
249
+ aws_access_key_id: "",
250
+ aws_secret_access_key: "…",
251
+ aws_region: "us-east-1",
252
+ },
253
+ });
254
+
255
+ // Azure
256
+ const db = connect("az://container/prefix", {
257
+ storageOptions: {
258
+ azure_storage_account_name: "…",
259
+ azure_storage_account_key: "…",
260
+ },
244
261
  });
245
262
  ```
246
263
 
264
+ Common keys:
265
+
266
+ | Backend | Keys |
267
+ | ------- | ---- |
268
+ | S3 | `aws_access_key_id`, `aws_secret_access_key`, `aws_region`, `aws_session_token`, `aws_endpoint` |
269
+ | Azure | `azure_storage_account_name`, `azure_storage_account_key`, `azure_storage_sas_key`, `azure_storage_client_id`, `azure_storage_client_secret`, `azure_storage_tenant_id` |
270
+
271
+ The full set is whatever `object_store` accepts for the backend; an unknown key
272
+ is rejected at `connect`. Pass `validate: true` to probe the backend at
273
+ `connect`, so wrong credentials or an unreachable bucket throw there instead of
274
+ on the first query. For an S3-compatible endpoint (MinIO / R2 / Ceph), set
275
+ `aws_endpoint` (with `aws_allow_http: "true"` for plain HTTP) alongside the
276
+ credentials.
277
+
247
278
  ### Local disk cache
248
279
 
249
280
  For object-storage-backed catalogs, a local disk cache keeps hot data on fast
@@ -273,9 +304,9 @@ const db = connect("s3://bucket/prefix", {
273
304
  ## API reference
274
305
 
275
306
  - `connect(uri, options?)` — backend from the URI scheme. `options`:
276
- S3-compatible credentials (`endpoint`, `region`, `accessKey`, `secretKey` —
277
- `endpoint` requires the other three) and, for remote-backed tables, a local
278
- disk cache (`cacheDir`, `cacheBudgetBytes`, `coldFetchMode`).
307
+ `storageOptions` (credentials, keyed by `object_store`'s `aws_*` / `azure_*`
308
+ strings), `validate`, and a local disk cache (`cacheDir`, `cacheBudgetBytes`,
309
+ `coldFetchMode`).
279
310
  - `Connection`
280
311
  - `createTable(name, schema, IndexSpec)` / `openTable(name)` /
281
312
  `dropTable(name, purge?)` (`purge = true` also deletes the data) /
package/infino/index.d.ts CHANGED
@@ -17,17 +17,23 @@ export type SchemaDescriptor = Record<string, string | {
17
17
  export type AppendData = RowRecord[] | arrow.Table | arrow.RecordBatch | Buffer | Uint8Array;
18
18
  /** Storage and cache config the `connect` URI can't carry. All optional. */
19
19
  export interface ConnectOptions {
20
- /** S3-compatible endpoint; requires `region`, `accessKey`, `secretKey`. */
21
- endpoint?: string;
22
- region?: string;
23
- accessKey?: string;
24
- secretKey?: string;
20
+ /**
21
+ * Credentials/tuning for the URI-selected backend, keyed by `object_store`
22
+ * config strings (`aws_*` / `azure_*`). An unknown key is rejected at
23
+ * `connect`.
24
+ */
25
+ storageOptions?: Record<string, string>;
25
26
  /** Local disk-cache directory for remote-backed tables. */
26
27
  cacheDir?: string;
27
28
  /** Disk-cache budget in bytes. */
28
29
  cacheBudgetBytes?: number;
29
30
  /** How cold misses are serviced. */
30
31
  coldFetchMode?: "hybrid_with_prefetch" | "range_only" | "lazy_foreground_with_background_fill";
32
+ /**
33
+ * Probe the object store at `connect` (default `false`). `true` fails fast
34
+ * on bad credentials instead of on the first table operation.
35
+ */
36
+ validate?: boolean;
31
37
  }
32
38
  /** Row counts returned by `update` / `delete`. */
33
39
  export interface MutationStats {
@@ -74,6 +80,16 @@ export interface VectorSearchOptions {
74
80
  /** Restrict the kNN to rows matching a text predicate (pushdown pre-filter). */
75
81
  filter?: VectorFilter;
76
82
  }
83
+ /** Options for `hybridSearch`. `mode` applies to the BM25 side; `nprobe` to
84
+ * the vector side. */
85
+ export interface HybridSearchOptions {
86
+ /** BM25 boolean mode: `"or"` (default) or `"and"`. */
87
+ mode?: BoolMode;
88
+ /** IVF partitions to probe on the vector side (higher = better recall). */
89
+ nprobe?: number;
90
+ projection?: string[];
91
+ arrow?: boolean;
92
+ }
77
93
  export interface TokenMatchOptions {
78
94
  mode?: BoolMode;
79
95
  projection?: string[];
@@ -107,6 +123,13 @@ export declare class Table {
107
123
  arrow: true;
108
124
  }): arrow.Table;
109
125
  vectorSearch(column: string, query: number[] | Float32Array, k: number, opts?: VectorSearchOptions): RowRecord[];
126
+ /** Hybrid BM25 + vector search, fused with reciprocal-rank fusion; rows as
127
+ * records (or an Arrow `Table`). `score` is the fused RRF score (higher is
128
+ * better). */
129
+ hybridSearch(textColumn: string, textQuery: string, vectorColumn: string, vectorQuery: number[] | Float32Array, k: number, opts: HybridSearchOptions & {
130
+ arrow: true;
131
+ }): arrow.Table;
132
+ hybridSearch(textColumn: string, textQuery: string, vectorColumn: string, vectorQuery: number[] | Float32Array, k: number, opts?: HybridSearchOptions): RowRecord[];
110
133
  /** Unranked token match; matching rows as records (or an Arrow `Table`). */
111
134
  tokenMatch(column: string, query: string, opts: TokenMatchOptions & {
112
135
  arrow: true;
package/infino/index.js CHANGED
@@ -216,6 +216,11 @@ class Table {
216
216
  const buf = this.inner.vectorSearch(column, q, k, opts.nprobe, opts.rerankMult, opts.projection, opts.filter);
217
217
  return decode(buf, opts.arrow);
218
218
  }
219
+ hybridSearch(textColumn, textQuery, vectorColumn, vectorQuery, k, opts = {}) {
220
+ const q = vectorQuery instanceof Float32Array ? vectorQuery : Float32Array.from(vectorQuery);
221
+ const buf = this.inner.hybridSearch(textColumn, textQuery, vectorColumn, q, k, opts.mode, opts.nprobe, opts.projection);
222
+ return decode(buf, opts.arrow);
223
+ }
219
224
  tokenMatch(column, query, opts = {}) {
220
225
  const buf = this.inner.tokenMatch(column, query, opts.mode, opts.projection);
221
226
  return decode(buf, opts.arrow);
@@ -9,11 +9,12 @@
9
9
  * disk cache.
10
10
  */
11
11
  export interface ConnectOptions {
12
- /** S3-compatible endpoint; requires `region`, `accessKey`, `secretKey`. */
13
- endpoint?: string
14
- region?: string
15
- accessKey?: string
16
- secretKey?: string
12
+ /**
13
+ * Credentials/tuning for the URI-selected backend, keyed by
14
+ * `object_store` config strings (`aws_*` / `azure_*`). An unknown key
15
+ * is rejected at `connect`.
16
+ */
17
+ storageOptions?: Record<string, string>
17
18
  /** Local disk-cache directory for remote-backed tables. */
18
19
  cacheDir?: string
19
20
  /** Disk-cache budget in bytes (a JS number; up to 2^53). */
@@ -23,6 +24,11 @@ export interface ConnectOptions {
23
24
  * `"lazy_foreground_with_background_fill"`.
24
25
  */
25
26
  coldFetchMode?: string
27
+ /**
28
+ * Probe the object store at `connect` (default `false`). `true` fails
29
+ * fast on bad credentials instead of on first use.
30
+ */
31
+ validate?: boolean
26
32
  }
27
33
  /** Tuning for `optimize`; all fields optional (omitted ⇒ engine default). */
28
34
  export interface OptimizeOptions {
@@ -57,8 +63,10 @@ export interface VectorFilter {
57
63
  }
58
64
  /**
59
65
  * Open (or create) a catalog rooted at `uri` (local dir, `memory://`, or
60
- * object-store prefix). S3-compatible static credentials are passed via
61
- * `options` (the JS-idiomatic form of the Rust `ConnectOptions`).
66
+ * object-store prefix). Credentials are passed via `options.storageOptions`
67
+ * (the JS-idiomatic form of the Rust `ConnectOptions`). Pass `validate: true`
68
+ * to probe object stores at connect (off by default) so bad credentials fail
69
+ * there rather than on the first table operation.
62
70
  */
63
71
  export declare function connect(uri: string, options?: ConnectOptions | undefined | null): Connection
64
72
  /**
@@ -141,6 +149,14 @@ export declare class Table {
141
149
  * columns (omit for full rows).
142
150
  */
143
151
  exactMatch(column: string, value: string, projection?: Array<string> | undefined | null): Buffer
152
+ /**
153
+ * Hybrid BM25 + vector search fused with reciprocal-rank fusion.
154
+ * `text_column`/`text_query` (under `mode`) drive BM25; `vector_column`/
155
+ * `vector_query` (a `Float32Array`, with optional `nprobe`) drive vector
156
+ * kNN. Returns Arrow rows like [`Table::bm25_search`], with `score` the
157
+ * fused RRF score (higher is better); `projection` selects columns.
158
+ */
159
+ hybridSearch(textColumn: string, textQuery: string, vectorColumn: string, vectorQuery: Float32Array, k: number, mode?: string | undefined | null, nprobe?: number | undefined | null, projection?: Array<string> | undefined | null): Buffer
144
160
  /**
145
161
  * Delete every row matching a SQL `predicate` (e.g. `"status = 'spam'"`),
146
162
  * returning the mutation counts. Requires durable storage — a `memory://`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infino-ai/infino",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Fast search on object storage — SQL, full-text, and vector search.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -82,12 +82,12 @@
82
82
  "apache-arrow": "^17"
83
83
  },
84
84
  "optionalDependencies": {
85
- "infx-darwin-x64": "0.1.0",
86
- "infx-darwin-arm64": "0.1.0",
87
- "infx-linux-x64-gnu": "0.1.0",
88
- "infx-linux-arm64-gnu": "0.1.0",
89
- "infx-linux-x64-musl": "0.1.0",
90
- "infx-linux-arm64-musl": "0.1.0"
85
+ "infx-darwin-x64": "0.1.1",
86
+ "infx-darwin-arm64": "0.1.1",
87
+ "infx-linux-x64-gnu": "0.1.1",
88
+ "infx-linux-arm64-gnu": "0.1.1",
89
+ "infx-linux-x64-musl": "0.1.1",
90
+ "infx-linux-arm64-musl": "0.1.1"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@napi-rs/cli": "^2.18.0",
@@ -99,4 +99,4 @@
99
99
  "infino/native.js",
100
100
  "infino/native.d.ts"
101
101
  ]
102
- }
102
+ }