mod memory;
mod provider;
pub mod document_store;
pub mod chunked_vector_store;
#[cfg(feature = "mongodb-persistence")]
mod mongo_document_store;
#[cfg(feature = "qdrant-integration")]
mod qdrant;
pub use memory::InMemoryVectorStore;
pub use provider::{VectorStoreProvider, VectorStoreType, VectorStoreBuilder};
pub use document_store::{DocumentStore, InMemoryDocumentStore, ChunkedDocumentStoreTrait, InMemoryChunkedDocumentStore, ChunkedDocumentStore, ChunkDocument};
pub use chunked_vector_store::ChunkedVectorStore;
#[cfg(feature = "mongodb-persistence")]
pub use mongo_document_store::{MongoChunkedDocumentStore, MongoStoreConfig};
#[cfg(feature = "qdrant-integration")]
pub use qdrant::{QdrantVectorStore, QdrantConfig, QdrantDistance};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::error::Error;
#[derive(Debug)]
pub enum VectorStoreError {
DocumentNotFound(String),
EmbeddingError(String),
StorageError(String),
ConnectionError(String),
}
impl std::fmt::Display for VectorStoreError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VectorStoreError::DocumentNotFound(id) => write!(f, "Document not found: {}", id),
VectorStoreError::EmbeddingError(msg) => write!(f, "Embedding error: {}", msg),
VectorStoreError::StorageError(msg) => write!(f, "Storage error: {}", msg),
VectorStoreError::ConnectionError(msg) => write!(f, "Connection error: {}", msg),
}
}
}
impl Error for VectorStoreError {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Document {
pub content: String,
pub metadata: HashMap<String, String>,
pub id: Option<String>,
}
impl Document {
pub fn new(content: impl Into<String>) -> Self {
Self {
content: content.into(),
metadata: HashMap::new(),
id: None,
}
}
pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.metadata.insert(key.into(), value.into());
self
}
pub fn with_id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
pub fn page_content(&self) -> &str {
&self.content
}
}
#[derive(Debug, Clone)]
pub struct VectorDocument {
pub document: Document,
pub embedding: Vec<f32>,
}
#[derive(Debug, Clone)]
pub struct SearchResult {
pub document: Document,
pub score: f32,
}
#[async_trait]
pub trait VectorStore: Send + Sync {
async fn add_documents(
&self,
documents: Vec<Document>,
embeddings: Vec<Vec<f32>>,
) -> Result<Vec<String>, VectorStoreError>;
async fn similarity_search(
&self,
query_embedding: &[f32],
k: usize,
) -> Result<Vec<SearchResult>, VectorStoreError>;
async fn get_document(&self, id: &str) -> Result<Option<Document>, VectorStoreError>;
async fn get_embedding(&self, id: &str) -> Result<Option<Vec<f32>>, VectorStoreError>;
async fn delete_document(&self, id: &str) -> Result<(), VectorStoreError>;
async fn count(&self) -> usize;
async fn clear(&self) -> Result<(), VectorStoreError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_document_creation() {
let doc = Document::new("Hello, world!")
.with_metadata("source", "test")
.with_id("doc-1");
assert_eq!(doc.content, "Hello, world!");
assert_eq!(doc.metadata.get("source"), Some(&"test".to_string()));
assert_eq!(doc.id, Some("doc-1".to_string()));
}
#[test]
fn test_document_page_content() {
let doc = Document::new("Test content");
assert_eq!(doc.page_content(), "Test content");
}
}