A semantic search engine for .txt and .md files. The goal is to actually understand what you're asking instead of just matching keywords. Upload a document, query it in plain English, and get back the specific sentence that answers you, not just the paragraph it happens to be sitting in.
Not deployed yet. The backend still needs session isolation before it can go live safely, since right now every upload shares one global collection, which would turn into a multi-user bug pretty fast. Run it locally for now, instructions below.
- Sentence-boundary-aware chunking. Uses
pysbdto split documents on real sentence boundaries instead of blind character slicing, with a hard-split fallback for the rare sentence that's still too long on its own - Two-tiered reranking engine. ChromaDB handles macro retrieval with explicit cosine-distance search, then a sentence-level reranker re-scores every sentence inside the retrieved chunks using the same already-loaded embedding model, so RAM never doubles on a 512MB free-tier box
- Highlighted-sentence responses. Every search result comes back with
score,highlighted_sentence, andsentence_score, so the UI can point at the exact sentence that matched instead of the whole chunk - Fully local embeddings. Runs
all-MiniLM-L6-v2viasentence-transformerson-device, no external API calls, no data leaving the machine - Rich chunk metadata. Each chunk tracks
start_sentence,end_sentence,start_char, andend_charfor precise provenance back to the source file
Requires Python 3.11+ and Node 18+.
Backend
cd backend
python -m venv venv
source venv/bin/activate # or venv\Scripts\activate on Windows
pip install -r requirements.txt
uvicorn app.main:app --reloadAPI docs at http://127.0.0.1:8000/docs.
Frontend
cd frontend
npm install
npm run devThen open http://localhost:3000.
No environment variables or external services are required — everything, including the embedding model, runs locally.
The hard problem here isn't retrieval, it's precision. ChromaDB is great at finding the right paragraph, but a paragraph isn't an answer, a sentence is. So Contexto retrieves at the chunk level first, since that's cheap and it's what ChromaDB is good at, then re-embeds and cosine-scores every individual sentence inside the top chunks to find the one that actually matters. The reranker reuses the already-loaded all-MiniLM-L6-v2 instance instead of spinning up a second model, which matters a lot on Render's 512MB free tier, since loading the model twice would blow the memory budget.
Chunking took a similar amount of care. Fixed-size character chunking is the obvious first pass, but it slices sentences in half at arbitrary offsets and quietly destroys the semantic signal you're trying to embed in the first place. Contexto chunks on real sentence boundaries with pysbd instead, and falls back to a hard split for the rare sentence that's still too long on its own.
Session isolation is the one piece that's been deliberately put off. Right now every upload lands in a single shared ChromaDB collection, which is fine for local single-user testing but not safe once more than one person is using it at a time. The fix is to tag each chunk with a client-side UUID session_id and filter queries by it. It's designed but not built yet, and it's a hard blocker before anything gets deployed.
| Layer | Library |
|---|---|
| Frontend | Next.js, Tailwind CSS, TypeScript |
| Backend | Python, FastAPI, Uvicorn |
| Vector DB | ChromaDB (embedded, ephemeral storage on the backend by design) |
| Embeddings | sentence-transformers (all-MiniLM-L6-v2) |
| Chunking | pysbd for sentence-boundary detection |
| Deployment (planned) | Vercel (frontend) + Render (backend, via Docker) |
Backend Phase 1 (chunking and reranking) is done. Frontend Phase 2 is still in design: a dark-mode, lab-instrument-inspired UI with a near-black background, a desaturated cyan accent, amber reserved for highlighted sentences, and monospace for numbers, but no components built yet. Session isolation and deployment (Phase 3) come after that.
Built on top of a few open-source projects doing the heavy lifting:
- Sentence-Transformers and the
all-MiniLM-L6-v2model for embeddings - ChromaDB for vector storage and retrieval
- pysbd for sentence boundary detection
Built by Arman Singh