MSc Data Science, AI & Digital Business — GISMA University of Applied Sciences, Berlin Headed for MLOps · ML Reliability · ML Engineering
I build ML systems that don't just work — they stay working.
Core focus: MLOps · ML Reliability Engineering Also open to: ML Engineering · Data Engineering · AI / LLM Engineering · Backend Engineering (Python) · Data Science
📧 nikhiladhikari1@gmail.com · 💼 LinkedIn
Most ML portfolios show a model that runs once. Mine show four systems that keep running. ML systems break at four predictable points — each project below hardens one, in the order a running system meets them:
bad data gets in → the model drifts → live data shifts under it → the same failure repeats.
data quality validation service
⚠️ Bad data doesn't announce itself. A model won't reject a broken file — it trains on it and hands back confident, wrong answers.
It checks every incoming CSV before it reaches the pipeline, so corruption gets caught at the door instead of surfacing three steps downstream where it's expensive to trace.
What it caught:
- 🧪 Run against a real 545,751-row U.S. government dataset
- 🚩 Flagged 5 columns that were 76–97% empty in seconds — the silent rot that quietly poisons any model trained on it
🔗 Live API · 📄 Case study · 🎥 Demo (coming)
▸ How it's built (engineering detail)
The first project in a deliberate MLOps sprint — a small problem on purpose, so the focus stayed on production patterns. Ships a v1-simple-script next to the v2-modular refactor so the diff itself carries the architectural reasoning. Custom exception hierarchy, structured logging, thresholds fully decoupled into config.yaml (re-tune strictness with no code change and no redeploy). Same validation logic exposed both as a CLI and a hosted Cloud Run endpoint. It never mutates source data — it only reports.
production ML monitoring & drift detection
⚠️ The world changes; the model doesn't. A model that passed every test on launch day slowly goes wrong — and the first sign is usually an angry user.
It watches a live model against its training baseline, so decay shows up as a number on a dashboard instead of a complaint in your inbox.
What it caught:
- 🏦 Trained on 2010–2019 U.S. loan data, then watched 2020 applicants after COVID hit
- 📉 Detected the shift directly: 7 of 12 features drifted significantly, the largest by 1.46 standard deviations — a model judging today's borrowers by yesterday's world
🔗 Live API · 📄 Case study · 🎥 Demo (coming)
▸ How it's built (engineering detail)
Four separated layers — data / models / monitoring / serving — each with one job and no cross-layer imports the contracts don't demand. The monitoring layer snapshots a PSI baseline at training time, then scores production data against it under a documented drift policy. CI runs ruff, mypy, a coverage gate, codespell, and a Docker build on every push. Every non-trivial decision is captured as an Architecture Decision Record — the code tells you what, the 27 ADRs tell you why. Deployed and publicly reachable on Cloud Run.
end-to-end data & ML engineering platform
⚠️ Live data never sits still. A model fed a constantly-shifting real-time feed is the hardest kind to keep honest — the data moves under its feet.
It collects live Berlin/VBB departure data every ~10 minutes and predicts one thing — will this train be more than 3 minutes late? — with the full reliability discipline applied end to end, from ingestion to a deployed public API and dashboard.
What it shows:
- 🎯 The first model tried to predict exact delay in seconds and lost to a "just guess zero" baseline (MAE ~45s) — kept in the repo, not hidden
- 🔁 Reframed as binary classification → XGBoost, ROC-AUC 0.886; service type (U-Bahn vs. RE vs. ICE) mattered more than station or time of day
🔗 Live API · Live dashboard · 📄 Case study · 🎥 Demo (coming)
▸ How it's built (engineering detail)
Single-cloud GCP, running inside the always-free tier. GitHub Actions scrapes live departures → Google Cloud Storage (raw vault) → BigQuery (warehouse) → dbt (staging → intermediate → mart, with tests) and a PySpark lake-ETL job → scikit-learn / XGBoost with MLflow tracking → FastAPI on Cloud Run, with a Streamlit dashboard. Orchestrated by a Cloud Run job + Cloud Scheduler, observed via Prometheus + Pushgateway + Grafana, provisioned with Terraform, and demonstrated on a local kind Kubernetes cluster. 14 ADRs record every course-correction, including the regression-to-classification reframe.
RAG + LangGraph agent for incident search
⚠️ The same outage happens twice — because nobody could find the write-up from the first one.
Describe a failure in plain English and get back the most relevant past incidents, their root causes, and how confident the match is. When nothing matches, it refuses to answer rather than inventing a convincing wrong one.
What it does well:
- 🎯 Retrieves the right past incident every time (hit rate 1.00, MRR 0.92)
- 🚦 A CI gate blocks any merge the moment retrieval quality drops — the evaluation framework is the point, not an afterthought
📄 Case study · 🎥 Demo (coming)
▸ How it's built (engineering detail)
Three layers, each answering a different question. Retrieval: section-aware chunks embedded into ChromaDB, grounded generation that cites its sources and declines below a distance threshold (0.30, chosen from a documented sweep — not guessed). Diagnosis: a LangGraph 4-node agent (decompose → retrieve → assess → diagnose) that separates root cause from symptom, with a grounding filter that strips any citation the model invented. Regression gate: CI re-runs the full metric suite on every push and fails the build the moment quality regresses. Models run locally via Ollama (qwen3:8b + nomic-embed-text). Known failure patterns are named in the README, not silently patched.
Daily practice, retyped from spec, not skimmed: python-llm-guided-practice · ml-study-lab · sql-practice
A slow, deep learner — I prioritize first-principles understanding over breadth, and I write down the why (every project above ships its decision log).