A full-stack RAG-powered support assistant. Upload your docs, ask questions, get grounded answers with citations.
Stack: FastAPI · PostgreSQL + pgvector · Redis · OpenAI · Next.js · Tailwind
┌─────────────────────────────────────────────────────────┐
│ Next.js Frontend │
│ Chat UI · Upload UI · Admin Dashboard │
└────────────────────┬────────────────────────────────────┘
│ HTTP
┌────────────────────▼────────────────────────────────────┐
│ FastAPI Backend │
│ /api/documents /api/chat /api/conversations │
│ /api/feedback /api/admin/stats │
└──────┬──────────────┬──────────────┬────────────────────┘
│ │ │
┌────▼────┐ ┌─────▼─────┐ ┌───▼────┐
│PostgreSQL│ │ pgvector │ │ Redis │
│(metadata)│ │(embeddings│ │(cache) │
└──────────┘ └───────────┘ └────────┘
│
┌──────▼──────┐
│ OpenAI API │
│ Embeddings + │
│ Chat │
└─────────────┘
- Upload → Extract text from PDF/TXT/MD
- Chunk → Split into ~800 char overlapping chunks
- Embed →
text-embedding-3-smallvia OpenAI - Store → pgvector in PostgreSQL
- Query → Embed user question
- Search → Cosine similarity (top 5 chunks)
- Generate → GPT-4o-mini with retrieved context
- Respond → Answer + source citations
- Python 3.11+
- Node.js 20+
- Docker & Docker Compose
- OpenAI API key
# 1. Clone and enter the project
git clone <repo-url>
cd supportiq
# 2. Set your OpenAI key
export OPENAI_API_KEY=sk-...
# 3. Start everything
cd docker
docker compose up --build
# App runs at:
# Frontend: http://localhost:3000
# Backend: http://localhost:8000
# API docs: http://localhost:8000/docsBackend:
cd backend
# Start Postgres + Redis
docker run -d --name pg -e POSTGRES_DB=supportiq \
-e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password \
-p 5432:5432 pgvector/pgvector:pg16
docker run -d --name redis -p 6379:6379 redis:7-alpine
# Install deps
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
# Configure
cp .env.example .env
# Edit .env with your OPENAI_API_KEY
# Run
uvicorn app.main:app --reload --port 8000Frontend:
cd frontend
npm install
cp .env.example .env.local
# Edit NEXT_PUBLIC_API_URL=http://localhost:8000
npm run dev| Method | Endpoint | Description |
|---|---|---|
| POST | /api/documents/upload |
Upload document (multipart/form-data) |
| GET | /api/documents/ |
List all documents |
| DELETE | /api/documents/{id} |
Delete document |
| POST | /api/chat |
Send message, get RAG response |
| GET | /api/conversations |
List conversations |
| GET | /api/conversations/{id} |
Get conversation with messages |
| POST | /api/feedback |
Submit thumbs up/down |
| GET | /api/admin/stats |
Analytics dashboard data |
Chat request:
{
"question": "How do I reset my password?",
"conversation_id": "optional-uuid-for-multi-turn"
}Chat response:
{
"answer": "To reset your password...",
"sources": [
{
"document_name": "faq.md",
"chunk_index": 2,
"content": "...",
"score": 0.91
}
],
"conversation_id": "uuid",
"message_id": "uuid"
}supportiq/
├── backend/
│ ├── app/
│ │ ├── api/ # Route handlers
│ │ │ ├── documents.py
│ │ │ ├── chat.py
│ │ │ └── admin.py
│ │ ├── services/ # Business logic
│ │ │ ├── document_service.py
│ │ │ ├── chat_service.py
│ │ │ └── admin_service.py
│ │ ├── models/
│ │ │ ├── orm.py # SQLAlchemy models
│ │ │ └── schemas.py # Pydantic schemas
│ │ ├── db/
│ │ │ └── session.py # DB engine + session
│ │ ├── rag/
│ │ │ ├── chunker.py # Text chunking
│ │ │ ├── embeddings.py # OpenAI calls
│ │ │ └── search.py # pgvector search
│ │ ├── core/
│ │ │ ├── config.py # Settings
│ │ │ └── cache.py # Redis client
│ │ └── main.py
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/
│ └── src/
│ ├── app/
│ │ ├── chat/page.tsx # Chat interface
│ │ ├── upload/page.tsx # Document upload
│ │ └── admin/page.tsx # Dashboard
│ ├── components/
│ │ └── Sidebar.tsx
│ ├── lib/
│ │ ├── api.ts # API client
│ │ └── utils.ts
│ └── types/index.ts
├── docker/
│ └── docker-compose.yml
└── sample-docs/
├── acme-faq.md
└── product-docs.txt
# Install Railway CLI
npm install -g @railway/cli
# Login and init
railway login
cd backend && railway init
# Add services: PostgreSQL + Redis from Railway marketplace
# Then deploy
railway up
# Set env vars in Railway dashboard:
# DATABASE_URL (Railway provides this)
# REDIS_URL (Railway provides this)
# OPENAI_API_KEY- Create new Web Service → connect GitHub repo
- Root directory:
backend - Build:
pip install -r requirements.txt - Start:
uvicorn app.main:app --host 0.0.0.0 --port $PORT - Add PostgreSQL and Redis services
- Set env vars
cd frontend
npx vercel
# Set env var:
# NEXT_PUBLIC_API_URL=https://your-backend.railway.appIn sample-docs/:
- acme-faq.md — Customer FAQ with password reset, billing, integrations
- product-docs.txt — Full product documentation with features, shortcuts, pricing
Upload these after starting the app to test the RAG pipeline.
SupportIQ — AI Customer Support Copilot | FastAPI · Next.js · pgvector · OpenAI
Built a full-stack RAG (Retrieval Augmented Generation) system enabling companies to deploy AI-powered support assistants grounded in their own documentation. Implemented semantic search using pgvector with cosine similarity for sub-100ms retrieval, an async FastAPI backend with OpenAI embeddings and GPT-4o-mini for answer generation, and a real-time chat interface with conversation history, citation display, and user feedback collection. Architected with Redis caching to reduce OpenAI API calls by ~60% for repeated queries. Deployed on Railway (backend) and Vercel (frontend).
Backend (.env):
DATABASE_URL=postgresql+asyncpg://postgres:password@localhost:5432/supportiq
REDIS_URL=redis://localhost:6379
OPENAI_API_KEY=sk-...
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
OPENAI_CHAT_MODEL=gpt-4o-mini
CHUNK_SIZE=800
CHUNK_OVERLAP=100
TOP_K_CHUNKS=5
Frontend (.env.local):
NEXT_PUBLIC_API_URL=http://localhost:8000