Skip to main content

qdrant_edge/edge/config/
vectors.rs

1//! User-facing vector and sparse-vector parameters for the edge shard.
2//!
3//! Uses `on_disk` (bool) instead of internal `storage_type`. Per-vector quantization
4//! is supported via `EdgeVectorParams::quantization_config`; when set it overrides the
5//! global `EdgeShardConfig::quantization_config` for that vector.
6
7use crate::segment::data_types::modifier::Modifier;
8use crate::segment::index::sparse_index::sparse_index_config::{SparseIndexConfig, SparseIndexType};
9use crate::segment::types::{
10    Distance, HnswConfig, Indexes, MultiVectorConfig, QuantizationConfig, SparseVectorDataConfig,
11    SparseVectorStorageType, VectorDataConfig, VectorStorageDatatype, VectorStorageType,
12};
13use serde::{Deserialize, Serialize};
14use crate::shard::optimizers::config::DenseVectorOptimizerConfig;
15
16/// User-facing dense vector parameters.
17///
18/// Uses `on_disk: bool` instead of `storage_type`. Per-vector quantization is
19/// supported via `quantization_config` and overrides the global config when set.
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21#[serde(rename_all = "snake_case")]
22pub struct EdgeVectorParams {
23    pub size: usize,
24    pub distance: Distance,
25    /// If true, vector storage is on disk (mmap); otherwise in RAM.
26    /// Default is false (RAM).
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub on_disk: Option<bool>,
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub multivector_config: Option<MultiVectorConfig>,
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    pub datatype: Option<VectorStorageDatatype>,
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub quantization_config: Option<QuantizationConfig>,
35    #[serde(default, skip_serializing_if = "Option::is_none")]
36    pub hnsw_config: Option<HnswConfig>,
37}
38
39impl EdgeVectorParams {
40    /// Start building [`EdgeVectorParams`] with a fluent API. The two
41    /// required fields (`size`, `distance`) are supplied here.
42    pub fn builder(size: usize, distance: Distance) -> crate::edge::builders::EdgeVectorParamsBuilder {
43        crate::edge::builders::EdgeVectorParamsBuilder::new(size, distance)
44    }
45
46    /// Build `VectorDataConfig` for segment/optimizer use, using global quantization.
47    pub fn to_plain_vector_data_config(
48        &self,
49        global_quantization: Option<&QuantizationConfig>,
50    ) -> VectorDataConfig {
51        let EdgeVectorParams {
52            size,
53            distance,
54            on_disk,
55            multivector_config,
56            datatype,
57            quantization_config,
58            hnsw_config: _, // edge does not use per-vector HNSW config
59        } = self;
60
61        let resolved_quantization_config = quantization_config.as_ref().or(global_quantization);
62        let quantization_config =
63            QuantizationConfig::for_appendable_segment(resolved_quantization_config);
64        VectorDataConfig {
65            size: *size,
66            distance: *distance,
67            storage_type: VectorStorageType::from_on_disk(on_disk.unwrap_or_default()),
68            index: Indexes::Plain {},
69            quantization_config,
70            multivector_config: *multivector_config,
71            datatype: *datatype,
72        }
73    }
74
75    pub fn to_dense_vector_optimizer_config(
76        &self,
77        global_hnsw_config: &HnswConfig,
78        global_quantization_config: Option<&QuantizationConfig>,
79    ) -> DenseVectorOptimizerConfig {
80        let EdgeVectorParams {
81            size: _,
82            distance: _,
83            on_disk,
84            multivector_config: _,
85            datatype: _,
86            quantization_config,
87            hnsw_config,
88        } = self;
89        DenseVectorOptimizerConfig {
90            on_disk: *on_disk,
91            hnsw_config: hnsw_config.unwrap_or(*global_hnsw_config),
92            quantization_config: quantization_config
93                .clone()
94                .or_else(|| global_quantization_config.cloned()),
95        }
96    }
97
98    pub fn from_vector_data_config(v: &VectorDataConfig) -> Self {
99        let VectorDataConfig {
100            size,
101            distance,
102            storage_type,
103            index,
104            quantization_config, // edge uses global only
105            multivector_config,
106            datatype,
107        } = v;
108        Self {
109            size: *size,
110            distance: *distance,
111            on_disk: Some(storage_type.is_on_disk()),
112            multivector_config: *multivector_config,
113            datatype: *datatype,
114            quantization_config: quantization_config.clone(),
115            hnsw_config: match index {
116                Indexes::Plain {} => None,
117                Indexes::Hnsw(hnsw_config) => Some(*hnsw_config),
118            },
119        }
120    }
121}
122
123/// User-facing sparse vector parameters.
124///
125/// Uses `on_disk: bool` instead of internal storage/index type enums.
126#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
127#[serde(rename_all = "snake_case")]
128pub struct EdgeSparseVectorParams {
129    #[serde(default, skip_serializing_if = "Option::is_none")]
130    pub full_scan_threshold: Option<usize>,
131    /// If true, sparse index is on disk (mmap); otherwise in RAM.
132    #[serde(default, skip_serializing_if = "Option::is_none")]
133    pub on_disk: Option<bool>,
134    #[serde(default, skip_serializing_if = "Option::is_none")]
135    pub modifier: Option<Modifier>,
136    #[serde(default, skip_serializing_if = "Option::is_none")]
137    pub datatype: Option<VectorStorageDatatype>,
138}
139
140impl EdgeSparseVectorParams {
141    /// Start building [`EdgeSparseVectorParams`] with a fluent API.
142    pub fn builder() -> crate::edge::builders::EdgeSparseVectorParamsBuilder {
143        crate::edge::builders::EdgeSparseVectorParamsBuilder::new()
144    }
145
146    pub fn to_plain_sparse_vector_data_config(&self) -> SparseVectorDataConfig {
147        let EdgeSparseVectorParams {
148            full_scan_threshold,
149            on_disk: _,
150            modifier,
151            datatype,
152        } = self;
153        SparseVectorDataConfig {
154            index: SparseIndexConfig {
155                full_scan_threshold: *full_scan_threshold,
156                index_type: SparseIndexType::default(),
157                datatype: *datatype,
158            },
159            storage_type: SparseVectorStorageType::Mmap,
160            modifier: *modifier,
161        }
162    }
163
164    pub fn to_sparse_vector_optimizer_config(
165        &self,
166    ) -> crate::shard::optimizers::config::SparseVectorOptimizerConfig {
167        let EdgeSparseVectorParams {
168            full_scan_threshold: _,
169            on_disk,
170            modifier: _,
171            datatype: _,
172        } = self;
173        crate::shard::optimizers::config::SparseVectorOptimizerConfig { on_disk: *on_disk }
174    }
175
176    pub fn from_sparse_vector_data_config(s: &SparseVectorDataConfig) -> Self {
177        let SparseVectorDataConfig {
178            index,
179            storage_type: _, // edge uses on_disk from index_type
180            modifier,
181        } = s;
182        let SparseIndexConfig {
183            full_scan_threshold,
184            index_type,
185            datatype,
186        } = index;
187        Self {
188            full_scan_threshold: *full_scan_threshold,
189            on_disk: Some(index_type.is_on_disk()),
190            modifier: *modifier,
191            datatype: *datatype,
192        }
193    }
194}