Inspiration

Every winter, Lahore, Islamabad/Rawalpindi, Peshawar and Karachi fill with smog. Lahore's worst day reached 539 µg/m³ of PM2.5 in November 2024; Pakistan's own 24-hour limit is 35. Actions that protect people (changing school timings, stopping outdoor play, preparing hospital smog counters, stopping burning) must be decided the evening before, but officials usually have only today's reading. Punjab's Smog Action Plan 2025-26 asks for AI-based early warnings. We built a working, open version of that.

What it does

Every evening at 20:00 PKT, for each city, it gives a district environment officer:

  • tomorrow's average PM2.5 with a calibrated 80% range, on the official AQI colours;
  • the chance that tomorrow is unhealthy (≥ 55.5 µg/m³);
  • a recommendation, advise or not, at the officer's own risk threshold (a slider: how much worse a missed smog day is than a false alarm);
  • the main reasons (smog already in the air, weather, fires, season) and a ready-to-forward Urdu message.

It updates every hour on a public dashboard, and an Insight Agent answers questions in English or Urdu with citations to official documents and to the exact data rows, or says "I don't know".

How we built it

  • Data: four free, independent sources: OpenAQ (202 ground sensors, ~905,000 hourly PM2.5 readings; most sensors owned by the Pakistan Air Quality Initiative and The Urban Unit), NASA FIRMS satellite fire detections, Open-Meteo weather (ECMWF) and Copernicus CAMS. Every raw file gets a SHA-256 fingerprint in manifest.csv.
  • Warehouse: raw → cleaned → gold layers in DuckDB; one command, make data, rebuilds everything.
  • Data Quality Agent: flags stuck, spiking, zero and impossible sensor readings, fills only 1–2 hour gaps, logs every fix/fill/flag decision with its reason, and two quality gates stop bad data from being published.
  • Model: scikit-learn gradient-boosted trees using only what is known at 8 PM; baseline ("tomorrow = today"), metric and locked test month declared before any results; rolling-origin validation; quantile models for the range, calibrated with conformalized quantile regression on validation months only.
  • Decision layer: chance of an unhealthy day from the calibrated range; advise when chance ≥ 1/(1+R).
  • Automation: Prefect runs the whole pipeline every hour on a laptop and publishes to a Hugging Face dataset; a static Hugging Face Space dashboard reads it.
  • Insight Agent (RAG): TF-IDF retrieval over WHO, US EPA, Pakistan NEQS and Punjab government documents plus facts built by code from gold rows; Groq gpt-oss (Gemini fallback) writes the answer; our code checks every citation and number, retries once, else "I don't know". Removes personal details; health questions point to Rescue 1122. Hosted on Render with keys as secrets.
  • Self-checks: a public daily report card, an hourly drift monitor (PSI against the same weeks last year, live vs test error), and a comparison with Punjab EPA's government reference stations.

Results

  • 17.7% lower error than "tomorrow = today" on the locked October 2026 test month (MAE 8.94 vs 10.86 µg/m³, 80 city-days).
  • By city: Islamabad/Rawalpindi 39.5% better, Peshawar 20.4%, Lahore 8.7% (just below our declared 10% target), Karachi 17.6% worse (clean, steady air). We report these openly.
  • The 80% range held the real value 91% of the time (66% before calibration).
  • The advisory rule caught 39 of 40 unhealthy test days ("warn if today is unhealthy" caught 29), with 17 false alarms instead of 7.
  • Insight Agent: 22/22 test questions, including a misleading one and five that must get "I don't know".
  • 24/24 hourly runs completed in the judged 24-hour window; 111 automated tests; a fresh-clone rebuild from an empty folder passed all 8 stages.

Challenges we ran into

  • Prefect created no scheduled runs at first: SQLAlchemy 2.1 crashed its scheduler; we pinned < 2.1.
  • OpenAQ returned server errors for some sensor-months; we retry by week and log known gaps instead of inventing data.
  • A "faster" AI setting dropped the agent from 16/20 to 9/20; we reverted it and added code to tidy citation formatting (20/20).
  • Our fresh-clone test found two real bugs (an empty Open-Meteo answer crashing a stage; the manifest listing files that can never be downloaded again); both fixed before the deadline.
  • Hugging Face Gradio Spaces needed a paid plan, so we built a static dashboard with no server and no secrets.

Accomplishments that we're proud of

A system that runs by itself every hour, checks its own data, explains itself in English and Urdu, refuses to make things up, and reports its weak spots (Lahore, Karachi, deep winter) instead of hiding them.

What we learned

Honest evaluation matters more than a high number: declaring the baseline first, locking the test month and calibrating uncertainty changed how much we could trust our own results. And a forecast only helps when it is turned into a decision someone can act on.

What's next for Smog Forecast Pakistan

Calibrate low-cost sensors against Punjab EPA stations; retrain through the coming smog season; add Faisalabad, Gujranwala and Multan; SMS/WhatsApp alerts at each user's threshold; move the pipeline to the cloud; a one-district pilot for a full smog season.

Built with

python, duckdb, pandas, scikit-learn, pandera, prefect, hugging-face, plotly, papaparse, groq, gemini, render, openaq, nasa-firms, open-meteo, copernicus-cams

Team

Laksh Kumar, Syed Mustehsan Akhtar Kazmi, Noor Fatima, Amna Iqbal.

Built With

Share this project:

Updates

Submission history