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 {
25        /// Qdrant 服务地址
26        url: String,
27        /// 集合名称
28        collection: String,
29    },
30}
31
32/// 向量存储提供者
33pub struct VectorStoreProvider;
34
35impl VectorStoreProvider {
36    /// 创建向量存储实例
37    pub async fn create(
38        store_type: VectorStoreType,
39    ) -> Result<Arc<dyn VectorStore>, VectorStoreError> {
40        match store_type {
41            VectorStoreType::InMemory => {
42                use crate::InMemoryVectorStore;
43                Ok(Arc::new(InMemoryVectorStore::new()))
44            }
45            VectorStoreType::FileBacked { path, dimension } => {
46                use crate::FileVectorStore;
47                let store = FileVectorStore::new(std::path::PathBuf::from(path), dimension)
48                    .await
49                    .map_err(|e| VectorStoreError::StorageError(e.to_string()))?;
50                Ok(Arc::new(store))
51            }
52            VectorStoreType::Qdrant { url, collection } => {
53                Self::create_qdrant_store(url, collection).await
54            }
55        }
56    }
57
58    /// 创建 Qdrant 向量存储
59    async fn create_qdrant_store(
60        url: String,
61        collection: String,
62    ) -> Result<Arc<dyn VectorStore>, VectorStoreError> {
63        #[cfg(feature = "qdrant-integration")]
64        {
65            use crate::{QdrantConfig, QdrantVectorStore};
66            let config = QdrantConfig::new(url, collection);
67            let store = QdrantVectorStore::new(config).await?;
68            Ok(Arc::new(store))
69        }
70
71        #[cfg(not(feature = "qdrant-integration"))]
72        {
73            // Q3: 未启用 feature 时显式报错,拒绝静默降级到内存存储 ——
74            // 生产代码若以为在写 Qdrant 实际写进内存,进程重启数据即丢。
75            Err(VectorStoreError::ConnectionError(format!(
76                "Qdrant store requires the 'qdrant-integration' feature (url={url}, collection={collection}); refusing to silently fall back to InMemory, enable the feature in Cargo.toml"
77            )))
78        }
79    }
80}
81
82/// 向量存储构建器,提供便利的创建方法
83pub struct VectorStoreBuilder {
84    store_type: VectorStoreType,
85}
86
87impl Default for VectorStoreBuilder {
88    fn default() -> Self {
89        Self::new()
90    }
91}
92
93impl VectorStoreBuilder {
94    /// 创建默认的内存存储构建器
95    pub fn new() -> Self {
96        Self {
97            store_type: VectorStoreType::InMemory,
98        }
99    }
100
101    /// 创建内存存储构建器
102    pub fn in_memory() -> Self {
103        Self {
104            store_type: VectorStoreType::InMemory,
105        }
106    }
107
108    /// 创建文件持久化存储构建器
109    pub fn file_backed(path: impl Into<String>, dimension: usize) -> Self {
110        Self {
111            store_type: VectorStoreType::FileBacked {
112                path: path.into(),
113                dimension,
114            },
115        }
116    }
117
118    /// 创建 Qdrant 存储构建器
119    pub fn qdrant(url: impl Into<String>, collection: impl Into<String>) -> Self {
120        Self {
121            store_type: VectorStoreType::Qdrant {
122                url: url.into(),
123                collection: collection.into(),
124            },
125        }
126    }
127
128    /// 构建向量存储实例
129    pub async fn build(self) -> Result<Arc<dyn VectorStore>, VectorStoreError> {
130        VectorStoreProvider::create(self.store_type).await
131    }
132}
133
134#[cfg(test)]
135mod tests {
136    use super::*;
137
138    #[tokio::test]
139    async fn test_create_in_memory() {
140        let result = VectorStoreProvider::create(VectorStoreType::InMemory).await;
141        assert!(result.is_ok());
142    }
143
144    #[tokio::test]
145    async fn test_builder_in_memory() {
146        let builder = VectorStoreBuilder::in_memory();
147        let store = builder.build().await;
148        assert!(store.is_ok());
149    }
150
151    #[cfg(not(feature = "qdrant-integration"))]
152    #[tokio::test]
153    async fn test_builder_qdrant_errors_when_feature_disabled() {
154        // Q3: 未启用 feature 时必须显式报错,不能静默降级到内存存储。
155        let builder = VectorStoreBuilder::qdrant("http://localhost:6334", "test_collection");
156        let store = builder.build().await;
157        assert!(store.is_err());
158    }
159}