demeter

Autonomous Hydroponic Intelligence

agent/sub_agents/water_and_atmospheric_dependencies/physics_engine.py (2700B)


 1import os
 2import json
 3from langchain_openai import AzureChatOpenAI
 4from langchain_core.messages import SystemMessage, HumanMessage
 5from dotenv import load_dotenv
 6
 7load_dotenv()
 8
 9# Configuration
10API_KEY = os.environ.get("AZURE_OPENAI_API_KEY")
11ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
12DEPLOYMENT_NAME = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
13API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
14
15
16def predict_outcome(current_state: dict, proposed_action: dict) -> dict:
17    """
18    Stateless 'What-If' Engine using Azure OpenAI (LLM-based Physics).
19    Takes a snapshot and an action, returns the PREDICTED future state.
20    """
21    if not API_KEY or not ENDPOINT:
22        print("   ⚠️ Physics Engine Error: Missing Azure OpenAI credentials")
23        return {"predicted_health": 50.0, "risk_warning": "No API Key configured"}
24
25    # Initialize Azure OpenAI Client
26    llm = AzureChatOpenAI(
27        azure_endpoint=ENDPOINT,
28        api_key=API_KEY,
29        api_version=API_VERSION,
30        deployment_name=DEPLOYMENT_NAME,
31        temperature=0.1,  # Low temp for consistent physics logic
32        max_tokens=1024,
33    )
34
35    system_prompt = (
36        "You are a Hydroponic Physics Engine.\n"
37        "Your task is to simulate the biological and chemical reaction of a plant ecosystem "
38        "to a specific set of environmental changes over a 4-hour period.\n"
39        "BE REALISTIC. If parameters are extreme (e.g. pH < 4, Temp > 35C), predict drastic health drops."
40    )
41
42    user_prompt = (
43        f"Current Sensor Readings: {json.dumps(current_state)}\n"
44        f"Proposed Action/Targets: {json.dumps(proposed_action)}\n\n"
45        f"TASK:\n"
46        f"1. Predict the Plant Health (0-100) after 4 hours.\n"
47        f"2. Identify any specific risks (Root Rot, Tip Burn, Lockout, Shock).\n"
48        f"OUTPUT JSON ONLY: {{ 'predicted_health': float, 'risk_warning': string }}"
49    )
50
51    try:
52        # Invoke Azure OpenAI
53        response = llm.invoke(
54            [SystemMessage(content=system_prompt), HumanMessage(content=user_prompt)]
55        )
56
57        # Clean and Parse JSON
58        content = response.content.replace("```json", "").replace("```", "").strip()
59        result = json.loads(content)
60
61        # Default fallback keys if the LLM misses them
62        return {
63            "predicted_health": result.get("predicted_health", 50.0),
64            "risk_warning": result.get("risk_warning", "Unknown Risk"),
65        }
66
67    except Exception as e:
68        print(f"   ⚠️ Physics Engine Error: {e}")
69        return {
70            "predicted_health": 70.0,
71            "risk_warning": "Simulation Connection Failed",
72        }