Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

DocMind — PDF Chat (Gemini Edition)

Upload any PDF → ask questions → get answers powered by Gemini 2.0 Flash.
Embeddings via Google text-embedding-004. Vector store via ChromaDB (local).
Zero OpenAI. Zero Anthropic. One API key.

PDF Upload
  └─► pypdf (text extraction)
      └─► RecursiveCharacterTextSplitter (chunks, overlap=150)
          └─► text-embedding-004 (Google Gemini API)
              └─► ChromaDB (cosine similarity, persistent)
                  └─► User Question ──► text-embedding-004 (query embed)
                                        └─► top-5 chunks retrieved
                                            └─► gemini-2.0-flash (strict RAG)
                                                └─► Answer

Folder Structure

pdf-chat/
├── backend/
│   ├── main.py                   # FastAPI: /upload  /ask  /session  /health
│   ├── config.py                 # All settings via .env
│   ├── requirements.txt          # google-generativeai, chromadb, pypdf, fastapi
│   ├── .env.example
│   └── services/
│       ├── pdf_processor.py      # pypdf + RecursiveCharacterTextSplitter
│       ├── vector_store.py       # text-embedding-004 + ChromaDB
│       └── llm_service.py        # gemini-2.0-flash, strict RAG prompt
└── frontend/
    ├── index.html
    ├── package.json
    ├── vite.config.js            # Proxies /upload /ask → localhost:8000
    ├── tailwind.config.js
    └── src/
        ├── App.jsx               # Root layout
        ├── main.jsx
        ├── index.css
        ├── hooks/useChat.js      # All state management
        ├── utils/api.js          # Backend API client (XHR for progress)
        └── components/
            ├── Sidebar.jsx
            ├── UploadZone.jsx
            ├── ChatWindow.jsx
            ├── ChatInput.jsx
            ├── MessageBubble.jsx
            ├── TypingIndicator.jsx
            └── ErrorBanner.jsx

Prerequisites

Tool Version
Python 3.10+
Node.js 18+
Gemini API key Free at aistudio.google.com/apikey

Setup & Run

Step 1 — Get your Gemini API key

Go to https://aistudio.google.com/apikey → Create API key → Copy it.

Step 2 — Backend

cd pdf-chat/backend

# Create virtual environment
python -m venv venv
source venv/bin/activate          # Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Configure
cp .env.example .env
# Open .env and set: GEMINI_API_KEY=AIza_your_key_here

# Start server
uvicorn main:app --reload --host 0.0.0.0 --port 8000

You should see:

INFO:     Uvicorn running on http://0.0.0.0:8000
INFO:     ChromaDB initialised.

Step 3 — Frontend

cd pdf-chat/frontend

npm install
npm run dev
# → Open http://localhost:5173

API Reference

POST /upload

Request: multipart/form-data, field file (PDF only, max 50 MB)

Response:

{
  "session_id": "3f2a...",
  "filename": "report.pdf",
  "chunks": 134,
  "message": "Processed successfully — 134 chunks indexed."
}

POST /ask

Request:

{ "session_id": "3f2a...", "question": "What is the conclusion?" }

Response:

{ "answer": "The conclusion states that..." }

DELETE /session/{session_id}

Removes the ChromaDB collection for that session.

GET /health

{ "status": "ok", "llm": "gemini-2.0-flash" }

Configuration (.env)

Variable Default Description
GEMINI_API_KEY (required) From Google AI Studio
GEMINI_LLM_MODEL gemini-2.0-flash For answering questions
GEMINI_EMBEDDING_MODEL text-embedding-004 For chunk + query embeddings
CHUNK_SIZE 800 Characters per chunk
CHUNK_OVERLAP 150 Overlap between adjacent chunks
TOP_K_CHUNKS 5 Chunks retrieved per query
MAX_FILE_SIZE_MB 50 Upload size limit
MAX_CONTEXT_CHARS 12000 Max chars passed to LLM per query
CHROMA_PERSIST_DIR ./chroma_db ChromaDB storage path

Why These Choices?

Component Choice Reason
LLM gemini-2.0-flash Fast, cheap, excellent instruction following
Embeddings text-embedding-004 Google's best embedding model, 768-dim, same API key
Vector DB ChromaDB Local, persistent, no extra service needed
Chunking RecursiveCharacterTextSplitter Respects sentence/paragraph boundaries
Overlap 150 chars Prevents answers split across chunk boundaries

Known Limitations

  • Image-only / scanned PDFs — pypdf cannot extract text from scanned images. The PDF must have embedded text.
  • Gemini free tier rate limits — if you upload a very large PDF (500+ chunks), the embedding step may hit rate limits. Add a short time.sleep(1) between batches in vector_store.py if needed.
  • Session memory — sessions are tied to the FastAPI process. Restarting the server loses the in-memory session mapping, but ChromaDB data persists on disk.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages