DEV Community

Lakshmi Sravya Vedantham
Lakshmi Sravya Vedantham

Posted on

I Built a pip-installable RAG Chatbot — Chat With Any Document in 3 Lines of Python

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..."
Enter fullscreen mode Exit fullscreen mode

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...
Enter fullscreen mode Exit fullscreen mode

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."""
        ...
Enter fullscreen mode Exit fullscreen mode

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)}")
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

What I Learned

  1. Separate logic from UI. If your AI project only works inside Streamlit, it's a demo, not a tool.

  2. pyproject.toml is all you need. No more setup.py — modern Python packaging is clean.

  3. CLIs are underrated. A docqa contract.pdf command is more useful than any web UI for daily work.

  4. 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
Enter fullscreen mode Exit fullscreen mode

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)