* refactor: make Reranker stateless with std::variant value semantics (#461)
Replace class hierarchy (Reranker/ScoreBasedReranker/RrfReranker/
WeightedReranker/CallbackReranker) with std::variant<RrfParams,
WeightedParams, CallbackParams> value type and a stateless free function
reranker::rerank().
Key changes:
- reranker.h: define RerankParams variant + reranker::rerank() API
- query.h: MultiQuery::reranker (shared_ptr) -> MultiQuery::rerank (value)
- schema.h: add CollectionSchema::get_field_ptr() returning FieldSchema::Ptr
- collection.cc: push field lookup to caller, pass vector<FieldSchema::Ptr>
- c_api: remove opaque zvec_reranker_t, add zvec_multi_query_set_rerank_*
- python binding: expose _RrfParams/_WeightedParams/_CallbackParams + setters
- python layer: WeightedReRanker(list[float]), remove Python rerank logic
- all tests updated to new interface
Benefits:
- Thread-safe by design: no mutable state, safe to share across threads
- Collection-decoupled: no bind_schema(), field info passed as parameter
- Simpler lifecycle: value semantics, no shared_ptr management
Closes#461
* chore: remove nightly_build.yml unrelated to reranker refactor
* chore: remove uv.lock unrelated to reranker refactor
* fix: raise ValueError when multi-query has no reranker
After the reranker stateless refactor the C++ MultiQuery rerank
strategy uses a std::variant with a default value, so the implicit
'reranker required' validation no longer triggered. Restore the
check in QueryExecutor._execute_multi_query so that a hybrid
(multi-query) request without a reranker raises ValueError.
* fix(reranker): use index_type FTS check for non-vector normalization
Replace dynamic_cast nullptr check with explicit IndexType::FTS check
and map FTS/BM25 positive scores to (0.0, 1.0) via 2*atan(score)/pi.
* refactor(reranker): move Params types into reranker namespace and qualify usages
Move RrfParams, WeightedParams, CallbackParams and RerankParams into the
zvec::reranker namespace, and add explicit reranker:: qualification at all
usage sites outside the reranker module (query.h, python/c bindings, tests).
* refactor(query): drop unused PendingQuery wrapper, use std::vector<SearchQuery> directly
* refactor(reranker): make _to_cpp_params non-abstract with default NotImplementedError
Remove @abstractmethod from RerankFunction._to_cpp_params and provide a
default implementation raising NotImplementedError. Drop the redundant
_to_cpp_params overrides from Qwen and Sentence rerankers since they use
the Python rerank path and don't need the C++ conversion.
* feat: migrate multi-vector query and reranker logic to C++
- Add Reranker base class with RrfReRanker and WeightedReRanker implementations
- Add Collection::MultiQuery interface for multi-vector queries with reranking
- Add MultiVectorQuery struct in doc.h with forward declaration for Reranker
- Add C API bindings for reranker and MultiQuery (zvec_reranker_*, zvec_multi_vector_query_*, zvec_collection_multi_query)
- Add Python binding for reranker classes with py::function bridge for callback
- Validate duplicate field names in multi-vector queries (C++ and Python consistent)
- Remove TODO comment about concurrent execution (SQLEngine is not thread-safe)
- Update collection.h MultiQuery doc comment from concurrently to sequentially
- Add C++ collection tests (6 MultiQuery test cases)
- Add C API tests (reranker functions + multi_vector_query end-to-end)
- Implement Python test cases (11 previously skipped tests now active)
- Simplify Python query_executor validation for unified duplicate field check
* style: format Python files with ruff
* fix: adapt to main branch API changes (VectorQuery->Query rename, validate_and_sanitize)
* fix: multi_vector tests now use multiple same-type vector fields (dense2, sparse2)
* fix: suppress RET501 for intentional default return None in RerankFunction._get_object
* style: ruff format test_collection.py
* refact multi vector query
* format code
* fix(multi-vector): expose SubVectorQuery in Python binding, fix tests
- Register _SubVectorQuery in pybind11 with from_vector_query() factory
- Convert _VectorQuery to _SubVectorQuery in MultiVectorQueryExecutor
- Relax RRF/Weighted score assertion tolerance from 1e-10 to 1e-6
- Fix WeightedReRanker test metric to IP (matching HnswIndexParam default)
* style: ruff format query_executor.py
* fix: define _USE_MATH_DEFINES for M_PI on Windows (MSVC)
* refactor: include reranker.h directly in query.h instead of forward declaration
* refactor(reranker): move topn from member variable to rerank() parameter
* refact code
* style(python): fix ruff UP035/UP037 in multi_vector_reranker
- import Callable from collections.abc instead of typing (UP035)
- remove redundant quotes around MetricType annotations (UP037)
* chore: trigger PR sync
* refact code
* fix(examples): restore CMakeLists.txt formatting broken by clang-format
* refactor(reranker): remove redundant metrics_ map by querying schema directly, and use insert return value to avoid duplicate set lookup
* refactor(reranker): defer schema binding to query time and remove C API callback reranker
* feat(examples): add custom HTTP embedding example for LM Studio / Ollama
* feat(extension): promote HTTPDenseEmbedding to first-class extension
Move the HTTP embedding implementation from the example script into
python/zvec/extension/ as HTTPDenseEmbedding, inheriting from
DenseEmbeddingFunction. The example now imports from zvec.extension
instead of defining the class inline.
Signed-off-by: Maxime <maxime@cluster2600.com>
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
* fix(examples): resolve ruff lint errors in HTTP embedding example
Move zvec imports to top-level, add noqa for print statements,
replace os.path.exists with pathlib, fix import sorting.
Signed-off-by: Maxime <maxime@cluster2600.com>
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
* style: apply ruff formatter
Signed-off-by: Maxime <maxime@cluster2600.com>
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
* ci: retrigger CI (flaky macOS C++ test)
The vector_column_indexer_test failure is a known flaky assertion in
hnsw_streamer_entity.h, unrelated to Python-only changes in this PR.
Signed-off-by: Maxime <maxime@cluster2600.com>
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
* chore: remove custom HTTP embedding example
Per maintainer feedback, examples requiring an external LLM server
belong in the zvec-web project rather than in this repository.
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
---------
Signed-off-by: Maxime <maxime@cluster2600.com>
Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>