use std::sync::Arc;
use async_trait::async_trait;
use xz_rag::channels::semantic::{Embedder, SemanticSearch};
use xz_rag::pipeline::channel::{ChannelConfig, ChannelPipeline};
use xz_rag::types::chunk::ChunkMetadata;
use xz_rag::types::config::RagEngineInfo;
use xz_rag::types::rag::RagRequest;
use xz_rag::types::retrieval::RetrieveRequest;
use xz_rag::{DefaultRagEngine, RagEngine, RagError};
struct MockEmbedder;
#[async_trait]
impl Embedder for MockEmbedder {
async fn embed(&self, text: &[String]) -> Result<Vec<Vec<f32>>, RagError> {
Ok(text.iter().map(|_| vec![0.0_f32; 4]).collect())
}
fn dimensions(&self) -> usize {
4
}
}
struct MockSemanticStore {
chunks: Vec<(String, f32, ChunkMetadata, String, String)>,
}
#[async_trait]
impl SemanticSearch for MockSemanticStore {
async fn search(
&self,
_query_embedding: &[f32],
top_k: usize,
_namespace: Option<&str>,
) -> Result<Vec<(String, f32, ChunkMetadata, String, String)>, RagError> {
let mut results: Vec<_> = self.chunks.clone();
results.truncate(top_k);
Ok(results)
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let chunks = vec![
(
"chunk-1".into(),
0.92_f32,
ChunkMetadata {
document_title: Some("Rust Book".into()),
source: Some("doc/rust-book.md".into()),
..ChunkMetadata::default()
},
"Rust is a systems programming language focused on safety and performance."
.into(),
"doc-1".into(),
),
(
"chunk-2".into(),
0.85_f32,
ChunkMetadata {
document_title: Some("Async Rust".into()),
source: Some("doc/async-rust.md".into()),
..ChunkMetadata::default()
},
"Tokio is the primary async runtime for Rust, providing I/O, timers, and synchronization."
.into(),
"doc-2".into(),
),
(
"chunk-3".into(),
0.73_f32,
ChunkMetadata {
document_title: Some("Rust Book".into()),
source: Some("doc/rust-book.md".into()),
..ChunkMetadata::default()
},
"Ownership is Rust's most unique feature, enabling memory safety without a garbage collector."
.into(),
"doc-1".into(),
),
];
let embedder: Arc<dyn Embedder> = Arc::new(MockEmbedder);
let store: Arc<dyn SemanticSearch> = Arc::new(MockSemanticStore { chunks });
let pipeline = ChannelPipeline::new(vec![ChannelConfig::semantic(0.5, 10).with_min_score(0.1)]);
let engine = DefaultRagEngine::builder()
.name("basic-rag")
.version("0.1.0")
.pipeline(pipeline)
.embedder(embedder)
.semantic_store(store)
.build();
let info: RagEngineInfo = engine.engine_info();
println!("=== Engine Info ===");
println!(" Name: {}", info.name);
println!(" Version: {}", info.version);
println!(" Channels: {:?}", info.supported_channels);
println!(" Max context: {} tokens", info.max_context_window);
println!(" Streaming: {}", info.supports_streaming);
println!(" Reranking: {}", info.reranking_enabled);
println!();
let retrieve_req = RetrieveRequest::builder("What is Rust?").top_k(5).build();
let retrieve_result = engine.retrieve(&retrieve_req).await?;
println!("=== Retrieve Results ===");
println!(" Query: {}", retrieve_result.effective_query);
println!(" Latency: {} ms", retrieve_result.latency_ms);
println!(" Hits: {}", retrieve_result.hits.len());
for hit in &retrieve_result.hits {
println!(" [{:.4}] (ch={}) {}", hit.score, hit.channel, hit.content);
}
println!();
let rag_req: RagRequest = RagRequest::builder("What makes Rust safe?")
.system_prompt("You are a Rust expert.")
.retrieve_config(RetrieveRequest::builder("What makes Rust safe?").top_k(3).build())
.build();
let rag_response = engine.retrieve_and_generate(&rag_req).await?;
println!("=== Retrieve + Generate ===");
println!(" Answer:");
for line in rag_response.answer.lines() {
println!(" {line}");
}
println!();
println!(" Citations: {}", rag_response.citations.len());
for cit in &rag_response.citations {
println!(
" [{}] {} (score={:.4})",
cit.index,
cit.document_title.as_deref().unwrap_or("?"),
cit.score
);
}
println!();
println!(" Token usage:");
println!(" Context: {}", rag_response.usage.context_tokens);
println!(" Prompt: {}", rag_response.usage.prompt_tokens);
println!(" Complete: {}", rag_response.usage.completion_tokens);
println!(" Chunks used: {}", rag_response.usage.chunks_used);
println!(" Chunks dropped: {}", rag_response.usage.chunks_dropped);
println!();
println!(" Total latency: {} ms", rag_response.total_latency_ms);
Ok(())
}