DocRAG is a full-stack web application that lets you upload PDF or plain-text documents and ask natural-language questions about their content. It uses a Retrieval-Augmented Generation (RAG) pipeline powered by Google Gemini to find relevant passages and generate accurate, context-grounded answers.
The goal of DocRAG is to give users a simple, private way to "chat" with their own documents. Instead of manually searching through long files, you upload them once and ask questions in plain English. The AI answers based only on what is in your documents — it will explicitly say when it cannot find relevant information rather than hallucinating.
- Upload multiple PDF and TXT files at once
- Automatic text extraction and chunking
- Semantic similarity search over your documents
- AI-generated answers grounded exclusively in your uploaded content
- Session-based isolation — each browser session has its own document store
- No cloud storage — documents live in server memory for the duration of the session
| Layer | Technology |
|---|---|
| Framework | SvelteKit (Svelte 5) |
| Styling | Tailwind CSS v4 |
| AI / LLM | Google Gemini 2.5 Pro (gemini-2.5-pro) |
| Embeddings | Google Gemini Embedding (gemini-embedding-001) |
| RAG orchestration | LangGraph |
| LLM abstractions | LangChain.js |
| PDF parsing | pdf-parse |
| Build tool | Vite |
- The browser sends one or more files as
multipart/form-data. - The server assigns a UUID session ID and stores it in an HTTP-only cookie (24-hour lifetime).
- Each file is read into a buffer:
- PDF files are parsed with
pdf-parseto extract plain text. - TXT files are decoded as UTF-8 directly.
- PDF files are parsed with
- The text is split into overlapping chunks using
RecursiveCharacterTextSplitter(chunk size 1 000 characters, overlap 200 characters). - Every chunk is embedded with the Gemini Embedding model and stored in the session's in-memory vector store.
- The response returns each file name and how many chunks were produced.
A lightweight SimpleVectorStore class holds (embedding, document) pairs in a plain array. When a query arrives, it embeds the query string and ranks every stored chunk by cosine similarity, returning the top-k results. There is no external database — the store lives in Node.js module memory and is keyed by session ID.
- The browser sends the user's question as JSON.
- The server looks up the session cookie and verifies a document store exists for it.
runRAGis called, which builds a two-node LangGraph state machine:
START → retrieve → generate → END
- retrieve — embeds the question and fetches the top-5 most relevant document chunks from the vector store.
- generate — passes those chunks as context to Gemini 2.5 Pro with a system prompt that instructs the model to answer only from the provided context.
- The final answer string is returned to the browser.
The single-page UI has two panels:
- Documents panel (left sidebar) — a drag-and-drop / click file picker that shows selected files with their sizes, a list of already-loaded files with chunk counts, and an upload button.
- Chat panel (main area) — a scrollable message thread plus a text input. Pressing Enter (or clicking Send) posts the question. The assistant's reply is appended when the request resolves.
src/
├── app.css # Global styles and CSS variables
├── app.html # HTML shell
├── lib/
│ └── server/
│ ├── rag.ts # LangGraph RAG pipeline
│ └── session.ts # In-memory vector store + session management
└── routes/
├── +layout.svelte # Root layout
├── +page.svelte # Main UI (upload + chat)
└── api/
├── chat/
│ └── +server.ts # POST /api/chat
└── upload/
└── +server.ts # POST /api/upload
- Node.js 18+
- A Google AI Studio API key with access to the Gemini models
# Install dependencies
npm install
# Create an environment file
echo "GOOGLE_API_KEY=your_api_key_here" > .envnpm run devOpen http://localhost:5173 in your browser.
npm run build
npm run preview| Variable | Description |
|---|---|
GOOGLE_API_KEY |
Google Generative AI API key used for both embeddings and chat generation |
- In-memory only — the vector store is reset on every server restart. Documents must be re-uploaded after a restart.
- Session expiry — the session cookie expires after 24 hours.
- No persistence — there is no database; all document data is held in RAM.
- Single server — the in-memory store is not shared across multiple server instances.