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    /// Build `VectorDataConfig` for segment/optimizer use, using global quantization.
41    pub fn to_plain_vector_data_config(
42        &self,
43        global_quantization: Option<&QuantizationConfig>,
44    ) -> VectorDataConfig {
45        let EdgeVectorParams {
46            size,
47            distance,
48            on_disk,
49            multivector_config,
50            datatype,
51            quantization_config,
52            hnsw_config: _, // edge does not use per-vector HNSW config
53        } = self;
54
55        let resolved_quantization_config = quantization_config.as_ref().or(global_quantization);
56        let quantization_config =
57            QuantizationConfig::for_appendable_segment(resolved_quantization_config);
58        VectorDataConfig {
59            size: *size,
60            distance: *distance,
61            storage_type: VectorStorageType::from_on_disk(on_disk.unwrap_or_default()),
62            index: Indexes::Plain {},
63            quantization_config,
64            multivector_config: *multivector_config,
65            datatype: *datatype,
66        }
67    }
68
69    pub fn to_dense_vector_optimizer_config(
70        &self,
71        global_hnsw_config: &HnswConfig,
72        global_quantization_config: Option<&QuantizationConfig>,
73    ) -> DenseVectorOptimizerConfig {
74        let EdgeVectorParams {
75            size: _,
76            distance: _,
77            on_disk,
78            multivector_config: _,
79            datatype: _,
80            quantization_config,
81            hnsw_config,
82        } = self;
83        DenseVectorOptimizerConfig {
84            on_disk: *on_disk,
85            hnsw_config: hnsw_config.unwrap_or(*global_hnsw_config),
86            quantization_config: quantization_config
87                .clone()
88                .or_else(|| global_quantization_config.cloned()),
89        }
90    }
91
92    pub fn from_vector_data_config(v: &VectorDataConfig) -> Self {
93        let VectorDataConfig {
94            size,
95            distance,
96            storage_type,
97            index,
98            quantization_config, // edge uses global only
99            multivector_config,
100            datatype,
101        } = v;
102        Self {
103            size: *size,
104            distance: *distance,
105            on_disk: Some(storage_type.is_on_disk()),
106            multivector_config: *multivector_config,
107            datatype: *datatype,
108            quantization_config: quantization_config.clone(),
109            hnsw_config: match index {
110                Indexes::Plain {} => None,
111                Indexes::Hnsw(hnsw_config) => Some(*hnsw_config),
112            },
113        }
114    }
115}
116
117/// User-facing sparse vector parameters.
118///
119/// Uses `on_disk: bool` instead of internal storage/index type enums.
120#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
121#[serde(rename_all = "snake_case")]
122pub struct EdgeSparseVectorParams {
123    #[serde(default, skip_serializing_if = "Option::is_none")]
124    pub full_scan_threshold: Option<usize>,
125    /// If true, sparse index is on disk (mmap); otherwise in RAM.
126    #[serde(default, skip_serializing_if = "Option::is_none")]
127    pub on_disk: Option<bool>,
128    #[serde(default, skip_serializing_if = "Option::is_none")]
129    pub modifier: Option<Modifier>,
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub datatype: Option<VectorStorageDatatype>,
132}
133
134impl EdgeSparseVectorParams {
135    pub fn to_plain_sparse_vector_data_config(&self) -> SparseVectorDataConfig {
136        let EdgeSparseVectorParams {
137            full_scan_threshold,
138            on_disk: _,
139            modifier,
140            datatype,
141        } = self;
142        SparseVectorDataConfig {
143            index: SparseIndexConfig {
144                full_scan_threshold: *full_scan_threshold,
145                index_type: SparseIndexType::default(),
146                datatype: *datatype,
147            },
148            storage_type: SparseVectorStorageType::Mmap,
149            modifier: *modifier,
150        }
151    }
152
153    pub fn to_sparse_vector_optimizer_config(
154        &self,
155    ) -> crate::shard::optimizers::config::SparseVectorOptimizerConfig {
156        let EdgeSparseVectorParams {
157            full_scan_threshold: _,
158            on_disk,
159            modifier: _,
160            datatype: _,
161        } = self;
162        crate::shard::optimizers::config::SparseVectorOptimizerConfig { on_disk: *on_disk }
163    }
164
165    pub fn from_sparse_vector_data_config(s: &SparseVectorDataConfig) -> Self {
166        let SparseVectorDataConfig {
167            index,
168            storage_type: _, // edge uses on_disk from index_type
169            modifier,
170        } = s;
171        let SparseIndexConfig {
172            full_scan_threshold,
173            index_type,
174            datatype,
175        } = index;
176        Self {
177            full_scan_threshold: *full_scan_threshold,
178            on_disk: Some(index_type.is_on_disk()),
179            modifier: *modifier,
180            datatype: *datatype,
181        }
182    }
183}