Most RAG tutorials end at "run 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 had everything tangled 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."""
...
The 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 general chat without any files, RAG mode with files
Step 2: Add a CLI
A simple argparse wrapper that takes file paths as arguments:
# docqa/cli.py
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=10 retrievals — 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
If you found this useful, star the repo and follow me — I'm building more AI tools in the open.
Top comments (0)