Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

VidyutMitra

AI Energy Advisor for MESCOM Households on WhatsApp

WhatsApp-First | Kannada Voice | Zero App Downloads | DPDPA Compliant by Design

Hackfest'26 - NMAMIT Nitte | Team Cube | Sustainable Development Track


The Problem

Karnataka's 22.6 lakh MESCOM households lose money every month to energy tariffs, subsidies, and solar payback math they cannot read. Climate action stalls at the first mile.

MetricReality
MESCOM consumers across DK / Udupi / Chikmagalur / Shivamogga22.6 lakh (2.26 million)
Households over-provisioned on sanctioned load (10% est.)~Rs. 39 crore / yr in unnecessary fixed charges
Karnataka-wide PM Surya Ghar conversion (6,519 installs / 6.15 lakh apps)1.1%
Coastal DK + Udupi households that have even expressed interest0.2% (1 in 500)
Gruha Jyothi beneficiaries who know about the 200-unit cliffAlmost none
WhatsApp penetration in rural Karnataka95%+

The Solution

VidyutMitra is a WhatsApp-first AI concierge. A household sends a photo of their MESCOM bill. Within 10-15 seconds they receive: a full bill analysis, subsidy eligibility verdict, solar payback math, a Kannada voice summary, and a personalised infographic. No app. No typing. No English required.

Core Innovation: Three-Module Analysis on Primary-Source Rules

Every inbound bill passes through three deterministic analysis modules, each backed by a named primary source. This is the defensive moat: no judge can challenge a number without also challenging KERC, MNRE, or the Karnataka Cabinet.

ModuleRule SourceWhat It Catches
Tariff EngineKERC Tariff Order 2025 Annexure 2The Fixed Charge Trap (Rs. 1,740 / yr / household)
Subsidy NavigatorKarnataka Cabinet 18-Jan-2024 + MNRE PMSGGruha Jyothi 3-level cliff, PM Surya Ghar eligibility
Solar ROI CalculatorKERC Solar Order + CEA v21.0 + MNRE3.8 yr payback, 2.98 t CO2 / yr, Rs. 4.3 L lifetime savings

AI handles the two steps where AI is defensibly better than rules: Gemini 2.5 Flash for bill extraction (vision + mixed Kannada-English OCR), Sarvam Bulbul v3 for Kannada voice (native Indian prosody).

The Four Zeros

PrincipleHow
Zero App InstallationInbound + outbound via WhatsApp Business Sandbox only
Zero English RequiredKannada voice note + Kannada snippets in every response
Zero PII PersistenceBill images NEVER touch disk. bills schema has no bill_image column by design
Zero Fabricated NumbersEvery constant cites a primary source. Tests assert each value

Architecture

graph TB
subgraph "User Channels"
WA[WhatsApp Business Sandbox]
AD[Admin Dashboard<br/>Next.js 14 + Tailwind]
end
subgraph "Webhook Layer"
TW[Twilio Webhook<br/>POST /whatsapp]
MED[Flask /media<br/>serves TTS + PNG to Twilio CDN]
API[Flask /admin<br/>aggregate JSON API]
end
subgraph "Consent Gate DPDPA"
CG[consent_manager<br/>START / STOP / never-contacted]
end
subgraph "Extraction"
TM[twilio_media.py<br/>bytes only, no disk]
GC[gemini_client.py<br/>Gemini 2.5 Flash]
SV[schema_validator.py<br/>R1-R8 structural rules]
EP[pipeline.py<br/>single retry + fallback ladder]
end
subgraph "Analysis Rule-Based"
TE[tariff_engine.py<br/>KERC 2025 math]
SN[subsidy_navigator.py<br/>PMSG + GJ cliff + SWH]
SR[solar_roi.py<br/>size + payback + lifetime]
LI[load_inference.py<br/>seasonal dominant load]
CC[climate_context.py<br/>carbon footprint]
OR[orchestrator.py<br/>analyze_bill]
end
subgraph "Output"
RC[response_composer.py<br/>PRD §2.1 + §2.2 templates]
TTS[kannada_tts.py<br/>Sarvam Bulbul v3]
IG[infographic.py<br/>Pillow PNG card]
TD[twilio_dispatcher.py<br/>text + voice + image, 1-sec rate limit]
end
subgraph "Data Layer"
SB[(Supabase Postgres<br/>users + bills, no bill_image)]
LBC[(last_bill_cache<br/>30-min TTL in-memory)]
DF[(demo_fallbacks.json<br/>path-2 ladder)]
end
WA --> TW
AD --> API
TW --> CG
CG --> TM
TM --> GC
GC --> SV
SV --> EP
EP --> DF
EP --> OR
OR --> TE
OR --> SN
OR --> SR
OR --> LI
OR --> CC
OR --> RC
RC --> TTS
RC --> IG
RC --> TD
TD --> MED
OR --> SB
OR --> LBC
API --> SB
Loading

Deliberate Architectural Decisions

DecisionChoiceWhy Not Alternative
Bill OCRGemini 2.5 Flash (vision)Tesseract needs preprocessing; Gemini handles rotation, low light, mixed Kannada-English text natively. ~85-92% field accuracy in-house.
Analysis layerRule-based, not ML15 sample bills overfits any ML model; KERC rules are deterministic and pitch-defensible against hostile judges.
Kannada TTSSarvam Bulbul v3Google Cloud TTS WaveNet has less native Indian prosody. Free tier covers hackathon usage.
Webhook frameworkFlask 3FastAPI adds async complexity not needed at 10-req-per-demo load. Daemon thread handles the ~10-sec processing.
DatabaseSupabase (managed Postgres)Self-hosted Postgres adds ops burden. Free tier covers hackathon. CASCADE delete for STOP is FK-level, not app-level.
DashboardNext.js 14 + TailwindStreamlit is Python-easy but a React SPA over a JSON API looks like real product. Aggregate-only, no PII.
DB schemaNo bill_image columnDeliberate DPDPA feature, not oversight. write_bill raises ValueError on any forbidden image-related kwarg.
Follow-up stateIn-memory dict, 30-min TTLSupabase table for this is premature; every follow-up is a pure function call on cached analysis.
Extraction retryExactly one retry, tighter promptMore retries burn latency budget (hard cap 17s incl. retry). Two Gemini calls in 10s beats three in 25s.

Cost Analysis

For a full production run serving every MESCOM consumer once per month:

ComponentCost per billNotes
Gemini 2.5 Flash~Rs. 9Vision + structured JSON out, ~3 sec median
Sarvam Bulbul v3Free tierUp to 2000 requests / month on hackathon tier
Twilio WhatsApp~Rs. 2Text + voice + infographic = ~4 outbound messages
Supabase PostgresFree tier500 MB fits consent + bills table at demo scale
Flask on Railway~Rs. 400 / month flatWebhook + admin API, single worker sufficient
Total per bill analysed~Rs. 11vs. Rs. 1,740 / yr saved per Fixed Charge Trap flag

Services

ServiceRole
Google Gemini 2.5 FlashBill extraction: vision + structured JSON output
Sarvam Bulbul v3Kannada TTS, OGG Opus at 16 kHz for WhatsApp native voice-note UI
Twilio WhatsApp Business SandboxInbound webhook + outbound text / voice / image dispatch
Supabase (managed Postgres)Consented-user + analyzed-bill persistence, CASCADE-delete on STOP
Flask 3Webhook server, /media route for Twilio CDN fetch, /admin JSON API
Next.js 14 + TailwindAdmin dashboard, aggregate-only, bearer-token gated
PillowPillow-drawn PNG infographic per bill (no template, draw from scratch)
Pytest305+ tests, smoke suite under 1 second
python-dotenvEnv var loading for local dev
ngrokWebhook tunneling during local development and demo

Quick Start

Prerequisites

  • Python 3.11+
  • Node.js 18+ (admin dashboard only)
  • Accounts + API keys for: Google AI Studio (Gemini), Twilio (WhatsApp Sandbox), Supabase, Sarvam AI

Deploy Backend

git clone https://github.com/hackfest-dev/HF26-13 vidyutmitra
cd vidyutmitra
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Fill in .env with your API keys

Initialise Supabase Schema

python scripts/init_supabase.py
# Prints the schema + paste instructions. Copy into Supabase SQL Editor,# run it, then verify:
python scripts/init_supabase.py --verify

Deploy Dashboard

cd vidyut-dashboard
cp .env.local.example .env.local
# Set NEXT_PUBLIC_ADMIN_PASSWORD to match ADMIN_PASSWORD in ../.env
npm install
npm run dev # http://localhost:3000

Seed Demo Data

python scripts/seed_demo_data.py # 35 users, ~70 realistic bills
python scripts/clean_demo_data.py # wipes DEMO-prefixed rows after rehearsal

Local Development

# Terminal 1: Flask webhook
python app.py
# Terminal 2: expose via ngrok
ngrok http 5001
# Update PUBLIC_BASE_URL in .env to the ngrok URL, then restart Flask.# Configure Twilio WhatsApp Sandbox webhook to <ngrok-url>/whatsapp.# Join the Twilio sandbox from your phone and send START.

Demo Mode for Judges

The project runs in demo mode by default:

  • Pre-seeded data: 35 synthetic users, ~70 bills with realistic KERC math
  • Demo fallbacks: demo_fallbacks.json caches real extractions for known demo phones; if Gemini is rate-limited or down, the pipeline falls back automatically
  • Dashboard charts display real aggregate data from Supabase
  • Activity table is anonymised: no phone numbers or consumer names, ever

To explore:

  1. Open the admin dashboard (http://localhost:3000) and enter ADMIN_PASSWORD
  2. Summary panel: consented users, bills analysed, GJ cliff counts
  3. Sustainability panel: aggregate CO2 footprint, potential solar impact at scale
  4. Recent Activity: anonymised log of the last 10 analyses

Project Structure

vidyutmitra/
app.py # Flask webhook + /media + admin blueprint registration
admin_api.py # Aggregate-only JSON API for the admin dashboard
config/
tariff_constants.py # All verified KERC / CEA / GJ constants with citations
personas.py # Frozen demo persona fixtures
extraction/
gemini_client.py # Gemini 2.5 Flash integration
prompts.py # Bill extraction prompt
schema_validator.py # 8 structural validation rules (R1-R8)
pipeline.py # Extraction orchestrator with retry + fallback
twilio_media.py # Twilio CDN media fetch (no disk writes)
analysis/
tariff_engine.py # Bill recalc + Fixed Charge Trap detection
subsidy_navigator.py # PM Surya Ghar + GJ visibility + SWH rebate
solar_roi.py # System sizing + ROI + climate impact
load_inference.py # Seasonal dominant-load inference
climate_context.py # Carbon footprint + conservation tips
orchestrator.py # analyze_bill, single analysis entry point
consent/
consent_manager.py # START / STOP flow (DPDPA consent gate)
output/
response_composer.py # WhatsApp text + Kannada voice templates
twilio_dispatcher.py # Outbound messages + rate limiting
kannada_tts.py # Sarvam Bulbul v3 client
infographic.py # Pillow-drawn PNG summary card
last_bill_cache.py # In-memory follow-up state (30-min TTL)
db/
supabase_client.py # Persistence wrapper (DPDPA-guarded)
schema.sql # DDL, deliberately no bill_image column
vidyut-dashboard/ # Next.js 14 admin dashboard (aggregate-only)
tests/ # 305+ pytest tests
scripts/
init_supabase.py # One-time schema initialiser
seed_demo_data.py # Deterministic synthetic data for dashboard
clean_demo_data.py # Wipe DEMO-prefixed rows post-rehearsal
docs/
briefing_v4.md # Canonical product context
prd_v3.md # Product requirements
tech_spec_v1_1.md # Technical specification
reconciliation_research.md # Why numbers are what they are

Security & Privacy

  • DPDPA 2023 compliant by design: explicit Kannada + English consent notice, bill image NEVER persisted (bills table has no image column), one-word STOP hard-deletes with CASCADE, no soft-delete column, not a checkbox
  • Aggregate-only admin dashboard: every query is COUNT / AVG / SUM or anonymised projection. No route surfaces phone number, consumer name, or RR number
  • Bearer-token gated admin API: /admin/* requires Authorization: Bearer <ADMIN_PASSWORD>, rejected otherwise
  • TLS: Twilio and Supabase both enforce TLS 1.2+ on all transit
  • DPDPA-forbidden-field guard: write_bill in db/supabase_client.py raises ValueError if ANY kwarg matches bill_image / bill_url / image_bytes / photo / etc., or if the analysis blob contains any such key
  • No committed secrets: .env gitignored, .env.example is the template, every tracked file scanned for leaked API keys pre-commit

Primary Sources (Defensibility)

Every numeric constant in config/tariff_constants.py carries an inline citation. Defending a number is a one-line grep:

  • KERC Tariff Order 2025, Order Dated 27 March 2025, Annexure 2 - flat Rs. 5.80/unit, Rs. 145/kW/month fixed, LT-1 domestic code
  • KERC Solar Tariff Order, effective 1 July 2025 - Rs. 2.48/unit export for 2-3 kW systems under PM Surya Ghar
  • CEA CO2 Baseline Database Version 21.0, December 2025 - 0.710 kg CO2 / kWh weighted average for FY 2024-25
  • Karnataka Cabinet Order, 18 January 2024 - Gruha Jyothi entitlement formula min(historical_avg + 10, 200)
  • MNRE PM Surya Ghar Muft Bijli Yojana - Rs. 30,000/kW first 2 kW, Rs. 18,000 third kW, Rs. 78,000 cap

Impact

SDGContribution
SDG 7 - Affordable Clean EnergyRemoves first-mile friction to rooftop solar adoption across 22.6 lakh MESCOM households
SDG 13 - Climate ActionEvery bill response surfaces household carbon footprint and scale-equivalent CO2 savings
SDG 1 - No PovertyMakes Rs. 12,960 / yr Gruha Jyothi subsidy visible to each beneficiary; prevents the 200-unit cliff loss
SDG 10 - Reduced InequalitiesKannada voice note + Kannada text snippets include non-English-literate households; WhatsApp-only removes app-download barrier

Team

Team Cube - Anjuman Institute of Technology and Management (AITM), Karnataka. Built in 36 hours at Hackfest'26, NMAMIT Nitte, April 17-19, 2026.

License

MIT

About

Hackfest26 repository for T13

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages