redis-vl 0.1.0-beta.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/LICENSE +22 -0
- package/README.md +212 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +87 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/indexes/search-index.d.ts +368 -0
- package/dist/indexes/search-index.d.ts.map +1 -0
- package/dist/indexes/search-index.js +475 -0
- package/dist/indexes/search-index.js.map +1 -0
- package/dist/query/base.d.ts +51 -0
- package/dist/query/base.d.ts.map +1 -0
- package/dist/query/base.js +6 -0
- package/dist/query/base.js.map +1 -0
- package/dist/query/index.d.ts +7 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +7 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/vector.d.ts +199 -0
- package/dist/query/vector.d.ts.map +1 -0
- package/dist/query/vector.js +198 -0
- package/dist/query/vector.js.map +1 -0
- package/dist/redis/index-info-parser.d.ts +25 -0
- package/dist/redis/index-info-parser.d.ts.map +1 -0
- package/dist/redis/index-info-parser.js +301 -0
- package/dist/redis/index-info-parser.js.map +1 -0
- package/dist/redis/schema-types.d.ts +81 -0
- package/dist/redis/schema-types.d.ts.map +1 -0
- package/dist/redis/schema-types.js +18 -0
- package/dist/redis/schema-types.js.map +1 -0
- package/dist/redis/utils.d.ts +7 -0
- package/dist/redis/utils.d.ts.map +1 -0
- package/dist/redis/utils.js +221 -0
- package/dist/redis/utils.js.map +1 -0
- package/dist/schema/fields.d.ts +163 -0
- package/dist/schema/fields.d.ts.map +1 -0
- package/dist/schema/fields.js +304 -0
- package/dist/schema/fields.js.map +1 -0
- package/dist/schema/index.d.ts +8 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +8 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/schema.d.ts +247 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +403 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/types.d.ts +56 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +62 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/storage/base-storage.d.ts +107 -0
- package/dist/storage/base-storage.d.ts.map +1 -0
- package/dist/storage/base-storage.js +187 -0
- package/dist/storage/base-storage.js.map +1 -0
- package/dist/storage/hash-storage.d.ts +29 -0
- package/dist/storage/hash-storage.d.ts.map +1 -0
- package/dist/storage/hash-storage.js +122 -0
- package/dist/storage/hash-storage.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +4 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/json-storage.d.ts +19 -0
- package/dist/storage/json-storage.d.ts.map +1 -0
- package/dist/storage/json-storage.js +81 -0
- package/dist/storage/json-storage.js.map +1 -0
- package/dist/utils/distance.d.ts +92 -0
- package/dist/utils/distance.d.ts.map +1 -0
- package/dist/utils/distance.js +98 -0
- package/dist/utils/distance.js.map +1 -0
- package/dist/vectorizers/base-vectorizer.d.ts +88 -0
- package/dist/vectorizers/base-vectorizer.d.ts.map +1 -0
- package/dist/vectorizers/base-vectorizer.js +32 -0
- package/dist/vectorizers/base-vectorizer.js.map +1 -0
- package/dist/vectorizers/huggingface-vectorizer.d.ts +103 -0
- package/dist/vectorizers/huggingface-vectorizer.d.ts.map +1 -0
- package/dist/vectorizers/huggingface-vectorizer.js +142 -0
- package/dist/vectorizers/huggingface-vectorizer.js.map +1 -0
- package/dist/vectorizers/index.d.ts +10 -0
- package/dist/vectorizers/index.d.ts.map +1 -0
- package/dist/vectorizers/index.js +10 -0
- package/dist/vectorizers/index.js.map +1 -0
- package/package.json +96 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser for Redis FT.INFO output to reconstruct IndexSchema
|
|
3
|
+
*/
|
|
4
|
+
import { IndexSchema, IndexInfo, StorageType } from '../schema/index.js';
|
|
5
|
+
import { TextField, TagField, NumericField, GeoField, VectorField, } from '../schema/fields.js';
|
|
6
|
+
import { VectorDistanceMetric, VectorDataType } from '../schema/types.js';
|
|
7
|
+
import { RedisVLError } from '../errors.js';
|
|
8
|
+
// ================================
|
|
9
|
+
// Public API
|
|
10
|
+
// ================================
|
|
11
|
+
/**
|
|
12
|
+
* Build RedisVL IndexSchema from Redis FT.INFO output
|
|
13
|
+
*
|
|
14
|
+
* @param info - The raw output from FT.INFO command
|
|
15
|
+
* @returns IndexSchema instance reconstructed from Redis index metadata
|
|
16
|
+
*/
|
|
17
|
+
export function buildRedisVLSchemaFromRedisIndexInfo(info) {
|
|
18
|
+
const indexName = String(info.index_name);
|
|
19
|
+
const indexDef = asRecord(info.index_definition);
|
|
20
|
+
const storageType = parseStorageType(indexDef);
|
|
21
|
+
const isJson = storageType === StorageType.JSON;
|
|
22
|
+
const prefix = parsePrefix(indexName, indexDef);
|
|
23
|
+
const stopwords = parseStopwords(info.stopwords_list);
|
|
24
|
+
// Parse fields
|
|
25
|
+
const fields = {};
|
|
26
|
+
for (const rawAttr of info.attributes) {
|
|
27
|
+
const attr = asRecord(rawAttr);
|
|
28
|
+
const fieldName = String(attr['identifier']);
|
|
29
|
+
const fieldType = String(attr['type']);
|
|
30
|
+
fields[fieldName] = parseField(fieldName, fieldType, attr, isJson);
|
|
31
|
+
}
|
|
32
|
+
// Create IndexInfo instance
|
|
33
|
+
const indexInfo = new IndexInfo({
|
|
34
|
+
name: indexName,
|
|
35
|
+
prefix,
|
|
36
|
+
storageType,
|
|
37
|
+
// Redis FT.INFO does not expose the key separator used by the application.
|
|
38
|
+
// Default to ':' (library default).
|
|
39
|
+
keySeparator: ':',
|
|
40
|
+
...(stopwords !== undefined && { stopwords }),
|
|
41
|
+
});
|
|
42
|
+
return new IndexSchema({ index: indexInfo, fields });
|
|
43
|
+
}
|
|
44
|
+
// ================================
|
|
45
|
+
// Index-level parsing
|
|
46
|
+
// ================================
|
|
47
|
+
function parseStorageType(indexDef) {
|
|
48
|
+
const keyType = String(indexDef['key_type']).toLowerCase();
|
|
49
|
+
return keyType === 'json' ? StorageType.JSON : StorageType.HASH;
|
|
50
|
+
}
|
|
51
|
+
function parsePrefix(indexName, indexDef) {
|
|
52
|
+
const prefixesValue = indexDef['prefixes'];
|
|
53
|
+
if (typeof prefixesValue === 'string') {
|
|
54
|
+
return prefixesValue;
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(prefixesValue) &&
|
|
57
|
+
prefixesValue.length > 0 &&
|
|
58
|
+
prefixesValue.every((p) => typeof p === 'string')) {
|
|
59
|
+
// Preserve all prefixes when more than one is configured so the schema
|
|
60
|
+
// round-trips through fromExisting() without silently dropping data.
|
|
61
|
+
return prefixesValue.length === 1 ? prefixesValue[0] : [...prefixesValue];
|
|
62
|
+
}
|
|
63
|
+
throw new RedisVLError(`RedisIndexParseError: Invalid index definition for '${indexName}': missing or invalid 'prefixes' value.`);
|
|
64
|
+
}
|
|
65
|
+
function parseStopwords(value) {
|
|
66
|
+
if (Array.isArray(value) && value.every((v) => typeof v === 'string')) {
|
|
67
|
+
return [...value];
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
function parseField(fieldName, fieldType, attr, isJson) {
|
|
72
|
+
const parser = FIELD_PARSERS[fieldType];
|
|
73
|
+
if (!parser) {
|
|
74
|
+
throw new RedisVLError(`RedisIndexParseError: Unsupported field type '${fieldType}' for field '${fieldName}' while rebuilding schema from index info.`);
|
|
75
|
+
}
|
|
76
|
+
return parser(fieldName, attr, isJson);
|
|
77
|
+
}
|
|
78
|
+
// ================================
|
|
79
|
+
// Common decoding helpers
|
|
80
|
+
// ================================
|
|
81
|
+
function asRecord(value) {
|
|
82
|
+
if (value === null || value === undefined || typeof value !== 'object') {
|
|
83
|
+
throw new RedisVLError('RedisIndexParseError: Invalid FT.INFO reply structure: expected an object.');
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
function readString(attr, ...keys) {
|
|
88
|
+
for (const key of keys) {
|
|
89
|
+
const value = attr[key];
|
|
90
|
+
if (typeof value === 'string') {
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
function readNumber(attr, ...keys) {
|
|
97
|
+
for (const key of keys) {
|
|
98
|
+
const value = attr[key];
|
|
99
|
+
if (typeof value === 'number') {
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
if (typeof value === 'string' && value.trim() !== '') {
|
|
103
|
+
const parsed = Number(value);
|
|
104
|
+
if (!Number.isNaN(parsed)) {
|
|
105
|
+
return parsed;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
function readFlag(attr, ...keys) {
|
|
112
|
+
for (const key of keys) {
|
|
113
|
+
if (!(key in attr)) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const value = attr[key];
|
|
117
|
+
if (value === true) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
if (typeof value === 'string') {
|
|
121
|
+
// Some replies use empty string to indicate a present flag
|
|
122
|
+
return value === '' || value.toLowerCase() === 'true' || value === '1';
|
|
123
|
+
}
|
|
124
|
+
if (typeof value === 'number') {
|
|
125
|
+
return value === 1;
|
|
126
|
+
}
|
|
127
|
+
// If the key exists and the value isn't a recognized boolean, treat presence as true
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
function normalizeJsonPath(path) {
|
|
133
|
+
if (path.startsWith('$.')) {
|
|
134
|
+
return path;
|
|
135
|
+
}
|
|
136
|
+
if (path.startsWith('$')) {
|
|
137
|
+
return `$.${path.slice(1)}`;
|
|
138
|
+
}
|
|
139
|
+
return `$.${path}`;
|
|
140
|
+
}
|
|
141
|
+
function parseBaseFieldAttrs(attr, isJson, asName) {
|
|
142
|
+
const attrs = {
|
|
143
|
+
sortable: readFlag(attr, 'SORTABLE', 'sortable'),
|
|
144
|
+
indexMissing: readFlag(attr, 'INDEXMISSING', 'index_missing', 'indexMissing'),
|
|
145
|
+
indexEmpty: readFlag(attr, 'INDEXEMPTY', 'index_empty', 'indexEmpty'),
|
|
146
|
+
};
|
|
147
|
+
// Only include `as` for JSON storage.
|
|
148
|
+
if (isJson) {
|
|
149
|
+
attrs.as = asName;
|
|
150
|
+
}
|
|
151
|
+
return attrs;
|
|
152
|
+
}
|
|
153
|
+
function applyJsonPath(field, attr, isJson) {
|
|
154
|
+
if (!isJson) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const rawPath = readString(attr, 'attribute', 'ATTRIBUTE');
|
|
158
|
+
if (!rawPath) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
field.path = normalizeJsonPath(rawPath);
|
|
162
|
+
}
|
|
163
|
+
class TextFieldParser {
|
|
164
|
+
static parse(fieldName, attr, isJson) {
|
|
165
|
+
const baseAttrs = parseBaseFieldAttrs(attr, isJson, fieldName);
|
|
166
|
+
const textAttrs = {
|
|
167
|
+
...baseAttrs,
|
|
168
|
+
weight: readNumber(attr, 'WEIGHT', 'weight'),
|
|
169
|
+
noStem: readFlag(attr, 'NOSTEM', 'no_stem', 'noStem'),
|
|
170
|
+
phonetic: readString(attr, 'PHONETIC', 'phonetic'),
|
|
171
|
+
withSuffixTrie: readFlag(attr, 'WITHSUFFIXTRIE', 'with_suffix_trie', 'withSuffixTrie'),
|
|
172
|
+
};
|
|
173
|
+
const field = new TextField(fieldName, textAttrs);
|
|
174
|
+
applyJsonPath(field, attr, isJson);
|
|
175
|
+
return field;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
class TagFieldParser {
|
|
179
|
+
static parse(fieldName, attr, isJson) {
|
|
180
|
+
const baseAttrs = parseBaseFieldAttrs(attr, isJson, fieldName);
|
|
181
|
+
const tagAttrs = {
|
|
182
|
+
...baseAttrs,
|
|
183
|
+
separator: readString(attr, 'SEPARATOR', 'separator'),
|
|
184
|
+
caseSensitive: readFlag(attr, 'CASESENSITIVE', 'case_sensitive', 'caseSensitive'),
|
|
185
|
+
};
|
|
186
|
+
const field = new TagField(fieldName, tagAttrs);
|
|
187
|
+
applyJsonPath(field, attr, isJson);
|
|
188
|
+
return field;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
class NumericFieldParser {
|
|
192
|
+
static parse(fieldName, attr, isJson) {
|
|
193
|
+
const baseAttrs = parseBaseFieldAttrs(attr, isJson, fieldName);
|
|
194
|
+
const field = new NumericField(fieldName, baseAttrs);
|
|
195
|
+
applyJsonPath(field, attr, isJson);
|
|
196
|
+
return field;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
class GeoFieldParser {
|
|
200
|
+
static parse(fieldName, attr, isJson) {
|
|
201
|
+
const baseAttrs = parseBaseFieldAttrs(attr, isJson, fieldName);
|
|
202
|
+
const field = new GeoField(fieldName, baseAttrs);
|
|
203
|
+
applyJsonPath(field, attr, isJson);
|
|
204
|
+
return field;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
class VectorFieldParser {
|
|
208
|
+
static parse(fieldName, attr, isJson) {
|
|
209
|
+
const dims = readNumber(attr, 'dim', 'DIM', 'dims', 'DIMS');
|
|
210
|
+
const algorithmRaw = readString(attr, 'algorithm', 'ALGORITHM');
|
|
211
|
+
const distanceMetricRaw = readString(attr, 'distance_metric', 'DISTANCE_METRIC');
|
|
212
|
+
const dataTypeRaw = readString(attr, 'data_type', 'DATA_TYPE', 'TYPE');
|
|
213
|
+
if (dims === undefined || !Number.isFinite(dims) || dims <= 0 || !Number.isInteger(dims)) {
|
|
214
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' is missing or has invalid dimension (DIM).`);
|
|
215
|
+
}
|
|
216
|
+
if (!algorithmRaw) {
|
|
217
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' is missing required 'algorithm' attribute`);
|
|
218
|
+
}
|
|
219
|
+
if (!distanceMetricRaw) {
|
|
220
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' is missing required 'distance_metric' attribute`);
|
|
221
|
+
}
|
|
222
|
+
if (!dataTypeRaw) {
|
|
223
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' is missing required 'data_type' attribute`);
|
|
224
|
+
}
|
|
225
|
+
const algorithm = VectorFieldParser.parseVectorAlgorithm(fieldName, algorithmRaw);
|
|
226
|
+
const distanceMetric = VectorFieldParser.parseVectorDistanceMetric(fieldName, distanceMetricRaw);
|
|
227
|
+
const datatype = VectorFieldParser.parseVectorDataType(fieldName, dataTypeRaw);
|
|
228
|
+
const baseAttrs = parseBaseFieldAttrs(attr, isJson, fieldName);
|
|
229
|
+
const options = {
|
|
230
|
+
...baseAttrs,
|
|
231
|
+
algorithm,
|
|
232
|
+
dims,
|
|
233
|
+
distanceMetric,
|
|
234
|
+
datatype,
|
|
235
|
+
};
|
|
236
|
+
// Parse algorithm-specific parameters
|
|
237
|
+
if (algorithm === 'hnsw') {
|
|
238
|
+
const m = readNumber(attr, 'm', 'M');
|
|
239
|
+
const efConstruction = readNumber(attr, 'ef_construction', 'EF_CONSTRUCTION', 'efConstruction');
|
|
240
|
+
const efRuntime = readNumber(attr, 'ef_runtime', 'EF_RUNTIME', 'efRuntime');
|
|
241
|
+
const epsilon = readNumber(attr, 'epsilon', 'EPSILON');
|
|
242
|
+
if (m !== undefined) {
|
|
243
|
+
options.m = Math.trunc(m);
|
|
244
|
+
}
|
|
245
|
+
if (efConstruction !== undefined) {
|
|
246
|
+
options.efConstruction = Math.trunc(efConstruction);
|
|
247
|
+
}
|
|
248
|
+
if (efRuntime !== undefined) {
|
|
249
|
+
options.efRuntime = Math.trunc(efRuntime);
|
|
250
|
+
}
|
|
251
|
+
if (epsilon !== undefined) {
|
|
252
|
+
options.epsilon = epsilon;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (algorithm === 'flat') {
|
|
256
|
+
const blockSize = readNumber(attr, 'block_size', 'BLOCK_SIZE', 'blockSize');
|
|
257
|
+
const initialCap = readNumber(attr, 'initial_cap', 'INITIAL_CAP', 'initialCap');
|
|
258
|
+
if (blockSize !== undefined) {
|
|
259
|
+
options.blockSize = Math.trunc(blockSize);
|
|
260
|
+
}
|
|
261
|
+
if (initialCap !== undefined) {
|
|
262
|
+
options.initialCap = Math.trunc(initialCap);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const field = new VectorField(fieldName, options);
|
|
266
|
+
applyJsonPath(field, attr, isJson);
|
|
267
|
+
return field;
|
|
268
|
+
}
|
|
269
|
+
static parseVectorAlgorithm(fieldName, algorithmRaw) {
|
|
270
|
+
const algorithmKey = algorithmRaw.toUpperCase();
|
|
271
|
+
if (algorithmKey === 'FLAT') {
|
|
272
|
+
return 'flat';
|
|
273
|
+
}
|
|
274
|
+
if (algorithmKey === 'HNSW') {
|
|
275
|
+
return 'hnsw';
|
|
276
|
+
}
|
|
277
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' uses unsupported algorithm '${algorithmRaw}'.`);
|
|
278
|
+
}
|
|
279
|
+
static parseVectorDistanceMetric(fieldName, metricRaw) {
|
|
280
|
+
const metricKey = metricRaw.toUpperCase();
|
|
281
|
+
if (!Object.values(VectorDistanceMetric).includes(metricKey)) {
|
|
282
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' has unsupported distance metric '${metricRaw}'.`);
|
|
283
|
+
}
|
|
284
|
+
return metricKey;
|
|
285
|
+
}
|
|
286
|
+
static parseVectorDataType(fieldName, typeRaw) {
|
|
287
|
+
const typeKey = typeRaw.toUpperCase();
|
|
288
|
+
if (!Object.values(VectorDataType).includes(typeKey)) {
|
|
289
|
+
throw new RedisVLError(`RedisIndexParseError: Vector field '${fieldName}' has unsupported data type '${typeRaw}'.`);
|
|
290
|
+
}
|
|
291
|
+
return typeKey;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const FIELD_PARSERS = {
|
|
295
|
+
TEXT: TextFieldParser.parse,
|
|
296
|
+
TAG: TagFieldParser.parse,
|
|
297
|
+
NUMERIC: NumericFieldParser.parse,
|
|
298
|
+
GEO: GeoFieldParser.parse,
|
|
299
|
+
VECTOR: VectorFieldParser.parse,
|
|
300
|
+
};
|
|
301
|
+
//# sourceMappingURL=index-info-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-info-parser.js","sourceRoot":"","sources":["../../src/redis/index-info-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis Search Schema Field Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* These types are extracted from the RediSearchSchema interface exported by @redis/search.
|
|
5
|
+
* While @redis/search doesn't export the individual field type interfaces (SchemaTextField, etc.),
|
|
6
|
+
* we can extract them using TypeScript utility types from the RediSearchSchema union.
|
|
7
|
+
*
|
|
8
|
+
* Source: @redis/search/dist/lib/commands/CREATE.d.ts
|
|
9
|
+
*
|
|
10
|
+
* This approach is more maintainable than duplicating the type definitions because:
|
|
11
|
+
* 1. Types automatically stay in sync with @redis/search updates
|
|
12
|
+
* 2. No risk of type definition drift
|
|
13
|
+
* 3. Leverages TypeScript's type system for extraction
|
|
14
|
+
*
|
|
15
|
+
* @see https://github.com/redis/node-redis/tree/master/packages/search
|
|
16
|
+
*/
|
|
17
|
+
import type { RediSearchSchema } from '@redis/search';
|
|
18
|
+
/**
|
|
19
|
+
* Extract the union of all schema field types from RediSearchSchema
|
|
20
|
+
*/
|
|
21
|
+
type ExtractSchemaTypes = RediSearchSchema[string];
|
|
22
|
+
/**
|
|
23
|
+
* Text field schema - extracted from RediSearchSchema
|
|
24
|
+
*/
|
|
25
|
+
export type SchemaTextField = Extract<ExtractSchemaTypes, {
|
|
26
|
+
type: 'TEXT';
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Extract the PHONETIC type from SchemaTextField
|
|
30
|
+
*/
|
|
31
|
+
export type SchemaTextFieldPhonetic = NonNullable<SchemaTextField['PHONETIC']>;
|
|
32
|
+
/**
|
|
33
|
+
* Numeric field schema - extracted from RediSearchSchema
|
|
34
|
+
*/
|
|
35
|
+
export type SchemaNumericField = Extract<ExtractSchemaTypes, {
|
|
36
|
+
type: 'NUMERIC';
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Geo field schema - extracted from RediSearchSchema
|
|
40
|
+
*/
|
|
41
|
+
export type SchemaGeoField = Extract<ExtractSchemaTypes, {
|
|
42
|
+
type: 'GEO';
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Tag field schema - extracted from RediSearchSchema
|
|
46
|
+
*/
|
|
47
|
+
export type SchemaTagField = Extract<ExtractSchemaTypes, {
|
|
48
|
+
type: 'TAG';
|
|
49
|
+
}>;
|
|
50
|
+
/**
|
|
51
|
+
* Vector field schema (base) - extracted from RediSearchSchema
|
|
52
|
+
*/
|
|
53
|
+
type SchemaVectorField = Extract<ExtractSchemaTypes, {
|
|
54
|
+
type: 'VECTOR';
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* FLAT vector field schema - extracted from RediSearchSchema
|
|
58
|
+
*/
|
|
59
|
+
export type SchemaFlatVectorField = Extract<SchemaVectorField, {
|
|
60
|
+
ALGORITHM: 'FLAT';
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* HNSW vector field schema - extracted from RediSearchSchema
|
|
64
|
+
*/
|
|
65
|
+
export type SchemaHNSWVectorField = Extract<SchemaVectorField, {
|
|
66
|
+
ALGORITHM: 'HNSW';
|
|
67
|
+
}>;
|
|
68
|
+
/**
|
|
69
|
+
* Extract the TYPE union from SchemaVectorField
|
|
70
|
+
*/
|
|
71
|
+
export type SchemaVectorFieldType = SchemaVectorField['TYPE'];
|
|
72
|
+
/**
|
|
73
|
+
* Extract the DISTANCE_METRIC union from SchemaVectorField
|
|
74
|
+
*/
|
|
75
|
+
export type SchemaVectorFieldDistanceMetric = SchemaVectorField['DISTANCE_METRIC'];
|
|
76
|
+
/**
|
|
77
|
+
* Union type of all Redis schema field types we support
|
|
78
|
+
*/
|
|
79
|
+
export type RedisSchemaFieldType = SchemaTextField | SchemaNumericField | SchemaGeoField | SchemaTagField | SchemaFlatVectorField | SchemaHNSWVectorField;
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=schema-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-types.d.ts","sourceRoot":"","sources":["../../src/redis/schema-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD;;GAEG;AACH,KAAK,kBAAkB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5E;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;AAE/E;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAElF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE1E;;GAEG;AACH,KAAK,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,+BAA+B,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC1B,eAAe,GACf,kBAAkB,GAClB,cAAc,GACd,cAAc,GACd,qBAAqB,GACrB,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis Search Schema Field Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* These types are extracted from the RediSearchSchema interface exported by @redis/search.
|
|
5
|
+
* While @redis/search doesn't export the individual field type interfaces (SchemaTextField, etc.),
|
|
6
|
+
* we can extract them using TypeScript utility types from the RediSearchSchema union.
|
|
7
|
+
*
|
|
8
|
+
* Source: @redis/search/dist/lib/commands/CREATE.d.ts
|
|
9
|
+
*
|
|
10
|
+
* This approach is more maintainable than duplicating the type definitions because:
|
|
11
|
+
* 1. Types automatically stay in sync with @redis/search updates
|
|
12
|
+
* 2. No risk of type definition drift
|
|
13
|
+
* 3. Leverages TypeScript's type system for extraction
|
|
14
|
+
*
|
|
15
|
+
* @see https://github.com/redis/node-redis/tree/master/packages/search
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=schema-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-types.js","sourceRoot":"","sources":["../../src/redis/schema-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { VectorDataType } from '../schema/types.js';
|
|
2
|
+
export type VectorDataTypeInput = VectorDataType | string | undefined;
|
|
3
|
+
export declare function normalizeVectorDataType(datatype: VectorDataTypeInput): VectorDataType;
|
|
4
|
+
export declare function vectorElementByteLength(datatype: VectorDataTypeInput): number;
|
|
5
|
+
export declare function encodeVectorBuffer(vector: readonly unknown[], datatype?: VectorDataTypeInput): Buffer;
|
|
6
|
+
export declare function decodeVectorBuffer(buffer: Buffer, datatype?: VectorDataTypeInput): number[];
|
|
7
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/redis/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;AAItE,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,cAAc,CAYrF;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,CAa7E;AAED,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,SAAS,OAAO,EAAE,EAC1B,QAAQ,GAAE,mBAA4C,GACvD,MAAM,CAmBR;AAED,wBAAgB,kBAAkB,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,mBAA4C,GACvD,MAAM,EAAE,CAwBV"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { SchemaValidationError } from '../errors.js';
|
|
2
|
+
import { VectorDataType } from '../schema/types.js';
|
|
3
|
+
const VALID_VECTOR_DATA_TYPES = new Set(Object.values(VectorDataType));
|
|
4
|
+
export function normalizeVectorDataType(datatype) {
|
|
5
|
+
const normalized = String(datatype ?? VectorDataType.FLOAT32).toUpperCase();
|
|
6
|
+
if (!VALID_VECTOR_DATA_TYPES.has(normalized)) {
|
|
7
|
+
throw new SchemaValidationError(`Invalid vector datatype: ${datatype}. Supported datatypes are: ${Object.values(VectorDataType).join(', ')}`);
|
|
8
|
+
}
|
|
9
|
+
return normalized;
|
|
10
|
+
}
|
|
11
|
+
export function vectorElementByteLength(datatype) {
|
|
12
|
+
switch (normalizeVectorDataType(datatype)) {
|
|
13
|
+
case VectorDataType.FLOAT64:
|
|
14
|
+
return 8;
|
|
15
|
+
case VectorDataType.FLOAT16:
|
|
16
|
+
case VectorDataType.BFLOAT16:
|
|
17
|
+
return 2;
|
|
18
|
+
case VectorDataType.INT8:
|
|
19
|
+
case VectorDataType.UINT8:
|
|
20
|
+
return 1;
|
|
21
|
+
case VectorDataType.FLOAT32:
|
|
22
|
+
return 4;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function encodeVectorBuffer(vector, datatype = VectorDataType.FLOAT32) {
|
|
26
|
+
switch (normalizeVectorDataType(datatype)) {
|
|
27
|
+
case VectorDataType.FLOAT64:
|
|
28
|
+
return Buffer.from(new Float64Array(validateVectorValues(vector)).buffer);
|
|
29
|
+
case VectorDataType.FLOAT16:
|
|
30
|
+
return encodeFloat16Buffer(validateVectorValues(vector));
|
|
31
|
+
case VectorDataType.BFLOAT16:
|
|
32
|
+
return encodeBFloat16Buffer(validateVectorValues(vector));
|
|
33
|
+
case VectorDataType.INT8:
|
|
34
|
+
return Buffer.from(Int8Array.from(validateIntegerVector(vector, -128, 127, VectorDataType.INT8)).buffer);
|
|
35
|
+
case VectorDataType.UINT8:
|
|
36
|
+
return Buffer.from(Uint8Array.from(validateIntegerVector(vector, 0, 255, VectorDataType.UINT8)).buffer);
|
|
37
|
+
case VectorDataType.FLOAT32:
|
|
38
|
+
return Buffer.from(new Float32Array(validateVectorValues(vector)).buffer);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function decodeVectorBuffer(buffer, datatype = VectorDataType.FLOAT32) {
|
|
42
|
+
const normalizedDatatype = normalizeVectorDataType(datatype);
|
|
43
|
+
const elementSize = vectorElementByteLength(normalizedDatatype);
|
|
44
|
+
if (buffer.byteLength % elementSize !== 0) {
|
|
45
|
+
throw new SchemaValidationError(`Vector buffer byte length (${buffer.byteLength}) is not a multiple of the ${normalizedDatatype} element size (${elementSize} bytes)`);
|
|
46
|
+
}
|
|
47
|
+
switch (normalizedDatatype) {
|
|
48
|
+
case VectorDataType.FLOAT64:
|
|
49
|
+
return decodeFloat64Buffer(buffer);
|
|
50
|
+
case VectorDataType.FLOAT16:
|
|
51
|
+
return decodeFloat16Buffer(buffer);
|
|
52
|
+
case VectorDataType.BFLOAT16:
|
|
53
|
+
return decodeBFloat16Buffer(buffer);
|
|
54
|
+
case VectorDataType.INT8:
|
|
55
|
+
return Array.from(new Int8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength));
|
|
56
|
+
case VectorDataType.UINT8:
|
|
57
|
+
return Array.from(new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength));
|
|
58
|
+
case VectorDataType.FLOAT32:
|
|
59
|
+
return decodeFloat32Buffer(buffer);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function validateVectorValues(vector) {
|
|
63
|
+
return vector.map((value, index) => {
|
|
64
|
+
assertFiniteNumber(value, index);
|
|
65
|
+
return value;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function validateIntegerVector(vector, min, max, datatype) {
|
|
69
|
+
return vector.map((value, index) => {
|
|
70
|
+
assertFiniteNumber(value, index);
|
|
71
|
+
const numericValue = value;
|
|
72
|
+
if (!Number.isInteger(numericValue) || numericValue < min || numericValue > max) {
|
|
73
|
+
throw new SchemaValidationError(`Vector value at index ${index} (${numericValue}) is outside the ${datatype} range (${min} to ${max})`);
|
|
74
|
+
}
|
|
75
|
+
return numericValue;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function assertFiniteNumber(value, index) {
|
|
79
|
+
if (typeof value !== 'number' || Number.isNaN(value)) {
|
|
80
|
+
const reported = Number.isNaN(value) ? 'NaN' : typeof value;
|
|
81
|
+
throw new SchemaValidationError(`Vector contains non-numeric value at index ${index}: ${reported}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function decodeFloat32Buffer(buffer) {
|
|
85
|
+
const values = [];
|
|
86
|
+
for (let offset = 0; offset + 4 <= buffer.byteLength; offset += 4) {
|
|
87
|
+
values.push(buffer.readFloatLE(offset));
|
|
88
|
+
}
|
|
89
|
+
return values;
|
|
90
|
+
}
|
|
91
|
+
function decodeFloat64Buffer(buffer) {
|
|
92
|
+
const values = [];
|
|
93
|
+
for (let offset = 0; offset + 8 <= buffer.byteLength; offset += 8) {
|
|
94
|
+
values.push(buffer.readDoubleLE(offset));
|
|
95
|
+
}
|
|
96
|
+
return values;
|
|
97
|
+
}
|
|
98
|
+
// Float16 (IEEE 754 binary16) encode/decode implemented manually on top of
|
|
99
|
+
// DataView. The standard `Float16Array` and `DataView#getFloat16` both
|
|
100
|
+
// landed in V8 13.0 — Node 23+ — so we can't rely on them while we support
|
|
101
|
+
// Node 22 LTS. The BFloat16 path uses the same DataView-based approach.
|
|
102
|
+
function encodeFloat16Buffer(values) {
|
|
103
|
+
const buffer = Buffer.alloc(values.length * 2);
|
|
104
|
+
for (let i = 0; i < values.length; i++) {
|
|
105
|
+
buffer.writeUInt16LE(encodeFloat16(values[i]), i * 2);
|
|
106
|
+
}
|
|
107
|
+
return buffer;
|
|
108
|
+
}
|
|
109
|
+
function decodeFloat16Buffer(buffer) {
|
|
110
|
+
const values = [];
|
|
111
|
+
for (let offset = 0; offset + 2 <= buffer.byteLength; offset += 2) {
|
|
112
|
+
values.push(decodeFloat16(buffer.readUInt16LE(offset)));
|
|
113
|
+
}
|
|
114
|
+
return values;
|
|
115
|
+
}
|
|
116
|
+
// Float16 layout: 1 sign | 5 exponent (bias 15) | 10 mantissa.
|
|
117
|
+
// Bridges through float32's bit pattern to preserve IEEE 754 semantics,
|
|
118
|
+
// then rounds to nearest with ties-to-even — matching `Float16Array` so a
|
|
119
|
+
// round-trip through this code produces identical bits on Node 22 vs 24+.
|
|
120
|
+
function encodeFloat16(value) {
|
|
121
|
+
const dataView = new DataView(new ArrayBuffer(4));
|
|
122
|
+
dataView.setFloat32(0, value);
|
|
123
|
+
const x = dataView.getUint32(0);
|
|
124
|
+
const sign = (x >>> 16) & 0x8000;
|
|
125
|
+
const exp32 = (x >>> 23) & 0xff;
|
|
126
|
+
const mant32 = x & 0x7fffff;
|
|
127
|
+
// NaN / Infinity (exp32 all-ones)
|
|
128
|
+
if (exp32 === 0xff) {
|
|
129
|
+
if (mant32 !== 0) {
|
|
130
|
+
// NaN — keep at least one mantissa bit set so it stays a NaN.
|
|
131
|
+
return sign | 0x7c00 | (mant32 >>> 13) | 0x200;
|
|
132
|
+
}
|
|
133
|
+
return sign | 0x7c00; // signed Infinity
|
|
134
|
+
}
|
|
135
|
+
const unbiased = exp32 - 127;
|
|
136
|
+
// Overflow → signed Infinity.
|
|
137
|
+
if (unbiased >= 16)
|
|
138
|
+
return sign | 0x7c00;
|
|
139
|
+
// Underflow past the smallest subnormal → signed zero.
|
|
140
|
+
if (unbiased < -24)
|
|
141
|
+
return sign;
|
|
142
|
+
// Subnormal range: unbiased in [-24, -15].
|
|
143
|
+
if (unbiased < -14) {
|
|
144
|
+
const fullMant = mant32 | 0x800000; // restore the implicit leading 1
|
|
145
|
+
const shiftBy = -1 - unbiased; // 14..23
|
|
146
|
+
const half = 1 << (shiftBy - 1);
|
|
147
|
+
const low = fullMant & ((1 << shiftBy) - 1);
|
|
148
|
+
let mant16 = fullMant >>> shiftBy;
|
|
149
|
+
if (low > half || (low === half && (mant16 & 1) !== 0)) {
|
|
150
|
+
mant16++;
|
|
151
|
+
// Subnormal mantissa rolled into the smallest normal value.
|
|
152
|
+
if (mant16 === 0x400)
|
|
153
|
+
return sign | 0x0400;
|
|
154
|
+
}
|
|
155
|
+
return sign | mant16;
|
|
156
|
+
}
|
|
157
|
+
// Normal range: unbiased in [-14, 15].
|
|
158
|
+
const exp16 = unbiased + 15;
|
|
159
|
+
const halfBit = 1 << 12;
|
|
160
|
+
const low = mant32 & 0x1fff;
|
|
161
|
+
let mant16 = mant32 >>> 13;
|
|
162
|
+
if (low > halfBit || (low === halfBit && (mant16 & 1) !== 0)) {
|
|
163
|
+
mant16++;
|
|
164
|
+
if (mant16 === 0x400) {
|
|
165
|
+
// Mantissa rolled over — bump the exponent and possibly overflow to Inf.
|
|
166
|
+
const newExp = exp16 + 1;
|
|
167
|
+
if (newExp >= 31)
|
|
168
|
+
return sign | 0x7c00;
|
|
169
|
+
return sign | (newExp << 10);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return sign | (exp16 << 10) | mant16;
|
|
173
|
+
}
|
|
174
|
+
function decodeFloat16(bits) {
|
|
175
|
+
const sign = (bits >>> 15) & 1;
|
|
176
|
+
const exp = (bits >>> 10) & 0x1f;
|
|
177
|
+
const mantissa = bits & 0x3ff;
|
|
178
|
+
let abs;
|
|
179
|
+
if (exp === 0x1f) {
|
|
180
|
+
// NaN or Infinity
|
|
181
|
+
abs = mantissa === 0 ? Infinity : NaN;
|
|
182
|
+
}
|
|
183
|
+
else if (exp === 0) {
|
|
184
|
+
// Zero or subnormal: value = mantissa × 2^-24
|
|
185
|
+
abs = mantissa === 0 ? 0 : mantissa * Math.pow(2, -24);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// Normal: value = (1 + mantissa/2^10) × 2^(exp - 15)
|
|
189
|
+
// = (1024 + mantissa) × 2^(exp - 25)
|
|
190
|
+
abs = (1024 + mantissa) * Math.pow(2, exp - 25);
|
|
191
|
+
}
|
|
192
|
+
return sign ? -abs : abs;
|
|
193
|
+
}
|
|
194
|
+
function encodeBFloat16Buffer(values) {
|
|
195
|
+
const buffer = Buffer.alloc(values.length * 2);
|
|
196
|
+
values.forEach((value, index) => {
|
|
197
|
+
buffer.writeUInt16LE(encodeBFloat16(value), index * 2);
|
|
198
|
+
});
|
|
199
|
+
return buffer;
|
|
200
|
+
}
|
|
201
|
+
function decodeBFloat16Buffer(buffer) {
|
|
202
|
+
const values = [];
|
|
203
|
+
for (let offset = 0; offset + 2 <= buffer.byteLength; offset += 2) {
|
|
204
|
+
values.push(decodeBFloat16(buffer.readUInt16LE(offset)));
|
|
205
|
+
}
|
|
206
|
+
return values;
|
|
207
|
+
}
|
|
208
|
+
// Round-half-to-even; matches numpy (ml_dtypes.bfloat16) at exact boundaries.
|
|
209
|
+
function encodeBFloat16(value) {
|
|
210
|
+
const dataView = new DataView(new ArrayBuffer(4));
|
|
211
|
+
dataView.setFloat32(0, value, false);
|
|
212
|
+
const bits = dataView.getUint32(0, false);
|
|
213
|
+
const leastSignificantBit = (bits >> 16) & 1;
|
|
214
|
+
return (bits + 0x7fff + leastSignificantBit) >>> 16;
|
|
215
|
+
}
|
|
216
|
+
function decodeBFloat16(bits) {
|
|
217
|
+
const dataView = new DataView(new ArrayBuffer(4));
|
|
218
|
+
dataView.setUint32(0, bits << 16, false);
|
|
219
|
+
return dataView.getFloat32(0, false);
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=utils.js.map
|