Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from transformers import pipeline | |
| from PIL import Image | |
| import base64 | |
| import io | |
| import requests | |
| app = FastAPI(title="STOA Plant Disease API") | |
| # --- CORS --- | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # --- MODEL LOADING --- | |
| print("Booting Agricultural Node. Loading MobileNetV2 Plant model...") | |
| # THE FIX: Explicitly borrow the Google MobileNetV2 image processor | |
| pipe = pipeline( | |
| "image-classification", | |
| model="linkanjarad/mobilenet_v2_1.0_224-plant-disease-identification", | |
| image_processor="google/mobilenet_v2_1.0_224" | |
| ) | |
| print("Agent Ready!") | |
| # --- REQUEST SCHEMA --- | |
| class PredictRequest(BaseModel): | |
| image: str | None = None | |
| image_url: str | None = None | |
| # --- ENDPOINTS --- | |
| def health_check(): | |
| return {"status": "ok"} | |
| def predict(req: PredictRequest): | |
| try: | |
| img = None | |
| # 1. Handle URL Input (with Super-Human headers) | |
| if req.image_url: | |
| headers = { | |
| "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", | |
| "Accept": "image/avif,image/webp,image/apng,image/*,*/*;q=0.8", | |
| "Referer": "https://google.com" | |
| } | |
| response = requests.get(req.image_url, stream=True, headers=headers, timeout=10) | |
| if response.status_code != 200: | |
| raise Exception(f"External site blocked us with error: {response.status_code}.") | |
| img = Image.open(response.raw).convert("RGB") | |
| # 2. Handle Base64 Input | |
| elif req.image: | |
| b64_data = req.image | |
| if "," in b64_data: | |
| b64_data = b64_data.split(",")[1] | |
| image_bytes = base64.b64decode(b64_data) | |
| img = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
| else: | |
| raise HTTPException(status_code=400, detail="Must provide 'image' (base64) or 'image_url'.") | |
| # 3. Execute AI Math | |
| results = pipe(img, top_k=3) | |
| # 4. Format Output for the STOA Marketplace | |
| top_3_list = [{"disease": res["label"], "confidence": round(res["score"], 4)} for res in results] | |
| return { | |
| "prediction": results[0]["label"], | |
| "confidence": round(results[0]["score"], 4), | |
| "top_3": top_3_list | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=400, detail=f"Failed to process leaf: {str(e)}") |