Metadata filtering directly reduces the search space before the vector similarity computation, significantly improving query latency in multi-tenant RAG systems. HNSW index parameters then fine-tune the balance between search quality (recall) and latency within the potentially reduced candidate set.
Here's how these elements interact:
1. Metadata Filtering (Pre-filtering)
This is crucial for multi-tenancy as it restricts vector search to only the data relevant to a specific tenant or context. By applying filters before the HNSW index traversal, the system operates on a much smaller subset of vectors, drastically reducing the number of distance calculations.
Mechanism: The vector database first applies a boolean or range filter on metadata fields (e.g., tenant_id, document_type). Only vectors whose associated metadata matches the filter criteria are considered for the subsequent vector search.
Impact on Latency: Directly proportional to the reduction in search space. A highly selective filter yields faster queries.
Example: Using a tenant_id filter in Qdrant:
```python
from qdrant_client import QdrantClient, models
client = QdrantClient(host="localhost", port=6333)
query_vector = [0.1, 0.2, ..., 0.9]
search_result = client.query(
collection_name="my_rag_collection",
query_vector=query_vector,
query_filter=models.Filter(
must=[
models.FieldCondition(
key="tenant_id",
match=models.MatchValue(value="tenant_alpha")
)
]
),
limit=10
)
```
2. HNSW Index Parameters (Post-filtering or Full-index Search)
Hierarchical Navigable Small World (HNSW) is a graph-based Approximate Nearest Neighbor (ANN) algorithm. Its parameters control the trade-off between index build time, memory usage, search speed, and recall.
M (Maximum number of connections per node): Determines the number of neighbors each node connects to in the graph layers. Higher M creates a denser graph, improving recall but increasing index size and search time.
efConstruction (Construction time search scope): Controls the size of the dynamic list of nearest neighbors during index construction. A higher value leads to a more accurate, but slower, index build.
efSearch (Query time search scope): Defines the size of the dynamic list of nearest neighbors maintained during query execution. Higher efSearch improves recall at the cost of increased query latency.
| Parameter | Description | Impact on Query Latency | Impact on Recall |
| :------------- | :---------------------------------------------- | :---------------------- | :--------------- |
| M | Max connections per node | Higher M = Slower | Higher |
| efConstruction | Search scope during index build | N/A (build time) | Higher |
| efSearch | Search scope during query | Higher efSearch = Slower | Higher |
* Example: Configuring HNSW for a collection in Weaviate:
```python
import weaviate
from weaviate.collections import CollectionConfig, HnswConfig
client = weaviate.Client("http://localhost:8080")
client.collections.create(
name="MyRAGCollection",
vectorizer_config=client.collections.config.Configure.Vectorizer.text2vec_openai(),
hnsw_config=HnswConfig(
ef_construction=128,
max_connections=32, # This is 'M'
dynamic_ef_min=64,
dynamic_ef_max=128,
dynamic_ef_factor=8
)
)
```
Gotcha: While metadata filtering is powerful, ensure your filtering fields are properly indexed (e.g., B-tree or hash indexes) within the vector database. Unindexed filters can degrade performance by requiring full table scans on metadata, negating the benefits of reduced vector search space.