AI Climate Early-Warning & Crop Advisory for Smallholder Farmers
Build with AI: Code for Communities (2nd Edition)
Team: Kanak Prabhakar (Lead) β Hazaribagh, Jharkhand
Fasal Kavach watches the weather against the crop a farmer is actually growing. When a risk crosses a threshold, it sends that farmer a specific, spoken instruction in their own language β not a generic forecast.
The core design principle: Deterministic agronomic rules decide whether there is a risk. Gemini only phrases it. The AI cannot invent a warning.
Fasal Kavach operates in one of three modes depending on your configuration:
- Cloud Mode (Gemini via Render / Cloud Run):
- Data: Real-time live weather data from Open-Meteo, evaluated against deterministic agronomic rules.
- AI Backend: Google Gemini 2.5 Flash via google-genai SDK.
- Storage: In-memory (on Render) or persistent (with Firestore).
- Local Mode (Ollama on Laptop):
- Data: Real-time live weather data, evaluated against deterministic agronomic rules.
- AI Backend: Local Ollama server (
USE_OLLAMA=true) running Gemma2 or another local LLM for offline AI execution. - Storage: In-memory or Firestore.
- Demo Mode (In-browser Mock):
- Data: Simulated static data returned by the client fallback.
- AI Backend: None (mocked local advisories).
- UI Indicator: Explicitly labeled at the top of every screen with an amber warning banner: Demo data β backend not connected.
git clone https://github.com/Kanak234/fasal-kavach.git
cd fasal-kavach
cp .env.example .env # backend
cp .env.example web/.env.local # frontend
# Paste your keys into bothFirst time? Read FIREBASE_SETUP.md first β
fifteen minutes in the Firebase console, no code. Without it the app runs
on in-memory storage and forgets everything on restart.
You can skip Firebase entirely and still run the rules engine:
USE_FIRESTORE=false DEMO_MODE=true uvicorn main:app --reload --port 8080cd api
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reload --port 8080
# β http://localhost:8080/docscd web
npm install
npm run dev
# β http://localhost:3000cd api && pytest -q # 88 testscurl http://localhost:8080/internal/status
# {"backend": "firestore", "persistent": true, "farms_stored": 12}If it reports "backend": "memory", Firestore did not connect and your
data will disappear on restart. The startup log prints the reason.
curl -X POST http://localhost:8080/internal/seedTwelve synthetic farms from data/seed/demo_farms.json. The farms are
invented; the weather they are evaluated against is fetched live from
Open-Meteo and is not.
curl -X POST http://localhost:8080/internal/ingestWatch template_fallbacks in the response. If it is high, GEMINI_API_KEY
is missing or rate limited β the app still works, which is the point of
the fallback ladder, but know which path your demo is on.
ruff check .
python3 scripts/check_locale_keys.pyA judge will ask this. The short answer:
- Farmers sign in with Google Sign-In (Firebase Auth).
- Every API call carries a signed ID token, verified server-side in
api/auth.pyagainst Google's public keys. It cannot be forged. - Every farm-scoped read checks ownership. One farmer cannot read
another's advisories β
test_api_flow.pyproves it. firestore.rulesenforces the same thing for any direct browser access to the database.- Data lives in Firestore, asia-south1 (Mumbai) β on Indian infrastructure.
- The district summary endpoint returns counts only. No farm ids, no names, nothing identifying an individual.
DEMO_MODE=true accepts unauthenticated calls as demo_user so a live
audience can tap through without waiting for Google sign-in. It is a labelled
environment flag, not a hidden bypass. Set it to false for anything with
real farmers in it.
ββββ (Backend Connected) ββββΊ FastAPI (Render / Cloud Run)
β ββββ AI: Gemini API (Cloud)
β ββββ AI: Local Ollama (Laptop)
β ββββ Database: Firestore / In-memory
Next.js PWA ββββββββββββ€
β
ββββ (Backend Offline) ββββββΊ In-browser Mock Fallback (Demo Mode)
ββββ Warning Banner Active
Rules decide. AI communicates.
| Layer | Choice |
|---|---|
| Frontend | Next.js 14, TailwindCSS, Firebase Auth |
| Backend | FastAPI (Python 3.11), Cloud Run |
| Database | Cloud Firestore |
| AI | Gemini 2.5 Flash OR Local Ollama (Gemma2, Gemma:2b, etc.) |
| Scheduling | Cloud Scheduler |
| Preprocessing | C++20 CLI tool (offline, not in request path) |
- Open the public URL (Note: If the backend is not yet deployed or is offline, the app will show a prominent amber warning banner indicating simulated demo mode).
- Log in (or use Demo Farm shortcut)
- Create a farm: crop = paddy, sowing = 15 July, area = 1.2 ha
- See a live alert generated from real forecast data
- Tap the speaker and hear it read aloud in Hindi
- Tap "Kya hua?" and see the exact rainfall/temperature numbers
- Change the crop to maize β the advisory changes accordingly (this is the key step)
Hazaribagh, Jharkhand β 4 grid cells at 0.25Β° resolution, 4 crops (paddy, maize, wheat, tomato), Hindi and English at Tier 1.
Copy .env.example to .env and fill in:
GEMINI_API_KEY=...
USE_OLLAMA=false
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=gemma2
GOOGLE_CLOUD_PROJECT=fasal-kavach
INTERNAL_TOKEN=...
NEXT_PUBLIC_API_BASE=http://localhost:8080
NEXT_PUBLIC_FIREBASE_*=... (from Firebase console)
Never commit .env or any key file.
Note: During production deployment, replace NEXT_PUBLIC_API_BASE=RENDER_URL_HERE in web/.env.production with your actual Render backend URL before running npm run build and firebase deploy.
fasal-kavach/
βββ api/ # FastAPI backend (Kanak)
β βββ main.py
β βββ routers/ # farms, advisories, ask, internal
β βββ rules/ # engine, definitions, templates, crop_calendar
β βββ ai/ # Gemini client, cache
β βββ ingest/ # Open-Meteo fetch, job runner
β βββ models/ # Pydantic canonical models
β βββ tests/ # pytest, 100% rule coverage
βββ web/ # Next.js PWA (Member 2)
β βββ src/
β βββ app/ # 6 screens
β βββ lib/ # api.ts, tts.ts, i18n.ts, firebase.ts
βββ tools/preprocess/ # C++20 offline baseline tool
βββ data/ # crop_calendar.csv, districts.json
βββ Dockerfile
βββ firestore.rules
βββ .github/workflows/ci.yml
cd api && pytest -q --tb=short
# Expected: all rules pass, calendar edge cases pass, AI validation passSee docs/BUILD_SPEC.docx Section 29 for the full runbook.
# Backend β Cloud Run
gcloud run deploy fasal-kavach-api --source api/ --region asia-south1
# Frontend β Firebase Hosting
cd web && npm run build && firebase deploy --only hostingSee data/README.md for source, licence, and transformation notes for every data file.
- Working end-to-end prototype for one district, four crops
- Seeded with real weather data from Open-Meteo (when backend is connected)
- Rules engine is fully unit-tested with boundary conditions
- Gemini output is validated β number containment check, no pesticide names
- Graceful degradation: template fallbacks when AI is unavailable, and automatic transparent transition to in-browser demo/mock fallback with a visible UI warning banner when the backend is disconnected
- Transparency: In-browser demo mode uses simulated data and does not run the backend rules engine, which is honestly declared to the user via the top warning banner.
- Not claiming: nationwide scale, field-validated agronomy, ML model training
Section numbers in this repo refer to BUILD_SPEC.docx β the single source of truth.