91 Commits

Author SHA1 Message Date
Andrey Vasnetsov
1d4d6f02da Per-query IDF corpus for sparse vector search (#9661)
* Add per-query IDF corpus for sparse vector search

Let the caller choose, per query, which population sparse IDF statistics
are computed over. `params.idf` is either `"global"` (default, unchanged
behavior) or `{"corpus": <filter>}`, where the corpus filter is
independent of - and usually broader than - the retrieval filter.
Decoupling the two keeps the score scale stable when the retrieval
filter tightens: term importance is measured against a population the
user names, not against whatever subset the filter happens to select.

Design decisions:
- Corpus grammar is restricted to a conjunction (`must`) of `match`
  conditions on payload fields; loosening later is backward compatible.
- Strict mode validates the corpus filter like a read filter
  (unindexed fields rejected).
- `idf` on a vector without the IDF modifier is a validation error,
  never silently ignored.
- An empty corpus yields degenerate but corpus-scoped scores (smoothed
  IDF over N=0), never a fallback to global statistics - in multi-tenant
  collections a fallback would leak term statistics across tenants.

Implementation:
- QueryContext IDF stats are keyed by corpus, so one batch can mix
  requests with different corpora.
- Statistics come from the sparse index: df(term) is counted over the
  query terms' posting lists only, never by scanning stored vectors.
  Small corpora (under ~1/32 of the segment, by cardinality estimate)
  are kept as a sorted id list galloping through posting lists via
  skip_to; large ones as a dense membership mask filled streaming from
  the filtered-points iterator. A misestimated small corpus degrades
  into the mask.
- Exposed uniformly: REST (`params.idf`), gRPC (`IdfParams` message),
  edge python bindings; OpenAPI schema regenerated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Apply rustfmt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix clippy manual_is_multiple_of in sparse IDF corpus test.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Allow any filter as IDF corpus

Drop the must+match grammar restriction on the corpus filter. A
restriction enforced only as a validation step over the full Filter
type buys nothing; if a narrower corpus syntax is ever wanted, it
should be a dedicated API-level type instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix build: add memory field to SparseIndexConfig in idf corpus test

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: root <111755117+qdrant-cloud-bot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 11:16:47 +02:00
Andrey Vasnetsov
8c8a72d120 Remove read_multi_iter to fix macOS linker symbol overflow (#9643)
* remove unused iter_offsets

* Replace MultivectorOffsetsStorage::iter_offsets with callback-based for_each_offset

First step of removing the iterator-returning read API (whose deep,
composable generic types blow up mangled symbol size). Convert the
offsets read from an iterator to a callback the caller pushes into:

- trait method iter_offsets -> for_each_offset(ids, FnMut(usize, MultivectorOffset))
  returning common::universal_io::Result<()>
- Mmap impl now uses the callback read_batch (drops one read_iter use)
- Ram / Chunked impls push into the callback; Chunked still goes through
  iter_vectors for now (converted in a later step)
- the single caller (for_each_in_multi_batch) passes a closure

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Implement read_batch directly on ReadPipeline, not via read_iter

read_batch now drives the pipeline itself (refill-then-wait loop, like
read_multi_iter) and invokes the callback per result, instead of
consuming the iterator returned by read_iter. A step toward removing the
iterator-returning read API.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Remove the ReadMulti RPC from the StorageRead gRPC service

ReadMulti was the only real consumer of UniversalRead::read_multi (which
itself relies on read_multi_iter). Removing the RPC end-to-end clears the
path to dropping that read API. StorageReadService keeps all its other
RPCs (ListFiles, FileExists, FileLength, ReadBytes, ReadBytesStream,
ReadWhole, ReadBatch).

- proto: drop `rpc ReadMulti` + ReadMulti{Entry,Request,Response}
- regenerated lib/api + uio-client generated code; drop ReadMulti
  validation rules in lib/api/build.rs
- tonic: delete the read_multi handler + its 2 tests
- uio-client: delete Client::read_multi, the mock-server impl, and 2 tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Remove UniversalRead::read_multi

Its only real consumer was the StorageRead ReadMulti gRPC handler (removed
in the previous commit); the two wrapper forwarders had no callers. Drop
the trait method and both forwarders (typed/read_only), and remove the
io_uring test that only existed to compare read_multi vs read_multi_iter
(read_multi_iter stays covered by the other tests). Another step toward
removing the iterator-returning read API.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Drive ReadPipeline directly in gridstore read_from_pages

Replace the read_multi_iter call in Pages::read_from_pages with a direct
pipeline loop (refill-then-drain), scheduling each multi-page read on its
own page file. Behavior unchanged; another step toward removing the
iterator-returning read_multi_iter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Drive ReadPipeline directly in gridstore read_batch_from_pages

Replace the second read_multi_iter call (in Pages::read_batch_from_pages)
with a direct pipeline loop, scheduling each (ReadMeta, page, range) on its
own page file and propagating errors via GridstoreError. Single/multi-page
buffering and out-of-order reassembly are unchanged. No more read_multi_iter
in gridstore.

Measured overhead on warm mmap (both paths are zero-copy borrows): ~0.3 ns
per read of fixed control cost, flat across read sizes — well under 0.1% of
a real payload read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Drive ReadPipeline directly in on-disk postings with_posting_views

Replace read_iter in OnDiskPostings::with_posting_views with a direct
pipeline loop. wait_bytemuck yields a file-borrowed Cow, so postings are
still stored zero-copy in raw_postings (a read_batch swap would have forced
an owned copy of every posting list per query on the mmap backend).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Read on-disk posting headers via read_batch, drop the HeadersBatch iterator

headers_iter now reads headers with the callback read_batch API: each header
is parsed (copied) out of the read bytes, so nothing borrows the file past the
read — no pipeline needed. Since the read is now eager, HeadersBatch holds the
collected Vec<HeaderResult> directly instead of a Box<dyn Iterator>, dropping
the boxing, the dynamic dispatch, and the struct's lifetime parameter.
with_posting_views takes the Vec and still pipelines the posting reads.

Removes the last read_iter use in this file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Use read_batch in simple_disk_cache populate_from

populate_from reads one byte per block only to fault blocks into the local
cache, discarding the bytes — a no-op-callback read_batch fits exactly. Drives
the same DiskCachePipeline as before; one less read_iter caller.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Implement read_iter directly on ReadPipeline, not via read_multi_iter

read_iter now drives the pipeline itself (refill-then-wait loop, mirroring
read_bytes_iter) instead of mapping its ranges onto self and calling
read_multi_iter. Same signature and iterator contract, so all callers are
unchanged. Leaves iter_vectors as read_multi_iter's only remaining caller.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "Drive ReadPipeline directly in on-disk postings with_posting_views"

This reverts commit c02c41f17b.

* Add callback-based for_each_vector next to iter_vectors

for_each_vector drives the ReadPipeline directly across chunk files and
invokes a fallible callback per flattened multi-vector, returning
OperationResult, instead of returning an iterator built on read_multi_iter.
Callers will migrate onto it so iter_vectors (read_multi_iter's last caller)
can be removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Make dense for_each_in_batch / for_each_in_dense_batch fallible

Thread OperationResult up the dense batch-read path so io_uring read
errors propagate instead of being .expect()ed deep inside the storage.
The for_each_in_dense_batch scorer path (custom/metric query scorers)
now carries the Result to the infallible score() boundary where it is
.expect()ed; read_vectors keeps its () signature and .expect()s locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Convert dense read_vectors to for_each_vector

The read-only and appendable dense storage read_vectors impls drove
ChunkedVectors::iter_vectors directly; switch them to the callback-based
for_each_vector and .expect() the result at the (infallible) read_vectors
boundary. Removes the last dense-path iter_vectors callers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Convert quantized for_each_offset to for_each_vector + OperationResult

The two chunked MultivectorOffsetsStorage impls drove iter_vectors to read
the offset table; switch them to the callback-based for_each_vector.
for_each_vector returns OperationResult, so upgrade the for_each_offset
trait (and all four impls) from universal_io::Result to OperationResult
(the universal_io -> Operation direction, via ?). No error downgrade.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Convert EncodedStorage/EncodedVectors iter_batch to callback for_each_batch

The two chunked-mmap EncodedStorage impls drove ChunkedVectors::iter_vectors
to back iter_batch. Replace the iterator-returning iter_batch on both the
EncodedStorage and EncodedVectors traits (quantization crate) with a callback
for_each_batch(FnMut(usize, &[u8])), and switch the chunked impls to
for_each_vector. The callback is infallible: the chunked impls .expect() the
read internally, matching iter_vectors' prior panic-on-read-error behavior,
so no OperationError is downgraded. Scorers and the multivector readers adopt
the callback; the accumulating multivector path owns (to_vec) only when it
must buffer across components.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Convert multivector read paths to for_each_vector

The read_only multivector free fn chained two iter_vectors (offsets feeding
vectors) - the recursive iterator nesting behind the worst symbol bloat.
Replace it with a callback for_each_vector that resolves the per-point
offsets into a Vec first, then drives ChunkedVectors::for_each_vector over
the flattened vectors. Migrate both multivector storages' read_vectors and
for_each_in_batch_multi accordingly, .expect()ing at their infallible
boundaries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Remove read_multi_iter and ChunkedVectors::iter_vectors

With every caller migrated to callback-based for_each_vector/for_each_batch,
delete the last iterator-returning multi-read APIs: ChunkedVectors::iter_vectors
(segment) and the read_multi_iter trait method plus its mmap override, the
TypedStorage/ReadOnly wrapper forwarders, and the two io_uring unit tests.

These deeply-nested monomorphized iterator types (read_multi_iter feeding
read_multi_iter) produced >1 MiB mangled drop_in_place symbols that overflowed
the macOS ld symbol-name limit; the callback rewrite eliminates them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Pass owned Cow through for_each_vector/for_each_batch to avoid a copy

The callback-based readers handed the callback a borrowed `&[u8]`/`&[T]`,
forcing the quantized multivector batch read to `to_vec()` each sub-vector
into its per-point buffer. But io_uring-like backends already return a freshly
owned buffer per read (`ACow::Owned`), so that was a redundant second copy.

Change `ChunkedVectorsRead::for_each_vector` and the `EncodedStorage` /
`EncodedVectors` `for_each_batch` callbacks to receive `Cow<[..]>` by value.
The buffering path now `into_owned()`s it — a move when the backend returned
owned (the case this path targets), a copy only for a borrowed Cow (mmap),
which never reaches this path. Immediate-use callers (scorers,
score_point_max_similarity, the dense/multivector readers) just deref the Cow;
the dense readers drop their now-redundant `Cow::Borrowed` wraps.

Also clarifies the multivector reader: `SubVectorOwner`/`owners`/
`sub_vector_offsets` naming, docs, and a corrected comment noting the per-point
buffer is what makes regrouping order-independent under out-of-order completion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Drop the removed ReadMulti JWT access test; fix clippy unwrap_or_default

The ReadMulti StorageRead RPC was removed earlier in this branch, so the
consensus JWT-access test (and its registry entry) for it must go too. Also
switch the multivector buffer's `or_insert_with(SmallVec::new)` to
`or_default()` per clippy::unwrap_or_default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add MmapFile::read_batch

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: xzfc <xzfcpw@gmail.com>
2026-07-01 14:03:32 +02:00
xzfc
596e8c7c01 Cleanup FieldCondition validation (#9557) 2026-06-29 09:14:09 +02:00
Tim Visée
b9154713d7 Fix empty min_should with non-zero min_count matching everything (#9401)
* Empty match any with non-zero min count matches nothing

* Update description

* Validate that min_count is greater than 0
2026-06-19 13:28:51 +02:00
Djole
25a4d4906d fix: validate hnsw_ef search parameter (#9320)
* fix: validate hnsw_ef search parameter

* chore: regenerate openapi spec
2026-06-08 18:09:52 +02:00
qdrant-cloud-bot
c150bd5caa Strict mode: add max_disk_usage_percent (#9212)
* Strict mode: add `max_disk_usage_percent`

Mirrors `max_resident_memory_percent`: rejects disk-consuming update ops
(upsert, set/overwrite payload, update vectors) when the filesystem hosting
Qdrant storage is filled above the configured percentage. Delete-style ops
remain allowed so callers can free disk.

Disk usage is sampled via `statvfs` and TTL-cached for 5s (same cadence as
the resident-memory reader) so high-RPS request paths don't hammer the
syscall. Reader is keyed by path in `common::disk_usage` and returns `None`
on stat failure — callers (the strict-mode check) treat `None` as "skip",
matching the memory-check behaviour.

Plumbing follows the existing pattern: field on `StrictModeConfig` (+
output/diff/Hash), gRPC proto field `22`, validation 1..=100, REST/proto
conversions, and the hook into `check_strict_mode_toc_batch` alongside the
memory check (both guarded by `any_consumes_memory`).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix CI: Windows disk_usage test + e2e WAL config

- `missing_path_returns_none` panicked on Windows because
  `GetDiskFreeSpaceEx` succeeds for non-existent paths (it resolves up to
  the containing drive). Relax the assertion to "must not panic; if a
  value is returned it must be well-formed". The contract we care about
  (None on failure) is platform-defined, not something we can portably
  force.

- e2e test failed at batch 0 with "WAL buffer size exceeds available disk
  space": Qdrant's existing per-shard `DiskUsageWatcher` enforces
  `free >= 2 * wal_capacity_mb` and the default WAL didn't fit in the
  50 MB tmpfs. Bump tmpfs to 200 MB and shrink `wal_capacity_mb` to 1 MB
  (same pattern as `test_low_disk.py`) so our strict-mode gate is the
  one that fires, not the WAL pre-check. Raise the gate threshold to
  50% to match the larger headroom.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-01 11:32:25 +02:00
Jojii
7a8703f166 [TQDT] API (#9172)
* [ai] TQDT in the API

* [ai] unify new sparse error for TQDT

* Rename to `turbo4`

* Add `Turbo4` to comments and doc strings.

* Also validate named sparse vector creation
2026-05-29 15:26:39 +02:00
Roman Titov
53a8562521 Upgrade tonic to v0.14.6 (#9139) 2026-05-25 16:11:43 +02:00
Arnaud Gourlay
4cb494d3b6 Fix missing validation on adding named vector (#8776) 2026-04-23 12:23:38 +02:00
Andrey Vasnetsov
9686c8f952 low ram strict mode (#8715)
* [AI] strict mode parameter for limiting update requests if ram usage is over threshold

* opanAPI update

* [AI] end-to-end test

* fmt

* Fix e2e test: memory rejection check broken by string truncation

UnexpectedResponse.__str__() truncates the raw response body, cutting
off the `max_resident_memory_percent` hint at the end of the error
message. Use `resident memory usage` instead, which appears early
enough to survive the truncation.

Made-with: Cursor

* add grpc validation

* test check_resident_memory

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: Arnaud Gourlay <arnaud.gourlay@gmail.com>
2026-04-20 15:48:39 +02:00
Jojii
8c72d3b12f API Changes for TurboQuant (#8686)
* [ai + manual] API changes for TQ

* CI

* Add TurboQuant types to Python type stubs

Made-with: Cursor

* Revert "Add TurboQuant types to Python type stubs"

This reverts commit 6543af3244.

---------

Co-authored-by: Cursor Agent <agent@cursor.com>
Co-authored-by: generall <andrey@vasnetsov.com>
2026-04-16 12:12:33 +02:00
Andrey Vasnetsov
5a899b74de deep memory reporting (#8606)
* Add mincore-based memory stats to MmapFile

Add `resident_bytes()`, `disk_bytes()`, and `probe_memory_stats()` methods
to `MmapFile` for measuring page cache residency via `mincore(2)`. This is
the foundation for per-collection memory usage reporting.

Also extract `page_size()` as a public function in `mmap::advice`, replacing
the internal `PAGE_SIZE_MASK` with a direct page size cache.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [AI] introduce trait for reporting memory usage per component

* [AI] memory reporter implementation for vector storage

* [AI] implement MemoryReporter for QuantizedVectors

* [AI] implement MemoryReporter for VectorIndexEnum

* Implement MemoryReporter for IdTrackerEnum with RAM estimation

Add ram_usage_bytes() to all ID tracker types and their data structures:
- PointMappings, CompressedPointMappings, CompressedVersions,
  CompressedInternalToExternal, CompressedExternalToInternal
- MutableIdTracker, ImmutableIdTracker, InMemoryIdTracker

All ID trackers load their data into RAM (none use mmap for working data).
Files are reported as OnDisk (persistence only), actual RAM footprint
is reported via extra_ram_bytes. Uses struct destructuring to ensure
new fields trigger compile errors if not accounted for.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [AI] implement MemoryReporter for PayloadStorageEnum and adjust FileStorageIntent

* [AI] implement MemoryReporter for PayloadStorageEnum and adjust FileStorageIntent

* [AI] implement MemoryReporter for payload indexes: in-ram structures memory consumtion computation + caching

* [AI] implement MemoryReporter for payload indexes: in-ram structures memory consumtion computation + caching

* [AI] segment-level memory usage report

* [AI] Block 3: Aggregation Layer and Data Model + internal api for remote shard

* [AI] REST API handler

* fmt

* [AI] clippy fixes

* [AI] macos fix + proxy segment fix

* [AI] make text index estimation a bit more correct

* fix is_on_disk reporting for dense_vector_storage

* fix after rebase

* [AI] deep account for quantized vectors RAM usage + unify chunk size + shring volatile storage after load

* remove debug log

* cache in test

* make manual test easier to run

* rollback chunk size diff, but keep it for test only

* review fixes

* Use exhaustive match

* Use div_ceil on bits everywhere

It does not seem to be strictly necessary because the number of bits
should already be a multiple of the used container size bytes. Still
it's good practice to be careful with this calculation.

* Improve heap size bytes for encoded product quantization vectors

* Include vector stats for binary quantized vectors

* In volatile chunked vectors, include heap allocated vector

* Include rest of heap allocated structures for mutable map index

* In mutable geo index, the hash map is also heap allocated

* Update tests/manual/test_memory_reporting.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: timvisee <tim@visee.me>
Co-authored-by: Tim Visée <tim+github@visee.me>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-14 12:37:31 +02:00
Andrey Vasnetsov
acfb6503b1 crud named vectors (#8605)
* Add empty placeholder vector storage types for named vector CRUD

Introduce EmptyDenseVectorStorage and EmptySparseVectorStorage as
placeholder storages for newly created named vectors on immutable
segments. These report all vectors as deleted, consume no disk space,
and are reconstructed from segment config on load via the new
VectorStorageType::Empty and SparseVectorStorageType::Empty variants.

Key design decisions:
- is_on_disk is derived from original user config, not hardcoded
- MultiVectorConfig is preserved for multi-vector support
- Config mismatch optimizer skips Empty storage to avoid false rebuilds
- Quantization delegates normally (handles 0 vectors gracefully)
- get_vector includes debug_assert to catch unexpected access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* [AI] segment-level operations for creating and deleting anmed vectors

* [AI] implement named vector creation and deleting in proxy segment

* [AI] Step 3: Proxy Segment Handling for Named Vector Operations

* [AI] implement for Edge

* [AI] implement consensus operations for named vector operations

* [AI] refactor VectorNameConfig, remove VectorNameConfigInternal

* [AI] handle vector schema inconsistency in raft snapshot recovery

* [AI] rest + grpc API

* [AI] clippy

* [AI] generate openAPI schema

* fmt

* ci fixes

* [AI] fix jwt access test

* [AI] nop operation for awaiting of consensus-commited update ops

* [AI] move vector name operations into points service

* [AI] implement internal api for vector name operations

* [AI] change collection-level config along with segment level operation

* [AI] vector schema reconceliation instead of error

* fmt

* missing compile-time option

* [AI] integration test

* [AI] fix missing JWT tests

* [AI] remove NOP

* [AI] openapi test

* [AI] fix initialization of mutable segment

* [AI] more simple integration tests

* fmt

* [AI] make cluster test a bit harder

* [AI] make test less flacky

* [AI] rabbit comments

* [AI] check params compatibility before writing vector config

* [AI] make sure to register vector storages in structure payload index

* [AI] vector name validation

* lower vector length validation to 200 chars to account for prefix in filename

* [AI] proxy segment: prevent stale data leak through optimization

* fmt

* [AI] filter out removed vectors from proxy response

* [AI] handle vector name in proxy

* fmt

* adjust proxy info based on dropped vectors

* [AI] proxy segment: update filters to correct has_vector condition

* fmt

* clippy

* Fix consensus snapshot applicaiton for vector schema

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:45:18 +02:00
Daniel Boros
974fcb63c7 Feat/storage api over universal io (#8311)
* feat: add storage_read_service proto definition

* feat: update qdrant tonic definition

* feat: add list_files

* feat: add read_bytes

* feat: add read_bytes_stream

* feat: add read_batch & read_whole api

* feat: add read_multi

* fix: mod.rs

* feat: update resolve_path

* feat: add path resolve

* feat: add more tests and fix stream api

* feat: better error handling

* feat: add collection_base_path

* fix: potential EOF error

* fix: nested runtime panic on tests

* fix: github actions

* fix: auth tests

* fix: coderabbit pr review

* fix: linter

* fix: clippy

* fix: range validation and path resolve

* fix: linter

* fix: clippy

* fix: clippy

* fix: universal io error

* fix: incoming changes

* fix: compiler error

* feat: spilt impl

* fix: pr review

* fix: linter

* fix: dev changes

* fix: linter

* review fixes

* fmt

* chore: fix naming

* fix: pr reviews

* fix: rebase dev

* fix: clippy

* fix: tests

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2026-03-29 23:08:16 +02:00
Andrey Vasnetsov
171b7cffba distributed optimization info (#8120)
* [AI] initial implementation

* [AI] review fixes

* [manaul] some small fix

* [AI] fix issue about serializing optional fields

* upd schema

* [manual] review fixes

* [manual] only ask updatable replicas about optimizations
2026-02-13 13:58:17 +01:00
Luis Cossío
a43780941b [relevance feedback] add rest and grpc interfaces (#7399)
* add rest and grpc interfaces

Also handle inference for this query

* follow refactor from base branch

* renaming from Ms Cooper

* get started on validation testing

* more validations

* test equivalence with query when less than 2 feedback elements

* rename feedback query to relevance_feedback query

* fix extraction of context pairs

* rename feedback vector to example

* make coderabbit happier

* upd test

---------

Co-authored-by: Arnaud Gourlay <arnaud.gourlay@gmail.com>
2026-02-11 16:05:11 +01:00
AMIR
4f13b994e3 Add list shard keys API (#7615) 2025-11-28 21:50:09 -03:00
xzfc
c1c9eb9ddb Add ACORN-1 search (#7414)
* GraphLayersBase::try_for_each_link

* Add FilteredScorer::score_points_unfiltered

* Add GraphLayersBase::search_on_level_acorn()

* Add SearchParams::acorn API parameter

* Integrate ACORN to HNSW search

* Add doc

* review fixes

* Misc fixes

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2025-10-24 19:09:21 +00:00
xzfc
a0d62330c7 Use fs-err (#7319) 2025-09-29 12:47:10 +00:00
Arnaud Gourlay
bc13f01680 [strict-mode] Add max number of payload index count (#7222)
* [strict-mode] Add max number of payload index count

* improve docs and validation for StrictModeConfig

* fix from coderabbit

* test blocking access to payload indexes

* polish test
2025-09-15 13:12:40 +02:00
Arnaud Gourlay
c05df46d8e Fix missing gRPC API validations for PointsSelector (#7221) 2025-09-08 17:01:09 +02:00
Arnaud Gourlay
3420311fd7 Fix missing API validation for MinShould (#7217) 2025-09-05 13:16:09 +02:00
Luis Cossío
a2d3270eb8 Custom RRF k parameter (#7065)
* allow custom K parameter for RRF

* generate grpc docs and openapi

* use tagged type approach for parametrized fusions

* use params approach in grpc

* simplify api structure

* upd schema

* nits

* rest: parameterized rrf as query variant

* consistency in doc comments

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2025-08-20 15:05:27 -04:00
Andrey Vasnetsov
c188f5b7c4 Update if (#7006)
* implement condition parameter for upsert operation

* fmt

* update api schema

* implement conditional update for update-vectors op

* rename to update_filter for consistency

* add tests

* explicilty ignore strict mode for conditional updates

* rabbit review fix

* Also assert vector element before, confirm we don't normalize

* Simplify filter creation using new helper

* Rename merge_with_ids to with_point_ids

---------

Co-authored-by: timvisee <tim@visee.me>
Co-authored-by: Tim Visée <tim+github@visee.me>
2025-08-15 15:47:43 +02:00
Kumar Shivendu
34e18eb22c Allow retaining more closed segments (#6976)
* Retain more closed segments

* Add back rocksdb

* Update WalOptions/WalConfig across the code

* Use NonZeroUsize

* Expose via APIs

* Update gRPC docs

* Fix stoarge compat test

* recompile openapi.json with rocksdb

* default wal retain closed fn

* update openapi.json

* Use qdrant/wal latest commit and remove from config.yaml
2025-08-07 13:44:26 +02:00
Luis Cossío
6307510476 [MMR] expose as query variant in rest and grpc (#6797)
* expose mmr in rest and grpc

* fix referenced vectors in mmr queries

* rename to MmrInput in grpc for consistency

* mmr is now an optional parameter of nearest query

* fix score_threshold at local shard

* fix conversion of rest -> collection

* fix and refactor planned query

* nits

* rename `lambda` to `diversity` in interface

* handle score_threshold within mmr calculation

* add openapi test

* fix candidate limit at collection level

* candidate_limit -> candidates_limit

* finish rename to candidates_limit

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2025-07-11 10:39:12 -04:00
Tim Visée
5e1728dadd Add validation for legacy collection names (#6752)
* Add function for validating legacy collection names

* Apply legacy collection name validation everywhere

* Add more validation to gRPC endpoints

* Adjust tests
2025-06-24 20:02:40 +05:30
Arnaud Gourlay
7f0b48a8a3 Fix missing API validations (#6499) 2025-05-07 19:10:14 +02:00
Arnaud Gourlay
fc64334e29 Validate IntegerIndexParams (#6494)
* Validate IntegerIndexParams

* focus
2025-05-07 16:35:57 +02:00
Arnaud Gourlay
9d6a08e3ce Fix missing gRPC query validations (#6485) 2025-05-05 15:58:48 +02:00
Andrey Vasnetsov
0ea6bc0b25 Faster wal-delta transfer (#6458)
* implement internal batch-update api

* use batch update in wal-delta

* fix ci
2025-04-29 19:31:50 +02:00
Arnaud Gourlay
1d5d997615 Remove validation on CollectionInfo response type (#6107) 2025-03-04 17:30:24 +01:00
Tim Visée
47de3955db Fix deleted threshold validation in gRPC, should be in range [0.0, 1.0] (#5810) 2025-01-15 15:39:32 +01:00
Tim Visée
2f7cde3d45 Fix collection creation validation, disallow replication factor 0 (#5643)
* Validate default collection config in settings

* Validate shard number, replication/write consistency factor in gRPC

* Cleanup

* Add more validation rules

* Also validate strict mode config in gRPC CollectionConfig

* Update OpenAPI specification
2024-12-20 12:07:58 +01:00
Tim Visée
7d52c95253 Simplify gRPC validation (#5650) 2024-12-16 12:46:43 +01:00
Arnaud Gourlay
2a2a7033db Rate limit requests per minute (#5597)
* Rate limit requests per minute

* rename to remove time unit for API
2024-12-10 00:26:37 +01:00
Arnaud Gourlay
4f1ccbb031 gRPC API for Distance Matrix (#5011)
* gRPC API for Distance Matrix

* generate API docs

* apply correct limit to sample

* add JWT tests

* pluralitiy

* fix COO naming

* drops COO as it trips codespell and is redundant

* clarify docs
2024-09-04 20:25:00 +02:00
Jojii
e9bad464ff [Strict-Mode] Basic implementation (#4887)
* add CollectionRequestVerification

* add to api

* rebase

* improve implementation

* implement strict mode for SearchRequest+Batch

* improve code + fix Clippy

* improve error handling

* restructure StrictModeVerification trait

* generate docs

* check `enabled` option

* review remarks

* rename StrictModeConfigDiff in grpc

* use missing payload detection from issue api

* performance improvement

* decouple extractor from issues (#4945)

* some review remarks

* don't default to empty functions in StrictModeVerification trait

* update openapi

* filter_limit => query_limit

* replace discovery_max_context_size and recommend_max_examples with max_input_examples

* review remarks

* review fix: include possible index types into error message

* review remarks

---------

Co-authored-by: Luis Cossío <luis.cossio@qdrant.com>
Co-authored-by: generall <andrey@vasnetsov.com>
2024-08-29 10:49:23 +02:00
Luis Cossío
b92908f602 Add grpc endpoint for Facet (#4933)
* add grpc endpoint

* gen grpc docs
2024-08-22 14:27:25 +02:00
Arnaud Gourlay
c8844388d7 Update Validator 0.18 (#4894)
* Update Validator 0.18

* fix new test error message

* clearer geo error message

* fix error message

* fix unit tests

* Put spaces back

---------

Co-authored-by: timvisee <tim@visee.me>
2024-08-15 15:22:51 +02:00
Luis Cossío
ba43d16880 Support timeout in Facets (#4792)
* nits in segments_searcher

* implement timeout into segment faceting

* Add timeout to internal service api

* refactor iterator_ext, and add test
2024-08-02 12:57:20 -04:00
Luis Cossío
5a8c79e05e Facets in internal service (#4790)
* add `facet` to shard trait

* Add internal service

* gen grpc docs
2024-08-01 16:03:40 -04:00
Arnaud Gourlay
1d6f3549aa universal-query: gRPC batch API (#4513)
* universal-query: gRPC batch API

* regen gRPC docs

* enable jwt access test
2024-06-20 14:10:27 +02:00
Arnaud Gourlay
d4b8e482ff universal-query: gRPC query API (#4495)
* universal-query: gRPC query API

* misc fixes

* more review

* add custom validation on QueryPoints.limit

* fix jwt_access test for gRPC query
2024-06-18 21:14:30 +02:00
Luis Cossío
4132d9a226 universal-query: Introduce new RawVector and VectorInput messages (#4209)
* Introduce `RawVector` and `VectorInput` messages

* gen grpc docs

* remove extra `optional`

* gen grpc docs
2024-05-14 11:40:11 -04:00
Arnaud Gourlay
23971e72b7 Add missing validation for gRPC UpsertPoints (#4074) 2024-04-19 13:26:25 +02:00
Tim Visée
4e234d2110 Add peer metadata to consensus, tracking Qdrant versions (#3702)
* Add peer metadata state to consensus, update on sync local state

* Minor formatting improvements

* Use Qdrant version from constant

* Initialize empty metadata if not present on disk

* Refactor old parameter name

* Logging improvements based on review feedback

* Assert that Qdrant version matches crate version

* Do not use a custom (de)serializer for peer metadata

* Use semver directly for handling Qdrant versions

* Rename is_outdated to is_different_version

* Assert Qdrant version in build.rs

* Disable updating peer metadata until Qdrant 1.9

We do this, because if a node is running 1.8, there may still be nodes
running 1.7. Those nodes do not support this operation.

* clippy

---------

Co-authored-by: generall <andrey@vasnetsov.com>
2024-03-04 16:48:44 +01:00
Kumar Shivendu
cf9f5aab98 fix: Include git commit id while building docker image if possible (#3640)
* feat: Print commit id in dev container build workflow

* fix: Keep .git while building Qdrant binary in docker

* fix: Remove redundant printing of git commit id

* fix: Copy only git files first

* fix: Docker build should have commit id if present

* refactor: Use fewer lines of code

* feat: Use git commit id from build arg

* refactor: Use cleaner code

* Fix string reference issue

* fix: Dont print info log if commit is not set

* fix: Include git commit id in release containers

---------

Co-authored-by: timvisee <tim@visee.me>
2024-02-22 21:26:44 +05:30
Tim Visée
e7fbc39ae3 Add gRPC API to set shard cutoff point (#3661)
* Add functions to propagate updating cutoff point from collection level

* Add gRPC endpoint to set cutoff point

* Lock highest and cutoff clock maps separately
2024-02-22 13:29:09 +01:00
Ivan Pleshkov
a39c8925af Validate sparse indices in grpc search (#3225)
* validate sparse indices in grpc search

* add test

* validate into vector conversion
2024-02-12 10:45:27 +01:00