Skip to main content

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

  • Provider-first, few-line API — pick a provider, point at a corpus, ask.
  • Two pipelines: traditional (single-pass) and ma_rag (planner → step-definer → retriever → extractor → QA → final-answer, multi-hop).
  • Per-agent configuration — with AgentConfig each 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, and google across 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 with export_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 + hashing embedder let the whole stack run with no API keys and no model downloads (used by the test suite).
  • Introspectablerag.agent_settings() and rag.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

  1. Put your provider key in a .env file (see .env.example):
    GROQ_API_KEY=gsk_xxxxxxxx
    
  2. 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:

  1. Similarity pre-filter (fast, offline) — rejects clearly-unrelated retrievals for free.
  2. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ragkit_vs-0.2.0.tar.gz (69.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ragkit_vs-0.2.0-py3-none-any.whl (70.0 kB view details)

Uploaded Python 3

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

Hashes for ragkit_vs-0.2.0.tar.gz
Algorithm Hash digest
SHA256 f5881868ec323469dbe39b0066d04aaaddc8fa58f7dcf684060ea337595fda5d
MD5 a394cf41eeef9c8a79d909aafab2904f
BLAKE2b-256 47cc170b49b3b8aa6902113f09d6db1ea4f55f2ebda6a9ab29b867ddecd3a522

See more details on using hashes here.

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

Hashes for ragkit_vs-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cd4f60e3aa3ebaa595d3ddb4250bead4da065764a6d4205921fdf9bcab18bc62
MD5 f49beaea434ae63f42d6bd77634ea7db
BLAKE2b-256 bfbc839de8fb7db54793e3defe3ed330429bafb3597052d84fa7b8c28d6f1d24

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page