I Built a pip-installable RAG Chatbot — Chat With Any Document in 3 Lines of Python
Source: Dev.to
Most RAG tutorials end at streamlit run app.py. Mine did too — until I realized nobody would actually use it that way.
So I turned my document Q&A chatbot into a proper Python package with a clean API and CLI. Here’s how it works and what I learned.
The Problem
Every RAG demo is a Streamlit app. That’s great for showing it off, but terrible for integration. What if someone wants to:
- Use it inside a Flask API?
- Run it from the command line?
- Import it into a Jupyter notebook?
They can’t – because the logic is buried inside Streamlit’s session state.
The Solution: 3 Lines of Python
from docqa import DocumentQA
qa = DocumentQA(openai_api_key="sk-...")
qa.index(["contract.pdf", "meeting_notes.txt"])
answer = qa.ask("What are the payment terms?")
# → "The payment terms are Net 30, as stated in Section 4.2..."
Or from the terminal:
docqa report.pdf notes.txt
# You: What were the key decisions?
# AI: Based on the meeting notes, three decisions were made...
How I Built It
Step 1: Extract the Core Logic
The original chatbot.py mixed everything with Streamlit (st.session_state, st.spinner, st.chat_message). I pulled the RAG pipeline into a clean DocumentQA class:
class DocumentQA:
def __init__(self, openai_api_key=None, model="gpt-4o-mini"):
...
def index(self, file_paths: list[str]) -> dict:
"""Index documents into FAISS vector store."""
...
def ask(self, question: str) -> str:
"""Ask a question — uses RAG if indexed, else general chat."""
...
Key design decisions
- Auto‑detect file types from extensions (PDF, TXT, CSV, DOCX, MD)
- Conversation memory built‑in — follow‑up questions just work
- Dual mode — works as a general chat without any files, and as RAG when files are indexed
Step 2: Add a CLI
A simple argparse wrapper that takes file paths as arguments:
# docqa/cli.py
import argparse
from docqa import DocumentQA
def main():
parser = argparse.ArgumentParser(prog="docqa")
parser.add_argument("files", nargs="*")
args = parser.parse_args()
qa = DocumentQA()
if args.files:
qa.index(args.files)
while True:
question = input("You: ")
print(f"AI: {qa.ask(question)}")
Step 3: Make It pip‑installable
A pyproject.toml with proper metadata:
[project]
name = "docqa-rag"
version = "0.1.0"
description = "Chat with any document using RAG"
[project.scripts]
docqa = "docqa.cli:main"
Now anyone can pip install docqa-rag and have a working RAG chatbot.
The Architecture
User Question
↓
DocumentQA.ask()
↓
┌─────────────────────┐
│ History‑Aware │ ← reformulates question using chat history
│ Retriever │
└─────────┬───────────┘
↓
┌─────────────────────┐
│ FAISS Vector Store │ ← top‑k similar chunks
└─────────┬───────────┘
↓
┌─────────────────────┐
│ GPT‑4o‑mini │ ← generates answer from context + question
└─────────┬───────────┘
↓
Grounded Answer
What I Learned
- Separate logic from UI. If your AI project only works inside Streamlit, it’s a demo, not a tool.
pyproject.tomlis all you need. No moresetup.py— modern Python packaging is clean.- CLIs are underrated. A
docqa contract.pdfcommand is more useful than any web UI for daily work. - Good defaults matter.
gpt-4o-mini, chunk size 1500,k=10retrievals — these work for 90 % of use cases without any config.
Try It
pip install docqa-rag
docqa your-document.pdf
GitHub: RAG-Based-Chatbot-with-Streamlit