ResearchFlow is a production-grade, full-stack AI document analysis platform. You upload PDFs (research papers, legal documents, financial reports) to private workspaces, and then chat with them in natural language. The AI answers are grounded exclusively in your documents, with inline [Source X] citations pointing back to the exact chunks the AI referenced.
Built to demonstrate real-world engineering: async job queues, vector embeddings, RAG pipelines, JWT auth, health monitoring, and containerized deployment.
┌─────────────┐ REST API ┌──────────────────────────────────────────┐
│ React App │ ────────────────► │ NestJS Backend │
│ (Vite/TS) │ ◄──────────────── │ │
└─────────────┘ JWT Protected │ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Auth │ │ Chat │ │ Docs │ │
│ │ /register│ │ /message │ │/upload │ │
│ │ /login │ │ │ │ │ │
│ └──────────┘ └────┬─────┘ └───┬────┘ │
└───────────────────── │ ──────────│──────┘
│ │
RAG Pipeline│ BullMQ│ Queue
▼ ▼
┌──────────────────────────────────────────┐
│ AI Service │
│ 1. Embed query (Gemini Embedding API) │
│ 2. Search chunks (Qdrant vector search) │
│ 3. Inject context + [Source X] labels │
│ 4. Generate answer (Gemini Pro) │
└──────────┬──────────────────┬────────────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ Qdrant │ │ PostgreSQL │
│ Vector Store│ │ (Prisma) │
└─────────────┘ └─────────────┘
┌──────────────────────────────────────────┐
│ Background Worker │
│ PDF → extract text (pdf-parse) │
│ → fallback: Tesseract.js OCR │
│ → chunk text (LangChain splitter) │
│ → embed chunks (Gemini Embedding) │
│ → upsert to Qdrant │
└──────────────────────────────────────────┘
| Feature | Details |
|---|---|
| 🔐 JWT Authentication | Register / login, 15-minute access tokens, bcrypt password hashing |
| 📄 PDF Ingestion | Upload PDFs via multipart form; stored on disk, metadata in Postgres |
| 🧠 Vector Embeddings | Google Gemini Embedding API converts text chunks to 768-dim vectors |
| 🔍 Semantic Search | Qdrant vector DB retrieves the top-K most relevant document chunks |
| 💬 RAG Chat | Retrieved chunks injected into Gemini Pro prompt with citation labels |
| 📎 Inline Citations | AI responses include [Source 1], [Source 2] mapped to doc chunks |
| 🔄 Background Queues | BullMQ + Redis processes documents asynchronously (3 retries, exp backoff) |
| 📷 OCR Fallback | Scanned/image PDFs auto-detected and processed with Tesseract.js locally |
| ⚡ Response Caching | Redis cache reduces redundant AI calls for identical queries |
| 🏥 Health Checks | /health endpoint monitors Postgres + Qdrant liveness via @nestjs/terminus |
| 📖 Swagger Docs | Auto-generated interactive API docs at /api/docs |
| 🐳 Docker Compose | Full stack (API + Postgres + Redis + Qdrant) in one command |
| 🤖 CI Pipeline | GitHub Actions: lint → build on every push to main |
- 83% Reduction in Read Latency: Implementing Redis caching for workspace lookups decreased average database query times from ~120ms to ~20ms.
- Sub-100ms UI Interactivity: Offloading heavy PDF parsing to background queues (BullMQ) keeps the primary Node.js event loop free, preventing API timeouts and ensuring immediate UI feedback on document upload.
- Real-Time Token Streaming: Server-Sent Events (SSE) provide a zero-latency "typing" experience for AI responses, bypassing standard HTTP long-polling constraints.
- Bandwidth Optimization: HTTP response compression (gzip) reduces API payload sizes by up to 70%, significantly speeding up initial page loads and chat history retrieval.
Backend
- NestJS — Modular Node.js framework
- Prisma — Type-safe ORM for PostgreSQL
- BullMQ — Redis-backed job queue for async document processing
- @google/generative-ai — Gemini Pro (chat) + Gemini Embedding (vectors)
- @qdrant/js-client-rest — Vector similarity search
- @nestjs/terminus — Health check endpoints
- @nestjs/swagger — OpenAPI documentation
- Passport.js + JWT — Stateless authentication
- nestjs-pino — Structured JSON logging
- Tesseract.js — Local OCR for scanned PDFs
Frontend
- React 19 + TypeScript — UI framework
- Vite — Build tool and dev server
- Lucide React — Icon system
Infrastructure
- PostgreSQL 15 — Primary database
- Redis — Job queue broker + response cache
- Qdrant — Vector database for semantic search
- Docker + Docker Compose — Containerized deployment
- GitHub Actions — Continuous integration
- Node.js 22+
- Docker + Docker Compose
- A Google AI Studio API key (free)
git clone https://github.com/farhan11166/ResearchFlow.git
cd ResearchFlow
# Set your Gemini API key
export GEMINI_API_KEY=your_key_here
# Boot the entire stack
cd backend && docker-compose upThe API will be available at http://localhost:3000.
# 1. Clone and install backend
git clone https://github.com/farhan11166/ResearchFlow.git
cd ResearchFlow/backend
npm install
# 2. Configure environment
cp .env.example .env
# Edit .env and add your GEMINI_API_KEY
# 3. Start infrastructure (Postgres, Redis, Qdrant)
docker-compose up postgres redis qdrant -d
# 4. Run database migrations
npx prisma migrate deploy
npx prisma generate
# 5. Start the backend
npm run start:dev# In a separate terminal — start the frontend
cd ResearchFlow/frontend
npm install
npm run devOpen http://localhost:5173 in your browser.
Interactive Swagger docs are available at http://localhost:3000/api/docs once the server is running.
| Method | Endpoint | Description | Auth |
|---|---|---|---|
POST |
/auth/register |
Create a new account | Public |
POST |
/auth/login |
Get a JWT access token | Public |
POST |
/workspaces |
Create a new workspace | JWT |
GET |
/workspaces |
List your workspaces | JWT |
POST |
/documents/upload |
Upload a PDF | JWT |
GET |
/documents |
List documents in a workspace | JWT |
POST |
/chat/message |
Send a message (RAG pipeline) | JWT |
GET |
/chat/history/:id |
Get chat history for a session | JWT |
GET |
/health |
System health check | Public |
Copy .env.example to .env and fill in the values:
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/researchflow?schema=public"
REDIS_HOST=localhost
REDIS_PORT=6379
GEMINI_API_KEY="your_api_key_here"
QDRANT_URL="http://localhost:6333"
JWT_SECRET="replace_with_a_long_random_string"ResearchFlow/
├── backend/
│ ├── src/
│ │ ├── ai/ # Embedding, RAG, streaming, BullMQ processor
│ │ ├── auth/ # JWT strategy, register/login
│ │ ├── chat/ # Chat controller, history, session management
│ │ ├── documents/ # Upload, OCR fallback, queue dispatch
│ │ ├── health/ # Health check endpoint
│ │ ├── prisma/ # PrismaService
│ │ ├── workspaces/ # Workspace CRUD + Redis cache
│ │ └── common/ # Exception filters, interceptors
│ ├── prisma/
│ │ └── schema.prisma # Database schema
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── .env.example
└── frontend/
└── src/
├── App.tsx # Auth routing
├── AuthPage.tsx # Login / Register
└── ChatApp.tsx # Main workspace + chat UI
MIT