Volunteers can't coordinate when rescue calls are scattered across Twitter, WhatsApp forwards, and Instagram DMs. ReliefStream funnels them into one prioritized dashboard.
When floods hit — Chennai 2015, Kerala 2018, Hyderabad 2020, Bengaluru 2022, every monsoon somewhere — the first hours are chaos. Rescue requests scatter across:
- Twitter threads with garbled locations
- WhatsApp forwards that lose context after 3 hops
- Instagram DMs with only a photo and a postcode
- Facebook posts with hundreds of comments burying the actual address
Local volunteers show up ready to help but spend more time finding requests than acting on them. Meanwhile the same request gets forwarded 40 times while an untouched request across town waits.
Existing government helplines exist but are structured (call, form, wait). The chaotic, informal channels are where real requests actually flow in the first hour.
ReliefStream is a single-screen dashboard that:
- Ingests raw social media text (paste-in or webhook)
- Extracts structured fields via LLM: location, urgency, request type, people affected, contact number
- Deduplicates — a request forwarded 40 times becomes one card with 40 "confirmed by" markers
- Maps all requests as pins on Leaflet with severity color-coding
- Assigns — volunteers claim requests, mark them resolved, log outcomes
- Surfaces failures — when the model can't parse a location, that request goes to a "Read this yourself" pile visible to a human operator, never silently dropped
The last one is the most important design decision: a confident wrong answer during a flood is worse than no answer. A misread pincode sends volunteers to the wrong neighborhood while a family waits on a rooftop. Every ambiguous parse is escalated to a human.
To keep scope honest:
- Not an emergency dispatch service. It doesn't call 108 for you or promise SLA.
- Not a replacement for NDRF/SDRF. It's a coordination layer for informal volunteer networks.
- Not a general-purpose disaster tool. Scoped to flood rescue coordination in the first 24-72 hrs of an event.
- Not deployable without a human operator watching the "read this yourself" pile.
┌────────────────────────────────────────────────────────────────┐
│ INGEST │
│ paste-in web form · webhook /ingest · bulk file upload │
└────────────────────────────┬───────────────────────────────────┘
▼
┌────────────────────────────────────────────────────────────────┐
│ EXTRACTOR — Ollama (qwen2.5:7b) via OpenAI-compatible API │
│ output: { location, urgency, type, people, contact, │
│ confidence, parseable } │
└──────────────┬────────────────────────┬────────────────────────┘
parseable=true parseable=false / low confidence
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────────────┐
│ DEDUP + STORE (SQLite) │ │ UNPARSEABLE PILE │
│ fingerprint hash │ │ "read this yourself" queue │
└──────────────┬───────────┘ │ operator triages manually │
▼ └──────────────────┬───────────────┘
┌──────────────────────────┐ │
│ DASHBOARD │◀────────────────────┘
│ · Map (Leaflet) │ both feed the dashboard;
│ · List (filter/sort) │ unparseable badge stays visible
│ · Claim / Resolve │ until human resolves
│ · Live via SSE │
└──────────────────────────┘
See docs/ARCHITECTURE.md for the full walkthrough.
| Decision | Why |
|---|---|
| Local Ollama over cloud LLM | Zero cost, runs on a laptop in an offline field kit, no rate limits during a surge |
| SQLite over PostgreSQL | One file, no DB server to set up during a crisis, backup by cp |
| Server-Sent Events over WebSockets | Simpler; volunteers only receive updates, don't need to push |
| Vanilla JS + Leaflet | No build step, single HTML file, works on any browser without npm |
| Explicit "unparseable" queue | The safety pattern the mentor brief flags is non-negotiable — chose to build it in from day 1, not add it later |
| Fingerprint dedup | Twitter/WhatsApp copies the same rescue request 40× — hashing keeps the queue clean |
Backend
- Python 3.11 + FastAPI (async, auto-docs)
- Ollama +
qwen2.5:7b(LLM extraction, local, ₹0) - SQLite (persistence, one file)
- OpenAI-compatible SDK (swap Ollama for Gemini/Claude with one env change)
Frontend
- Vanilla HTML + JS (no build step)
- Leaflet.js (open-source maps)
- OpenStreetMap tiles (no API key)
- Server-Sent Events for live updates
Ops
- No external dependencies at runtime beyond an Ollama server
- Single-file deploy:
git clone && cd backend && pip install -r requirements.txt && uvicorn main:app
Two commands after clone:
# 1. Backend
cd backend
pip install -r requirements.txt
cp .env.example .env # defaults to local Ollama, no key required
uvicorn main:app --reload --port 8000
# 2. Frontend (any static server, or open index.html directly)
cd ../frontend
python -m http.server 8080
# open http://localhost:8080Prerequisites: ollama pull qwen2.5:7b if not already local. Or swap .env to point at Gemini/Groq/OpenRouter.
Sample data to test with is in sample_data/ — realistic-style rescue messages you can paste into the dashboard ingest form.
| Deployment | Cost per parsed request |
|---|---|
| Local Ollama | ₹0 (electricity only) |
| Gemini 2.5 Flash free tier | ₹0 up to 1M tokens/day |
| Gemini 2.5 Flash paid | ~₹0.05 |
| Claude Haiku 4.5 | ~₹0.15 |
During a real flood surge (10,000+ messages/hour), local deployment is the only economically defensible option.
- Phase 1 (this MVP) — paste-in ingest, LLM extraction, map + list dashboard, unparseable pile, manual claim/resolve
- Phase 2 — webhook receivers for Twitter API, WhatsApp Business API, Meta Graph API
- Phase 3 — geocoding integration (Nominatim / MapmyIndia) so "opposite Kovai Kutralam" resolves to lat/lon
- Phase 4 — SMS/WhatsApp notifications back to requester when a volunteer claims their request
- Phase 5 — multi-language: Tamil, Malayalam, Kannada, Telugu, Hindi extraction (currently English + transliterated Tamil)
- Phase 6 — offline-first mode: PWA with local model, works when 4G is saturated
- Phase 7 — post-event analytics: response times, coverage gaps, volunteer utilization
Inspired by problem statement #205 at Tech for Good — Code for Communities 2026 (Dr. G. R. Damodaran College of Science, Coimbatore, Aug 8-9, 2026), attributed in the mentor brief to team "Black hole" (Daksh Chariwal, Huzefa Saroodwala, Mahipal Singh U, Tarun Kumar B). This is an independent implementation of that same problem statement — not affiliated with the original team.
The mentor brief flagged one non-negotiable safety condition:
"Build the pile of requests you could not parse. When the model cannot extract a location, or is unsure, that request must appear somewhere visible marked 'read this yourself'."
ReliefStream implements exactly that. See docs/PROBLEM.md for the full source.
MIT — see LICENSE.
Attribution appreciated when deployed. If you use this for an actual flood response, please cite in your post-event report so the safety patterns propagate.