post_cortex_embeddings/vector_db/config.rs
1// Copyright (c) 2025, 2026 Julius ML
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12
13//! Vector database configuration and search quality presets.
14
15use std::path::PathBuf;
16
17/// Search mode for vector similarity search
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
19pub enum SearchMode {
20 /// Exact search using full linear scan - highest accuracy, slowest
21 Exact,
22 /// Approximate search using HNSW - fastest, good accuracy
23 Approximate,
24 /// Balanced search with optimized HNSW parameters - good speed/accuracy tradeoff
25 #[default]
26 Balanced,
27}
28
29/// Search quality preset for automatic parameter tuning
30#[derive(Debug, Clone, Copy)]
31pub enum SearchQualityPreset {
32 /// Fast search with lower accuracy (ef_search = 32)
33 Fast,
34 /// Balanced search (ef_search = 64)
35 Balanced,
36 /// Accurate search with higher recall (ef_search = 128)
37 Accurate,
38 /// Maximum accuracy search (ef_search = 256)
39 Maximum,
40}
41
42impl SearchQualityPreset {
43 /// Get ef_search value for this preset
44 pub fn ef_search(&self) -> usize {
45 match self {
46 SearchQualityPreset::Fast => 32,
47 SearchQualityPreset::Balanced => 64,
48 SearchQualityPreset::Accurate => 128,
49 SearchQualityPreset::Maximum => 256,
50 }
51 }
52}
53
54/// Configuration for the vector database
55#[derive(Debug, Clone)]
56pub struct VectorDbConfig {
57 /// Vector dimension (must match embedding model)
58 pub dimension: usize,
59 /// Maximum number of connections per node in HNSW
60 pub max_connections: usize,
61 /// Size of the dynamic candidate list
62 pub ef_construction: usize,
63 /// Size of the search candidate list
64 pub ef_search: usize,
65 /// Number of layers in HNSW hierarchy
66 pub num_layers: usize,
67 /// Enable vector quantization for memory optimization
68 pub enable_quantization: bool,
69 /// Quantization buckets (power of 2)
70 pub quantization_buckets: usize,
71 /// Enable HNSW indexing
72 pub enable_hnsw_index: bool,
73 /// Up to this many vectors, searches are exact linear scans and no HNSW
74 /// graph is maintained (inserts stay O(1)). The first insert that
75 /// crosses it builds the graph once; from then on it is kept up to date
76 /// incrementally. [`VectorDB::build_index`](super::VectorDB::build_index)
77 /// builds it explicitly regardless of size.
78 pub exact_search_threshold: usize,
79 /// Distance threshold for considering vectors similar
80 pub distance_threshold: f32,
81 /// Maximum number of vectors to store in total (all sources). Inserts
82 /// beyond it fail with an error; bulk inserts stop and warn.
83 pub max_vectors: usize,
84 /// Auto-save interval (number of operations)
85 pub auto_save_interval: usize,
86 /// Enable persistent storage
87 pub persistent_storage: bool,
88 /// Storage path
89 pub storage_path: Option<PathBuf>,
90 /// Enable Product Quantization for memory optimization
91 pub enable_product_quantization: bool,
92 /// Number of subvectors for PQ (must divide dimension evenly)
93 pub pq_subvectors: usize,
94 /// Bits per PQ code (2^bits centroids per subvector)
95 pub pq_bits: usize,
96 /// Keep in-memory BM25 postings over the vectors' text
97 /// ([`VectorDB::search_text`](super::VectorDB::search_text)), for storage
98 /// backends without full-text search of their own. Word frequencies for
99 /// [`VectorDB::query_terms`](super::VectorDB::query_terms) are kept
100 /// regardless.
101 pub full_text_index: bool,
102}
103
104impl Default for VectorDbConfig {
105 fn default() -> Self {
106 Self {
107 dimension: 384, // Default for MiniLM model
108 max_connections: 16,
109 ef_construction: 200,
110 ef_search: 50,
111 num_layers: 4,
112 // Off: the u8 copy is never read by search; keep it opt-in.
113 enable_quantization: false,
114 quantization_buckets: 256,
115 enable_hnsw_index: true,
116 exact_search_threshold: 10_000,
117 distance_threshold: 0.7,
118 max_vectors: 100_000,
119 auto_save_interval: 1000,
120 persistent_storage: false,
121 storage_path: None,
122 enable_product_quantization: false, // Disabled by default (experimental)
123 pq_subvectors: 8, // 384/8 = 48 dims per subvector
124 pq_bits: 8, // 256 centroids per subvector
125 full_text_index: false,
126 }
127 }
128}