Files
qdrant-cloud-bot bdee947aba feat(serverless): expose CollectionsService response time (#1452)
* feat(serverless): expose CollectionsService response time

Sync the serverless collections proto with the public-api `time` field and
surface it on create/delete/get/list results (sync and async clients).

* feat(serverless): drop objects_deleted from delete result

Match public-api DeleteCollectionResponse after removing the storage
object count from the tenant-facing delete reply.

* chore(serverless): sync DeleteCollectionResponse.time to field 2
2026-09-21 15:09:04 +02:00

198 lines
4.9 KiB
Python

"""Pydantic models for the Qdrant Serverless collection management API.
**In development — do not use yet.** Part of the experimental serverless client;
the API may change without notice.
These mirror the tenant-facing serverless config: unlike the regular client's
collection models, they deliberately expose no storage internals (quantization,
WAL, segments, on_disk placement, ...) - the serverless manager decides those.
"""
from enum import Enum
from typing import Literal, Optional, Union
from pydantic import BaseModel, Field
from qdrant_client.http.models import Distance, TokenizerType
class PrecisionTier(str, Enum):
"""How much vector precision may be traded for cost.
The manager turns this into a concrete quantization / datatype choice.
"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
class DenseVectorConfig(BaseModel):
"""Configuration of a single dense (embedding) vector."""
size: int
distance: Distance
multivector: bool = False
precision_tier: Optional[PrecisionTier] = None
class SparseVectorConfig(BaseModel):
"""Configuration of a single sparse vector."""
use_idf: bool = False
precision_tier: Optional[PrecisionTier] = None
class KeywordPrefixParams(BaseModel):
"""Prefix matching options for a keyword index. Presence enables prefix matching."""
class KeywordIndex(BaseModel):
"""Exact match on string values, e.g. `color: "red"`."""
type: Literal["keyword"] = "keyword"
prefix: Optional[KeywordPrefixParams] = None
class IntegerIndex(BaseModel):
"""Exact match and/or range filters on integers. Both default to enabled."""
type: Literal["integer"] = "integer"
lookup: Optional[bool] = None
range: Optional[bool] = None
class FloatIndex(BaseModel):
"""Range filters on floating point (and integer) numbers."""
type: Literal["float"] = "float"
class UuidIndex(BaseModel):
"""Exact match on UUID strings; like keyword but stored compactly."""
type: Literal["uuid"] = "uuid"
class DatetimeIndex(BaseModel):
"""Range filters on RFC 3339 datetimes."""
type: Literal["datetime"] = "datetime"
class StopwordsSet(BaseModel):
"""Tokens ignored by a full-text index."""
languages: list[str] = Field(default_factory=list)
custom: list[str] = Field(default_factory=list)
class SnowballParams(BaseModel):
"""Snowball stemming for a full-text index."""
language: str
class StemmingAlgorithm(BaseModel):
"""Stemming algorithm for a full-text index. Unset: no stemming.
Exactly one of `snowball` or `disabled` should be set.
"""
snowball: Optional[SnowballParams] = None
disabled: Optional[bool] = None
class TextIndex(BaseModel):
"""Full-text filtering on string values."""
type: Literal["text"] = "text"
tokenizer: Optional[TokenizerType] = None
lowercase: Optional[bool] = None
phrase_matching: Optional[bool] = None
min_token_len: Optional[int] = None
max_token_len: Optional[int] = None
ascii_folding: Optional[bool] = None
stopwords: Optional[StopwordsSet] = None
stemmer: Optional[StemmingAlgorithm] = None
class GeoIndex(BaseModel):
"""Geo radius / bounding box / polygon filters on `{lon, lat}` values."""
type: Literal["geo"] = "geo"
class BoolIndex(BaseModel):
"""Exact match on booleans."""
type: Literal["bool"] = "bool"
PayloadIndex = Union[
KeywordIndex,
IntegerIndex,
FloatIndex,
UuidIndex,
DatetimeIndex,
TextIndex,
GeoIndex,
BoolIndex,
]
class CollectionConfig(BaseModel):
"""The tenant-facing collection config.
Vector maps are keyed by vector name; the empty name "" is the unnamed
default vector. Payload indexes are keyed by payload field name
(JSON path, e.g. `user_id` or `meta.tags`).
"""
dense_vectors: dict[str, DenseVectorConfig] = Field(default_factory=dict)
sparse_vectors: dict[str, SparseVectorConfig] = Field(default_factory=dict)
payload_indexes: dict[str, PayloadIndex] = Field(default_factory=dict)
class CreateCollectionResult(BaseModel):
"""Result of `create_collection`."""
collection_name: str
result: str
time: float
class DeleteCollectionResult(BaseModel):
"""Result of `delete_collection`."""
deleted: bool
time: float
class CollectionInfo(BaseModel):
"""A collection's configuration and stats, as returned by `get_collection`.
`point_count` is eventually consistent and absent until stats have been
written for the collection.
"""
exists: bool
config: Optional[CollectionConfig] = None
point_count: Optional[int] = None
time: float
class CollectionSummary(BaseModel):
"""One collection in a `get_collections` listing."""
collection_name: str
point_count: Optional[int] = None
class CollectionsList(BaseModel):
"""A page of collections returned by `get_collections`."""
collections: list[CollectionSummary]
next_offset_token: Optional[str] = None
time: float