A full-stack application combining a FastAPI backend with a Next.js chatbot UI that enables users to upload PDF documents, ask questions about their content, and query connected databases using natural language.
- Overview
- Architecture
- Technology Stack
- AI Agent Structure
- API Endpoints
- Database Schema
- Getting Started
- Environment Variables
This system provides:
- PDF Document Upload & Processing - Upload PDFs, extract text, generate page images, and store vector embeddings
- AI-Powered Q&A - Ask natural language questions about your documents
- Multimodal Responses - Get answers with relevant document page images
- Database Querying - Query connected databases using natural language via a specialized subagent
- User Isolation - Each user's documents and data are completely isolated
- Session Memory - Conversation context is maintained across messages
┌─────────────────────────────────────────────────────────────────────┐
│ Next.js Frontend │
│ (chatbot-nextjs/) │
│ - Login/Registration (Zustand + localStorage) │
│ - Document Upload/Management (React Query + Dropzone) │
│ - Chat Interface (Framer Motion animations) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ FastAPI Backend │
│ (main.py) │
│ /api/v1/login - JWT Authentication │
│ /api/v1/documents - Document CRUD operations │
│ /api/v1/chat - AI Agent interaction │
│ /api/v1/database - Database schema exploration │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ AI Agent Layer │
│ (app/agents/agent.py) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Main RAG Agent (xAI Grok 4) │ │
│ │ - Vector search for document content │ │
│ │ - Page image retrieval │ │
│ │ - Full document reconstruction │ │
│ │ - Delegates database queries to subagent │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Database Subagent (xAI Grok 4) │ │
│ │ - Schema introspection │ │
│ │ - SQL query execution (SELECT only) │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Supabase │
│ - PostgreSQL Database (documents, chunks, pages, users) │
│ - Vector Store (pgvector for embeddings) │
│ - File Storage (PDF documents) │
│ - Authentication │
└─────────────────────────────────────────────────────────────────────┘
| Technology | Purpose |
|---|---|
| FastAPI | REST API framework |
| Python 3.12 | Runtime environment |
| Uvicorn | ASGI server |
| Pydantic | Data validation and serialization |
| python-jose | JWT token handling |
| bcrypt | Password hashing |
| Technology | Purpose |
|---|---|
| LangChain | Agent orchestration framework |
| LangGraph | Stateful agent workflows with memory |
| deepagents | Hierarchical agent creation with subagents |
| xAI Grok 4 | Primary LLM (grok-4-fast-non-reasoning) |
| OpenAI Embeddings | Text-to-vector conversion for semantic search |
| Technology | Purpose |
|---|---|
| Supabase | Backend-as-a-Service (PostgreSQL + Storage + Auth) |
| pgvector | Vector similarity search extension |
| Supabase Storage | PDF file storage |
| Technology | Purpose |
|---|---|
| PyMuPDF (fitz) | PDF parsing, text extraction, image rendering |
| LangChain Text Splitters | Recursive text chunking |
| Technology | Purpose |
|---|---|
| Next.js 14 | React framework with App Router |
| React 18 | UI library |
| TypeScript | Type-safe JavaScript |
| TailwindCSS | Utility-first CSS styling |
| Zustand | Lightweight state management (auth, chat) |
| React Query (@tanstack/react-query) | Server state management & caching |
| Framer Motion | Animations and transitions |
| Axios | HTTP client for API calls |
| react-dropzone | Drag-and-drop file uploads |
| react-markdown | Markdown rendering in chat |
| Lucide React | Icon library |
| Technology | Purpose |
|---|---|
| Docker | Containerization |
| Azure App Service | Cloud hosting (optional) |
The system uses a hierarchical multi-agent architecture powered by LangChain and the deepagents library.
The primary agent handles document-related queries and orchestrates the overall conversation.
Model: xAI Grok 4 Fast Non-Reasoning
Tools:
-
vector_search_tool- Semantic search across document chunks using OpenAI embeddings- Returns text content with metadata (document ID, page number, chapter, similarity score)
- Filters results by 90% similarity threshold
-
get_page_image_tool- Retrieves base64-encoded PNG images of document pages- Middleware intercepts and injects actual images for multimodal responses
-
get_full_document_tool- Reconstructs complete documents from chunks- Assembles all chunks in page/chunk order
- Limited to 3 calls per thread via middleware
-
list_documents_tool- Lists all available documents with metadata -
task()- Delegates queries to the database subagent
Middleware:
ImageInjectionMiddleware- Interceptsget_page_image_toolcalls and injects actual base64 images from the databaseToolCallLimitMiddleware- Limits expensive tool calls (e.g., full document retrieval)
A specialized subagent for structured database queries.
Model: xAI Grok 4 Fast Non-Reasoning
Tools:
get_database_schema- Retrieves table schemas from Supabase OpenAPI endpointexecute_query_tool- Executes validated SELECT queries- SQL validation using
sqlparse - Only SELECT statements allowed for safety
- SQL validation using
InMemorySaver- LangGraph checkpointer for conversation persistence- Session-based threading - Each session maintains its own conversation history
- User-scoped data -
UserScopedSupabasewrapper ensures data isolation
Located in app/agents/system_prompts.py:
MAIN_RAG_AGENT_PROMPT- Instructs the main agent on tool usage, citation requirements, and when to delegate to subagentsDATABASE_SUBAGENT_PROMPT- Guides the database subagent on query execution and result formatting
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/login |
Authenticate user, returns JWT token |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/documents/upload |
Upload single PDF |
| POST | /api/v1/documents/upload-multiple |
Upload multiple PDFs |
| GET | /api/v1/documents |
List user's documents |
| GET | /api/v1/documents/{id}/full |
Get reconstructed document |
| GET | /api/v1/documents/{id}/page/{num} |
Get page image |
| DELETE | /api/v1/documents/{id} |
Delete document |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/chat |
Send message to AI agent |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/database/tables |
Get accessible database tables |
match_documents(query_embedding, user_id, match_count) - RPC function for similarity search with user filtering.
- Python 3.12+
- Supabase project with pgvector extension
- API keys for xAI and OpenAI
- Clone and install dependencies:
pip install -r requirements.txt-
Configure environment variables (see below)
-
Run the API server:
uvicorn main:app --reload --host 0.0.0.0 --port 8000- Run the Next.js frontend:
cd chatbot-nextjs
npm install
npm run devFrontend runs on http://localhost:3000
docker build -t document-chatbot .
docker run -p 8000:8000 --env-file .env document-chatbotCreate a .env file with:
# Supabase
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-key
SUPABASE_SERVICE_KEY=your-service-key
# AI Models
XAI_API_KEY=your-xai-api-key
OPENAI_API_KEY=your-openai-api-key
# JWT
JWT_SECRET_KEY=your-secret-key
JWT_ALGORITHM=HS256
# Next.js Frontend (.env.local in chatbot-nextjs/)
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000- User Data Isolation -
UserScopedSupabasewrapper automatically injectsuser_idfilters into all queries - Multimodal Support - Middleware pattern allows injecting images into tool responses for visual LLM analysis
- Hierarchical Agents - Main agent delegates specialized tasks (database queries) to subagents
- Strict RAG - Agent is instructed to ONLY answer from retrieved documents, never from general knowledge
- Session Memory - LangGraph checkpointer maintains conversation context across messages
- Safety Guards - Database subagent only allows SELECT queries, validated via SQL parsing

