#![cfg(feature = "qdrant-integration")]
use langchainrust::vector_stores::{
Document, VectorStore, QdrantVectorStore, QdrantConfig, QdrantDistance,
};
use langchainrust::retrieval::{SimilarityRetriever, RetrieverTrait};
use langchainrust::embeddings::MockEmbeddings;
use std::sync::Arc;
const QDRANT_URL: &str = "http://192.168.10.100:6334";
const VECTOR_SIZE: usize = 128;
#[tokio::test]
async fn t01_connection() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_basic")
.with_vector_size(VECTOR_SIZE)
.with_distance(QdrantDistance::Cosine);
let store = QdrantVectorStore::new(config).await.unwrap();
println!("✅ 连接成功: {}", QDRANT_URL);
println!(" 文档数: {}", store.count().await);
}
#[tokio::test]
async fn t02_add_documents() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_add")
.with_vector_size(VECTOR_SIZE);
let store = QdrantVectorStore::new(config).await.unwrap();
let _ = store.clear().await;
let docs = vec![
Document::new("Rust 编程语言").with_metadata("category", "programming"),
Document::new("向量数据库").with_metadata("category", "database"),
];
let embeddings: Vec<Vec<f32>> = vec![
vec![1.0; VECTOR_SIZE],
vec![0.0; VECTOR_SIZE],
];
let ids = store.add_documents(docs, embeddings).await.unwrap();
println!("✅ 添加 {} 个文档", ids.len());
}
#[tokio::test]
async fn t03_custom_id() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_custom_id")
.with_vector_size(VECTOR_SIZE);
let store = QdrantVectorStore::new(config).await.unwrap();
let _ = store.clear().await;
let docs = vec![
Document::new("文档 A").with_id("doc-a"),
Document::new("文档 B").with_id("doc-b"),
];
let embeddings = vec![vec![1.0; VECTOR_SIZE], vec![0.5; VECTOR_SIZE]];
let ids = store.add_documents(docs, embeddings).await.unwrap();
println!("✅ 自定义 ID: {:?}", ids);
let doc = store.get_document("doc-a").await.unwrap();
println!(" 获取 doc-a: {:?}", doc.map(|d| d.content));
}
#[tokio::test]
async fn t04_similarity_search() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_search")
.with_vector_size(VECTOR_SIZE);
let store = QdrantVectorStore::new(config).await.unwrap();
let _ = store.clear().await;
let docs = vec![
Document::new("机器学习").with_id("ml"),
Document::new("深度学习").with_id("dl"),
];
let embeddings = vec![
vec![1.0, 0.0].into_iter().cycle().take(VECTOR_SIZE).collect(),
vec![0.0, 1.0].into_iter().cycle().take(VECTOR_SIZE).collect(),
];
store.add_documents(docs, embeddings).await.unwrap();
let query: Vec<f32> = vec![0.9, 0.1].into_iter().cycle().take(VECTOR_SIZE).collect();
let results = store.similarity_search(&query, 2).await.unwrap();
println!("✅ 搜索结果:");
for (i, r) in results.iter().enumerate() {
println!(" {}. {} (分数: {:.4})", i + 1, r.document.content, r.score);
}
}
#[tokio::test]
async fn t05_get_embedding() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_get_vec")
.with_vector_size(8);
let store = QdrantVectorStore::new(config).await.unwrap();
let _ = store.clear().await;
let doc = Document::new("测试文档").with_id("test-doc");
let custom_embedding = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
println!("存储向量: {:?}", custom_embedding);
store.add_documents(vec![doc], vec![custom_embedding.clone()]).await.unwrap();
let embedding = store.get_embedding("test-doc").await.unwrap();
match embedding {
Some(vec) => {
println!("✅ 获取向量: {:?}", vec);
println!(" 验证: {}", vec == custom_embedding);
}
None => println!("❌ 向量不存在"),
}
}
#[tokio::test]
async fn t06_retriever() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_retriever")
.with_vector_size(VECTOR_SIZE);
let store = Arc::new(QdrantVectorStore::new(config).await.unwrap());
let _ = store.clear().await;
let embeddings = Arc::new(MockEmbeddings::new(VECTOR_SIZE));
let retriever = SimilarityRetriever::new(store.clone(), embeddings);
retriever.add_documents(vec![
Document::new("Rust 教程").with_metadata("type", "lang"),
Document::new("Qdrant 数据库").with_metadata("type", "db"),
]).await.unwrap();
println!("✅ 通过 Retriever 添加 {} 个文档", store.count().await);
let results = retriever.retrieve("编程", 2).await.unwrap();
for r in &results {
println!(" - {}", r.content);
}
}
#[tokio::test]
async fn t07_rag_flow() {
let config = QdrantConfig::new(QDRANT_URL, "rag_demo")
.with_vector_size(VECTOR_SIZE);
let store = Arc::new(QdrantVectorStore::new(config).await.unwrap());
let _ = store.clear().await;
let embeddings = Arc::new(MockEmbeddings::new(VECTOR_SIZE));
let retriever = SimilarityRetriever::new(store.clone(), embeddings);
let knowledge = vec![
Document::new("Rust 专注内存安全").with_id("doc-1"),
Document::new("Cargo 是包管理器").with_id("doc-2"),
];
retriever.add_documents(knowledge).await.unwrap();
println!("📚 索引 {} 个文档", store.count().await);
let question = "Rust 的特点?";
let relevant = retriever.retrieve(question, 2).await.unwrap();
println!("\n❓ 问题: {}", question);
println!("🔍 相关文档:");
for doc in &relevant {
println!(" - {}", doc.content);
}
println!("\n✅ RAG 流程完成");
}
#[tokio::test]
async fn t08_metadata() {
let config = QdrantConfig::new(QDRANT_URL, "tutorial_metadata")
.with_vector_size(VECTOR_SIZE);
let store = QdrantVectorStore::new(config).await.unwrap();
let _ = store.clear().await;
let doc = Document::new("Rust 教程")
.with_metadata("author", "张三")
.with_metadata("category", "programming")
.with_metadata("date", "2024-01-01");
store.add_documents(vec![doc], vec![vec![1.0; VECTOR_SIZE]]).await.unwrap();
let results = store.similarity_search(&[1.0; VECTOR_SIZE], 1).await.unwrap();
let metadata = &results[0].document.metadata;
println!("✅ 文档元数据:");
println!(" author: {:?}", metadata.get("author"));
println!(" category: {:?}", metadata.get("category"));
println!(" date: {:?}", metadata.get("date"));
}