Zvec Logo

Announcing Zvec v0.6.0

TL;DR: We are releasing Zvec v0.6.0, headlined by the new Turbo quantizer framework, random rotation for INT8/INT4 quantization, group-by search, FTS(language support, matching operators, stemming), and DiskANN I/O decoupling via dlopen. This release pushes quantization accuracy and memory efficiency further, enriches the full-text search pipeline with multi-language and Unicode support, and makes DiskANN deployment simpler than ever β€” no more plugin .so or libaio-dev build-time dependency.

You can find the complete release notes on GitHub.


Turbo: New Quantizer Framework

Zvec v0.6.0 introduces Turbo β€” a pluggable quantizer framework that decouples quantization logic from index builders and searchers. Turbo establishes a uniform interface that future quantizers (int8 uniform, int8 record, PQ, RaBitQ, …) can implement, making it easier to add new quantization methods without touching index code.

The initial release includes:

  • Quantizer abstraction β€” an abstract base class with a DistanceImpl callable distance handle, the first concrete Fp32Quantizer implementation, and scalar FP32 distance kernels. IndexMeta and IndexQueryMeta have been extended with quantizer support, and IndexFactory now wires quantizers into the index pipeline.

This framework lays the groundwork for RaBitQ quantization on IVF indexes β€” a memory optimization that compresses vectors to 1-bit representations, dramatically reducing memory footprint while maintaining competitive recall. The Turbo abstraction ensures RaBitQ can be integrated cleanly across IVF and other index types. A Turbo preprocessor (rotation, dimensionality reduction) is planned for a follow-up release.


Random Rotation for INT8/INT4 Quantization

Quantization error in INT8 is directly proportional to the data range (max βˆ’ min). By applying a random rotation before quantization, variance is distributed evenly across all vector dimensions, reducing the overall range and thereby improving quantization accuracy.

This release adds an optional rotation parameter to INT8/INT4 quantization, now supporting HNSW, Flat and Vamana indexes. The benefits are significant β€” recall improves while maintaining the same QPS:

DatasetIndexINT8 Recall (before β†’ after)INT4 Recall (before β†’ after)
cohere-1mHNSW0.9285 β†’ 0.93970.2114 β†’ 0.7117
cohere-1mFlat0.9695 β†’ 0.98810.248 β†’ 0.8146
cohere-1mVamana0.9576 β†’ 0.97340.2415 β†’ 0.771

The rotation is implemented via an abstract Rotator base class with FhtRotator (Fast Hadamard Transform) and MatrixRotator inheritance, providing flexibility for different rotation strategies.


Zvec v0.6.0 adds group-by search (a.k.a. group-by deduplication) across the core interface, algorithm, and DB layers. Users can now retrieve top-K results per group instead of globally β€” essential for de-duplicating near-identical documents, returning diverse results per category, or implementing per-group pagination.

Key capabilities:

  • Supports fetch_vector, is_linear, and bf_pks query modes
  • Works with Flat (dense & sparse), HNSW (dense & sparse), and HNSW-RaBitQ indexes
  • Group-by is mutually exclusive with refiner search (rejected when refiner_param is set)
  • Unsupported index types (DiskANN, IVF, Vamana) now fail fast with IndexError_Unsupported instead of silently returning empty or incorrect results

Group-by search is also exposed in the Python API:

from zvec import Query, GroupByParam

result = collection.query(
    queries=Query(
        field_name="embedding",
        vector=[0.1] * 128,
        group_by_param=GroupByParam(
            group_topk=3,       # top-K per group
            group_count=10,     # number of groups
        ),
    ),
    topk=30,
)

FTS: Language Support, Matching Operators & Stemming

Building on the native full-text search introduced in v0.5.0, this release significantly expands the FTS text analysis pipeline with full Unicode support, multi-language stemming, and a production-grade standard tokenizer.

Standard Tokenizer (UAX #29)

Replaced the previous general-category tokenizer with Unicode 17 UAX #29 word-boundary tables generated from official Unicode data. The new tokenizer implements Lucene-style token selection for alphanumeric, numeric, ideographic, hiragana, katakana, hangul, southeast Asian, regional indicator, and common emoji sequences β€” bringing Zvec's tokenization behavior closer to Elasticsearch's standard tokenizer.

UTF-8 Lowercase & ASCII Folding

Integrated utf8proc 2.11.3 to upgrade the entire FTS text analysis pipeline with full Unicode support:

  • LowercaseTokenFilter: Codepoint-aware lowercase conversion replacing byte-level std::tolower
  • AsciiFoldingTokenFilter (new): Converts Unicode characters to ASCII equivalents using NFKD decomposition + STRIPMARK, with a supplementary folding table for characters without decomposition mappings (ΓΈβ†’o, Δ‘β†’d, ΓŸβ†’ss, Γ†β†’AE, Γžβ†’TH, etc.)

Stemmer Token Filter

Added a stemmer token filter based on Snowball 3.1.1, reducing words to their root form with support for 34+ languages configurable via stemmer_lang in extra_params (defaults to English). The filter uses a thread-local stemmer cache for lock-free performance.

from zvec import FieldSchema, DataType, FtsIndexParam

FieldSchema(
    "content",
    DataType.STRING,
    index_param=FtsIndexParam(
        tokenizer_name="standard",
        filters=["lowercase", "ascii_folding", "stemmer"],
        extra_params={"stemmer_lang": "english"},
    ),
)

DiskANN I/O Decoupling

Prior to v0.6.0, DiskANN shipped as a separate runtime-loaded plugin .so that required a hard build-time dependency on libaio-dev. This release replaces that design with a simpler, more robust approach:

  • Runtime dlopen: A thread-safe singleton dlopens libaio.so at runtime and caches the syscall pointers β€” no more libaio-dev build dependency
  • Graceful fallback: If libaio is absent, DiskANN automatically falls back to synchronous pread() with a warning
  • Simplified deployment: No more plugin .so to ship or preload β€” DiskANN is now compiled directly into the core library

Performance comparison on Cohere 1M (Aliyun g9i, PL0, 10000 IOPS) shows that AIO-enabled pread delivers ~1.7Γ— the QPS of the synchronous fallback, while recall remains identical β€” so users on systems with libaio still get full performance automatically.


Performance Improvements

  • Faster FTS Conjunction Queries: Added block-max skip and score early-exit to ConjunctionIterator β€” skip entire non-competitive blocks (128 docs) by checking block-max score upper bounds, and short-circuit score accumulation when the remaining upper bound cannot beat the threshold. Benchmark (500k docs, quora dataset): AND queries 22–38% faster, phrase queries 33% faster.
  • Zero-Copy Python Vector Query: Replaced serialize_vector memcpy with VectorViewClause that points directly at the numpy buffer, eliminating redundant memory copies for Python dense vector queries.

Other Improvements & Fixes

  • DiskANN C API: Added complete DiskANN C API interfaces including index params setter/getters, query params with CRUD operations, and query wiring for vector / group-by vector / sub-query.
  • Collection Consistency: Preserved the live writing segment across CreateIndex/DropIndex DDL failures so persisted-segment tasks no longer corrupt the active segment.
  • Index Stability: Fixed lost-wakeup race in DiskANN and HNSW sparse builder progress loops, IVF nprobe selected list scanning, and miscellaneous IVF index bugs.
  • FTS Correctness: Fixed segment stats not written on reopen, zero-match filter semantics, global doc id gaps during compaction, and snapshot read-only indexes without flush.
  • Collection: Fixed LOCK file to open read-only when collection is read-only.
  • Build: Propagated compiler settings to Arrow ExternalProject, propagated CMAKE_C_COMPILER to LZ4, accepted Xcode 26.5's renamed libtool version string, and declared 64-bit-only Python support.

Roadmap

For a glimpse into our future plans β€” including storage scalability, expanded algorithm support, and more language SDKs β€” please visit our official roadmap.