Skip to content

kmahesh18/documind

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“š DocuMind

Intelligent Document Understanding with RAG (Retrieval-Augmented Generation)

Upload any document β€’ Chat with your files β€’ Get accurate, context-aware answers


🧠 What is RAG?

Retrieval-Augmented Generation (RAG) bridges the gap between what AI models know and what your documents contain.

Think of a large language model like a brilliant scholar locked inside a vast library that closed five years ago. It remembers every page but hasn't read a single new book since. RAG hands that scholar a new ability β€” to walk out, fetch the latest data, and respond with current, evidence-backed information.

The Core Idea

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   QUERY     β”‚ ──▢ β”‚  RETRIEVE   β”‚ ──▢ β”‚   AUGMENT   β”‚ ──▢ β”‚  GENERATE   β”‚
β”‚             β”‚     β”‚  Relevant   β”‚     β”‚   Context   β”‚     β”‚   Answer    β”‚
β”‚ "What's the β”‚     β”‚  Documents  β”‚     β”‚   + Query   β”‚     β”‚  with Facts β”‚
β”‚  refund..." β”‚     β”‚             β”‚     β”‚             β”‚     β”‚             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Why RAG Matters

Without RAG With RAG
"Refunds are typically available within 30 days." (generic guess) "Refunds can be requested within 14 days of purchase, provided the license hasn't been activated." (from your actual policy)

πŸ” Naive vs Neural Retrieval

Every retrieval system walks the same line: finding what's relevant. The trick lies in how relevance is defined.

Naive Retrieval (Keyword Matching)

# TF-IDF based search - matches words, not meaning
query = "renewable energy from the sun"

# Results:
# ❌ "Solar panels convert sunlight into electricity" β†’ 0.00 (no word overlap!)
# βœ… "Wind turbines generate renewable power" β†’ 0.19 (matches "renewable")

The curse: Literal loyalty, semantic blindness.

Neural Retrieval (Semantic Search)

# Sentence embeddings - matches meaning
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('all-MiniLM-L6-v2')
query = "renewable energy from the sun"

# Results:
# βœ… "Solar panels convert sunlight into electricity" β†’ 0.87 (understands solar = sun)
# βœ… "Wind turbines generate renewable power" β†’ 0.55

The magic: No matching words, yet perfect understanding.

Hybrid Approach (Best of Both)

DocuMind combines both for optimal results:

def hybrid_score(bm25_score, vector_score, alpha=0.6):
    return alpha * vector_score + (1 - alpha) * bm25_score

πŸ’Ύ Vector Databases Explained

A model doesn't think in words. It thinks in vectors β€” numerical representations of meaning.

# Text β†’ Vector (384 dimensions)
"Solar panels convert sunlight" β†’ [0.13, 0.72, -0.48, ..., 0.19]
"Renewable energy from sun"    β†’ [0.15, 0.69, -0.45, ..., 0.21]
# Similar meaning = Close vectors in 384-dimensional space

Why Traditional Databases Fail

-- Traditional SQL can't do this:
SELECT * FROM docs WHERE meaning SIMILAR TO 'vacation policy'

-- It can only do exact matches:
SELECT * FROM docs WHERE content LIKE '%vacation%'

Vector Database (Pinecone) Solution

# Semantic search with Pinecone
query_embedding = model.encode("time off policy")
results = index.query(vector=query_embedding, top_k=5)
# Returns: vacation policy, leave guidelines, PTO rules...

πŸ—οΈ Architecture

                                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                   β”‚         DocuMind Frontend        β”‚
                                   β”‚          (Next.js 14)            β”‚
                                   β”‚    β€’ Google OAuth (NextAuth)     β”‚
                                   β”‚    β€’ File Upload UI              β”‚
                                   β”‚    β€’ Chat Interface              β”‚
                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                 β”‚
                                                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              DocuMind Backend (FastAPI)                          β”‚
β”‚                                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚  β”‚   /auth     β”‚  β”‚   /files    β”‚  β”‚   /chat     β”‚  β”‚  /credits   β”‚            β”‚
β”‚  β”‚   Router    β”‚  β”‚   Router    β”‚  β”‚   Router    β”‚  β”‚   Router    β”‚            β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜            β”‚
β”‚         β”‚                β”‚                β”‚                β”‚                    β”‚
β”‚         β–Ό                β–Ό                β–Ό                β–Ό                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚                         Services Layer                               β”‚       β”‚
β”‚  β”‚  β€’ MongoDB Service (Users, Files, Chats, Credits)                   β”‚       β”‚
β”‚  β”‚  β€’ RAG Service (LangChain + Pinecone)                               β”‚       β”‚
β”‚  β”‚  β€’ Local Processor (PDF, DOCX, Images, Audio/Video)                 β”‚       β”‚
β”‚  β”‚  β€’ Payment Service (Razorpay)                                       β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚                    β”‚                    β”‚
                    β–Ό                    β–Ό                    β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚   MongoDB    β”‚     β”‚   Pinecone   β”‚     β”‚  Cloudinary  β”‚
           β”‚   Atlas      β”‚     β”‚ Vector Store β”‚     β”‚  File Store  β”‚
           β”‚              β”‚     β”‚              β”‚     β”‚              β”‚
           β”‚ β€’ Users      β”‚     β”‚ β€’ Embeddings β”‚     β”‚ β€’ PDFs       β”‚
           β”‚ β€’ Files      β”‚     β”‚ β€’ Semantic   β”‚     β”‚ β€’ Images     β”‚
           β”‚ β€’ Chats      β”‚     β”‚   Search     β”‚     β”‚ β€’ Videos     β”‚
           β”‚ β€’ Credits    β”‚     β”‚              β”‚     β”‚ β€’ Audio      β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”„ The Complete RAG Pipeline

Step 1: Indexing (Document Ingestion)

from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Pinecone

# 1. Load document
loader = PyPDFLoader("company_policy.pdf")
docs = loader.load()

# 2. Split into chunks (800 chars, 100 overlap)
splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=100)
chunks = splitter.split_documents(docs)

# 3. Generate embeddings (FREE with local model)
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")

# 4. Store in Pinecone
vectorstore = Pinecone.from_documents(chunks, embeddings, index_name="documind")

Step 2: Retrieval

# User query
query = "What is the vacation policy?"

# Embed query
query_embedding = embeddings.embed_query(query)

# Semantic search (top 5 most relevant chunks)
results = vectorstore.similarity_search(query, k=5)

Step 3: Augmentation

# Build context-aware prompt
context = "\n\n".join([doc.page_content for doc in results])

prompt = f"""
You are a helpful assistant. Answer based ONLY on the context below.
If the information isn't in the context, say "I don't have that information."

Context:
{context}

Question: {query}

Answer:
"""

Step 4: Generation

import google.generativeai as genai

# Generate grounded response
response = genai.generate_text(prompt)
print(response.text)

# Output: "According to your company policy, employees are entitled 
# to 21 days of paid leave annually. Leave requests should be 
# submitted 2 weeks in advance..."

πŸ› οΈ Tech Stack

Layer Technology Purpose
Frontend Next.js 14, TypeScript, Tailwind CSS Modern React UI
Auth NextAuth.js + Google OAuth Secure authentication
Backend FastAPI (Python 3.11+) High-performance API
Database MongoDB Atlas Document storage
Vector DB Pinecone Semantic search
Embeddings Sentence Transformers (all-MiniLM-L6-v2) Local, FREE embeddings
LLM Google Gemini Pro AI responses
File Storage Cloudinary Scalable file CDN
Payments Razorpay Credit system
Deployment Docker + Render Production hosting

πŸš€ Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 20+
  • MongoDB Atlas account
  • Pinecone account
  • Google Cloud Console (OAuth + Gemini API)
  • Cloudinary account

1. Clone & Setup

git clone https://github.com/yourusername/documind.git
cd documind

2. Backend Setup

cd backend

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

# Install dependencies
pip install -r requirements.txt

# Create .env file
cp .env.example .env

Configure backend/.env:

# App
APP_NAME=DocuMind API
API_PREFIX=/api

# MongoDB Atlas
MONGODB_URI=mongodb+srv://<user>:<pass>@cluster.mongodb.net
MONGODB_DB_NAME=documind

# Security
JWT_SECRET=your-super-secret-jwt-key
JWT_ALGORITHM=HS256

# Google OAuth (from Google Cloud Console)
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret

# Gemini AI
GEMINI_API_KEY=your-gemini-api-key

# Pinecone Vector DB
PINECONE_API_KEY=your-pinecone-api-key
PINECONE_ENVIRONMENT=your-environment
PINECONE_INDEX_NAME=documind

# Cloudinary File Storage
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret

# Razorpay Payments
RAZORPAY_KEY_ID=your-key-id
RAZORPAY_KEY_SECRET=your-key-secret

Run backend:

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

3. Frontend Setup

cd frontend

# Install dependencies
npm install

# Create .env file
cp .env.example .env.local

Configure frontend/.env.local:

# API
NEXT_PUBLIC_API_URL=http://localhost:8000

# NextAuth
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-nextauth-secret

# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret

Run frontend:

npm run dev

4. Initialize Database

cd backend
python setup_mongodb.py

Visit http://localhost:3000 and sign in with Google!


🐳 Docker Deployment

Local Development

# Build and run all services
docker-compose up --build

# Run in background
docker-compose up -d

# View logs
docker-compose logs -f

# Stop
docker-compose down

Production Optimizations

The Docker setup is optimized for Render's free tier (512MB RAM):

# Multi-stage build (minimal image)
FROM python:3.11-slim as builder
# ... build dependencies ...

FROM python:3.11-slim as production
# ... only runtime dependencies ...

# Gunicorn with memory-optimized settings
CMD ["gunicorn", "app.main:app",
    "--workers", "2",                    # 2 workers for 512MB
    "--worker-class", "uvicorn.workers.UvicornWorker",
    "--max-requests", "1000",            # Prevent memory leaks
    "--max-requests-jitter", "50",
    "--preload"]                         # Load models once in master

Deploy to Render

  1. Create Web Service for Backend:

    • Root Directory: backend
    • Environment: Docker
    • Add all environment variables from .env
  2. Create Web Service for Frontend:

    • Root Directory: frontend
    • Build Command: npm install && npm run build
    • Start Command: npm start

πŸ“‚ Project Structure

documind/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”‚   β”œβ”€β”€ config.py          # Environment settings
β”‚   β”‚   β”‚   └── security.py        # JWT authentication
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   └── schemas.py         # Pydantic models
β”‚   β”‚   β”œβ”€β”€ routers/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.py            # Google OAuth endpoints
β”‚   β”‚   β”‚   β”œβ”€β”€ files.py           # File upload/management
β”‚   β”‚   β”‚   β”œβ”€β”€ chat.py            # RAG chat endpoints
β”‚   β”‚   β”‚   └── credits.py         # Credit system
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”‚   β”œβ”€β”€ mongodb_service.py # Database operations
β”‚   β”‚   β”‚   β”œβ”€β”€ langchain_rag.py   # RAG pipeline ⭐
β”‚   β”‚   β”‚   β”œβ”€β”€ local_processor.py # Document processing
β”‚   β”‚   β”‚   β”œβ”€β”€ credit_service.py  # Credit management
β”‚   β”‚   β”‚   └── payment_service.py # Razorpay integration
β”‚   β”‚   └── main.py                # FastAPI app
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ requirements.txt
β”‚   └── .env
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ app/                   # Next.js App Router
β”‚   β”‚   β”œβ”€β”€ components/            # React components
β”‚   β”‚   β”œβ”€β”€ contexts/              # React contexts
β”‚   β”‚   β”œβ”€β”€ hooks/                 # Custom hooks
β”‚   β”‚   β”œβ”€β”€ lib/                   # Utilities
β”‚   β”‚   └── types/                 # TypeScript types
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ package.json
β”‚   └── .env.local
β”œβ”€β”€ docker-compose.yml
└── README.md

πŸ”Œ API Reference

Authentication

Method Endpoint Description
POST /api/auth/google Google OAuth login
GET /api/auth/me Get current user

Files

Method Endpoint Description
POST /api/files/upload Upload document
GET /api/files List user files
GET /api/files/{id} Get file details
DELETE /api/files/{id} Delete file

Chat (RAG)

Method Endpoint Description
POST /api/chat Send message (RAG query)
GET /api/chat/history/{file_id} Get chat history

Credits

Method Endpoint Description
GET /api/credits/balance Get credit balance
GET /api/credits/packages List credit packages
POST /api/credits/order Create payment order
POST /api/credits/verify Verify payment

πŸ§ͺ Example: RAG in Action

1. Upload Document

curl -X POST "http://localhost:8000/api/files/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@company_policy.pdf"

2. Ask Question

curl -X POST "http://localhost:8000/api/chat" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": "abc123",
    "message": "What is the vacation policy?"
  }'

3. Response

{
  "response": "According to your company policy, employees are entitled to 21 days of paid leave annually. Leave requests should be submitted at least 2 weeks in advance. Up to 5 days of unused leave can be carried forward to the next year.",
  "sources": [
    {"chunk": "Employees are entitled to 21 days...", "page": 12},
    {"chunk": "Leave requests must be submitted...", "page": 13}
  ]
}

πŸ’° Credit System

Action Credits
Upload file Free
Ask question 1 credit
New users 50 free credits

Credit Packages (Razorpay):

Package Credits Price
Starter 100 β‚Ή99
Pro 500 β‚Ή399
Enterprise 2000 β‚Ή999

πŸ”§ Environment Variables

Backend (.env)

Variable Description Required
MONGODB_URI MongoDB connection string βœ…
MONGODB_DB_NAME Database name βœ…
JWT_SECRET Secret for JWT tokens βœ…
GOOGLE_CLIENT_ID OAuth client ID βœ…
GOOGLE_CLIENT_SECRET OAuth secret βœ…
GEMINI_API_KEY Google Gemini API key βœ…
PINECONE_API_KEY Pinecone API key βœ…
PINECONE_INDEX_NAME Pinecone index name βœ…
CLOUDINARY_CLOUD_NAME Cloudinary cloud name βœ…
CLOUDINARY_API_KEY Cloudinary API key βœ…
CLOUDINARY_API_SECRET Cloudinary API secret βœ…
RAZORPAY_KEY_ID Razorpay key ID βœ…
RAZORPAY_KEY_SECRET Razorpay secret βœ…

Frontend (.env.local)

Variable Description Required
NEXT_PUBLIC_API_URL Backend API URL βœ…
NEXTAUTH_URL Frontend URL βœ…
NEXTAUTH_SECRET NextAuth secret βœ…
GOOGLE_CLIENT_ID OAuth client ID βœ…
GOOGLE_CLIENT_SECRET OAuth secret βœ…

πŸ“ˆ Performance Optimization

Memory Management (for Render 512MB)

# Lazy load embedding model
class RAGService:
    def __init__(self):
        self._model = None
    
    def _get_model(self):
        if self._model is None:
            self._model = SentenceTransformer('all-MiniLM-L6-v2')
        return self._model

Chunking Strategy

# Optimal settings for most documents
splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,      # Not too small (loses context)
    chunk_overlap=100,   # Preserves continuity
    separators=["\n\n", "\n", ". ", " "]  # Natural breaks
)

Retrieval Tuning

# Start with k=5, adjust based on accuracy
results = vectorstore.similarity_search(query, k=5)

# For complex queries, try k=10
# For simple lookups, k=3 is enough

πŸ›‘οΈ Security

  • βœ… JWT-based authentication
  • βœ… Google OAuth 2.0
  • βœ… User data isolation (files, chats)
  • βœ… Non-root Docker containers
  • βœ… Environment variable secrets
  • βœ… CORS configuration

πŸ“š Further Reading


🀝 Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing)
  5. Open Pull Request

πŸ“„ License

MIT License - see LICENSE for details.


Built with ❀️ using RAG technology

Back to top ↑

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors