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

Published: (February 20, 2026 at 02:01 PM EST)
3 min read
Source: Dev.to

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.toml is all you need. No more setup.py — modern Python packaging is clean.
  • CLIs are underrated. A docqa contract.pdf command 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

0 views
Back to Blog

Related posts

Read more »

Warm Introduction

Introduction Hello everyone! I'm fascinated by the deep tech discussions here. It's truly amazing to see the community thrive. Project Overview I'm passionate...