Spaces:
Sleeping
Sleeping
| 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() | |