Multi-user AI knowledge and data analysis platform with RAG, personal memory, streaming chat, voice transcription, and dataset analyst agents.
VectorHub is a production-style AI application for ingesting personal knowledge sources and tabular datasets, then interacting with them through secure, streaming AI workflows. It supports normal chat, retrieval-augmented chat over uploaded media, persistent personal memory, human-approved external tools, voice transcription, and an analyst mode for CSV and Excel files.
The repository is intentionally split into three application surfaces:
apps/client: React and Vite single-page application.apps/server: Express gateway for authentication, uploads, public API routing, rate limiting, WebSockets, and FastAPI proxying.ai: FastAPI AI service containing LangGraph workflows, ingestion, retrieval, memory, dataset analysis, database adapters, and vector-store integration.
FastAPI is not designed to be public. Public traffic enters through Nginx and Express, then Express authenticates the user and forwards trusted internal requests to FastAPI with a short-lived internal JWT.
| Area | Implemented behavior |
|---|---|
| AI chat | LangGraph chat workflow with intent routing, RAG context, personal memory, tool decisioning, and SSE streaming. |
| RAG ingestion | YouTube transcripts, text, audio, video, PDF/document uploads, semantic chunking, metadata enrichment, Gemini embeddings, and Qdrant retrieval. |
| Analyst mode | CSV/Excel upload, preprocessing, EDA, schema-aware tool use, pandas queries, statistics, and generated chart artifacts. |
| Personal memory | Durable user memory extraction, semantic deduplication, reconciliation, PostgreSQL persistence, and Qdrant indexing. |
| Authentication | Email/password registration, OTP verification, bcrypt, JWT access tokens, refresh-token rotation, sessions, logout-all, and Google OAuth. |
| Streaming | Browser Fetch stream readers for SSE, Express stream proxying, FastAPI StreamingResponse, and WebSocket voice transcription. |
| Deployment | Docker Compose, Nginx reverse proxy, TLS certificate mount, internal container network, persistent volumes, and health checks. |
HTTPS / WSS
+------------------+ +--------------------+
| Browser | -----> | Nginx |
| React SPA | | TLS, static files |
| Fetch SSE | | /api and /ws proxy |
+------------------+ +---------+----------+
|
| internal Docker DNS
v
+----------+-----------+
| Express Gateway |
| Auth, uploads, WS |
| rate limits, AI proxy|
+----+------------+----+
| |
MongoDB | | internal JWT, SSE proxy
auth/session data | v
| +--------+---------+
| | FastAPI AI |
| | LangGraph, RAG |
| | memory, analyst |
| +---+----+----+----+
| | | |
v v v v
+------+ +-----+ +--------+
| Redis| |Post-| | Qdrant |
| | |gres | | |
+------+ +-----+ +--------+
|
v
+--------------------------------------+
| Groq, Gemini, YouTube, DuckDuckGo, |
| Wikipedia, Gmail, Google OAuth |
+--------------------------------------+
| Boundary | Responsibility |
|---|---|
| React client | UI state, routing, protected/public route gating, chat input, upload modals, SSE parsing, WebSocket microphone capture. |
| Express gateway | Public API surface, MongoDB-backed authentication, refresh sessions, upload handling, Redis-backed rate limits, WebSocket transcription, and internal FastAPI proxy. |
| FastAPI AI service | AI workflows, LangGraph state machines, ingestion pipelines, retrieval, memory, dataset analysis, PostgreSQL models, Qdrant integration, and Redis ingestion status. |
| Nginx | Serves the built React app, redirects HTTP to HTTPS, terminates TLS, proxies /api/ and /ws, and keeps FastAPI unexposed. |
React + Redux + Router
|
| Axios JSON requests with bearer access token
| Fetch requests for SSE chat streams
| WebSocket for live voice transcription
v
Express API Gateway
|
| verifies browser JWT
| manages refresh-token sessions
| stores uploads on shared volume
| signs 90 second internal JWT
v
FastAPI AI Service
|
| validates internal JWT service="express"
| runs LangGraph workflows
| reads and writes AI-domain state
v
Datastores
|
| MongoDB: users, accounts, sessions, OTP, uploaded file metadata
| PostgreSQL: threads, datasets, memory topics, memory conflicts, LangGraph checkpoints
| Redis: rate-limit counters and thread processing status
| Qdrant: chat embeddings and personal memory embeddings
v
External AI and utility providers
|
| Groq chat and transcription
| Gemini embeddings
| YouTube transcript API
| DuckDuckGo and Wikipedia tools
| Gmail and Google OAuth
The primary chat workflow is built in ai/services/chat/graph.py with LangGraph.
POST /api/ai/chat
|
v
Express requireAuth
|
v
Express forwardStreamToAI("/chat")
|
v
FastAPI /chat
|
v
LangGraph START
|
v
intent_node
|-------------------------------+
| |
v v
rag_node or simple_chat_node personal_memory_node
| |
+---------------+---------------+
|
v
chat_node
|
| can answer without tools?
|
+---------+----------+
| |
v v
END tool_node
|
v
interrupt_before tools
|
user approves or denies
|
v
ToolNode
DuckDuckGo, Wikipedia
|
v
chat_node
|
v
END
| Component | File | Role |
|---|---|---|
| Intent router | ai/services/chat/nodes.py |
Classifies whether the user request needs uploaded-content retrieval or normal chat. |
| RAG node | ai/services/chat/nodes.py |
Retrieves documents from Qdrant by user_id and thread_id. |
| Personal memory node | ai/services/chat/nodes.py |
Extracts durable facts, reconciles memory, stores memory, and retrieves relevant memories. |
| Chat node | ai/services/chat/nodes.py |
Builds final prompt from system prompt, personal memory, RAG context, metadata, summary, facts, and recent history. |
| Tool node | ai/services/chat/nodes.py |
Asks the LLM to select an external tool when the structured answer says tools are required. |
| Tools | ai/services/chat/tools_config.py |
Provides DuckDuckGo search and Wikipedia lookup through LangGraph ToolNode. |
| Checkpointing | ai/infrastructure/db/checkpointer.py |
Uses LangGraph Postgres checkpointer when available. |
Authentication is owned by Express and MongoDB. FastAPI only trusts internal JWTs produced by Express.
Registration
React RegisterForm
-> POST /api/auth/register
-> validate fields
-> bcrypt password
-> create User in MongoDB
-> generate OTP
-> store OTP hash and verification token
-> send Gmail OAuth2 email
-> set verificationToken httpOnly cookie
Email verification
React OTP page
-> POST /api/auth/verify
-> compare OTP with stored hash
-> mark User.isVerified=true
-> create Session
-> issue access JWT
-> issue refresh token httpOnly cookie
Login
React LoginForm
-> POST /api/auth/login
-> verify username, password, isVerified
-> create Session
-> store bcrypt refresh token hash
-> return access JWT
-> set refresh token cookie
Refresh
Axios interceptor or App bootstrap
-> POST /api/auth/refresh-token
-> verify refresh JWT
-> find active Session
-> compare refresh token hash
-> rotate refresh token
-> return new access JWT
AI request
React sends bearer access token
-> Express requireAuth verifies JWT_SECRET
-> Express signs internal JWT with INTERNAL_API_SECRET
-> FastAPI validates internal JWT and service="express"
Google sign-in is implemented with arctic. Express creates a state value and PKCE-style code verifier, stores both as httpOnly cookies, redirects to Google, validates the callback, decodes the returned ID token, links the Google account in MongoDB, and then creates the same refresh-token session model as password login.
VectorHub supports several ingestion paths that converge into LangChain Document objects and Qdrant vectors.
User selects media in React
|
v
POST /api/upload
|
v
Express upload controller
|
| file upload: Multer disk storage
| text or YouTube: JSON payload
v
FastAPI /process_media
|
v
BackgroundTasks process_media_upload
|
+-- youtube -> YouTubeTranscriptApi
+-- audio -> Groq Whisper transcription
+-- video -> ffmpeg audio extraction -> Groq Whisper transcription
+-- text -> RecursiveCharacterTextSplitter
+-- document -> Docling DocumentConverter -> semantic chunks
|
v
Document metadata enrichment
|
| document_id
| document_name
| media_type
| user_id
| thread_id
| source/start/duration/type where available
v
Gemini embeddings + optional FastEmbedSparse BM25
|
v
Qdrant CHAT_COLLECTIONN
|
v
rag_node retrieval
|
v
chat_node context injection
| Media type | Entry point | Processor |
|---|---|---|
| YouTube | URL or video ID | youtube_transcript_api fetches transcript chunks. |
| Audio | Uploaded file | Groq Whisper transcription into timestamped segments. |
| Video | Uploaded file | ffmpeg extracts audio, then Groq Whisper transcribes it. |
| Text | Pasted text | Recursive character splitting. |
| PDF/document | Uploaded document | Docling converts content to markdown, then LlamaIndex semantic splitting is used. |
| Dataset | CSV/XLS/XLSX upload | Routed to Analyst Mode instead of the chat RAG pipeline. |
Qdrant is created through ai/infrastructure/vector/qdrant.py. The vector store uses Gemini dense embeddings and attempts to enable FastEmbedSparse("Qdrant/bm25") for hybrid retrieval. Chat embeddings are filtered by metadata fields:
metadata.user_idmetadata.thread_id
This prevents one user's uploaded content from being retrieved in another user's conversation.
Personal memory is separate from uploaded-content RAG.
User message
|
v
personal_memory_node
|
v
PersonalMemoryDecision structured output
|
| should_store
| facts
| should_retrieve
v
store_user_memories
|
v
Semantic candidate lookup in Qdrant PERSONAL_MEMORY_COLLECTION
|
v
Memory reconciliation LLM
|
| ignore
| create
| replace
| merge
| delete
v
PostgreSQL memory_topics and memory_conflicts
|
v
Qdrant memory vector upsert/delete
|
v
retrieve_user_memories
|
v
chat_node prompt context
Memory data is stored in PostgreSQL as durable topic documents. Qdrant stores semantic vectors for retrieval. Conflicts and corrections are captured in memory_conflicts, while active memories live in memory_topics.
Analyst Mode is a separate workflow for CSV and Excel datasets.
React Analyst page
|
v
CSV / Excel upload
|
v
Express /api/upload with media="dataset"
|
v
FastAPI /process_dataset
|
v
run_preprocessing
|
| numeric coercion
| missing value handling
| outlier detection
v
DatasetDB metadata in PostgreSQL
|
v
POST /api/ai/analyst_chat
|
v
Analyst LangGraph workflow
|
+-- preprocessor_agent
+-- eda_agent
+-- analyst_agent with tools
+-- synthesis_agent
|
v
SSE stream
|
| progress events
| text chunks
| tool previews
| visualization JSON
v
React Redux analyst state and MessageBubble charts
| Tool | Purpose |
|---|---|
dataset_summary_tool |
Returns shape, dtypes, null counts, numeric describe output, and categorical counts. |
pandas_query_tool |
Runs schema-validated df.query(...) filters against the active dataset. |
visualization_tool |
Generates bar, line, scatter, histogram, box, or heatmap charts with matplotlib/seaborn and returns base64 PNG JSON. |
statistical_tool |
Runs correlation, groupby, value counts, and describe-column operations. |
The analyst agent binds these tools to a Groq-backed chat model and executes up to MAX_TOOL_ITERATIONS = 8 tool loops before synthesis.
| Channel | Implementation | Purpose |
|---|---|---|
| Chat SSE | React fetch() stream reader -> Express forwardStreamToAI -> FastAPI StreamingResponse |
Streams assistant chunks and tool approval events. |
| Analyst SSE | React analyst hook -> Express stream proxy -> FastAPI analyst route | Streams progress labels, text chunks, tool previews, and visualization artifacts. |
| Voice WebSocket | Browser MediaRecorder -> /ws -> Express ws server -> Groq Whisper |
Sends independent WebM segments and appends partial/final transcripts to the input. |
| Upload status polling | React polling utility -> /api/ai/ingestion_status/:threadId -> Redis |
Tracks queued, processing, completed, failed, and pending states. |
| Store | Used by | Data stored |
|---|---|---|
| MongoDB | Express | User, Account, Session, Otp, VerificationToken, and UploadedFile models. |
| PostgreSQL | FastAPI | Threads, analyst datasets, personal memory topics, memory conflicts, and LangGraph checkpoint tables. |
| Redis | Express and FastAPI | Express rate-limit counters and FastAPI thread ingestion statuses. |
| Qdrant | FastAPI | Chat document embeddings and personal memory embeddings. |
| Docker volumes | Docker Compose services | PostgreSQL data, Redis append-only data, Qdrant storage, and shared uploads. |
| Local upload path | Express and FastAPI | Uploaded media under data/runtime/uploads/{userId}/{threadId} inside the app volume. |
| Route | Method | Purpose |
|---|---|---|
/api/auth/register |
POST | Register user and send OTP email. |
/api/auth/verify |
POST | Verify OTP and create session. |
/api/auth/login |
POST | Password login and session creation. |
/api/auth/refresh-token |
POST | Rotate refresh token and return a new access token. |
/api/auth/logout |
GET | Revoke current session. |
/api/auth/logoutAll |
GET | Revoke all user sessions. |
/api/auth/google |
GET | Start Google OAuth. |
/api/auth/google/callback |
GET | Complete Google OAuth. |
/api/upload |
POST | Upload media or dataset, then forward processing to FastAPI. |
/api/transcript/transcribe |
POST | Transcribe a posted audio blob with Groq. |
/api/ai/* |
GET/POST | Authenticated proxy routes to FastAPI. |
/ws |
WebSocket | Live segmented voice transcription. |
| Route | Purpose |
|---|---|
/chat |
Streaming LangGraph chat execution. |
/analyst_chat |
Streaming analyst workflow execution. |
/process_media |
Background media ingestion. |
/process_dataset |
Dataset preprocessing and metadata persistence. |
| `/threads?mode=chat | analyst` |
/loadConv/{thread_id} |
Load chat conversation from checkpointed state. |
/load_analyst_conv/{thread_id} |
Load analyst conversation and visualizations. |
/ingestion_status/{thread_id} |
Read Redis ingestion status. |
/thread_status/{thread_id} |
Read current thread status with chat fallback. |
/nameChat |
Generate and persist a chat title. |
/nameThreadFromUpload |
Name a thread from uploaded media metadata. |
/health |
Container health check endpoint. |
| Technology | Usage |
|---|---|
| React 19 | SPA component model. |
| Vite | Development server and production build. |
| TypeScript | Frontend type safety. |
| Redux Toolkit | Auth, theme, and analyst state. |
| React Router | Public/protected routes and page navigation. |
| Axios | JSON API client with auth refresh interceptor. |
| Fetch streams | SSE streaming chat and analyst responses. |
| Tailwind CSS | Application styling. |
| React Markdown | Assistant markdown rendering. |
| MediaRecorder API | Browser microphone capture. |
| Technology | Usage |
|---|---|
| Express 5 | Public API gateway. |
| Node.js 22 | Server runtime in Docker. |
| Mongoose | MongoDB models for auth and upload metadata. |
| Multer | File upload handling. |
| bcrypt | Password and refresh-token hashing. |
| jsonwebtoken | Browser and internal JWTs. |
| cookie-parser | httpOnly refresh and OAuth cookies. |
| express-rate-limit | Route-level abuse protection. |
| rate-limit-redis / ioredis | Redis-backed distributed rate limit store. |
| ws | WebSocket transcription endpoint. |
| nodemailer | Gmail OAuth2 email delivery. |
| arctic | Google OAuth flow. |
| Technology | Usage |
|---|---|
| FastAPI | Internal AI API. |
| Pydantic | Request schemas and settings. |
| LangGraph | Chat and analyst workflow orchestration. |
| LangChain | Messages, tools, prompts, embeddings, vector store integration. |
| LangSmith | Tracing hooks and traceable functions. |
| Groq / ChatGroq | Chat model and Whisper transcription integration. |
| Google Gemini | Dense embedding model adapter. |
| LlamaIndex | Semantic splitting for document text. |
| Docling | Document conversion to markdown. |
| pandas / NumPy | Dataset preprocessing and analysis. |
| matplotlib / seaborn | Analyst visualizations. |
| Technology | Usage |
|---|---|
| PostgreSQL 17 | AI-domain relational data and LangGraph checkpoints. |
| MongoDB Atlas | Authentication, sessions, OAuth accounts, OTP, upload metadata. |
| Redis 7 | Rate limits and ingestion status. |
| Qdrant | Vector storage and retrieval. |
| Docker Compose | Multi-container orchestration. |
| Nginx | Static SPA hosting, TLS, reverse proxy, WebSocket upgrade. |
| ffmpeg | Video-to-audio extraction in the AI container. |
.
|-- README.md
|-- requirements.txt
|-- docker-compose.yml
|-- nginx/
| |-- Dockerfile
| `-- nginx.conf
|-- apps/
| |-- client/
| | |-- Dockerfile
| | |-- package.json
| | |-- vite.config.ts
| | |-- tsconfig*.json
| | |-- public/
| | | |-- VectorHub logo.png
| | | |-- favicon.svg
| | | `-- icons.svg
| | `-- src/
| | |-- App.tsx
| | |-- main.tsx
| | |-- config/
| | |-- services/
| | |-- redux/
| | |-- hooks/
| | |-- pages/
| | |-- components/
| | |-- types/
| | |-- utils/
| | `-- assets/
| `-- server/
| |-- Dockerfile
| |-- package.json
| |-- server.ts
| |-- tsconfig.json
| `-- src/
| |-- app.ts
| |-- config/
| |-- controllers/
| |-- middlewares/
| |-- models/
| |-- oauth/
| |-- rate-limit/
| |-- routes/
| |-- services/
| |-- types/
| `-- utils/
`-- ai/
|-- Dockerfile
|-- api/
| |-- app.py
| |-- dependencies.py
| |-- schemas.py
| `-- routes/
|-- core/
|-- domains/
| |-- analyst/
| `-- rag/
|-- infrastructure/
| |-- cache/
| |-- db/
| `-- vector/
`-- services/
|-- analyst/
|-- chat/
|-- ingestion/
|-- media/
|-- rag/
`-- context_builder.py
- Node.js 22 or compatible.
- Python 3.11.
- Docker and Docker Compose for containerized deployment.
- PostgreSQL, Redis, Qdrant, and MongoDB when running services locally outside Docker.
ffmpegfor local video ingestion.- API credentials for Groq, Gemini, Google OAuth/Gmail, and MongoDB.
Do not commit real secrets. The local workspace contains .env and .env.docker, but this README intentionally documents names only.
FastAPI reads the repository-root .env through ai/core/config.py.
DATABASE_URL=
DB_HOST=
DB_PORT=
DB_NAME=
DB_USER=
DB_PASSWORD=
SESSION_SECRET_KEY=
INTERNAL_API_SECRET=
QDRANT_URL=
REDIS_HOST=
REDIS_PORT=
REDIS_PASSWORD=
GROQ_API_KEY=
GEMINI_API_KEY=
LANGSMITH_TRACING=
LANGSMITH_ENDPOINT=
LANGSMITH_API_KEY=
LANGSMITH_PROJECT=Express reads process environment through dotenv.config(). If running from apps/server, provide apps/server/.env or export these variables in the shell. Docker Compose injects them from root .env.docker.
MONGODB_COMPASS_URL=
JWT_SECRET=
GOOGLE_USER=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REFRESH_TOKEN=
GOOGLE_CONTINUE_WITH_GOOGLE_CLIENT_ID=
GOOGLE_CONTINUE_WITH_GOOGLE_CLIENT_SECRET=
GOOGLE_OAUTH_CALLBACK_URL=
CLIENT_URL=
AI_URL=
PORT=
COOKIE_SECURE=
INTERNAL_API_SECRET=
REDIS_HOST=
REDIS_PORT=
REDIS_PASSWORD=
GROQ_API_KEY=The client requires:
VITE_API_BASE_URL=For same-origin production behind Nginx, this can be an empty string when passed as a defined Vite env value. For local development, use the Express origin, for example http://localhost:3000.
Start infrastructure first using your preferred local services or Docker containers for PostgreSQL, Redis, and Qdrant.
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
uvicorn ai.api.app:app --reload --port 8000cd apps/server
npm install
npm run devcd apps/client
npm install
npm run devThe Compose file builds and runs:
nginxserveraipostgresredisqdrant
docker compose up --buildProduction Nginx expects TLS certificates mounted from /etc/letsencrypt for the configured domain in nginx/nginx.conf. For local Docker-only testing, either provide compatible certificates or adjust the Nginx config for local HTTP.
The repository does not include Terraform, CloudFormation, or AWS-specific automation. The provided deployment is a Docker Compose stack that can run on any Docker host, including an EC2 instance, a VM, or a bare-metal server. Nginx exposes ports 80 and 443; Express and FastAPI are only exposed on the Docker network.
Docker host
|
+-- vectorhub-network
|
+-- nginx
| |-- ports 80 and 443
| |-- serves React build
| |-- proxies /api/ to vectorhub-server:3000
| `-- proxies /ws to vectorhub-server:3000 with upgrade headers
|
+-- server
| |-- expose 3000 internally
| |-- depends on redis and ai
| `-- mounts uploads_data
|
+-- ai
| |-- expose 8000 internally
| |-- healthcheck /health
| |-- depends on postgres, redis, qdrant
| `-- mounts uploads_data
|
+-- postgres
| `-- postgres_data
|
+-- redis
| `-- redis_data
|
`-- qdrant
`-- qdrant_data
Express owns public authentication and browser-facing concerns: CORS, cookies, upload parsing, refresh-token sessions, rate limits, Google OAuth, and WebSocket transcription. This keeps browser security logic in one public boundary and prevents the AI service from trusting arbitrary client traffic.
FastAPI runs expensive and sensitive AI workflows. It trusts only a short-lived internal JWT signed by Express with INTERNAL_API_SECRET. This allows the AI service to focus on validated user_id scoped work: ingestion, retrieval, memory, datasets, and LangGraph execution.
MongoDB stores identity and session records through Mongoose models. PostgreSQL stores relational AI-domain state: threads, analyst datasets, memory topics, memory conflicts, and LangGraph checkpoint data. This split mirrors ownership: Express owns auth, FastAPI owns AI state.
Redis is used by Express for distributed rate-limit counters and by FastAPI for ingestion status. FastAPI also includes an in-memory fallback for thread status when Redis is unavailable.
Qdrant is purpose-built for vector retrieval. Chat documents and personal memories need semantic lookup with metadata filters, so they are stored outside PostgreSQL and MongoDB.
The workflows need branching, parallel memory retrieval, resumable state, tool approval interrupts, and checkpointed conversations. LangGraph provides explicit state machines and Postgres-backed checkpointing for those behaviors.
Nginx serves the React build, terminates TLS, redirects HTTP to HTTPS, proxies REST API calls, supports WebSocket upgrades, and hides internal services from the public network.
| Optimization | Implementation |
|---|---|
| SSE streaming | FastAPI streams events, Express forwards chunks, and React reads ReadableStream packets with fetch(). |
| Background ingestion | /process_media schedules processing with FastAPI BackgroundTasks and returns immediately. |
| Redis status cache | Ingestion progress is stored in Redis and polled by the client. |
| Redis-backed rate limits | Auth, upload, AI chat, polling, naming, and transcription routes have route-specific limits. |
| Vector store cache | Qdrant vector store instances are cached per collection in ai/infrastructure/vector/qdrant.py. |
| Hybrid retrieval | Dense Gemini embeddings are combined with optional Qdrant BM25 sparse embeddings when available. |
| Context compaction | context_builder.py summarizes long conversations and keeps recent human/AI turns to control prompt size. |
| Checkpointing | LangGraph stores workflow state in PostgreSQL so conversations and tool approvals can resume. |
| Segmented voice transcription | The client records independent 3-second WebM segments, reducing corruption risk and enabling partial transcript updates. |
| Docker volumes | Database, cache, vector, and upload data persist across container restarts. |
- Access tokens are stored in Redux memory, not localStorage.
- Refresh tokens are httpOnly cookies and are rotated on refresh.
- Refresh token hashes are stored in MongoDB sessions.
- Google OAuth uses state and code-verifier cookies before callback validation.
- AI routes require a browser access token at Express and an internal JWT at FastAPI.
- Nginx only exposes Nginx publicly; Express and FastAPI are internal Docker services.
- Redis rate limits protect auth, uploads, transcription, polling, chat, reads, and naming endpoints.
- Executable upload extensions such as
.exe,.dll, and.batare blocked by the upload middleware.
These are natural extensions of the current architecture, not features currently implemented:
- Add Alembic migrations for PostgreSQL instead of relying only on SQLAlchemy
create_all. - Add automated tests for auth, upload forwarding, FastAPI routes, LangGraph behavior, and frontend streaming reducers.
- Add CI for linting, type checking, Docker builds, and dependency scanning.
- Move uploaded media to object storage such as S3-compatible storage while keeping metadata in MongoDB/PostgreSQL.
- Add a dedicated worker queue for long-running ingestion instead of FastAPI
BackgroundTasks. - Add observability dashboards for request latency, ingestion duration, vector retrieval quality, and model/tool failure rates.
- Add user-facing dataset management for deleting datasets and selecting among multiple datasets in one analyst thread.
- Add deployment IaC if the target environment is fixed to AWS EC2 or another cloud provider.
This README describes the implementation present in the repository:
- React frontend in
apps/client. - Express gateway in
apps/server. - FastAPI AI service in
ai. - Docker Compose stack with Nginx, Express, FastAPI, PostgreSQL, Redis, and Qdrant.
- MongoDB Atlas used by Express through environment configuration.
It intentionally does not document unsupported features such as Kubernetes, Terraform, S3, CI/CD pipelines, or AWS-specific infrastructure files because they are not present in the codebase.