I built this to experiment with RAG and understand how it truly works. Upload a document, ask questions, get answers grounded in your content. I hope to improve it and make it better with time. Embeddings and all data live in a local Postgres database with pgvector.
- Conversation persistence — chat history saved per conversation, resumable at any time
- Document-scoped chat — pin a specific document to scope the search, or leave it open to search across everything
- Multi-format ingestion — upload PDF, DOCX, TXT, and Markdown files
- RAG with query rewrite — queries get rewritten for precision before embedding and similarity search
- Streaming responses — answers stream in real time
- Authentication — secure sign-up and sign-in
- AI SDK — streaming chat, embeddings, query rewrite
- Gemini —
gemini-2.5-flashfor chat,gemini-embedding-001for embeddings - Drizzle ORM — database queries
- Postgres + pgvector — vector storage and similarity search
# clone and install
git clone https://github.com/mrshabel/shrag
cd shrag
bun install
# set up environment
cp .env.example .env
# start the database, run migrations, and start the dev server
make start
make auto-migration
make migrateOpen http://localhost:3000.
POSTGRES_USER=shrag
POSTGRES_PASSWORD=shrag
POSTGRES_DB=shrag
DATABASE_URL=postgresql://shrag:shrag@localhost:5433/shrag
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3000
GOOGLE_GENERATIVE_AI_API_KEY=make start # start database and dev server
make stop # shut down
make auto-migration # generate migrations from schema changes
make migrate # apply pending migrations
make custom-migration # generate a blank migration to edit manually- Upload a document (PDF, DOCX, TXT, MD) in the Documents tab
- Shrag chunks the text, generates embeddings, and stores them in the database
- When you ask a question, your query gets rewritten, gets embedded and matched against stored chunks using cosine similarity
- The top matching chunks get passed to the LLM as context with their tagged document
- You get an answer grounded in your documents. Pin a specific document to scope the search, or leave it open to search across everything
- Background document processing in a separate worker
- Hybrid search with BM25