RAG Pipeline Builder
By (author)Sidhant N
read more
Read Me
RAG Pipeline Builder
A production-ready Retrieval-Augmented Generation pipeline that lets you chat with your own documents. Ingest PDFs, Markdown, text files, or URLs — then query them with a grounded LLM that cites its sources.
Architecture
Documents (PDF / TXT / MD / URL)
│
▼
Load & chunk RecursiveCharacterTextSplitter
│ chunk_size=800, overlap=120
▼
Embed & store text-embedding-3-small → Chroma (local)
│ → Pinecone (cloud)
▼
Retrieve (MMR) Top-K diverse chunks via Max Marginal Relevance
│
▼
Rerank cross-encoder/ms-marco-MiniLM-L-6-v2
│ narrows to top-N most relevant chunks
▼
Generate GPT-4o / Claude — grounded answer + source citations
Requirements
Python >= 3.10
langchain
langchain-openai
langchain-community
chromadb
sentence-transformers
fastapi
uvicorn
streamlit
pypdf
tiktoken
python-dotenv
requests
Install everything:
pip install langchain langchain-openai langchain-community \
chromadb sentence-transformers fastapi uvicorn \
streamlit pypdf tiktoken python-dotenv requests
Setup
# 1. Clone or copy the files cp .env.example .env2. Add your OpenAI key to .env
OPENAI_API_KEY=sk-...
3. Ingest your documents
python rag_pipeline.py ingest --source ./docs
4. Ask a question
python rag_pipeline.py query --question "What is our refund policy?"
Usage
CLI
# Ingest a directory of PDFs and Markdown files python rag_pipeline.py ingest --source ./docsIngest a single file
python rag_pipeline.py ingest --source ./contracts/tos.pdf
Ingest a web page
python rag_pipeline.py ingest --source https://docs.yourproduct.com/faq
Query (with reranker, default)
python rag_pipeline.py query --question "What are the SLA guarantees?"
Query without reranker (faster, slightly less precise)
python rag_pipeline.py query --question "Who do I contact for billing?" --no-reranker
Stream the answer token by token
python rag_pipeline.py query --question "Summarise the privacy policy" --stream
Streamlit chat UI
streamlit run rag_pipeline.py
Opens a browser chat interface with a sidebar for ingesting new documents on the fly.
REST API
uvicorn rag_pipeline:app --reload
| Endpoint | Method | Description |
|---|---|---|
/query | POST | Ask a question, get a cited answer |
/ingest?source=... | POST | Ingest a new source at runtime |
/health | GET | Health check |
Example request:
curl -X POST http://localhost:8000/query \
-H "Content-Type: application/json" \
-d '{"question": "What is our cancellation policy?", "use_reranker": true}'
Example response:
{
"question": "What is our cancellation policy?",
"answer": "Customers may cancel within 30 days for a full refund...\n\nSources:\n[1] tos.pdf, p.4\n[2] faq.md"
}
Configuration
All settings live in .env. Key options:
| Variable | Default | Description |
|---|---|---|
OPENAI_API_KEY | — | Required |
EMBED_MODEL | text-embedding-3-small | Cheaper than ada-002, better quality |
LLM_MODEL | gpt-4o | Swap to gpt-4o-mini to cut costs |
CHUNK_SIZE | 800 | Tokens per chunk. Increase for dense docs |
CHUNK_OVERLAP | 120 | Overlap between chunks. Prevents split-sentence misses |
TOP_K | 6 | Chunks fetched before reranking |
RERANK_TOP_N | 3 | Chunks passed to the LLM after reranking |
CHROMA_PATH | ./chroma_db | Local vector store directory |
Swapping to Pinecone
# In rag_pipeline.py, replace build_vectorstore() with: from langchain_community.vectorstores import Pinecone import pinecone
pinecone.init(api_key=os.getenv("PINECONE_API_KEY"), environment=os.getenv("PINECONE_ENV")) vs = Pinecone.from_documents(chunks, embeddings, index_name=os.getenv("PINECONE_INDEX"))
Using local models (Ollama)
ollama pull nomic-embed-text
ollama pull mistral
# Replace embeddings + LLM in rag_pipeline.py: from langchain_community.embeddings import OllamaEmbeddings from langchain_community.chat_models import ChatOllama
embeddings = OllamaEmbeddings(model="nomic-embed-text") llm = ChatOllama(model="mistral", temperature=0)
Fully local, zero API costs.
Output example
> Q: What is the enterprise refund window?> A: Enterprise customers are entitled to a full refund within 30 days of purchase, provided the cancellation request is submitted via the billing portal. Partial refunds are not available after the 30-day window.
Sources: [1] enterprise-tos.pdf, p.4 [2] pricing-faq.md
Project structure
rag_pipeline.py Main pipeline — ingest, retrieve, generate, API, UI
.env.example Environment variable template
.env Your local config (git-ignored)
chroma_db/ Persisted vector store (auto-created on first ingest)
docs/ Put your source documents here
Delivering this as a freelance gig
A typical engagement looks like this:
- Discovery call — understand the client's document types, volume, and query patterns
- Ingest + test — run their docs through the pipeline, tune
CHUNK_SIZEandTOP_K - Reranker eval — compare answers with/without the cross-encoder on 20 sample questions
- Handoff — deliver the code,
.env.example, and a short Loom walkthrough
Upsell hooks: persistent chat history (add Redis), multi-user auth (add Clerk/Auth0), Slack bot integration, automated re-ingestion on doc update (add a webhook).