updated params

This commit is contained in:
Kirstin
2025-10-23 01:47:02 +02:00
parent 6d3ace7aa0
commit a8fc646642
2 changed files with 55 additions and 36 deletions
@@ -162,8 +162,11 @@ client.create_collection(
hnsw_config=models.HnswConfigDiff( hnsw_config=models.HnswConfigDiff(
m=0, # Bulk load fast: m=0 (build links after ingest). m=0, # Bulk load fast: m=0 (build links after ingest).
ef_construct=100, # Build quality: used after we set m>0 ef_construct=100, # Build quality: used after we set m>0
full_scan_threshold=10000, full_scan_threshold=10, # force HNSW instead of full scan
), ),
optimizers_config=models.OptimizersConfigDiff(
indexing_threshold=10
), # Force indexing even on small sets for demo
strict_mode_config=models.StrictModeConfig( strict_mode_config=models.StrictModeConfig(
enabled=False, enabled=False,
), # More flexible while testing ), # More flexible while testing
@@ -311,12 +314,11 @@ Let's measure search performance on the HNSW‑enabled collection.
print("Running baseline performance test...") print("Running baseline performance test...")
# Warm up the RAM index/vectors cache with a test query # Warm up the RAM index/vectors cache with a test query
print("Warming up caches...")
client.query_points(collection_name=collection_name, query=query_embedding, limit=1) client.query_points(collection_name=collection_name, query=query_embedding, limit=1)
# Measure vector search performance # Measure vector search performance
search_times = [] search_times = []
for _ in range(3): # Multiple runs for a stable average for _ in range(25): # Multiple runs for a stable average
start_time = time.time() start_time = time.time()
response = client.query_points( response = client.query_points(
collection_name=collection_name, query=query_embedding, limit=10 collection_name=collection_name, query=query_embedding, limit=10
@@ -329,7 +331,9 @@ baseline_time = sum(search_times) / len(search_times)
print(f"Average search time: {baseline_time:.2f}ms") print(f"Average search time: {baseline_time:.2f}ms")
print(f"Search times: {[f'{t:.2f}ms' for t in search_times]}") print(f"Search times: {[f'{t:.2f}ms' for t in search_times]}")
print(f"Found {len(response.points)} results") print(f"Found {len(response.points)} results")
print(f"Top result: '{response.points[0].payload['title']}' (score: {response.points[0].score:.4f})") print(
f"Top result: '{response.points[0].payload['title']}' (score: {response.points[0].score:.4f})"
)
# Show a few more results for context # Show a few more results for context
print(f"\nTop 3 results:") print(f"\nTop 3 results:")
@@ -344,7 +348,7 @@ for i, point in enumerate(response.points[:3], 1):
**Performance factors:** **Performance factors:**
- **Cache warming**: First query loads relevant index parts/vectors into memory, subsequent queries are faster - **Cache warming**: First query loads relevant index parts/vectors into memory, subsequent queries are faster
- **HNSW with m=16**: Graph-based search is much faster than full scan - **HNSW with m=16**: Graph-based search is much faster than full scan
- **MRepeated runs**: Average of several queries gives more reliable timing results - **Repeated runs**: Average of several queries gives more reliable timing results
## Step 9: Filtering Without Payload Indexes ## Step 9: Filtering Without Payload Indexes
@@ -370,7 +374,7 @@ client.query_points(collection_name=collection_name, query=query_embedding, limi
# Run multiple times for more reliable measurement # Run multiple times for more reliable measurement
unindexed_times = [] unindexed_times = []
for i in range(3): for i in range(25):
start_time = time.time() start_time = time.time()
response = client.query_points( response = client.query_points(
collection_name=collection_name, collection_name=collection_name,
@@ -388,7 +392,9 @@ print(f"Individual times: {[f'{t:.2f}ms' for t in unindexed_times]}")
print(f"Overhead vs baseline: {unindexed_filter_time - baseline_time:.2f}ms") print(f"Overhead vs baseline: {unindexed_filter_time - baseline_time:.2f}ms")
print(f"Found {len(response.points)} matching results") print(f"Found {len(response.points)} matching results")
if response.points: if response.points:
print(f"Top result: '{response.points[0].payload['text']}'\nScore: {response.points[0].score:.4f}") print(
f"Top result: '{response.points[0].payload['text']}'\nScore: {response.points[0].score:.4f}"
)
else: else:
print("No results found - try a different filter term") print("No results found - try a different filter term")
``` ```
@@ -432,7 +438,7 @@ client.query_points(collection_name=collection_name, query=query_embedding, limi
# Run multiple times for more reliable measurement # Run multiple times for more reliable measurement
indexed_times = [] indexed_times = []
for i in range(3): for i in range(25):
start_time = time.time() start_time = time.time()
response = client.query_points( response = client.query_points(
collection_name=collection_name, collection_name=collection_name,
@@ -450,7 +456,9 @@ print(f"Individual times: {[f'{t:.2f}ms' for t in indexed_times]}")
print(f"Overhead vs baseline: {indexed_filter_time - baseline_time:.2f}ms") print(f"Overhead vs baseline: {indexed_filter_time - baseline_time:.2f}ms")
print(f"Found {len(response.points)} matching results") print(f"Found {len(response.points)} matching results")
if response.points: if response.points:
print(f"Top result: '{response.points[0].payload['text']}'\nScore: {response.points[0].score:.4f}") print(
f"Top result: '{response.points[0].payload['text']}'\nScore: {response.points[0].score:.4f}"
)
else: else:
print("No results found - try a different filter term") print("No results found - try a different filter term")
``` ```
@@ -87,9 +87,13 @@ for config in configs:
collection_name=collection_name, collection_name=collection_name,
vectors_config=models.VectorParams(size=384, distance=models.Distance.COSINE), vectors_config=models.VectorParams(size=384, distance=models.Distance.COSINE),
hnsw_config=models.HnswConfigDiff( hnsw_config=models.HnswConfigDiff(
m=config["m"], ef_construct=config["ef_construct"], full_scan_threshold=10 m=config["m"],
ef_construct=config["ef_construct"],
full_scan_threshold=10, # force HNSW instead of full scan
), ),
optimizers_config=models.OptimizersConfigDiff(indexing_threshold=0), optimizers_config=models.OptimizersConfigDiff(
indexing_threshold=10
), # Force indexing even on small sets for demo
) )
print(f"Created collection: {collection_name}") print(f"Created collection: {collection_name}")
``` ```
@@ -125,7 +129,9 @@ def upload_with_timing(collection_name, data, config_name):
) )
# Warmup # Warmup
client.query_points(collection_name=collection_name, query=points[0].vector, limit=1) client.query_points(
collection_name=collection_name, query=points[0].vector, limit=1
)
start_time = time.time() start_time = time.time()
client.upload_points(collection_name=collection_name, points=points) client.upload_points(collection_name=collection_name, points=points)
@@ -136,7 +142,7 @@ def upload_with_timing(collection_name, data, config_name):
# Load your dataset here # 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 to each collection
upload_times = {} upload_times = {}
@@ -185,7 +191,7 @@ def benchmark_search(collection_name, query_embedding, ef_values=[64, 128, 256])
times = [] times = []
# Run multiple queries for more reliable timing # Run multiple queries for more reliable timing
for _ in range(5): for _ in range(25):
start_time = time.time() start_time = time.time()
_ = client.query_points( _ = client.query_points(
@@ -193,6 +199,7 @@ def benchmark_search(collection_name, query_embedding, ef_values=[64, 128, 256])
query=query_embedding, query=query_embedding,
limit=10, limit=10,
search_params=models.SearchParams(hnsw_ef=hnsw_ef), search_params=models.SearchParams(hnsw_ef=hnsw_ef),
with_payload=False,
) )
times.append((time.time() - start_time) * 1000) times.append((time.time() - start_time) * 1000)
@@ -230,7 +237,7 @@ def test_filtering_performance(collection_name):
filter_condition = models.Filter( filter_condition = models.Filter(
must=[models.FieldCondition(key="length", range=models.Range(gte=10, lte=200))] 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. # Demo only: unindexed_filtering_retrieve=True forces a scan; turn it off right after measuring.
client.update_collection( client.update_collection(
collection_name=collection_name, collection_name=collection_name,
@@ -241,24 +248,27 @@ def test_filtering_performance(collection_name):
client.query_points(collection_name=collection_name, query=query_embedding, limit=1) client.query_points(collection_name=collection_name, query=query_embedding, limit=1)
# Timing without payload index # Timing without payload index
start_time = time.time() times = []
_ = client.query_points( for _ in range(25):
collection_name=collection_name, start_time = time.time()
query=query_embedding, _ = client.query_points(
query_filter=filter_condition, collection_name=collection_name,
limit=10, query=query_embedding,
) query_filter=filter_condition,
time_without_index = (time.time() - start_time) * 1000 limit=10,
with_payload=False,
)
times.append((time.time() - start_time) * 1000)
time_without_index = np.mean(times)
# Create payload index # Create payload index
client.create_payload_index( client.create_payload_index(
collection_name=collection_name, collection_name=collection_name,
field_name="length", field_name="length",
field_schema=models.PayloadSchemaType.INTEGER, field_schema=models.PayloadSchemaType.INTEGER,
wait=True,
) )
suffix = collection_name.replace("my_domain_", "")
config = next((c for c in configs if c["name"] == suffix), None)
base_ef = client.get_collection( base_ef = client.get_collection(
collection_name=collection_name collection_name=collection_name
).config.hnsw_config.ef_construct ).config.hnsw_config.ef_construct
@@ -276,21 +286,22 @@ def test_filtering_performance(collection_name):
), # Turn off scanning and use payload index instead. ), # Turn off scanning and use payload index instead.
) )
# Wait for index to be built
wait_for_index_built(collection_name)
# Warmup # Warmup
client.query_points(collection_name=collection_name, query=query_embedding, limit=1) client.query_points(collection_name=collection_name, query=query_embedding, limit=1)
# Timing with index # Timing with index
start_time = time.time() times = []
_ = client.query_points( for _ in range(25):
collection_name=collection_name, start_time = time.time()
query=query_embedding, _ = client.query_points(
query_filter=filter_condition, collection_name=collection_name,
limit=10, query=query_embedding,
) query_filter=filter_condition,
time_with_index = (time.time() - start_time) * 1000 limit=10,
with_payload=False,
)
times.append((time.time() - start_time) * 1000)
time_with_index = np.mean(times)
return { return {
"without_index": time_without_index, "without_index": time_without_index,