A Retrieval-Augmented Generation (RAG) system for financial documents — annual reports, earnings call transcripts, investor presentations, and SEBI filings. Upload PDFs, ask questions in natural language, and get answers grounded in the source documents with page-level citations.
User → Streamlit UI → FastAPI → Ingestion → Embeddings → ChromaDB
↓
Retriever → Prompt → LLM (Ollama/Gemini) → Answer + Sources
| Layer | Choice |
|---|---|
| Backend API | FastAPI + Uvicorn |
| PDF parsing | PyMuPDF |
| Chunking | LangChain recursive text splitter |
| Embeddings | Local BAAI/bge-small-en-v1.5 (default) or Gemini |
| Vector DB | ChromaDB (persistent, local) |
| LLM | Ollama llama3:latest (default) or Gemini |
| Frontend | Streamlit |
# 1. Create and activate a virtual environment
python3.11 -m venv .venv
source .venv/bin/activate
# 2. Install dependencies (editable package + dev tools)
pip install -r requirements.txt
pip install -e .
# 3. Configure environment
cp .env.example .env
# Defaults use local embeddings + Ollama (no API key required).
# Start Ollama and pull the model: ollama pull llama3:latest
# For Gemini instead, set LLM_PROVIDER=gemini and add GEMINI_API_KEY.ollama serve # if not already running via the Ollama app
ollama pull llama3:latestsource .venv/bin/activate
uvicorn api.main:app --reload --host 127.0.0.1 --port 8000 \
--reload-dir api --reload-dir src --reload-dir configOpen http://127.0.0.1:8000/docs for interactive Swagger UI.
Example flow:
# Upload a PDF
curl -F "file=@data/documents/annual-report-2025-2026.pdf" http://127.0.0.1:8000/upload
# Ingest into the vector store
curl -X POST http://127.0.0.1:8000/ingest \
-H "Content-Type: application/json" \
-d '{"source_file":"annual-report-2025-2026.pdf","company":"TCS","doc_type":"annual_report","year":2026}'
# Ask a question
curl -X POST http://127.0.0.1:8000/query \
-H "Content-Type: application/json" \
-d '{"question":"What risks did TCS mention?","company":"TCS"}'Requires the API server to be running (see above).
source .venv/bin/activate
streamlit run frontend/app.pyOpens http://localhost:8501 by default. Set FINSIGHT_API_URL if the API is not on port 8000.
The UI uses a Chat tab for questions and a Documents & upload tab for ingestion (better on narrow screens).
Answers include inline [filename p.N] citations. Context blocks expose explicit citation tokens; if the LLM omits them, FinSight post-processes the answer to replace Source N labels and append a citations line.
For local development, defaults are permissive but safer than open *:
- CORS restricted to Streamlit origins (
CORS_ORIGINSin.env) - PDF uploads validated by
%PDFmagic bytes and size limit (MAX_UPLOAD_BYTES) - Rate limiting via
RATE_LIMIT(default60/minute)
For production, add authentication and tighten CORS_ORIGINS to your deployed frontend URL.
scripts/evaluate.py scores FinSight on a question set with known answer pages: retrieval
hit@k, citation accuracy, fact match, refusals and latency. eval/questions.jsonl has 46
questions written from the TCS 2025-26 and IndianOil 2024-25 annual reports; with the default
local embeddings, retrieval finds an answer page in the top 5 for 83.7% of them (k=10: 88.4%).
With Llama 3 (8B) on Ollama, 74.4% of answers cite a page that holds the answer, 67.4% state
every key figure, and all 3 questions the reports can't answer are declined. Run it with or
without the LLM:
python scripts/evaluate.py eval/questions.jsonl --retrieval-only # free: retrieval only
python scripts/evaluate.py eval/questions.jsonl # full runSee eval/README.md for the question format and what each number means.
config/ App settings (Pydantic)
src/finsight/ Core library
ingestion/ PDF loading, cleaning, chunking
embeddings/ Embedding providers
vectorstore/ ChromaDB wrapper
retrieval/ Query -> top-k chunks
llm/ LLM providers
prompts/ Prompt templates
pipeline/ Ingest & query orchestration
evaluation.py Scoring for scripts/evaluate.py
api/ FastAPI app
frontend/ Streamlit UI
data/documents/ Uploaded PDFs (gitignored; .gitkeep preserves folder on clone)
storage/chroma/ Vector DB persistence (gitignored)
scripts/ CLI: ingest.py, query.py, evaluate.py
eval/ Evaluation guide and question template (results gitignored)
tests/ Unit & integration tests