Skip to main content
Weaviate Docs (migrated from docs.weaviate.io) Docs

Search documentation

Type to search this documentation.

On this pageOverview

Rotational Quantization (RQ)

Rotational quantization (RQ) is a fast vector compression technique that offers significant performance benefits. Three RQ variants are available in Weaviate:

  • 8-bit RQ: Up to 4x compression while retaining almost perfect recall (98-99% on most datasets). Recommended for most use cases.
  • 4-bit RQ: Up to 8x compression, roughly half the size of 8-bit RQ, and it depends on rescoring to reach comparable recall. Available for the hnsw index only.
  • 1-bit RQ: Close to 32x compression as dimensionality increases with moderate recall across various datasets.

8-bit RQ provides up-to 4x compression while maintaining 98-99% recall in internal testing. It is generally recommended for most use cases as the default quantization techniques.

RQ can be enabled at collection creation time through the collection definition:

Python
from weaviate.classes.config import Configure, Property, DataTypeclient.collections.create(    name="MyCollection",    vector_config=Configure.Vectors.text2vec_openai(        quantizer=Configure.VectorIndex.Quantizer.rq()    ),    properties=[        Property(name="title", data_type=DataType.TEXT),    ],)
JavaScript/TypeScript
import weaviate, { configure } from 'weaviate-client';
Go
// Define the configuration for RQ. Setting 'enabled' to truerq_config := map[string]interface{}{  "enabled": true,}// Define the class schemaclass := &models.Class{  Class:      className,  Vectorizer: "text2vec-openai",  // Assign the RQ configuration to the vector index config  VectorIndexConfig: map[string]interface{}{    "rq": rq_config,  },}// Create the collection in Weaviateerr = client.Schema().ClassCreator().  WithClass(class).  Do(context.Background())
Java
client.collections.create("MyCollection",    col -> col.vectorConfig(VectorConfig.text2vecTransformers(vc -> vc        .quantization(Quantization.rq())    )).properties(Property.text("title")));
C#
await client.Collections.Create(    new CollectionCreateParams    {        Name = "MyCollection",        Properties = [Property.Text("title")],        VectorConfig = Configure.Vector(            "default",            v => v.Text2VecTransformers(),            index: new VectorIndex.HNSW            {                Quantizer = new VectorIndex.Quantizers.RQ(),            }        ),    });

RQ can also be enabled for an existing collection by updating the collection definition:

Python
from weaviate.classes.config import Reconfigure

collection = client.collections.use("MyCollection")
collection.config.update(
    vector_config=Reconfigure.Vectors.update(
        name="default",
        vector_index_config=Reconfigure.VectorIndex.hnsw(
            quantizer=Reconfigure.VectorIndex.Quantizer.rq(),
        ),
    )
)
JS/TS
import { reconfigure } from 'weaviate-client';

const collection = client.collections.use("MyCollection")
Java
CollectionHandle<Map<String, Object>> collection =
    client.collections.use("MyCollection");
collection.config.update(c -> c.vectorConfig(VectorConfig
    .text2vecTransformers(vc -> vc.quantization(Quantization.rq()))));
C#
await collection.Config.Update(c =>
{
    var vectorConfig = c.VectorConfig["default"];
    vectorConfig.VectorIndexConfig.UpdateHNSW(h =>
        h.Quantizer = new VectorIndex.Quantizers.RQ()
    );
});
Go
// Get the existing collection configuration
class, err := client.Schema().ClassGetter().
  WithClassName(className).Do(context.Background())

if err != nil {
  log.Fatalf("get class for vec idx cfg update: %v", err)
}

// Get the current vector index configuration
cfg := class.VectorIndexConfig.(map[string]interface{})

// Add RQ configuration to enable quantization
cfg["rq"] = map[string]interface{}{
  "enabled": true,
}

// Update the class configuration
class.VectorIndexConfig = cfg

// Apply the updated configuration to the collection
err = client.Schema().ClassUpdater().
  WithClass(class).Do(context.Background())

if err != nil {
  log.Fatalf("update class to use rq: %v", err)
}

4-bit RQ stores each dimension in 4 bits instead of 8, so a compressed vector is about half the size of the 8-bit equivalent and roughly 8x smaller than the uncompressed vector. It sits between 8-bit RQ and 1-bit RQ: it trades some accuracy in the compressed distance calculation for a smaller index, and it depends more heavily on rescoring against the uncompressed vectors to recover that accuracy.

4-bit RQ can be enabled at collection creation time through the collection definition:

Python
from weaviate.classes.config import Configure, Property, DataTypeclient.collections.create(    name="MyCollection",    vector_config=Configure.Vectors.text2vec_openai(        quantizer=Configure.VectorIndex.Quantizer.rq(            bits=4,            rescore_limit=20,  # Optional: Number of candidates to fetch before rescoring        )    ),    properties=[        Property(name="title", data_type=DataType.TEXT),    ],)
JavaScript/TypeScript
import weaviate, { configure } from 'weaviate-client';
Go
// Define the configuration for RQ. 'bits' set to 4 requires an hnsw indexrq_config := map[string]interface{}{  "enabled":      true,  "bits":         4,  "rescoreLimit": 20, // Optional: Number of candidates to fetch before rescoring}// Define the class schemaclass := &models.Class{  Class:      className,  Vectorizer: "text2vec-openai",  // Assign the RQ configuration to the vector index config  VectorIndexConfig: map[string]interface{}{    "rq": rq_config,  },}// Create the collection in Weaviateerr = client.Schema().ClassCreator().  WithClass(class).  Do(context.Background())
Java
client.collections.create("MyCollection",    col -> col.vectorConfig(VectorConfig.text2vecTransformers(vc -> vc        .quantization(Quantization.rq(q -> q.bits(4)))    )).properties(Property.text("title")));
C#
await client.Collections.Create(    new CollectionCreateParams    {        Name = "MyCollection",        Properties = [Property.Text("title")],        VectorConfig = Configure.Vector(            "default",            v => v.Text2VecTransformers(),            index: new VectorIndex.HNSW            {                Quantizer = new VectorIndex.Quantizers.RQ                {                    Bits = 4,                    RescoreLimit = 20, // Optional: Number of candidates to fetch before rescoring                },            }        ),    });

4-bit RQ can also be enabled for an existing collection that is not yet compressed, by updating the collection definition. Weaviate re-encodes the existing vectors in the background.

Python
from weaviate.classes.config import Reconfigure

collection = client.collections.use("MyCollection")
collection.config.update(
    vector_config=Reconfigure.Vectors.update(
        name="default",
        vector_index_config=Reconfigure.VectorIndex.hnsw(
            quantizer=Reconfigure.VectorIndex.Quantizer.rq(
                bits=4,
                rescore_limit=20,
            ),
        ),
    )
)
Go
// Get the existing collection configuration
class, err := client.Schema().ClassGetter().
  WithClassName(className).Do(context.Background())

if err != nil {
  log.Fatalf("get class for vec idx cfg update: %v", err)
}

// Get the current vector index configuration
cfg := class.VectorIndexConfig.(map[string]interface{})

// Add RQ configuration to enable 4-bit quantization
cfg["rq"] = map[string]interface{}{
  "enabled":      true,
  "bits":         4,
  "rescoreLimit": 20, // Optional: Number of candidates to fetch before rescoring
}

// Update the class configuration
class.VectorIndexConfig = cfg

// Apply the updated configuration to the collection
err = client.Schema().ClassUpdater().
  WithClass(class).Do(context.Background())

if err != nil {
  log.Fatalf("update class to use rq: %v", err)
}
Java
CollectionHandle<Map<String, Object>> collection =
    client.collections.use("MyCollection");
collection.config
    .update(c -> c.vectorConfig(VectorConfig.text2vecTransformers(
        vc -> vc.quantization(Quantization.rq(q -> q.bits(4))))));
C#
await collection.Config.Update(c =>
{
    var vectorConfig = c.VectorConfig["default"];
    vectorConfig.VectorIndexConfig.UpdateHNSW(h =>
        h.Quantizer = new VectorIndex.Quantizers.RQ { Bits = 4, RescoreLimit = 20 }
    );
});

1-bit RQ is an quantization technique that provides close to 32x compression as dimensionality increases. 1-bit RQ serves as a more robust and accurate alternative to BQ with only a slight performance trade-off. While more performant than PQ in terms of encoding time and distance calculations, 1-bit RQ typically offers slightly lower recall than well-tuned PQ.

RQ can be enabled at collection creation time through the collection definition:

Python
from weaviate.classes.config import Configure, Property, DataTypeclient.collections.create(    name="MyCollection",    vector_config=Configure.Vectors.text2vec_openai(        quantizer=Configure.VectorIndex.Quantizer.rq(bits=1)    ),    properties=[        Property(name="title", data_type=DataType.TEXT),    ],)
JavaScript/TypeScript
import weaviate, { configure } from 'weaviate-client';
Go
// Define the configuration for RQ. Setting 'enabled' to truerq_config := map[string]interface{}{  "enabled": true,  "bits":    1,}// Define the class schemaclass := &models.Class{  Class:      className,  Vectorizer: "text2vec-openai",  // Assign the RQ configuration to the vector index config  VectorIndexConfig: map[string]interface{}{    "rq": rq_config,  },}// Create the collection in Weaviateerr = client.Schema().ClassCreator().  WithClass(class).  Do(context.Background())
Java
client.collections.create("MyCollection",    col -> col.vectorConfig(VectorConfig.text2vecTransformers(vc -> vc        .quantization(Quantization.rq(q -> q.bits(1)))    )).properties(Property.text("title")));
C#
await client.Collections.Create(    new CollectionCreateParams    {        Name = "MyCollection",        Properties = [Property.Text("title")],        VectorConfig = Configure.Vector(            "default",            v => v.Text2VecTransformers(),            index: new VectorIndex.HNSW            {                Quantizer = new VectorIndex.Quantizers.RQ { Bits = 1 },            }        ),    });

RQ can also be enabled for an existing collection by updating the collection definition:

Python
from weaviate.classes.config import Reconfigure

collection = client.collections.use("MyCollection")
collection.config.update(
    vector_config=Reconfigure.Vectors.update(
        name="default",
        vector_index_config=Reconfigure.VectorIndex.hnsw(
            quantizer=Reconfigure.VectorIndex.Quantizer.rq(bits=1),
        ),
    )
)
JS/TS
import { reconfigure } from 'weaviate-client';

const collection = client.collections.use("MyCollection")
Go
// Get the existing collection configuration
class, err := client.Schema().ClassGetter().
  WithClassName(className).Do(context.Background())

if err != nil {
  log.Fatalf("get class for vec idx cfg update: %v", err)
}

// Get the current vector index configuration
cfg := class.VectorIndexConfig.(map[string]interface{})

// Add RQ configuration to enable scalar quantization
cfg["rq"] = map[string]interface{}{
  "enabled": true,
  "bits":    1,
}

// Update the class configuration
class.VectorIndexConfig = cfg

// Apply the updated configuration to the collection
err = client.Schema().ClassUpdater().
  WithClass(class).Do(context.Background())

if err != nil {
  log.Fatalf("update class to use rq: %v", err)
}
Java
CollectionHandle<Map<String, Object>> collection =
    client.collections.use("MyCollection");
collection.config
    .update(c -> c.vectorConfig(VectorConfig.text2vecTransformers(
        vc -> vc.quantization(Quantization.rq(q -> q.bits(1))))));
C#
await collection.Config.Update(c =>
{
    var vectorConfig = c.VectorConfig["default"];
    vectorConfig.VectorIndexConfig.UpdateHNSW(h =>
        h.Quantizer = new VectorIndex.Quantizers.RQ { Bits = 1 }
    );
});

To tune RQ, use these quantization and vector index parameters:

Parameter Type Default Details
rq: bits integer 8 The number of bits used to quantize each data point. Value can be 8, 4 or 1, but not every index type accepts all three. The hnsw index type accepts 8, 4 and 1. The flat index type accepts only 8 and 1. The hfresh index type accepts only 1.

This parameter is fixed once RQ is enabled and cannot be changed afterwards.

Learn more about 8-bit, 4-bit and 1-bit RQ.
rq: rescoreLimit integer 20 (hnsw, 8-bit and 4-bit)
512 (hnsw, 1-bit)
-1 (flat)
The minimum number of candidates to fetch before rescoring. Mutable at any time.

The default depends on the vector index type, and under hnsw also on bits: 20 for 8-bit and 4-bit RQ, and 512 for 1-bit RQ. Under the flat index type the default is -1, which lets Weaviate pick the limit.

The Java client sends this parameter under a field name that Weaviate does not read, so values set from that client are ignored and the server default applies.

These defaults apply to the hnsw and flat index types. For the HFresh index, see HFresh index parameters.
rq : cache boolean false Whether to cache the vectors in memory.
(only when using the flat vector index type)
vectorCacheMaxObjects integer 1e12 Maximum number of objects in the memory cache. By default, this limit is set to one trillion (1e12) objects when a new collection is created. For sizing recommendations, see Vector cache considerations.

RQ supports the cosine, dot and l2-squared distance metrics. Other distance metrics are not supported.

Python
from weaviate.classes.config import Configure, Property, DataTypeclient.collections.create(    name="MyCollection",    vector_config=Configure.Vectors.text2vec_openai(        quantizer=Configure.VectorIndex.Quantizer.rq(            bits=8,  # Optional: Number of bits            rescore_limit=20,  # Optional: Number of candidates to fetch before rescoring            cache=True,  # Optional: Enable caching for flat index (enabled by default for for HNSW)        ),        vector_index_config=Configure.VectorIndex.flat(            vector_cache_max_objects=100000,  # Optional: Maximum number of objects in the memory cache        ),    ),    properties=[        Property(name="title", data_type=DataType.TEXT),    ],)
JavaScript/TypeScript
import weaviate, { configure } from 'weaviate-client';
Go
// Define a custom configuration for RQrq_with_options_config := map[string]interface{}{  "enabled":      true,  "bits":         8,  // Optional: Number of bits  "rescoreLimit": 20, // Optional: Number of candidates to fetch before rescoring}// Define the class schema with the custom RQ config and other HNSW settingsclass_with_options := &models.Class{  Class:      className,  Vectorizer: "text2vec-openai",  VectorIndexConfig: map[string]interface{}{    "rq": rq_with_options_config,  },}// Create the collection in Weaviateerr = client.Schema().ClassCreator().  WithClass(class_with_options).  Do(context.Background())
Java
client.collections.create("MyCollection",    col -> col.vectorConfig(VectorConfig.text2vecTransformers(vc -> vc        .quantization(Quantization.rq(q -> q.bits(8) // Optional: Number of bits            .rescoreLimit(20) // Optional: Number of candidates to fetch before rescoring        ))    )).properties(Property.text("title")));
C#
await client.Collections.Create(    new CollectionCreateParams    {        Name = "MyCollection",        Properties = [Property.Text("title")],        VectorConfig = Configure.Vector(            "default",            v => v.Text2VecTransformers(),            index: new VectorIndex.HNSW            {                Quantizer = new VectorIndex.Quantizers.RQ                {                    Bits = 8, // Optional: Number of bits                    RescoreLimit = 20, // Optional: Number of candidates to fetch before rescoring                },            }        ),    });

Collections can have multiple named vectors. The vectors in a collection can have their own configurations, and compression must be enabled independently for each vector. Every vector is independent and can use PQ, BQ, RQ, SQ, or no compression.

Multi-vector embeddings (ColBERT, ColPali, etc.)

Section titled “Multi-vector embeddings (ColBERT, ColPali, etc.)”

Multi-vector embeddings (implemented through models like ColBERT, ColPali, or ColQwen) represent each object or query using multiple vectors instead of a single vector. Just like with single vectors, multi-vectors support PQ, BQ, RQ, SQ, or no compression.

During the initial search phase, compressed vectors are used for efficiency. However, when computing the MaxSim operation, uncompressed vectors are utilized to ensure more precise similarity calculations. This approach balances the benefits of compression for search efficiency with the accuracy of uncompressed vectors during final scoring.

Have a question or feedback? Here's how to reach us.

Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu