I spent the last few months building ragway, a Python RAG library where the entire pipeline is controlled by a single YAML file.
The Problem
Every RAG project I worked on ended up with the same messy code: branching logic to switch between LLMs, copy-pasted vectorstore setup, tightly coupled retrieval and generation. When requirements changed — swap GPT-4 for Llama, move from FAISS to Pinecone — it meant touching a lot of code that shouldn't need to change.
The Solution
ragway separates configuration from code completely. One YAML file describes your entire pipeline:
version: "1.0"
pipeline: hybrid
plugins:
llm:
provider: groq
model: llama-3.3-70b-versatile
api_key: ${GROQ_API_KEY}
embedding:
provider: bge
model: BAAI/bge-large-en-v1.5
vectorstore:
provider: qdrant
index_path: .ragway/index
reranker:
enabled: true
provider: bge
chunking:
strategy: recursive
chunk_size: 512
Your Python code never changes:
from ragway import RAG
import asyncio
rag = RAG.from_config("rag.yaml")
async def main():
count = await rag.ingest("./docs/")
print(f"Ingested {count} chunks")
answer = await rag.query("What is in my documents?")
print(answer)
asyncio.run(main())
Switch the LLM without re-ingesting:
fast = rag.switch(llm="groq")
What's Configurable
| Component | Options |
|---|---|
| LLM |
anthropic, openai, mistral, groq, llama, local
|
| Vectorstore |
faiss, chroma, qdrant, pinecone, weaviate, pgvector
|
| Pipeline |
naive, hybrid, self, long_context, agentic
|
| Reranker |
cohere, bge, cross_encoder (or none) |
| Chunking |
fixed, recursive, semantic, sliding_window, hierarchical
|
| Embedding |
openai, bge, cohere, sentence_transformer
|
Running Fully Local (Zero API Costs)
pip install ragway[faiss,bge]
plugins:
llm:
provider: llama
model_path: ./models/llama-3.1-8b.gguf
embedding:
provider: bge
model: BAAI/bge-large-en-v1.5
vectorstore:
provider: faiss
index_path: .ragway/index
reranker:
enabled: false
Under the Hood
- Python 3.11, pydantic v2, fully async I/O
-
ComponentRegistryresolves YAML strings to real classes -
ConfigLoaderhandles${ENV_VAR}substitution and key injection - 357 tests, mypy strict mode, ruff clean
- Optional dependencies — install only what you use
Interactive Config Builder
The docs site has a visual config builder where you pick your providers and download a ready-to-use rag.yaml instantly.
Links
- 📦 PyPI: https://pypi.org/project/ragway
- 🐙 GitHub: https://github.com/swapanth/ragway
- 📖 Docs: https://ragway.vercel.app/docs
Feedback welcome — especially from anyone who's tried to build production RAG and hit the same configuration pain.
Top comments (0)