Active — Live Machine Learning Accessibility

KrishiBot — AI Agriculture Assistant

An offline-first AI assistant for Bangladeshi farmers — detects crop diseases from photos, provides treatment recommendations, and delivers weather alerts, with full bilingual English & Bengali support.

Python FastAPI Next.js Computer Vision LLM Vercel
KrishiBot interface

Overview

What it does

Takes a photo of a crop, identifies the disease, generates treatment recommendations, and answers follow-up questions — in English or Bengali — with weather-aware advice.

Problem solved

Small-scale farmers in Bangladesh rarely have access to agronomists. A crop disease left untreated for 2–3 days can destroy an entire harvest. KrishiBot gives instant expert-level advice via any phone.

Built for

Bangladeshi small-scale farmers, agricultural extension workers, NGO field agents, and agri-tech developers building on top of open crop disease models.

KrishiBot ("Krishi" = agriculture in Bengali) is a full-stack web application with a Next.js frontend deployed on Vercel and a FastAPI backend. When a farmer uploads a leaf photo, a fine-tuned CNN classifies the disease. The result is passed to an LLM with a structured prompt that generates a treatment plan in the user's chosen language.

The bilingual capability is the core differentiator. Bengali is the native language for ~165 million people in Bangladesh, and most farmers are not comfortable reading technical English. The LLM is prompted with both the disease classification and a language preference, generating native-quality responses in both languages simultaneously.


Technical Architecture

System overview

Crop Photo
FastAPI
CNN Disease Classifier
Disease label + confidence
Text Query
Language detection
Bilingual LLM prompt
EN/BN response
User location
Weather API
Weather-aware alerts

The Next.js frontend communicates with the FastAPI backend via REST. The disease classifier and LLM inference are separated into two FastAPI services, allowing them to be scaled independently. The weather service call is parallelized with the LLM call using asyncio so both complete before the final response is assembled.


Key Features

Bilingual English & Bengali

Auto-detects language from the query and responds in kind — proper Bengali script, not transliteration.

Crop disease photo detection

CNN classifier identifies disease from a leaf photo in under 2 seconds, with confidence score.

Weather-aware advice

Treatment recommendations are adjusted for current temperature and humidity — e.g., fungicide application warnings in high humidity.

Live Vercel deployment

Production-deployed on Vercel with sub-second cold starts — accessible from any browser on any device.


Challenges & Solutions

Generating high-quality Bengali agricultural text

Challenge: Standard LLMs produce Bengali that is grammatically correct but uses formal "standard Bengali" vocabulary that rural farmers don't use. Technical terms for pesticides and fertilizers differ from what's sold locally.

Solution: Added a system prompt with a glossary of common Bangladeshi agrochemical trade names and instructed the model to use accessible vocabulary. Follow-up human review was used to build an example response library for few-shot prompting.

Crop disease dataset for Bangladeshi crops

Challenge: Public crop disease datasets (PlantVillage) are primarily US/European crops in controlled lab conditions — not Bangladeshi field conditions with different lighting and soil.

Solution: Fine-tuned a ResNet-50 model pre-trained on PlantVillage with locally collected images of rice, jute, and wheat diseases common to Bangladesh. Applied aggressive augmentation (rotation, blur, brightness) to simulate field photography conditions.

Low-bandwidth user experience

Challenge: Many rural users have 2G/3G connections. Sending full-resolution photos for inference was too slow.

Solution: Implemented client-side image compression to 224×224 (the model's input size) before upload — reducing payload from ~3MB to ~15KB with no quality loss for the CNN input.


Results & Impact

Live

Production deploy

2

Languages supported

<2s

Disease detection

15KB

Compressed upload

KrishiBot is live at krishibot-sandy-three.vercel.app and accessible from any device. It represents a practical example of how AI can solve real-world problems for underserved communities — not just as a showcase, but as a tool that could genuinely improve farming outcomes when put in the right hands.

What I'd do differently

  • Build a domain-specific disease dataset from the ground up. The fine-tuned ResNet performs adequately, but the PlantVillage base dataset is too clean and too US-centric. A proper Bangladeshi field-condition dataset — collected with farmers — would dramatically improve accuracy on actual user photos.
  • Move the LLM inference fully offline on a community server. The current deployment uses cloud LLM inference for the text responses. The vision model is local; the language model shouldn't be cloud-dependent for a tool targeting connectivity-constrained users.
  • Design for voice-first, not text-first. Many farmers are comfortable speaking but not typing. A voice input flow with Whisper STT in Bengali would serve the actual target user better than the current text chat interface.

Code Highlight

Parallel async calls to the LLM and Weather API — both requests fire simultaneously, halving response time.

import asyncio
from fastapi import FastAPI, UploadFile

PROMPTS = {
    "en": "The crop has {disease} (confidence: {conf:.0%}). Current weather: {temp}°C, {humidity}% humidity. Provide treatment in English.",
    "bn": "ফসলে {disease} রোগ শনাক্ত হয়েছে ({conf:.0%} নিশ্চিত)। আবহাওয়া: {temp}°C, {humidity}% আর্দ্রতা। বাংলায় চিকিৎসা পরামর্শ দিন।"
}

async def get_advice(disease: str, conf: float, lat: float, lon: float, lang: str) -> dict:
    # Fire both calls in parallel — no sequential waiting
    weather, llm_response = await asyncio.gather(
        fetch_weather(lat, lon),
        llm.generate(PROMPTS[lang].format(
            disease=disease, conf=conf,
            temp="?", humidity="?"  # filled after gather completes
        ))
    )
    return {"disease": disease, "advice": llm_response, "weather": weather}