|
|
""" |
|
|
Cleanup Planning MCP Tool |
|
|
|
|
|
Analyzes detected trash and generates cleanup action plans. |
|
|
""" |
|
|
|
|
|
from typing import Any, Optional |
|
|
from trash_model import Detection |
|
|
import llm_client |
|
|
|
|
|
|
|
|
def plan_cleanup( |
|
|
detections: list[Detection], |
|
|
location: Optional[str] = None, |
|
|
notes: Optional[str] = None, |
|
|
use_llm: bool = True |
|
|
): |
|
|
""" |
|
|
Generate a cleanup plan based on detected trash. |
|
|
|
|
|
Args: |
|
|
detections: List of trash detections from detection tool |
|
|
location: Optional location description |
|
|
notes: Optional additional context |
|
|
use_llm: Whether to use Gemini AI for intelligent planning (default: True) |
|
|
|
|
|
Returns: |
|
|
Dict containing: |
|
|
- severity: "low" | "medium" | "high" |
|
|
- recommended_volunteers: int |
|
|
- estimated_time_minutes: int |
|
|
- equipment_needed: list[str] |
|
|
- urgency_days: int (recommended action timeframe) |
|
|
- environmental_impact: str |
|
|
- action_summary: str (AI-generated when use_llm=True) |
|
|
""" |
|
|
if not detections: |
|
|
return { |
|
|
"severity": "low", |
|
|
"recommended_volunteers": 0, |
|
|
"estimated_time_minutes": 0, |
|
|
"equipment_needed": [], |
|
|
"urgency_days": 0, |
|
|
"environmental_impact": "No trash detected - area appears clean.", |
|
|
"action_summary": "No cleanup action needed at this time." |
|
|
} |
|
|
|
|
|
|
|
|
count = len(detections) |
|
|
avg_confidence = sum(d["score"] for d in detections) / count |
|
|
categories = set(d["label"] for d in detections) |
|
|
|
|
|
|
|
|
if count >= 15 or len(categories) >= 6: |
|
|
severity = "high" |
|
|
urgency_days = 1 |
|
|
volunteers = 4 + (count // 10) |
|
|
time_estimate = 90 + (count * 3) |
|
|
elif count >= 7 or len(categories) >= 4: |
|
|
severity = "medium" |
|
|
urgency_days = 3 |
|
|
volunteers = 2 + (count // 8) |
|
|
time_estimate = 45 + (count * 2) |
|
|
else: |
|
|
severity = "low" |
|
|
urgency_days = 7 |
|
|
volunteers = 1 + (count // 5) |
|
|
time_estimate = 20 + (count * 2) |
|
|
|
|
|
|
|
|
equipment = ["Heavy-duty trash bags", "Gloves", "Grabber tools"] |
|
|
|
|
|
if "glass_bottle" in categories: |
|
|
equipment.append("Safety goggles") |
|
|
equipment.append("Puncture-resistant bags") |
|
|
|
|
|
if count > 10: |
|
|
equipment.append("Wheeled collection bin") |
|
|
|
|
|
|
|
|
impact_descriptions = { |
|
|
"high": "Significant environmental concern. Risk of wildlife harm, water contamination, and community health issues. Immediate action recommended.", |
|
|
"medium": "Moderate environmental impact. Potential for wildlife interaction and visual pollution. Timely cleanup will prevent escalation.", |
|
|
"low": "Minor environmental impact. Early intervention will maintain area cleanliness and prevent accumulation." |
|
|
} |
|
|
|
|
|
plan = { |
|
|
"severity": severity, |
|
|
"recommended_volunteers": volunteers, |
|
|
"estimated_time_minutes": time_estimate, |
|
|
"equipment_needed": equipment, |
|
|
"urgency_days": urgency_days, |
|
|
"environmental_impact": impact_descriptions[severity], |
|
|
"action_summary": _generate_action_summary( |
|
|
severity, volunteers, time_estimate, count, categories |
|
|
) |
|
|
} |
|
|
|
|
|
|
|
|
if use_llm: |
|
|
plan["action_summary"] = _enhance_with_llm(plan, detections, location, notes) |
|
|
|
|
|
return plan |
|
|
|
|
|
|
|
|
def _generate_action_summary( |
|
|
severity: str, |
|
|
volunteers: int, |
|
|
time_minutes: int, |
|
|
count: int, |
|
|
categories: set[str] |
|
|
) -> str: |
|
|
"""Generate human-readable action summary.""" |
|
|
category_list = ", ".join(sorted(categories)[:3]) |
|
|
if len(categories) > 3: |
|
|
category_list += f" and {len(categories) - 3} other types" |
|
|
|
|
|
summary = f"""**Cleanup Plan - {severity.upper()} Priority** |
|
|
|
|
|
Detected {count} trash items including {category_list}. |
|
|
|
|
|
**Recommended Resources:** |
|
|
- {volunteers} volunteer(s) |
|
|
- Approximately {time_minutes} minutes |
|
|
- Standard cleanup equipment |
|
|
|
|
|
**Next Steps:** |
|
|
1. Gather volunteers and equipment |
|
|
2. Coordinate cleanup date/time |
|
|
3. Execute cleanup operation |
|
|
4. Dispose of collected waste properly |
|
|
5. Document completion for tracking |
|
|
""" |
|
|
return summary |
|
|
|
|
|
|
|
|
def _enhance_with_llm( |
|
|
plan, |
|
|
detections: list[Detection], |
|
|
location: Optional[str], |
|
|
notes: Optional[str] |
|
|
) -> str: |
|
|
"""Use Gemini AI to create intelligent, context-aware cleanup plans.""" |
|
|
import os |
|
|
|
|
|
|
|
|
api_key = os.getenv("GEMINI_API_KEY") |
|
|
if api_key: |
|
|
try: |
|
|
import google.generativeai as genai |
|
|
genai.configure(api_key=api_key) |
|
|
|
|
|
|
|
|
detection_details = [] |
|
|
category_counts = {} |
|
|
for d in detections: |
|
|
label = d.get("label", "unknown") |
|
|
category_counts[label] = category_counts.get(label, 0) + 1 |
|
|
|
|
|
for label, count in sorted(category_counts.items(), key=lambda x: -x[1]): |
|
|
detection_details.append(f"- {label}: {count} item(s)") |
|
|
|
|
|
context = f"""**Trash Detection Analysis:** |
|
|
{chr(10).join(detection_details)} |
|
|
|
|
|
**Total Items:** {len(detections)} |
|
|
**Categories:** {len(category_counts)} types |
|
|
**Severity:** {plan['severity']} |
|
|
**Location:** {location or 'Not specified'} |
|
|
**Notes:** {notes or 'None'} |
|
|
|
|
|
**Baseline Estimates:** |
|
|
- Volunteers needed: {plan['recommended_volunteers']} |
|
|
- Time estimate: {plan['estimated_time_minutes']} minutes |
|
|
- Equipment: {', '.join(plan['equipment'])} |
|
|
""" |
|
|
|
|
|
prompt = f"""You are an expert environmental cleanup coordinator with years of field experience. |
|
|
|
|
|
Analyze this trash situation and create an intelligent, actionable cleanup plan: |
|
|
|
|
|
{context} |
|
|
|
|
|
Generate a comprehensive cleanup plan that includes: |
|
|
|
|
|
1. **Situation Assessment** - What's the severity and why? What environmental risks exist? |
|
|
|
|
|
2. **Resource Optimization** - Are the baseline estimates right? Should we adjust volunteers, time, or equipment based on: |
|
|
- Specific trash types detected (sharp objects need safety gear, electronics need special disposal, etc.) |
|
|
- Quantity and distribution |
|
|
- Location characteristics |
|
|
- Potential hazards |
|
|
|
|
|
3. **Specific Action Steps** - Not generic steps, but SPECIFIC to this situation: |
|
|
- What should be prioritized first? |
|
|
- What special handling is needed? |
|
|
- What safety precautions? |
|
|
- What disposal methods? |
|
|
|
|
|
4. **Environmental Impact** - Why does THIS specific cleanup matter? What habitat/ecosystem benefits? |
|
|
|
|
|
5. **Smart Recommendations** - Any location-specific tips or efficiency strategies? |
|
|
|
|
|
Be SPECIFIC and PRACTICAL. This is a real cleanup, not a template. If you see hazardous items, mention them. If the time estimate seems wrong, adjust it. Make it actionable.""" |
|
|
|
|
|
model = genai.GenerativeModel('gemini-1.5-flash-latest') |
|
|
response = model.generate_content(prompt) |
|
|
|
|
|
if response and response.text: |
|
|
return response.text.strip() |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Gemini AI planning failed: {e}") |
|
|
|
|
|
|
|
|
detection_summary = f"{len(detections)} items detected: " |
|
|
detection_summary += ", ".join(set(d["label"] for d in detections)) |
|
|
|
|
|
context_parts = [ |
|
|
f"Trash detection summary: {detection_summary}", |
|
|
f"Severity assessment: {plan['severity']}", |
|
|
f"Recommended volunteers: {plan['recommended_volunteers']}", |
|
|
f"Estimated time: {plan['estimated_time_minutes']} minutes" |
|
|
] |
|
|
|
|
|
if location: |
|
|
context_parts.append(f"Location: {location}") |
|
|
if notes: |
|
|
context_parts.append(f"Additional context: {notes}") |
|
|
|
|
|
prompt = f"""Based on this trash detection analysis, create a clear, actionable cleanup plan summary: |
|
|
|
|
|
{chr(10).join(context_parts)} |
|
|
|
|
|
Write a brief, practical summary that: |
|
|
1. States the situation clearly |
|
|
2. Recommends specific actions |
|
|
3. Estimates resources needed |
|
|
4. Explains why this matters for the environment |
|
|
|
|
|
Keep it concise (3-4 sentences).""" |
|
|
|
|
|
try: |
|
|
enhanced = llm_client.generate_text( |
|
|
prompt, |
|
|
system_prompt="You are a helpful environmental cleanup coordinator. Be practical and encouraging.", |
|
|
max_tokens=300, |
|
|
temperature=0.7 |
|
|
) |
|
|
return enhanced |
|
|
except Exception as e: |
|
|
print(f"LLM enhancement failed: {e}") |
|
|
return plan["action_summary"] |
|
|
|