import gradio as gr import requests from geopy.geocoders import Nominatim from PIL import Image import base64 import io import os import json from duckduckgo_search import DDGS # šŸ”‘ OpenAI API Key (set in Hugging Face Space Secrets) OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") API_URL = "https://api.openai.com/v1/chat/completions" # šŸŒ Reverse geocode lat/lon → location name def get_address(lat, lon): geolocator = Nominatim(user_agent="farming_guidance") try: location = geolocator.reverse((lat, lon), language="en") return location.address if location else "Unknown Location" except: return "Error fetching location" # šŸ–¼ļø Analyze crop & damage using GPT-4o Vision def analyze_crop_image(image): buffered = io.BytesIO() image.save(buffered, format="PNG") img_b64 = base64.b64encode(buffered.getvalue()).decode("utf-8") vision_prompt = """ You are an agricultural vision expert. Carefully analyze this crop image. - Identify the crop. - State if Healthy or Damaged. - If damaged, classify (pest / disease / nutrient deficiency). - Suggest organic + inorganic treatments. Return JSON only. """ headers = {"Authorization": f"Bearer {OPENAI_API_KEY}", "Content-Type": "application/json"} data = { "model": "gpt-4o", "messages": [ {"role": "system", "content": "You are a professional agriculture crop doctor."}, { "role": "user", "content": [ {"type": "text", "text": vision_prompt}, {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img_b64}"}} ] } ], "temperature": 0.2 } response = requests.post(API_URL, headers=headers, json=data) if response.status_code == 200: raw = response.json()["choices"][0]["message"]["content"] try: if "```json" in raw: json_part = raw.split("```json")[1].split("```")[0].strip() return json.loads(json_part) return json.loads(raw) except Exception: return {"Crop": "Unknown", "Status": "Unknown", "Reason": "Parsing Error", "Raw": raw} return {"Error": response.text} # 🌐 Web search if detection confidence is low def search_crop_disease(crop, symptom): query = f"{crop} {symptom} disease treatment site:.org OR site:.gov OR site:.edu" try: with DDGS() as ddgs: results = ddgs.text(query, max_results=3) return [f"- {r['title']}: {r['body']} ({r['href']})" for r in results] except Exception as e: return [f"āŒ Web search failed: {str(e)}"] # šŸ“‹ Advisory generator def get_recommendations(image, lat, lon): vision_result = analyze_crop_image(image) crop = vision_result.get("Crop", "Unknown") reason = vision_result.get("Reason", "Unclear") confidence = vision_result.get("Confidence", "Low") address = get_address(lat, lon) soil_profile = "Loamy soil, moderate organic matter (default assumption)" climate = f"Climate for Lat:{lat}, Lon:{lon} - Avg temp 27°C, humidity 70%, rainfall forecast: 15mm" web_results = [] if confidence.lower() == "low" or crop == "Unknown": web_results = search_crop_disease(crop, reason) advisory_prompt = f""" You are an agricultural advisor for Indian farmers. Farmer details: Location: {address} (Lat:{lat}, Lon:{lon}) Crop: {crop} Soil: {soil_profile} Climate: {climate} Image Analysis: {vision_result} Internet Search Findings: {web_results} Give practical farmer guidance: - Fertilizers (stage-wise dosage/acre). - Pesticides (preventive + curative). - Herbicides (safe use). - Common pest/disease alerts in region. - Alternative crops and secondary crops. """ headers = {"Authorization": f"Bearer {OPENAI_API_KEY}", "Content-Type": "application/json"} data = {"model": "gpt-4o", "messages": [{"role": "user", "content": advisory_prompt}], "temperature": 0.5} response = requests.post(API_URL, headers=headers, json=data) if response.status_code == 200: return ( f"šŸ–¼ļø Image Analysis:\n{vision_result}\n\n" f"🌐 Web Search Support:\n" + "\n".join(web_results) + f"\n\nšŸ“ Location: {address}\n\n" + response.json()["choices"][0]["message"]["content"] ) return f"āŒ Error: {response.text}" # šŸŽØ Gradio UI with gr.Blocks() as demo: gr.Markdown("## 🌱 AI Farming Guidance Platform (Lightweight Cropseetalk model with Internet Powered)") with gr.Row(): image_input = gr.Image(type="pil", label="Upload Crop Image") with gr.Row(): lat_box = gr.Number(label="Latitude", value=28.61) lon_box = gr.Number(label="Longitude", value=77.23) get_loc_btn = gr.Button("šŸ“ Get Location from Device") run_btn = gr.Button("🚜 Analyze & Get Guidance") output = gr.Textbox(label="Recommendations", lines=30) get_loc_btn.click( None, js=""" () => new Promise((resolve, reject) => { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (pos) => resolve([pos.coords.latitude, pos.coords.longitude]), (err) => reject("Location access denied") ); } else { reject("Geolocation not supported"); } }) """, outputs=[lat_box, lon_box] ) run_btn.click(fn=get_recommendations, inputs=[image_input, lat_box, lon_box], outputs=output) if __name__ == "__main__": demo.launch()