FarmAI / app.py
sumitkrsharma's picture
Update app.py
19f9c62 verified
Raw
History Blame Contribute Delete
5.73 kB
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()