demeter

Autonomous Hydroponic Intelligence

agent/main_agent.py (3955B)


  1import sys
  2import os
  3import requests
  4import time
  5from dotenv import load_dotenv
  6
  7# Load env from root
  8current_dir = os.path.dirname(os.path.abspath(__file__))
  9env_path = os.path.join(current_dir, "..", ".env")
 10load_dotenv(env_path)
 11
 12current_dir = os.path.dirname(os.path.abspath(__file__))
 13sys.path.append(current_dir)
 14
 15from sub_agents.fetching_agent import FetchingAgent
 16from sub_agents.judge_agent import JudgeAgent
 17from sub_agents.atmospheric_agent import AtmosphericAgent
 18from sub_agents.water_agent import WaterAgent
 19from sub_agents.Researcher import ResearcherAgent
 20from sub_agents.Supervisor import SupervisorAgent
 21
 22SIMULATOR_ACTION_URL = os.getenv(
 23    "SIMULATOR_ACTION_URL", "http://localhost:8001/simulation/action"
 24)
 25
 26
 27def main():
 28    print("🚀 Initializing Demeter Orchestrator...")
 29
 30    try:
 31        fetcher = FetchingAgent()
 32        judge = JudgeAgent()
 33        researcher = ResearcherAgent()
 34        atmos_agent = AtmosphericAgent()
 35        water_agent = WaterAgent()
 36        supervisor = SupervisorAgent(researcher_agent=researcher)
 37        print("✅ Agents Online.")
 38    except Exception as e:
 39        print(f"❌ Init Error: {e}")
 40        return
 41
 42    while True:
 43        print("\n" + "=" * 50)
 44        print("⏱️  STARTING NEW CYCLE")
 45        print("=" * 50)
 46
 47        crops_data = fetcher.fetch_and_process()
 48        if not crops_data:
 49            print("⚠️ No crops found. Waiting...")
 50            time.sleep(10)
 51            continue
 52
 53        batch_actions = []
 54
 55        for crop_data in crops_data:
 56            fmu = crop_data["fmu"]
 57            sensor_snapshot = crop_data["sensor_snapshot"]
 58            history = crop_data["history"]
 59            image_b64 = crop_data["image_b64"]
 60            crop_id = crop_data["crop_id"]
 61
 62            print(f"\n🌱 --- PROCESSING CROP: {crop_id} ---")
 63
 64            time.sleep(1)
 65            judge_result = judge.review_previous_cycle(fmu, image_b64)
 66
 67            # 🧠 BANDIT LEARNING: Update model based on previous cycle outcome
 68            if judge_result:
 69                supervisor.learn_from_outcome(fmu, judge_result)
 70
 71            time.sleep(1)
 72            strat_name, strat_instr, action_idx = supervisor.get_strategic_goal(fmu)
 73            print(f"\n🎰 BANDIT STRATEGY: {strat_name}")
 74
 75            crop = fmu.metadata.get("crop", "unknown")
 76            stage = fmu.metadata.get("stage", "unknown")
 77            query = f"optimal hydroponic conditions for {crop} in {stage} stage"
 78
 79            time.sleep(1)
 80            research_context = researcher.search(query)
 81
 82            print("\n🧠 Agents Planning...")
 83
 84            time.sleep(1)
 85            atmos_plan = atmos_agent.reason(
 86                sensors=sensor_snapshot,
 87                research=research_context,
 88                strategy=strat_instr,
 89                history=history,
 90                image_b64=image_b64,
 91            )
 92
 93            time.sleep(1)
 94            water_plan = water_agent.reason(
 95                sensors=sensor_snapshot,
 96                research=research_context,
 97                strategy=strat_instr,
 98                history=history,
 99                image_b64=image_b64,
100            )
101
102            print("\n👮 Supervisor Finalizing...")
103            final_action = supervisor.synthesize_plan(
104                atmos_plan,
105                water_plan,
106                fmu,
107                history,
108                strategy_info=(strat_name, strat_instr, action_idx),
109            )
110
111            batch_actions.append({"crop_id": crop_id, "action": final_action})
112
113            print(f"\n✅ Final Action for {crop_id}: {final_action}")
114        try:
115            requests.post(SIMULATOR_ACTION_URL, json=batch_actions)
116
117            print(f"\n✅ Batch sent to Simulator ({len(batch_actions)} actions).")
118        except Exception as e:
119            print(f"\n❌ Connection Error: {e}")
120
121        # print("\nzzz Sleeping 2 minutes...")
122        # time.sleep(120)
123
124
125if __name__ == "__main__":
126    main()