demeter

Autonomous Hydroponic Intelligence

agent/sub_agents/Explainer.py (2331B)


 1import json
 2import os
 3from openai import AzureOpenAI
 4from dotenv import load_dotenv
 5
 6load_dotenv()
 7
 8class ExplainerAgent:
 9    def __init__(self):
10        self.llm = AzureOpenAI(
11            api_key=os.getenv("AZURE_OPENAI_API_KEY"),
12            api_version=os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview"),
13            azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
14        )
15        self.deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
16
17    def explain(self, current_fmu, similar_fmus, sub_agent_reports, final_decision):
18        """
19        Generates a detailed, human-readable log of the decision process.
20        """
21        
22        # Construct the context for the LLM
23        context = f"""
24        CONTEXT DATA:
25        - Current Sensors: {json.dumps(current_fmu['payload']['sensors'])}
26        - Visual Context: {current_fmu['metadata'].get('stage')} {current_fmu['metadata'].get('crop')}
27        - Expert Reports: {json.dumps(sub_agent_reports)}
28        - Historical Precedents: Found {len(similar_fmus)} similar past cases.
29        
30        FINAL DECISION TAKEN:
31        {json.dumps(final_decision)}
32        """
33
34        system_prompt = """
35        You are the "Explainer" for an AI Hydroponic System. 
36        Your goal is to write a "Chain of Thought" log that explains WHY a specific decision was made.
37        
38        STRUCTURE YOUR RESPONSE AS A CLEAN LIST OF STEPS:
39        1. **Observation**: What did the sensors and vision see? (Cite specific numbers).
40        2. **Precedent**: Did we see this before? (Reference the similar cases).
41        3. **Logic**: Connect the dots. (e.g., "High pH + Yellow Leaves usually means X").
42        4. **Conclusion**: Why is the recommended action the safest bet?
43        
44        Keep the tone professional, transparent, and educational.
45        """
46
47        try:
48            response = self.llm.chat.completions.create(
49                model=self.deployment_name,
50                messages=[
51                    {"role": "system", "content": system_prompt},
52                    {"role": "user", "content": context}
53                ],
54                temperature=0.3 # Keep it factual
55            )
56            return response.choices[0].message.content
57        except Exception as e:
58            return f"Explanation unavailable: {str(e)}"