Skip to content

new: update models to 1.18, add create_named_vector and delete_named_vector#1201

Merged
joein merged 5 commits into
devfrom
models-1.18.0
May 8, 2026
Merged

new: update models to 1.18, add create_named_vector and delete_named_vector#1201
joein merged 5 commits into
devfrom
models-1.18.0

Conversation

@joein
Copy link
Copy Markdown
Member

@joein joein commented May 5, 2026

No description provided.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for poetic-froyo-8baba7 ready!

Name Link
🔨 Latest commit 6f84d5f
🔍 Latest deploy log https://app.netlify.com/projects/poetic-froyo-8baba7/deploys/69fcce25f08e890008a33db4
😎 Deploy Preview https://deploy-preview-1201--poetic-froyo-8baba7.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@joein joein requested a review from tbung May 5, 2026 10:19
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds named-vector management (create/delete vector name) across public, async, remote (gRPC/REST), and local clients; introduces Dense/Sparse vector creation configs and a VectorNameConfig alias. Adds gRPC messages/RPCs and HTTP endpoints for vector name lifecycle. Extends conversion layer, HTTP models, inspection cache, and protobufs to support new TurboQuantization and additional strict-mode/telemetry fields. Updates local collection storage and local remote persistence to handle named vectors. Adds congruence tests for named-vector operations and updates proto-generation tooling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • tbung
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning No description was provided by the author, making it impossible to assess whether it relates to the changeset. Add a description explaining the purpose of the model updates to version 1.18 and the new named vector management functionality to help reviewers understand the intent.
Docstring Coverage ⚠️ Warning Docstring coverage is 23.93% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main changes: updating models to version 1.18 and adding create_named_vector and delete_named_vector functionality, which aligns with the extensive additions to the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch models-1.18.0

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
qdrant_client/proto/collections.proto (1)

368-370: ⚡ Quick win

Resolve TODO field lifecycle in public schema before merge.

Line 368 introduces plus with a TODO in a public proto message. If this field is temporary, remove it now and reserve tag 3 to avoid future wire-compatibility ambiguity.

Suggested schema adjustment
 message TurboQuantization{
   optional bool always_ram = 1;
   optional TurboQuantBitSize bits = 2;
-
-  // TODO(turbo): Remove before release
-  optional bool plus = 3;
+  // Reserved to prevent accidental tag reuse from pre-release experiments.
+  reserved 3;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/proto/collections.proto` around lines 368 - 370, Remove the
temporary optional field "plus" (optional bool plus = 3;) from the public proto
message and replace it by reserving tag 3 (reserve 3;) to preserve wire
compatibility; remove the TODO comment and ensure any references to the "plus"
field in code/clients are deleted or migrated to avoid compilation/runtime
errors.
qdrant_client/http/models/models.py (1)

2952-2960: ⚡ Quick win

Constrain mode to known values instead of plain str.

At Line 2957, mode is documented as high_cpu/high_io but typed as str. Using Literal["high_cpu", "high_io"] (or a small enum) improves validation and generated client typing.

Proposed change
+from typing import Literal
...
 class SearchThreadPoolTelemetry(BaseModel):
@@
-    mode: str = Field(..., description="Currently active mode (`high_cpu` or `high_io`).")
+    mode: Literal["high_cpu", "high_io"] = Field(
+        ..., description="Currently active mode (`high_cpu` or `high_io`)."
+    )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/http/models/models.py` around lines 2952 - 2960, Change the
SearchThreadPoolTelemetry.mode field from a plain str to a constrained type so
only "high_cpu" or "high_io" are accepted: update the type annotation for mode
in the SearchThreadPoolTelemetry model to either typing.Literal["high_cpu",
"high_io"] or a small enum (e.g., class SearchMode(Enum): HIGH_CPU="high_cpu";
HIGH_IO="high_io") and adjust the Field import/usage accordingly so Pydantic
validation and generated client typing reflect the two allowed values.
tests/conversions/fixtures.py (1)

260-281: ⚡ Quick win

Add a TurboQuant fixture variant with model_id to close a round-trip coverage gap.

Current turbo fixtures validate bits variants, but they don’t exercise model_id preservation. Adding one fixture with model_id would catch mapping regressions immediately.

Proposed fixture extension
+turbo_quantization_with_model = grpc.TurboQuantization(
+    model_id="test-model-v1",
+    bits=grpc.TurboQuantBitSize.Bits2,
+)
+
+turbo_quantization_config_with_model = grpc.QuantizationConfig(
+    turboquant=turbo_quantization_with_model,
+)
+
+quantization_config_diff_turbo_with_model = grpc.QuantizationConfigDiff(
+    turboquant=turbo_quantization_with_model,
+)
     "QuantizationConfig": [
         quantization_config,
         binary_quantization_config,
         binary_quantization_config_0,
         binary_quantization_config_1,
         binary_quantization_config_2,
         binary_quantization_config_3,
         turbo_quantization_config,
         turbo_quantization_config_minimal,
         turbo_quantization_config_bits1,
         turbo_quantization_config_bits1_5,
         turbo_quantization_config_bits4,
+        turbo_quantization_config_with_model,
     ]
     + product_quantizations,
     "QuantizationConfigDiff": [
         quantization_config_diff_disabled,
         quantization_config_diff_scalar,
         quantization_config_diff_product,
         quantization_config_diff_turbo,
         quantization_config_diff_binary,
+        quantization_config_diff_turbo_with_model,
     ],

Also applies to: 855-874, 1777-1783

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/conversions/fixtures.py` around lines 260 - 281, Add a
TurboQuantization fixture that includes a model_id field to exercise round-trip
preservation of model identifiers: create a new variable (e.g.,
turbo_quantization_with_model_id) alongside the existing fixtures
(turbo_quantization, turbo_quantization_minimal, turbo_quantization_bits1,
turbo_quantization_bits1_5, turbo_quantization_bits4) and instantiate
grpc.TurboQuantization with a representative model_id string plus whatever other
fields you want (e.g., bits or always_ram) so serializers/mappers preserve
model_id during conversion tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qdrant_client/local/local_collection.py`:
- Around line 2878-2881: The code silently no-ops when self.config.vectors is a
models.VectorParams instance (single unnamed vector); detect that case in the
block around the assignment and replace self.config.vectors with a dict that
preserves the original unnamed VectorParams and adds the new named vector:
convert the existing VectorParams into a dict entry (e.g., key "" or other
implicit-name used elsewhere) and set self.config.vectors[vector_name] = params
so info() and consumers see the updated config; update the logic around
self.config.vectors, vector_name and params to handle both dict and VectorParams
cases consistently.

In `@qdrant_client/qdrant_remote.py`:
- Around line 2420-2467: The gRPC branch of create vector-name/update code
ignores the ordering argument (seen where CreateVectorNameRequest is built and
sent via self.grpc_points.CreateVectorName), causing transport-dependent
semantics; modify the gRPC request construction to include ordering (map
types.WriteOrdering to the corresponding grpc ordering enum/field using
RestToGrpc.convert_* or a new converter) and pass it into
grpc.CreateVectorNameRequest (or, if gRPC truly cannot support ordering,
explicitly raise a clear UnsupportedOperationError when ordering is provided) so
behavior matches the REST path; update the analogous block handling the other
CreateVectorName/CreateVector logic referenced around the later range
(2484-2498) as well.

---

Nitpick comments:
In `@qdrant_client/http/models/models.py`:
- Around line 2952-2960: Change the SearchThreadPoolTelemetry.mode field from a
plain str to a constrained type so only "high_cpu" or "high_io" are accepted:
update the type annotation for mode in the SearchThreadPoolTelemetry model to
either typing.Literal["high_cpu", "high_io"] or a small enum (e.g., class
SearchMode(Enum): HIGH_CPU="high_cpu"; HIGH_IO="high_io") and adjust the Field
import/usage accordingly so Pydantic validation and generated client typing
reflect the two allowed values.

In `@qdrant_client/proto/collections.proto`:
- Around line 368-370: Remove the temporary optional field "plus" (optional bool
plus = 3;) from the public proto message and replace it by reserving tag 3
(reserve 3;) to preserve wire compatibility; remove the TODO comment and ensure
any references to the "plus" field in code/clients are deleted or migrated to
avoid compilation/runtime errors.

In `@tests/conversions/fixtures.py`:
- Around line 260-281: Add a TurboQuantization fixture that includes a model_id
field to exercise round-trip preservation of model identifiers: create a new
variable (e.g., turbo_quantization_with_model_id) alongside the existing
fixtures (turbo_quantization, turbo_quantization_minimal,
turbo_quantization_bits1, turbo_quantization_bits1_5, turbo_quantization_bits4)
and instantiate grpc.TurboQuantization with a representative model_id string
plus whatever other fields you want (e.g., bits or always_ram) so
serializers/mappers preserve model_id during conversion tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 731edda5-8d1b-4a96-b79b-b6eb2b9b2253

📥 Commits

Reviewing files that changed from the base of the PR and between f6964b6 and 38c4c34.

📒 Files selected for processing (27)
  • qdrant_client/async_client_base.py
  • qdrant_client/async_qdrant_client.py
  • qdrant_client/async_qdrant_remote.py
  • qdrant_client/client_base.py
  • qdrant_client/conversions/common_types.py
  • qdrant_client/conversions/conversion.py
  • qdrant_client/embed/_inspection_cache.py
  • qdrant_client/grpc/collections_pb2.py
  • qdrant_client/grpc/collections_pb2.pyi
  • qdrant_client/grpc/points_pb2.py
  • qdrant_client/grpc/points_pb2.pyi
  • qdrant_client/grpc/points_service_pb2.py
  • qdrant_client/grpc/points_service_pb2_grpc.py
  • qdrant_client/http/api/collections_api.py
  • qdrant_client/http/api/service_api.py
  • qdrant_client/http/models/models.py
  • qdrant_client/local/async_qdrant_local.py
  • qdrant_client/local/local_collection.py
  • qdrant_client/local/qdrant_local.py
  • qdrant_client/proto/collections.proto
  • qdrant_client/proto/points.proto
  • qdrant_client/proto/points_service.proto
  • qdrant_client/qdrant_client.py
  • qdrant_client/qdrant_remote.py
  • tests/congruence_tests/test_modify_named_vector.py
  • tests/conversions/fixtures.py
  • tools/generate_grpc_client.sh

Comment thread qdrant_client/local/local_collection.py Outdated
Comment thread qdrant_client/qdrant_remote.py
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qdrant_client/local/local_collection.py`:
- Around line 2860-2864: The VectorParams construction assigned to params is
dropping the datatype from DenseVectorConfig; update the params =
models.VectorParams(...) call (where params is built from config) to include
datatype=config.datatype so the DenseVectorConfig.datatype value is forwarded
into VectorParams; locate the VectorParams instantiation in local_collection
(the params variable creation) and add the datatype field.
- Around line 2890-2892: The conversion of SparseVectorConfig to
models.SparseVectorParams is dropping the datatype property; update the
conversion so datatype is preserved by either adding a datatype field to
models.SparseVectorParams and including datatype=config.datatype when
constructing params in local_collection.py (the SparseVectorConfig -> params
creation block), or if models.SparseVectorParams should not hold datatype, route
config.datatype to the appropriate consumer (e.g., the index creation or vector
schema builder) instead—ensure SparseVectorConfig.datatype is forwarded from the
place where params are built (the params variable in local_collection.py) to
wherever the vector type is used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ae8a5d73-ff5d-447c-8423-47f311c56a07

📥 Commits

Reviewing files that changed from the base of the PR and between 4830c47 and 369581a.

📒 Files selected for processing (1)
  • qdrant_client/local/local_collection.py

Comment on lines +2860 to +2864
params = models.VectorParams(
size=config.size,
distance=config.distance,
multivector_config=config.multivector_config,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Show all fields defined on DenseVectorConfig and VectorParams to compare.

# Find DenseVectorConfig class definition and its fields
rg -n "DenseVectorConfig" --type py -A 30

# Show VectorParams fields for comparison
rg -n "class VectorParams" --type py -A 30

Repository: qdrant/qdrant-client

Length of output: 22410


Forward the datatype field from DenseVectorConfig to VectorParams.

The datatype field exists in DenseVectorConfig but is not passed when constructing VectorParams at line 2860-2864, causing that configuration to be silently dropped. Include it in the constructor:

Suggested fix
params = models.VectorParams(
    size=config.size,
    distance=config.distance,
    multivector_config=config.multivector_config,
    datatype=config.datatype,
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/local/local_collection.py` around lines 2860 - 2864, The
VectorParams construction assigned to params is dropping the datatype from
DenseVectorConfig; update the params = models.VectorParams(...) call (where
params is built from config) to include datatype=config.datatype so the
DenseVectorConfig.datatype value is forwarded into VectorParams; locate the
VectorParams instantiation in local_collection (the params variable creation)
and add the datatype field.

Comment thread qdrant_client/local/local_collection.py
@joein joein force-pushed the models-1.18.0 branch from 369581a to 5d547c0 Compare May 6, 2026 11:39
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
qdrant_client/local/local_collection.py (1)

2311-2327: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject sparse/multi relevance feedback here or add a matching scorer.

_preprocess_vector_input() can resolve using to sparse or multivector data, but this branch always builds a NaiveFeedbackQuery that later goes through the dense search path. In local mode that turns sparse feedback into a misleading “Dense vector … not found” failure instead of a supported query.

Suggested guard
         strategy = relevance_feedback.strategy
         if isinstance(strategy, models.NaiveFeedbackStrategy):
+            if vector_name in self.sparse_vectors or vector_name in self.multivectors:
+                raise ValueError(
+                    "Naive feedback is only supported for dense vectors in local mode"
+                )
             params = strategy.naive
             coefficients = NaiveFeedbackCoefficients(a=params.a, b=params.b, c=params.c)
             naive_query = NaiveFeedbackQuery(
                 target=target_vector,
                 feedback=feedback_items,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/local/local_collection.py` around lines 2311 - 2327, The
NaiveFeedbackStrategy branch always builds a NaiveFeedbackQuery and sends it
down the dense search path (via search), but _preprocess_vector_input can
resolve the `using` vector to sparse or multivector types causing incorrect
"Dense vector ... not found" failures; update the branch that handles
isinstance(strategy, models.NaiveFeedbackStrategy) to inspect the preprocessed
vector type (the output from _preprocess_vector_input or the resolved
`vector_name`/target_vector) and either (a) reject sparse/multivector feedback
with a clear error, or (b) route to or construct a matching scorer for
sparse/multivector inputs before calling search; reference
NaiveFeedbackStrategy, NaiveFeedbackQuery, _preprocess_vector_input, and search
when implementing the guard/routing.
♻️ Duplicate comments (1)
qdrant_client/local/local_collection.py (1)

2860-2864: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve datatype when creating dense named vectors.

The new dense-vector path still drops DenseVectorConfig.datatype, so local collections silently create the vector with the default dtype even when the caller requested another one.

Suggested fix
         params = models.VectorParams(
             size=config.size,
             distance=config.distance,
             multivector_config=config.multivector_config,
+            datatype=config.datatype,
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/local/local_collection.py` around lines 2860 - 2864, The
dense-vector creation path drops the DenseVectorConfig.datatype so vectors use
the default dtype; update the VectorParams construction to preserve the
requested dtype by setting the datatype field from the DenseVectorConfig (e.g.
change the models.VectorParams call that builds params to include
datatype=config.datatype). Locate the vector creation code using
models.VectorParams and the DenseVectorConfig instance named config and pass
config.datatype through so the local collection creates the named dense vector
with the correct dtype.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qdrant_client/async_qdrant_remote.py`:
- Around line 2207-2297: The public methods create_vector_name and
delete_vector_name accept an ordering parameter but when self._prefer_grpc is
True the ordering is not forwarded to grpc.CreateVectorNameRequest /
grpc.DeleteVectorNameRequest (proto has no ordering), causing silent behavior
drift; update both functions to check if ordering is not None when
self._prefer_grpc is True and raise a ValueError (with a clear message like
"ordering is not supported with gRPC; set prefer_grpc=False or omit ordering")
so callers are prevented from accidentally losing write-ordering semantics.
- Around line 2217-2243: The gRPC branch handling of vector_name_config in
async_qdrant_remote.py silently allows unknown types by leaving dense_config and
sparse_config as None; update the if/elif block that checks
isinstance(vector_name_config, models.DenseVectorNameConfig) and
isinstance(vector_name_config, models.SparseVectorNameConfig) to add an explicit
else that raises a TypeError with a clear message (mentioning the unexpected
type and the value of vector_name_config) so the client fails fast; follow the
pattern used in _try_argument_to_grpc_selector and cluster_collection_update for
message style and placement so callers get immediate, descriptive feedback
instead of sending an empty CreateVectorNameRequest.

In `@qdrant_client/local/local_collection.py`:
- Around line 2913-2931: delete_vector_name currently only mutates in-memory
structures and meta.json, leaving the vector data present in on-disk persisted
points; fix by, after removing the in-memory/vector-config entries in
delete_vector_name, detecting persistent collections and scanning all persisted
point records to remove the field(s) corresponding to vector_name (handle dense
vectors, sparse_vectors_idf entries and multivectors appropriately) and
re-persist each point (or rewrite each point file) so the vector data is
actually removed from disk; use the collection's existing persistence/write API
(or add a helper to load a point, delete the vector entry, write to a temp file
and atomically replace) and ensure meta.json/delete markers remain consistent
and errors are handled so the operation is durable.

In `@qdrant_client/proto/collections.proto`:
- Around line 368-370: Remove the temporary TurboQuantization.plus proto field
and all usages: delete the optional bool plus = 3; from the TurboQuantization
message in collections.proto, then remove the corresponding property from the
HTTP REST model TurboQuantQuantizationConfig, strip handling of .plus from the
gRPC<->REST conversion logic (conversion functions that read/write
TurboQuantization/TurboQuantQuantizationConfig), and update tests and fixtures
that reference TurboQuantization.plus; alternatively, if you must keep it for
experimentation, move it into a clearly versioned/experimental proto
message/path and update conversions and tests to use that experimental type
instead.

In `@qdrant_client/proto/points.proto`:
- Around line 378-405: Add an optional WriteOrdering field to both
CreateVectorNameRequest and DeleteVectorNameRequest so callers can enforce
Medium/Strong write consistency for named-vector schema changes: in
CreateVectorNameRequest (which currently ends with optional uint64 timeout = 6)
add "optional WriteOrdering ordering = 7;" and in DeleteVectorNameRequest (which
currently ends with optional uint64 timeout = 4) add "optional WriteOrdering
ordering = 5;". Ensure WriteOrdering is available/imported in this proto file
and run protoc to validate.

In `@qdrant_client/qdrant_remote.py`:
- Around line 2424-2476: The create_vector_name implementation must accept
grpc-native config objects: detect if vector_name_config is a
grpc.DenseVectorCreationConfig or grpc.SparseVectorCreationConfig and convert
them to the proper variants instead of treating them as REST models (and
conversely, in the gRPC branch accept models.DenseVectorNameConfig/
SparseVectorNameConfig). Update the logic in create_vector_name to: when
self._prefer_grpc is True, if vector_name_config is a
grpc.DenseVectorCreationConfig or grpc.SparseVectorCreationConfig, map/unwrap
those into the dense_config/sparse_config fields (reuse RestToGrpc.convert_*
helpers where appropriate); when self._prefer_grpc is False, if
vector_name_config is a grpc.*CreationConfig, wrap/translate it into
models.DenseVectorNameConfig or models.SparseVectorNameConfig before calling
http.collections_api.create_vector_name so serialization succeeds. Reference
symbols: create_vector_name, vector_name_config, grpc.DenseVectorCreationConfig,
grpc.SparseVectorCreationConfig, models.DenseVectorNameConfig,
models.SparseVectorNameConfig,
RestToGrpc.convert_datatype/convert_multivector_config/convert_modifier.

---

Outside diff comments:
In `@qdrant_client/local/local_collection.py`:
- Around line 2311-2327: The NaiveFeedbackStrategy branch always builds a
NaiveFeedbackQuery and sends it down the dense search path (via search), but
_preprocess_vector_input can resolve the `using` vector to sparse or multivector
types causing incorrect "Dense vector ... not found" failures; update the branch
that handles isinstance(strategy, models.NaiveFeedbackStrategy) to inspect the
preprocessed vector type (the output from _preprocess_vector_input or the
resolved `vector_name`/target_vector) and either (a) reject sparse/multivector
feedback with a clear error, or (b) route to or construct a matching scorer for
sparse/multivector inputs before calling search; reference
NaiveFeedbackStrategy, NaiveFeedbackQuery, _preprocess_vector_input, and search
when implementing the guard/routing.

---

Duplicate comments:
In `@qdrant_client/local/local_collection.py`:
- Around line 2860-2864: The dense-vector creation path drops the
DenseVectorConfig.datatype so vectors use the default dtype; update the
VectorParams construction to preserve the requested dtype by setting the
datatype field from the DenseVectorConfig (e.g. change the models.VectorParams
call that builds params to include datatype=config.datatype). Locate the vector
creation code using models.VectorParams and the DenseVectorConfig instance named
config and pass config.datatype through so the local collection creates the
named dense vector with the correct dtype.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 57e7ec5e-68b6-4f37-959e-f146a34ada63

📥 Commits

Reviewing files that changed from the base of the PR and between 369581a and 5d547c0.

📒 Files selected for processing (27)
  • qdrant_client/async_client_base.py
  • qdrant_client/async_qdrant_client.py
  • qdrant_client/async_qdrant_remote.py
  • qdrant_client/client_base.py
  • qdrant_client/conversions/common_types.py
  • qdrant_client/conversions/conversion.py
  • qdrant_client/embed/_inspection_cache.py
  • qdrant_client/grpc/collections_pb2.py
  • qdrant_client/grpc/collections_pb2.pyi
  • qdrant_client/grpc/points_pb2.py
  • qdrant_client/grpc/points_pb2.pyi
  • qdrant_client/grpc/points_service_pb2.py
  • qdrant_client/grpc/points_service_pb2_grpc.py
  • qdrant_client/http/api/collections_api.py
  • qdrant_client/http/api/service_api.py
  • qdrant_client/http/models/models.py
  • qdrant_client/local/async_qdrant_local.py
  • qdrant_client/local/local_collection.py
  • qdrant_client/local/qdrant_local.py
  • qdrant_client/proto/collections.proto
  • qdrant_client/proto/points.proto
  • qdrant_client/proto/points_service.proto
  • qdrant_client/qdrant_client.py
  • qdrant_client/qdrant_remote.py
  • tests/congruence_tests/test_modify_named_vector.py
  • tests/conversions/fixtures.py
  • tools/generate_grpc_client.sh
✅ Files skipped from review due to trivial changes (1)
  • qdrant_client/conversions/common_types.py

Comment thread qdrant_client/async_qdrant_remote.py
Comment thread qdrant_client/async_qdrant_remote.py
Comment thread qdrant_client/local/local_collection.py
Comment thread qdrant_client/proto/collections.proto Outdated
Comment thread qdrant_client/proto/points.proto
Comment thread qdrant_client/qdrant_remote.py
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (4)
qdrant_client/async_qdrant_remote.py (2)

2220-2243: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fail fast on unsupported vector_name_config types in gRPC path.

At Line [2220], only REST-model configs are matched. Any other runtime value leaves both dense_config and sparse_config unset, and Line [2249] still sends the request with an empty config instead of raising a client-side error.

💡 Suggested fix
             if isinstance(vector_name_config, models.DenseVectorNameConfig):
                 cfg = vector_name_config.dense
                 dense_config = grpc.DenseVectorCreationConfig(
                     size=cfg.size,
                     distance=RestToGrpc.convert_distance(cfg.distance),
                     multivector_config=RestToGrpc.convert_multivector_config(
                         cfg.multivector_config
                     )
                     if cfg.multivector_config is not None
                     else None,
                     datatype=RestToGrpc.convert_datatype(cfg.datatype)
                     if cfg.datatype is not None
                     else None,
                 )
             elif isinstance(vector_name_config, models.SparseVectorNameConfig):
                 cfg = vector_name_config.sparse
                 sparse_config = grpc.SparseVectorCreationConfig(
                     modifier=RestToGrpc.convert_modifier(cfg.modifier)
                     if cfg.modifier is not None
                     else None,
                     datatype=RestToGrpc.convert_datatype(cfg.datatype)
                     if cfg.datatype is not None
                     else None,
                 )
+            else:
+                raise TypeError(
+                    f"Unsupported vector_name_config type: {type(vector_name_config)}; "
+                    f"value={vector_name_config!r}"
+                )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/async_qdrant_remote.py` around lines 2220 - 2243, The code path
that builds grpc.DenseVectorCreationConfig / grpc.SparseVectorCreationConfig
only handles models.DenseVectorNameConfig and models.SparseVectorNameConfig,
leaving dense_config and sparse_config unset for any other runtime type; update
the logic around the vector_name_config handling (the block that uses
RestToGrpc.convert_* and constructs
DenseVectorCreationConfig/SparseVectorCreationConfig) to detect unsupported
types and immediately raise a clear client-side error (e.g., ValueError or
TypeError) referencing vector_name_config, instead of falling through and
sending an empty config; ensure the exception is thrown before the request is
built/sent so callers get fast, explicit failure when an unexpected
vector_name_config type is provided.

2244-2248: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Do not drop grpc-native ordering values.

At Line [2244] and Line [2284], non-models.WriteOrdering inputs are coerced to None. That silently discards valid grpc ordering values in gRPC mode.

💡 Suggested fix
-            grpc_ordering = (
-                RestToGrpc.convert_write_ordering(ordering)
-                if isinstance(ordering, models.WriteOrdering)
-                else None
-            )
+            grpc_ordering = ordering
+            if isinstance(ordering, models.WriteOrdering):
+                grpc_ordering = RestToGrpc.convert_write_ordering(ordering)
...
-            grpc_ordering = (
-                RestToGrpc.convert_write_ordering(ordering)
-                if isinstance(ordering, models.WriteOrdering)
-                else None
-            )
+            grpc_ordering = ordering
+            if isinstance(ordering, models.WriteOrdering):
+                grpc_ordering = RestToGrpc.convert_write_ordering(ordering)

Also applies to: 2284-2288

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/async_qdrant_remote.py` around lines 2244 - 2248, The code
currently coerces non-models.WriteOrdering inputs to None, which drops valid
gRPC-native ordering values; update both places where grpc_ordering (and the
similar variable at the second occurrence) is set — using
RestToGrpc.convert_write_ordering(ordering) if isinstance(ordering,
models.WriteOrdering) else keep the original ordering value (i.e., pass through
the incoming grpc-native ordering) instead of None — so replace the else branch
to return the original ordering; reference the grpc_ordering assignment and
RestToGrpc.convert_write_ordering usages in async_qdrant_remote.py (also apply
the same change at the second occurrence around the later lines).
qdrant_client/qdrant_remote.py (2)

2427-2456: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject unsupported vector_name_config inputs before sending gRPC request.

At Line [2427], only two model variants are parsed. For any other runtime type, both configs stay unset and Line [2462] still sends CreateVectorNameRequest, leading to a server-side failure instead of a clear client error.

💡 Suggested fix
             if isinstance(vector_name_config, models.DenseVectorNameConfig):
                 cfg = vector_name_config.dense
                 dense_config = grpc.DenseVectorCreationConfig(
                     size=cfg.size,
                     distance=RestToGrpc.convert_distance(cfg.distance),
                     multivector_config=(
                         RestToGrpc.convert_multivector_config(cfg.multivector_config)
                         if cfg.multivector_config is not None
                         else None
                     ),
                     datatype=(
                         RestToGrpc.convert_datatype(cfg.datatype)
                         if cfg.datatype is not None
                         else None
                     ),
                 )
             elif isinstance(vector_name_config, models.SparseVectorNameConfig):
                 cfg = vector_name_config.sparse
                 sparse_config = grpc.SparseVectorCreationConfig(
                     modifier=(
                         RestToGrpc.convert_modifier(cfg.modifier)
                         if cfg.modifier is not None
                         else None
                     ),
                     datatype=(
                         RestToGrpc.convert_datatype(cfg.datatype)
                         if cfg.datatype is not None
                         else None
                     ),
                 )
+            else:
+                raise TypeError(
+                    f"Unsupported vector_name_config type: {type(vector_name_config)}; "
+                    f"value={vector_name_config!r}"
+                )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/qdrant_remote.py` around lines 2427 - 2456, The code only
handles models.DenseVectorNameConfig and models.SparseVectorNameConfig but
proceeds to call CreateVectorNameRequest even when neither branch ran; add an
explicit else that rejects unsupported vector_name_config types (e.g., raise
TypeError or ValueError with a clear message) before building/sending the gRPC
CreateVectorNameRequest so the client fails fast; update the logic around
vector_name_config, dense_config, and sparse_config (same block that checks
isinstance against models.DenseVectorNameConfig and
models.SparseVectorNameConfig) to validate input and surface a helpful error
instead of letting the server return an opaque failure.

2457-2461: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve grpc ordering values in gRPC mode.

At Line [2457] and Line [2496], ordering is dropped to None unless it is models.WriteOrdering. This can silently remove requested ordering semantics.

💡 Suggested fix
-            grpc_ordering = (
-                RestToGrpc.convert_write_ordering(ordering)
-                if isinstance(ordering, models.WriteOrdering)
-                else None
-            )
+            grpc_ordering = ordering
+            if isinstance(ordering, models.WriteOrdering):
+                grpc_ordering = RestToGrpc.convert_write_ordering(ordering)
...
-            grpc_ordering = (
-                RestToGrpc.convert_write_ordering(ordering)
-                if isinstance(ordering, models.WriteOrdering)
-                else None
-            )
+            grpc_ordering = ordering
+            if isinstance(ordering, models.WriteOrdering):
+                grpc_ordering = RestToGrpc.convert_write_ordering(ordering)

Also applies to: 2496-2500

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qdrant_client/qdrant_remote.py` around lines 2457 - 2461, The code currently
sets grpc_ordering to None unless ordering is a models.WriteOrdering, which
drops already-formed gRPC ordering enums; update the logic around grpc_ordering
(the assignment using RestToGrpc.convert_write_ordering) so it preserves
ordering when it is already a gRPC enum: if ordering is an instance of
models.WriteOrdering call RestToGrpc.convert_write_ordering(ordering), else if
ordering is not None assign grpc_ordering = ordering (preserve existing gRPC
enum), otherwise None; apply the same change for both places that set
grpc_ordering (the blocks referencing RestToGrpc.convert_write_ordering and
models.WriteOrdering).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@qdrant_client/async_qdrant_remote.py`:
- Around line 2220-2243: The code path that builds
grpc.DenseVectorCreationConfig / grpc.SparseVectorCreationConfig only handles
models.DenseVectorNameConfig and models.SparseVectorNameConfig, leaving
dense_config and sparse_config unset for any other runtime type; update the
logic around the vector_name_config handling (the block that uses
RestToGrpc.convert_* and constructs
DenseVectorCreationConfig/SparseVectorCreationConfig) to detect unsupported
types and immediately raise a clear client-side error (e.g., ValueError or
TypeError) referencing vector_name_config, instead of falling through and
sending an empty config; ensure the exception is thrown before the request is
built/sent so callers get fast, explicit failure when an unexpected
vector_name_config type is provided.
- Around line 2244-2248: The code currently coerces non-models.WriteOrdering
inputs to None, which drops valid gRPC-native ordering values; update both
places where grpc_ordering (and the similar variable at the second occurrence)
is set — using RestToGrpc.convert_write_ordering(ordering) if
isinstance(ordering, models.WriteOrdering) else keep the original ordering value
(i.e., pass through the incoming grpc-native ordering) instead of None — so
replace the else branch to return the original ordering; reference the
grpc_ordering assignment and RestToGrpc.convert_write_ordering usages in
async_qdrant_remote.py (also apply the same change at the second occurrence
around the later lines).

In `@qdrant_client/qdrant_remote.py`:
- Around line 2427-2456: The code only handles models.DenseVectorNameConfig and
models.SparseVectorNameConfig but proceeds to call CreateVectorNameRequest even
when neither branch ran; add an explicit else that rejects unsupported
vector_name_config types (e.g., raise TypeError or ValueError with a clear
message) before building/sending the gRPC CreateVectorNameRequest so the client
fails fast; update the logic around vector_name_config, dense_config, and
sparse_config (same block that checks isinstance against
models.DenseVectorNameConfig and models.SparseVectorNameConfig) to validate
input and surface a helpful error instead of letting the server return an opaque
failure.
- Around line 2457-2461: The code currently sets grpc_ordering to None unless
ordering is a models.WriteOrdering, which drops already-formed gRPC ordering
enums; update the logic around grpc_ordering (the assignment using
RestToGrpc.convert_write_ordering) so it preserves ordering when it is already a
gRPC enum: if ordering is an instance of models.WriteOrdering call
RestToGrpc.convert_write_ordering(ordering), else if ordering is not None assign
grpc_ordering = ordering (preserve existing gRPC enum), otherwise None; apply
the same change for both places that set grpc_ordering (the blocks referencing
RestToGrpc.convert_write_ordering and models.WriteOrdering).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 45c53da8-3643-4657-8e4b-a920d40672b0

📥 Commits

Reviewing files that changed from the base of the PR and between 5d547c0 and d181177.

📒 Files selected for processing (12)
  • qdrant_client/async_qdrant_remote.py
  • qdrant_client/conversions/conversion.py
  • qdrant_client/embed/_inspection_cache.py
  • qdrant_client/grpc/collections_pb2.py
  • qdrant_client/grpc/collections_pb2.pyi
  • qdrant_client/grpc/points_pb2.py
  • qdrant_client/grpc/points_pb2.pyi
  • qdrant_client/http/models/models.py
  • qdrant_client/proto/collections.proto
  • qdrant_client/proto/points.proto
  • qdrant_client/qdrant_remote.py
  • tests/conversions/fixtures.py
✅ Files skipped from review due to trivial changes (1)
  • qdrant_client/grpc/collections_pb2.pyi
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/conversions/fixtures.py
  • qdrant_client/proto/collections.proto
  • qdrant_client/conversions/conversion.py
  • qdrant_client/embed/_inspection_cache.py
  • qdrant_client/grpc/points_pb2.pyi

@joein joein force-pushed the models-1.18.0 branch from ece1fc6 to 6f84d5f Compare May 7, 2026 17:38
@joein joein merged commit d72554e into dev May 8, 2026
12 checks passed
joein added a commit that referenced this pull request May 11, 2026
…vector (#1201)

* new: update models to 1.18, add create_named_vector and delete_named_vector

* fix: add missing strict mode config updates

* fix: fix local mode create and delete vector name

* new: update turbo quant fields

* fix: persist vector deletion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants