adk-rag
Give your AI agents a knowledge base. adk-rag adds Retrieval-Augmented Generation (RAG) to ADK-Rust so your agents can search documents and answer questions using your own data.
ADK RAG
The adk-rag crate provides Retrieval-Augmented Generation capabilities for the ADK-Rust workspace. It offers a modular, trait-based architecture for document chunking, embedding generation, vector storage, similarity search, reranking, and agentic retrieval. The crate follows the ADK-Rust conventions of feature-gated backends, async-trait interfaces, and builder-pattern configuration. It integrates with existing ADK crates (adk-gemini for embeddings, adk-core for the Tool trait) and supports multiple vector store backends (in-memory, Qdrant, LanceDB, pgvector, SurrealDB).
What is RAG?
RAG stands for Retrieval-Augmented Generation. Instead of relying only on what an LLM was trained on, RAG lets your agent look up relevant information from your documents before answering. The flow is:
- Ingest — Your documents are split into chunks, converted to vector embeddings, and stored
- Query — When a user asks a question, the question is embedded and matched against stored chunks
- Generate — The most relevant chunks are passed to the LLM as context for its answer
This means your agent can answer questions about your product docs, company policies, codebases, or any text you feed it.
Quick Start
Add adk-rag to your Cargo.toml:
[]
= "0.3"
Minimal example — no API keys needed
This uses the built-in InMemoryVectorStore and a simple mock embedder. Good for trying things out locally.
use Arc;
use *;
// A mock embedder that turns text into vectors using hashing.
// In production, swap this for GeminiEmbeddingProvider or OpenAIEmbeddingProvider.
;
async
With a real LLM agent
This is the practical use case — an agent that searches your knowledge base to answer questions. Requires a GOOGLE_API_KEY.
[]
= { = "0.3", = ["gemini"] }
= "0.3"
= "0.3"
= "0.3"
use Arc;
use LlmAgentBuilder;
use GeminiModel;
use *;
async
The agent will automatically call rag_search when it needs information from your knowledge base.
How It Works
adk-rag is built from four pluggable components:
Documents → [Chunker] → [EmbeddingProvider] → [VectorStore]
↓
Query → [EmbeddingProvider] → [VectorStore search] → [Reranker] → Results
| Component | What it does | Built-in options |
|---|---|---|
| Chunker | Splits documents into smaller pieces | FixedSizeChunker, RecursiveChunker, MarkdownChunker |
| EmbeddingProvider | Converts text to vector embeddings | GeminiEmbeddingProvider¹, OpenAIEmbeddingProvider² |
| VectorStore | Stores and searches embeddings | InMemoryVectorStore, QdrantVectorStore³, LanceDBVectorStore⁴, PgVectorStore⁵, SurrealVectorStore⁶ |
| Reranker | Re-scores results after search | NoOpReranker (or write your own) |
¹ requires gemini feature ² requires openai feature ³ requires qdrant feature ⁴ requires lancedb feature ⁵ requires pgvector feature ⁶ requires surrealdb feature
The RagPipeline wires these together. The RagTool wraps the pipeline as an adk_core::Tool so any ADK agent can call it.
Choosing a Chunker
| Chunker | Best for | How it splits |
|---|---|---|
FixedSizeChunker |
General text, logs | Every N characters with overlap |
RecursiveChunker |
Articles, docs, code comments | Paragraphs → sentences → words (natural boundaries) |
MarkdownChunker |
Markdown files, READMEs | By headers, preserving section hierarchy in metadata |
// Fixed: 512 chars per chunk, 100 char overlap
let chunker = new;
// Recursive: tries paragraph breaks first, then sentences
let chunker = new;
// Markdown: splits by ## headers, stores header path in metadata
let chunker = new;
Configuration
let config = builder
.chunk_size // max characters per chunk (default: 512)
.chunk_overlap // overlap between chunks (default: 100)
.top_k // number of results to return (default: 10)
.similarity_threshold // minimum score to include (default: 0.0)
.build?;
- chunk_size — Smaller chunks are more precise but may lose context. Larger chunks preserve context but may include irrelevant text. 200–500 is a good range for most use cases.
- chunk_overlap — Overlap ensures important information at chunk boundaries isn't lost. 10–20% of chunk_size works well.
- top_k — How many results to return. More results give the LLM more context but increase token usage.
- similarity_threshold — Filter out low-quality matches. Set to 0.0 to return everything, or 0.3–0.7 to only keep strong matches.
Feature Flags
Only pull the dependencies you need:
# Just the core (in-memory store, all chunkers, no external deps)
= "0.3"
# With Gemini embeddings
= { = "0.3", = ["gemini"] }
# With OpenAI embeddings
= { = "0.3", = ["openai"] }
# With Qdrant vector store
= { = "0.3", = ["qdrant"] }
# With SurrealDB vector store (embedded or remote)
= { = "0.3", = ["surrealdb"] }
# Everything
= { = "0.3", = ["full"] }
| Feature | Enables | Extra dependency |
|---|---|---|
| (default) | Core traits, InMemoryVectorStore, all chunkers |
none |
gemini |
GeminiEmbeddingProvider |
adk-gemini |
openai |
OpenAIEmbeddingProvider |
reqwest |
qdrant |
QdrantVectorStore |
qdrant-client |
lancedb |
LanceDBVectorStore |
lancedb, arrow |
pgvector |
PgVectorStore |
sqlx |
surrealdb |
SurrealVectorStore |
surrealdb |
full |
All of the above | all |
Note: The
lancedbfeature requiresprotoc(Protocol Buffers compiler) installed on your system. Install withbrew install protobuf(macOS),apt install protobuf-compiler(Ubuntu), orchoco install protoc(Windows).
Writing a Custom Reranker
The default NoOpReranker passes results through unchanged. You can write your own to improve precision:
use ;
// Use it in the pipeline
let pipeline = builder
.config
.embedding_provider
.vector_store
.chunker
.reranker
.build?;
Examples
Run these from the ADK-Rust workspace root:
| Example | What it shows | API key needed? | Command |
|---|---|---|---|
rag_basic |
Pipeline fundamentals with mock embeddings | No | cargo run --example rag_basic --features rag |
rag_markdown |
Markdown-aware chunking with header metadata | No | cargo run --example rag_markdown --features rag |
rag_agent |
LlmAgent with RagTool for product support | Yes | cargo run --example rag_agent --features rag-gemini |
rag_recursive |
Codebase Q&A agent with RecursiveChunker | Yes | cargo run --example rag_recursive --features rag-gemini |
rag_reranker |
HR policy agent with custom keyword reranker | Yes | cargo run --example rag_reranker --features rag-gemini |
rag_multi_collection |
Support agent searching docs, troubleshooting, and changelog collections | Yes | cargo run --example rag_multi_collection --features rag-gemini |
For examples that need an API key, set GOOGLE_API_KEY in your environment or .env file.
API Reference
Core Types
// A document to ingest
Document
// A chunk produced by a Chunker (with embedding attached after processing)
Chunk
// A search result with relevance score
SearchResult
Pipeline Methods
let pipeline = builder
.config
.embedding_provider
.vector_store
.chunker
.reranker // optional
.build?;
// Collection management
pipeline.create_collection.await?;
pipeline.delete_collection.await?;
// Ingestion (chunk → embed → store)
let chunks = pipeline.ingest.await?;
let chunks = pipeline.ingest_batch.await?;
// Query (embed → search → rerank → filter)
let results = pipeline.query.await?;
RagTool
Wraps a pipeline as an adk_core::Tool for agent use:
let tool = new;
// The agent calls it with JSON:
// { "query": "How do I reset my password?" }
// { "query": "pricing info", "collection": "faq", "top_k": 5 }
License
Apache-2.0
Part of ADK-Rust
This crate is part of the ADK-Rust framework for building AI agents in Rust.