Marathi · Hindi · English · voice notes — grounded in real weather, powered by local open-source AI, costing ₹0 in AI fees.
Working name only.
APP_NAMEis configurable — rename the product without touching code.
- What is KrishiSathi?
- The core idea: Free AI + real weather
- Features
- How it works (architecture)
- System requirements
- External services & APIs (all free)
- Tech stack
- Install — prerequisites (Windows / macOS / Linux)
- Quick start (run locally)
- Running modes (mock ↔ real AI)
- Using the app
- Connect real WhatsApp
- Configuration reference
- Testing & development
- Production deployment
- Project structure
- Safety & limitations
- Documentation index
- Roadmap
- License
KrishiSathi is a farming assistant a farmer talks to on WhatsApp — by text or voice note, in their own language. They share their farm location once, then ask things like "आज पाऊस पडेल का?" (will it rain today?), "सोयाबीनला फवारणी करू का?" (should I spray my soybean?), or "कोणते पीक घेऊ?" (which crop should I grow?). They get a short, grounded reply in Marathi / Hindi / English.
It is designed to be trustworthy and cheap to run:
- Weather is never invented by AI — every forecast number comes from a real weather API; the AI only phrases it.
- AI is free & local — all language understanding and generation runs on your own machine/server via Ollama using open-source models. No OpenAI, no Anthropic, no per-message cost.
- Safety-first — a deterministic validator blocks unsupported pesticide doses, fake forecasts, and any number that isn't backed by real data.
There's a browser dev chat emulator so you can build and try everything without any WhatsApp/Meta account first.
| Concern | How KrishiSathi solves it | Cost |
|---|---|---|
| Language AI (understand + reply in Marathi/Hindi/English) | Local open models via Ollama (qwen3:1.7b, or bigger) |
Free |
| Embeddings (knowledge search) | bge-m3 via Ollama |
Free |
| Speech-to-text (voice notes) | faster-whisper running locally, or the browser's built-in speech engine in dev |
Free |
| Weather | Open-Meteo — no API key, no signup | Free |
| Place lookup | Built-in city gazetteer + OpenStreetMap Nominatim fallback | Free |
| Messaging | WhatsApp Cloud API test number | Free to start |
You can run the entire app end-to-end for ₹0 — the only "paid" thing later is a small VPS if you deploy it to serve real farmers, and even that is a ~₹500/month box.
- 💬 WhatsApp text, shared GPS location, and voice notes (transcribed locally)
- 🗣️ Marathi / Hindi / English + mixed detection, with an explicit
LANGUAGEoverride - 🧑🌾 Durable profile: farmer → farm(s) → crop cycle, with progressive onboarding (never a long form)
- 🌦️ Exact-coordinate weather (current / hourly / daily) with caching, stale fallback, and a confidence score
- ⚡ Deterministic weather quick-replies + full weather-aware agriculture advice (spray / irrigate / sow / harvest)
- 🌾 Season-aware crop suggestions ("which crop for Pune this season?") with a KVK caveat
- 📍 Place-name understanding — "मी पुण्यामध्ये राहतो" sets an approximate location, no GPS needed
- 📚 Knowledge base (RAG) with an admin approval workflow (candidate → verified)
- 🔎 Bounded, allowlisted research with SSRF protection
- 🖥️ Browser dev-chat emulator (mic, location, audio) + a secure admin console
- 📊 Prometheus metrics, structured logs, delete-my-data, backups
flowchart TD
WA[WhatsApp Cloud API] -->|webhook| API[FastAPI api]
DEV[/dev/chat emulator/] --> API
API -->|validate signature + idempotent insert| PG[(Postgres 16 + pgvector<br/>or SQLite in dev)]
API -->|enqueue| REDIS[(Redis / arq queue)]
REDIS --> W[worker: LangGraph]
subgraph Graph [Message pipeline - a bounded DAG]
N[normalize] --> V{audio?}
V -->|yes| VOICE[voice: faster-whisper] --> P[load profile]
V -->|no| P
P --> DET[deterministic:<br/>commands / onboarding / place / crop-suggest]
DET -->|handled| SEND
DET -->|needs AI| SUP[supervisor router]
SUP -->|weather| WX[weather fast path]
SUP -->|farming| CTX[weather+RAG+rules] --> DEC[decision]
SUP -->|help| CONV[conversation]
WX --> SEND
DEC --> REN[language renderer] --> VAL[safety validator] --> SEND
CONV --> SEND
SEND[send reply] --> PERSIST[persist run + decision]
end
W -->|Ollama: qwen3 / bge-m3| OLLAMA[(Ollama - local, free)]
W -->|weather| METEO[Open-Meteo API - free]
ADMIN[/admin console/] --> PG
In one paragraph: FastAPI validates the webhook and drops an idempotent message row + a queue job (nothing heavy in the request). A worker runs a bounded LangGraph: deterministic paths (commands, onboarding, place/crop detection, weather quick-replies) never touch the AI, so they're instant and always work; an AI supervisor routes the rest. Rules always override the model, and a deterministic validator checks every reply before it's sent. Postgres+pgvector is the store of record in production; SQLite works for local dev with zero setup.
Deeper docs: ARCHITECTURE · AGENT_GRAPH · DATA_MODEL.
| Minimum (mock-AI mode) | Recommended (real local AI) | |
|---|---|---|
| OS | Windows 10/11, macOS 12+, or Linux | same |
| CPU | Any 2-core | 4-core+ |
| RAM | 4 GB | 8 GB+ |
| Disk | ~1 GB | ~4 GB (for AI models) |
| GPU | Not required | Not required (CPU inference; Apple Silicon uses Metal automatically) |
| Python | 3.12 (managed automatically by uv) |
same |
| Internet | Only for weather | For weather + first-time model download |
You can run the whole app in "mock AI" mode with zero model downloads — great for low-disk machines. Real AI replies need ~2–5 GB for a model (see Running modes).
Target reference box: Hostinger KVM 2 (or any equivalent VPS):
| Resource | Spec |
|---|---|
| CPU | 2 vCPU (CPU-only, no GPU) |
| RAM | 8 GB |
| Disk | 100 GB NVMe |
| OS | Linux + Docker + Docker Compose |
Approx memory budget (leaves room for other apps + OS): Ollama ≤3 GB · Postgres ~640 MB · API/workers ~512 MB each · Redis ~160 MB. Default chat model qwen3:1.7b is sized for this box; qwen2.5:7b / qwen3:4b are optional upgrades if you have more RAM.
| Service | Purpose | Key needed? | Notes |
|---|---|---|---|
| Open-Meteo | Weather (current/hourly/daily) | ❌ No key, no signup | The one external call that matters most — exact farm lat/lon |
| Ollama | Local LLM + embeddings | ❌ Runs on your machine | Free, open models |
| OpenStreetMap Nominatim | Reverse/forward geocoding | ❌ (fair-use, rate-limited) | Optional — a built-in city gazetteer covers common places offline |
| WhatsApp Cloud API | Messaging transport | ✅ Free test token | Only needed to connect real WhatsApp; dev chat needs nothing |
| Brave Search | Ad-hoc research (optional) | ✅ Optional free-tier key | Off by default; app works without it |
Python 3.12 · FastAPI · Uvicorn · Pydantic v2 · SQLAlchemy 2 (async) · PostgreSQL 16 + pgvector (SQLite in dev) · Redis + arq · LangGraph · Ollama (qwen3:1.7b, bge-m3) · faster-whisper · Open-Meteo · Jinja2 + HTMX · structlog · Prometheus · uv (deps) · Ruff + mypy · pytest · Docker Compose.
You need up to four things. Only uv is strictly required (the app runs in mock-AI + SQLite mode with just that). Add the others as you turn on real features.
1. uv — Python dependency & environment manager (required)
macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | shWindows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Then open a new terminal and verify: uv --version.
uv installs Python 3.12 for you automatically — you don't need to install Python separately.
2. Ollama — local AI engine (needed for real AI replies; skip for mock mode)
macOS: brew install ollama (or download from ollama.com/download) then ollama serve / it runs as a menu-bar app.
Windows: download & run the installer from ollama.com/download.
Linux: curl -fsSL https://ollama.com/install.sh | sh
Then pull the models (see Running modes for lighter options):
ollama pull qwen3:1.7b # chat model (~1.4 GB)
ollama pull bge-m3 # embeddings (~1.2 GB)3. Redis — message queue (required to actually process messages)
macOS: brew install redis && brew services start redis
Linux (Debian/Ubuntu): sudo apt update && sudo apt install -y redis-server && sudo systemctl enable --now redis-server
Windows: Redis isn't native. Easiest options:
- WSL2 (recommended): install Ubuntu from the Microsoft Store, then run the Linux commands above inside WSL.
- Docker Desktop:
docker run -d -p 6379:6379 redis:7-alpine - Memurai (a Windows-native Redis-compatible server).
Verify: redis-cli ping → should print PONG.
4. ffmpeg — only for real voice-note transcription (optional)
macOS: brew install ffmpeg · Linux: sudo apt install -y ffmpeg · Windows: winget install Gyan.FFmpeg (or choco install ffmpeg).
Not needed for text, weather, crop advice, or the browser mic.
These are the cross-platform commands (raw uv — works on Windows/macOS/Linux). On macOS/Linux you can use the make shortcuts noted in brackets.
git clone https://github.com/KrishnaRode/krishisathi.git # or your fork/remote
cd krishisathi
uv sync --group dev# macOS / Linux:
cp .env.example .env
# Windows (PowerShell):
Copy-Item .env.example .envOpen .env in any text editor and set these three lines:
DATABASE_URL=sqlite+aiosqlite:///./krishi_local.db
LLM_PROVIDER=mock
WEATHER_PROVIDER=open_meteosqlite→ no database server to install.LLM_PROVIDER=mock→ no AI model download (canned wording, but real weather + real rules).WEATHER_PROVIDER=open_meteo→ live, free forecasts.
macOS/Linux one-liners instead of editing by hand:
sed -i '' 's|^DATABASE_URL=.*|DATABASE_URL=sqlite+aiosqlite:///./krishi_local.db|' .env # (Linux: drop the '') sed -i '' 's|^LLM_PROVIDER=.*|LLM_PROVIDER=mock|' .envOn Windows, just edit
.envin Notepad/VS Code.
uv run alembic upgrade head # [make migrate] — creates tables (reads DATABASE_URL from .env)
uv run python scripts/seed_demo.py # [make seed] — demo farm + demo knowledgeTerminal 1 — the web server:
uv run uvicorn app.main:app --host 127.0.0.1 --port 8088 --reload # [make run-api]Terminal 2 — the worker (this is the "brain"; restart it whenever code changes):
uv run arq app.workers.settings.DefaultWorkerSettings # [make run-worker]- Dev chat: http://127.0.0.1:8088/dev/chat — type, share a location, speak, or upload audio
- Admin console: http://127.0.0.1:8088/admin — login
admin/admin
Try: type pune → then कोणते पीक घेऊ? → then आज पाऊस पडेल का?.
⚠️ The worker holds the logic. After any code change, restart Terminal 2 (make run-worker), not just the API — otherwise you'll see old behaviour.
Everything is controlled by a few .env switches. Weather is always real (Open-Meteo) unless you set it to mock.
| Goal | .env settings |
Downloads | Reply quality |
|---|---|---|---|
| Fastest / lowest disk | LLM_PROVIDER=mock |
none | canned wording, real weather + rules |
| Real AI, reuse a model you already have | LLM_PROVIDER=ollamaOLLAMA_CHAT_MODEL=llama3.2:3b (or any chat model)EMBED_PROVIDER=mock |
none extra | natural AI wording, no knowledge-base search |
| Full featured | LLM_PROVIDER=ollamaOLLAMA_CHAT_MODEL=qwen3:1.7b(pull bge-m3 too) |
~2.6 GB | natural wording + knowledge search |
| Best Marathi/Hindi | OLLAMA_CHAT_MODEL=qwen2.5:7b-instruct |
~4.7 GB | strongest local Indian-language handling |
Voice: VOICE_TRANSCRIBER=mock (default) ignores audio content; set VOICE_TRANSCRIBER=faster_whisper (needs ffmpeg + uv sync --extra voice) to transcribe real speech. The browser mic in dev chat transcribes via Chrome with zero install.
After changing .env, restart both the API and the worker.
In the dev chat (and later on real WhatsApp):
- Weather:
आज पाऊस पडेल का?·या आठवड्यात हवामान कसे असेल?·will it rain today? - Set location by name:
pune·मी पुण्यामध्ये राहतो·नाशिक(or share exact GPS for precision) - Crop suggestions:
कोणते पीक घेऊ?·पुण्यासाठी कोणते पीक?·which crop should I grow? - Advice for your crop: first tell it your crop (
सोयाबीन), thenफवारणी करू का?·पाणी द्यावे का? - Voice: click 🎤 Start speaking, talk, then Send; or upload an audio file
- Commands:
HELP·WEATHER·MY FARM·ADD FARM·SWITCH FARM·LANGUAGE MARATHI/HINDI/ENGLISH·DELETE MY DATA - 🗑 Clear chat button resets the conversation; the dev chat also starts fresh on each restart (
DEV_CHAT_RESET_ON_START).
You can connect a free WhatsApp test number and message the bot from your own phone, even while the app runs on your laptop (via a tunnel).
- Run a tunnel so Meta can reach your machine:
cloudflared tunnel --url http://127.0.0.1:8088(install:brew install cloudflared/winget install Cloudflare.cloudflared/ apt). - Create a Meta app → add WhatsApp → copy 4 values + invent a verify token.
- Put them in
.env, setWHATSAPP_SEND_ENABLED=true, restart. - Point the Meta webhook at
https://<your-tunnel>/webhooks/whatsapp.
Full click-by-click beginner guide: docs/BEGINNER_LOCAL_WHATSAPP.md · reference: docs/WHATSAPP_SETUP.md.
All settings are environment variables — see .env.example (dev) and .env.production.example (server). The most important:
| Variable | What it does |
|---|---|
LLM_PROVIDER |
ollama (real AI) or mock (no download) |
OLLAMA_CHAT_MODEL |
which chat model, e.g. qwen3:1.7b, llama3.2:3b, qwen2.5:7b-instruct |
EMBED_PROVIDER |
auto (follow LLM) or mock (run real chat without downloading bge-m3) |
WEATHER_PROVIDER |
open_meteo (real, free) or mock |
GEOCODING_PROVIDER |
nominatim or mock (a built-in gazetteer covers common cities regardless) |
VOICE_TRANSCRIBER |
mock or faster_whisper |
DATABASE_URL |
sqlite+aiosqlite:///./krishi_local.db (dev) or a Postgres URL |
DEV_CHAT_RESET_ON_START |
true = fresh empty dev chat on every restart |
WHATSAPP_*, META_APP_SECRET |
real WhatsApp credentials (see setup docs) |
Production startup fails fast if a required secret is missing or left at a placeholder.
uv run pytest -q -m "not integration" # [make test] — 128 unit/contract/golden tests, no external creds
uv run ruff check app tests scripts # [make lint]
uv run mypy app # [make typecheck]
TEST_DATABASE_URL=postgresql+asyncpg://... uv run pytest -m integration # [make test-integration]CI never needs Meta, Ollama, weather, or search credentials — everything runs on SQLite + mocks.
Build images on the server (CPU-arch match), expose via your existing reverse proxy or a Cloudflare Tunnel — the API only binds 127.0.0.1:8088 and never touches ports 80/443.
cp .env.production.example .env.production # fill secrets, then chmod 600
docker compose -f deploy/docker-compose.prod.yml --env-file .env.production up -d --build
bash scripts/pull_models.sh
docker compose -f deploy/docker-compose.prod.yml exec api alembic upgrade headFull Mac→VPS walkthrough (with the memory budget and "don't touch existing containers" notes): docs/HOSTINGER_DEPLOYMENT.md · operations: docs/OPERATIONS.md.
app/
api/ FastAPI routers (webhook, dev_chat, admin, health)
agents/ LangGraph state + nodes (thin; delegate to services)
services/ domain logic: weather, geocoding, agriculture, rag, research, voice, language, conversations
llm/ Ollama client, structured schemas, prompts, mock, fallback
db/ models, repositories, migrations, session
whatsapp/ Cloud API client, parser, sender, media, fixtures
security/ encryption, signatures, PII redaction, admin auth
workers/ arq settings, jobs, cron
rules/ weather-operation rules, crop calendar, safety policy, glossary (YAML)
seed/ trusted sources + demo advisories
deploy/ Dockerfiles, compose (dev/prod), nginx & Cloudflare examples
docs/ architecture, data model, safety, deployment, WhatsApp setup, …
tests/ unit / contract / golden / integration
- No pesticide dosage or chemical-mix advice unless present in a cited verified source.
- No crop-disease diagnosis from text alone; high-risk topics escalate to the local agriculture officer / KVK.
- Crop suggestions are general season/region guidance, not soil-specific (that's a KVK/soil-test job).
- Forecasts express uncertainty & horizon — coordinates select a model grid, not a field sensor.
- One question at a time — a single message bundling several asks is handled by primary intent; a stronger model (
qwen2.5:7b) parses compound questions better. - Phone numbers & message bodies are encrypted at rest; logs are redacted. Details in docs/SAFETY.md.
| Doc | Contents |
|---|---|
| ARCHITECTURE | Processes, request lifecycle, layering |
| AGENT_GRAPH | The LangGraph nodes & routing |
| DATA_MODEL | All tables, portability, encryption |
| SAFETY | Prohibited outputs, validator, confidence bands |
| RAG_AND_RESEARCH | Retrieval + research + SSRF guards |
| WEATHER_ACCURACY | What coordinates do and don't mean |
| BEGINNER_LOCAL_WHATSAPP | Zero-knowledge WhatsApp connect |
| WHATSAPP_SETUP | Meta app / tokens / webhook reference |
| HOSTINGER_DEPLOYMENT | Mac→VPS production deploy |
| OPERATIONS | Health, metrics, backups, retention |
| CLAUDE.md | Architectural non-negotiables |
- Crop recommendation with soil/market signals (currently season+region only)
- Multi-part compound-question handling
- IMD official-advisory ingestion adapter
- Feedback-driven weather confidence calibration
- More languages & a wider place gazetteer
MIT © 2026 Krishna Rode. Free to use, modify, and build on — for FPOs, KVKs, students, and anyone serving farmers.
Built as Sunday Build #8. Free AI 🌱 real weather 🌦️ for farmers.