demeter

Autonomous Hydroponic Intelligence

agent/sub_agents/water_and_atmospheric_dependencies/retrieval.py (3797B)


  1import os
  2import json
  3from langchain.tools import tool
  4from qdrant_client import QdrantClient
  5
  6# Import your existing modules
  7from agent.sub_agents.Researcher import ResearcherAgent
  8from agent.Qdrant.Store import COLLECTION_NAME
  9
 10from agent.sub_agents.Doctor import VisionAgent
 11from agent.memory import FarmMemory
 12
 13# Initialize shared clients
 14# Note: We rely on the existing ResearcherAgent logic for embeddings/search
 15researcher_instance = ResearcherAgent()
 16farm_memory = FarmMemory()
 17
 18# Initialize Qdrant for the Historian
 19qdrant_client = QdrantClient(
 20    url=os.environ.get("QDRANT_URL", "http://localhost:6333"),
 21    api_key=os.environ.get("QDRANT_API_KEY"),
 22)
 23
 24doctor = VisionAgent()
 25
 26@tool
 27def diagnose_plant(image_b64: str = None):
 28    """
 29    Uses Computer Vision to scan the latest plant image for disease.
 30    
 31    INSTRUCTIONS FOR LLM: 
 32    Call this tool with NO arguments. The system will automatically 
 33    attach the latest camera feed for you.
 34    """
 35    if not image_b64:
 36        return {"error": "System Error: No visual data was injected into the tool call."}
 37        
 38    # Calls the analyze_frame method you updated earlier
 39    result = doctor.analyze_frame(image_b64)
 40    print(f"Diagnose Plant Result: {result}")
 41    return result
 42
 43@tool
 44def ask_memory(plant_id: str):
 45    """
 46    Consult the Farm Memory for past events, strategies, and outcomes.
 47    Useful for recalling what has been tried before and its results.
 48    
 49    Args:
 50        plant_id: The specific crop ID to look up (e.g. "crop_beta").
 51    """
 52    print(f"Consulting Farm Memory for plant ID: {plant_id}")
 53    try:
 54        # Fixed: calling the wrapper method directly on the instance
 55        response = farm_memory.get_plant_history(plant_id)
 56        print(f"Memory response for {plant_id}: {response}")
 57        return response
 58    except Exception as e:
 59        return f"Memory unavailable: {str(e)}"
 60
 61@tool
 62def ask_historian(query: str):
 63    """
 64    Search the Farm's Database (History) for similar past events.
 65    Useful for checking past mistakes, success rates, or specific scenarios.
 66    
 67    Args:
 68        query: A description of the situation to look up (e.g. "What happened when pH dropped to 5.5?")
 69    """
 70    try:
 71        # 1. Generate Embedding using Researcher's Encoder (384 dims)
 72        # .embed() returns a generator, convert to list and take first item
 73        embeddings = list(researcher_instance.encoder.embed([query]))
 74        query_vector = embeddings[0].tolist()
 75        
 76        # 2. Search the TEXT collection (Plant_Biographies_HF)
 77        # We CANNOT search COLLECTION_NAME (Farm_Memory) because the vector dimensions don't match.
 78        hits = qdrant_client.query_points(
 79            collection_name="Plant_Biographies_HF  ",
 80            query=query_vector,
 81            limit=3
 82        )
 83        
 84        results = []
 85        for hit in hits:
 86            # Handle different payload structures
 87            content = hit.payload.get('text', hit.payload.get('memory', ''))
 88            source = hit.payload.get('source', hit.payload.get('user_id', 'Unknown'))
 89            results.append(f"[{source}]: {content}")
 90            
 91        return "\n".join(results) if results else "No relevant history found."
 92        
 93    except Exception as e:
 94        return f"Historian unavailable: {str(e)}"
 95
 96@tool
 97def ask_rag(query: str):
 98    """
 99    Consult the Research Assistant (RAG) for scientific knowledge.
100    Useful for finding optimal ranges, chemical interactions, or biological facts.
101    
102    Args:
103        query: Scientific question (e.g. "Optimal VPD for Lettuce in late flower")
104    """
105    try:
106        # Reuse your existing ResearcherAgent logic
107        return researcher_instance.search(query)
108    except Exception as e:
109        return f"Research unavailable: {str(e)}"
110