Local-first PDF question answering app for indexing a single document, storing embeddings locally, and answering only from the uploaded content.
This project is built with Streamlit, ChromaDB, SentenceTransformers, PyMuPDF, and Ollama. A user uploads one PDF, the app extracts and chunks the text, stores embeddings in a persistent local vector database, and answers questions using only the uploaded document.
- Upload and index a PDF through a Streamlit web interface
- Extract text locally with
PyMuPDF - Chunk content automatically with LangChain text splitters using fixed app defaults
- Create embeddings locally with
all-MiniLM-L6-v2 - Persist vectors locally with
ChromaDB - Generate answers locally with an
Ollamamodel such asllama3ormistral - Return the exact fallback message when the answer is not supported by the document
- Let the model synthesize summaries and answers from the retrieved document chunks
app.py
config.py
ingest.py
qa.py
vector_store.py
tests/
report/
presentation/
- Python
3.11or3.12 uvfor environment and dependency managementOllamainstalled locally- An Ollama model pulled locally, for example
llama3
Create a fresh environment with a supported Python version:
uv venv --python 3.12
source .venv/bin/activate
uv syncPull a local Ollama model if you do not already have one:
ollama pull llama3source .venv/bin/activate
streamlit run app.pyThen open the local Streamlit URL, upload a PDF, click Index PDF, and start asking questions.
Chunk size and overlap are handled automatically by the app.
- The user uploads a PDF in the Streamlit sidebar.
PyMuPDFextracts text page by page.- LangChain smart chunking breaks each page on likely headings, paragraphs, bullets, and sentence boundaries before falling back to smaller splits.
SentenceTransformerscreates embeddings for each chunk.ChromaDBstores the embeddings and metadata locally.- The user question is embedded and matched against the indexed chunks.
- Retrieved chunks are sent to
Ollamawith a synthesis prompt that can answer questions or summarize the document. - If support is not found, the app returns:
The information is not available in the uploaded document.
- The first version is optimized for one small PDF at a time.
- The vector collection is reset whenever a new PDF is indexed.
- The UI does not yet show citations, but page metadata is stored for future extension.
- Upload a short PDF of 5-6 pages.
- Ask one direct factual question from the document.
- Ask a paraphrased version of the same question.
- Ask an unsupported question to show the fallback behavior.