Projects
Things I've built, with the results and the limitations included. Every repo below is public.
- Quest 01Cleared
Multi-label content classification
A DistilBERT fine-tune that predicts every applicable policy label on a comment — toxic, severe_toxic, obscene, threat, insult, identity_hate — not just the most likely one.
Built around one claim: accuracy is the wrong metric. A model that predicts nothing at all scores 89.83% exact-match accuracy on this data at a macro-F1 of exactly 0.0. So the work is choosing the metric, calibrating a threshold per label on validation, and doing real error analysis. Macro-F1 0.6626 at 0.5, 0.6836 with tuned thresholds, against 0.5412 for a TF-IDF one-vs-rest baseline. Documented failure mode: it is English-only and fails silently on Hinglish.
- PyTorch
- Transformers
- DistilBERT
- scikit-learn
- Streamlit
- Quest 02Cleared
Rupee-Optimal Risk
A fraud decision engine that optimises money lost, not F1. On 118k held-out out-of-time transactions, picking the operating point by F1 instead of by rupee cost costs the merchant ₹112,750 per 10,000 transactions.
LightGBM + isotonic calibration on IEEE-CIS (590k transactions), split temporally with each fold given exactly one job. Test PR-AUC 0.498, ECE 0.004, recall 0.536 at the cost-optimal threshold. Served as a FastAPI scorer with SHAP reason codes, an append-only audit log, and a degraded mode that falls back to a count rule rather than failing open or closed — p95 78ms. Two of our own ideas are reported as failures: amount-dependent thresholds measured null, per-band calibration improved validation and degraded test by ₹215k/10k. Cost constants are estimates, and the data is US e-commerce re-denominated at ₹88/USD — the method transfers, the rupee figures are illustrative.
- Python
- LightGBM
- scikit-learn
- FastAPI
- SQLite
- Quest 03Cleared
Battleship over WebSocket
Two-player Battleship on Cloudflare Workers and Durable Objects — one room is one Durable Object that holds both fleets, runs every rule, and persists state, so a dropped connection resumes where it paused. Playable right now, against a friend by invite link or against the server's own bot.
The server is authoritative: a shot returns hit, miss or sunk for that one cell, and neither player is sent the other's layout until the game is over. The computer opponent runs server-side as a player with no socket and is a pure function over its own tracking grid — there is no parameter through which the opposing fleet could arrive, so the suite plays 80 games and fails if one ever finishes in under 20 shots. Hard hunts on parity and needs about 52 shots to Easy's 95. There are no accounts, and rooms have no timeout — they hibernate and evict naturally.
- Cloudflare Workers
- Durable Objects
- WebSockets
- SQLite
- Vanilla JS
- Quest 04Cleared
JobHunter
Finds job postings on public ATS boards, resolves a hiring contact where one is published, scores each opening against your profile, and exports a ranked sheet.
A research assistant that surfaces openings and one right person to email — deliberately not a lead-generation scraper. The rate limiting, robots.txt checks and draft-only outreach are load-bearing design constraints rather than style preferences, and they are documented as such.
- Python
- ATS APIs
- CLI
- Quest 05Cleared
Football player re-identification
Keeps player IDs stable across a football video feed, including when a player leaves the frame and comes back.
YOLOv11 for detection, then multi-modal feature extraction over appearance, motion and temporal cues, with Kalman-filter tracking and feature matching to re-associate identities. Tracks 45 players at a track continuity of 1.00 and an average track length of 126.5 frames; identity preservation across re-entries is the weak point at 0.32, which the repo reports rather than hides.
- Python
- YOLOv11
- OpenCV
- Kalman filter
- CNN embeddings
- Quest 06Cleared
RAG Q&A over industrial safety documents
A question-answering service over industrial and machine safety PDFs, with citations back to the source document.
A cosine-similarity baseline over sentence embeddings, then a hybrid reranker combining vector similarity with BM25 keyword matching to measure what the enhancement actually buys. 20 safety PDFs, exposed behind a REST endpoint.
- Python
- Sentence Transformers
- BM25
- REST API
- Quest 07Cleared
Schema-Aware NL2SQL
Converts natural language questions into SQL across database schemas it has not seen before.
Fine-tuned T5 with QLoRA, conditioned on the target schema so it generalises across dynamic databases rather than memorising one. Ships both a web interface and a REST API.
- Python
- T5
- QLoRA
- FastAPI