diff --git a/proto/collections.proto b/proto/collections.proto index 474735f..ca9d8a5 100644 --- a/proto/collections.proto +++ b/proto/collections.proto @@ -145,6 +145,17 @@ enum CompressionRatio { x64 = 4; } +message MaxOptimizationThreads { + enum Setting { + Auto = 0; + } + + oneof variant { + uint64 value = 1; + Setting setting = 2; + } +} + message OptimizerStatus { bool ok = 1; string error = 2; @@ -237,7 +248,7 @@ message OptimizersConfigDiff { optional uint64 max_segment_size = 4; /* Maximum size (in kilobytes) of vectors to store in-memory per segment. - Segments larger than this threshold will be stored as read-only memmaped file. + Segments larger than this threshold will be stored as read-only memmapped file. Memmap storage is disabled by default, to enable it, set this threshold to a reasonable value. @@ -260,13 +271,17 @@ message OptimizersConfigDiff { Interval between forced flushes. */ optional uint64 flush_interval_sec = 7; + + // Deprecated in favor of `max_optimization_threads` + optional uint64 deprecated_max_optimization_threads = 8; + /* Max number of threads (jobs) for running optimizations per shard. Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. - If null - have no limit and choose dynamically to saturate CPU. + If "auto" - have no limit and choose dynamically to saturate CPU. If 0 - no optimization threads, optimizations will be disabled. */ - optional uint64 max_optimization_threads = 8; + optional MaxOptimizationThreads max_optimization_threads = 9; } message ScalarQuantization { @@ -320,6 +335,13 @@ message StrictModeConfig { optional uint32 search_max_hnsw_ef = 6; optional bool search_allow_exact = 7; optional float search_max_oversampling = 8; + optional uint64 upsert_max_batchsize = 9; + optional uint64 max_collection_vector_size_bytes = 10; + optional uint32 read_rate_limit = 11; // Max number of read operations per minute per replica + optional uint32 write_rate_limit = 12; // Max number of write operations per minute per replica + optional uint64 max_collection_payload_size_bytes = 13; + optional uint64 filter_max_conditions = 14; + optional uint64 condition_max_size = 15; } message CreateCollection { @@ -351,6 +373,7 @@ message UpdateCollection { optional VectorsConfigDiff vectors_config = 6; // New vector parameters optional QuantizationConfigDiff quantization_config = 7; // Quantization configuration of vector optional SparseVectorConfig sparse_vectors_config = 8; // New sparse vector parameters + optional StrictModeConfig strict_mode_config = 9; // New strict mode configuration } message DeleteCollection { @@ -430,6 +453,7 @@ message TextIndexParams { } message BoolIndexParams { + optional bool on_disk = 1; // If true - store index on disk. } message DatetimeIndexParams { @@ -530,7 +554,8 @@ enum ReplicaState { Listener = 4; // A shard which receives data, but is not used for search; Useful for backup shards PartialSnapshot = 5; // Deprecated: snapshot shard transfer is in progress; Updates should not be sent to (and are ignored by) the shard Recovery = 6; // Shard is undergoing recovered by an external node; Normally rejects updates, accepts updates if force is true - Resharding = 7; // Points are being migrated to this shard as part of resharding + Resharding = 7; // Points are being migrated to this shard as part of scale-up resharding + ReshardingScaleDown = 8; // Points are being migrated to this shard as part of scale-down resharding } message ShardKey { @@ -566,6 +591,15 @@ message ReshardingInfo { uint32 shard_id = 1; uint64 peer_id = 2; optional ShardKey shard_key = 3; + ReshardingDirection direction = 4; +} + +/* + Resharding direction, scale up or down in number of shards +*/ +enum ReshardingDirection { + Up = 0; // Scale up, add a new shard + Down = 1; // Scale down, remove a shard } message CollectionClusterInfoResponse { @@ -574,8 +608,7 @@ message CollectionClusterInfoResponse { repeated LocalShardInfo local_shards = 3; // Local shards repeated RemoteShardInfo remote_shards = 4; // Remote shards repeated ShardTransferInfo shard_transfers = 5; // Shard transfers - // TODO(resharding): enable on release: - // repeated ReshardingInfo resharding_operations = 6; // Resharding operations + repeated ReshardingInfo resharding_operations = 6; // Resharding operations } message MoveShard { diff --git a/proto/points.proto b/proto/points.proto index 03fa593..7078e0f 100644 --- a/proto/points.proto +++ b/proto/points.proto @@ -46,11 +46,48 @@ message SparseIndices { repeated uint32 data = 1; } +message Document { + string text = 1; // Text of the document + string model = 3; // Model name + map options = 4; // Model options +} + +message Image { + Value image = 1; // Image data, either base64 encoded or URL + string model = 2; // Model name + map options = 3; // Model options +} + +message InferenceObject { + Value object = 1; // Object to infer + string model = 2; // Model name + map options = 3; // Model options +} + // Legacy vector format, which determines the vector type by the configuration of its fields. message Vector { - repeated float data = 1; // Vector data (flatten for multi vectors) - optional SparseIndices indices = 2; // Sparse indices for sparse vectors - optional uint32 vectors_count = 3; // Number of vectors per multi vector + repeated float data = 1; // Vector data (flatten for multi vectors), deprecated + optional SparseIndices indices = 2; // Sparse indices for sparse vectors, deprecated + optional uint32 vectors_count = 3; // Number of vectors per multi vector, deprecated + oneof vector { + DenseVector dense = 101; // Dense vector + SparseVector sparse = 102; // Sparse vector + MultiDenseVector multi_dense = 103; // Multi dense vector + Document document = 104; + Image image = 105; + InferenceObject object = 106; + } +} + +message VectorOutput { + repeated float data = 1; // Vector data (flatten for multi vectors), deprecated + optional SparseIndices indices = 2; // Sparse indices for sparse vectors, deprecated + optional uint32 vectors_count = 3; // Number of vectors per multi vector, deprecated + oneof vector { + DenseVector dense = 101; // Dense vector + SparseVector sparse = 102; // Sparse vector + MultiDenseVector multi_dense = 103; // Multi dense vector + } } message DenseVector { @@ -73,6 +110,9 @@ message VectorInput { DenseVector dense = 2; SparseVector sparse = 3; MultiDenseVector multi_dense = 4; + Document document = 5; + Image image = 6; + InferenceObject object = 7; } } @@ -214,6 +254,10 @@ message NamedVectors { map vectors = 1; } +message NamedVectorsOutput { + map vectors = 1; +} + message Vectors { oneof vectors_options { Vector vector = 1; @@ -221,6 +265,13 @@ message Vectors { } } +message VectorsOutput { + oneof vectors_options { + VectorOutput vector = 1; + NamedVectorsOutput vectors = 2; + } +} + message VectorsSelector { repeated string names = 1; // List of vectors to include into result } @@ -737,7 +788,7 @@ message ScoredPoint { float score = 3; // Similarity score reserved 4; // deprecated "vector" field uint64 version = 5; // Last update operation applied to this point - optional Vectors vectors = 6; // Vectors to search + optional VectorsOutput vectors = 6; // Vectors to search optional ShardKey shard_key = 7; // Shard key optional OrderValue order_value = 8; // Order by value } @@ -766,21 +817,25 @@ message GroupsResult { message SearchResponse { repeated ScoredPoint result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message QueryResponse { repeated ScoredPoint result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message QueryBatchResponse { repeated BatchResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message QueryGroupsResponse { GroupsResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message BatchResult { @@ -790,16 +845,19 @@ message BatchResult { message SearchBatchResponse { repeated BatchResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message SearchGroupsResponse { GroupsResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message CountResponse { CountResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message ScrollResponse { @@ -816,7 +874,7 @@ message RetrievedPoint { PointId id = 1; map payload = 2; reserved 3; // deprecated "vector" field - optional Vectors vectors = 4; + optional VectorsOutput vectors = 4; optional ShardKey shard_key = 5; // Shard key optional OrderValue order_value = 6; // Order-by value } @@ -829,26 +887,31 @@ message GetResponse { message RecommendResponse { repeated ScoredPoint result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message RecommendBatchResponse { repeated BatchResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message DiscoverResponse { repeated ScoredPoint result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message DiscoverBatchResponse { repeated BatchResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message RecommendGroupsResponse { GroupsResult result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message UpdateBatchResponse { @@ -864,11 +927,13 @@ message FacetResponse { message SearchMatrixPairsResponse { SearchMatrixPairs result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } message SearchMatrixOffsetsResponse { SearchMatrixOffsets result = 1; double time = 2; // Time spent to process + optional HardwareUsage usage = 3; } // --------------------------------------------- @@ -895,6 +960,7 @@ message Condition { Filter filter = 4; IsNullCondition is_null = 5; NestedCondition nested = 6; + HasVectorCondition has_vector = 7; } } @@ -910,6 +976,10 @@ message HasIdCondition { repeated PointId has_id = 1; } +message HasVectorCondition { + string has_vector = 1; +} + message NestedCondition { string key = 1; // Path to nested object Filter filter = 2; // Filter condition @@ -1021,3 +1091,13 @@ message GeoPoint { double lon = 1; double lat = 2; } + +// --------------------------------------------- +// ------------ Hardware measurements ---------- +// --------------------------------------------- + +message HardwareUsage { + uint64 cpu = 1; + uint64 io_read = 2; + uint64 io_write = 3; +} diff --git a/src/builders/bool_index_params_builder.rs b/src/builders/bool_index_params_builder.rs new file mode 100644 index 0000000..966320e --- /dev/null +++ b/src/builders/bool_index_params_builder.rs @@ -0,0 +1,61 @@ +use crate::qdrant::*; + +pub struct BoolIndexParamsBuilder { + /// If true - store index on disk. + pub(crate) on_disk: Option>, +} + +impl Default for BoolIndexParamsBuilder { + fn default() -> Self { + Self::new() + } +} + +impl BoolIndexParamsBuilder { + pub fn new() -> Self { + Self::create_empty() + } + + /// If true - store index on disk. + #[allow(unused_mut)] + pub fn on_disk(self, value: bool) -> Self { + let mut new = self; + new.on_disk = Option::Some(Option::Some(value)); + new + } + + fn build_inner(self) -> Result { + Ok(BoolIndexParams { + on_disk: self.on_disk.unwrap_or_default(), + }) + } + /// Create an empty builder, with all fields set to `None` or `PhantomData`. + fn create_empty() -> Self { + Self { + on_disk: core::default::Default::default(), + } + } +} + +impl From for BoolIndexParams { + fn from(value: BoolIndexParamsBuilder) -> Self { + value.build_inner().unwrap_or_else(|_| { + panic!( + "Failed to convert {0} to {1}", + "BoolIndexParamsBuilder", "BoolIndexParams" + ) + }) + } +} + +impl BoolIndexParamsBuilder { + /// Builds the desired type. Can often be omitted. + pub fn build(self) -> BoolIndexParams { + self.build_inner().unwrap_or_else(|_| { + panic!( + "Failed to build {0} into {1}", + "BoolIndexParamsBuilder", "BoolIndexParams" + ) + }) + } +} diff --git a/src/builders/dense_vector_builder.rs b/src/builders/dense_vector_builder.rs new file mode 100644 index 0000000..fdf705c --- /dev/null +++ b/src/builders/dense_vector_builder.rs @@ -0,0 +1,48 @@ +use crate::qdrant::*; + +pub struct DenseVectorBuilder { + pub(crate) values: Vec, +} + +impl DenseVectorBuilder { + pub fn new(values: impl Into>) -> Self { + Self { + values: values.into(), + } + } + + #[allow(unused_mut)] + pub fn values(mut self, values: impl Into>) -> Self { + self.values = values.into(); + self + } + + /// Builds the desired type. Can often be omitted. + pub fn build(self) -> DenseVector { + DenseVector { data: self.values } + } +} + +impl From> for DenseVector { + fn from(values: Vec) -> Self { + DenseVectorBuilder::new(values).build() + } +} + +impl From for Vector { + fn from(dense_vector: DenseVector) -> Self { + crate::qdrant::vector::Vector::from(dense_vector).into() + } +} + +impl From for Vector { + fn from(dense_vector: DenseVectorBuilder) -> Self { + crate::qdrant::vector::Vector::from(dense_vector.build()).into() + } +} + +impl From for crate::qdrant::vector::Vector { + fn from(dense_vector: DenseVector) -> Self { + Self::Dense(dense_vector) + } +} diff --git a/src/builders/max_optimization_threads_builder.rs b/src/builders/max_optimization_threads_builder.rs new file mode 100644 index 0000000..2957628 --- /dev/null +++ b/src/builders/max_optimization_threads_builder.rs @@ -0,0 +1,87 @@ +use crate::qdrant::*; + +/// Max number of threads (jobs) for running optimizations per shard. +/// Each optimization job will also use `max_indexing_threads` threads by itself for index building. +/// +/// - If `auto` - have no limit and choose dynamically to saturate CPU. +/// - If `disabled` or `0` - no optimization threads, optimizations will be disabled. +pub struct MaxOptimizationThreadsBuilder { + pub(crate) inner: MaxOptimizationThreads, +} + +impl MaxOptimizationThreadsBuilder { + /// Use specific number of optimization threads. + /// + /// - If `0` - no optimization threads, optimizations will be disabled. + #[allow(unused_mut)] + #[inline] + pub fn threads(threads: u64) -> Self { + Self { + inner: MaxOptimizationThreads::from(threads), + } + } + + /// No optimization threads, optimizations will be disabled. + #[allow(unused_mut)] + #[inline] + pub fn disabled() -> Self { + Self::threads(0) + } + + /// Have no limit and choose dynamically to saturate CPU. + #[allow(unused_mut)] + #[inline] + pub fn auto() -> Self { + Self { + inner: MaxOptimizationThreads::from(max_optimization_threads::Variant::Setting( + max_optimization_threads::Setting::Auto as i32, + )), + } + } +} + +impl From for MaxOptimizationThreads { + fn from(value: MaxOptimizationThreadsBuilder) -> Self { + value.build() + } +} + +impl MaxOptimizationThreadsBuilder { + pub fn build(self) -> MaxOptimizationThreads { + self.inner + } +} + +impl Default for MaxOptimizationThreadsBuilder { + fn default() -> Self { + Self::auto() + } +} + +impl From for MaxOptimizationThreads { + fn from(threads: u64) -> Self { + MaxOptimizationThreads { + variant: Some(max_optimization_threads::Variant::from(threads)), + } + } +} + +impl From for MaxOptimizationThreads { + fn from(setting: max_optimization_threads::Variant) -> Self { + MaxOptimizationThreads { + variant: Some(setting), + } + } +} + +impl From for max_optimization_threads::Variant { + fn from(threads: u64) -> Self { + Self::Value(threads) + } +} + +impl From for max_optimization_threads::Variant { + fn from(setting: max_optimization_threads::Setting) -> Self { + Self::Setting(setting as i32) + } +} diff --git a/src/builders/mod.rs b/src/builders/mod.rs index 1b93015..b12cd57 100644 --- a/src/builders/mod.rs +++ b/src/builders/mod.rs @@ -52,6 +52,9 @@ pub use integer_index_params_builder::IntegerIndexParamsBuilder; mod float_index_params_builder; pub use float_index_params_builder::FloatIndexParamsBuilder; +mod bool_index_params_builder; +pub use bool_index_params_builder::BoolIndexParamsBuilder; + mod geo_index_params_builder; pub use geo_index_params_builder::GeoIndexParamsBuilder; @@ -70,6 +73,9 @@ pub use create_alias_builder::CreateAliasBuilder; mod rename_alias_builder; pub use rename_alias_builder::RenameAliasBuilder; +mod max_optimization_threads_builder; +pub use max_optimization_threads_builder::MaxOptimizationThreadsBuilder; + mod move_shard_builder; pub use move_shard_builder::MoveShardBuilder; @@ -210,3 +216,12 @@ pub use create_collection_builder::CreateCollectionBuilder; pub mod count_points_builder; pub use count_points_builder::*; + +pub mod dense_vector_builder; +pub use dense_vector_builder::DenseVectorBuilder; + +pub mod sparse_vector_builder; +pub use sparse_vector_builder::SparseVectorBuilder; + +pub mod multi_dense_vector_builder; +pub use multi_dense_vector_builder::MultiDenseVectorBuilder; diff --git a/src/builders/multi_dense_vector_builder.rs b/src/builders/multi_dense_vector_builder.rs new file mode 100644 index 0000000..59ac8d9 --- /dev/null +++ b/src/builders/multi_dense_vector_builder.rs @@ -0,0 +1,72 @@ +use crate::qdrant::*; + +#[derive(Default)] +pub struct MultiDenseVectorBuilder { + pub(crate) vectors: Vec, +} + +impl MultiDenseVectorBuilder { + pub fn new(vectors: impl Into>) -> Self { + Self { + vectors: vectors.into(), + } + } + + pub fn single(vector: impl Into) -> Self { + Self::new(vec![vector.into()]) + } + + #[allow(unused_mut)] + pub fn vectors(mut self, vectors: impl Into>) -> Self { + self.vectors = vectors.into(); + self + } + + #[allow(unused_mut)] + pub fn add_vector(mut self, vector: impl Into) -> Self { + self.vectors.push(vector.into()); + self + } + + /// Builds the desired type. Can often be omitted. + pub fn build(self) -> MultiDenseVector { + MultiDenseVector { + vectors: self.vectors, + } + } +} + +impl From>> for MultiDenseVector { + fn from(vectors: Vec>) -> Self { + Self::from( + vectors + .into_iter() + .map(DenseVector::from) + .collect::>(), + ) + } +} + +impl From> for MultiDenseVector { + fn from(vectors: Vec) -> Self { + MultiDenseVectorBuilder::new(vectors).build() + } +} + +impl From for Vector { + fn from(dense_vector: MultiDenseVector) -> Self { + crate::qdrant::vector::Vector::from(dense_vector).into() + } +} + +impl From for Vector { + fn from(dense_vector: MultiDenseVectorBuilder) -> Self { + crate::qdrant::vector::Vector::from(dense_vector.build()).into() + } +} + +impl From for crate::qdrant::vector::Vector { + fn from(dense_vector: MultiDenseVector) -> Self { + Self::MultiDense(dense_vector) + } +} diff --git a/src/builders/optimizers_config_diff_builder.rs b/src/builders/optimizers_config_diff_builder.rs index 78d1d4f..1f63a1d 100644 --- a/src/builders/optimizers_config_diff_builder.rs +++ b/src/builders/optimizers_config_diff_builder.rs @@ -51,10 +51,11 @@ pub struct OptimizersConfigDiffBuilder { pub(crate) flush_interval_sec: Option>, /// /// Max number of threads (jobs) for running optimizations per shard. - /// Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. - /// If null - have no limit and choose dynamically to saturate CPU. - /// If 0 - no optimization threads, optimizations will be disabled. - pub(crate) max_optimization_threads: Option>, + /// Each optimization job will also use `max_indexing_threads` threads by itself for index building. + /// + /// - If `auto` - have no limit and choose dynamically to saturate CPU. + /// - If `disabled` or `0` - no optimization threads, optimizations will be disabled. + pub(crate) max_optimization_threads: Option>, } impl OptimizersConfigDiffBuilder { @@ -143,13 +144,40 @@ impl OptimizersConfigDiffBuilder { } /// /// Max number of threads (jobs) for running optimizations per shard. - /// Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. - /// If null - have no limit and choose dynamically to saturate CPU. - /// If 0 - no optimization threads, optimizations will be disabled. + /// Each optimization job will also use `max_indexing_threads` threads by itself for index building. + /// + /// - If `auto` - have no limit and choose dynamically to saturate CPU. + /// - If `disabled` or `0` - no optimization threads, optimizations will be disabled. + /// + /// ```no_run + ///# use qdrant_client::{Qdrant, QdrantError}; + /// use qdrant_client::qdrant::{OptimizersConfigDiffBuilder, UpdateCollectionBuilder, MaxOptimizationThreadsBuilder}; + /// + ///# async fn create_collection(client: &Qdrant) + ///# -> Result<(), QdrantError> { + /// let optimizers_config = OptimizersConfigDiffBuilder::default() + /// // Use exactly 8 threads + /// .max_optimization_threads(8) + /// // Or automatically choose + /// .max_optimization_threads(MaxOptimizationThreadsBuilder::auto()) + /// // Or disable + /// .max_optimization_threads(MaxOptimizationThreadsBuilder::disabled()); + /// + /// client + /// .update_collection( + /// UpdateCollectionBuilder::new("my_collection").optimizers_config(optimizers_config), + /// ) + /// .await?; + ///# Ok(()) + ///# } + /// ``` #[allow(unused_mut)] - pub fn max_optimization_threads(self, value: u64) -> Self { + pub fn max_optimization_threads>( + self, + value: VALUE, + ) -> Self { let mut new = self; - new.max_optimization_threads = Option::Some(Option::Some(value)); + new.max_optimization_threads = Option::Some(Option::Some(value.into())); new } @@ -163,6 +191,8 @@ impl OptimizersConfigDiffBuilder { indexing_threshold: self.indexing_threshold.unwrap_or_default(), flush_interval_sec: self.flush_interval_sec.unwrap_or_default(), max_optimization_threads: self.max_optimization_threads.unwrap_or_default(), + // Deprecated: replaced with max_optimization_threads + deprecated_max_optimization_threads: None, }) } /// Create an empty builder, with all fields set to `None` or `PhantomData`. diff --git a/src/builders/sparse_vector_builder.rs b/src/builders/sparse_vector_builder.rs new file mode 100644 index 0000000..c225608 --- /dev/null +++ b/src/builders/sparse_vector_builder.rs @@ -0,0 +1,60 @@ +use crate::qdrant::*; + +#[derive(Default)] +pub struct SparseVectorBuilder { + pub(crate) indices: Vec, + pub(crate) values: Vec, +} + +impl SparseVectorBuilder { + pub fn new(indices: impl Into>, values: impl Into>) -> Self { + Self { + indices: indices.into(), + values: values.into(), + } + } + + #[allow(unused_mut)] + pub fn indices(mut self, indices: impl Into>) -> Self { + self.indices = indices.into(); + self + } + + #[allow(unused_mut)] + pub fn values(mut self, values: impl Into>) -> Self { + self.values = values.into(); + self + } + + /// Builds the desired type. Can often be omitted. + pub fn build(self) -> SparseVector { + SparseVector { + indices: self.indices, + values: self.values, + } + } +} + +impl From<(Vec, Vec)> for SparseVector { + fn from((indices, values): (Vec, Vec)) -> Self { + SparseVectorBuilder::new(indices, values).build() + } +} + +impl From for Vector { + fn from(dense_vector: SparseVector) -> Self { + crate::qdrant::vector::Vector::from(dense_vector).into() + } +} + +impl From for Vector { + fn from(dense_vector: SparseVectorBuilder) -> Self { + crate::qdrant::vector::Vector::from(dense_vector.build()).into() + } +} + +impl From for crate::qdrant::vector::Vector { + fn from(dense_vector: SparseVector) -> Self { + Self::Sparse(dense_vector) + } +} diff --git a/src/builders/strict_mode_config_builder.rs b/src/builders/strict_mode_config_builder.rs index 4f124be..eaa6b31 100644 --- a/src/builders/strict_mode_config_builder.rs +++ b/src/builders/strict_mode_config_builder.rs @@ -9,6 +9,13 @@ pub struct StrictModeConfigBuilder { pub(crate) search_max_hnsw_ef: Option>, pub(crate) search_allow_exact: Option>, pub(crate) search_max_oversampling: Option>, + pub(crate) upsert_max_batchsize: Option>, + pub(crate) max_collection_vector_size_bytes: Option>, + pub(crate) read_rate_limit: Option>, + pub(crate) write_rate_limit: Option>, + pub(crate) max_collection_payload_size_bytes: Option>, + pub(crate) filter_max_conditions: Option>, + pub(crate) condition_max_size: Option>, } impl StrictModeConfigBuilder { @@ -60,6 +67,48 @@ impl StrictModeConfigBuilder { new.search_max_oversampling = Option::Some(Option::Some(value)); new } + #[allow(unused_mut)] + pub fn upsert_max_batchsize(self, value: u64) -> Self { + let mut new = self; + new.upsert_max_batchsize = Option::Some(Option::Some(value)); + new + } + #[allow(unused_mut)] + pub fn max_collection_vector_size_bytes(self, value: u64) -> Self { + let mut new = self; + new.max_collection_vector_size_bytes = Option::Some(Option::Some(value)); + new + } + #[allow(unused_mut)] + pub fn read_rate_limit(self, value: u32) -> Self { + let mut new = self; + new.read_rate_limit = Option::Some(Option::Some(value)); + new + } + #[allow(unused_mut)] + pub fn write_rate_limit(self, value: u32) -> Self { + let mut new = self; + new.write_rate_limit = Option::Some(Option::Some(value)); + new + } + #[allow(unused_mut)] + pub fn max_collection_payload_size_bytes(self, value: u64) -> Self { + let mut new = self; + new.max_collection_payload_size_bytes = Option::Some(Option::Some(value)); + new + } + #[allow(unused_mut)] + pub fn filter_max_conditions(self, value: u64) -> Self { + let mut new = self; + new.filter_max_conditions = Option::Some(Option::Some(value)); + new + } + #[allow(unused_mut)] + pub fn condition_max_size(self, value: u64) -> Self { + let mut new = self; + new.condition_max_size = Option::Some(Option::Some(value)); + new + } fn build_inner(self) -> Result { Ok(StrictModeConfig { @@ -71,6 +120,17 @@ impl StrictModeConfigBuilder { search_max_hnsw_ef: self.search_max_hnsw_ef.unwrap_or_default(), search_allow_exact: self.search_allow_exact.unwrap_or_default(), search_max_oversampling: self.search_max_oversampling.unwrap_or_default(), + upsert_max_batchsize: self.upsert_max_batchsize.unwrap_or_default(), + max_collection_vector_size_bytes: self + .max_collection_vector_size_bytes + .unwrap_or_default(), + read_rate_limit: self.read_rate_limit.unwrap_or_default(), + write_rate_limit: self.write_rate_limit.unwrap_or_default(), + max_collection_payload_size_bytes: self + .max_collection_payload_size_bytes + .unwrap_or_default(), + filter_max_conditions: self.filter_max_conditions.unwrap_or_default(), + condition_max_size: self.condition_max_size.unwrap_or_default(), }) } /// Create an empty builder, with all fields set to `None` or `PhantomData`. @@ -84,6 +144,13 @@ impl StrictModeConfigBuilder { search_max_hnsw_ef: core::default::Default::default(), search_allow_exact: core::default::Default::default(), search_max_oversampling: core::default::Default::default(), + upsert_max_batchsize: core::default::Default::default(), + max_collection_vector_size_bytes: core::default::Default::default(), + read_rate_limit: core::default::Default::default(), + write_rate_limit: core::default::Default::default(), + max_collection_payload_size_bytes: core::default::Default::default(), + filter_max_conditions: core::default::Default::default(), + condition_max_size: core::default::Default::default(), } } } diff --git a/src/builders/update_collection_builder.rs b/src/builders/update_collection_builder.rs index f260e34..26c7886 100644 --- a/src/builders/update_collection_builder.rs +++ b/src/builders/update_collection_builder.rs @@ -18,6 +18,8 @@ pub struct UpdateCollectionBuilder { quantization_config: Option, /// New sparse vector parameters pub(crate) sparse_vectors_config: Option>, + /// New strict mode configuration + pub(crate) strict_mode_config: Option>, } impl UpdateCollectionBuilder { @@ -91,6 +93,16 @@ impl UpdateCollectionBuilder { new.sparse_vectors_config = Option::Some(Option::Some(value.into())); new } + /// New strict mode configuration + #[allow(unused_mut)] + pub fn strict_mode_config>( + self, + value: VALUE, + ) -> Self { + let mut new = self; + new.strict_mode_config = Option::Some(Option::Some(value.into())); + new + } fn build_inner(self) -> Result { Ok(UpdateCollection { @@ -109,6 +121,7 @@ impl UpdateCollectionBuilder { vectors_config: self.vectors_config.unwrap_or_default(), quantization_config: { convert_option(&self.quantization_config) }, sparse_vectors_config: self.sparse_vectors_config.unwrap_or_default(), + strict_mode_config: self.strict_mode_config.unwrap_or_default(), }) } /// Create an empty builder, with all fields set to `None` or `PhantomData`. @@ -122,6 +135,7 @@ impl UpdateCollectionBuilder { vectors_config: core::default::Default::default(), quantization_config: core::default::Default::default(), sparse_vectors_config: core::default::Default::default(), + strict_mode_config: core::default::Default::default(), } } } diff --git a/src/client/collection.rs b/src/client/collection.rs index a28a88c..8dd033a 100644 --- a/src/client/collection.rs +++ b/src/client/collection.rs @@ -140,6 +140,7 @@ impl QdrantClient { hnsw_config: hnsw_config.cloned(), vectors_config: vectors_config.cloned(), quantization_config: quantization_config.cloned(), + strict_mode_config: None, }) .await?; diff --git a/src/filters.rs b/src/filters.rs index f4d2256..8b9b91d 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -3,8 +3,8 @@ use crate::qdrant::points_selector::PointsSelectorOneOf; use crate::qdrant::r#match::MatchValue; use crate::qdrant::{ self, Condition, DatetimeRange, FieldCondition, Filter, GeoBoundingBox, GeoPolygon, GeoRadius, - HasIdCondition, IsEmptyCondition, IsNullCondition, MinShould, NestedCondition, PointId, - PointsSelector, Range, ValuesCount, + HasIdCondition, HasVectorCondition, IsEmptyCondition, IsNullCondition, MinShould, + NestedCondition, PointId, PointsSelector, Range, ValuesCount, }; impl From for PointsSelector { @@ -47,6 +47,14 @@ impl From for Condition { } } +impl From for Condition { + fn from(has_vector_condition: HasVectorCondition) -> Self { + Condition { + condition_one_of: Some(ConditionOneOf::HasVector(has_vector_condition)), + } + } +} + impl From for Condition { fn from(filter: Filter) -> Self { Condition { @@ -180,6 +188,18 @@ impl qdrant::Condition { }) } + /// Create a [`Condition`] to check if the point has a specific named vector. + /// + /// # Examples: + /// ``` + /// qdrant_client::qdrant::Condition::has_vector("my_vector"); + /// ``` + pub fn has_vector(vector_name: impl Into) -> Self { + Self::from(qdrant::HasVectorCondition { + has_vector: vector_name.into(), + }) + } + /// Create a [`Condition`] that matches a field against a certain value. /// /// # Examples: diff --git a/src/qdrant.rs b/src/qdrant.rs index acf5bf2..27e94f0 100644 --- a/src/qdrant.rs +++ b/src/qdrant.rs @@ -149,6 +149,54 @@ pub struct ListCollectionsResponse { #[prost(double, tag = "2")] pub time: f64, } +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct MaxOptimizationThreads { + #[prost(oneof = "max_optimization_threads::Variant", tags = "1, 2")] + pub variant: ::core::option::Option, +} +/// Nested message and enum types in `MaxOptimizationThreads`. +pub mod max_optimization_threads { + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum Setting { + Auto = 0, + } + impl Setting { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Auto => "Auto", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "Auto" => Some(Self::Auto), + _ => None, + } + } + } + #[derive(Clone, Copy, PartialEq, ::prost::Oneof)] + pub enum Variant { + #[prost(uint64, tag = "1")] + Value(u64), + #[prost(enumeration = "Setting", tag = "2")] + Setting(i32), + } +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct OptimizerStatus { #[prost(bool, tag = "1")] @@ -248,7 +296,7 @@ pub struct OptimizersConfigDiff { pub max_segment_size: ::core::option::Option, /// /// Maximum size (in kilobytes) of vectors to store in-memory per segment. - /// Segments larger than this threshold will be stored as read-only memmaped file. + /// Segments larger than this threshold will be stored as read-only memmapped file. /// /// Memmap storage is disabled by default, to enable it, set this threshold to a reasonable value. /// @@ -271,13 +319,16 @@ pub struct OptimizersConfigDiff { /// Interval between forced flushes. #[prost(uint64, optional, tag = "7")] pub flush_interval_sec: ::core::option::Option, + /// Deprecated in favor of `max_optimization_threads` + #[prost(uint64, optional, tag = "8")] + pub deprecated_max_optimization_threads: ::core::option::Option, /// /// Max number of threads (jobs) for running optimizations per shard. /// Note: each optimization job will also use `max_indexing_threads` threads by itself for index building. - /// If null - have no limit and choose dynamically to saturate CPU. + /// If "auto" - have no limit and choose dynamically to saturate CPU. /// If 0 - no optimization threads, optimizations will be disabled. - #[prost(uint64, optional, tag = "8")] - pub max_optimization_threads: ::core::option::Option, + #[prost(message, optional, tag = "9")] + pub max_optimization_threads: ::core::option::Option, } #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct ScalarQuantization { @@ -362,6 +413,22 @@ pub struct StrictModeConfig { pub search_allow_exact: ::core::option::Option, #[prost(float, optional, tag = "8")] pub search_max_oversampling: ::core::option::Option, + #[prost(uint64, optional, tag = "9")] + pub upsert_max_batchsize: ::core::option::Option, + #[prost(uint64, optional, tag = "10")] + pub max_collection_vector_size_bytes: ::core::option::Option, + /// Max number of read operations per minute per replica + #[prost(uint32, optional, tag = "11")] + pub read_rate_limit: ::core::option::Option, + /// Max number of write operations per minute per replica + #[prost(uint32, optional, tag = "12")] + pub write_rate_limit: ::core::option::Option, + #[prost(uint64, optional, tag = "13")] + pub max_collection_payload_size_bytes: ::core::option::Option, + #[prost(uint64, optional, tag = "14")] + pub filter_max_conditions: ::core::option::Option, + #[prost(uint64, optional, tag = "15")] + pub condition_max_size: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct CreateCollection { @@ -437,6 +504,9 @@ pub struct UpdateCollection { /// New sparse vector parameters #[prost(message, optional, tag = "8")] pub sparse_vectors_config: ::core::option::Option, + /// New strict mode configuration + #[prost(message, optional, tag = "9")] + pub strict_mode_config: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeleteCollection { @@ -577,7 +647,11 @@ pub struct TextIndexParams { pub on_disk: ::core::option::Option, } #[derive(Clone, Copy, PartialEq, ::prost::Message)] -pub struct BoolIndexParams {} +pub struct BoolIndexParams { + /// If true - store index on disk. + #[prost(bool, optional, tag = "1")] + pub on_disk: ::core::option::Option, +} #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct DatetimeIndexParams { /// If true - store index on disk. @@ -827,6 +901,8 @@ pub struct ReshardingInfo { pub peer_id: u64, #[prost(message, optional, tag = "3")] pub shard_key: ::core::option::Option, + #[prost(enumeration = "ReshardingDirection", tag = "4")] + pub direction: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct CollectionClusterInfoResponse { @@ -845,6 +921,9 @@ pub struct CollectionClusterInfoResponse { /// Shard transfers #[prost(message, repeated, tag = "5")] pub shard_transfers: ::prost::alloc::vec::Vec, + /// Resharding operations + #[prost(message, repeated, tag = "6")] + pub resharding_operations: ::prost::alloc::vec::Vec, } #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct MoveShard { @@ -1347,8 +1426,10 @@ pub enum ReplicaState { PartialSnapshot = 5, /// Shard is undergoing recovered by an external node; Normally rejects updates, accepts updates if force is true Recovery = 6, - /// Points are being migrated to this shard as part of resharding + /// Points are being migrated to this shard as part of scale-up resharding Resharding = 7, + /// Points are being migrated to this shard as part of scale-down resharding + ReshardingScaleDown = 8, } impl ReplicaState { /// String value of the enum field names used in the ProtoBuf definition. @@ -1365,6 +1446,7 @@ impl ReplicaState { Self::PartialSnapshot => "PartialSnapshot", Self::Recovery => "Recovery", Self::Resharding => "Resharding", + Self::ReshardingScaleDown => "ReshardingScaleDown", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -1378,6 +1460,37 @@ impl ReplicaState { "PartialSnapshot" => Some(Self::PartialSnapshot), "Recovery" => Some(Self::Recovery), "Resharding" => Some(Self::Resharding), + "ReshardingScaleDown" => Some(Self::ReshardingScaleDown), + _ => None, + } + } +} +/// +/// Resharding direction, scale up or down in number of shards +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ReshardingDirection { + /// Scale up, add a new shard + Up = 0, + /// Scale down, remove a shard + Down = 1, +} +impl ReshardingDirection { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Up => "Up", + Self::Down => "Down", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "Up" => Some(Self::Up), + "Down" => Some(Self::Down), _ => None, } } @@ -2817,18 +2930,106 @@ pub struct SparseIndices { #[prost(uint32, repeated, tag = "1")] pub data: ::prost::alloc::vec::Vec, } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Document { + /// Text of the document + #[prost(string, tag = "1")] + pub text: ::prost::alloc::string::String, + /// Model name + #[prost(string, tag = "3")] + pub model: ::prost::alloc::string::String, + /// Model options + #[prost(map = "string, message", tag = "4")] + pub options: ::std::collections::HashMap<::prost::alloc::string::String, Value>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Image { + /// Image data, either base64 encoded or URL + #[prost(message, optional, tag = "1")] + pub image: ::core::option::Option, + /// Model name + #[prost(string, tag = "2")] + pub model: ::prost::alloc::string::String, + /// Model options + #[prost(map = "string, message", tag = "3")] + pub options: ::std::collections::HashMap<::prost::alloc::string::String, Value>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct InferenceObject { + /// Object to infer + #[prost(message, optional, tag = "1")] + pub object: ::core::option::Option, + /// Model name + #[prost(string, tag = "2")] + pub model: ::prost::alloc::string::String, + /// Model options + #[prost(map = "string, message", tag = "3")] + pub options: ::std::collections::HashMap<::prost::alloc::string::String, Value>, +} /// Legacy vector format, which determines the vector type by the configuration of its fields. #[derive(Clone, PartialEq, ::prost::Message)] pub struct Vector { - /// Vector data (flatten for multi vectors) + /// Vector data (flatten for multi vectors), deprecated #[prost(float, repeated, tag = "1")] pub data: ::prost::alloc::vec::Vec, - /// Sparse indices for sparse vectors + /// Sparse indices for sparse vectors, deprecated #[prost(message, optional, tag = "2")] pub indices: ::core::option::Option, - /// Number of vectors per multi vector + /// Number of vectors per multi vector, deprecated #[prost(uint32, optional, tag = "3")] pub vectors_count: ::core::option::Option, + #[prost(oneof = "vector::Vector", tags = "101, 102, 103, 104, 105, 106")] + pub vector: ::core::option::Option, +} +/// Nested message and enum types in `Vector`. +pub mod vector { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Vector { + /// Dense vector + #[prost(message, tag = "101")] + Dense(super::DenseVector), + /// Sparse vector + #[prost(message, tag = "102")] + Sparse(super::SparseVector), + /// Multi dense vector + #[prost(message, tag = "103")] + MultiDense(super::MultiDenseVector), + #[prost(message, tag = "104")] + Document(super::Document), + #[prost(message, tag = "105")] + Image(super::Image), + #[prost(message, tag = "106")] + Object(super::InferenceObject), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VectorOutput { + /// Vector data (flatten for multi vectors), deprecated + #[prost(float, repeated, tag = "1")] + pub data: ::prost::alloc::vec::Vec, + /// Sparse indices for sparse vectors, deprecated + #[prost(message, optional, tag = "2")] + pub indices: ::core::option::Option, + /// Number of vectors per multi vector, deprecated + #[prost(uint32, optional, tag = "3")] + pub vectors_count: ::core::option::Option, + #[prost(oneof = "vector_output::Vector", tags = "101, 102, 103")] + pub vector: ::core::option::Option, +} +/// Nested message and enum types in `VectorOutput`. +pub mod vector_output { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Vector { + /// Dense vector + #[prost(message, tag = "101")] + Dense(super::DenseVector), + /// Sparse vector + #[prost(message, tag = "102")] + Sparse(super::SparseVector), + /// Multi dense vector + #[prost(message, tag = "103")] + MultiDense(super::MultiDenseVector), + } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DenseVector { @@ -2850,7 +3051,7 @@ pub struct MultiDenseVector { /// Vector type to be used in queries. Ids will be substituted with their corresponding vectors from the collection. #[derive(Clone, PartialEq, ::prost::Message)] pub struct VectorInput { - #[prost(oneof = "vector_input::Variant", tags = "1, 2, 3, 4")] + #[prost(oneof = "vector_input::Variant", tags = "1, 2, 3, 4, 5, 6, 7")] pub variant: ::core::option::Option, } /// Nested message and enum types in `VectorInput`. @@ -2865,6 +3066,12 @@ pub mod vector_input { Sparse(super::SparseVector), #[prost(message, tag = "4")] MultiDense(super::MultiDenseVector), + #[prost(message, tag = "5")] + Document(super::Document), + #[prost(message, tag = "6")] + Image(super::Image), + #[prost(message, tag = "7")] + Object(super::InferenceObject), } } #[derive(Clone, PartialEq, ::prost::Message)] @@ -3115,6 +3322,14 @@ pub struct NamedVectors { pub vectors: ::std::collections::HashMap<::prost::alloc::string::String, Vector>, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct NamedVectorsOutput { + #[prost(map = "string, message", tag = "1")] + pub vectors: ::std::collections::HashMap< + ::prost::alloc::string::String, + VectorOutput, + >, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct Vectors { #[prost(oneof = "vectors::VectorsOptions", tags = "1, 2")] pub vectors_options: ::core::option::Option, @@ -3130,6 +3345,21 @@ pub mod vectors { } } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct VectorsOutput { + #[prost(oneof = "vectors_output::VectorsOptions", tags = "1, 2")] + pub vectors_options: ::core::option::Option, +} +/// Nested message and enum types in `VectorsOutput`. +pub mod vectors_output { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum VectorsOptions { + #[prost(message, tag = "1")] + Vector(super::VectorOutput), + #[prost(message, tag = "2")] + Vectors(super::NamedVectorsOutput), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct VectorsSelector { /// List of vectors to include into result #[prost(string, repeated, tag = "1")] @@ -4154,7 +4384,7 @@ pub struct ScoredPoint { pub version: u64, /// Vectors to search #[prost(message, optional, tag = "6")] - pub vectors: ::core::option::Option, + pub vectors: ::core::option::Option, /// Shard key #[prost(message, optional, tag = "7")] pub shard_key: ::core::option::Option, @@ -4207,6 +4437,8 @@ pub struct SearchResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryResponse { @@ -4215,6 +4447,8 @@ pub struct QueryResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryBatchResponse { @@ -4223,6 +4457,8 @@ pub struct QueryBatchResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryGroupsResponse { @@ -4231,6 +4467,8 @@ pub struct QueryGroupsResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct BatchResult { @@ -4244,6 +4482,8 @@ pub struct SearchBatchResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct SearchGroupsResponse { @@ -4252,6 +4492,8 @@ pub struct SearchGroupsResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct CountResponse { @@ -4260,6 +4502,8 @@ pub struct CountResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ScrollResponse { @@ -4284,7 +4528,7 @@ pub struct RetrievedPoint { #[prost(map = "string, message", tag = "2")] pub payload: ::std::collections::HashMap<::prost::alloc::string::String, Value>, #[prost(message, optional, tag = "4")] - pub vectors: ::core::option::Option, + pub vectors: ::core::option::Option, /// Shard key #[prost(message, optional, tag = "5")] pub shard_key: ::core::option::Option, @@ -4307,6 +4551,8 @@ pub struct RecommendResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RecommendBatchResponse { @@ -4315,6 +4561,8 @@ pub struct RecommendBatchResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DiscoverResponse { @@ -4323,6 +4571,8 @@ pub struct DiscoverResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DiscoverBatchResponse { @@ -4331,6 +4581,8 @@ pub struct DiscoverBatchResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RecommendGroupsResponse { @@ -4339,6 +4591,8 @@ pub struct RecommendGroupsResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpdateBatchResponse { @@ -4363,6 +4617,8 @@ pub struct SearchMatrixPairsResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct SearchMatrixOffsetsResponse { @@ -4371,6 +4627,8 @@ pub struct SearchMatrixOffsetsResponse { /// Time spent to process #[prost(double, tag = "2")] pub time: f64, + #[prost(message, optional, tag = "3")] + pub usage: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Filter { @@ -4396,7 +4654,7 @@ pub struct MinShould { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Condition { - #[prost(oneof = "condition::ConditionOneOf", tags = "1, 2, 3, 4, 5, 6")] + #[prost(oneof = "condition::ConditionOneOf", tags = "1, 2, 3, 4, 5, 6, 7")] pub condition_one_of: ::core::option::Option, } /// Nested message and enum types in `Condition`. @@ -4415,6 +4673,8 @@ pub mod condition { IsNull(super::IsNullCondition), #[prost(message, tag = "6")] Nested(super::NestedCondition), + #[prost(message, tag = "7")] + HasVector(super::HasVectorCondition), } } #[derive(Clone, PartialEq, ::prost::Message)] @@ -4433,6 +4693,11 @@ pub struct HasIdCondition { pub has_id: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct HasVectorCondition { + #[prost(string, tag = "1")] + pub has_vector: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct NestedCondition { /// Path to nested object #[prost(string, tag = "1")] @@ -4618,6 +4883,15 @@ pub struct GeoPoint { #[prost(double, tag = "2")] pub lat: f64, } +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct HardwareUsage { + #[prost(uint64, tag = "1")] + pub cpu: u64, + #[prost(uint64, tag = "2")] + pub io_read: u64, + #[prost(uint64, tag = "3")] + pub io_write: u64, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum WriteOrderingType { diff --git a/src/qdrant_client/builders/vectors.rs b/src/qdrant_client/builders/vectors.rs index 3965c23..457c61e 100644 --- a/src/qdrant_client/builders/vectors.rs +++ b/src/qdrant_client/builders/vectors.rs @@ -1,37 +1,27 @@ -use crate::qdrant::{NamedVectors, SparseIndices, Vector}; +use crate::qdrant::{ + DenseVectorBuilder, MultiDenseVector, NamedVectors, SparseVectorBuilder, Vector, +}; use crate::QdrantError; impl Vector { + #[inline] pub fn new(values: Vec) -> Self { Self::new_dense(values) } - pub fn new_dense(values: Vec) -> Self { - Vector { - data: values, - indices: None, - vectors_count: None, - } + #[inline] + pub fn new_dense(values: impl Into>) -> Self { + DenseVectorBuilder::new(values.into()).build().into() } + #[inline] pub fn new_sparse(indices: impl Into>, values: impl Into>) -> Self { - Vector { - data: values.into(), - indices: Some(SparseIndices { - data: indices.into(), - }), - vectors_count: None, - } + SparseVectorBuilder::new(indices, values).build().into() } - pub fn new_multi(values: Vec>) -> Self { - let vectors_count = values.len() as u32; - - Vector { - data: values.into_iter().flatten().collect(), - indices: None, - vectors_count: Some(vectors_count), - } + #[inline] + pub fn new_multi(vectors: impl Into>>) -> Self { + MultiDenseVector::from(vectors.into()).into() } pub fn try_into_dense(self) -> Result, QdrantError> { @@ -107,3 +97,15 @@ impl NamedVectors { self } } + +impl From for Vector { + fn from(vector: crate::qdrant::vector::Vector) -> Self { + Vector { + vector: Some(vector), + // Deprecated + data: vec![], + indices: None, + vectors_count: None, + } + } +} diff --git a/src/qdrant_client/conversions/payloads.rs b/src/qdrant_client/conversions/payloads.rs index 85fa8f9..bf38a53 100644 --- a/src/qdrant_client/conversions/payloads.rs +++ b/src/qdrant_client/conversions/payloads.rs @@ -1,9 +1,10 @@ use crate::qdrant::payload_index_params::IndexParams; use crate::qdrant::{ - BoolIndexParams, DatetimeIndexParams, DatetimeIndexParamsBuilder, FloatIndexParams, - FloatIndexParamsBuilder, GeoIndexParams, GeoIndexParamsBuilder, IntegerIndexParams, - IntegerIndexParamsBuilder, KeywordIndexParams, KeywordIndexParamsBuilder, PayloadIndexParams, - TextIndexParams, TextIndexParamsBuilder, UuidIndexParams, UuidIndexParamsBuilder, + BoolIndexParams, BoolIndexParamsBuilder, DatetimeIndexParams, DatetimeIndexParamsBuilder, + FloatIndexParams, FloatIndexParamsBuilder, GeoIndexParams, GeoIndexParamsBuilder, + IntegerIndexParams, IntegerIndexParamsBuilder, KeywordIndexParams, KeywordIndexParamsBuilder, + PayloadIndexParams, TextIndexParams, TextIndexParamsBuilder, UuidIndexParams, + UuidIndexParamsBuilder, }; impl From for PayloadIndexParams { @@ -102,6 +103,18 @@ impl From for IndexParams { } } +impl From for IndexParams { + fn from(value: BoolIndexParams) -> Self { + Self::BoolIndexParams(value) + } +} + +impl From for IndexParams { + fn from(value: BoolIndexParamsBuilder) -> Self { + Self::BoolIndexParams(value.build()) + } +} + impl From for IndexParams { fn from(value: GeoIndexParams) -> Self { Self::GeoIndexParams(value) @@ -113,9 +126,3 @@ impl From for IndexParams { Self::GeoIndexParams(value.build()) } } - -impl From for IndexParams { - fn from(value: BoolIndexParams) -> Self { - Self::BoolIndexParams(value) - } -} diff --git a/src/qdrant_client/conversions/vectors.rs b/src/qdrant_client/conversions/vectors.rs index b9262af..81a337d 100644 --- a/src/qdrant_client/conversions/vectors.rs +++ b/src/qdrant_client/conversions/vectors.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use crate::qdrant::vectors::VectorsOptions; -use crate::qdrant::{NamedVectors, SparseIndices, Vector, Vectors}; +use crate::qdrant::{NamedVectors, Vector, Vectors}; impl From> for Vector { fn from(vector: Vec) -> Self { @@ -24,12 +24,8 @@ impl From>> for Vector { // Since we construct two new Vec's anyway it's fine to source from a reference impl From<&[(u32, f32)]> for Vector { fn from(tuples: &[(u32, f32)]) -> Self { - let (indices, values) = tuples.iter().cloned().unzip(); - Vector { - data: values, - indices: Some(SparseIndices { data: indices }), - vectors_count: None, - } + let (indices, values): (Vec<_>, Vec<_>) = tuples.iter().cloned().unzip(); + Self::new_sparse(indices, values) } }