Metadata-Version: 2.4
Name: ragkit-vs
Version: 0.2.0
Summary: A simple, extensible toolkit for building advanced multi-agent Retrieval-Augmented Generation (RAG) pipelines in a few lines of code.
Author: K Varshit
Maintainer: K Varshit
License-Expression: MIT
Project-URL: Homepage, https://github.com/Varshitcode14/RagKit-vs
Project-URL: Repository, https://github.com/Varshitcode14/RagKit-vs
Project-URL: Documentation, https://github.com/Varshitcode14/RagKit-vs/tree/main/docs
Project-URL: Issues, https://github.com/Varshitcode14/RagKit-vs/issues
Project-URL: Changelog, https://github.com/Varshitcode14/RagKit-vs/blob/main/CHANGELOG.md
Keywords: rag,retrieval-augmented-generation,multi-agent,llm,groq,openai,embeddings,faiss,vector-search,nlp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: python-dotenv>=1.0
Provides-Extra: faiss
Requires-Dist: faiss-cpu>=1.7; extra == "faiss"
Provides-Extra: embeddings
Requires-Dist: sentence-transformers>=2.2; extra == "embeddings"
Provides-Extra: ma-rag
Requires-Dist: langgraph>=0.2; extra == "ma-rag"
Provides-Extra: pdf
Requires-Dist: pypdf>=4.0; extra == "pdf"
Provides-Extra: groq
Requires-Dist: groq>=0.11; extra == "groq"
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.30; extra == "anthropic"
Provides-Extra: google
Requires-Dist: google-generativeai>=0.7; extra == "google"
Provides-Extra: bedrock
Requires-Dist: boto3>=1.34; extra == "bedrock"
Provides-Extra: cerebras
Requires-Dist: cerebras-cloud-sdk>=1.0; extra == "cerebras"
Provides-Extra: llm
Requires-Dist: groq>=0.11; extra == "llm"
Requires-Dist: cerebras-cloud-sdk>=1.0; extra == "llm"
Requires-Dist: openai>=1.0; extra == "llm"
Requires-Dist: boto3>=1.34; extra == "llm"
Provides-Extra: eval
Requires-Dist: matplotlib>=3.6; extra == "eval"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Provides-Extra: all
Requires-Dist: faiss-cpu>=1.7; extra == "all"
Requires-Dist: sentence-transformers>=2.2; extra == "all"
Requires-Dist: langgraph>=0.2; extra == "all"
Requires-Dist: pypdf>=4.0; extra == "all"
Requires-Dist: groq>=0.11; extra == "all"
Requires-Dist: openai>=1.0; extra == "all"
Requires-Dist: anthropic>=0.30; extra == "all"
Requires-Dist: google-generativeai>=0.7; extra == "all"
Requires-Dist: boto3>=1.34; extra == "all"
Requires-Dist: cerebras-cloud-sdk>=1.0; extra == "all"
Requires-Dist: matplotlib>=3.6; extra == "all"
Requires-Dist: pytest>=7.0; extra == "all"
Requires-Dist: ruff>=0.6; extra == "all"
Dynamic: license-file

# 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`**

```python
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](#features)
- [Installation](#installation)
- [Quick start](#quick-start)
- [Examples](#examples)
- [Supported pipelines](#supported-pipelines)
- [Supported LLM providers](#supported-llm-providers)
- [Supported document formats](#supported-document-formats)
- [Per-agent configuration (AgentConfig)](#per-agent-configuration-agentconfig)
- [Custom prompts (PromptStore)](#custom-prompts-promptstore)
- [Grounding & evidence verification](#grounding--evidence-verification)
- [Configuration](#configuration)
- [Error handling](#error-handling)
- [Contributing](#contributing)
- [FAQ](#faq)
- [Roadmap](#roadmap)
- [License](#license)

## 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`](#per-agent-configuration-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).
- **Introspectable** — `rag.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

```bash
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:

```bash
pip install "ragkit-vs[embeddings,faiss,ma_rag,groq,pdf]"
```

## Quick start

1. Put your provider key in a `.env` file (see [`.env.example`](.env.example)):
   ```
   GROQ_API_KEY=gsk_xxxxxxxx
   ```
2. Ask questions over your documents:
   ```python
   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:

```python
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/`](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.

```python
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):

```python
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):

```python
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`:

```python
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.

```python
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):

```python
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):

```python
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:

```python
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`):

```python
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](CONTRIBUTING.md). In short:

```bash
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](LICENSE) © K Varshit
