commit dd30683d3b09874f38339d55caae18532d8a8b62
parent 2edd4a2d45914d24a8dfbc3cee91bce978064525
Author: arnav0103 <66205884+arnav0103@users.noreply.github.com>
Date: Wed, 25 Mar 2026 21:56:10 +0530
Added azure openai
Diffstat:
11 files changed, 119 insertions(+), 69 deletions(-)
diff --git a/.env.example b/.env.example
@@ -0,0 +1,13 @@
+# Azure OpenAI Configuration
+AZURE_OPENAI_API_KEY=your_api_key_here
+AZURE_OPENAI_ENDPOINT=https://demeter-final.openai.azure.com/
+AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4.1
+AZURE_OPENAI_API_VERSION=2024-12-01-preview
+
+# Qdrant Configuration (if using memory service)
+QDRANT_URL=http://localhost:6333
+QDRANT_API_KEY=your_qdrant_key_here
+
+# Simulator Configuration
+SIMULATOR_STATE_URL=http://localhost:3001/simulation/state
+SIMULATOR_ACTION_URL=http://localhost:3001/simulation/action
diff --git a/agent/memory.py b/agent/memory.py
@@ -1,7 +1,7 @@
import logging
from mem0 import Memory
import os
-import time # <--- IMPORT ADDED
+import time
from dotenv import load_dotenv
from qdrant_client import QdrantClient, models
@@ -15,6 +15,12 @@ class FarmMemory:
# 1. Setup Collection
self._setup_collection()
+ # --- NEW CODE: Map Azure variables for mem0 natively ---
+ os.environ["LLM_AZURE_OPENAI_API_KEY"] = os.getenv("AZURE_OPENAI_API_KEY", "")
+ os.environ["LLM_AZURE_DEPLOYMENT"] = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
+ os.environ["LLM_AZURE_ENDPOINT"] = os.getenv("AZURE_OPENAI_ENDPOINT", "")
+ os.environ["LLM_AZURE_API_VERSION"] = os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
+
# 2. Initialize Mem0
config = {
"vector_store": {
@@ -27,11 +33,8 @@ class FarmMemory:
}
},
"llm": {
- "provider": "openai",
+ "provider": "azure_openai",
"config": {
- "model": "qwen/qwen3-32b",
- "api_key": os.getenv("GROQ_API_KEY"),
- "openai_base_url": "https://api.groq.com/openai/v1",
"max_tokens": 1500
}
},
@@ -80,10 +83,7 @@ class FarmMemory:
# 1. Use get_all() to fetch raw history (bypassing vector similarity)
# This ensures we get the *actual* latest events, not just "relevant" ones
history = self.memory.get_all(user_id=crop_id)
- # print(f" -> Raw history count: {history}")
-
-
# 2. Extract List from response
results = []
if isinstance(history, dict):
@@ -100,15 +100,12 @@ class FarmMemory:
# 4. Slice the top N (Past 3)
recent_results = results[:limit]
-
- # print(f" -> Extracted entries: {results}")
# 5. Format the output
formatted_lines = []
for item in recent_results:
# Handle different mem0 versions where content might be in 'memory' or 'text'
text = item.get("memory", item.get("text", str(item)))
- # print(f" -> Processing entry: {text}")
# Optional: Add a timestamp to the output for verification
timestamp = item.get("created_at", "")
@@ -121,7 +118,6 @@ class FarmMemory:
clean_output = "\n".join(formatted_lines)
- # print(f" -> Formatted Output:\n{clean_output}")
return clean_output
except Exception as e:
diff --git a/agent/sub_agents/Explainer.py b/agent/sub_agents/Explainer.py
@@ -1,8 +1,18 @@
import json
+import os
+from openai import AzureOpenAI
+from dotenv import load_dotenv
+
+load_dotenv()
class ExplainerAgent:
- def __init__(self, llm_client):
- self.llm = llm_client
+ def __init__(self):
+ self.llm = AzureOpenAI(
+ api_key=os.getenv("AZURE_OPENAI_API_KEY"),
+ api_version=os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview"),
+ azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
+ )
+ self.deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
def explain(self, current_fmu, similar_fmus, sub_agent_reports, final_decision):
"""
@@ -36,7 +46,7 @@ class ExplainerAgent:
try:
response = self.llm.chat.completions.create(
- model="qwen/qwen3-32b",
+ model=self.deployment_name,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": context}
diff --git a/agent/sub_agents/Researcher.py b/agent/sub_agents/Researcher.py
@@ -2,7 +2,7 @@ import uuid
from qdrant_client import models
from fastembed import TextEmbedding
from Qdrant.Client import client
-from groq import Groq
+from openai import AzureOpenAI
import os
from dotenv import load_dotenv
@@ -11,7 +11,12 @@ load_dotenv()
class ResearcherAgent:
def __init__(self):
self.client = client
- self.llm = Groq(api_key=os.getenv("GROQ_API_KEY"))
+ self.llm = AzureOpenAI(
+ api_key=os.getenv("AZURE_OPENAI_API_KEY"),
+ api_version=os.getenv("AZURE_OPENAI_API_VERSION", "2024-12-01-preview"),
+ azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT")
+ )
+ self.deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
self.collection = "Knowledge_Base"
# FastEmbed is lightweight and runs locally on CPU
self.encoder = TextEmbedding(model_name="BAAI/bge-small-en-v1.5")
diff --git a/agent/sub_agents/Supervisor.py b/agent/sub_agents/Supervisor.py
@@ -1,7 +1,7 @@
import os
import json
import numpy as np
-from langchain_openai import ChatOpenAI
+from langchain_openai import AzureChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
from langgraph.graph import StateGraph, END
from agent.tools.actuation import convert_targets_to_actions
@@ -10,6 +10,9 @@ from agent.Marl.bandit import ContextualBandit
from agent.Marl.strategies import STRATEGIES, NUM_ACTIONS
from agent.Qdrant.Store import store_fmu
from agent.sub_agents.water_and_atmospheric_dependencies.physics_engine import predict_outcome
+from dotenv import load_dotenv
+
+load_dotenv()
# --- NEW TOOLS DEFINITION ---
def check_cross_domain_conflicts(atmos, water):
@@ -58,18 +61,22 @@ class SupervisorState(TypedDict):
final_decision: str # "APPROVE" or "REJECT"
critique: str # Feedback for sub-agents if Rejected
-API_KEY = os.environ.get("GROQ_API_KEY")
+API_KEY = os.environ.get("AZURE_OPENAI_API_KEY")
+ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
+DEPLOYMENT_NAME = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
+API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
class SupervisorAgent:
def __init__(self, researcher_agent=None):
self.name = "Supervisor"
self.bandit = ContextualBandit(n_actions=NUM_ACTIONS, feature_dim=519)
- if API_KEY:
- self.model = ChatOpenAI(
- base_url="https://api.groq.com/openai/v1",
+ if API_KEY and ENDPOINT:
+ self.model = AzureChatOpenAI(
+ azure_endpoint=ENDPOINT,
api_key=API_KEY,
- model="qwen/qwen3-32b",
+ api_version=API_VERSION,
+ deployment_name=DEPLOYMENT_NAME,
temperature=0.0 # Zero temp for strict judging
)
diff --git a/agent/sub_agents/atmospheric_agent.py b/agent/sub_agents/atmospheric_agent.py
@@ -1,5 +1,5 @@
import os
-from langchain_openai import ChatOpenAI
+from langchain_openai import AzureChatOpenAI
from langgraph.graph import StateGraph, END
# Graph State & Nodes
@@ -11,9 +11,10 @@ from agent.sub_agents.water_and_atmospheric_dependencies.retrieval import ask_hi
from agent.sub_agents.water_and_atmospheric_dependencies.tools import calculate_vpd, web_search
# Configuration
-API_KEY = os.environ.get("GROQ_API_KEY")
-
-MODEL_ID = "qwen/qwen3-32b"
+API_KEY = os.environ.get("AZURE_OPENAI_API_KEY")
+ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
+DEPLOYMENT_NAME = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
+API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
ATMOS_PROMPT = """
You are the Atmospheric Specialist for a Hydroponic Farm.
@@ -38,14 +39,15 @@ class AtmosphericAgent:
def __init__(self):
self.name = "Atmospheric Agent"
- if not API_KEY:
- print(f"[{self.name}] ⚠️ No API Key found.")
+ if not API_KEY or not ENDPOINT:
+ print(f"[{self.name}] ⚠️ No Azure OpenAI credentials found.")
self.model = None
else:
- llm = ChatOpenAI(
- base_url="https://api.groq.com/openai/v1",
+ llm = AzureChatOpenAI(
+ azure_endpoint=ENDPOINT,
api_key=API_KEY,
- model="qwen/qwen3-32b",
+ api_version=API_VERSION,
+ deployment_name=DEPLOYMENT_NAME,
temperature=0.2,
model_kwargs={"tool_choice": "auto", "parallel_tool_calls": False}
)
diff --git a/agent/sub_agents/base_agent.py b/agent/sub_agents/base_agent.py
@@ -1,43 +1,45 @@
import os
-from openai import OpenAI
+from openai import AzureOpenAI
from dotenv import load_dotenv
load_dotenv()
-# --- GROQ CONFIGURATION ---
-# Common Groq Models: "llama3-70b-8192", "mixtral-8x7b-32768"
-MODEL_ID = "qwen/qwen3-32b"
-API_KEY = os.environ.get("GROQ_API_KEY")
+# --- AZURE OPENAI CONFIGURATION ---
+DEPLOYMENT_NAME = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
+API_KEY = os.environ.get("AZURE_OPENAI_API_KEY")
+ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
+API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
class BaseReasoningAgent:
def __init__(self, name):
self.name = name
- if not API_KEY:
- print(f"[{self.name}] ⚠️ WARNING: GROQ_API_KEY not found in environment.")
+ if not API_KEY or not ENDPOINT:
+ print(f"[{self.name}] ⚠️ WARNING: Azure OpenAI credentials not found in environment.")
self.client = None
else:
try:
- self.client = OpenAI(
- base_url="https://api.groq.com/openai/v1",
- api_key=os.getenv("GROQ_API_KEY")
+ self.client = AzureOpenAI(
+ api_key=API_KEY,
+ api_version=API_VERSION,
+ azure_endpoint=ENDPOINT
)
except Exception as e:
- print(f"[{self.name}] ⚠️ Groq Connection Error: {e}")
+ print(f"[{self.name}] ⚠️ Azure OpenAI Connection Error: {e}")
self.client = None
def _call_llm(self, prompt):
"""
- Helper method to send prompts to Groq Cloud.
+ Helper method to send prompts to Azure OpenAI.
"""
if not self.client:
return "Error: LLM Client not connected (Check API Key)."
print("Other Prompt:\n", prompt)
try:
- # Groq/OpenAI Chat Completion Structure
+ # Azure OpenAI Chat Completion Structure
response = self.client.chat.completions.create(
- model=MODEL_ID,
+ model=DEPLOYMENT_NAME,
messages=[
{"role": "system", "content": f"You are the {self.name} Agent for a high-tech hydroponic farm."},
{"role": "user", "content": prompt}
diff --git a/agent/sub_agents/judge_agent.py b/agent/sub_agents/judge_agent.py
@@ -5,10 +5,13 @@ import re
import tempfile
from typing import TypedDict, Dict, Any, Optional
-from langchain_openai import ChatOpenAI
+from langchain_openai import AzureChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
from langgraph.graph import StateGraph, END
from qdrant_client import models
+from dotenv import load_dotenv
+
+load_dotenv()
from Sentinel.fmu import FMU
from agent.sub_agents.base_agent import BaseReasoningAgent
@@ -46,10 +49,11 @@ class JudgeAgent(BaseReasoningAgent):
self.qdrant = client
# LLM for the "Deliberation" phase
- self.llm = ChatOpenAI(
- base_url="https://api.groq.com/openai/v1",
- api_key=os.environ.get("GROQ_API_KEY"),
- model="qwen/qwen3-32b",
+ self.llm = AzureChatOpenAI(
+ azure_endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
+ api_key=os.environ.get("AZURE_OPENAI_API_KEY"),
+ api_version=os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview"),
+ deployment_name=os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1"),
temperature=0.1
)
diff --git a/agent/sub_agents/water_agent.py b/agent/sub_agents/water_agent.py
@@ -1,5 +1,5 @@
import os
-from langchain_openai import ChatOpenAI
+from langchain_openai import AzureChatOpenAI
from langgraph.graph import StateGraph, END
# Graph State & Nodes
@@ -11,7 +11,10 @@ from agent.sub_agents.water_and_atmospheric_dependencies.retrieval import ask_hi
from agent.sub_agents.water_and_atmospheric_dependencies.tools import check_ph_safety, web_search
# Configuration
-API_KEY = os.environ.get("GROQ_API_KEY")
+API_KEY = os.environ.get("AZURE_OPENAI_API_KEY")
+ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
+DEPLOYMENT_NAME = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
+API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
# 🟢 UPDATE 1: Mention visual data availability in the prompt
WATER_PROMPT = """
@@ -40,14 +43,15 @@ class WaterAgent:
self.name = "Water Agent"
# 1. Initialize Model
- if not API_KEY:
- print(f"[{self.name}] ⚠️ No API Key found.")
+ if not API_KEY or not ENDPOINT:
+ print(f"[{self.name}] ⚠️ No Azure OpenAI credentials found.")
self.model = None
else:
- llm = ChatOpenAI(
- base_url="https://api.groq.com/openai/v1",
+ llm = AzureChatOpenAI(
+ azure_endpoint=ENDPOINT,
api_key=API_KEY,
- model="qwen/qwen3-32b", # Keeping consistent model
+ api_version=API_VERSION,
+ deployment_name=DEPLOYMENT_NAME,
temperature=0.2,
model_kwargs={"tool_choice": "auto", "parallel_tool_calls": False}
)
diff --git a/agent/sub_agents/water_and_atmospheric_dependencies/physics_engine.py b/agent/sub_agents/water_and_atmospheric_dependencies/physics_engine.py
@@ -1,27 +1,33 @@
import os
import json
-from langchain_openai import ChatOpenAI
+from langchain_openai import AzureChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
+from dotenv import load_dotenv
+
+load_dotenv()
# Configuration
-API_KEY = os.environ.get("GROQ_API_KEY")
-MODEL_ID = "qwen/qwen3-32b" # Using the latest supported Groq model
+API_KEY = os.environ.get("AZURE_OPENAI_API_KEY")
+ENDPOINT = os.environ.get("AZURE_OPENAI_ENDPOINT")
+DEPLOYMENT_NAME = os.environ.get("AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4.1")
+API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")
def predict_outcome(current_state: dict, proposed_action: dict) -> dict:
"""
- Stateless 'What-If' Engine using Groq (LLM-based Physics).
+ Stateless 'What-If' Engine using Azure OpenAI (LLM-based Physics).
Takes a snapshot and an action, returns the PREDICTED future state.
"""
- if not API_KEY:
- print(" ⚠️ Physics Engine Error: Missing GROQ_API_KEY")
+ if not API_KEY or not ENDPOINT:
+ print(" ⚠️ Physics Engine Error: Missing Azure OpenAI credentials")
return {"predicted_health": 50.0, "risk_warning": "No API Key configured"}
- # Initialize Groq Client
- llm = ChatOpenAI(
- base_url="https://api.groq.com/openai/v1",
+ # Initialize Azure OpenAI Client
+ llm = AzureChatOpenAI(
+ azure_endpoint=ENDPOINT,
api_key=API_KEY,
- model=MODEL_ID,
+ api_version=API_VERSION,
+ deployment_name=DEPLOYMENT_NAME,
temperature=0.1, # Low temp for consistent physics logic
max_tokens=1024,
)
@@ -43,7 +49,7 @@ def predict_outcome(current_state: dict, proposed_action: dict) -> dict:
)
try:
- # Invoke Groq
+ # Invoke Azure OpenAI
response = llm.invoke(
[SystemMessage(content=system_prompt), HumanMessage(content=user_prompt)]
)
diff --git a/simulator/requirements.txt b/simulator/requirements.txt
@@ -7,3 +7,4 @@ Pillow
python-dotenv
azure-identity
azure-digitaltwins-core
+openai