← Open the interactive desktop

Sumit Jadhav

AI/ML Engineer · B.Tech AI & DS '27 · 2nd at ANRF AISEHack (IIT Delhi) · 3rd nationally at AISEHack 2.0 (GalaxEye) · Deep Learning · Remote Sensing · GenAI Agents

I'm a final-year B.Tech student in Artificial Intelligence & Data Science at MGM's Jawaharlal Nehru College of Engineering (MGM University), graduating in 2027 with a CGPA of 8.04. I build machine-learning systems end to end, from the data and the model to a deployed app someone can actually use.

Selected work

Every project links to its code. Metrics link to their proof where one has been attached.

What broke, and how it was found

PM2.5 Forecasting
Dependency resolution failed under a force-injected Gradio
root cause The Space force-injected gradio 6.20.0, which conflicted with the old gradio and huggingface_hub pins in requirements.txt.
Expected
The Space rebuilds from requirements.txt.
Observed
The build failed with ResolutionImpossible.
Fix
Dropped the pins, set sdk_version 6.20.0, and moved theme and css from Blocks() to launch() for Gradio 6. The sync workflow also needed fetch-depth 0 to stop shallow pushes being rejected.
SAR Crop Yield Forecasting
The decaying-limb rule scored +0.284 — and only because of a drift
root cause The rule predicts a higher canopy than persistence, and the district sits +1.65 dB higher from June to November, so it could win by being biased in the direction of a drift neither predictor models.
Expected
A fitted senescence limb projected forward beats persistence at a 30-day horizon (pre-registered claim 9).
Observed
On the raw level it scored +0.284 [+0.206, +0.353] against persistence, with an interval excluding zero.
Fix
Built a control that hands every predictor the drift. Under it the decaying rule scores −0.409. The shipped projection became a flat hold; the decaying variant is kept as B5 so the comparison stays runnable rather than becoming a claim in a comment.
Verified by
Leave-future-out back-test: fit on T1–T4, predict T6, 2000-bootstrap intervals.
Learned
The back-test did not certify the model. It deleted a rule that looked principled, produced a favourable headline, and did not survive a control built to break it.
SAR Crop Yield Forecasting
The Kaggle re-run moved 39 plots between crops
root cause Tier-2 plots were ranked on the November canopy clipped at zero, so 403 of the 793 allocated plots tied at exactly 0.0 and an unstable sort settled the bajra/maize cut.
Expected
Running the notebook end to end on Kaggle reproduces logs/pipeline_clean.log number for number.
Observed
Every SAR number matched, but the tier-2 allocation moved: Maize 316 → 277, Bajra 136 → 175, village total 898.3 t → 896.6 t.
Fix
Rank on the signed departure (TIER2_AXIS = "departure_T6") with a stable mergesort on [axis, farm_id], so the result is a property rather than a coincidence. A shuffled-input regression test pins it.
Verified by
185 tier-2 labels moved; village total 893.9 t.
Learned
Every gate and forty tests passed, and the number was stable on either machine alone. Running the same code somewhere else was the only control that worked on a quantity with no ground truth.
SAR Crop Yield Forecasting
The write-up audit matched numbers no run had printed
root cause The audit matched bare tokens against the whole log, and both strings happened to occur on unrelated lines.
Expected
audit_writeup.py traces every number in the write-up to the log line that printed it.
Observed
The write-up claimed t5_anomaly ordered the cohorts "Bajra +1.99 dB … Rice +0.24" — numbers no Round 3 run ever printed — and the audit passed.
Fix
--trace now writes every token beside the line it was read off. The claim was replaced by the measured medians and recorded in the ledger as contradicted.
Emotion Classification Pipeline
A model trained by the script could not be loaded by the app
root cause The TF-IDF vectoriser carries preprocess_text as its preprocessor. Pickled from a script run as __main__, the function is recorded as __main__.preprocess_text, a name that does not exist in the app.
Expected
python train_model.py writes artifacts/emotion_model.joblib, and predict.py loads it.
Observed
The script-trained artifact needed a fix before the inference module could load it; a regression test now trains through the script and loads the result.
Fix
When run as __main__, the script registers itself as the train_model module and sets the function's __module__ before building the pipeline, so the pickle refers to train_model.preprocess_text.
Verified by
test_artifact_trained_via_script_loads_in_predict.
Next Word Prediction
The LSTM app would not run on Streamlit Community Cloud
root cause The deployed Python environment could not run the TensorFlow model.
Expected
The deployed Streamlit app loads lstm_model.h5 and ranks next words with the LSTM.
Observed
Three successive fixes — configuring the TensorFlow runtime, a Streamlit-Cloud-compatible TensorFlow, allowing NumPy wheels — did not get it running on Streamlit's Python.
Fix
The deployed app dropped TensorFlow and serves an n-gram predictor built from the quote dataset (up to 5-gram context). The LSTM remains the trained model in the notebook.
AI Video Assistant
Render killed the pipeline on long uploads
root cause pydub loaded the entire decoded file into RAM as raw PCM twice — once to convert to WAV and again to chunk it.
Expected
A long upload is transcribed like a short one.
Observed
The pipeline crashed with "Ran out of memory (used over 512MB)" on Render's free tier.
Fix
One streaming ffmpeg pass (-vn -ac 1 -ar 16000 -f segment) decodes and chunks at constant memory regardless of length; downstream speech-to-text is unchanged. Uploads are also capped at MAX_UPLOAD_MB (default 200), streamed to disk in bounded reads, with a clean 413 above it.
SumitOS — this portfolio
Admin login rejected the correct password on the deployed Worker
root cause Deployed Workers reject a single PBKDF2 deriveBits call above 100,000 iterations. verifyPassword failed closed, which turned the NotSupportedError into "Incorrect password". Local workerd does not enforce the ceiling, so every local test passed.
Expected
The PBKDF2-SHA256 password check (210,000 iterations) verifies the correct password.
Observed
Every password was refused as "Incorrect password", correct or not — only in production.
Fix
Derivation runs in chained rounds that sum to 210,000, each round's output seeding the next; the hashing script derives identically.
Verified by
A throwaway Worker on the edge produced the real error text. The regression test now asserts the per-call iteration count, not only the round trip.
Learned
A green suite was what the bug was hiding behind.
SumitOS — this portfolio
A project link's URL was only checked in the browser
root cause projects.links is a JSON field, checked for shape and entry count only; the URL check ran in the admin UI.
Expected
The server refuses a javascript: URL in a project link.
Observed
A direct PATCH with {"links":[{"url":"javascript:alert(1)"}]} stored a link that executes when a visitor clicks it.
Fix
One allowlist function, urlAllowed, is used by every field that becomes an href; a JSON field opts in with urls: true. Every write path goes through validate, so the admin UI, a raw PATCH and a promoted draft are covered by one guard.
SumitOS — this portfolio
Connecting from claude.ai showed the sign-in form forever
root cause claude.ai opens the page from its own origin and the admin cookie is SameSite=Strict. A reload keeps the cross-site initiator, so the freshly set cookie was withheld.
Expected
After signing in on /admin/authorize, the consent screen appears.
Observed
The sign-in form came back after every successful sign-in. Claude Code was unaffected.
Fix
Navigate with location.assign() instead of reloading: a navigation the page starts itself is same-site, so the cookie is sent.
Evidence
SumitOS — this portfolio
No backdrop blur in the stylesheet reached the page
root cause The CSS build merges -webkit-backdrop-filter and backdrop-filter into one declaration and keeps the last. The file wrote the standard property first, so only the -webkit alias shipped — and current Chrome has dropped it.
Expected
The dock and sidebars render frosted glass.
Observed
They rendered flat. The source and DevTools' Styles pane both looked correct.
Fix
Write -webkit-backdrop-filter first and backdrop-filter second, everywhere; inline blurs use CSS variables so Reduce Transparency can remove them.
Verified by
grep backdrop-filter over the built CSS chunks.

Technical stack

Languages & data
PythonC++JavaSQLJavaScriptPandasNumPy
ML & deep learning
PyTorchTensorFlowScikit-learnOpenCVConvLSTMFourier Neural OperatorHugging Face
Generative AI & MLOps
LangChainRAG architecturesMulti-agent systemsMistral AIpgvectorFastAPIDockerStreamlitGit
Application
ElectronReactVitestGitHub Actions

Experience and education

25 certificates, each with its issuer and credential link, are in the desktop’s Certificates window.

Agent context

The same published content is available to MCP-compatible AI agents through a read-only server, behind OAuth. Read: yes · Write: no — it has no tool that can change anything.

claude mcp add --transport http sumit-context https://sumitos-api.jadhavsumit534.workers.dev/mcp