Intelligent Document Assistant powered by RAG
Upload a PDF, Word doc, or text file. Ask questions. Get answers with exact page citations — backed by semantic vector search, not just keyword matching.
| Multi-format upload | PDF (page-aware), DOCX via Mammoth, TXT, Markdown |
| Semantic RAG | OpenAI text-embedding-3-small embeddings → cosine similarity retrieval; falls back to keyword scoring when no key is present |
| Page-level citations | Every answer cites exact page numbers (p. 3–5) pulled from the original document |
| Streaming responses | Server-Sent Events deliver tokens as they arrive, with a live cursor |
| Web cross-check | Manual toggle or automatic detection — if your question contains signals like "latest", "verify", "as of", or "compare", the web search fires automatically and Claude flags any conflicts with the document |
| Multi-document | Upload several files; select which ones to search per query |
| Three LLM providers | Anthropic Claude Sonnet 4, OpenAI GPT-4o, or any local Ollama model — switchable in-app |
| File caching | Original buffers are held in memory so source passage highlighting is always available |
git clone https://github.com/your-username/docmind.git
cd docmind
npm installcp .env.local.example .env.localThen edit .env.local:
# Required for Claude (default provider)
ANTHROPIC_API_KEY=sk-ant-...
# Optional — enables semantic embeddings + GPT-4o chat
OPENAI_API_KEY=sk-...Tip: Keys can also be entered directly in the in-app Settings panel (⚙ in the header). Browser-stored keys always take precedence over env vars.
npm run devOpen http://localhost:3000.
No API costs, fully private.
# Install Ollama
# macOS
brew install ollama
# Linux
curl -fsSL https://ollama.com/install.sh | sh
# Pull a model
ollama pull llama3.2 # ~2 GB, fast
ollama pull mistral # ~4 GB, higher quality
ollama pull phi3:mini # ~2 GB, fastestThen open Settings in the app, choose Local via Ollama, set the base URL (http://localhost:11434), and enter your model name.
Note: Web cross-check requires Anthropic — it is silently skipped for OpenAI and Ollama.
┌─────────────────────────────────────────────────────────────┐
│ UPLOAD PIPELINE │
│ │
│ File → extractTextWithPages() ──────────────────────────┐ │
│ (pdf-parse page hooks / Mammoth / plain UTF-8) │ │
│ ↓ │
│ chunkTextWithPages() → [{text, pages[]}] │ │
│ (1 500-char chunks, 200-char overlap, │ │
│ page sentinel tracking) │ │
│ ↓ │
│ generateEmbeddings() → float[] per chunk │ │
│ (OpenAI text-embedding-3-small, batched) │ │
│ ↓ │
│ In-memory store: documents, chunks, file buffer │ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ CHAT / RETRIEVAL LOOP │
│ │
│ Question → embed query (text-embedding-3-small) │
│ → cosineSimilarity() against all chunk embeddings │
│ (falls back to keywordScore() without a key) │
│ → top-6 chunks with page numbers │
│ → shouldAutoWebSearch(query)? │
│ yes → fetchWebResults() via Claude tool use │
│ → buildSystemPrompt(context, webResults) │
│ → stream response (Claude / GPT-4o / Ollama) │
│ → SSE: { sources[], webSearchAuto, text, done } │
└─────────────────────────────────────────────────────────────┘
docmind/
├── app/
│ ├── api/
│ │ ├── upload/route.ts ← Extraction, chunking, embedding, caching
│ │ ├── chat/route.ts ← Query embedding, RAG, auto web-search, streaming
│ │ └── documents/route.ts ← List & delete documents
│ ├── components/
│ │ └── SettingsPanel.tsx ← Provider / API key configuration UI
│ ├── lib/
│ │ ├── chunker.ts ← extractTextWithPages, chunkTextWithPages, generateEmbeddings
│ │ ├── retrieval.ts ← retrieveChunks (cosine + keyword), buildContext, buildSystemPrompt
│ │ ├── store.ts ← In-memory documents / chunks / file buffers
│ │ └── providers.ts ← Provider type definitions and metadata
│ ├── page.tsx ← Main chat UI
│ ├── layout.tsx
│ └── globals.css
├── .env.local.example
├── next.config.ts
└── package.json
| Component | Current (dev) | Recommended for production |
|---|---|---|
| Vector store | In-memory Map |
Pinecone · pgvector · Qdrant |
| File storage | In-memory Buffer |
S3 · Cloudflare R2 |
| Embeddings | text-embedding-3-small via OpenAI |
Same, or self-hosted via Ollama |
| Database | None | PostgreSQL · Supabase |
| Auth | None | Clerk · NextAuth.js |
| Deployment | npm run dev |
Vercel · Railway · Docker |
MIT