Skip to content

Commit cf9ad92

Browse files
committed
feat: add support for RQ
1 parent d2c3b42 commit cf9ad92

File tree

8 files changed

+163
-57
lines changed

8 files changed

+163
-57
lines changed

src/collections/config/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
CollectionConfigUpdate,
2020
PQConfig,
2121
QuantizerConfig,
22+
RQConfig,
2223
SQConfig,
2324
VectorIndexConfig,
2425
VectorIndexConfigDynamic,
@@ -40,15 +41,15 @@ const config = <T>(
4041
.withClassName(name)
4142
.withProperty(resolveProperty<any>(property, []))
4243
.do()
43-
.then(() => {}),
44+
.then(() => { }),
4445
addReference: (
4546
reference: ReferenceSingleTargetConfigCreate<any> | ReferenceMultiTargetConfigCreate<any>
4647
) =>
4748
new PropertyCreator(connection)
4849
.withClassName(name)
4950
.withProperty(resolveReference<any>(reference))
5051
.do()
51-
.then(() => {}),
52+
.then(() => { }),
5253
addVector: async (vectors: VectorizersConfigAdd<T>) => {
5354
const supportsDynamicVectorIndex = await dbVersionSupport.supportsDynamicVectorIndex();
5455
const { vectorsConfig } = makeVectorsConfig(vectors, supportsDynamicVectorIndex);
@@ -72,7 +73,7 @@ const config = <T>(
7273
})
7374
);
7475
},
75-
updateShards: async function (status: 'READY' | 'READONLY', names?: string | string[]) {
76+
updateShards: async function(status: 'READY' | 'READONLY', names?: string | string[]) {
7677
let shardNames: string[];
7778
if (names === undefined) {
7879
shardNames = await this.getShards().then((shards) => shards.map((s) => s.name));
@@ -97,7 +98,7 @@ const config = <T>(
9798
)
9899
)
99100
.then((merged) => new ClassUpdater(connection).withClass(merged).do())
100-
.then(() => {});
101+
.then(() => { });
101102
},
102103
};
103104
};
@@ -192,6 +193,9 @@ export class Quantizer {
192193
static isSQ(config?: QuantizerConfig): config is SQConfig {
193194
return config?.type === 'sq';
194195
}
196+
static isRQ(config?: QuantizerConfig): config is RQConfig {
197+
return config?.type === 'rq';
198+
}
195199
}
196200

197201
export const configGuards = {

src/collections/config/integration.test.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ import {
1212
VectorIndexConfigHNSW,
1313
} from './types/index.js';
1414

15-
const fail = (msg: string) => {
16-
throw new Error(msg);
17-
};
1815

1916
describe('Testing of the collection.config namespace', () => {
2017
let client: WeaviateClient;
@@ -210,6 +207,30 @@ describe('Testing of the collection.config namespace', () => {
210207
expect(config.vectorizers.default.vectorizer.name).toEqual('none');
211208
});
212209

210+
it('should be able to get the config of a collection with hnsw-rq', async () => {
211+
const collectionName = 'TestCollectionConfigGetHNSWPlusRQ';
212+
const collection = await client.collections.create({
213+
name: collectionName,
214+
vectorizers: weaviate.configure.vectorizer.none({
215+
vectorIndexConfig: weaviate.configure.vectorIndex.hnsw({
216+
quantizer: weaviate.configure.vectorIndex.quantizer.rq(),
217+
}),
218+
}),
219+
});
220+
const config = await collection.config.get();
221+
222+
const vectorIndexConfig = config.vectorizers.default.indexConfig as VectorIndexConfigHNSW;
223+
expect(config.name).toEqual(collectionName);
224+
expect(config.generative).toBeUndefined();
225+
expect(config.reranker).toBeUndefined();
226+
expect(vectorIndexConfig).toBeDefined();
227+
expect(vectorIndexConfig.quantizer).toBeDefined();
228+
expect(vectorIndexConfig.quantizer?.type).toEqual('rq');
229+
expect(config.vectorizers.default.indexType).toEqual('hnsw');
230+
expect(config.vectorizers.default.properties).toBeUndefined();
231+
expect(config.vectorizers.default.vectorizer.name).toEqual('none');
232+
});
233+
213234
it('should be able to get the config of a collection with hnsw-bq', async () => {
214235
const collectionName = 'TestCollectionConfigGetHNSWPlusBQ';
215236
const query = () =>
@@ -534,8 +555,8 @@ describe('Testing of the collection.config namespace', () => {
534555
.update({
535556
propertyDescriptions: supportsUpdatingPropertyDescriptions
536557
? {
537-
testProp: 'This is a test property',
538-
}
558+
testProp: 'This is a test property',
559+
}
539560
: undefined,
540561
vectorizers: weaviate.reconfigure.vectorizer.update({
541562
vectorIndexConfig: weaviate.reconfigure.vectorIndex.hnsw({

src/collections/config/types/vectorIndex.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export type VectorIndexConfigHNSW = {
99
filterStrategy: VectorIndexFilterStrategy;
1010
flatSearchCutoff: number;
1111
maxConnections: number;
12-
quantizer: PQConfig | BQConfig | SQConfig | undefined;
12+
quantizer: PQConfig | BQConfig | SQConfig | RQConfig | undefined;
1313
skip: boolean;
1414
vectorCacheMaxObjects: number;
1515
type: 'hnsw';
@@ -61,6 +61,12 @@ export type PQConfig = {
6161
type: 'pq';
6262
};
6363

64+
export type RQConfig = {
65+
bits?: number;
66+
rescoreLimit?: number;
67+
type: 'rq';
68+
}
69+
6470
export type PQEncoderConfig = {
6571
type: PQEncoderType;
6672
distribution: PQEncoderDistribution;
@@ -77,4 +83,4 @@ export type VectorIndexFilterStrategy = 'sweeping' | 'acorn';
7783

7884
export type VectorIndexConfig = VectorIndexConfigHNSW | VectorIndexConfigFlat | VectorIndexConfigDynamic;
7985

80-
export type QuantizerConfig = PQConfig | BQConfig | SQConfig;
86+
export type QuantizerConfig = PQConfig | BQConfig | SQConfig | RQConfig;

src/collections/config/utils.ts

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
PQEncoderType,
4747
PropertyConfig,
4848
PropertyVectorizerConfig,
49+
RQConfig,
4950
ReferenceConfig,
5051
ReplicationConfig,
5152
Reranker,
@@ -182,6 +183,16 @@ export const parseVectorIndex = (module: ModuleConfig<VectorIndexType, VectorInd
182183
},
183184
};
184185
}
186+
if (QuantizerGuards.isRQCreate(quantizer)) {
187+
const { type, ...quant } = quantizer;
188+
return {
189+
...conf,
190+
rq: {
191+
...quant,
192+
enabled: true,
193+
},
194+
};
195+
}
185196
};
186197

187198
export const parseVectorizerConfig = (config?: VectorizerConfig): any => {
@@ -202,11 +213,11 @@ export const makeVectorsConfig = <TProperties extends Properties | undefined = u
202213
const vectorizersConfig = Array.isArray(configVectorizers)
203214
? configVectorizers
204215
: [
205-
{
206-
...configVectorizers,
207-
name: configVectorizers.name || 'default',
208-
},
209-
];
216+
{
217+
...configVectorizers,
218+
name: configVectorizers.name || 'default',
219+
},
220+
];
210221
vectorizersConfig.forEach((v) => {
211222
if (v.vectorIndex.name === 'dynamic' && !supportsDynamicVectorIndex.supports) {
212223
throw new WeaviateUnsupportedFeatureError(supportsDynamicVectorIndex.message);
@@ -329,18 +340,18 @@ class ConfigMapping {
329340
vectorizer:
330341
v.vectorizer === 'none'
331342
? {
332-
name: 'none',
333-
config: undefined,
334-
}
343+
name: 'none',
344+
config: undefined,
345+
}
335346
: {
336-
name: v.vectorizer,
337-
config: v.moduleConfig
338-
? ({
339-
...(v.moduleConfig[v.vectorizer] as any),
340-
vectorizeCollectionName: (v.moduleConfig[v.vectorizer] as any).vectorizeClassName,
341-
} as VectorizerConfig)
342-
: undefined,
343-
},
347+
name: v.vectorizer,
348+
config: v.moduleConfig
349+
? ({
350+
...(v.moduleConfig[v.vectorizer] as any),
351+
vectorizeCollectionName: (v.moduleConfig[v.vectorizer] as any).vectorizeClassName,
352+
} as VectorizerConfig)
353+
: undefined,
354+
},
344355
indexConfig: ConfigMapping.vectorIndex(v.vectorIndexConfig, v.vectorIndexType),
345356
indexType: ConfigMapping.vectorIndexType(v.vectorIndexType),
346357
},
@@ -468,11 +479,13 @@ class ConfigMapping {
468479
throw new WeaviateDeserializationError(
469480
'Vector index vector cache max objects was not returned by Weaviate'
470481
);
471-
let quantizer: PQConfig | BQConfig | SQConfig | undefined;
482+
let quantizer: PQConfig | BQConfig | SQConfig | RQConfig | undefined;
472483
if (exists<Record<string, any>>(v.pq) && v.pq.enabled === true) {
473484
quantizer = ConfigMapping.pq(v.pq);
474485
} else if (exists<Record<string, any>>(v.bq) && v.bq.enabled === true) {
475486
quantizer = ConfigMapping.bq(v.bq);
487+
} else if (exists<Record<string, any>>(v.rq) && v.rq.enabled === true) {
488+
quantizer = ConfigMapping.rq(v.rq);
476489
} else if (exists<Record<string, any>>(v.sq) && v.sq.enabled === true) {
477490
quantizer = ConfigMapping.sq(v.sq);
478491
} else {
@@ -508,6 +521,19 @@ class ConfigMapping {
508521
type: 'bq',
509522
};
510523
}
524+
static rq(v?: Record<string, unknown>): RQConfig | undefined {
525+
if (v === undefined) throw new WeaviateDeserializationError('RQ was not returned by Weaviate');
526+
if (!exists<boolean>(v.enabled))
527+
throw new WeaviateDeserializationError('RQ enabled was not returned by Weaviate');
528+
if (v.enabled === false) return undefined;
529+
const bits = v.bits === undefined ? 6 : (v.bits as number);
530+
const rescoreLimit = v.rescoreLimit === undefined ? 20 : (v.rescoreLimit as number);
531+
return {
532+
bits,
533+
rescoreLimit,
534+
type: 'rq',
535+
};
536+
}
511537
static sq(v?: Record<string, unknown>): SQConfig | undefined {
512538
if (v === undefined) throw new WeaviateDeserializationError('SQ was not returned by Weaviate');
513539
if (!exists<boolean>(v.enabled))

src/collections/configure/parsing.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import {
33
BQConfigUpdate,
44
PQConfigCreate,
55
PQConfigUpdate,
6+
RQConfigCreate,
7+
RQConfigUpdate,
68
SQConfigCreate,
79
SQConfigUpdate,
810
} from './types/index.js';
@@ -13,7 +15,9 @@ type QuantizerConfig =
1315
| BQConfigCreate
1416
| BQConfigUpdate
1517
| SQConfigCreate
16-
| SQConfigUpdate;
18+
| SQConfigUpdate
19+
| RQConfigCreate
20+
| RQConfigUpdate;
1721

1822
export class QuantizerGuards {
1923
static isPQCreate(config?: QuantizerConfig): config is PQConfigCreate {
@@ -34,6 +38,12 @@ export class QuantizerGuards {
3438
static isSQUpdate(config?: QuantizerConfig): config is SQConfigUpdate {
3539
return (config as SQConfigUpdate)?.type === 'sq';
3640
}
41+
static isRQCreate(config?: QuantizerConfig): config is RQConfigCreate {
42+
return (config as RQConfigCreate)?.type === 'rq';
43+
}
44+
static isRQUpdate(config?: QuantizerConfig): config is RQConfigUpdate {
45+
return (config as RQConfigUpdate)?.type === 'rq';
46+
}
3747
}
3848

3949
export function parseWithDefault<D>(value: D | undefined, defaultValue: D): D {

src/collections/configure/types/vectorIndex.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
PQConfig,
55
PQEncoderDistribution,
66
PQEncoderType,
7+
RQConfig,
78
SQConfig,
89
VectorDistance,
910
VectorIndexConfigDynamic,
@@ -17,6 +18,13 @@ export type QuantizerRecursivePartial<T> = {
1718
[P in keyof T]: P extends 'type' ? T[P] : RecursivePartial<T[P]> | undefined;
1819
};
1920

21+
export type RQConfigCreate = QuantizerRecursivePartial<RQConfig>;
22+
23+
export type RQConfigUpdate = {
24+
rescoreLimit?: number;
25+
type: 'rq';
26+
}
27+
2028
export type PQConfigCreate = QuantizerRecursivePartial<PQConfig>;
2129

2230
export type PQConfigUpdate = {
@@ -59,7 +67,7 @@ export type VectorIndexConfigHNSWUpdate = {
5967
ef?: number;
6068
filterStrategy?: VectorIndexFilterStrategy;
6169
flatSearchCutoff?: number;
62-
quantizer?: PQConfigUpdate | BQConfigUpdate | SQConfigUpdate;
70+
quantizer?: PQConfigUpdate | BQConfigUpdate | SQConfigUpdate | RQConfigUpdate;
6371
vectorCacheMaxObjects?: number;
6472
};
6573

@@ -131,7 +139,7 @@ export type VectorIndexConfigHNSWCreateOptions = {
131139
/** The maximum number of connections. Default is 64. */
132140
maxConnections?: number;
133141
/** The quantizer configuration to use. Use `vectorIndex.quantizer.bq` or `vectorIndex.quantizer.pq` to make one. */
134-
quantizer?: PQConfigCreate | BQConfigCreate | SQConfigCreate;
142+
quantizer?: PQConfigCreate | BQConfigCreate | SQConfigCreate | RQConfigCreate;
135143
/** Whether to skip the index. Default is false. */
136144
skip?: boolean;
137145
/** The maximum number of objects to cache in the vector cache. Default is 1000000000000. */

0 commit comments

Comments
 (0)