Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ env:
WEAVIATE_129: 1.29.8
WEAVIATE_130: 1.30.7
WEAVIATE_131: 1.31.0
WEAVIATE_132: 1.32.0-rc.1

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
Expand Down Expand Up @@ -48,9 +49,11 @@ jobs:
{ node: "22.x", weaviate: $WEAVIATE_127},
{ node: "22.x", weaviate: $WEAVIATE_128},
{ node: "22.x", weaviate: $WEAVIATE_129},
{ node: "18.x", weaviate: $WEAVIATE_130},
{ node: "20.x", weaviate: $WEAVIATE_130},
{ node: "22.x", weaviate: $WEAVIATE_130}
{ node: "22.x", weaviate: $WEAVIATE_130},
{ node: "22.x", weaviate: $WEAVIATE_131},
{ node: "18.x", weaviate: $WEAVIATE_132},
{ node: "20.x", weaviate: $WEAVIATE_132},
{ node: "22.x", weaviate: $WEAVIATE_132}
]
steps:
- uses: actions/checkout@v3
Expand Down
4 changes: 4 additions & 0 deletions src/collections/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
CollectionConfigUpdate,
PQConfig,
QuantizerConfig,
RQConfig,
SQConfig,
VectorIndexConfig,
VectorIndexConfigDynamic,
Expand Down Expand Up @@ -192,6 +193,9 @@ export class Quantizer {
static isSQ(config?: QuantizerConfig): config is SQConfig {
return config?.type === 'sq';
}
static isRQ(config?: QuantizerConfig): config is RQConfig {
return config?.type === 'rq';
}
}

export const configGuards = {
Expand Down
28 changes: 24 additions & 4 deletions src/collections/config/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ import {
VectorIndexConfigHNSW,
} from './types/index.js';

const fail = (msg: string) => {
throw new Error(msg);
};

describe('Testing of the collection.config namespace', () => {
let client: WeaviateClient;

Expand Down Expand Up @@ -210,6 +206,30 @@ describe('Testing of the collection.config namespace', () => {
expect(config.vectorizers.default.vectorizer.name).toEqual('none');
});

requireAtLeast(1, 32, 0).it('should be able to get the config of a collection with hnsw-rq', async () => {
const collectionName = 'TestCollectionConfigGetHNSWPlusRQ';
const collection = await client.collections.create({
name: collectionName,
vectorizers: weaviate.configure.vectorizer.none({
vectorIndexConfig: weaviate.configure.vectorIndex.hnsw({
quantizer: weaviate.configure.vectorIndex.quantizer.rq(),
}),
}),
});
const config = await collection.config.get();

const vectorIndexConfig = config.vectorizers.default.indexConfig as VectorIndexConfigHNSW;
expect(config.name).toEqual(collectionName);
expect(config.generative).toBeUndefined();
expect(config.reranker).toBeUndefined();
expect(vectorIndexConfig).toBeDefined();
expect(vectorIndexConfig.quantizer).toBeDefined();
expect(vectorIndexConfig.quantizer?.type).toEqual('rq');
expect(config.vectorizers.default.indexType).toEqual('hnsw');
expect(config.vectorizers.default.properties).toBeUndefined();
expect(config.vectorizers.default.vectorizer.name).toEqual('none');
});

it('should be able to get the config of a collection with hnsw-bq', async () => {
const collectionName = 'TestCollectionConfigGetHNSWPlusBQ';
const query = () =>
Expand Down
10 changes: 8 additions & 2 deletions src/collections/config/types/vectorIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type VectorIndexConfigHNSW = {
filterStrategy: VectorIndexFilterStrategy;
flatSearchCutoff: number;
maxConnections: number;
quantizer: PQConfig | BQConfig | SQConfig | undefined;
quantizer: PQConfig | BQConfig | SQConfig | RQConfig | undefined;
skip: boolean;
vectorCacheMaxObjects: number;
type: 'hnsw';
Expand Down Expand Up @@ -61,6 +61,12 @@ export type PQConfig = {
type: 'pq';
};

export type RQConfig = {
bits?: number;
rescoreLimit?: number;
type: 'rq';
};

export type PQEncoderConfig = {
type: PQEncoderType;
distribution: PQEncoderDistribution;
Expand All @@ -77,4 +83,4 @@ export type VectorIndexFilterStrategy = 'sweeping' | 'acorn';

export type VectorIndexConfig = VectorIndexConfigHNSW | VectorIndexConfigFlat | VectorIndexConfigDynamic;

export type QuantizerConfig = PQConfig | BQConfig | SQConfig;
export type QuantizerConfig = PQConfig | BQConfig | SQConfig | RQConfig;
28 changes: 27 additions & 1 deletion src/collections/config/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
PQEncoderType,
PropertyConfig,
PropertyVectorizerConfig,
RQConfig,
ReferenceConfig,
ReplicationConfig,
Reranker,
Expand Down Expand Up @@ -182,6 +183,16 @@ export const parseVectorIndex = (module: ModuleConfig<VectorIndexType, VectorInd
},
};
}
if (QuantizerGuards.isRQCreate(quantizer)) {
const { type, ...quant } = quantizer;
return {
...conf,
rq: {
...quant,
enabled: true,
},
};
}
};

export const parseVectorizerConfig = (config?: VectorizerConfig): any => {
Expand Down Expand Up @@ -468,11 +479,13 @@ class ConfigMapping {
throw new WeaviateDeserializationError(
'Vector index vector cache max objects was not returned by Weaviate'
);
let quantizer: PQConfig | BQConfig | SQConfig | undefined;
let quantizer: PQConfig | BQConfig | SQConfig | RQConfig | undefined;
if (exists<Record<string, any>>(v.pq) && v.pq.enabled === true) {
quantizer = ConfigMapping.pq(v.pq);
} else if (exists<Record<string, any>>(v.bq) && v.bq.enabled === true) {
quantizer = ConfigMapping.bq(v.bq);
} else if (exists<Record<string, any>>(v.rq) && v.rq.enabled === true) {
quantizer = ConfigMapping.rq(v.rq);
} else if (exists<Record<string, any>>(v.sq) && v.sq.enabled === true) {
quantizer = ConfigMapping.sq(v.sq);
} else {
Expand Down Expand Up @@ -508,6 +521,19 @@ class ConfigMapping {
type: 'bq',
};
}
static rq(v?: Record<string, unknown>): RQConfig | undefined {
if (v === undefined) throw new WeaviateDeserializationError('RQ was not returned by Weaviate');
if (!exists<boolean>(v.enabled))
throw new WeaviateDeserializationError('RQ enabled was not returned by Weaviate');
if (v.enabled === false) return undefined;
const bits = v.bits === undefined ? 6 : (v.bits as number);
const rescoreLimit = v.rescoreLimit === undefined ? 20 : (v.rescoreLimit as number);
return {
bits,
rescoreLimit,
type: 'rq',
};
}
static sq(v?: Record<string, unknown>): SQConfig | undefined {
if (v === undefined) throw new WeaviateDeserializationError('SQ was not returned by Weaviate');
if (!exists<boolean>(v.enabled))
Expand Down
12 changes: 11 additions & 1 deletion src/collections/configure/parsing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
BQConfigUpdate,
PQConfigCreate,
PQConfigUpdate,
RQConfigCreate,
RQConfigUpdate,
SQConfigCreate,
SQConfigUpdate,
} from './types/index.js';
Expand All @@ -13,7 +15,9 @@ type QuantizerConfig =
| BQConfigCreate
| BQConfigUpdate
| SQConfigCreate
| SQConfigUpdate;
| SQConfigUpdate
| RQConfigCreate
| RQConfigUpdate;

export class QuantizerGuards {
static isPQCreate(config?: QuantizerConfig): config is PQConfigCreate {
Expand All @@ -34,6 +38,12 @@ export class QuantizerGuards {
static isSQUpdate(config?: QuantizerConfig): config is SQConfigUpdate {
return (config as SQConfigUpdate)?.type === 'sq';
}
static isRQCreate(config?: QuantizerConfig): config is RQConfigCreate {
return (config as RQConfigCreate)?.type === 'rq';
}
static isRQUpdate(config?: QuantizerConfig): config is RQConfigUpdate {
return (config as RQConfigUpdate)?.type === 'rq';
}
}

export function parseWithDefault<D>(value: D | undefined, defaultValue: D): D {
Expand Down
12 changes: 10 additions & 2 deletions src/collections/configure/types/vectorIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
PQConfig,
PQEncoderDistribution,
PQEncoderType,
RQConfig,
SQConfig,
VectorDistance,
VectorIndexConfigDynamic,
Expand All @@ -17,6 +18,13 @@ export type QuantizerRecursivePartial<T> = {
[P in keyof T]: P extends 'type' ? T[P] : RecursivePartial<T[P]> | undefined;
};

export type RQConfigCreate = QuantizerRecursivePartial<RQConfig>;

export type RQConfigUpdate = {
rescoreLimit?: number;
type: 'rq';
};

export type PQConfigCreate = QuantizerRecursivePartial<PQConfig>;

export type PQConfigUpdate = {
Expand Down Expand Up @@ -59,7 +67,7 @@ export type VectorIndexConfigHNSWUpdate = {
ef?: number;
filterStrategy?: VectorIndexFilterStrategy;
flatSearchCutoff?: number;
quantizer?: PQConfigUpdate | BQConfigUpdate | SQConfigUpdate;
quantizer?: PQConfigUpdate | BQConfigUpdate | SQConfigUpdate | RQConfigUpdate;
vectorCacheMaxObjects?: number;
};

Expand Down Expand Up @@ -131,7 +139,7 @@ export type VectorIndexConfigHNSWCreateOptions = {
/** The maximum number of connections. Default is 64. */
maxConnections?: number;
/** The quantizer configuration to use. Use `vectorIndex.quantizer.bq` or `vectorIndex.quantizer.pq` to make one. */
quantizer?: PQConfigCreate | BQConfigCreate | SQConfigCreate;
quantizer?: PQConfigCreate | BQConfigCreate | SQConfigCreate | RQConfigCreate;
/** Whether to skip the index. Default is false. */
skip?: boolean;
/** The maximum number of objects to cache in the vector cache. Default is 1000000000000. */
Expand Down
42 changes: 36 additions & 6 deletions src/collections/configure/vectorIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
BQConfigUpdate,
PQConfigCreate,
PQConfigUpdate,
RQConfigCreate,
RQConfigUpdate,
SQConfigCreate,
SQConfigUpdate,
VectorIndexConfigDynamicCreate,
Expand Down Expand Up @@ -65,7 +67,6 @@ const configure = {
? {
...rest,
distance: distanceMetric,
quantizer: rest.quantizer,
}
: undefined,
};
Expand Down Expand Up @@ -111,12 +112,26 @@ const configure = {
type: 'bq',
};
},
/**
* Create an object of type `RQConfigCreate` to be used when defining the quantizer configuration of a vector index.
*
* @param {number} [options.bits] Number of bits to user per vector element.
* @param {number} [options.rescoreLimit] The rescore limit. Default is 1000.
* @returns {RQConfigCreate} The object of type `RQConfigCreate`.
*/
rq: (options?: { bits?: number; rescoreLimit?: number }): RQConfigCreate => {
return {
bits: options?.bits,
rescoreLimit: options?.rescoreLimit,
type: 'rq',
};
},
/**
* Create an object of type `PQConfigCreate` to be used when defining the quantizer configuration of a vector index.
*
* @param {boolean} [options.bitCompression] Whether to use bit compression.
* @param {number} [options.centroids] The number of centroids[.
* @param {PQEncoderDistribution} ]options.encoder.distribution The encoder distribution.
* @param {number} [options.centroids] The number of centroids.
* @param {PQEncoderDistribution} [options.encoder.distribution] The encoder distribution.
* @param {PQEncoderType} [options.encoder.type] The encoder type.
* @param {number} [options.segments] The number of segments.
* @param {number} [options.trainingLimit] The training limit.
Expand Down Expand Up @@ -194,7 +209,7 @@ const reconfigure = {
* @param {number} [options.ef] The ef parameter. Default is -1.
* @param {VectorIndexFilterStrategy} [options.filterStrategy] The filter strategy. Default is 'sweeping'.
* @param {number} [options.flatSearchCutoff] The flat search cutoff. Default is 40000.
* @param {PQConfigUpdate | BQConfigUpdate} [options.quantizer] The quantizer configuration to use. Use `vectorIndex.quantizer.bq` or `vectorIndex.quantizer.pq` to make one.
* @param {PQConfigUpdate | BQConfigUpdate | SQConfigUpdate | RQConfigUpdate} [options.quantizer] The quantizer configuration to use. Use `vectorIndex.quantizer.bq` or `vectorIndex.quantizer.pq` to make one.
* @param {number} [options.vectorCacheMaxObjects] The maximum number of objects to cache in the vector cache. Default is 1000000000000.
* @returns {ModuleConfig<'hnsw', VectorIndexConfigHNSWUpdate>} The configuration object.
*/
Expand All @@ -205,7 +220,7 @@ const reconfigure = {
ef?: number;
filterStrategy?: VectorIndexFilterStrategy;
flatSearchCutoff?: number;
quantizer?: PQConfigUpdate | BQConfigUpdate | SQConfigUpdate;
quantizer?: PQConfigUpdate | BQConfigUpdate | SQConfigUpdate | RQConfigUpdate;
vectorCacheMaxObjects?: number;
}): ModuleConfig<'hnsw', VectorIndexConfigHNSWUpdate> => {
return {
Expand All @@ -225,14 +240,29 @@ const reconfigure = {
*
* @param {boolean} [options.cache] Whether to cache the quantizer.
* @param {number} [options.rescoreLimit] The new rescore limit.
* @returns {BQConfigCreate} The configuration object.
* @returns {BQConfigUpdate} The configuration object.
*/
bq: (options?: { cache?: boolean; rescoreLimit?: number }): BQConfigUpdate => {
return {
...options,
type: 'bq',
};
},
/**
* Create an object of type `RQConfigUpdate` to be used when updating the quantizer configuration of a vector index.
*
* NOTE: If the vector index already has a quantizer configured, you cannot change its quantizer type; only its values.
* So if you want to change the quantizer type, you must recreate the collection.
*
* @param {number} [options.rescoreLimit] The new rescore limit.
* @returns {BQConfigUpdate} The configuration object.
*/
rq: (options?: { rescoreLimit?: number }): RQConfigUpdate => {
return {
...options,
type: 'rq',
};
},
/**
* Create an object of type `PQConfigUpdate` to be used when updating the quantizer configuration of a vector index.
*
Expand Down
Loading