@upstash/vector 1.1.7 → 1.2.0-canary-hybrid

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.
@@ -58,7 +58,9 @@ var HttpClient = class {
58
58
  break;
59
59
  }
60
60
  error = error_;
61
- await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
61
+ if (i < this.retry.attempts) {
62
+ await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
63
+ }
62
64
  }
63
65
  }
64
66
  if (!res) {
@@ -72,6 +74,23 @@ var HttpClient = class {
72
74
  }
73
75
  };
74
76
 
77
+ // src/commands/client/query/types.ts
78
+ var WeightingStrategy = /* @__PURE__ */ ((WeightingStrategy2) => {
79
+ WeightingStrategy2["IDF"] = "IDF";
80
+ return WeightingStrategy2;
81
+ })(WeightingStrategy || {});
82
+ var FusionAlgorithm = /* @__PURE__ */ ((FusionAlgorithm2) => {
83
+ FusionAlgorithm2["RRF"] = "RRF";
84
+ FusionAlgorithm2["DBSF"] = "DBSF";
85
+ return FusionAlgorithm2;
86
+ })(FusionAlgorithm || {});
87
+ var QueryMode = /* @__PURE__ */ ((QueryMode2) => {
88
+ QueryMode2["HYBRID"] = "HYBRID";
89
+ QueryMode2["DENSE"] = "DENSE";
90
+ QueryMode2["SPARSE"] = "SPARSE";
91
+ return QueryMode2;
92
+ })(QueryMode || {});
93
+
75
94
  // src/commands/command.ts
76
95
  var Command = class {
77
96
  payload;
@@ -98,23 +117,6 @@ var Command = class {
98
117
  }
99
118
  };
100
119
 
101
- // src/commands/client/delete/index.ts
102
- var DeleteCommand = class extends Command {
103
- constructor(id, options) {
104
- let endpoint = "delete";
105
- if (options?.namespace) {
106
- endpoint = `${endpoint}/${options.namespace}`;
107
- }
108
- const finalArr = [];
109
- if (Array.isArray(id)) {
110
- finalArr.push(...id);
111
- } else {
112
- finalArr.push(id);
113
- }
114
- super(finalArr, endpoint);
115
- }
116
- };
117
-
118
120
  // src/commands/client/query/query-many/index.ts
119
121
  var QueryManyCommand = class extends Command {
120
122
  constructor(payload, options) {
@@ -134,6 +136,8 @@ var QueryCommand = class extends Command {
134
136
  let endpoint = "query";
135
137
  if ("data" in payload) {
136
138
  endpoint = "query-data";
139
+ } else if (!payload.vector && !payload.sparseVector) {
140
+ throw new UpstashError("Either data, vector or sparseVector should be provided.");
137
141
  }
138
142
  if (options?.namespace) {
139
143
  endpoint = `${endpoint}/${options.namespace}`;
@@ -142,6 +146,23 @@ var QueryCommand = class extends Command {
142
146
  }
143
147
  };
144
148
 
149
+ // src/commands/client/delete/index.ts
150
+ var DeleteCommand = class extends Command {
151
+ constructor(id, options) {
152
+ let endpoint = "delete";
153
+ if (options?.namespace) {
154
+ endpoint = `${endpoint}/${options.namespace}`;
155
+ }
156
+ const finalArr = [];
157
+ if (Array.isArray(id)) {
158
+ finalArr.push(...id);
159
+ } else {
160
+ finalArr.push(id);
161
+ }
162
+ super(finalArr, endpoint);
163
+ }
164
+ };
165
+
145
166
  // src/commands/client/upsert/index.ts
146
167
  var UpsertCommand = class extends Command {
147
168
  constructor(payload, opts) {
@@ -159,7 +180,7 @@ var UpsertCommand = class extends Command {
159
180
  }
160
181
  };
161
182
  var isVectorPayload = (payload) => {
162
- return "vector" in payload;
183
+ return "vector" in payload || "sparseVector" in payload;
163
184
  };
164
185
 
165
186
  // src/commands/client/fetch/index.ts
@@ -380,6 +401,11 @@ var Namespace = class {
380
401
  var UpdateCommand = class extends Command {
381
402
  constructor(payload, opts) {
382
403
  let endpoint = "update";
404
+ if (!("metadata" in payload) && !("vector" in payload) && !("sparseVector" in payload) && !("data" in payload)) {
405
+ throw new UpstashError(
406
+ `Error while updating vector with id ${payload.id}.At least one of 'metadata', 'vector', 'sparseVector' or 'data' should be provided.`
407
+ );
408
+ }
383
409
  if (opts?.namespace) {
384
410
  endpoint = `${endpoint}/${opts.namespace}`;
385
411
  }
@@ -757,5 +783,8 @@ var Index = class {
757
783
 
758
784
  export {
759
785
  HttpClient,
786
+ WeightingStrategy,
787
+ FusionAlgorithm,
788
+ QueryMode,
760
789
  Index
761
790
  };
@@ -1,5 +1,5 @@
1
- import { R as RequesterConfig, D as Dict, I as Index$1 } from './vector-gR6tGrYi.mjs';
2
- export { F as FetchResult, d as InfoResult, Q as QueryResult, c as RangeResult, a as Requester, U as UpstashRequest, b as UpstashResponse, V as Vector } from './vector-gR6tGrYi.mjs';
1
+ import { R as RequesterConfig, D as Dict, I as Index$1 } from './vector-uKwku_iy.mjs';
2
+ export { d as FetchResult, F as FusionAlgorithm, f as InfoResult, Q as QueryMode, e as QueryResult, c as RangeResult, a as Requester, U as UpstashRequest, b as UpstashResponse, V as Vector, W as WeightingStrategy } from './vector-uKwku_iy.mjs';
3
3
 
4
4
  /**
5
5
  * Connection credentials for upstash vector.
@@ -1,5 +1,5 @@
1
- import { R as RequesterConfig, D as Dict, I as Index$1 } from './vector-gR6tGrYi.js';
2
- export { F as FetchResult, d as InfoResult, Q as QueryResult, c as RangeResult, a as Requester, U as UpstashRequest, b as UpstashResponse, V as Vector } from './vector-gR6tGrYi.js';
1
+ import { R as RequesterConfig, D as Dict, I as Index$1 } from './vector-uKwku_iy.js';
2
+ export { d as FetchResult, F as FusionAlgorithm, f as InfoResult, Q as QueryMode, e as QueryResult, c as RangeResult, a as Requester, U as UpstashRequest, b as UpstashResponse, V as Vector, W as WeightingStrategy } from './vector-uKwku_iy.js';
3
3
 
4
4
  /**
5
5
  * Connection credentials for upstash vector.
@@ -20,7 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/platforms/cloudflare.ts
21
21
  var cloudflare_exports = {};
22
22
  __export(cloudflare_exports, {
23
- Index: () => Index2
23
+ FusionAlgorithm: () => FusionAlgorithm,
24
+ Index: () => Index2,
25
+ QueryMode: () => QueryMode,
26
+ WeightingStrategy: () => WeightingStrategy
24
27
  });
25
28
  module.exports = __toCommonJS(cloudflare_exports);
26
29
 
@@ -84,7 +87,9 @@ var HttpClient = class {
84
87
  break;
85
88
  }
86
89
  error = error_;
87
- await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
90
+ if (i < this.retry.attempts) {
91
+ await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
92
+ }
88
93
  }
89
94
  }
90
95
  if (!res) {
@@ -160,6 +165,8 @@ var QueryCommand = class extends Command {
160
165
  let endpoint = "query";
161
166
  if ("data" in payload) {
162
167
  endpoint = "query-data";
168
+ } else if (!payload.vector && !payload.sparseVector) {
169
+ throw new UpstashError("Either data, vector or sparseVector should be provided.");
163
170
  }
164
171
  if (options?.namespace) {
165
172
  endpoint = `${endpoint}/${options.namespace}`;
@@ -168,6 +175,23 @@ var QueryCommand = class extends Command {
168
175
  }
169
176
  };
170
177
 
178
+ // src/commands/client/query/types.ts
179
+ var WeightingStrategy = /* @__PURE__ */ ((WeightingStrategy2) => {
180
+ WeightingStrategy2["IDF"] = "IDF";
181
+ return WeightingStrategy2;
182
+ })(WeightingStrategy || {});
183
+ var FusionAlgorithm = /* @__PURE__ */ ((FusionAlgorithm2) => {
184
+ FusionAlgorithm2["RRF"] = "RRF";
185
+ FusionAlgorithm2["DBSF"] = "DBSF";
186
+ return FusionAlgorithm2;
187
+ })(FusionAlgorithm || {});
188
+ var QueryMode = /* @__PURE__ */ ((QueryMode2) => {
189
+ QueryMode2["HYBRID"] = "HYBRID";
190
+ QueryMode2["DENSE"] = "DENSE";
191
+ QueryMode2["SPARSE"] = "SPARSE";
192
+ return QueryMode2;
193
+ })(QueryMode || {});
194
+
171
195
  // src/commands/client/upsert/index.ts
172
196
  var UpsertCommand = class extends Command {
173
197
  constructor(payload, opts) {
@@ -185,7 +209,7 @@ var UpsertCommand = class extends Command {
185
209
  }
186
210
  };
187
211
  var isVectorPayload = (payload) => {
188
- return "vector" in payload;
212
+ return "vector" in payload || "sparseVector" in payload;
189
213
  };
190
214
 
191
215
  // src/commands/client/fetch/index.ts
@@ -406,6 +430,11 @@ var Namespace = class {
406
430
  var UpdateCommand = class extends Command {
407
431
  constructor(payload, opts) {
408
432
  let endpoint = "update";
433
+ if (!("metadata" in payload) && !("vector" in payload) && !("sparseVector" in payload) && !("data" in payload)) {
434
+ throw new UpstashError(
435
+ `Error while updating vector with id ${payload.id}.At least one of 'metadata', 'vector', 'sparseVector' or 'data' should be provided.`
436
+ );
437
+ }
409
438
  if (opts?.namespace) {
410
439
  endpoint = `${endpoint}/${opts.namespace}`;
411
440
  }
@@ -856,5 +885,8 @@ var Index2 = class _Index extends Index {
856
885
  };
857
886
  // Annotate the CommonJS export names for ESM import in node:
858
887
  0 && (module.exports = {
859
- Index
888
+ FusionAlgorithm,
889
+ Index,
890
+ QueryMode,
891
+ WeightingStrategy
860
892
  });
@@ -1,7 +1,10 @@
1
1
  import {
2
+ FusionAlgorithm,
2
3
  HttpClient,
3
- Index
4
- } from "./chunk-XN6MKCVR.mjs";
4
+ Index,
5
+ QueryMode,
6
+ WeightingStrategy
7
+ } from "./chunk-6XOYYLIG.mjs";
5
8
 
6
9
  // src/platforms/cloudflare.ts
7
10
  var Index2 = class _Index extends Index {
@@ -77,5 +80,8 @@ var Index2 = class _Index extends Index {
77
80
  }
78
81
  };
79
82
  export {
80
- Index2 as Index
83
+ FusionAlgorithm,
84
+ Index2 as Index,
85
+ QueryMode,
86
+ WeightingStrategy
81
87
  };
package/dist/nodejs.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RequesterConfig, D as Dict, I as Index$1, a as Requester } from './vector-gR6tGrYi.mjs';
2
- export { F as FetchResult, d as InfoResult, Q as QueryResult, c as RangeResult, U as UpstashRequest, b as UpstashResponse, V as Vector } from './vector-gR6tGrYi.mjs';
1
+ import { R as RequesterConfig, D as Dict, I as Index$1, a as Requester } from './vector-uKwku_iy.mjs';
2
+ export { d as FetchResult, F as FusionAlgorithm, f as InfoResult, Q as QueryMode, e as QueryResult, c as RangeResult, U as UpstashRequest, b as UpstashResponse, V as Vector, W as WeightingStrategy } from './vector-uKwku_iy.mjs';
3
3
 
4
4
  /**
5
5
  * Connection credentials for upstash vector.
package/dist/nodejs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RequesterConfig, D as Dict, I as Index$1, a as Requester } from './vector-gR6tGrYi.js';
2
- export { F as FetchResult, d as InfoResult, Q as QueryResult, c as RangeResult, U as UpstashRequest, b as UpstashResponse, V as Vector } from './vector-gR6tGrYi.js';
1
+ import { R as RequesterConfig, D as Dict, I as Index$1, a as Requester } from './vector-uKwku_iy.js';
2
+ export { d as FetchResult, F as FusionAlgorithm, f as InfoResult, Q as QueryMode, e as QueryResult, c as RangeResult, U as UpstashRequest, b as UpstashResponse, V as Vector, W as WeightingStrategy } from './vector-uKwku_iy.js';
3
3
 
4
4
  /**
5
5
  * Connection credentials for upstash vector.
package/dist/nodejs.js CHANGED
@@ -20,7 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/platforms/nodejs.ts
21
21
  var nodejs_exports = {};
22
22
  __export(nodejs_exports, {
23
- Index: () => Index2
23
+ FusionAlgorithm: () => FusionAlgorithm,
24
+ Index: () => Index2,
25
+ QueryMode: () => QueryMode,
26
+ WeightingStrategy: () => WeightingStrategy
24
27
  });
25
28
  module.exports = __toCommonJS(nodejs_exports);
26
29
 
@@ -84,7 +87,9 @@ var HttpClient = class {
84
87
  break;
85
88
  }
86
89
  error = error_;
87
- await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
90
+ if (i < this.retry.attempts) {
91
+ await new Promise((r) => setTimeout(r, this.retry.backoff(i)));
92
+ }
88
93
  }
89
94
  }
90
95
  if (!res) {
@@ -160,6 +165,8 @@ var QueryCommand = class extends Command {
160
165
  let endpoint = "query";
161
166
  if ("data" in payload) {
162
167
  endpoint = "query-data";
168
+ } else if (!payload.vector && !payload.sparseVector) {
169
+ throw new UpstashError("Either data, vector or sparseVector should be provided.");
163
170
  }
164
171
  if (options?.namespace) {
165
172
  endpoint = `${endpoint}/${options.namespace}`;
@@ -168,6 +175,23 @@ var QueryCommand = class extends Command {
168
175
  }
169
176
  };
170
177
 
178
+ // src/commands/client/query/types.ts
179
+ var WeightingStrategy = /* @__PURE__ */ ((WeightingStrategy2) => {
180
+ WeightingStrategy2["IDF"] = "IDF";
181
+ return WeightingStrategy2;
182
+ })(WeightingStrategy || {});
183
+ var FusionAlgorithm = /* @__PURE__ */ ((FusionAlgorithm2) => {
184
+ FusionAlgorithm2["RRF"] = "RRF";
185
+ FusionAlgorithm2["DBSF"] = "DBSF";
186
+ return FusionAlgorithm2;
187
+ })(FusionAlgorithm || {});
188
+ var QueryMode = /* @__PURE__ */ ((QueryMode2) => {
189
+ QueryMode2["HYBRID"] = "HYBRID";
190
+ QueryMode2["DENSE"] = "DENSE";
191
+ QueryMode2["SPARSE"] = "SPARSE";
192
+ return QueryMode2;
193
+ })(QueryMode || {});
194
+
171
195
  // src/commands/client/upsert/index.ts
172
196
  var UpsertCommand = class extends Command {
173
197
  constructor(payload, opts) {
@@ -185,7 +209,7 @@ var UpsertCommand = class extends Command {
185
209
  }
186
210
  };
187
211
  var isVectorPayload = (payload) => {
188
- return "vector" in payload;
212
+ return "vector" in payload || "sparseVector" in payload;
189
213
  };
190
214
 
191
215
  // src/commands/client/fetch/index.ts
@@ -406,6 +430,11 @@ var Namespace = class {
406
430
  var UpdateCommand = class extends Command {
407
431
  constructor(payload, opts) {
408
432
  let endpoint = "update";
433
+ if (!("metadata" in payload) && !("vector" in payload) && !("sparseVector" in payload) && !("data" in payload)) {
434
+ throw new UpstashError(
435
+ `Error while updating vector with id ${payload.id}.At least one of 'metadata', 'vector', 'sparseVector' or 'data' should be provided.`
436
+ );
437
+ }
409
438
  if (opts?.namespace) {
410
439
  endpoint = `${endpoint}/${opts.namespace}`;
411
440
  }
@@ -835,5 +864,8 @@ var Index2 = class _Index extends Index {
835
864
  };
836
865
  // Annotate the CommonJS export names for ESM import in node:
837
866
  0 && (module.exports = {
838
- Index
867
+ FusionAlgorithm,
868
+ Index,
869
+ QueryMode,
870
+ WeightingStrategy
839
871
  });
package/dist/nodejs.mjs CHANGED
@@ -1,7 +1,10 @@
1
1
  import {
2
+ FusionAlgorithm,
2
3
  HttpClient,
3
- Index
4
- } from "./chunk-XN6MKCVR.mjs";
4
+ Index,
5
+ QueryMode,
6
+ WeightingStrategy
7
+ } from "./chunk-6XOYYLIG.mjs";
5
8
 
6
9
  // src/platforms/nodejs.ts
7
10
  var Index2 = class _Index extends Index {
@@ -56,5 +59,8 @@ var Index2 = class _Index extends Index {
56
59
  }
57
60
  };
58
61
  export {
59
- Index2 as Index
62
+ FusionAlgorithm,
63
+ Index2 as Index,
64
+ QueryMode,
65
+ WeightingStrategy
60
66
  };
@@ -45,11 +45,13 @@ type RequesterConfig = {
45
45
  type Vector<TMetadata = Dict> = {
46
46
  id: string;
47
47
  vector?: number[];
48
+ sparseVector?: SparseVector;
48
49
  metadata?: TMetadata;
49
50
  data?: string;
50
51
  };
51
52
  type NAMESPACE = string;
52
53
  type Dict = Record<string, unknown>;
54
+ type SparseVector = [indices: number[], values: number[]];
53
55
 
54
56
  declare const _ENDPOINTS: readonly ["upsert", "update", "query", "delete", "fetch", "reset", "range", "info", "resumable-query", "resumable-query-data", "resumable-query-next", "resumable-query-end", "upsert-data", "query-data", "list-namespaces", "delete-namespace"];
55
57
  type EndpointVariants = (typeof _ENDPOINTS)[number] | `${(typeof _ENDPOINTS)[number]}/${NAMESPACE}` | `reset?all`;
@@ -80,23 +82,138 @@ type QueryCommandPayload = {
80
82
  includeVectors?: boolean;
81
83
  includeMetadata?: boolean;
82
84
  includeData?: boolean;
85
+ weightingStrategy?: WeightingStrategy;
86
+ fusionAlgorithm?: FusionAlgorithm;
87
+ queryMode?: QueryMode;
83
88
  } & ({
84
- vector: number[];
89
+ vector?: number[];
90
+ sparseVector?: SparseVector;
85
91
  data?: never;
86
92
  } | {
87
93
  data: string;
88
94
  vector?: never;
95
+ sparseVector?: never;
89
96
  });
90
97
  type QueryResult<TMetadata = Dict> = {
91
98
  id: number | string;
92
99
  score: number;
93
100
  vector?: number[];
101
+ sparseVector?: SparseVector;
94
102
  metadata?: TMetadata;
95
103
  data?: string;
96
104
  };
97
105
  type QueryCommandOptions = {
98
106
  namespace?: string;
99
107
  };
108
+ /**
109
+ * For sparse vectors, what kind of weighting strategy
110
+ * should be used while querying the matching non-zero
111
+ * dimension values of the query vector with the documents.
112
+ *
113
+ * If not provided, no weighting will be used.
114
+ */
115
+ declare enum WeightingStrategy {
116
+ /**
117
+ * Inverse document frequency.
118
+ *
119
+ * It is recommended to use this weighting strategy for
120
+ * BM25 sparse embedding models.
121
+ *
122
+ * It is calculated as
123
+ *
124
+ * ln(((N - n(q) + 0.5) / (n(q) + 0.5)) + 1) where
125
+ * N: Total number of sparse vectors.
126
+ * n(q): Total number of sparse vectors having non-zero value
127
+ * for that particular dimension.
128
+ * ln: Natural logarithm
129
+ *
130
+ * The values of N and n(q) are maintained by Upstash as the
131
+ * vectors are indexed.
132
+ */
133
+ IDF = "IDF"
134
+ }
135
+ /**
136
+ * Fusion algorithm to use while fusing scores
137
+ * from dense and sparse components of a hybrid index.
138
+ *
139
+ * If not provided, defaults to `RRF`.
140
+ */
141
+ declare enum FusionAlgorithm {
142
+ /**
143
+ * Reciprocal rank fusion.
144
+ *
145
+ * Each sorted score from the dense and sparse indexes are
146
+ * mapped to 1 / (rank + K), where rank is the order of the
147
+ * score in the dense or sparse scores and K is a constant
148
+ * with the value of 60.
149
+ *
150
+ * Then, scores from the dense and sparse components are
151
+ * deduplicated (i.e. if a score for the same vector is present
152
+ * in both dense and sparse scores, the mapped scores are
153
+ * added; otherwise individual mapped scores are used)
154
+ * and the final result is returned as the topK values
155
+ * of this final list.
156
+ *
157
+ * In short, this algorithm just takes the order of the scores
158
+ * into consideration.
159
+ */
160
+ RRF = "RRF",
161
+ /**
162
+ * Distribution based score fusion.
163
+ *
164
+ * Each sorted score from the dense and sparse indexes are
165
+ * normalized as
166
+ * (s - (mean - 3 * stddev)) / ((mean + 3 * stddev) - (mean - 3 * stddev))
167
+ * where s is the score, (mean - 3 * stddev) is the minimum,
168
+ * and (mean + 3 * stddev) is the maximum tail ends of the distribution.
169
+ *
170
+ * Then, scores from the dense and sparse components are
171
+ * deduplicated (i.e. if a score for the same vector is present
172
+ * in both dense and sparse scores, the normalized scores are
173
+ * added; otherwise individual normalized scores are used)
174
+ * and the final result is returned as the topK values
175
+ * of this final list.
176
+ *
177
+ * In short, this algorithm takes distribution of the scores
178
+ * into consideration as well, as opposed to the `RRF`.
179
+ */
180
+ DBSF = "DBSF"
181
+ }
182
+ /**
183
+ * Query mode for hybrid indexes with Upstash-hosted
184
+ * embedding models.
185
+ *
186
+ * Specifies whether to run the query in only the
187
+ * dense index, only the sparse index, or in both.
188
+ *
189
+ * If not provided, defaults to `HYBRID`.
190
+ */
191
+ declare enum QueryMode {
192
+ /**
193
+ * Runs the query in hybrid index mode, after embedding
194
+ * the raw text data into dense and sparse vectors.
195
+ *
196
+ * Query results from the dense and sparse index components
197
+ * of the hybrid index are fused before returning the result.
198
+ */
199
+ HYBRID = "HYBRID",
200
+ /**
201
+ * Runs the query in dense index mode, after embedding
202
+ * the raw text data into a dense vector.
203
+ *
204
+ * Only the query results from the dense index component
205
+ * of the hybrid index is returned.
206
+ */
207
+ DENSE = "DENSE",
208
+ /**
209
+ * Runs the query in sparse index mode, after embedding
210
+ * the raw text data into a sparse vector.
211
+ *
212
+ * Only the query results from the sparse index component
213
+ * of the hybrid index is returned.
214
+ */
215
+ SPARSE = "SPARSE"
216
+ }
100
217
 
101
218
  declare class QueryManyCommand<TMetadata> extends Command<QueryResult<TMetadata>[][]> {
102
219
  constructor(payload: QueryCommandPayload[], options?: QueryCommandOptions);
@@ -189,7 +306,8 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
189
306
  */
190
307
  upsert: <TMetadata extends Dict = TIndexMetadata>(args: {
191
308
  id: string | number;
192
- vector: number[];
309
+ vector?: number[] | undefined;
310
+ sparseVector?: SparseVector | undefined;
193
311
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
194
312
  } | {
195
313
  id: string | number;
@@ -197,7 +315,8 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
197
315
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
198
316
  } | {
199
317
  id: string | number;
200
- vector: number[];
318
+ vector?: number[] | undefined;
319
+ sparseVector?: SparseVector | undefined;
201
320
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
202
321
  }[] | {
203
322
  id: string | number;
@@ -206,7 +325,8 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
206
325
  }[]) => Promise<string>;
207
326
  update: <TMetadata extends Dict = TIndexMetadata>(args: {
208
327
  id: string | number;
209
- vector: number[];
328
+ vector?: number[] | undefined;
329
+ sparseVector?: SparseVector | undefined;
210
330
  } | {
211
331
  id: string | number;
212
332
  data: string;
@@ -215,7 +335,28 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
215
335
  metadata: TMetadata extends infer U ? U : never;
216
336
  metadataUpdateMode?: "PATCH" | "OVERWRITE" | undefined;
217
337
  }) => Promise<{
218
- updated: number;
338
+ updated: number; /**
339
+ * Upserts (Updates and Inserts) specific items into the index namespace.
340
+ * It's used for adding new items to the index namespace or updating existing ones.
341
+ *
342
+ * @example
343
+ * ```js
344
+ * const upsertArgs = {
345
+ * id: '123',
346
+ * vector: [0.42, 0.87, ...],
347
+ * metadata: { property1: 'value1', property2: 'value2' }
348
+ * };
349
+ * const upsertResult = await index.namespace("ns").upsert(upsertArgs);
350
+ * console.log(upsertResult); // Outputs the result of the upsert operation
351
+ * ```
352
+ *
353
+ * @param {CommandArgs<typeof UpsertCommand>} args - The arguments for the upsert command.
354
+ * @param {number|string} args.id - The unique identifier for the item being upserted.
355
+ * @param {number[]} args.vector - The feature vector associated with the item.
356
+ * @param {Dict} [args.metadata] - Optional metadata to be associated with the item.
357
+ *
358
+ * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed.
359
+ */
219
360
  }>;
220
361
  /**
221
362
  * It's used for retrieving specific items from the index namespace, optionally including
@@ -482,7 +623,8 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
482
623
  */
483
624
  upsert: <TMetadata extends Dict = TIndexMetadata>(args: {
484
625
  id: string | number;
485
- vector: number[];
626
+ vector?: number[] | undefined;
627
+ sparseVector?: SparseVector | undefined;
486
628
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
487
629
  } | {
488
630
  id: string | number;
@@ -490,7 +632,8 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
490
632
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
491
633
  } | {
492
634
  id: string | number;
493
- vector: number[];
635
+ vector?: number[] | undefined;
636
+ sparseVector?: SparseVector | undefined;
494
637
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
495
638
  }[] | {
496
639
  id: string | number;
@@ -501,7 +644,8 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
501
644
  }) => Promise<string>;
502
645
  update: <TMetadata extends Dict = TIndexMetadata>(args: {
503
646
  id: string | number;
504
- vector: number[];
647
+ vector?: number[] | undefined;
648
+ sparseVector?: SparseVector | undefined;
505
649
  } | {
506
650
  id: string | number;
507
651
  data: string;
@@ -642,4 +786,4 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
642
786
  deleteNamespace: (namespace: string) => Promise<string>;
643
787
  }
644
788
 
645
- export { type Dict as D, type FetchResult as F, Index as I, type QueryResult as Q, type RequesterConfig as R, type UpstashRequest as U, type Vector as V, type Requester as a, type UpstashResponse as b, type RangeResult as c, type InfoResult as d };
789
+ export { type Dict as D, FusionAlgorithm as F, Index as I, QueryMode as Q, type RequesterConfig as R, type UpstashRequest as U, type Vector as V, WeightingStrategy as W, type Requester as a, type UpstashResponse as b, type RangeResult as c, type FetchResult as d, type QueryResult as e, type InfoResult as f };
@@ -45,11 +45,13 @@ type RequesterConfig = {
45
45
  type Vector<TMetadata = Dict> = {
46
46
  id: string;
47
47
  vector?: number[];
48
+ sparseVector?: SparseVector;
48
49
  metadata?: TMetadata;
49
50
  data?: string;
50
51
  };
51
52
  type NAMESPACE = string;
52
53
  type Dict = Record<string, unknown>;
54
+ type SparseVector = [indices: number[], values: number[]];
53
55
 
54
56
  declare const _ENDPOINTS: readonly ["upsert", "update", "query", "delete", "fetch", "reset", "range", "info", "resumable-query", "resumable-query-data", "resumable-query-next", "resumable-query-end", "upsert-data", "query-data", "list-namespaces", "delete-namespace"];
55
57
  type EndpointVariants = (typeof _ENDPOINTS)[number] | `${(typeof _ENDPOINTS)[number]}/${NAMESPACE}` | `reset?all`;
@@ -80,23 +82,138 @@ type QueryCommandPayload = {
80
82
  includeVectors?: boolean;
81
83
  includeMetadata?: boolean;
82
84
  includeData?: boolean;
85
+ weightingStrategy?: WeightingStrategy;
86
+ fusionAlgorithm?: FusionAlgorithm;
87
+ queryMode?: QueryMode;
83
88
  } & ({
84
- vector: number[];
89
+ vector?: number[];
90
+ sparseVector?: SparseVector;
85
91
  data?: never;
86
92
  } | {
87
93
  data: string;
88
94
  vector?: never;
95
+ sparseVector?: never;
89
96
  });
90
97
  type QueryResult<TMetadata = Dict> = {
91
98
  id: number | string;
92
99
  score: number;
93
100
  vector?: number[];
101
+ sparseVector?: SparseVector;
94
102
  metadata?: TMetadata;
95
103
  data?: string;
96
104
  };
97
105
  type QueryCommandOptions = {
98
106
  namespace?: string;
99
107
  };
108
+ /**
109
+ * For sparse vectors, what kind of weighting strategy
110
+ * should be used while querying the matching non-zero
111
+ * dimension values of the query vector with the documents.
112
+ *
113
+ * If not provided, no weighting will be used.
114
+ */
115
+ declare enum WeightingStrategy {
116
+ /**
117
+ * Inverse document frequency.
118
+ *
119
+ * It is recommended to use this weighting strategy for
120
+ * BM25 sparse embedding models.
121
+ *
122
+ * It is calculated as
123
+ *
124
+ * ln(((N - n(q) + 0.5) / (n(q) + 0.5)) + 1) where
125
+ * N: Total number of sparse vectors.
126
+ * n(q): Total number of sparse vectors having non-zero value
127
+ * for that particular dimension.
128
+ * ln: Natural logarithm
129
+ *
130
+ * The values of N and n(q) are maintained by Upstash as the
131
+ * vectors are indexed.
132
+ */
133
+ IDF = "IDF"
134
+ }
135
+ /**
136
+ * Fusion algorithm to use while fusing scores
137
+ * from dense and sparse components of a hybrid index.
138
+ *
139
+ * If not provided, defaults to `RRF`.
140
+ */
141
+ declare enum FusionAlgorithm {
142
+ /**
143
+ * Reciprocal rank fusion.
144
+ *
145
+ * Each sorted score from the dense and sparse indexes are
146
+ * mapped to 1 / (rank + K), where rank is the order of the
147
+ * score in the dense or sparse scores and K is a constant
148
+ * with the value of 60.
149
+ *
150
+ * Then, scores from the dense and sparse components are
151
+ * deduplicated (i.e. if a score for the same vector is present
152
+ * in both dense and sparse scores, the mapped scores are
153
+ * added; otherwise individual mapped scores are used)
154
+ * and the final result is returned as the topK values
155
+ * of this final list.
156
+ *
157
+ * In short, this algorithm just takes the order of the scores
158
+ * into consideration.
159
+ */
160
+ RRF = "RRF",
161
+ /**
162
+ * Distribution based score fusion.
163
+ *
164
+ * Each sorted score from the dense and sparse indexes are
165
+ * normalized as
166
+ * (s - (mean - 3 * stddev)) / ((mean + 3 * stddev) - (mean - 3 * stddev))
167
+ * where s is the score, (mean - 3 * stddev) is the minimum,
168
+ * and (mean + 3 * stddev) is the maximum tail ends of the distribution.
169
+ *
170
+ * Then, scores from the dense and sparse components are
171
+ * deduplicated (i.e. if a score for the same vector is present
172
+ * in both dense and sparse scores, the normalized scores are
173
+ * added; otherwise individual normalized scores are used)
174
+ * and the final result is returned as the topK values
175
+ * of this final list.
176
+ *
177
+ * In short, this algorithm takes distribution of the scores
178
+ * into consideration as well, as opposed to the `RRF`.
179
+ */
180
+ DBSF = "DBSF"
181
+ }
182
+ /**
183
+ * Query mode for hybrid indexes with Upstash-hosted
184
+ * embedding models.
185
+ *
186
+ * Specifies whether to run the query in only the
187
+ * dense index, only the sparse index, or in both.
188
+ *
189
+ * If not provided, defaults to `HYBRID`.
190
+ */
191
+ declare enum QueryMode {
192
+ /**
193
+ * Runs the query in hybrid index mode, after embedding
194
+ * the raw text data into dense and sparse vectors.
195
+ *
196
+ * Query results from the dense and sparse index components
197
+ * of the hybrid index are fused before returning the result.
198
+ */
199
+ HYBRID = "HYBRID",
200
+ /**
201
+ * Runs the query in dense index mode, after embedding
202
+ * the raw text data into a dense vector.
203
+ *
204
+ * Only the query results from the dense index component
205
+ * of the hybrid index is returned.
206
+ */
207
+ DENSE = "DENSE",
208
+ /**
209
+ * Runs the query in sparse index mode, after embedding
210
+ * the raw text data into a sparse vector.
211
+ *
212
+ * Only the query results from the sparse index component
213
+ * of the hybrid index is returned.
214
+ */
215
+ SPARSE = "SPARSE"
216
+ }
100
217
 
101
218
  declare class QueryManyCommand<TMetadata> extends Command<QueryResult<TMetadata>[][]> {
102
219
  constructor(payload: QueryCommandPayload[], options?: QueryCommandOptions);
@@ -189,7 +306,8 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
189
306
  */
190
307
  upsert: <TMetadata extends Dict = TIndexMetadata>(args: {
191
308
  id: string | number;
192
- vector: number[];
309
+ vector?: number[] | undefined;
310
+ sparseVector?: SparseVector | undefined;
193
311
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
194
312
  } | {
195
313
  id: string | number;
@@ -197,7 +315,8 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
197
315
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
198
316
  } | {
199
317
  id: string | number;
200
- vector: number[];
318
+ vector?: number[] | undefined;
319
+ sparseVector?: SparseVector | undefined;
201
320
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
202
321
  }[] | {
203
322
  id: string | number;
@@ -206,7 +325,8 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
206
325
  }[]) => Promise<string>;
207
326
  update: <TMetadata extends Dict = TIndexMetadata>(args: {
208
327
  id: string | number;
209
- vector: number[];
328
+ vector?: number[] | undefined;
329
+ sparseVector?: SparseVector | undefined;
210
330
  } | {
211
331
  id: string | number;
212
332
  data: string;
@@ -215,7 +335,28 @@ declare class Namespace<TIndexMetadata extends Dict = Dict> {
215
335
  metadata: TMetadata extends infer U ? U : never;
216
336
  metadataUpdateMode?: "PATCH" | "OVERWRITE" | undefined;
217
337
  }) => Promise<{
218
- updated: number;
338
+ updated: number; /**
339
+ * Upserts (Updates and Inserts) specific items into the index namespace.
340
+ * It's used for adding new items to the index namespace or updating existing ones.
341
+ *
342
+ * @example
343
+ * ```js
344
+ * const upsertArgs = {
345
+ * id: '123',
346
+ * vector: [0.42, 0.87, ...],
347
+ * metadata: { property1: 'value1', property2: 'value2' }
348
+ * };
349
+ * const upsertResult = await index.namespace("ns").upsert(upsertArgs);
350
+ * console.log(upsertResult); // Outputs the result of the upsert operation
351
+ * ```
352
+ *
353
+ * @param {CommandArgs<typeof UpsertCommand>} args - The arguments for the upsert command.
354
+ * @param {number|string} args.id - The unique identifier for the item being upserted.
355
+ * @param {number[]} args.vector - The feature vector associated with the item.
356
+ * @param {Dict} [args.metadata] - Optional metadata to be associated with the item.
357
+ *
358
+ * @returns {string} A promise that resolves with the result of the upsert operation after the command is executed.
359
+ */
219
360
  }>;
220
361
  /**
221
362
  * It's used for retrieving specific items from the index namespace, optionally including
@@ -482,7 +623,8 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
482
623
  */
483
624
  upsert: <TMetadata extends Dict = TIndexMetadata>(args: {
484
625
  id: string | number;
485
- vector: number[];
626
+ vector?: number[] | undefined;
627
+ sparseVector?: SparseVector | undefined;
486
628
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
487
629
  } | {
488
630
  id: string | number;
@@ -490,7 +632,8 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
490
632
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
491
633
  } | {
492
634
  id: string | number;
493
- vector: number[];
635
+ vector?: number[] | undefined;
636
+ sparseVector?: SparseVector | undefined;
494
637
  metadata?: (TMetadata extends infer U ? U : never) | undefined;
495
638
  }[] | {
496
639
  id: string | number;
@@ -501,7 +644,8 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
501
644
  }) => Promise<string>;
502
645
  update: <TMetadata extends Dict = TIndexMetadata>(args: {
503
646
  id: string | number;
504
- vector: number[];
647
+ vector?: number[] | undefined;
648
+ sparseVector?: SparseVector | undefined;
505
649
  } | {
506
650
  id: string | number;
507
651
  data: string;
@@ -642,4 +786,4 @@ declare class Index<TIndexMetadata extends Dict = Dict> {
642
786
  deleteNamespace: (namespace: string) => Promise<string>;
643
787
  }
644
788
 
645
- export { type Dict as D, type FetchResult as F, Index as I, type QueryResult as Q, type RequesterConfig as R, type UpstashRequest as U, type Vector as V, type Requester as a, type UpstashResponse as b, type RangeResult as c, type InfoResult as d };
789
+ export { type Dict as D, FusionAlgorithm as F, Index as I, QueryMode as Q, type RequesterConfig as R, type UpstashRequest as U, type Vector as V, WeightingStrategy as W, type Requester as a, type UpstashResponse as b, type RangeResult as c, type FetchResult as d, type QueryResult as e, type InfoResult as f };
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@upstash/vector", "version": "v1.1.7", "author": "Oguzhan Olguncu <oguzhan@upstash.com>", "repository": { "type": "git", "url": "https://github.com/upstash/vector-js" }, "exports": { ".": { "import": "./dist/nodejs.mjs", "require": "./dist/nodejs.js" }, "./cloudflare": { "import": "./dist/cloudflare.mjs", "require": "./dist/cloudflare.js" }, "./nodejs": { "import": "./dist/nodejs.mjs", "require": "./dist/nodejs.js" } }, "main": "./dist/nodejs.js", "module": "./dist/nodejs.mjs", "types": "./dist/nodejs.d.ts", "devDependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", "@typescript-eslint/eslint-plugin": "^8.4.0", "bun-types": "latest", "eslint": "9.10.0", "eslint-plugin-unicorn": "^55.0.0", "husky": "^8.0.3", "prettier": "^3.3.3", "tsup": "latest", "typescript": "^5.0.0", "vitest": "^1.2.2" }, "bugs": { "url": "https://github.com/upstash/vector/issues" }, "description": "An HTTP/REST based Vector DB client built on top of Upstash REST API.", "files": [ "dist" ], "homepage": "https://upstash.com/vector", "keywords": [ "vector", "upstash", "db" ], "license": "MIT", "scripts": { "test": "bun test src --coverage --bail --coverageSkipTestFiles=[test-utils.ts] --timeout 20000 && vitest run --typecheck", "fmt": "prettier --write .", "lint": "tsc && eslint \"src/**/*.{js,ts,tsx}\" --quiet --fix", "build": "tsup", "prepare": "husky install" } }
1
+ { "name": "@upstash/vector", "version": "v1.2.0-canary-hybrid", "author": "Oguzhan Olguncu <oguzhan@upstash.com>", "repository": { "type": "git", "url": "https://github.com/upstash/vector-js" }, "exports": { ".": { "import": "./dist/nodejs.mjs", "require": "./dist/nodejs.js" }, "./cloudflare": { "import": "./dist/cloudflare.mjs", "require": "./dist/cloudflare.js" }, "./nodejs": { "import": "./dist/nodejs.mjs", "require": "./dist/nodejs.js" } }, "main": "./dist/nodejs.js", "module": "./dist/nodejs.mjs", "types": "./dist/nodejs.d.ts", "devDependencies": { "@commitlint/cli": "^18.6.0", "@commitlint/config-conventional": "^18.6.0", "@typescript-eslint/eslint-plugin": "^8.4.0", "bun-types": "latest", "eslint": "9.10.0", "eslint-plugin-unicorn": "^55.0.0", "husky": "^8.0.3", "prettier": "^3.3.3", "tsup": "latest", "typescript": "^5.0.0", "vitest": "^1.2.2" }, "bugs": { "url": "https://github.com/upstash/vector/issues" }, "description": "An HTTP/REST based Vector DB client built on top of Upstash REST API.", "files": [ "dist" ], "homepage": "https://upstash.com/vector", "keywords": [ "vector", "upstash", "db" ], "license": "MIT", "scripts": { "test": "bun test src --coverage --bail --coverageSkipTestFiles=[test-utils.ts] --timeout 20000", "fmt": "prettier --write .", "lint": "tsc && eslint \"src/**/*.{js,ts,tsx}\" --quiet --fix", "build": "tsup ", "prepare": "husky install" } }