Harshil Patel commited on
Commit
e0d574f
·
1 Parent(s): 7ec791b

Implement agent manager

Browse files
Files changed (1) hide show
  1. src/agent_manager.py +203 -0
src/agent_manager.py ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, Type, Any, Optional
3
+ import os
4
+ import json
5
+ import ollama
6
+ from src.singleton import singleton
7
+
8
+ class Agent(ABC):
9
+
10
+ def __init__(self, agent_name: str, base_model: str, system_prompt: str):
11
+ self.agent_name = agent_name
12
+ self.base_model = base_model
13
+ self.system_prompt = system_prompt
14
+ self.create_model()
15
+
16
+ @abstractmethod
17
+ def create_model(self) -> None:
18
+ """Create and Initialize agent"""
19
+ pass
20
+
21
+ @abstractmethod
22
+ def ask_agent(self, prompt: str) -> str:
23
+ """ask agent a question"""
24
+ pass
25
+
26
+ @abstractmethod
27
+ def delete_agent(self) ->None:
28
+ """delete agent"""
29
+ pass
30
+
31
+ class OllamaAgent(Agent):
32
+
33
+ def create_model(self):
34
+ ollama_response = ollama.create(
35
+ model = self.agent_name,
36
+ from_ = self.base_model,
37
+ system = self.system_prompt,
38
+ stream = False
39
+ )
40
+
41
+ def ask_agent(self, prompt):
42
+ print(f"Asked Agent {self.agent_name} a question")
43
+ agent_response = ollama.chat(
44
+ model=self.agent_name,
45
+ messages=[{"role": "user", "content": prompt}],
46
+ )
47
+ print(f"Agent {self.agent_name} answered with {agent_response.message.content}")
48
+ return agent_response.message.content
49
+
50
+ def delete_agent(self):
51
+ ollama.delete(self.agent_name)
52
+
53
+ @singleton
54
+ class AgentManager():
55
+
56
+ def __init__(self):
57
+ self._agents = {}
58
+ self._agent_types ={
59
+ ollama: OllamaAgent
60
+ }
61
+
62
+ self._load_agents()
63
+
64
+ def create_agent(self, agent_name: str, base_model: str, system_prompt: str, description: str = "", create_cost: float = 0, invoke_cost: float = 0,
65
+ **additional_params) -> Agent:
66
+
67
+ if agent_name in self._agents:
68
+ raise ValueError(f"Agent {agent_name} already exists")
69
+
70
+ agent_type = self._get_agent_type(base_model)
71
+ agent_class = self._agent_types.get(agent_type)
72
+
73
+ if not agent_class:
74
+ raise ValueError(f"Unsupported base model {base_model}")
75
+
76
+ # create agent
77
+ self._agents[agent_name] = agent_class(agent_name, base_model, system_prompt)
78
+
79
+ #save agent to file
80
+ self._save_agent(
81
+ agent_name,
82
+ base_model,
83
+ system_prompt,
84
+ description=description,
85
+ create_cost=create_cost,
86
+ invoke_cost=invoke_cost,
87
+ **additional_params # For any future parameters we might want to add
88
+ )
89
+
90
+ return self._agents[agent_name]
91
+
92
+ def get_agent(self, agent_name: str) -> Agent:
93
+ """Get existing agent by name"""
94
+ if agent_name in self._agents:
95
+ raise ValueError(f"Agent {agent_name} already exists")
96
+ return self._agents[agent_name]
97
+
98
+ def list_agents(self) -> dict:
99
+ """Return agent information (name, description, costs)"""
100
+ try:
101
+ if os.path.exists("./models/models.json"):
102
+ with open("./models/models.json", "r", encoding="utf8") as f:
103
+ full_models = json.loads(f.read())
104
+
105
+ # Create a simplified version with only the description and costs
106
+ simplified_agents = {}
107
+ for name, data in full_models.items():
108
+ simplified_agents[name] = {
109
+ "description": data.get("description", ""),
110
+ "create_cost": data.get("create_cost", 0),
111
+ "invoke_cost": data.get("invoke_cost", 0)
112
+ }
113
+ return simplified_agents
114
+ else:
115
+ return {}
116
+ except Exception as e:
117
+ print(f"Error listing agents: {e}")
118
+ return {}
119
+
120
+ def delete_agent(self, agent_name: str) -> None:
121
+ if agent_name not in self._agents:
122
+ raise ValueError(f"Agent {agent_name} does not exist")
123
+ self._agents[agent_name].delete_agent()
124
+
125
+ del self._agents[agent_name]
126
+ try:
127
+ if os.path.exists("./models/models.json"):
128
+ with open("./models/models.json", "r", encoding="utf8") as f:
129
+ models = json.loads(f.read())
130
+
131
+ del models[agent_name]
132
+ with open("./models/models.json", "w", encoding="utf8") as f:
133
+ f.write(json.dumps(models, indent=4))
134
+ except Exception as e:
135
+ print(f"Error deleting agent: {e}")
136
+
137
+
138
+ def _save_agent(self, agent_name: str, base_model: str, system_prompt: str,
139
+ description: str = "", create_cost: float = 0, invoke_cost: float = 0,
140
+ **additional_params) -> None:
141
+ """Save a single agent to the models.json file"""
142
+ try:
143
+ # Ensure the directory exists
144
+ os.makedirs("./models", exist_ok=True)
145
+
146
+ # Read existing models file or create empty dict if it doesn't exist
147
+ try:
148
+ with open("./models/models.json", "r", encoding="utf8") as f:
149
+ models = json.loads(f.read())
150
+ except (FileNotFoundError, json.JSONDecodeError):
151
+ models = {}
152
+
153
+ # Update the models dict with the new agent
154
+ models[agent_name] = {
155
+ "base_model": base_model,
156
+ "description": description,
157
+ "system_prompt": system_prompt,
158
+ "create_cost": create_cost,
159
+ "invoke_cost": invoke_cost,
160
+ }
161
+
162
+ # Add any additional parameters that were passed
163
+ for key, value in additional_params.items():
164
+ models[agent_name][key] = value
165
+
166
+ # Write the updated models back to the file
167
+ with open("./models/models.json", "w", encoding="utf8") as f:
168
+ f.write(json.dumps(models, indent=4))
169
+
170
+ except Exception as e:
171
+ print(f"Error saving agent {agent_name}: {e}")
172
+
173
+ def _get_agent_type(self, base_model)->str:
174
+ if base_model.startswith("ollama"):
175
+ return "ollama"
176
+ else:
177
+ return "unknown"
178
+
179
+ def _load_agents(self) -> None:
180
+ """Load agent configurations from disk"""
181
+ try:
182
+ if not os.path.exists("./models/models.json"):
183
+ return
184
+
185
+ with open("./models/models.json", "r", encoding="utf8") as f:
186
+ models = json.loads(f.read())
187
+
188
+ for name, data in models.items():
189
+ base_model = data["base_model"]
190
+ system_prompt = data["system_prompt"]
191
+
192
+ model_type = self._get_model_type(base_model)
193
+ manager_class = self._model_types.get(model_type)
194
+
195
+ if manager_class:
196
+ # Create the agent with the appropriate manager class
197
+ self._agents[name] = manager_class(
198
+ name,
199
+ base_model,
200
+ system_prompt
201
+ )
202
+ except Exception as e:
203
+ print(f"Error loading agents: {e}")