Skip to content

Commit 87567de

Browse files
Release v0.2.0
* Bump version to 0.2.0 for development * feat(vector_database): Add comprehensive quantization support with PQ integration * feat(pq): Implement complete Product Quantization module with ADC support * feat(hnsw_index): Complete Step 3 - ADC distance integration with automatic quantization * feat(lib): Add PQ module to Rust library exports * feat(vector_database): Add comprehensive quantization support with PQ integration * feat(hnsw_index): Complete Step 3 - ADC distance integration with automatic quantization - part 2 * fix(vector_database): Make `quantization_config` fully optional in Python `.create()` API for PQ support * Add: latest uv.lock file for reproducible Python dependency management * test(vector_database): Add comprehensive Stage 3 test suite for PQ integration and ADC readiness * fix(vector_database): Make quantization_config fully optional in Python .create() API for PQ support * feat: completes Step 4 of the PQ implementation, enabling robust input parsing for both storage paths * test: add internal tests for PQ, high-volume, and high-dimensional vectors * 📄 docs(changelog): update for v0.2.0 release * feat: implement comprehensive input format support and enhanced vector processing * feat: implement vector normalization for cosine space consistency * Add expected_size to get_stats output for enhanced index diagnostics * fix: add proper space validation with RuntimeError for invalid spaces * fix: resolve NumPy batch parsing issues with ID and metadata preservation * feat: implement production-quality error collection in vector parsing * feat: implement conditional debug logging with environment variable control * fix: restore missing stats keys in get_stats() method * test: add comprehensive PQ quantization integration tests * chore: fix warning for training info method * fix: increase default ef_search for L1/L2 distance metrics * 📦chore(release): Version bump: v0.1.2 → v0.2.0 * 📄 docs(changelog): update for v0.2.0 release * 📄 docs(readme): updated the content information * 📄 docs(readme): updated the content information * Add: latest uv.lock file for reproducible Python dependency management * 📄 docs(readme): updated the content information * Add: comprehensive product quantization usage example for README
1 parent c2e9740 commit 87567de

17 files changed

Lines changed: 5212 additions & 549 deletions

CHANGELOG.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,130 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
---
99

10+
## [0.2.0] - 2025-07-25
11+
12+
### Added
13+
- Product Quantization (PQ) Support
14+
- Quantized vector storage with configurable compression ratios (4x-256x)
15+
- Automatic training pipeline with intelligent threshold detection
16+
- 3-path storage architecture for optimal memory usage:
17+
- Path A: Raw storage (no quantization)
18+
- Path B: Raw storage + ID collection (pre-training)
19+
- Path C: Quantized storage (post-training)
20+
21+
- Quantized Search API
22+
- Unified search interface supports both raw and quantized vectors transparently.
23+
- Automatic fallback to raw search if quantization is not yet trained.
24+
- Quantization-aware batch addition for efficient ingestion at scale.
25+
- Detailed quantization diagnostics via get_quantization_info() (e.g., codebook stats, compression ratio, memory footprint).
26+
- Debug logging macro (ZEUSDB_DEBUG) for controlled diagnostic output in Rust backend.
27+
- Thread safety diagnostics in get_stats() (e.g., "thread_safety": "RwLock+Mutex").
28+
- Improved test coverage for quantized and raw modes, including edge cases and error handling.
29+
30+
- Asymmetric Distance Computation (ADC) for fast quantized search
31+
- Memory-efficient k-means clustering for codebook generation
32+
- Configurable quantization parameters:
33+
- `subvectors`: Number of vector subspaces (divisor of dimension)
34+
- `bits`: Bits per quantized code (1-8)
35+
- `training_size`: Vectors needed for training (minimum 1000)
36+
- `max_training_vectors`: Maximum vectors used for training
37+
38+
- Enhanced Vector Database API
39+
- Quantization configuration support in create() method
40+
- Training progress monitoring with get_training_progress()
41+
- Storage mode detection with get_storage_mode()
42+
- Quantization status methods:
43+
- `has_quantization()`: Check if quantization is configured
44+
- `can_use_quantization()`: Check if PQ model is trained
45+
- `is_quantized()`: Check if index is using quantized storage
46+
- Quantization info retrieval with `get_quantization_info()`
47+
- Training readiness check with `is_training_ready()`
48+
- Training vectors needed with `training_vectors_needed()`
49+
50+
- Performance Monitoring
51+
- Compression ratio calculation and reporting
52+
- Memory usage estimation for raw vs compressed storage
53+
- Training time measurement and optimization
54+
- Search performance metrics for quantized vs raw modes
55+
- Detailed statistics in 'get_stats()' method
56+
57+
- Input Handling
58+
- Enhanced dictionary input parsing with comprehensive error handling
59+
- Flexible metadata support for various Python object types
60+
- Automatic type detection and conversion for metadata
61+
- Graceful handling of None values and edge cases
62+
- Comprehensive input validation with descriptive error messages
63+
64+
- Performance Optimizations
65+
- Batch processing for large-scale vector additions
66+
- Optimized memory allocation during training and storage
67+
- Efficient vector reconstruction from quantized codes
68+
- Fast ADC search implementation with SIMD optimizations
69+
- Automatic performance scaling post-training (up to 8x faster additions)
70+
71+
### Changed
72+
- Vector Addition Behavior
73+
- Automatic training trigger when threshold is reached during vector addition
74+
- Dynamic storage mode switching from raw to quantized seamlessly
75+
- Enhanced error reporting with detailed failure information in AddResult
76+
- Improved batch processing with better memory management
77+
78+
- Search Performance
79+
- Adaptive search strategy based on storage mode (raw vs quantized)
80+
- Optimized distance calculations for quantized vectors
81+
- Enhanced result quality with proper score normalization
82+
83+
- Index Architecture
84+
- 3-path storage system replaces simple raw storage
85+
- Intelligent memory management with automatic cleanup
86+
- Robust state transitions between storage modes
87+
- Enhanced concurrency handling with proper lock management
88+
89+
- Statistics and Monitoring
90+
- Extended statistics including quantization metrics
91+
- Real-time progress tracking during training operations
92+
- Enhanced memory usage reporting with compression analysis
93+
- Detailed timing information for performance optimization
94+
95+
- Default search parameters tuned for quantized and L1/L2 spaces (e.g., higher default ef_search for L1/L2).
96+
- Improved error messages for quantization-related failures and configuration issues.
97+
- Consistent handling of vector normalization (cosine) vs. raw (L1/L2) in all input/output paths.
98+
99+
### Fixed
100+
- Memory Management
101+
- Fixed temporary value lifetime issues in PyO3 integration
102+
- Resolved borrow checker conflicts in quantization pipeline
103+
- Corrected memory leaks during large-scale operations
104+
- Fixed reference counting for Python object handling
105+
106+
- Vector Processing
107+
- Fixed input format parsing for edge cases and invalid data
108+
- Resolved metadata conversion issues for complex Python objects
109+
- Corrected vector dimension validation with proper error messages
110+
- Fixed batch processing memory allocation issues
111+
112+
- Performance Issues
113+
- Optimized training memory usage to prevent out-of-memory errors
114+
- Fixed search performance degradation in large indexes
115+
- Resolved training stability issues with improved k-means initialization
116+
- Corrected distance calculation accuracy in quantized mode
117+
118+
- Error Handling
119+
- Enhanced validation for quantization configuration parameters
120+
- Improved error propagation from Rust to Python
121+
- Fixed panic conditions in edge cases
122+
- Better handling of invalid input combinations
123+
124+
- Fixed rare edge case where quantization training could stall with duplicate vectors.
125+
- Resolved non-deterministic search results in small datasets with L1/L2 metrics by tuning search parameters.
126+
- Fixed debug output leaking to production logs (now controlled by environment variable).
127+
128+
### Removed
129+
- Removed legacy single-path storage logic (now fully 3-path).
130+
- Deprecated or removed any old quantization/test hooks that are no longer needed.
131+
132+
---
133+
10134
## [0.1.2] - 2025-07-17
11135

12136
### Added

README.md

Lines changed: 167 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,30 @@ ZeusDB leverages the HNSW (Hierarchical Navigable Small World) algorithm for spe
3737

3838
## ⭐ Features
3939

40-
🔍 Approximate Nearest Neighbor (ANN) search with HNSW
40+
🐍 User-friendly Python API for adding vectors and running similarity searches
4141

42-
📋 Supports multiple distance metrics: `cosine`, `L1`, `L2`
42+
🔥 High-performance Rust backend optimized for speed and concurrency
4343

44-
🔥 High-performance Rust backend
44+
🔍 Approximate Nearest Neighbor (ANN) search using HNSW for fast, accurate results
45+
46+
📦 Product Quantization (PQ) for compact storage, faster distance computations, and scalability for Big Data
47+
48+
📥 Flexible input formats, including native Python types and zero-copy NumPy arrays
49+
50+
🗂️ Metadata-aware filtering for precise and contextual querying
4551

46-
📥 Supports multiple input formats using a single, easy-to-use Python method
4752

48-
🗂️ Metadata-aware filtering at query time
4953

50-
🐍 Simple and intuitive Python API
54+
55+
<!--
56+
📋 Supports multiple distance metrics: `cosine`, `L1`, `L2`
57+
58+
📥 Supports multiple input formats using a single, easy-to-use Python method
5159
5260
⚡ Smart multi-threaded inserts that automatically speed up large batch uploads
5361
5462
🚀 Fast, concurrent searches so you can run multiple queries at the same time
55-
63+
-->
5664

5765
<br/>
5866

@@ -196,10 +204,11 @@ index = vdb.create(
196204
|------------------|--------|-----------|-----------------------------------------------------------------------------|
197205
| `index_type` | `str` | `"hnsw"` | The type of vector index to create. Currently supports `"hnsw"`. Future options include `"ivf"`, `"flat"`, etc. Case-insensitive. |
198206
| `dim` | `int` | `1536` | Dimensionality of the vectors to be indexed. Each vector must have this length. The default dim=1536 is chosen to match the output dimensionality of OpenAI’s text-embedding-ada-002 model. |
199-
| `space` | `str` | `"cosine"`| Distance metric used for similarity search. Options include `"cosine"`. Additional metrics such as `"l2"`, and `"dot"` will be added in future versions. |
207+
| `space` | `str` | `"cosine"`| Distance metric used for similarity search. Options include `"cosine"`, `"L1"` and `"L2"`.|
200208
| `m` | `int` | `16` | Number of bi-directional connections created for each new node. Higher `m` improves recall but increases index size and build time. |
201209
| `ef_construction`| `int` | `200` | Size of the dynamic list used during index construction. Larger values increase indexing time and memory, but improve quality. |
202210
| `expected_size` | `int` | `10000` | Estimated number of elements to be inserted. Used for preallocating internal data structures. Not a hard limit. |
211+
| `quantization_config` | `dict` | `None` | Product Quantization configuration for memory-efficient vector compression. |
203212

204213
<br/>
205214

@@ -536,6 +545,156 @@ print(partial)
536545

537546
⚠️ `get_records()` only returns results for IDs that exist in the index. Missing IDs are silently skipped.
538547

548+
<br />
549+
550+
551+
## 🗜️ Product Quantization
552+
553+
Product Quantization (PQ) is a vector compression technique that significantly reduces memory usage while preserving high search accuracy. Commonly used in HNSW-based vector databases, PQ works by dividing each vector into subvectors and quantizing them independently. This enables compression ratios of 4× to 256×, making it ideal for large-scale, high-dimensional datasets.
554+
555+
ZeusDB Vector Database’s PQ implementation features:
556+
557+
✅ Intelligent Training – PQ model trains automatically at defined thresholds
558+
559+
✅ Efficient Memory Use – Store 4× to 256× more vectors in the same RAM footprint
560+
561+
✅ Fast Approximate Search – Uses Asymmetric Distance Computation (ADC) for high-speed search computation
562+
563+
✅ Seamless Operation – Index automatically switches from raw to quantized storage modes
564+
565+
<br />
566+
567+
### 📘 Quantization Configuration Parameters
568+
569+
To enable PQ, pass a `quantization_config` dictionary to the `.create()` index method:
570+
571+
| Parameter | Type | Description | Valid Range | Default |
572+
|-----------|------|-------------|-------------|---------|
573+
| `type` | `str` | Quantization algorithm type | `"pq"` | *required* |
574+
| `subvectors` | `int` | Number of vector subspaces (must divide dimension evenly) | 1 to dimension | `8` |
575+
| `bits` | `int` | Bits per quantized code (controls centroids per subvector) | 1-8 | `8` |
576+
| `training_size` | `int` | Minimum vectors needed for stable k-means clustering | ≥ 1000 | 1000 |
577+
| `max_training_vectors` | `int` | Maximum vectors used during training (optional limit) | ≥ training_size | `None` |
578+
579+
580+
<br/>
581+
582+
583+
### 🔧 Usage Example
584+
585+
```python
586+
from zeusdb_vector_database import VectorDatabase
587+
import numpy as np
588+
589+
# Create index with product quantization
590+
vdb = VectorDatabase()
591+
592+
# Configure quantization for memory efficiency
593+
quantization_config = {
594+
'type': 'pq', # `pq` for Product Quantization
595+
'subvectors': 8, # Divide 1536-dim vectors into 8 subvectors of 192 dims each
596+
'bits': 8, # 256 centroids per subvector (2^8)
597+
'training_size': 10000, # Train when 10k vectors are collected
598+
'max_training_vectors': 50000 # Use max 50k vectors for training
599+
}
600+
601+
# Create index with quantization
602+
# This will automatically handle training when enough vectors are added
603+
index = vdb.create(
604+
index_type="hnsw",
605+
dim=1536, # OpenAI `text-embedding-3-small` dimension
606+
quantization_config=quantization_config # Add the compression configuration
607+
)
608+
609+
# Add vectors - training triggers automatically at threshold
610+
documents = [
611+
{
612+
"id": f"doc_{i}",
613+
"values": np.random.rand(1536).astype(float).tolist(),
614+
"metadata": {"category": "tech", "year": 2026}
615+
}
616+
for i in range(15000)
617+
]
618+
619+
# Training will trigger automatically when 10k vectors are added
620+
result = index.add(documents)
621+
print(f"Added {result.total_inserted} vectors")
622+
623+
# Check quantization status
624+
print(f"Training progress: {index.get_training_progress():.1f}%")
625+
print(f"Storage mode: {index.get_storage_mode()}")
626+
print(f"Is quantized: {index.is_quantized()}")
627+
628+
# Get compression statistics
629+
quant_info = index.get_quantization_info()
630+
if quant_info:
631+
print(f"Compression ratio: {quant_info['compression_ratio']:.1f}x")
632+
print(f"Memory usage: {quant_info['memory_mb']:.1f} MB")
633+
634+
# Search works seamlessly with quantized storage
635+
query_vector = np.random.rand(1536).astype(float).tolist()
636+
results = index.search(vector=query_vector, top_k=3)
637+
638+
# Simply print raw results
639+
print(results)
640+
```
641+
642+
Results
643+
```python
644+
[
645+
{'id': 'doc_9719', 'score': 0.5133496522903442, 'metadata': {'category': 'tech', 'year': 2026}},
646+
{'id': 'doc_8148', 'score': 0.5139288306236267, 'metadata': {'category': 'tech', 'year': 2026}},
647+
{'id': 'doc_7822', 'score': 0.5151920914649963, 'metadata': {'category': 'tech', 'year': 2026}},
648+
]
649+
```
650+
651+
<br />
652+
653+
### ⚙️ Configuration Guidelines
654+
655+
For Balanced Memory & Accuracy (Recommended to start with)
656+
```python
657+
quantization_config = {
658+
'type': 'pq',
659+
'subvectors': 8, # Balanced: moderate compression, good accuracy
660+
'bits': 8, # 256 centroids per subvector (high precision)
661+
'training_size': 10000 # Or higher for large datasets
662+
}
663+
# Achieves ~16x–32x compression with strong recall for most applications
664+
```
665+
666+
667+
For Memory Optimization:
668+
```python
669+
quantization_config = {
670+
'type': 'pq',
671+
'subvectors': 16, # More subvectors = better compression
672+
'bits': 6, # Fewer bits = less memory per centroid
673+
'training_size': 20000
674+
}
675+
# Achieves ~32x compression ratio
676+
```
677+
678+
For Accuracy Optimization:
679+
```python
680+
quantization_config = {
681+
'type': 'pq',
682+
'subvectors': 4, # Fewer subvectors = better accuracy
683+
'bits': 8, # More bits = more precise quantization
684+
'training_size': 50000 # More training data = better centroids
685+
}
686+
# Achieves ~4x compression ratio with minimal accuracy loss
687+
```
688+
689+
### 📊 Performance Characteristics
690+
691+
- Training: Occurs once when threshold is reached (typically 1-5 minutes for 50k vectors)
692+
- Memory Reduction: 4x-256x depending on configuration
693+
- Search Speed: Comparable or faster than raw vectors due to ADC optimization
694+
- Accuracy Impact: Typically 1-5% recall reduction with proper tuning
695+
696+
Quantization is ideal for production deployments with large vector datasets (100k+ vectors) where memory efficiency is critical.
697+
539698

540699
<br/>
541700

0 commit comments

Comments
 (0)