Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ReliefStream

Real-time centralization of flood-rescue requests from social media chaos

Volunteers can't coordinate when rescue calls are scattered across Twitter, WhatsApp forwards, and Instagram DMs. ReliefStream funnels them into one prioritized dashboard.

Status License Stack SDG


The problem

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.

The solution

ReliefStream is a single-screen dashboard that:

  1. Ingests raw social media text (paste-in or webhook)
  2. Extracts structured fields via LLM: location, urgency, request type, people affected, contact number
  3. Deduplicates — a request forwarded 40 times becomes one card with 40 "confirmed by" markers
  4. Maps all requests as pins on Leaflet with severity color-coding
  5. Assigns — volunteers claim requests, mark them resolved, log outcomes
  6. 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.


What ReliefStream is not

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.

Architecture

┌────────────────────────────────────────────────────────────────┐
│  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.


Key design decisions

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

Tech stack

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

Quick start

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:8080

Prerequisites: 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.


Cost

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.


Roadmap

  • 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

Origin

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.


License

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.


Built as a reference implementation for Code for Communities · Tech for Good 2026

About

Real-time flood-rescue request centralization dashboard · LLM extraction + dedup + map · Code for Communities 2026

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages