Spaces:
Sleeping
title: AgroSense
emoji: π±
colorFrom: green
colorTo: yellow
sdk: docker
app_port: 7860
pinned: false
short_description: Offline-first AI farming advisor for India
π± AgroSense β RAG-Based Agriculture Farming Advisor
A working implementation of the AgroSense concept from the project report: a Retrieval-Augmented Generation (RAG) advisor that answers farmer questions with grounded, cited guidance drawn from an agriculture knowledge base.
This is the Phase 1 MVP (text interface, offline) β built as a full stack:
Knowledge Base (JSON) -> Embeddings -> Vector Store -> Retrieve + Re-rank -> Grounded Generation (cited)
|
Modern Web App (SPA) / Streamlit UI / CLI <---- FastAPI <---- RAGEngine
π₯οΈ Modern web app
A responsive single-page dashboard (no build step β modern HTML/CSS/vanilla JS in web/) is served by FastAPI itself. Start the API and open it:
uvicorn api.main:app --reload # then open:
# http://127.0.0.1:8000/ui/ (the web app)
# http://127.0.0.1:8000/docs (API docs)
It covers every feature via the API: the date/calendar/IST header, news + commodities tickers, the advisor chat with a speaking avatar ("AgroBot" β an animated SVG mascot that reads answers aloud via the browser's Web Speech API, keyless and multilingual, with an Auto-speak toggle), a Location intel dashboard (weather Β· satellite Β· NDVI Β· environment Β· sky Β· hazards Β· advisories), market prices, and the Plant clinic β AI image diagnosis + telemedicine that escalates to a live verified plant doctor (expert routing, video room, chat) in one tab.
There is also a polished marketing landing page (the campaign destination) at
/landing (web/landing/index.html) β hero, features,
how-it-works, audience segments, CTAs into the app, and the downloadable campaign kit.
A headless render test lives at web/smoke.mjs (node web/smoke.mjs,
needs npm i jsdom). The Streamlit UI (streamlit run ui/app.py) and CLI remain as
alternatives.
π Documentation & marketing kit (Word + PDF, downloadable)
A full set of documents is provided in both Word and PDF, with download links in the web app header. They live in docs/:
| Document | What it covers |
|---|---|
| User Manual | End-user guide to every feature/tab |
| Technical Guide | Architecture, modules, API, config, extending, deployment, security |
| Standard Operating Procedure (SOP) | Operational runbook: start/stop, monitoring, KB + doctor admin, incident response, backup/recovery |
| Go-to-Market & Monetization Plan (India) | Freemium tiers, pricing, monetization streams, 3-year financial projection, unit economics, GTM strategy |
| Instagram Campaign | Reels/storyboards, voiceover + audio direction, captions, hashtags |
| Facebook Campaign | Page, Groups, Meta Ads + Lead Ads, ad copy |
| LinkedIn (B2B) Campaign | FPOs, agri-input partners, investors, enterprise/API |
| 30-Day Content Calendar | Post-launch monthly plan with recurring series |
Served at GET /downloads/{user-manual|technical-guide|sop|gtm-plan|instagram-campaign|
facebook-campaign|linkedin-campaign|content-calendar}.{pdf|docx}. All share a
renderer (scripts/docgen.py) so the two formats never drift.
Regenerate everything with one command:
pip install python-docx fpdf2
python scripts/build_docs.py
βοΈ Admin β configure the knowledge base
The web app has an Admin tab to add / edit / delete knowledge-base entries. Saving
persists to data/knowledge_base.json and rebuilds the
live vector index, so new guidance is retrievable immediately. Admin endpoints are
token-gated (X-Admin-Token header):
GET /admin/kb Β· POST /admin/kb Β· PUT /admin/kb/{id} Β· DELETE /admin/kb/{id}
Set the token with AGROSENSE_ADMIN_TOKEN (defaults to admin for the local POC β
change it for any shared deployment). Logic lives in
agrosense/kb_admin.py; validation requires at least crop
and source.
Live local weather (optional, no API key)
Provide a location and AgroSense attaches a real-time forecast + farming advisory from Open-Meteo (free, no API key), implementing the report's Data Layer "dynamic (weather) data" source:
python cli.py --location Belagavi "I grow cotton on black soil β fertilizer and pest steps?"
The advisory is computed strictly from the forecast numbers (e.g. "rain likely on 2026-05-30 β postpone foliar sprays and nitrogen top-dressing to avoid wash-off"), so it stays as trustworthy as the KB-grounded advice. If there's no internet (or the place can't be resolved), weather is silently skipped and the KB answer is unaffected.
Satellite monitoring (optional, no API key)
Provide a location and AgroSense pulls real satellite monitoring from two free, keyless NASA sources:
- NASA GIBS β MODIS true-color and NDVI (vegetation greenness) imagery for your area's bounding box, plus a one-click NASA Worldview link.
- NASA POWER β satellite-derived agroclimate (solar radiation, temperature, rainfall) for the point, with number-grounded notes (e.g. "ample solar radiation β good for growth", "very little rainfall β check soil moisture").
python cli.py --location Belagavi --satellite "How is my paddy field doing?"
In the UI, set a location and tick π°οΈ Show satellite monitoring to see the imagery and agroclimate panel.
Field-level numeric NDVI (optional, Google Earth Engine)
For a true per-field Sentinel-2 (~10 m) NDVI time series β latest value, mean,
trend, and a health status (healthy/dense Β· moderate Β· sparse/stressed) β
AgroSense integrates Google Earth Engine. It is fully optional and credential-
gated: with no credentials the app silently uses MODIS NDVI imagery + POWER
agroclimate instead (see agrosense/ndvi.py).
Enable it:
pip install earthengine-api
# Option A β user / default credentials (after a one-time browser auth):
earthengine authenticate
$env:AGROSENSE_EE_PROJECT = "your-gcp-project-id"
# Option B β service account (for servers / CI, no browser):
$env:AGROSENSE_EE_SERVICE_ACCOUNT = "agro@your-project.iam.gserviceaccount.com"
$env:AGROSENSE_EE_KEY_FILE = "C:\path\to\service-account-key.json"
$env:AGROSENSE_EE_PROJECT = "your-gcp-project-id"
Then any satellite request (UI checkbox, --satellite, or GET /satellite) adds a
numeric_ndvi block with the time series, trend, and number-grounded notes (e.g.
"NDVI is trending down β investigate for stress, senescence, or recent harvest").
Tunables: AGROSENSE_NDVI_DAYS (60), AGROSENSE_NDVI_BUFFER_M (100 m field radius),
AGROSENSE_NDVI_MAX_CLOUD (40%). The architecture is provider-agnostic β swap in
Sentinel Hub by adding a sibling provider in agrosense/ndvi.py.
Cloud handling is two-layer: scenes are filtered by CLOUDY_PIXEL_PERCENTAGE, and
clouds/shadows/cirrus/snow are masked per pixel via the Sentinel-2 SCL band
(build_scl_mask), so cloud over the field can't skew the field-mean NDVI.
Location environment profile
Display a full environment readout for a place or lat/lon β keyless (Open-Meteo):
| Field | Source | Notes |
|---|---|---|
| Longitude, Latitude | geocoding | |
| Altitude (sea level) | geocoding / elevation API | metres |
| Local population | geocoding | of the resolved place |
| Humidity | forecast current |
% |
| Sunlight | forecast | sunshine hours/day, UV-index max, live solar W/mΒ² |
| Wind speed & direction | forecast current |
km/h + 16-point compass |
| Air quality | Air Quality API | US/EU AQI, PM2.5, PM10, ozone + category |
| Pollen | Air Quality API | Europe-only (CAMS) β shows "not available for this region" elsewhere |
| Ground water level | CGWB / data.gov.in (keyed) | real nearest-well water-table depth when AGROSENSE_GROUNDWATER_RESOURCE + AGROSENSE_DATAGOV_API_KEY are set (agrosense/groundwater.py); otherwise a labelled soil-moisture proxy (3β9 cm) |
python cli.py --location Belagavi --environment "..."
Endpoint: GET /environment?location=β¦ or ?latitude=β¦&longitude=β¦. UI: tick
π Show location environment. See agrosense/environment.py.
Real ground-water level (optional): set a CGWB "depth to water level" resource id and a data.gov.in key to replace the proxy with an actual nearest-observation-well water-table depth:
$env:AGROSENSE_DATAGOV_API_KEY = "your-data.gov.in-key"
$env:AGROSENSE_GROUNDWATER_RESOURCE = "<cgwb-resource-id>"
$env:AGROSENSE_GROUNDWATER_STATE = "Karnataka" # optional server-side filter
The nearest-well geometry (haversine + parsing) is unit-tested; the live fetch is mock-tested. Caveat: CGWB data is station-based and ~quarterly (not real-time), and resource field names vary β confirm your resource's schema (see agrosense/groundwater.py).
Natural-hazard events & active fires (NASA EONET + FIRMS)
Shows natural-hazard events and active fires near the location:
- NASA EONET β keyless open natural events (wildfires, severe storms, floods, drought, dust/hazeβ¦) filtered to a radius of the farm and sorted by distance.
- NASA FIRMS β active fire / thermal anomalies (VIIRS/MODIS); needs a free
map-key (
AGROSENSE_FIRMS_MAP_KEY) β shows "set key to enable" otherwise.
UI: tick β οΈ Show hazards & fires. GET /hazards?location=β¦ (or lat/lon).
See agrosense/hazards.py.
Plant-disease, plant-ID & pest vision
Upload a leaf/plant/insect photo (UI: πΏ Plant image diagnosis, or
POST /vision/classify?task=all) to get three classifications β disease/health,
plant ID, and pest ID:
- With trained models configured (
AGROSENSE_VISION_DISEASE_MODEL/_PLANT_MODEL/_PEST_MODEL) and TensorFlow installed, real CNN inference runs. - Without them, an honest Pillow colour heuristic gives a leaf-health indication (clearly labelled "not a diagnosis"); plant-ID and pest-ID report that a trained model is required. See agrosense/vision.py.
Train the models (needs TensorFlow + datasets β run outside this sandbox) with scripts/train_plant_models.py:
- disease β PlantVillage (~54k images, 38 classes)
- plant β any per-class leaf/plant folder dataset (Flavia, Oxford-102β¦)
- pest β IP102 (~75k images, 102 crop-pest classes) or the Kaggle "Agricultural Pests Image Dataset" (12 classes)
Point the env vars at the resulting .keras + labels files to activate real inference.
Note: this Python 3.14 POC has Pillow + numpy but not TensorFlow/ONNX, so only the heuristic path runs here; the model backend activates wherever TF is available.
Plant telemedicine (diagnosis β prescription)
A clinician-style consult that fuses the image diagnosis (disease/pest vision) + symptom intake + the KB's treatment fields + weather-aware timing into a structured diagnosis β health assessment β prescription β follow-up:
- Intake: crop, free-text symptoms, optional leaf photo, location.
- Assessment: diagnosis (from image and/or symptom keywords), health status, severity.
- Diagnosis-driven prescription: a recognized disease/pest class β from the
vision model's predicted label (e.g. PlantVillage
Tomato___Late_blight) or from symptom text that names the condition β is mapped to a targeted IPM prescription via agrosense/ipm.py + data/ipm_prescriptions.json (e.g. "Late blight β spray Mancozeb 0.25%β¦"). This specific treatment is listed first, then the crop's KB-grounded steps follow. - Prescription: treatment + nutrition + cultural/IPM steps composed only from the IPM lookup and retrieved KB fields (dosages verbatim, every line cited) β never invented.
- Weather-aware timing (e.g. "rain likely β postpone foliar sprays") + a clear safety disclaimer (decision support, not a substitute for an expert).
UI: sidebar π©Ί Plant telemedicine (crop + symptoms + the uploaded photo) β
consultation card. POST /telemedicine (multipart: crop/symptoms/location + optional
image). See agrosense/telemedicine.py.
Farmers' digital clubs
Location-wise and commodity-wise farmer communities (π₯ Clubs tab). Browse/filter
clubs by location or commodity, create a club, join, post to a discussion feed
and share information/links, and start a live video meeting (Jitsi room per club,
keyless). Each club has members, a feed, and its own meeting room. Seeded with starter
clubs (Karnataka/Maharashtra; Tomato/Cotton/Coffee/Paddy). API: GET/POST /clubs,
GET /clubs/{id}, POST /clubs/{id}/join, POST /clubs/{id}/post. See
agrosense/clubs.py (persisted to data/clubs.json).
Live agri-doctor consultation
Escalate from the AI consult to a human expert: a consultation request is routed to a matching available expert (pest β entomologist, disease β pathologist, etc., honoring language), attaches the AI telemedicine consult as context, and opens a live video room (Jitsi, keyless) plus an in-app chat thread.
UI: sidebar π¨ββοΈ Live agri-doctor (name + channel + language) β session card with
the assigned expert, a Join live video room button, and chat. API: GET /experts,
POST /consult/request, GET /consult/{id}, POST /consult/{id}/message. See
agrosense/consultation.py + data/agri_experts.json.
Onboarding & verification: anyone can apply to become a plant doctor
(POST /doctors/apply, status pending); an admin verifies them
(POST /admin/doctors/{id}/verify, token-gated) β and only verified doctors enter
the consultation directory (GET /experts) and can be routed live consults.
Applications require name, specialization, region, contact, languages, credentials,
and a format-checked ICAR / registration number; routing tags are derived from the
specialization.
Profiles & ratings: each verified doctor has a public profile page
(GET /doctors/{id}) showing specialization, region, languages, registration number,
and an aggregate star rating with recent reviews; farmers rate a doctor
(POST /doctors/{id}/rate, 1-5 stars + comment). Ratings show in the directory and on
the profile. The web app has an Apply as a plant doctor form + View profile with a
rating widget (in the Plant clinic tab's live-doctor section) and a Plant doctor
verification panel (Admin tab).
Backed by agrosense/doctors.py (data/plant_doctors.json,
seeded from data/agri_experts.json).
Expert notifications: when a consult is routed, the assigned expert is notified β
always recorded in an in-app audit log (GET /notifications), and, when
configured, delivered via webhook (AGROSENSE_NOTIFY_WEBHOOK β Slack/Discord/
Zapier/custom, keyless) and/or email (AGROSENSE_NOTIFY_EMAIL_TO + SMTP env). See
agrosense/notifications.py.
Honest scope: the experts are demo/seed entries β there are no real practitioners on the other end in the POC. Connecting real experts means populating the directory with availability + contact, and they'll be alerted via the notification channels above; the video room, chat, and notifications are functional. The default Jitsi room (meet.jit.si) may ask the first joiner to sign in as moderator β set
AGROSENSE_VIDEO_BASEto a self-hosted Jitsi for production.
Traditional Advisor (traditional knowledge + Panchang)
A πͺ Traditional advisor for daily farm activities that combines Indian traditional/desi practices with Panchang (astrological) guidance. For an activity (sowing, transplanting, harvesting, pest control, β¦) it gives:
- an astrological suitability verdict from today's Panchang β favourable nakshatras for sowing, waxing vs waning moon (Shukla/Krishna paksha), Vishti (Bhadra) karana and Amavasya/Rikta-tithi cautions β with the reasons, and
- relevant traditional practices (Beejamrit, Jeevamrit, lunar/nakshatra sowing, neem & panchagavya pest control, mixed croppingβ¦), matched to the area/region.
GET /traditional?activity=β¦&location=β¦ (keyless). See
agrosense/traditional.py +
data/traditional_knowledge.json.
Finance β bank assistance + government schemes & subsidies
A single π¦ Finance tab combines two things a farmer needs money-wise:
Bank assistance & agri-loans. A curated catalog of agri-credit products β KCC and
crop/production loans, term/investment loans, farm-mechanization, allied
(dairy/AH/fisheries), agri gold loans, warehouse-receipt finance, FPO & SHG credit, the
Agriculture Infrastructure Fund, solar-pump (PM-KUSUM) and horticulture loans. Each lists
provider, interest, loan amount, tenure, benefits, eligibility, step-by-step application
process, documents, portal and helpline. Browse/filter by category or search, then
lodge a loan enquiry (name + contact + requested amount) β applications are recorded
and visible to an admin in the βοΈ Admin tab (GET /admin/finance/applications,
token-gated). API: GET /finance?category=&provider=&search=, GET /finance/{id},
POST /finance/{id}/apply. See agrosense/finance.py +
data/finance.json (enquiries persist to the gitignored runtime
data/finance_applications.json).
Government schemes & subsidies. Central and state agricultural schemes with the full
publication for each β summary, benefits, eligibility, step-by-step application
process, documents required, official portal, helpline β plus an
announcements/updates feed. Browse and filter by level (Central / State),
state (the sidebar Location surfaces schemes that apply to you β central schemes
always show), category, or free-text search; open any scheme for its full detail,
and see a latest-announcements feed aggregated across all schemes (newest first).
Seeded with 13 schemes β 10 central (PM-KISAN, PMFBY, KCC, PMKSY, Soil Health Card, SMAM,
PKVY, eNAM, AIF, PM-KMY) and 3 state (Krishi Bhagya/Karnataka, Rythu Bandhu/Telangana,
Magel Tyala Shettale/Maharashtra). Admins can append updates to a scheme
(POST /admin/subsidies/{id}/update, token-gated). API:
GET /subsidies?level=&state=&category=&search=, GET /subsidies/{id},
GET /subsidies/updates. See agrosense/subsidies.py +
data/subsidies.json.
Honest scope: both are curated knowledge bases (no reliable keyless live scheme/loan-rate feed exists). Interest rates, scheme amounts and rules are set by RBI/NABARD/banks and governments and change over time; "apply" lodges an enquiry in AgroSense, not a bank/portal submission. Each view carries a disclaimer to verify and apply through the bank or official portal.
Land record search & documents
A πΊοΈ Land records tab to find your State's official land-record system and take the exact steps to view/download your record. Land is a State subject, so the tab is a searchable directory (15 states + an all-India fallback) giving, per state: the local record name (RTC/Pahani, 7/12 Saatbara, Khatauni, Jamabandi, Patta/Chitta, β¦), the official portal and cadastral-map (Bhu-Naksha) portal, what to search by (district, taluk/tehsil, village, survey/khasra/khata number), step-by-step search & download instructions, what the record contains, and the helpline. The sidebar Location is geocoded to its state (or pick a state explicitly). You can also download a printable guide (Word/PDF) for that state, generated on the fly.
API: GET /land-records?location=&state=, GET /land-records/guide.{pdf|docx}?location=&state=.
See agrosense/land_records.py +
data/land_records.json (PDF/Word via the shared
scripts/docgen.py renderer).
Honest scope: AgroSense does not fetch or store your actual land record β those live on each State's portal, usually behind a login/OTP/fee. This feature helps you find and download yours from the official source; always rely on the State portal's copy.
This is cultural, belief-based knowledge offered as complementary to β not a replacement for β scientific agronomy, soil tests and local conditions. The nakshatra/yoga rely on an approximate ayanamsa (see the Panchang note above).
Decision-fusion advisories
Fuse the live signals β weather forecast + satellite agroclimate (NASA POWER) + field NDVI β into prioritized, cross-signal, actionable advisories that no single source can give (e.g. "NDVI trending down while rain is forecast β inspect drainage and scout disease"). Works by place name or latitude/longitude:
python cli.py --location Belagavi --advisories "advice for my cotton field?"
Advisories are tagged by urgency (high/medium/low) and category (irrigation, spray, disease, protection, monitoring), each with the rationale (which signals drove it). The rule set lives in agrosense/fusion.py as a pure function over the fetched signals, so it is fully unit-tested.
Crop- and stage-aware: pass a crop and growth stage
(seedling/vegetative/flowering/maturity) and the thresholds + urgencies adapt per
agrosense/crop_profiles.py β e.g. tomato flags heat at
32Β°C while cotton tolerates 40Β°C, flowering/seedling stages escalate stress
advisories, and rain near maturity raises a harvest-quality warning.
python cli.py --location Belagavi --advisories --stage flowering "advice for my tomato?"
Endpoint: GET /advisories?location=β¦&crop=Tomato&stage=flowering (or latitude/longitude).
Planetary positions
Show the Sun, Moon (with phase) and classical planets (MercuryβSaturn) for the location at the current time β altitude/azimuth, RA/Dec, and what's above the horizon β useful for sky context and traditional/Panchang-style scheduling.
python cli.py --location Belagavi --planets "..."
Computed locally with a pure-Python ephemeris (Schlyter's algorithm) β keyless,
offline, no dependencies (agrosense/planetary.py),
validated in tests against known astronomy (solar declination β +23.4Β° at the June
solstice). Endpoint: GET /planetary?location=β¦ or ?latitude=β¦&longitude=β¦.
Multilingual answers (Phase 2)
Ask in β or get answers in β the report's Phase 2 languages (Hindi, Kannada, Telugu, Tamil, Marathi, Bengali, Malayalam, Gujarati, Punjabi). The query is translated to English for retrieval and the grounded answer is translated back:
python cli.py --lang hi "What fertilizer should I use for maize?"
Backends (auto-selected, optional): argostranslate (fully offline) β deep- translator (online, no key) β identity (English passthrough). If no backend is installed, the answer simply stays English and the UI/CLI says so. See agrosense/translation.py.
Real-time market prices (closes the report's last pain point)
Attach live mandi (Agmarknet) prices for the crop in a question β min/max/modal βΉ/quintal across markets, with a "compare mandis" note when prices spread widely:
python cli.py --prices "what's the price of tomato in Karnataka?"
Requires a free data.gov.in api-key (set AGROSENSE_DATAGOV_API_KEY); without
it, prices degrade gracefully to "unavailable". See
agrosense/prices.py.
π€ Farmer trading platform (in the Market tab)
A peer-to-peer produce marketplace inside the Market tab: farmers post sell offers and buyers post buy requirements (commodity, quantity/unit, price, grade, location/state, description). Anyone can browse/filter by type (sell|buy), commodity or state, open a listing, express interest (an inquiry with contact + offer + quantity), negotiate live in a per-listing video room (Jitsi, keyless), and the poster can mark it sold/closed (closed listings drop out of the default browse). Live mandi prices and the commodity ticker sit alongside in the same tab as a pricing reference. Seeded with demo listings on first run.
API: GET/POST /market/listings, GET /market/listings/{id},
POST /market/listings/{id}/inquire, POST /market/listings/{id}/close. See
agrosense/trading.py (persisted to data/market_listings.json,
gitignored runtime state).
Honest scope: a POC marketplace β listings and seed buyers/sellers are demo/user-generated; there is no payment, escrow, KYC or logistics. Verify the other party and agree terms independently before transacting (the UI carries this disclaimer).
π» Internet radio
A Radio tab lists online radio stations for India (Vivid Bharti, Radio Mirchi,
Red FM, AIR, regional/agriculture stationsβ¦) and plays them in an in-app audio player.
Keyless via the Radio Browser community API. GET /radio?country=IN&search=β¦. See
agrosense/radio.py.
This is internet radio, not over-the-air FM tuning (a browser has no RF hardware). Many FM/AIR stations stream online so the local station is often present, but coverage of small stations varies and some streams may be temporarily offline (filtered with
hidebroken=true+ popularity ordering). On an HTTPS deployment, plainhttp://streams are blocked as mixed content β prefer https streams or proxy.
Date/time header + Reuters news ticker
The UI shows a top bar with the date in the Gregorian (English) calendar, the Indian National (Saka) calendar with a mini-Panchang β lunar day (tithi), nakshatra shown inline (e.g. "Shukla Purnima Β· Anuradha") and the full five limbs (vaara, tithi, nakshatra, yoga, karana) in a hover tooltip, computed from the ephemeris β and the current IST time, plus the Google News headline ticker.
- Calendar/IST logic: agrosense/calendars.py (pure,
unit-tested β the GregorianβSaka conversion is exact). Endpoint
GET /datetime. - Headlines: agrosense/news.py β Google News RSS, keyless,
graceful empty list on failure. The UI has region (India/US/UK/Australia/
Canada/Singapore) and topic (Top stories/Agriculture/Business/Technology/
Science/Health/Sports/World) selectors above the ticker.
GET /news?region=US&query=technology&limit=15βregionselects the locale,query=None gives general top stories, or pass a topic/keyword (or asite:reuters.comfilter for the Reuters feed).
Directly below the news scroll, a slow-scrolling commodity ticker shows
Gold, Silver, Crude Oil, Coffee (Yahoo Finance futures, keyless, with day
change %) and Arecanut, Coconut (Agmarknet via data.gov.in β show "n/a" until a
key is set). See agrosense/commodities.py; GET /commodities.
Below that, a local weather strip shows current conditions for the sidebar location (temperature, humidity, today's range, rain chance, top advisory) β driven by the same Open-Meteo forecast as the rest of the app.
The displayed time reflects the page render (updates on refresh/interaction).
Evaluation harness (RAGAS-style, offline)
Measure the report's accuracy targets against a gold questionβexpected-source set:
$env:AGROSENSE_EMBEDDING_BACKEND="hashing"; python scripts/evaluate.py
Reports context relevance, citation MRR, faithfulness, hallucination rate, answer relevance, out-of-domain accuracy, and latency p50/p95 β each checked against the report's targets (β₯95% relevance/faithfulness, <5% hallucination, β€3 s). Exits non-zero if any target is missed (CI-friendly). Metrics are pure functions (agrosense/evaluation.py); the gold set is data/eval_set.json.
On the offline hashing-embedder POC the current set passes all targets (context relevance 100%, faithfulness 100%, hallucination 0%, p95 < 1 ms). Faithfulness is high by construction for the extractive generator; the harness's value is catching regressions and re-measuring once a real embedder/LLM is plugged in.
Runs fully offline, no API keys, no internet
Every heavy dependency is optional. Out of the box the app uses:
- a deterministic hashing embedder (no model download), and
- a numpy cosine-similarity vector store (no FAISS), and
- an extractive grounded generator that composes answers only from retrieved KB fields and attaches citations β so it cannot hallucinate agronomic facts.
If you install the optional accelerators, the same code automatically upgrades:
pip install sentence-transformersβ better semantic embeddingspip install faiss-cpuβ faster vector search
Quick start
# 1. (optional) create a venv, then install core deps
pip install -r requirements.txt
# 2a. Try it on the command line (no server needed)
python cli.py "My soil is sandy, rainfall 900 mm, I plan to grow maize. What fertilizer and pest steps?"
# 2b. Or run the interactive REPL
python cli.py
# 3. Run the API
uvicorn api.main:app --reload # http://127.0.0.1:8000/docs
# 4. Run the chat UI (in another terminal)
streamlit run ui/app.py # http://localhost:8501
The Streamlit UI calls the FastAPI backend if it's running, and otherwise falls back to running the engine in-process β so the UI works on its own too.
Run the tests
python tests/test_rag.py # or: python -m pytest
How it maps to the report
| Report concept | Where it lives |
|---|---|
| Data Layer / Knowledge Base (structured JSON entries) | data/knowledge_base.json, agrosense/knowledge_base.py |
| Knowledge Layer (vectorized documents) | agrosense/embeddings.py, agrosense/vector_store.py |
| Cognitive Layer β RAG pipeline (retrieval + re-ranking + generation) | agrosense/retriever.py, agrosense/generator.py, agrosense/rag.py |
| Cognitive Layer β decision fusion (multi-signal advisories) | agrosense/fusion.py, agrosense/crop_profiles.py |
| Cognitive Layer β traditional advisor (Panchang + desi practices) | agrosense/traditional.py |
| Data Layer β government schemes & subsidies (central + state, updates) | agrosense/subsidies.py, data/subsidies.json |
| Application Layer β agri finance (bank assistance / loans + apply) | agrosense/finance.py, data/finance.json |
| Data Layer β land records (state RoR portal directory + generated guide) | agrosense/land_records.py, data/land_records.json |
| Data Layer β planetary positions | agrosense/planetary.py (pure-Python ephemeris) |
| Data Layer β hazards & fires | agrosense/hazards.py (NASA EONET keyless + FIRMS keyed) |
| Cognitive Layer β plant vision | agrosense/vision.py (disease + plant ID + pest ID; Keras backend + heuristic) |
| Cognitive Layer β plant telemedicine | agrosense/telemedicine.py (diagnosis + grounded, cited prescription) |
| Engagement Layer β live agri-doctor | agrosense/consultation.py (expert routing + Jitsi video + chat) |
| Engagement Layer β farmers' clubs | agrosense/clubs.py (location/commodity communities: feed + video + sharing) |
| RAG Workflow steps 1β7 (intake β preprocess β retrieve β re-rank β generate β cite) | agrosense/rag.py (RAGEngine.answer) |
| CARO β Context-Aware Retrieval Optimizer (metadata-weighted re-ranking) | Retriever._rerank_score in agrosense/retriever.py |
| Data Layer β dynamic (weather) data | agrosense/weather.py (Open-Meteo, no key) |
| Data Layer β location environment | agrosense/environment.py (elevation, AQ, pollen, wind, groundwater proxy) |
| Data Layer β satellite / remote sensing | agrosense/satellite.py (NASA GIBS + POWER, no key) |
| Data Layer β field-level NDVI (keyed) | agrosense/ndvi.py (Sentinel-2 via Google Earth Engine) |
| Data Layer β market prices | agrosense/prices.py (Agmarknet via data.gov.in) |
| Application Layer β farmer trading platform (P2P produce marketplace) | agrosense/trading.py, data/market_listings.json |
| Engagement Layer β multilingual | agrosense/translation.py (argos / deep-translator) |
| Interaction Layer (conversational UI) | ui/app.py |
| "Use only retrieved KB data. Include citations." system prompt | SYSTEM_PROMPT in agrosense/generator.py |
| Faithfulness / low-hallucination targets | extractive generator + relevance gate β off-domain queries get a safe fallback, never fabricated advice |
| Latency β€ 3 s target | every response reports latency_ms (sub-millisecond on the offline backends) |
Sample knowledge base
Covers paddy, maize, wheat, cotton, plus fertilizer schedules for aromatic (mint, citronella), vegetable (tomato), fruit (banana) and flower (marigold) crops, and a general soil-health entry β modeled on the report's KB design and the Azure assistant examples shown in the document.
Configuration
All tunable via environment variables (see agrosense/config.py):
| Variable | Default | Purpose |
|---|---|---|
AGROSENSE_EMBEDDING_BACKEND |
auto |
auto | sentence-transformers | hashing |
AGROSENSE_GENERATION_BACKEND |
extractive |
extractive (offline) | openai (real LLM seam) |
AGROSENSE_TOP_K |
5 |
candidates from vector search |
AGROSENSE_RERANK_K |
3 |
kept after re-ranking |
AGROSENSE_KB_PATH |
data/knowledge_base.json |
knowledge base location |
AGROSENSE_API_URL |
http://127.0.0.1:8000 |
API URL used by the UI |
Plugging in a real LLM (production path)
OpenAIGenerator in agrosense/generator.py shows the seam.
Set AGROSENSE_GENERATION_BACKEND=openai, pip install openai, and provide
OPENAI_API_KEY. The same pattern adapts to Azure OpenAI (the report's gpt-5-mini
deployment). The retrieval context and the strict "use only the provided context,
cite sources" instruction are already wired in.
Project layout
AgroSense/
βββ data/knowledge_base.json # the agriculture KB (structured JSON)
βββ agrosense/ # RAG core (the reusable library)
β βββ config.py # env-driven configuration
β βββ embeddings.py # hashing (offline) + sentence-transformers backends
β βββ knowledge_base.py # KB loading + document construction
β βββ vector_store.py # numpy fallback + FAISS backend
β βββ retriever.py # vector search + CARO-style re-ranking + relevance gate
β βββ generator.py # extractive grounded generator (+ OpenAI seam)
β βββ weather.py # live local forecast + advisory (Open-Meteo, no key)
β βββ satellite.py # satellite imagery + agroclimate (NASA GIBS + POWER)
β βββ ndvi.py # field-level Sentinel-2 NDVI (Google Earth Engine, keyed)
β βββ translation.py # multilingual layer (argos / deep-translator / identity)
β βββ prices.py # mandi market prices (Agmarknet via data.gov.in, keyed)
β βββ fusion.py # decision-fusion advisories (weather + satellite + NDVI)
β βββ crop_profiles.py # per-crop thresholds + growth stages (crop-aware fusion)
β βββ environment.py # location environment profile (Open-Meteo, keyless)
β βββ planetary.py # Sun/Moon/planet positions (pure-Python ephemeris)
β βββ groundwater.py # real water-table depth (CGWB/data.gov.in, keyed)
β βββ evaluation.py # RAGAS-style eval metrics (pure) + evaluate()
β βββ calendars.py # Gregorian + Indian National (Saka) calendars + IST
β βββ news.py # Google News headlines (region/topic, keyless)
β βββ radio.py # internet radio stations (Radio Browser, keyless)
β βββ commodities.py # Gold/Silver/Oil/Coffee (Yahoo) + Arecanut/Coconut (Agmarknet)
β βββ hazards.py # NASA EONET events (keyless) + FIRMS fires (keyed)
β βββ vision.py # plant disease + ID + pest (Keras backend + Pillow heuristic)
β βββ telemedicine.py # plant consult: diagnosis + grounded, cited prescription
β βββ ipm.py # recognized class -> exact IPM prescription lookup
β βββ consultation.py # live agri-doctor: expert routing + video + chat
β βββ doctors.py # plant-doctor onboarding + verification registry
β βββ notifications.py # expert alerts: in-app log + webhook + email
β βββ kb_admin.py # knowledge-base CRUD store + validation (admin)
β βββ rag.py # RAGEngine: end-to-end pipeline
βββ api/main.py # FastAPI: /query /weather /satellite /environment /planetary /hazards /vision/classify /telemedicine /experts /doctors/apply /doctors/{id} /doctors/{id}/rate /admin/doctors /consult/* /notifications /admin/kb /advisories /prices /news /commodities /datetime /languages
βββ scripts/evaluate.py # run the evaluation harness over data/eval_set.json
βββ scripts/train_plant_models.py # train the disease + plant-ID CNNs (needs TF + datasets)
βββ ui/app.py # Streamlit chat UI
βββ cli.py # command-line interface
βββ tests/test_rag.py # offline smoke + behavior tests
βββ requirements.txt
Limitations & next steps (toward the report's later phases)
- The offline hashing embedder is lexical-ish; install
sentence-transformersfor true semantic retrieval. - The extractive generator returns KB fields verbatim with citations rather than free-form prose β swap in the LLM backend for natural-language synthesis.
- Phase 2+: voice/image input, multilingual responses, live weather/market data,
and IoT signals (the data layer and
RAGEngineare structured to accept them).