Skip to main content

lc_vector_stores/
provider.rs

1// lc-vector-stores/src/provider.rs
2//! 向量存储提供者
3//!
4//! 提供多种向量存储引擎的选择:内存、持久化、Qdrant等
5
6use crate::{VectorStore, VectorStoreError};
7use std::sync::Arc;
8
9/// 向量存储类型枚举
10#[derive(Debug, Clone)]
11pub enum VectorStoreType {
12    /// 内存存储,适用于测试和小型应用
13    InMemory,
14
15    /// 文件持久化存储,适用于个人知识库
16    FileBacked {
17        /// 存储文件路径
18        path: String,
19        /// 向量维度
20        dimension: usize,
21    },
22
23    /// Qdrant 向量数据库,适用于生产环境
24    Qdrant { url: String, collection: String },
25}
26
27/// 向量存储提供者
28pub struct VectorStoreProvider;
29
30impl VectorStoreProvider {
31    /// 创建向量存储实例
32    pub async fn create(
33        store_type: VectorStoreType,
34    ) -> Result<Arc<dyn VectorStore>, VectorStoreError> {
35        match store_type {
36            VectorStoreType::InMemory => {
37                use crate::InMemoryVectorStore;
38                Ok(Arc::new(InMemoryVectorStore::new()))
39            }
40            VectorStoreType::FileBacked { path, dimension } => {
41                use crate::FileVectorStore;
42                let store = FileVectorStore::new(std::path::PathBuf::from(path), dimension)
43                    .await
44                    .map_err(|e| VectorStoreError::StorageError(e.to_string()))?;
45                Ok(Arc::new(store))
46            }
47            VectorStoreType::Qdrant { url, collection } => {
48                Self::create_qdrant_store(url, collection).await
49            }
50        }
51    }
52
53    /// 创建 Qdrant 向量存储
54    async fn create_qdrant_store(
55        url: String,
56        collection: String,
57    ) -> Result<Arc<dyn VectorStore>, VectorStoreError> {
58        #[cfg(feature = "qdrant-integration")]
59        {
60            use crate::{QdrantConfig, QdrantVectorStore};
61            let config = QdrantConfig::new(url, collection);
62            let store = QdrantVectorStore::new(config).await?;
63            Ok(Arc::new(store))
64        }
65
66        #[cfg(not(feature = "qdrant-integration"))]
67        {
68            // Q3: 未启用 feature 时显式报错,拒绝静默降级到内存存储 ——
69            // 生产代码若以为在写 Qdrant 实际写进内存,进程重启数据即丢。
70            Err(VectorStoreError::ConnectionError(format!(
71                "Qdrant 存储需要启用 'qdrant-integration' feature (url={url}, collection={collection});拒绝静默降级为 InMemory,请在 Cargo.toml 开启该 feature"
72            )))
73        }
74    }
75}
76
77/// 向量存储构建器,提供便利的创建方法
78pub struct VectorStoreBuilder {
79    store_type: VectorStoreType,
80}
81
82impl Default for VectorStoreBuilder {
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88impl VectorStoreBuilder {
89    pub fn new() -> Self {
90        Self {
91            store_type: VectorStoreType::InMemory,
92        }
93    }
94
95    pub fn in_memory() -> Self {
96        Self {
97            store_type: VectorStoreType::InMemory,
98        }
99    }
100
101    pub fn file_backed(path: impl Into<String>, dimension: usize) -> Self {
102        Self {
103            store_type: VectorStoreType::FileBacked {
104                path: path.into(),
105                dimension,
106            },
107        }
108    }
109
110    pub fn qdrant(url: impl Into<String>, collection: impl Into<String>) -> Self {
111        Self {
112            store_type: VectorStoreType::Qdrant {
113                url: url.into(),
114                collection: collection.into(),
115            },
116        }
117    }
118
119    pub async fn build(self) -> Result<Arc<dyn VectorStore>, VectorStoreError> {
120        VectorStoreProvider::create(self.store_type).await
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    #[tokio::test]
129    async fn test_create_in_memory() {
130        let result = VectorStoreProvider::create(VectorStoreType::InMemory).await;
131        assert!(result.is_ok());
132    }
133
134    #[tokio::test]
135    async fn test_builder_in_memory() {
136        let builder = VectorStoreBuilder::in_memory();
137        let store = builder.build().await;
138        assert!(store.is_ok());
139    }
140
141    #[cfg(not(feature = "qdrant-integration"))]
142    #[tokio::test]
143    async fn test_builder_qdrant_errors_when_feature_disabled() {
144        // Q3: 未启用 feature 时必须显式报错,不能静默降级到内存存储。
145        let builder = VectorStoreBuilder::qdrant("http://localhost:6334", "test_collection");
146        let store = builder.build().await;
147        assert!(store.is_err());
148    }
149}