mirror of
https://github.com/qdrant/landing_page.git
synced 2026-10-02 17:38:31 +02:00
day 2 pitstop updated
This commit is contained in:
@@ -72,10 +72,10 @@ Test different HNSW configurations to find what works best:
|
||||
```python
|
||||
# Test configurations
|
||||
configs = [
|
||||
{"name": "fast_initial_upload", "m": 0, "ef_construct": 100},
|
||||
{"name": "memory_optimized", "m": 8, "ef_construct": 100},
|
||||
{"name": "balanced", "m": 16, "ef_construct": 200},
|
||||
{"name": "high_quality", "m": 32, "ef_construct": 400},
|
||||
{"name": "fast_initial_upload", "m": 0, "ef_construct": 100}, # m=0 = ingest-only
|
||||
{"name": "memory_optimized", "m": 8, "ef_construct": 100}, # m=8 = lower RAM
|
||||
{"name": "balanced", "m": 16, "ef_construct": 200}, # m=16 = balanced
|
||||
{"name": "high_quality", "m": 32, "ef_construct": 400}, # m=32 = higher recall, slower build
|
||||
]
|
||||
|
||||
for config in configs:
|
||||
@@ -90,9 +90,6 @@ for config in configs:
|
||||
m=config["m"], ef_construct=config["ef_construct"], full_scan_threshold=10
|
||||
),
|
||||
optimizers_config=models.OptimizersConfigDiff(indexing_threshold=0),
|
||||
strict_mode_config=models.StrictModeConfig(
|
||||
unindexed_filtering_retrieve=True, unindexed_filtering_update=True
|
||||
),
|
||||
)
|
||||
print(f"Created collection: {collection_name}")
|
||||
```
|
||||
@@ -103,7 +100,10 @@ Measure upload performance for each configuration:
|
||||
|
||||
```python
|
||||
def upload_with_timing(collection_name, data, config_name):
|
||||
embeddings = [encoder.encode(dat["description"]).tolist() for dat in data]
|
||||
embeddings = encoder.encode(
|
||||
[d["description"] for d in data], show_progress_bar=True
|
||||
).tolist()
|
||||
|
||||
points = []
|
||||
for i, item in enumerate(data):
|
||||
embedding = embeddings[i]
|
||||
@@ -124,6 +124,9 @@ def upload_with_timing(collection_name, data, config_name):
|
||||
)
|
||||
)
|
||||
|
||||
# Warmup
|
||||
client.query_points(collection_name=collection_name, query=points[0].vector, limit=1)
|
||||
|
||||
start_time = time.time()
|
||||
client.upload_points(collection_name=collection_name, points=points)
|
||||
upload_time = time.time() - start_time
|
||||
@@ -133,7 +136,7 @@ def upload_with_timing(collection_name, data, config_name):
|
||||
|
||||
|
||||
# Load your dataset here
|
||||
# your_dataset = [{"description": "This is a description of a product"}, ...]
|
||||
# your_dataset = [{"description": "This is a description of a product"}, ...]
|
||||
|
||||
# Upload to each collection
|
||||
upload_times = {}
|
||||
@@ -143,11 +146,15 @@ for config in configs:
|
||||
collection_name, your_dataset, config["name"]
|
||||
)
|
||||
|
||||
|
||||
# Wait for index to be built
|
||||
def wait_for_index_built(collection_name, vectors_per_point=1):
|
||||
info = client.get_collection(collection_name=collection_name)
|
||||
count = 0
|
||||
while info.points_count * vectors_per_point - info.indexed_vectors_count != 0 and count < 10:
|
||||
while (
|
||||
info.points_count * vectors_per_point - info.indexed_vectors_count != 0
|
||||
and count < 10
|
||||
):
|
||||
time.sleep(1)
|
||||
info = client.get_collection(collection_name=collection_name)
|
||||
count += 1
|
||||
@@ -158,9 +165,9 @@ def wait_for_index_built(collection_name, vectors_per_point=1):
|
||||
|
||||
|
||||
for config in configs:
|
||||
collection_name = f"my_domain_{config['name']}"
|
||||
wait_for_index_built(collection_name)
|
||||
|
||||
if config["m"] > 0: # m=0 has no HNSW to wait for
|
||||
collection_name = f"my_domain_{config['name']}"
|
||||
wait_for_index_built(collection_name)
|
||||
```
|
||||
|
||||
### Step 4: Benchmark Search Performance
|
||||
@@ -170,13 +177,9 @@ Test search speed with different `hnsw_ef` values:
|
||||
```python
|
||||
def benchmark_search(collection_name, query_embedding, ef_values=[64, 128, 256]):
|
||||
# Warmup
|
||||
_ = client.query_points(
|
||||
collection_name=collection_name,
|
||||
query=query_embedding,
|
||||
limit=10,
|
||||
search_params=models.SearchParams(hnsw_ef=ef_values[0]),
|
||||
)
|
||||
client.query_points(collection_name=collection_name, query=query_embedding, limit=1)
|
||||
|
||||
# hnsw_ef: higher = better recall, but slower. Tune per your latency goal.
|
||||
results = {}
|
||||
for hnsw_ef in ef_values:
|
||||
times = []
|
||||
@@ -225,8 +228,17 @@ def test_filtering_performance(collection_name):
|
||||
|
||||
# Test filter without index
|
||||
filter_condition = models.Filter(
|
||||
must=[models.FieldCondition(key="length", range=models.Range(gte=100, lte=500))]
|
||||
must=[models.FieldCondition(key="length", range=models.Range(gte=10, lte=200))]
|
||||
)
|
||||
|
||||
# Demo only: unindexed_filtering_retrieve=True forces a scan; turn it off right after measuring.
|
||||
client.update_collection(
|
||||
collection_name=collection_name,
|
||||
strict_mode_config=models.StrictModeConfig(unindexed_filtering_retrieve=True),
|
||||
)
|
||||
|
||||
# Warmup
|
||||
client.query_points(collection_name=collection_name, query=query_embedding, limit=1)
|
||||
|
||||
# Timing without payload index
|
||||
start_time = time.time()
|
||||
@@ -240,33 +252,36 @@ def test_filtering_performance(collection_name):
|
||||
|
||||
# Create payload index
|
||||
client.create_payload_index(
|
||||
collection_name=collection_name, field_name="length", field_schema="integer"
|
||||
collection_name=collection_name,
|
||||
field_name="length",
|
||||
field_schema=models.PayloadSchemaType.INTEGER,
|
||||
)
|
||||
|
||||
# Rebuild HNSW to attach filter data structures.
|
||||
# Note: This is not advised for production. Better create payload index before uploading any data to avoid rebuild.
|
||||
suffix = collection_name.replace("my_domain_", "")
|
||||
config = next((c for c in configs if c["name"] == suffix), None)
|
||||
|
||||
client.update_collection(
|
||||
collection_name=collection_name, hnsw_config=models.HnswConfigDiff(m=0)
|
||||
)
|
||||
base_ef = client.get_collection(
|
||||
collection_name=collection_name
|
||||
).config.hnsw_config.ef_construct
|
||||
|
||||
client.update_collection(
|
||||
collection_name=collection_name,
|
||||
hnsw_config=models.HnswConfigDiff(
|
||||
m=16,
|
||||
ef_construct=config["ef_construct"],
|
||||
full_scan_threshold=10,
|
||||
payload_m=None,
|
||||
max_indexing_threads=1,
|
||||
# HNSW was already built; adding the payload index doesn’t rebuild it.
|
||||
# Bump ef_construct (+1) once to trigger a safe rebuild and turn off scanning.
|
||||
ef_construct=base_ef
|
||||
+ 1,
|
||||
),
|
||||
optimizers_config=models.OptimizersConfigDiff(vacuum_min_vector_number=0),
|
||||
strict_mode_config=models.StrictModeConfig(
|
||||
unindexed_filtering_retrieve=False
|
||||
), # Turn off scanning and use payload index instead.
|
||||
)
|
||||
|
||||
# Wait for index to be built
|
||||
wait_for_index_built(collection_name)
|
||||
|
||||
# Warmup
|
||||
client.query_points(collection_name=collection_name, query=query_embedding, limit=1)
|
||||
|
||||
# Timing with index
|
||||
start_time = time.time()
|
||||
_ = client.query_points(
|
||||
|
||||
Reference in New Issue
Block a user