demeter
Autonomous Hydroponic Intelligencegit clone https://github.com/maydayv7/demeter
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()