xz-rag 0.1.1

Multi-channel Retrieval-Augmented Generation engine
Documentation
# xz-rag

Multi-channel Retrieval-Augmented Generation engine for the 小竹 AI ecosystem.

Build composable RAG pipelines with multiple retrieval channels, RRF fusion, query preprocessing (HYDE), optional reranking, and LLM generation.

## Architecture

`xz-rag` coordinates a pluggable retrieval pipeline:

```
Query → [Preprocessing] → Channel Executors → [Normalize] → [RRF Fusion] → [Rerank] → [Context Build] → [Generate]
           ┌──────────────────┼──────────────────┐
      Semantic             BM25              Metadata            Graph
   (vector search)    (full-text via     (structured         (knowledge
                       tantivy)           filters)            graph)
```

### Channels

| Channel | Feature | Backend | Purpose |
|---------|---------|---------|---------|
| **Semantic** | default | any `Embedder` + `SemanticSearch` impl | Dense vector similarity search |
| **BM25** | `bm25` | tantivy | Sparse keyword retrieval |
| **Metadata** | default | any `MetadataStore` impl | Structured field filtering |
| **Graph** | default | any `KnowledgeGraphSearch` impl | Entity-relation traversal |

### Pipeline stages

1. **Query preprocessing** -- HYDE (hypothetical document generation) or query expansion, both powered by `xz-provider` (feature `hyde`).
2. **Multi-channel retrieval** -- each channel runs independently, configured with per-channel weight and `top_k`.
3. **Score normalization** -- min-max normalization equalizes scores across heterogeneous channels.
4. **RRF fusion** -- reciprocal rank fusion (`RRFusion`) merges results by rank position, smoothing out score distribution differences.
5. **Reranking** -- optional cross-encoder reranking via `xz-rerank` (feature `rerank`) with Cohere/Jina support.
6. **Context assembly** -- token-budget-aware context window with configurable citation formatting.
7. **Generation** -- optional LLM response via `xz-provider` (feature `llm-generation`), with streaming support.

## Features

| Feature | Default | Description |
|---------|---------|-------------|
| `bm25` | no | BM25 full-text search via tantivy |
| `rerank` | no | Cross-encoder reranking via `xz-rerank` |
| `hyde` | no | HYDE query expansion and query variation generation |
| `llm-generation` | no | LLM integration via `xz-provider` for `retrieve_and_generate` |
| `caching` | no | In-memory result caching via moka |
| `query-expansion` | no | Alias for `hyde` (same provider dep) |

## Usage

### Basic retrieval with DefaultRagEngine

```rust
use std::sync::Arc;
use xz_rag::{
    DefaultRagEngine, RagEngine,
    channels::semantic::{Embedder, SemanticSearch, SemanticChannelExecutor},
    pipeline::channel::{ChannelConfig, ChannelPipeline},
    types::retrieval::RetrieveRequest,
};

// Provide your embedder and vector store implementations
let embedder: Arc<dyn Embedder> = Arc::new(MyEmbedder);
let store: Arc<dyn SemanticSearch> = Arc::new(MyVectorStore);

let engine = DefaultRagEngine::builder()
    .embedder(embedder)
    .semantic_store(store)
    .pipeline(
        ChannelPipeline::new(vec![
            ChannelConfig::semantic(0.6, 10).with_min_score(0.2),
            ChannelConfig::metadata(0.4, 5),
        ])
        .with_rrf_k(60),
    )
    .build();

let request = RetrieveRequest::builder("what is RAG?")
    .channels(vec![
        ChannelConfig::semantic(0.6, 10),
        ChannelConfig::metadata(0.4, 5),
    ])
    .top_k(15)
    .build();

let result = engine.retrieve(&request).await?;
println!("got {} hits from {} channels",
    result.hits.len(), result.channel_report.len());
```

### With HYDE and reranking

Enable features in `Cargo.toml`:

```toml
[dependencies]
xz-rag = { version = "0.1", features = ["hyde", "rerank", "llm-generation"] }
```

```rust
use xz_rag::types::retrieval::{QueryPreprocessing, RetrieveRequest};

let request = RetrieveRequest::builder("explain attention mechanism")
    .channels(vec![ChannelConfig::semantic(1.0, 20)])
    .query_preprocessing(QueryPreprocessing::Hyde)
    .top_k(10)
    .build();

// engine built with .reranker(...) and .provider(...)
let response = engine.retrieve_and_generate(&rag_request).await?;
println!("{}", response.answer);
```

### YAML/JSON configuration

```yaml
engine:
  name: "my-rag"
channels:
  semantic:
    weight: 0.5
    top_k: 10
    min_score: 0.1
  bm25:
    weight: 0.3
    top_k: 8
  metadata:
    weight: 0.2
    top_k: 5
fusion:
  algorithm: "rrf"
  rrf_k: 60
  normalize_scores: true
reranking:
  enabled: true
context:
  max_context_tokens: 4096
  citation_format: "numeric"
```

Load via `RagConfig::from_file()` and build the engine:

```rust
use xz_rag::types::config::RagConfig;

let config: RagConfig = serde_yaml::from_str(&yaml_str)?;
let engine = config.build_engine()?;
```

### Streaming generation

```rust
use futures::StreamExt;
use xz_rag::types::rag::RagStreamEvent;

let mut stream = engine.retrieve_and_generate_stream(&request).await?;
while let Some(event) = stream.next().await {
    match event? {
        RagStreamEvent::GenerationStarted { context_chunks, .. } => {
            eprintln!("context: {} chunks", context_chunks);
        }
        RagStreamEvent::ContentDelta { delta } => print!("{}", delta),
        RagStreamEvent::Done { citations, .. } => println!("\n[Done]"),
    }
}
```

## Modules

- `engine` -- `DefaultRagEngine` and its builder
- `channels` -- per-retriever channel executors (semantic, bm25, metadata, graph)
- `pipeline` -- channel orchestration, RRF fusion, score normalization
- `context` -- token budget management and citation formatting
- `preprocessing` -- HYDE and query expansion
- `generation` -- LLM response generation via `xz-provider`
- `indexing` -- document chunking (fixed, recursive, separator-based)
- `types` -- shared types (configs, requests, responses, chunk metadata)
- `cache` -- optional in-memory result caching
- `error` -- typed RAG errors

## Crate features

All optional components are feature-gated. The default crate is lightweight with only semantic and metadata channels. Turn on `bm25`, `rerank`, `hyde`, `llm-generation`, or `caching` as needed.

## License

MIT OR Apache-2.0