Upload a bank statement, get instant categorization, anomaly alerts, month-end balance predictions, and a chat assistant that actually knows your transactions.
🔗 Live Demo · Backend not publicly hosted (see Note on the demo)
Dashboard — spending overview, category split, and AI-generated weekly summary
Transactions — full history with statement upload built directly into the page
Upload — bank statement PDF |
Upload — UPI / CSV history |
AI Assistant — ask natural-language questions about your own spending
- Full-stack, two-service architecture — a Next.js app talking to an independent Python ML service over a JWT-secured proxy, not a toy monolith.
- Idempotent ingestion — every transaction gets a deterministic hash ID, so re-uploading the same statement safely re-classifies instead of duplicating rows.
- Tiered classification pipeline — a zero-cost deterministic pass resolves most real-world UPI traffic before the ML model ever runs, cutting inference cost and improving accuracy where it matters most.
- Real, measured model performance — 82.9% F1-score on 600+ hand-labeled transactions (XGBoost vs. fine-tuned DistilBERT), not a hand-wavy number.
- RAG-powered assistant — ask natural-language questions about your own spending, backed by FAISS retrieval over your actual transaction history.
- Parses bank statement PDFs and UPI/CSV history into clean, structured transactions
- Classifies every transaction using a 3-tier pipeline (deterministic tags → rules → ML model)
- Learns your contacts — tag a UPI counterparty once ("PRIYANKA" = Rent), and every past and future transaction from that person is auto-categorized, instantly, at zero ML cost
- Detects anomalies with Isolation Forest ("You spent 3x more on dining this month")
- Predicts month-end balance using an LSTM time-series model
- Answers questions in plain English — "How much did I spend on food last month?" — via a RAG pipeline (LangChain + FAISS + LLaMA 3)
- Visualizes everything on an interactive Recharts dashboard
┌───────────────────────────────┐ ┌──────────────────────────────────┐
│ FRONTEND (Next.js) │ │ ML PIPELINE (FastAPI/Python) │
│ Drizzle ORM · Neon Postgres │◄──────►│ Parser → Cleaner → Classifier │
│ Auth · Dashboard · Chat UI │ HTTP │ (VPA → Rules → XGBoost/BERT) │
│ /api/ml/[...path] proxy │ │ → Anomaly Detector → LSTM │
└───────────────┬───────────────┘ └────────────────┬───────────────────┘
│ │
│ ┌───────────────────────────▼─────────────┐
│ │ RAG LAYER │
│ │ FAISS Vector Store + LangChain │
│ │ LLaMA 3 (via Ollama) │
│ └──────────────────────────────────────────┘
▼
PostgreSQL (Neon) — transactions, vpa_labels, users
The two services communicate over plain HTTP: the frontend proxies ML requests
(/api/ml/[...path]) straight through to FastAPI, and the ML pipeline calls back into the
frontend only for one thing — batch VPA label lookups during classification.
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, TypeScript, Recharts, Tailwind CSS |
| Backend / DB layer | Drizzle ORM, Neon (serverless Postgres), JWT auth |
| ML Service | Python, FastAPI, Pydantic |
| Classification | XGBoost + TF-IDF, fine-tuned DistilBERT (via HF Inference API) |
| Anomaly & Forecasting | Isolation Forest, LSTM (PyTorch) |
| RAG / Chat | LangChain, FAISS, sentence-transformers, LLaMA 3 (Ollama) |
| PDF/CSV Parsing | pdfplumber, pandas |
| Deployment | Vercel (frontend) — ML service run locally / not publicly hosted |
Every transaction runs through three passes, cheapest and most reliable first:
| Pass | What it does | Cost |
|---|---|---|
| 0 — VPA Tags | Matches the UPI counterparty against contacts you've already tagged once | Free, instant |
| 1 — Rule Engine | Known merchant keywords + peer-to-peer UPI pattern matching | Free |
| 2 — ML Model | XGBoost / DistilBERT handles only what's still ambiguous | Model inference |
In practice, most recurring UPI traffic never reaches the ML model at all once a user has tagged their regular contacts — the model earns its keep on genuinely new merchants.
| Model | Purpose | Result |
|---|---|---|
| XGBoost (TF-IDF) / fine-tuned DistilBERT | Transaction classification | 82.9% F1-score on 600+ labeled transactions |
| Isolation Forest | Spending anomaly / spike detection | Flags outlier transactions per category |
| LSTM | Month-end balance forecasting | Time-series prediction from spending history |
| sentence-transformers + FAISS | Retrieval for the RAG chat assistant | Transaction-aware Q&A |
finsight-ai/
├── ml-pipeline/ # FastAPI ML service
│ ├── app/
│ │ ├── routers/ # ingest, classify, anomaly, predict, chat
│ │ ├── services/
│ │ │ ├── parser/ # PDF / CSV / manual parsers
│ │ │ ├── classifier/ # rules.py, xgboost_model.py, bert_model.py
│ │ │ ├── anomaly/ # isolation_forest.py
│ │ │ ├── predictor/ # lstm_model.py
│ │ │ └── rag/ # embedder.py, chatbot.py
│ │ ├── utils/ # cleaner.py, vpa.py, db.py
│ │ └── config/ # categories.py
│ ├── data/ # labeled_transactions.csv (training data)
│ └── requirements.txt
│
├── frontend/ # Next.js app
│ ├── src/
│ │ ├── modules/personal-tags/
│ │ ├── lib/ # vpa.ts, categories.ts
│ │ └── components/
│ └── package.json
│
└── docker-compose.yml
- Python 3.10+
- Node.js 18+
- A Neon (or any Postgres) database
- Ollama installed locally, for LLaMA 3
git clone https://github.com/your-username/finsight-ai.git
cd finsight-aicd ml-pipeline
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # fill in DB credentials
uvicorn app.main:app --reload --port 8000ollama pull llama3cd ../frontend
npm install
cp .env.example .env.local
npm run devML Pipeline docs: http://localhost:8000/docs
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/ingest/pdf |
Upload & parse a bank statement PDF |
| POST | /api/ingest/csv |
Upload UPI history CSV |
| POST | /api/classify |
Run the 3-pass classification pipeline |
| GET | /api/anomaly/{user_id} |
Get anomaly report |
| GET | /api/predict/{user_id} |
Get month-end balance prediction |
| POST | /api/chat |
Ask a natural-language question about your finances |
| GET/PATCH | /api/vpa-labels |
Manage tagged UPI counterparties |
- No OCR — scanned/image-only PDFs return zero rows.
- Password-protected PDFs aren't auto-handled (no password prompt yet).
- Deleting a VPA tag doesn't retroactively re-categorize past transactions — only future ones.
Only the frontend is deployed — the ML service (FastAPI + model files) is heavier than most free hosting tiers allow, so it's run locally for development. The deployed frontend showcases the UI/UX; see the screenshots above for the full ML-powered workflow in action.
Pull requests are welcome. For major changes, please open an issue first to discuss what you'd like to change.
© 2027 Sourabh Kumar — built as a portfolio project at IIT Bhilai.





