Skip to content
samadarshPublic

About

FinSight: a local-first RAG system for financial PDFs (annual reports, transcripts, filings). Ingest with PyMuPDF, embed with BGE, store in ChromaDB, answer with Ollama/Gemini. FastAPI + Streamlit, page-level citations, multi-company comparison.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

📊 FinSight

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.

Architecture

User → Streamlit UI → FastAPI → Ingestion → Embeddings → ChromaDB
                                                  ↓
                          Retriever → Prompt → LLM (Ollama/Gemini) → Answer + Sources

Tech Stack

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

🚀 Setup

# 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.

Run Ollama (default LLM)

ollama serve          # if not already running via the Ollama app
ollama pull llama3:latest

Run the API

source .venv/bin/activate
uvicorn api.main:app --reload --host 127.0.0.1 --port 8000 \
  --reload-dir api --reload-dir src --reload-dir config

Open 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"}'

💬 Run the frontend

Requires the API server to be running (see above).

source .venv/bin/activate
streamlit run frontend/app.py

Opens 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).

📎 Citations

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.

🔒 Security notes

For local development, defaults are permissive but safer than open *:

  • CORS restricted to Streamlit origins (CORS_ORIGINS in .env)
  • PDF uploads validated by %PDF magic bytes and size limit (MAX_UPLOAD_BYTES)
  • Rate limiting via RATE_LIMIT (default 60/minute)

For production, add authentication and tighten CORS_ORIGINS to your deployed frontend URL.

📏 Evaluation

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 run

See eval/README.md for the question format and what each number means.

Project Structure

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

About

FinSight: a local-first RAG system for financial PDFs (annual reports, transcripts, filings). Ingest with PyMuPDF, embed with BGE, store in ChromaDB, answer with Ollama/Gemini. FastAPI + Streamlit, page-level citations, multi-company comparison.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages