A simple, extensible toolkit for building advanced multi-agent Retrieval-Augmented Generation (RAG) pipelines in a few lines of code.
Project description
RAGKit
Build advanced Retrieval-Augmented Generation (RAG) systems — including multi-agent RAG — in a few lines of code.
RAGKit hides the plumbing (embedders, vector stores, retrievers, agents, LLM providers) behind clean, replaceable interfaces so you can go from a folder of documents to grounded answers immediately, and swap any component when you need to.
PyPI distribution name:
ragkit-vs· import name:ragkit
from ragkit import RagKit
rag = RagKit(
pipeline="ma_rag",
llm="groq",
model="llama-3.3-70b-versatile",
corpus="docs/",
).build()
response = rag.query("What is RAG?")
print(response.answer)
Table of contents
- Features
- Installation
- Quick start
- Examples
- Supported pipelines
- Supported LLM providers
- Supported document formats
- Per-agent configuration (AgentConfig)
- Custom prompts (PromptStore)
- Grounding & evidence verification
- Configuration
- Error handling
- Contributing
- FAQ
- Roadmap
- License
Features
- Provider-first, few-line API — pick a provider, point at a corpus, ask.
- Two pipelines:
traditional(single-pass) andma_rag(planner → step-definer → retriever → extractor → QA → final-answer, multi-hop). - Per-agent configuration — with
AgentConfigeach MA-RAG agent can use its own LLM, model, temperature, max_tokens, and prompt; anything unset inherits the global config. - Multiple providers, per agent — mix
groq,openai,anthropic, andgoogleacross agents, or keep one provider for all. - Prompt system (
PromptStore) — default prompts ship as editable Markdown files. Override per agent inline, from a file, or from a whole directory; export the bundled defaults withexport_default_prompts(...). - Grounding / evidence verification — a two-tier gate (fast similarity pre-filter + an LLM evidence verifier) decides before any LLM call whether the retrieved context can support an answer.
- Hallucination prevention — unrelated questions are answered with "The answer is not available in the provided documents." and no agent is run (not the planner, QA, or final).
- Partial-evidence grounded reasoning — the verifier accepts context that can be combined or reasoned over to build a grounded answer, preserving MA-RAG multi-hop while still rejecting unrelated queries.
- Everything is replaceable — LLM, embedder, vector store, retriever, chunker, corpus loader, and prompts each have an interface + registry.
- Runs offline — a
MockLLM+hashingembedder let the whole stack run with no API keys and no model downloads (used by the test suite). - Introspectable —
rag.agent_settings()andrag.show_prompt()report the resolved model and effective prompt for every agent (no API key needed). - Typed (ships
py.typed) and lightweight by default.
Installation
pip install ragkit-vs
The base install is tiny. Install only the extras you need:
| Extra | Enables | Example |
|---|---|---|
embeddings |
SentenceTransformer embeddings | pip install "ragkit-vs[embeddings]" |
faiss |
FAISS vector store | pip install "ragkit-vs[faiss]" |
ma_rag |
Multi-agent pipeline (LangGraph) | pip install "ragkit-vs[ma_rag]" |
pdf |
PDF ingestion (pypdf) | pip install "ragkit-vs[pdf]" |
groq |
Groq provider | pip install "ragkit-vs[groq]" |
openai |
OpenAI provider | pip install "ragkit-vs[openai]" |
anthropic |
Anthropic provider | pip install "ragkit-vs[anthropic]" |
google |
Google Gemini provider | pip install "ragkit-vs[google]" |
bedrock |
AWS Bedrock (boto3) | pip install "ragkit-vs[bedrock]" |
cerebras |
Cerebras provider | pip install "ragkit-vs[cerebras]" |
all |
everything (dev) | pip install "ragkit-vs[all]" |
Typical setup for a Groq-powered RAG over PDFs:
pip install "ragkit-vs[embeddings,faiss,ma_rag,groq,pdf]"
Quick start
- Put your provider key in a
.envfile (see.env.example):GROQ_API_KEY=gsk_xxxxxxxx - Ask questions over your documents:
from ragkit import RagKit rag = RagKit(pipeline="ma_rag", llm="groq", corpus="docs/").build() print(rag.ask("Explain Retrieval Augmented Generation"))
No key? Run fully offline:
from ragkit import RagKit, RagKitConfig
from ragkit.llms.mock import MockLLM
cfg = RagKitConfig()
cfg.embedding.backend = "hashing" # deterministic, no downloads
rag = RagKit(pipeline="traditional", corpus="docs/", config=cfg, llm=MockLLM()).build()
print(rag.ask("What is in my documents?"))
Examples
Runnable scripts live in examples/:
| File | What it shows |
|---|---|
basic.py |
Offline end-to-end (no keys) |
traditional.py |
Single-pass pipeline |
ma_rag.py |
Multi-agent pipeline |
folder.py |
Ingest a folder of mixed documents |
pdf.py |
Ingest a PDF |
groq.py / openai.py |
Choosing a provider |
save_load.py |
Persist and reload an index |
Supported pipelines
traditional— retrieve top-k chunks, build context, one LLM call. Fast and cheap.ma_rag— decomposes the question into steps, retrieves and reasons per step, then synthesizes a final answer. Better for multi-hop questions.
List them at runtime: ragkit.available_pipelines().
Supported LLM providers
groq, openai, anthropic, google (Gemini), plus a provider_manager
multi-provider fallback and an offline mock. Keys are read from standard
environment variables (GROQ_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY,
ANTHROPIC_API_KEY) or passed via api_key=....
Supported document formats
Folders of mixed files, plus individual files: .txt, .md, .pdf,
.json, .jsonl, or an in-memory list of {"title", "text"} dicts. Long
documents are automatically chunked.
Per-agent configuration (AgentConfig)
Beginners write nothing extra — a single llm/model applies to every agent.
Advanced users configure each MA-RAG agent independently with AgentConfig
(dicts work too, for backward compatibility). Any field left unset inherits the
global configuration.
from ragkit import RagKit, AgentConfig
rag = RagKit(
pipeline="ma_rag",
llm="groq",
model="llama-3.3-70b-versatile", # global default for every agent
planner=AgentConfig(model="llama-3.3-70b-versatile", temperature=0.1),
step_definer=AgentConfig(model="llama-3.1-8b-instant"),
qa={"model": "llama-3.1-8b-instant"}, # dict form is also accepted
final=AgentConfig(model="llama-3.3-70b-versatile", max_tokens=512),
corpus="docs/",
).build()
# See exactly what each agent resolved to — no API call, no keys needed.
print(rag.agent_settings())
# {'planner': {'llm': 'groq', 'model': 'llama-3.3-70b-versatile', ...}, ...}
Each agent (planner, step_definer, extractor, qa, final) accepts
llm, model, temperature, max_tokens, api_key, prompt, and
prompt_file. You can even mix providers across agents (install each provider's
extra and set its key):
rag = RagKit(
pipeline="ma_rag",
llm="groq", model="llama-3.3-70b-versatile", # default for unset agents
planner=AgentConfig(llm="openai", model="gpt-4o-mini"),
qa=AgentConfig(llm="google", model="gemini-1.5-flash"),
final=AgentConfig(llm="anthropic", model="claude-3-5-sonnet-latest"),
corpus="docs/",
).build()
Custom prompts (PromptStore)
Default prompts ship with the package as Markdown files and are loaded automatically — you never need to specify them. To customize, override a prompt three ways (precedence: inline → file → directory → bundled default):
from ragkit import RagKit, AgentConfig
# 1) inline string
RagKit(pipeline="ma_rag", llm="groq",
planner=AgentConfig(prompt="You are the planner...\n{question}"))
# 2) a prompt file
RagKit(pipeline="ma_rag", llm="groq",
qa=AgentConfig(prompt_file="./prompts/qa.md"))
# 3) a whole directory — missing files fall back to the bundled defaults
RagKit(pipeline="ma_rag", llm="groq", prompt_dir="./prompts")
# traditional pipeline takes a top-level prompt / prompt_file
RagKit(pipeline="traditional", llm="groq",
prompt="Answer only from the context.\n\n{context}\n\n{question}")
Export the bundled defaults to edit them, then load them back with prompt_dir:
import ragkit
ragkit.export_default_prompts("./prompts") # writes planner.md, qa.md, ...
# Inspect the effective prompt an agent will actually use:
rag = RagKit(pipeline="ma_rag", llm="groq", prompt_dir="./prompts")
print(rag.show_prompt("planner"))
Custom prompts are validated on load: each agent supports a fixed set of
{placeholders} (e.g. planner → {question}, qa → {goal}/{history}/
{evidence}), and an unknown placeholder raises ConfigurationError.
Grounding & evidence verification
Similarity alone measures topical relatedness, not whether the context can actually answer the question. RAGKit runs a two-tier evidence gate before any LLM call:
- Similarity pre-filter (fast, offline) — rejects clearly-unrelated retrievals for free.
- LLM evidence verifier — asks "can a grounded answer be constructed solely from the retrieved context?" (allowing multi-passage reasoning).
If the evidence is insufficient, RAGKit returns the standard "not available" response and runs no agents.
rag = RagKit(pipeline="ma_rag", llm="groq", corpus="docs/").build()
resp = rag.query("Who won the 2022 World Cup?") # not in the documents
print(resp.answer) # -> The answer is not available in the provided documents.
print(resp.evidence) # {'accepted': False, 'decided_by': 'llm',
# 'verifier_verdict': 'NO', 'reason': '...'}
The decision is exposed on every response as response.evidence. Grounding is
on by default and fully configurable (thresholds are calibrated for the default
normalized-cosine embeddings):
RagKit(pipeline="ma_rag", llm="groq", evidence=False) # disable
RagKit(pipeline="ma_rag", llm="groq", evidence={"mode": "similarity"}) # offline gate only
RagKit(pipeline="ma_rag", llm="groq",
evidence={"verifier": {"model": "llama-3.1-8b-instant"}}) # cheap verifier model
Configuration
Everything is tunable through RagKitConfig (all fields have sensible
defaults):
from ragkit import RagKit, RagKitConfig
cfg = RagKitConfig()
cfg.retrieval.top_k = 8
cfg.retrieval.min_score = 0.3 # ignore weak retrievals
cfg.chunking.chunk_size = 300 # words per chunk (0 = whole document)
rag = RagKit(pipeline="ma_rag", llm="groq", corpus="docs/", config=cfg).build()
Persist and reload an index:
rag.save_index(".ragkit/my_index")
rag2 = RagKit(pipeline="traditional", llm="groq").load_index(".ragkit/my_index")
Error handling
RAGKit raises clear, typed exceptions (all subclass ragkit.RagKitError):
from ragkit import RagKit
from ragkit.exceptions import MissingAPIKeyError, CorpusNotFoundError
try:
RagKit(pipeline="ma_rag", llm="groq", corpus="docs/").build()
except MissingAPIKeyError as e:
print("Set your API key:", e)
except CorpusNotFoundError as e:
print("Bad corpus path:", e)
For backward compatibility these also subclass the relevant built-ins
(MissingAPIKeyError is a ValueError, CorpusNotFoundError is a
FileNotFoundError, NotIndexedError is a RuntimeError, etc.).
Contributing
See CONTRIBUTING.md. In short:
pip install -e ".[all]"
pytest
ruff check .
The test suite runs offline (mock LLM + hashing embedder).
FAQ
Do I need API keys to try it? No — use the mock LLM + hashing
embedder (see examples/basic.py).
Why ragkit-vs on PyPI but import ragkit? The distribution name is
ragkit-vs (the ragkit name was taken); the import name stays ragkit.
Does it work on Colab / Linux / macOS / Windows? Yes — all backends ship prebuilt wheels for the major platforms.
How do I avoid installing torch? Only the embeddings extra pulls torch.
Use the hashing embedder for a torch-free setup.
Roadmap
- Hybrid (dense + sparse) retrieval and reranking
- Automatic, persistent index caching
- Additional vector store backends
- CLI and optional API server
License
MIT © K Varshit
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ragkit_vs-0.2.0.tar.gz.
File metadata
- Download URL: ragkit_vs-0.2.0.tar.gz
- Upload date:
- Size: 69.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5881868ec323469dbe39b0066d04aaaddc8fa58f7dcf684060ea337595fda5d
|
|
| MD5 |
a394cf41eeef9c8a79d909aafab2904f
|
|
| BLAKE2b-256 |
47cc170b49b3b8aa6902113f09d6db1ea4f55f2ebda6a9ab29b867ddecd3a522
|
File details
Details for the file ragkit_vs-0.2.0-py3-none-any.whl.
File metadata
- Download URL: ragkit_vs-0.2.0-py3-none-any.whl
- Upload date:
- Size: 70.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd4f60e3aa3ebaa595d3ddb4250bead4da065764a6d4205921fdf9bcab18bc62
|
|
| MD5 |
f49beaea434ae63f42d6bd77634ea7db
|
|
| BLAKE2b-256 |
bfbc839de8fb7db54793e3defe3ed330429bafb3597052d84fa7b8c28d6f1d24
|