P / 03 · RAG platform · Self-hosted AI
ENSET AI
A self-hosted academic RAG platform: students and staff chat with their own PDFs, get streamed answers with source-page citations, and admins run the whole thing from one console.
Self-hosted · CI green on main
Explore repository- Python
- Flask
- React
- PostgreSQL
- MinIO
- Qdrant
- Redis
- Docker
The initial document-chat workspace, before a conversation. PDF upload and reference-document controls are visible.
Image sourceProblem & users
Students and staff want answers from course material, not from a model’s general memory, and their documents and conversations must stay private. The school also needs something it can host, administer and trust, not a demo notebook.
Implementation
Ingestion extracts PDF text, splits it into overlapping chunks, embeds them with all-MiniLM-L6-v2 and stores vectors in Qdrant. At question time Flask checks the user can access each selected document, retrieves the top passages, and streams the answer over SSE with the source pages attached. PostgreSQL holds users, roles, conversations and audit logs; MinIO keeps the original PDFs; Redis backs rate limiting. The LLM layer is provider-agnostic (Gemini, Groq, Mistral, OpenRouter and others), selected per model from admin settings. An admin console manages users, documents, announcements, audit logs, runtime settings and a live health check across database, storage, vector store and providers.
Engineering decision
Treat storage as layers with one source of truth: PDFs and metadata are durable, vectors are rebuildable from them with a reindex script. Keep the optional public landing assistant fully separate from private chat: its endpoints only see admin-approved public context, never session or document IDs, and log metadata only with hashed IP and user agent.
Evidence
CI runs frontend lint and build, backend lint and 30 backend tests including document-privacy tests. Production fixes are documented: a Postgres advisory lock stopped gunicorn workers deadlocking on startup migrations, and a TTL on the settings cache made admin changes reach every worker.
Current limitations
- Citations show which passages were retrieved; they do not prove the answer is correct.
- The public assistant’s grounding is an instruction to the model, not a guaranteed boundary, so its public context must stay free of private data.
On GitHub
- TypeScript
- 1 star
- Updated


