use anyhow::Result;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VectorSearchResult {
pub id: String,
pub score: f32,
pub content: String,
pub metadata: serde_json::Value,
}
#[async_trait]
pub trait VectorStore: Send + Sync {
async fn initialize(&self, dimension: usize) -> Result<()>;
async fn upsert(
&self,
ids: Vec<String>,
embeddings: Vec<Vec<f32>>,
contents: Vec<String>,
metadata: Vec<serde_json::Value>,
) -> Result<usize>;
async fn search(
&self,
query_vector: Vec<f32>,
limit: usize,
min_score: f32,
) -> Result<Vec<VectorSearchResult>>;
async fn delete(&self, ids: Vec<String>) -> Result<usize>;
async fn clear(&self) -> Result<()>;
async fn count(&self) -> Result<usize>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_search_result_serialization() {
let result = VectorSearchResult {
id: "chunk-1".to_string(),
score: 0.95,
content: "fn main() {}".to_string(),
metadata: serde_json::json!({"file": "main.rs", "language": "rust"}),
};
let json = serde_json::to_string(&result).unwrap();
let deserialized: VectorSearchResult = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.id, "chunk-1");
assert!((deserialized.score - 0.95).abs() < f32::EPSILON);
}
}