A fully local RAG chat assistant. Ask questions about your own documents and get cited, grounded answers — powered by Ollama, Chroma, and Streamlit. No cloud APIs, no accounts, no data ever leaving your machine.
- Three modes — Notes RAG (answers only from your documents), Reasoning
(direct answers, uncertain facts flagged
[VERIFY]), Web (answers from live web search). - Cited answers — inline
[1]/[2]citations mapped to a Sources panel with similarity + rerank scores and PDF page numbers. - Serious retrieval — hybrid dense + BM25 search with a local cross-encoder reranker, so both fuzzy questions and exact names/IDs are found (details below).
- Smart ingestion — upload
.pdf.docx.md.txt.csv; multi-column PDFs parsed page-aware, docx tables included, markdown split at headings. Content-hash dedup makes re-uploads a no-op. - Multiple knowledge bases — separate named collections (e.g. work / personal), each with per-file management and JSON backup/restore.
- Multi-turn chat — follow-ups like "what about her?" are rewritten into standalone queries before retrieval; conversations persist in SQLite across restarts.
- Honest when it doesn't know — a relevance gate drops weak matches, and an empty retrieval gets a graceful reply instead of a hallucinated answer.
- Built-in eval harness — measure retrieval hit-rate/MRR and LLM-judged answer quality against your own test questions.
question ──► condense follow-up (LLM) ──► dense search ─┐
├─► RRF fusion ─► cross-encoder
BM25 search ──┘ rerank
│
cited, streamed answer ◄── prompt with numbered ◄── expand hits with ┘
context blocks neighbor chunks
Every stage is visible in the UI — a live status narrates the pipeline, and the Sources panel shows exactly what the answer was grounded in.
Prerequisites: Python 3.10+ and Ollama
installed and running (ollama serve, or the desktop app).
git clone https://github.com/zoddiacc/jarvis.git
cd jarvis
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# pull the two local models
ollama pull nomic-embed-text # embeddings
ollama pull gemma4:12b # generation
streamlit run app.pyThe app opens at http://localhost:8501. Keep the terminal open; Ctrl+C stops it. (First question downloads a ~4 MB reranker model once, then everything is offline.)
Optional: one-command launcher
Add an alias to ~/.zshrc (adjust the path to your clone):
alias jarvis='cd ~/path/to/jarvis && .venv/bin/streamlit run app.py'Or create an executable run.sh in the project root:
#!/usr/bin/env bash
cd "$(dirname "$0")"
.venv/bin/streamlit run app.py- Pick a mode in the sidebar (start with Notes RAG).
- Upload documents — they're chunked and embedded once, then reused for every question.
- Ask away. Tune retrieval in the sidebar if you like: number of chunks (
k), the relevance gate, or limit answers to specific files. - Conversations save automatically; create or switch chats from the sidebar.
Write a few test questions about your documents:
[
{"question": "What is the notice period?", "expected_sources": ["contract.pdf"]}
]python eval_rag.py my_evalset.json # hit@k + MRR (fast)
python eval_rag.py my_evalset.json --judge # + LLM-judged faithfulness/relevanceUse --kb <name> for a non-default knowledge base. Run it before and after
changing the pipeline (chunk size, k, models…) to see whether quality actually
moved.
Defaults are gemma4:12b (generation — switchable in the UI to any
installed Ollama model) and nomic-embed-text (embeddings). To change the
defaults, edit GEN_MODEL / EMBED_MODEL at the top of rag_core.py.
Changing the embedding model requires re-uploading documents (old vectors won't
match the new space).
jarvis/
├── app.py # Streamlit chat UI ← run this
├── rag_core.py # framework-agnostic RAG core (ingest, retrieval, prompts)
├── chat_store.py # SQLite persistent chat history
├── eval_rag.py # retrieval/answer quality eval harness (CLI)
├── .streamlit/ # theme + UI config
└── requirements.txt
Generated at runtime (gitignored, safe to delete — rebuilt on next launch):
chroma_db/ (your embedded documents) and data/chats.db (saved chats).
rag_core.py has zero UI dependencies, so you can build other frontends (CLI,
API, …) on the same retrieval pipeline.
