--- title: ShambaSense AI emoji: 🌱 colorFrom: green colorTo: yellow sdk: static pinned: false --- # ShambaSense AI ShambaSense AI is a crop-health screening tool for Kenyan smallholder farmers. The user interface runs on a Hugging Face **Static Space** and sends image-analysis requests to a separate Python **FastAPI service on Render**. The browser never runs Python, PyTorch, or model inference. > **Safety:** This is a screening aid, not a confirmed agricultural diagnosis. Model confidence is not proof that a disease is present. Consult a qualified local agricultural extension officer before treatment, especially for severe or uncertain cases. ## Architecture ```text Hugging Face Static Space index.html + style.css + app.js | | HTTPS multipart/form-data v Render Web Service backend/main.py + backend/inference.py | v Transformers/PyTorch model neghani/plantvillage-mobilenetv2 ``` Repository structure: ```text shambasense-ai-2/ ├── index.html ├── style.css ├── app.js ├── README.md ├── render.yaml # authoritative Render Blueprint ├── data/guidance_sources.json └── backend/ ├── main.py ├── inference.py ├── guidance.py ├── requirements.txt ├── README.md └── tests/test_api.py ``` ## Implemented frontend features - Responsive, accessible static UI for mobile, tablet, and desktop. - English/Kiswahili language switching. - Drag-and-drop and file-picker upload with preview and removal. - JPEG, PNG, and WEBP validation with a 10 MB client-side limit. - Crop metadata for maize, tomato, potato, beans, banana, and other/unknown. - Symptom notes, loading/error states, local field history, and TXT/JSON reports. - No predictions are shown unless the backend returns valid model output. - Photos are not stored in browser history or reports. ## AI model and limitations The backend reuses the existing public model: [`neghani/plantvillage-mobilenetv2`](https://huggingface.co/neghani/plantvillage-mobilenetv2) Its actual labels include maize/corn, potato, and tomato classes. Beans and banana are accepted as field metadata, but this model does not provide validated disease classes for them. The model was trained on curated PlantVillage-style images and may perform poorly on real field photographs, unfamiliar varieties, mixed symptoms, or poor lighting. The backend reports `503 model_unavailable` if the model cannot load. It never substitutes a mock classifier or fabricated confidence. ## Deployment order ### 1. Deploy the Render backend first The repository-root `render.yaml` is the only Render configuration. It defines a Python Web Service with `rootDir: backend`: ```yaml buildCommand: pip install -r requirements.txt startCommand: uvicorn main:app --host 0.0.0.0 --port $PORT healthCheckPath: /health ``` In Render, create a Web Service from this repository and apply the Blueprint, or enter the equivalent settings: | Render setting | Value | | --- | --- | | Runtime | Python | | Root Directory | `backend` | | Build Command | `pip install -r requirements.txt` | | Start Command | `uvicorn main:app --host 0.0.0.0 --port $PORT` | | Health Check Path | `/health` | | Python version | `3.11.11` via `PYTHON_VERSION` in the root `render.yaml` | Set these environment variables in Render: | Variable | Required | Purpose | | --- | --- | --- | | `MODEL_ID` | No | Defaults to `neghani/plantvillage-mobilenetv2`. | | `FRONTEND_ORIGIN` | Yes for deployed browser calls | Exact Space origin, for example `https://quantmodeldev-shambasense-ai-2.hf.space`. Multiple origins may be comma-separated. | | `HF_TOKEN` | No | Only needed if you replace the public model with a private model. Store it as a Render secret; never expose it to the browser. | | `PYTHON_VERSION` | Set by Blueprint | `3.11.11`, matching the pinned PyTorch wheel. | Wait for `/health` to respond. `status: "ready"` means the model has loaded; `unavailable` means it is not configured or failed to load. The first health check can be slow while Transformers downloads model files. **Memory limitation:** PyTorch and Transformers require substantially more memory than the static frontend. Check Render's current free-plan RAM and runtime limits before relying on this service for real farmer traffic. A cold start may reload the model. ### 2. Configure the frontend After Render provides the actual service URL, edit the single central setting near the top of `app.js`: ```javascript const API_BASE_URL = "https://YOUR-RENDER-SERVICE.onrender.com"; ``` Replace the placeholder with the exact HTTPS Render URL. Do not add `/api/v1/predict` to this line; the frontend appends that route itself. Do not put `HF_TOKEN` or any private key in `app.js`. ### 3. Push the Static Space From this directory: ```bash git add index.html style.css app.js README.md render.yaml backend git commit -m "Connect ShambaSense static frontend to FastAPI backend" git push origin main ``` The Hugging Face Space continues to use `sdk: static` and serves the root `index.html`. ## API endpoints - `GET /` — service status. - `GET /health` — model configuration/loading status. - `GET /api/v1/info` — API version, model ID, and supported crop metadata. - `POST /api/v1/predict` — accepts multipart fields: - `image`: JPEG, PNG, or WEBP file - `crop`: `maize`, `tomato`, `potato`, `beans`, `banana`, or `other` - `symptoms`: optional text up to 600 characters - `language`: `en` or `sw` Example: ```bash curl -X POST "https://YOUR-RENDER-SERVICE.onrender.com/api/v1/predict" \ -F "image=@leaf.jpg" \ -F "crop=tomato" \ -F "symptoms=yellow spots after rain" \ -F "language=en" ``` The response contains only model-derived `diagnosis`, `confidence`, and top predictions, plus guidance from the existing conservative guidance logic. A model loading failure returns a structured `503` response. ## Local development ### Frontend ```bash cd shambasense-ai-2 python3 -m http.server 8000 ``` Open . Until `API_BASE_URL` is changed, the page deliberately shows that backend inference is unavailable. ### Backend ```bash cd shambasense-ai-2/backend python3.11 -m venv .venv source .venv/bin/activate pip install -r requirements.txt export MODEL_ID=neghani/plantvillage-mobilenetv2 export FRONTEND_ORIGIN=http://localhost:8000 uvicorn main:app --reload --port 8000 ``` The backend and frontend cannot use the same local port. Use a different frontend port, for example: ```bash cd shambasense-ai-2 python3 -m http.server 8080 export FRONTEND_ORIGIN=http://localhost:8080 ``` ## Testing Backend tests use a controlled test double only for the successful-inference case: ```bash cd shambasense-ai-2/backend pip install -r requirements.txt pip install pytest httpx pytest -q ``` Frontend syntax and static checks: ```bash cd shambasense-ai-2 node --check app.js python3 - <<'PY' from pathlib import Path from html.parser import HTMLParser HTMLParser().feed(Path("index.html").read_text()) assert Path("style.css").exists() assert Path("app.js").exists() print("Static assets are valid") PY ``` These tests do not claim that the live Render model loaded successfully. Test that separately through `/health` and a real, suitable leaf image. ## Troubleshooting - **Frontend says backend unavailable:** replace `API_BASE_URL` in `app.js` with the actual HTTPS Render URL and redeploy the Static Space. - **CORS errors:** set `FRONTEND_ORIGIN` to the exact Space origin, without a trailing slash, then redeploy/restart Render. - **`503 model_unavailable`:** inspect Render logs and `/health`; verify `MODEL_ID`, model access, available RAM, and cold-start completion. - **Slow first request:** Transformers downloads model files on first load. Render may also sleep or restart a free service. - **No predictions for beans or banana:** the current model does not contain validated classes for those crops. Use a model trained and evaluated for them before presenting those results. - **Reports/history disappear:** they are browser-local and are not synchronized to a database. ## Privacy Field history remains in the current browser's local storage. Raw photos are not stored there. When the backend is configured, the selected image and symptom note are sent to the Render service for inference. Do not enter unnecessary personal information. Review the backend hosting and model provider policies before collecting real farmer data. Guidance provenance is retained in `data/guidance_sources.json`, including KALRO, FAO Plant Production and Protection, and the original model card.