--- 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/](web/)) is **served by FastAPI itself**. Start the API and open it: ```powershell 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](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](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/](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](scripts/docgen.py)) so the two formats never drift. **Regenerate everything with one command:** ```powershell 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](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](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](https://open-meteo.com/)** (free, **no API key**), implementing the report's Data Layer "dynamic (weather) data" source: ```powershell 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"*). ```powershell 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](agrosense/ndvi.py)). **Enable it:** ```powershell 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](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](agrosense/groundwater.py)); otherwise a labelled **soil-moisture proxy** (3–9 cm) | ```powershell python cli.py --location Belagavi --environment "..." ``` Endpoint: `GET /environment?location=…` or `?latitude=…&longitude=…`. UI: tick **🌍 Show location environment**. See [agrosense/environment.py](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: ```powershell $env:AGROSENSE_DATAGOV_API_KEY = "your-data.gov.in-key" $env:AGROSENSE_GROUNDWATER_RESOURCE = "" $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](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](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](agrosense/vision.py). **Train the models** (needs TensorFlow + datasets β€” run outside this sandbox) with [scripts/train_plant_models.py](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](agrosense/ipm.py) + [data/ipm_prescriptions.json](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](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](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](agrosense/consultation.py) + [data/agri_experts.json](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](agrosense/doctors.py) (`data/plant_doctors.json`, seeded from [data/agri_experts.json](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](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_BASE` to 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](agrosense/traditional.py) + [data/traditional_knowledge.json](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](agrosense/finance.py) + [data/finance.json](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](agrosense/subsidies.py) + [data/subsidies.json](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](agrosense/land_records.py) + [data/land_records.json](data/land_records.json) (PDF/Word via the shared [scripts/docgen.py](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: ```powershell 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](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](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. ```powershell 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. ```powershell python cli.py --location Belagavi --planets "..." ``` Computed locally with a pure-Python ephemeris (Schlyter's algorithm) β€” **keyless, offline, no dependencies** ([agrosense/planetary.py](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: ```powershell 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](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: ```powershell 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](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](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](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, > plain `http://` 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](agrosense/calendars.py) (pure, unit-tested β€” the Gregorianβ†’Saka conversion is exact). Endpoint `GET /datetime`. - Headlines: [agrosense/news.py](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` β€” `region` selects the locale, `query`=None gives general top stories, or pass a topic/keyword (or a `site:reuters.com` filter 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](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: ```powershell $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](agrosense/evaluation.py)); the gold set is [data/eval_set.json](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 embeddings - `pip install faiss-cpu` β†’ faster vector search --- ## Quick start ```powershell # 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 ```powershell 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](data/knowledge_base.json), [agrosense/knowledge_base.py](agrosense/knowledge_base.py) | | Knowledge Layer (vectorized documents) | [agrosense/embeddings.py](agrosense/embeddings.py), [agrosense/vector_store.py](agrosense/vector_store.py) | | Cognitive Layer β€” RAG pipeline (retrieval + re-ranking + generation) | [agrosense/retriever.py](agrosense/retriever.py), [agrosense/generator.py](agrosense/generator.py), [agrosense/rag.py](agrosense/rag.py) | | Cognitive Layer β€” decision fusion (multi-signal advisories) | [agrosense/fusion.py](agrosense/fusion.py), [agrosense/crop_profiles.py](agrosense/crop_profiles.py) | | Cognitive Layer β€” traditional advisor (Panchang + desi practices) | [agrosense/traditional.py](agrosense/traditional.py) | | Data Layer β€” government schemes & subsidies (central + state, updates) | [agrosense/subsidies.py](agrosense/subsidies.py), [data/subsidies.json](data/subsidies.json) | | Application Layer β€” agri finance (bank assistance / loans + apply) | [agrosense/finance.py](agrosense/finance.py), [data/finance.json](data/finance.json) | | Data Layer β€” land records (state RoR portal directory + generated guide) | [agrosense/land_records.py](agrosense/land_records.py), [data/land_records.json](data/land_records.json) | | Data Layer β€” planetary positions | [agrosense/planetary.py](agrosense/planetary.py) (pure-Python ephemeris) | | Data Layer β€” hazards & fires | [agrosense/hazards.py](agrosense/hazards.py) (NASA EONET keyless + FIRMS keyed) | | Cognitive Layer β€” plant vision | [agrosense/vision.py](agrosense/vision.py) (disease + plant ID + pest ID; Keras backend + heuristic) | | Cognitive Layer β€” plant telemedicine | [agrosense/telemedicine.py](agrosense/telemedicine.py) (diagnosis + grounded, cited prescription) | | Engagement Layer β€” live agri-doctor | [agrosense/consultation.py](agrosense/consultation.py) (expert routing + Jitsi video + chat) | | Engagement Layer β€” farmers' clubs | [agrosense/clubs.py](agrosense/clubs.py) (location/commodity communities: feed + video + sharing) | | RAG Workflow steps 1–7 (intake β†’ preprocess β†’ retrieve β†’ re-rank β†’ generate β†’ cite) | [agrosense/rag.py](agrosense/rag.py) (`RAGEngine.answer`) | | **CARO** β€” Context-Aware Retrieval Optimizer (metadata-weighted re-ranking) | `Retriever._rerank_score` in [agrosense/retriever.py](agrosense/retriever.py) | | Data Layer β€” dynamic (weather) data | [agrosense/weather.py](agrosense/weather.py) (Open-Meteo, no key) | | Data Layer β€” location environment | [agrosense/environment.py](agrosense/environment.py) (elevation, AQ, pollen, wind, groundwater proxy) | | Data Layer β€” satellite / remote sensing | [agrosense/satellite.py](agrosense/satellite.py) (NASA GIBS + POWER, no key) | | Data Layer β€” field-level NDVI (keyed) | [agrosense/ndvi.py](agrosense/ndvi.py) (Sentinel-2 via Google Earth Engine) | | Data Layer β€” market prices | [agrosense/prices.py](agrosense/prices.py) (Agmarknet via data.gov.in) | | Application Layer β€” farmer trading platform (P2P produce marketplace) | [agrosense/trading.py](agrosense/trading.py), `data/market_listings.json` | | Engagement Layer β€” multilingual | [agrosense/translation.py](agrosense/translation.py) (argos / deep-translator) | | Interaction Layer (conversational UI) | [ui/app.py](ui/app.py) | | "Use only retrieved KB data. Include citations." system prompt | `SYSTEM_PROMPT` in [agrosense/generator.py](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](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](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-transformers` for 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 `RAGEngine` are structured to accept them).