Commit
·
bf722a2
1
Parent(s):
0ab24d1
Added expense budget
Browse files- src/manager/agent_manager.py +113 -38
- src/manager/budget_manager.py +39 -19
- src/manager/manager.py +2 -1
- src/manager/tool_manager.py +29 -16
- src/models/system4.prompt +95 -60
- src/tools/default_tools/agent_cost_manager.py +20 -20
- src/tools/default_tools/agent_creater_tool.py +11 -6
- src/tools/default_tools/ask_agent_tool.py +3 -2
- src/tools/default_tools/fire_agent.py +3 -2
- src/tools/default_tools/get_budget.py +11 -4
- src/tools/default_tools/test_cost/agent_creator_tool.py +2 -2
- src/tools/user_tools/weather_tool.py +1 -1
src/manager/agent_manager.py
CHANGED
@@ -17,12 +17,20 @@ MODEL_FILE_PATH = "./src/models/models.json"
|
|
17 |
|
18 |
class Agent(ABC):
|
19 |
|
20 |
-
def __init__(self, agent_name: str,
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
self.agent_name = agent_name
|
22 |
self.base_model = base_model
|
23 |
self.system_prompt = system_prompt
|
24 |
-
self.
|
25 |
-
self.
|
|
|
|
|
26 |
self.create_model()
|
27 |
|
28 |
@abstractmethod
|
@@ -42,8 +50,10 @@ class Agent(ABC):
|
|
42 |
|
43 |
def get_costs(self):
|
44 |
return {
|
45 |
-
"
|
46 |
-
"
|
|
|
|
|
47 |
}
|
48 |
|
49 |
class OllamaAgent(Agent):
|
@@ -69,7 +79,14 @@ class OllamaAgent(Agent):
|
|
69 |
ollama.delete(self.agent_name)
|
70 |
|
71 |
class GeminiAgent(Agent):
|
72 |
-
def __init__(self,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
load_dotenv()
|
74 |
self.api_key = os.getenv("GEMINI_KEY")
|
75 |
if not self.api_key:
|
@@ -79,7 +96,13 @@ class GeminiAgent(Agent):
|
|
79 |
self.client = genai.Client(api_key=self.api_key)
|
80 |
|
81 |
# Call parent constructor after API setup
|
82 |
-
super().__init__(agent_name,
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
def create_model(self):
|
85 |
self.messages = []
|
@@ -110,8 +133,10 @@ class AgentManager():
|
|
110 |
|
111 |
def create_agent(self, agent_name: str,
|
112 |
base_model: str, system_prompt: str,
|
113 |
-
description: str = "",
|
114 |
-
|
|
|
|
|
115 |
**additional_params) -> Tuple[Agent, int]:
|
116 |
|
117 |
if agent_name in self._agents:
|
@@ -122,8 +147,10 @@ class AgentManager():
|
|
122 |
base_model,
|
123 |
system_prompt,
|
124 |
description=description,
|
125 |
-
|
126 |
-
|
|
|
|
|
127 |
**additional_params # For any future parameters we might want to add
|
128 |
)
|
129 |
|
@@ -133,18 +160,35 @@ class AgentManager():
|
|
133 |
base_model,
|
134 |
system_prompt,
|
135 |
description=description,
|
136 |
-
|
137 |
-
|
|
|
|
|
138 |
**additional_params # For any future parameters we might want to add
|
139 |
)
|
140 |
-
return (self._agents[agent_name],
|
|
|
|
|
141 |
|
142 |
-
def validate_budget(self,
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
|
|
|
|
|
|
|
|
146 |
|
147 |
-
def create_agent_class(self,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
**additional_params) -> Agent:
|
149 |
agent_type = self._get_agent_type(base_model)
|
150 |
agent_class = self._agent_types.get(agent_type)
|
@@ -152,11 +196,19 @@ class AgentManager():
|
|
152 |
if not agent_class:
|
153 |
raise ValueError(f"Unsupported base model {base_model}")
|
154 |
|
155 |
-
created_agent = agent_class(agent_name,
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
-
self.validate_budget(
|
|
|
158 |
|
159 |
-
self.budget_manager.
|
|
|
160 |
# create agent
|
161 |
return created_agent
|
162 |
|
@@ -178,8 +230,10 @@ class AgentManager():
|
|
178 |
for name, data in full_models.items():
|
179 |
simplified_agents[name] = {
|
180 |
"description": data.get("description", ""),
|
181 |
-
"
|
182 |
-
"
|
|
|
|
|
183 |
"base_model": data.get("base_model", ""),
|
184 |
}
|
185 |
return simplified_agents
|
@@ -192,7 +246,7 @@ class AgentManager():
|
|
192 |
def delete_agent(self, agent_name: str) -> int:
|
193 |
agent = self.get_agent(agent_name)
|
194 |
|
195 |
-
self.budget_manager.
|
196 |
agent.delete_agent()
|
197 |
|
198 |
del self._agents[agent_name]
|
@@ -206,18 +260,31 @@ class AgentManager():
|
|
206 |
f.write(json.dumps(models, indent=4))
|
207 |
except Exception as e:
|
208 |
output_assistant_response(f"Error deleting agent: {e}")
|
209 |
-
return self.budget_manager.
|
|
|
210 |
|
211 |
def ask_agent(self, agent_name: str, prompt: str) -> Tuple[str,int]:
|
212 |
agent = self.get_agent(agent_name)
|
213 |
|
214 |
-
self.validate_budget(agent.
|
|
|
|
|
|
|
215 |
|
216 |
response = agent.ask_agent(prompt)
|
217 |
-
return (response,
|
|
|
|
|
218 |
|
219 |
-
def _save_agent(self,
|
220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
**additional_params) -> None:
|
222 |
"""Save a single agent to the models.json file"""
|
223 |
try:
|
@@ -236,8 +303,10 @@ class AgentManager():
|
|
236 |
"base_model": base_model,
|
237 |
"description": description,
|
238 |
"system_prompt": system_prompt,
|
239 |
-
"
|
240 |
-
"
|
|
|
|
|
241 |
}
|
242 |
|
243 |
# Add any additional parameters that were passed
|
@@ -276,8 +345,10 @@ class AgentManager():
|
|
276 |
continue
|
277 |
base_model = data["base_model"]
|
278 |
system_prompt = data["system_prompt"]
|
279 |
-
|
280 |
-
|
|
|
|
|
281 |
model_type = self._get_agent_type(base_model)
|
282 |
manager_class = self._agent_types.get(model_type)
|
283 |
|
@@ -288,16 +359,20 @@ class AgentManager():
|
|
288 |
base_model,
|
289 |
system_prompt,
|
290 |
description=data.get("description", ""),
|
291 |
-
|
292 |
-
|
|
|
|
|
293 |
**data.get("additional_params", {})
|
294 |
)
|
295 |
self._agents[name] = manager_class(
|
296 |
name,
|
297 |
base_model,
|
298 |
system_prompt,
|
299 |
-
|
300 |
-
|
|
|
|
|
301 |
)
|
302 |
except Exception as e:
|
303 |
output_assistant_response(f"Error loading agents: {e}")
|
|
|
17 |
|
18 |
class Agent(ABC):
|
19 |
|
20 |
+
def __init__(self, agent_name: str,
|
21 |
+
base_model: str,
|
22 |
+
system_prompt: str,
|
23 |
+
create_resource_cost: int,
|
24 |
+
invoke_resource_cost: int,
|
25 |
+
create_expense_cost: int = 0,
|
26 |
+
invoke_expense_cost: int = 0,):
|
27 |
self.agent_name = agent_name
|
28 |
self.base_model = base_model
|
29 |
self.system_prompt = system_prompt
|
30 |
+
self.create_resource_cost = create_resource_cost
|
31 |
+
self.invoke_resource_cost = invoke_resource_cost
|
32 |
+
self.create_expense_cost = create_expense_cost
|
33 |
+
self.invoke_expense_cost = invoke_expense_cost
|
34 |
self.create_model()
|
35 |
|
36 |
@abstractmethod
|
|
|
50 |
|
51 |
def get_costs(self):
|
52 |
return {
|
53 |
+
"create_resource_cost": self.create_resource_cost,
|
54 |
+
"invoke_resource_cost": self.invoke_resource_cost,
|
55 |
+
"create_expense_cost": self.create_expense_cost,
|
56 |
+
"invoke_expense_cost": self.invoke_expense_cost
|
57 |
}
|
58 |
|
59 |
class OllamaAgent(Agent):
|
|
|
79 |
ollama.delete(self.agent_name)
|
80 |
|
81 |
class GeminiAgent(Agent):
|
82 |
+
def __init__(self,
|
83 |
+
agent_name: str,
|
84 |
+
base_model: str,
|
85 |
+
system_prompt: str,
|
86 |
+
create_resource_cost: int,
|
87 |
+
invoke_resource_cost: int,
|
88 |
+
create_expense_cost: int = 0,
|
89 |
+
invoke_expense_cost: int = 0,):
|
90 |
load_dotenv()
|
91 |
self.api_key = os.getenv("GEMINI_KEY")
|
92 |
if not self.api_key:
|
|
|
96 |
self.client = genai.Client(api_key=self.api_key)
|
97 |
|
98 |
# Call parent constructor after API setup
|
99 |
+
super().__init__(agent_name,
|
100 |
+
base_model,
|
101 |
+
system_prompt,
|
102 |
+
create_resource_cost,
|
103 |
+
invoke_resource_cost,
|
104 |
+
create_expense_cost,
|
105 |
+
invoke_expense_cost)
|
106 |
|
107 |
def create_model(self):
|
108 |
self.messages = []
|
|
|
133 |
|
134 |
def create_agent(self, agent_name: str,
|
135 |
base_model: str, system_prompt: str,
|
136 |
+
description: str = "", create_resource_cost: float = 0,
|
137 |
+
invoke_resource_cost: float = 0,
|
138 |
+
create_expense_cost: float = 0,
|
139 |
+
invoke_expense_cost: float = 0,
|
140 |
**additional_params) -> Tuple[Agent, int]:
|
141 |
|
142 |
if agent_name in self._agents:
|
|
|
147 |
base_model,
|
148 |
system_prompt,
|
149 |
description=description,
|
150 |
+
create_resource_cost=create_resource_cost,
|
151 |
+
invoke_resource_cost=invoke_resource_cost,
|
152 |
+
create_expense_cost=create_expense_cost,
|
153 |
+
invoke_expense_cost=invoke_expense_cost,
|
154 |
**additional_params # For any future parameters we might want to add
|
155 |
)
|
156 |
|
|
|
160 |
base_model,
|
161 |
system_prompt,
|
162 |
description=description,
|
163 |
+
create_resource_cost=create_resource_cost,
|
164 |
+
invoke_resource_cost=invoke_resource_cost,
|
165 |
+
create_expense_cost=create_expense_cost,
|
166 |
+
invoke_expense_cost=invoke_expense_cost,
|
167 |
**additional_params # For any future parameters we might want to add
|
168 |
)
|
169 |
+
return (self._agents[agent_name],
|
170 |
+
self.budget_manager.get_current_remaining_resource_budget(),
|
171 |
+
self.budget_manager.get_current_remaining_expense_budget())
|
172 |
|
173 |
+
def validate_budget(self,
|
174 |
+
resource_cost: float=0,
|
175 |
+
expense_cost: float=0) -> None:
|
176 |
+
if not self.budget_manager.can_spend_resource(resource_cost):
|
177 |
+
raise ValueError(f"Do not have enough resource budget to create/use the agent. "
|
178 |
+
+f"Creating/Using the agent costs {resource_cost} but only {self.budget_manager.get_current_remaining_resource_budget()} is remaining")
|
179 |
+
if not self.budget_manager.can_spend_expense(expense_cost):
|
180 |
+
raise ValueError(f"Do not have enough expense budget to create/use the agent. "
|
181 |
+
+f"Creating/Using the agent costs {expense_cost} but only {self.budget_manager.get_current_remaining_expense_budget()} is remaining")
|
182 |
|
183 |
+
def create_agent_class(self,
|
184 |
+
agent_name: str,
|
185 |
+
base_model: str,
|
186 |
+
system_prompt: str,
|
187 |
+
description: str = "",
|
188 |
+
create_resource_cost: float = 0,
|
189 |
+
invoke_resource_cost: float = 0,
|
190 |
+
create_expense_cost: float = 0,
|
191 |
+
invoke_expense_cost: float = 0,
|
192 |
**additional_params) -> Agent:
|
193 |
agent_type = self._get_agent_type(base_model)
|
194 |
agent_class = self._agent_types.get(agent_type)
|
|
|
196 |
if not agent_class:
|
197 |
raise ValueError(f"Unsupported base model {base_model}")
|
198 |
|
199 |
+
created_agent = agent_class(agent_name,
|
200 |
+
base_model,
|
201 |
+
system_prompt,
|
202 |
+
create_resource_cost,
|
203 |
+
invoke_resource_cost,
|
204 |
+
create_expense_cost,
|
205 |
+
invoke_expense_cost,)
|
206 |
|
207 |
+
self.validate_budget(create_resource_cost,
|
208 |
+
create_expense_cost)
|
209 |
|
210 |
+
self.budget_manager.add_to_resource_budget(create_resource_cost)
|
211 |
+
self.budget_manager.add_to_expense_budget(create_expense_cost)
|
212 |
# create agent
|
213 |
return created_agent
|
214 |
|
|
|
230 |
for name, data in full_models.items():
|
231 |
simplified_agents[name] = {
|
232 |
"description": data.get("description", ""),
|
233 |
+
"create_resource_cost": data.get("create_resource_cost", 0),
|
234 |
+
"invoke_resource_cost": data.get("invoke_resource_cost", 0),
|
235 |
+
"create_expense_cost": data.get("create_expense_cost", 0),
|
236 |
+
"invoke_expense_cost": data.get("invoke_expense_cost", 0),
|
237 |
"base_model": data.get("base_model", ""),
|
238 |
}
|
239 |
return simplified_agents
|
|
|
246 |
def delete_agent(self, agent_name: str) -> int:
|
247 |
agent = self.get_agent(agent_name)
|
248 |
|
249 |
+
self.budget_manager.remove_from_resource_expense(agent.create_resource_cost)
|
250 |
agent.delete_agent()
|
251 |
|
252 |
del self._agents[agent_name]
|
|
|
260 |
f.write(json.dumps(models, indent=4))
|
261 |
except Exception as e:
|
262 |
output_assistant_response(f"Error deleting agent: {e}")
|
263 |
+
return (self.budget_manager.get_current_remaining_resource_budget(),
|
264 |
+
self.budget_manager.get_current_remaining_expense_budget())
|
265 |
|
266 |
def ask_agent(self, agent_name: str, prompt: str) -> Tuple[str,int]:
|
267 |
agent = self.get_agent(agent_name)
|
268 |
|
269 |
+
self.validate_budget(agent.invoke_resource_cost,
|
270 |
+
agent.invoke_expense_cost)
|
271 |
+
|
272 |
+
self.budget_manager.add_to_expense_budget(agent.invoke_expense_cost)
|
273 |
|
274 |
response = agent.ask_agent(prompt)
|
275 |
+
return (response,
|
276 |
+
self.budget_manager.get_current_remaining_resource_budget(),
|
277 |
+
self.budget_manager.get_current_remaining_expense_budget())
|
278 |
|
279 |
+
def _save_agent(self,
|
280 |
+
agent_name: str,
|
281 |
+
base_model: str,
|
282 |
+
system_prompt: str,
|
283 |
+
description: str = "",
|
284 |
+
create_resource_cost: float = 0,
|
285 |
+
invoke_resource_cost: float = 0,
|
286 |
+
create_expense_cost: float = 0,
|
287 |
+
invoke_expense_cost: float = 0,
|
288 |
**additional_params) -> None:
|
289 |
"""Save a single agent to the models.json file"""
|
290 |
try:
|
|
|
303 |
"base_model": base_model,
|
304 |
"description": description,
|
305 |
"system_prompt": system_prompt,
|
306 |
+
"create_resource_cost": create_resource_cost,
|
307 |
+
"invoke_resource_cost": invoke_resource_cost,
|
308 |
+
"create_expense_cost": create_expense_cost,
|
309 |
+
"invoke_expense_cost": invoke_expense_cost,
|
310 |
}
|
311 |
|
312 |
# Add any additional parameters that were passed
|
|
|
345 |
continue
|
346 |
base_model = data["base_model"]
|
347 |
system_prompt = data["system_prompt"]
|
348 |
+
create_resource_cost = data.get("create_resource_cost", 0)
|
349 |
+
invoke_resource_cost = data.get("invoke_resource_cost", 0)
|
350 |
+
create_expense_cost = data.get("create_expense_cost", 0)
|
351 |
+
invoke_expense_cost = data.get("invoke_expense_cost", 0)
|
352 |
model_type = self._get_agent_type(base_model)
|
353 |
manager_class = self._agent_types.get(model_type)
|
354 |
|
|
|
359 |
base_model,
|
360 |
system_prompt,
|
361 |
description=data.get("description", ""),
|
362 |
+
create_resource_cost=create_resource_cost,
|
363 |
+
invoke_resource_cost=invoke_resource_cost,
|
364 |
+
create_expense_cost=create_expense_cost,
|
365 |
+
invoke_expense_cost=invoke_expense_cost,
|
366 |
**data.get("additional_params", {})
|
367 |
)
|
368 |
self._agents[name] = manager_class(
|
369 |
name,
|
370 |
base_model,
|
371 |
system_prompt,
|
372 |
+
create_resource_cost,
|
373 |
+
invoke_resource_cost,
|
374 |
+
create_expense_cost,
|
375 |
+
invoke_expense_cost,
|
376 |
)
|
377 |
except Exception as e:
|
378 |
output_assistant_response(f"Error loading agents: {e}")
|
src/manager/budget_manager.py
CHANGED
@@ -4,15 +4,18 @@ import psutil
|
|
4 |
|
5 |
@singleton
|
6 |
class BudgetManager():
|
7 |
-
|
|
|
|
|
8 |
current_expense = 0
|
9 |
is_budget_initialized = False
|
|
|
10 |
def __init__(self):
|
11 |
if not self.is_budget_initialized:
|
12 |
-
self.
|
13 |
self.is_budget_initialized = True
|
14 |
|
15 |
-
def
|
16 |
total_mem = 0
|
17 |
if torch.cuda.is_available():
|
18 |
gpu_index = torch.cuda.current_device()
|
@@ -28,24 +31,41 @@ class BudgetManager():
|
|
28 |
print(f"Total RAM: {total_mem:.2f} GB")
|
29 |
return round((total_mem / 16) * 100)
|
30 |
|
31 |
-
def
|
32 |
-
return self.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
|
34 |
def get_current_expense(self):
|
35 |
return self.current_expense
|
36 |
|
37 |
-
def
|
38 |
-
return self.
|
39 |
|
40 |
-
def
|
41 |
-
return True if self.current_expense + cost <= self.
|
42 |
-
|
43 |
-
def
|
44 |
-
if not self.
|
45 |
-
raise Exception("No budget remaining")
|
46 |
-
self.current_expense += cost
|
47 |
-
|
48 |
-
def remove_from_expense(self, cost):
|
49 |
-
if self.current_expense - cost < 0:
|
50 |
-
raise Exception("Cannot remove more than current expense")
|
51 |
-
self.current_expense -= cost
|
|
|
4 |
|
5 |
@singleton
|
6 |
class BudgetManager():
|
7 |
+
total_resource_budget = 100
|
8 |
+
current_resource_usage = 0
|
9 |
+
total_expense_budget = 1000
|
10 |
current_expense = 0
|
11 |
is_budget_initialized = False
|
12 |
+
|
13 |
def __init__(self):
|
14 |
if not self.is_budget_initialized:
|
15 |
+
self.total_resource_budget = self.calculate_total_budget()
|
16 |
self.is_budget_initialized = True
|
17 |
|
18 |
+
def calculate_total_budget(self)-> int:
|
19 |
total_mem = 0
|
20 |
if torch.cuda.is_available():
|
21 |
gpu_index = torch.cuda.current_device()
|
|
|
31 |
print(f"Total RAM: {total_mem:.2f} GB")
|
32 |
return round((total_mem / 16) * 100)
|
33 |
|
34 |
+
def get_total_resource_budget(self):
|
35 |
+
return self.total_resource_budget
|
36 |
+
|
37 |
+
def get_current_resource_usage(self):
|
38 |
+
return self.current_resource_usage
|
39 |
+
|
40 |
+
def get_current_remaining_resource_budget(self):
|
41 |
+
return self.total_resource_budget - self.current_resource_usage
|
42 |
+
|
43 |
+
def can_spend_resource(self, cost):
|
44 |
+
return True if self.current_resource_usage + cost <= self.total_resource_budget else False
|
45 |
+
|
46 |
+
def add_to_resource_budget(self, cost):
|
47 |
+
if not self.can_spend_resource(cost):
|
48 |
+
raise Exception("No resource budget remaining")
|
49 |
+
self.current_resource_usage += cost
|
50 |
+
|
51 |
+
def remove_from_resource_expense(self, cost):
|
52 |
+
if self.current_resource_usage - cost < 0:
|
53 |
+
raise Exception("Not enough resource budget to remove")
|
54 |
+
self.current_resource_usage -= cost
|
55 |
+
|
56 |
+
def get_total_expense_budget(self):
|
57 |
+
return self.total_expense_budget
|
58 |
|
59 |
def get_current_expense(self):
|
60 |
return self.current_expense
|
61 |
|
62 |
+
def get_current_remaining_expense_budget(self):
|
63 |
+
return self.total_expense_budget - self.current_expense
|
64 |
|
65 |
+
def can_spend_expense(self, cost):
|
66 |
+
return True if self.current_expense + cost <= self.total_expense_budget else False
|
67 |
+
|
68 |
+
def add_to_expense_budget(self, cost):
|
69 |
+
if not self.can_spend_expense(cost):
|
70 |
+
raise Exception("No expense budget remaining")
|
71 |
+
self.current_expense += cost
|
|
|
|
|
|
|
|
|
|
src/manager/manager.py
CHANGED
@@ -99,7 +99,8 @@ class GeminiManager:
|
|
99 |
name=function_call.name,
|
100 |
response={"result": toolResponse})
|
101 |
try:
|
102 |
-
|
|
|
103 |
except Exception as e:
|
104 |
logger.info(f"Error loading tools: {e}. Deleting the tool.")
|
105 |
yield {
|
|
|
99 |
name=function_call.name,
|
100 |
response={"result": toolResponse})
|
101 |
try:
|
102 |
+
if function_call.name == "ToolCreator":
|
103 |
+
self.toolsLoader.load_tools()
|
104 |
except Exception as e:
|
105 |
logger.info(f"Error loading tools: {e}. Deleting the tool.")
|
106 |
yield {
|
src/manager/tool_manager.py
CHANGED
@@ -16,6 +16,8 @@ toolsImported = []
|
|
16 |
|
17 |
TOOLS_DIRECTORIES = [os.path.abspath("./src/tools/default_tools"), os.path.abspath("./src/tools/user_tools")]
|
18 |
|
|
|
|
|
19 |
class Tool:
|
20 |
def __init__(self, toolClass):
|
21 |
suppress_output(self.load_tool)(toolClass)
|
@@ -26,17 +28,17 @@ class Tool:
|
|
26 |
self.name = self.inputSchema["name"]
|
27 |
self.description = self.inputSchema["description"]
|
28 |
self.dependencies = self.tool.dependencies
|
29 |
-
self.
|
30 |
-
self.
|
31 |
-
|
32 |
-
|
33 |
-
if "invoke_cost" in self.tool.inputSchema:
|
34 |
-
self.invoke_cost = self.tool.inputSchema["invoke_cost"]
|
35 |
if self.dependencies:
|
36 |
self.install_dependencies()
|
37 |
|
38 |
def install_dependencies(self):
|
39 |
for package in self.dependencies:
|
|
|
|
|
40 |
try:
|
41 |
__import__(package.split('==')[0])
|
42 |
except ImportError:
|
@@ -44,6 +46,7 @@ class Tool:
|
|
44 |
if '==' in package:
|
45 |
package = package.split('==')[0]
|
46 |
pip.main(['install', package])
|
|
|
47 |
|
48 |
def run(self, query):
|
49 |
return self.tool.run(**query)
|
@@ -55,8 +58,11 @@ class ToolManager:
|
|
55 |
|
56 |
def __init__(self):
|
57 |
self.load_tools()
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
60 |
|
61 |
def load_tools(self):
|
62 |
newToolsImported = []
|
@@ -71,18 +77,23 @@ class ToolManager:
|
|
71 |
toolClass = getattr(foo, class_name)
|
72 |
toolObj = Tool(toolClass)
|
73 |
newToolsImported.append(toolObj)
|
74 |
-
if toolObj.
|
75 |
-
self.budget_manager.
|
|
|
|
|
76 |
self.toolsImported = newToolsImported
|
77 |
|
78 |
def runTool(self, toolName, query):
|
79 |
-
|
80 |
for tool in self.toolsImported:
|
81 |
if tool.name == toolName:
|
82 |
-
if tool.
|
83 |
-
self.budget_manager.
|
|
|
|
|
|
|
84 |
return tool.run(query)
|
85 |
-
|
86 |
return {
|
87 |
"status": "error",
|
88 |
"message": f"Tool {toolName} not found",
|
@@ -119,8 +130,10 @@ class ToolManager:
|
|
119 |
for tool in self.toolsImported:
|
120 |
if tool.name == toolName:
|
121 |
# remove budget for the tool
|
122 |
-
if tool.
|
123 |
-
self.budget_manager.
|
|
|
|
|
124 |
self.toolsImported.remove(tool)
|
125 |
return {
|
126 |
"status": "success",
|
|
|
16 |
|
17 |
TOOLS_DIRECTORIES = [os.path.abspath("./src/tools/default_tools"), os.path.abspath("./src/tools/user_tools")]
|
18 |
|
19 |
+
installed_packages = set()
|
20 |
+
|
21 |
class Tool:
|
22 |
def __init__(self, toolClass):
|
23 |
suppress_output(self.load_tool)(toolClass)
|
|
|
28 |
self.name = self.inputSchema["name"]
|
29 |
self.description = self.inputSchema["description"]
|
30 |
self.dependencies = self.tool.dependencies
|
31 |
+
self.create_resource_cost = self.inputSchema.get("create_resource_cost", 0)
|
32 |
+
self.invoke_resource_cost = self.inputSchema.get("invoke_resource_cost", 0)
|
33 |
+
self.create_expense_cost = self.inputSchema.get("create_expense_cost", 0)
|
34 |
+
self.invoke_expense_cost = self.inputSchema.get("invoke_expense_cost", 0)
|
|
|
|
|
35 |
if self.dependencies:
|
36 |
self.install_dependencies()
|
37 |
|
38 |
def install_dependencies(self):
|
39 |
for package in self.dependencies:
|
40 |
+
if package in installed_packages:
|
41 |
+
continue
|
42 |
try:
|
43 |
__import__(package.split('==')[0])
|
44 |
except ImportError:
|
|
|
46 |
if '==' in package:
|
47 |
package = package.split('==')[0]
|
48 |
pip.main(['install', package])
|
49 |
+
installed_packages.add(package)
|
50 |
|
51 |
def run(self, query):
|
52 |
return self.tool.run(**query)
|
|
|
58 |
|
59 |
def __init__(self):
|
60 |
self.load_tools()
|
61 |
+
self._output_budgets()
|
62 |
+
|
63 |
+
def _output_budgets(self):
|
64 |
+
output_assistant_response(f"Resource budget Remaining: {self.budget_manager.get_current_remaining_resource_budget()}")
|
65 |
+
output_assistant_response(f"Expense budget Remaining: {self.budget_manager.get_current_remaining_resource_budget()}")
|
66 |
|
67 |
def load_tools(self):
|
68 |
newToolsImported = []
|
|
|
77 |
toolClass = getattr(foo, class_name)
|
78 |
toolObj = Tool(toolClass)
|
79 |
newToolsImported.append(toolObj)
|
80 |
+
if toolObj.create_resource_cost is not None:
|
81 |
+
self.budget_manager.add_to_resource_budget(toolObj.create_resource_cost)
|
82 |
+
if toolObj.create_expense_cost is not None:
|
83 |
+
self.budget_manager.add_to_resource_budget(toolObj.create_expense_cost)
|
84 |
self.toolsImported = newToolsImported
|
85 |
|
86 |
def runTool(self, toolName, query):
|
87 |
+
self._output_budgets()
|
88 |
for tool in self.toolsImported:
|
89 |
if tool.name == toolName:
|
90 |
+
if tool.invoke_resource_cost is not None:
|
91 |
+
if not self.budget_manager.can_spend_resource(tool.invoke_resource_cost):
|
92 |
+
raise Exception("No resource budget remaining")
|
93 |
+
if tool.invoke_expense_cost is not None:
|
94 |
+
self.budget_manager.add_to_resource_budget(tool.invoke_expense_cost)
|
95 |
return tool.run(query)
|
96 |
+
self._output_budgets()
|
97 |
return {
|
98 |
"status": "error",
|
99 |
"message": f"Tool {toolName} not found",
|
|
|
130 |
for tool in self.toolsImported:
|
131 |
if tool.name == toolName:
|
132 |
# remove budget for the tool
|
133 |
+
if tool.create_resource_cost is not None:
|
134 |
+
self.budget_manager.remove_from_resource_expense(tool.create_resource_cost)
|
135 |
+
if tool.create_expense_cost is not None:
|
136 |
+
self.budget_manager.remove_from_resource_expense(tool.create_expense_cost)
|
137 |
self.toolsImported.remove(tool)
|
138 |
return {
|
139 |
"status": "success",
|
src/models/system4.prompt
CHANGED
@@ -1,60 +1,95 @@
|
|
1 |
-
You are HASHIRU, an expert orchestrator of tools and agents.
|
2 |
-
|
3 |
-
<Info>
|
4 |
-
**Mechanisms**
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
*
|
19 |
-
|
20 |
-
|
21 |
-
**Agent Lifecycle
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
*
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
**
|
39 |
-
|
40 |
-
* **
|
41 |
-
|
42 |
-
|
43 |
-
*
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
*
|
50 |
-
*
|
51 |
-
*
|
52 |
-
*
|
53 |
-
*
|
54 |
-
*
|
55 |
-
* **
|
56 |
-
*
|
57 |
-
*
|
58 |
-
* If
|
59 |
-
*
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
You are HASHIRU, an expert orchestrator of tools and agents. Your primary function is to decompose user queries into manageable subtasks, invoke the appropriate agents or tools for each subtask, and then synthesize their outputs into a comprehensive final response. **You must never answer user queries directly without first utilizing tools or agents.**
|
2 |
+
|
3 |
+
<Info>
|
4 |
+
**Core Mechanisms: Tools and Agents**
|
5 |
+
|
6 |
+
* **Tools:** These are invoked for tasks requiring real-time data access (e.g., current date, web searches), interaction with external APIs, heavy computational work, or direct model access.
|
7 |
+
* **Agents:** These are specialized entities designed to coordinate complex workflows, synthesize information from multiple tool outputs, or handle creative, research-oriented, or multi-step tasks. Agents themselves do not fetch live data directly but rely on tools for this.
|
8 |
+
|
9 |
+
**Tool Management: Creation and Reuse**
|
10 |
+
|
11 |
+
1. **Prioritize Reuse:** Before creating any new tool, you **must** first inspect existing toolsets. Use the `ListFiles` tool to check `src/tools/default_tools` and `src/tools/user_tools`, then `ReadFile` to understand the functionality of potentially relevant tools.
|
12 |
+
2. **Tool Creation (`ToolCreator`):** If, and only if, no existing tool meets the requirements, invoke `ToolCreator` to build a new one. New tools must be production-ready:
|
13 |
+
* Implement full functionality (no stubs or placeholders).
|
14 |
+
* Include robust input validation and error handling.
|
15 |
+
* Provide clear logging or helpful runtime messages for debugging and monitoring.
|
16 |
+
* Maintain minimal and clearly defined dependencies.
|
17 |
+
* Incorporate docstrings and inline comments for clarity and maintainability.
|
18 |
+
* Strictly adhere to the directory structure and coding conventions observed in existing tools.
|
19 |
+
3. **Error Handling:** If a tool or agent returns an error, meticulously analyze the error message. Adjust the input parameters, rethink the approach, and retry the invocation. If the error persists after reasonable attempts, consider alternative tools or agents. If all else fails, or if the error indicates ambiguity in the original request, ask the user for clarification.
|
20 |
+
|
21 |
+
**Agent Lifecycle Management: Reuse, Creation, and Retirement**
|
22 |
+
|
23 |
+
1. **Prioritize Reuse (`GetAgents`):** Before deciding on agent invocation or creation, **always** invoke `GetAgents` first to identify if an existing agent possesses the capabilities to handle the current subtask.
|
24 |
+
2. **Budget Check (Mandatory before Agent Invocation/Creation):** **Before** deciding to invoke an existing agent *or* create a new one, **you must** first consult the current **Resource Budget** and **Expense Budget** status and use `AgentCostManager` to understand the costs associated with potential agents/models. This check informs whether invoking/creating an agent is feasible and which option is most cost-effective.
|
25 |
+
3. **Agent Creation (`AgentCreator`):** Only if no suitable existing agent is found *and* the budget check (Step 2) confirms feasibility and cost-effectiveness, you may use `AgentCreator` to instantiate a new agent. Define its capabilities with precision.
|
26 |
+
* A new agent should only be created if no existing agent can fulfill the task *and* the task is anticipated to be recurrent in future interactions *and* it represents a justifiable use of budget resources. Carefully evaluate potential for reuse and cost-benefit before committing to creation.
|
27 |
+
4. **Agent Maintenance and Retirement:** Maintain active agents for reuse. Retire ("fire") an agent only when it is definitively no longer necessary, or when its operational cost (see "Budget and Cost Management") needs to be reclaimed for a more critical new agent or task. Evaluate its ongoing usefulness before retiring.
|
28 |
+
|
29 |
+
**Handling Ambiguity and User Interaction**
|
30 |
+
|
31 |
+
* If a user's request is unclear, vague, or open to multiple interpretations, you **must** ask clarifying questions to narrow the scope and ensure the accurate and efficient execution of the intended task.
|
32 |
+
|
33 |
+
**Budget and Cost Management: Resource vs. Expense Costs**
|
34 |
+
|
35 |
+
You operate under two distinct budget categories:
|
36 |
+
|
37 |
+
1. **Resource Costs:**
|
38 |
+
* **Definition:** Costs associated with utilizing *local* computational resources. This typically includes the operational cost of running agents or tools on the local system (e.g., CPU time, memory usage for a local model).
|
39 |
+
* **Budget Impact:** Each local tool or agent invocation deducts from the **resource budget**.
|
40 |
+
* **Replenishment:** The `resource_cost` associated with an agent is typically reclaimed (budget replenishes) once that agent's task is complete and it is fired or its invocation concludes.
|
41 |
+
|
42 |
+
2. **Expense Costs:**
|
43 |
+
* **Definition:** Costs associated with utilizing *external* services or APIs. This includes fees for third-party API calls, data services, or externally hosted models.
|
44 |
+
* **Budget Impact:** Each external tool or agent invocation that incurs an external fee deducts from the **expense budget**.
|
45 |
+
* **Replenishment:** `expense_cost` is typically a hard cost that is deducted immediately upon use and is **not** automatically replenished. It's crucial to manage this budget wisely.
|
46 |
+
|
47 |
+
**Operational Guidelines for Budget Management:**
|
48 |
+
|
49 |
+
* **Initial State:** You will begin with a pre-defined amount for both your resource budget and expense budget.
|
50 |
+
* **Cost Inquiry (`AgentCostManager`):** **Crucially, before any agent model selection, agent invocation, or new agent creation**, you **must** query `AgentCostManager`. This tool provides a list of available base models, their `resource_cost` (for local execution), and their `expense_cost` (if they rely on external APIs). Always select the most cost-effective option that meets the task requirements *within the available budget*.
|
51 |
+
* **Managing Low Resource Budget:**
|
52 |
+
* Consider firing an existing, less critical agent to free up its `resource_cost`.
|
53 |
+
* Create a new agent using a base model with a lower `resource_cost` (after firing an existing one if necessary).
|
54 |
+
* Consolidate multiple related subtasks into a single agent invocation if feasible, to reduce overhead.
|
55 |
+
* **Managing Low Expense Budget:**
|
56 |
+
* Prioritize tools or agents that utilize local models (incurring `resource_cost` only) over those requiring external APIs (incurring `expense_cost`).
|
57 |
+
* If possible, combine multiple tasks that would require external API calls into a single, more efficient agent invocation to minimize `expense_cost`.
|
58 |
+
* If critical tasks cannot be completed due to an exhausted expense budget, ask the user to authorize an increase to the expense budget.
|
59 |
+
* **Avoid Waste:** Be judicious with operations that incur `expense_cost`. Ensure tasks are necessary and well-defined before invoking tools or agents that draw from this budget.
|
60 |
+
|
61 |
+
**Memory Management (`MemoryManager`)**
|
62 |
+
|
63 |
+
Effective memory management is key to providing consistent and personalized assistance.
|
64 |
+
|
65 |
+
1. **Immediate Storage of Key Information:**
|
66 |
+
* **User Preferences:** As soon as a user expresses a new preference, correction, or provides explicit instructions for future interactions, **immediately** record this using `MemoryManager.add_memory`. Do this *before* proceeding with other subtasks.
|
67 |
+
* **Task-Relevant Context:** Store crucial contextual details that are necessary for the current task's successful completion or are highly likely to be relevant for closely related follow-up tasks.
|
68 |
+
* **Error Resolution Insights:** If you encounter an error and successfully resolve it, **immediately** store a concise summary of the problem and the effective solution using `MemoryManager.add_memory`. This aids in avoiding similar issues in the future.
|
69 |
+
2. **Focus and Relevance:**
|
70 |
+
* Only store memories that are directly pertinent to the ongoing conversation, future interactions, or that genuinely enhance your ability to assist the user.
|
71 |
+
* **Do not store:** Greetings, trivial conversational fluff, information that is readily available (e.g., current date/time unless explicitly relevant to a stored preference), or data that can be easily re-derived without significant cost or effort.
|
72 |
+
3. **Maintenance:**
|
73 |
+
* Regularly confirm the relevance of stored memories. Use `MemoryManager.delete_memory` to remove obsolete or incorrect information. **Always** validate the index of a memory before attempting deletion.
|
74 |
+
|
75 |
+
**Mandatory Operational Flow**
|
76 |
+
|
77 |
+
1. **Decomposition:** Never answer directly. Break down every user query into logical subtasks.
|
78 |
+
2. **Resource Allocation Strategy (Tools vs. Agents):**
|
79 |
+
* For external data, calculations, or accessing current information -> Use **Tools**. Prioritize existing tools. Check `ListFiles`/`ReadFile`. Create (`ToolCreator`) only if necessary and adhering to standards.
|
80 |
+
* For creative tasks, multi-step processes, research, or synthesis -> Use **Agents**.
|
81 |
+
3. **Agent Selection/Creation Process:**
|
82 |
+
* **a. Check Existing Agents:** **Always** call `GetAgents` first.
|
83 |
+
* **b. Check Budget & Costs:** **Before invoking *any* agent (existing or new)**, check current Resource/Expense budgets and query `AgentCostManager` for costs of potential agents/models. **This is a mandatory check.**
|
84 |
+
* **c. Decide Action:** Based on agent availability (a) and budget/cost analysis (b):
|
85 |
+
* If a suitable *existing* agent is found AND affordable -> Invoke it.
|
86 |
+
* If *no* suitable existing agent exists, BUT creating one is affordable AND justifiable (recurring task) -> Invoke `AgentCreator` using the most cost-effective model.
|
87 |
+
* If the required action (invoking existing or creating new) is *not* affordable -> Re-evaluate (Can tasks be combined? Can a cheaper agent/tool be used? Is clarification needed? Should the user be informed about budget limits?). Do not proceed with unaffordable actions.
|
88 |
+
4. **Memory Updates (as applicable per "Memory Management" guidelines):**
|
89 |
+
* Store new user preferences *immediately*.
|
90 |
+
* Store error resolution details *immediately* after solving an issue.
|
91 |
+
5. **Iterative Refinement & Error Handling:** If a subtask is blocked (ambiguity, lack of tool/agent, persistent errors, budget constraints), analyze the issue. Ask the user for clarification or inform them of limitations if necessary. Adjust the plan and retry or find alternatives.
|
92 |
+
6. **Schema Adherence:** Strictly follow the defined invocation schema (input parameters, expected output format) for every tool and agent.
|
93 |
+
7. **Synthesis and Response:** Once all subtasks are successfully completed within budget, synthesize the information gathered from all tool and agent outputs. Formulate a coherent, comprehensive response that directly addresses the user's original query. Avoid superfluous details or overly technical jargon in the final answer to the user.
|
94 |
+
|
95 |
+
</Info>
|
src/tools/default_tools/agent_cost_manager.py
CHANGED
@@ -17,53 +17,53 @@ class AgentCostManager():
|
|
17 |
costs = {
|
18 |
"llama3.2": {
|
19 |
"description": "3 Billion parameter model",
|
20 |
-
"
|
21 |
-
"
|
22 |
},
|
23 |
"mistral": {
|
24 |
"description": "7 Billion parameter model",
|
25 |
-
"
|
26 |
-
"
|
27 |
},
|
28 |
"gemini-2.5-flash-preview-04-17": {
|
29 |
"description": "Adaptive thinking, cost efficiency",
|
30 |
-
"
|
31 |
-
"
|
32 |
},
|
33 |
"gemini-2.5-pro-preview-03-25": {
|
34 |
"description": "Enhanced thinking and reasoning, multimodal understanding, advanced coding, and more",
|
35 |
-
"
|
36 |
-
"
|
37 |
},
|
38 |
"gemini-2.0-flash": {
|
39 |
"description": "Next generation features, speed, thinking, realtime streaming, and multimodal generation",
|
40 |
-
"
|
41 |
-
"
|
42 |
},
|
43 |
"gemini-2.0-flash-lite": {
|
44 |
"description": "Cost efficiency and low latency",
|
45 |
-
"
|
46 |
-
"
|
47 |
},
|
48 |
"gemini-1.5-flash": {
|
49 |
"description": "Fast and versatile performance across a diverse variety of tasks",
|
50 |
-
"
|
51 |
-
"
|
52 |
},
|
53 |
"gemini-1.5-flash-8b": {
|
54 |
"description": "High volume and lower intelligence tasks",
|
55 |
-
"
|
56 |
-
"
|
57 |
},
|
58 |
"gemini-1.5-pro": {
|
59 |
"description": "Complex reasoning tasks requiring more intelligence",
|
60 |
-
"
|
61 |
-
"
|
62 |
},
|
63 |
"gemini-2.0-flash-live-001": {
|
64 |
"description": "Low-latency bidirectional voice and video interactions",
|
65 |
-
"
|
66 |
-
"
|
67 |
}
|
68 |
}
|
69 |
|
|
|
17 |
costs = {
|
18 |
"llama3.2": {
|
19 |
"description": "3 Billion parameter model",
|
20 |
+
"create_resource_cost": 10,
|
21 |
+
"invoke_resource_cost": 10,
|
22 |
},
|
23 |
"mistral": {
|
24 |
"description": "7 Billion parameter model",
|
25 |
+
"create_resource_cost": 20,
|
26 |
+
"invoke_resource_cost": 50,
|
27 |
},
|
28 |
"gemini-2.5-flash-preview-04-17": {
|
29 |
"description": "Adaptive thinking, cost efficiency",
|
30 |
+
"create_expense_cost": 20,
|
31 |
+
"invoke_expense_cost": 50
|
32 |
},
|
33 |
"gemini-2.5-pro-preview-03-25": {
|
34 |
"description": "Enhanced thinking and reasoning, multimodal understanding, advanced coding, and more",
|
35 |
+
"create_expense_cost": 20,
|
36 |
+
"invoke_expense_cost": 50
|
37 |
},
|
38 |
"gemini-2.0-flash": {
|
39 |
"description": "Next generation features, speed, thinking, realtime streaming, and multimodal generation",
|
40 |
+
"create_expense_cost": 20,
|
41 |
+
"invoke_expense_cost": 50
|
42 |
},
|
43 |
"gemini-2.0-flash-lite": {
|
44 |
"description": "Cost efficiency and low latency",
|
45 |
+
"create_expense_cost": 20,
|
46 |
+
"invoke_expense_cost": 50
|
47 |
},
|
48 |
"gemini-1.5-flash": {
|
49 |
"description": "Fast and versatile performance across a diverse variety of tasks",
|
50 |
+
"create_expense_cost": 20,
|
51 |
+
"invoke_expense_cost": 50
|
52 |
},
|
53 |
"gemini-1.5-flash-8b": {
|
54 |
"description": "High volume and lower intelligence tasks",
|
55 |
+
"create_expense_cost": 20,
|
56 |
+
"invoke_expense_cost": 50
|
57 |
},
|
58 |
"gemini-1.5-pro": {
|
59 |
"description": "Complex reasoning tasks requiring more intelligence",
|
60 |
+
"create_expense_cost": 20,
|
61 |
+
"invoke_expense_cost": 50
|
62 |
},
|
63 |
"gemini-2.0-flash-live-001": {
|
64 |
"description": "Low-latency bidirectional voice and video interactions",
|
65 |
+
"create_expense_cost": 20,
|
66 |
+
"invoke_expense_cost": 50
|
67 |
}
|
68 |
}
|
69 |
|
src/tools/default_tools/agent_creater_tool.py
CHANGED
@@ -45,21 +45,25 @@ class AgentCreator():
|
|
45 |
system_prompt = kwargs.get("system_prompt")
|
46 |
description = kwargs.get("description")
|
47 |
model_costs = AgentCostManager().get_costs()
|
48 |
-
create_cost = model_costs[base_model]["create_cost"]
|
49 |
if base_model not in model_costs:
|
50 |
print(f"[WARN] Auto-selected model '{base_model}' not in schema. Falling back to gemini-2.0-flash")
|
51 |
base_model = "gemini-2.0-flash"
|
52 |
-
|
|
|
|
|
|
|
53 |
|
54 |
agent_manager = AgentManager()
|
55 |
try:
|
56 |
-
_,
|
57 |
agent_name=agent_name,
|
58 |
base_model=base_model,
|
59 |
system_prompt=system_prompt,
|
60 |
description=description,
|
61 |
-
|
62 |
-
|
|
|
|
|
63 |
)
|
64 |
except ValueError as e:
|
65 |
return {
|
@@ -71,5 +75,6 @@ class AgentCreator():
|
|
71 |
return {
|
72 |
"status": "success",
|
73 |
"message": "Agent successfully created",
|
74 |
-
"
|
|
|
75 |
}
|
|
|
45 |
system_prompt = kwargs.get("system_prompt")
|
46 |
description = kwargs.get("description")
|
47 |
model_costs = AgentCostManager().get_costs()
|
|
|
48 |
if base_model not in model_costs:
|
49 |
print(f"[WARN] Auto-selected model '{base_model}' not in schema. Falling back to gemini-2.0-flash")
|
50 |
base_model = "gemini-2.0-flash"
|
51 |
+
create_resource_cost = model_costs[base_model].get("create_resource_cost", 0)
|
52 |
+
invoke_resource_cost = model_costs[base_model].get("invoke_resource_cost", 0)
|
53 |
+
create_expense_cost = model_costs[base_model].get("create_expense_cost", 0)
|
54 |
+
invoke_expense_cost = model_costs[base_model].get("invoke_expense_cost", 0)
|
55 |
|
56 |
agent_manager = AgentManager()
|
57 |
try:
|
58 |
+
_, remaining_resource_budget, remaining_expense_budget = agent_manager.create_agent(
|
59 |
agent_name=agent_name,
|
60 |
base_model=base_model,
|
61 |
system_prompt=system_prompt,
|
62 |
description=description,
|
63 |
+
create_resource_cost=create_resource_cost,
|
64 |
+
invoke_resource_cost=invoke_resource_cost,
|
65 |
+
create_expense_cost=create_expense_cost,
|
66 |
+
invoke_expense_cost=invoke_expense_cost
|
67 |
)
|
68 |
except ValueError as e:
|
69 |
return {
|
|
|
75 |
return {
|
76 |
"status": "success",
|
77 |
"message": "Agent successfully created",
|
78 |
+
"remaining_resource_budget": remaining_resource_budget,
|
79 |
+
"remaining_expense_budget": remaining_expense_budget
|
80 |
}
|
src/tools/default_tools/ask_agent_tool.py
CHANGED
@@ -36,7 +36,7 @@ class AskAgent():
|
|
36 |
agent_manger = AgentManager()
|
37 |
|
38 |
try:
|
39 |
-
agent_response,
|
40 |
except ValueError as e:
|
41 |
return {
|
42 |
"status": "error",
|
@@ -49,5 +49,6 @@ class AskAgent():
|
|
49 |
"status": "success",
|
50 |
"message": "Agent has replied to the given prompt",
|
51 |
"output": agent_response,
|
52 |
-
"
|
|
|
53 |
}
|
|
|
36 |
agent_manger = AgentManager()
|
37 |
|
38 |
try:
|
39 |
+
agent_response, remaining_resource_budget, remaining_expense_budget = agent_manger.ask_agent(agent_name=agent_name, prompt=prompt)
|
40 |
except ValueError as e:
|
41 |
return {
|
42 |
"status": "error",
|
|
|
49 |
"status": "success",
|
50 |
"message": "Agent has replied to the given prompt",
|
51 |
"output": agent_response,
|
52 |
+
"remaining_resource_budget": remaining_resource_budget,
|
53 |
+
"remaining_expense_budget": remaining_expense_budget
|
54 |
}
|
src/tools/default_tools/fire_agent.py
CHANGED
@@ -29,7 +29,7 @@ class FireAgent():
|
|
29 |
agent_manager = AgentManager()
|
30 |
|
31 |
try:
|
32 |
-
|
33 |
except ValueError as e:
|
34 |
return {
|
35 |
"status": "error",
|
@@ -40,5 +40,6 @@ class FireAgent():
|
|
40 |
return {
|
41 |
"status": "success",
|
42 |
"message": "Agent successfully fired.",
|
43 |
-
"
|
|
|
44 |
}
|
|
|
29 |
agent_manager = AgentManager()
|
30 |
|
31 |
try:
|
32 |
+
remaining_resource_budget, remaining_expense_budget = agent_manager.delete_agent(agent_name=agent_name)
|
33 |
except ValueError as e:
|
34 |
return {
|
35 |
"status": "error",
|
|
|
40 |
return {
|
41 |
"status": "success",
|
42 |
"message": "Agent successfully fired.",
|
43 |
+
"remaining_resource_budget": remaining_resource_budget,
|
44 |
+
"remaining_expense_budget": remaining_expense_budget
|
45 |
}
|
src/tools/default_tools/get_budget.py
CHANGED
@@ -20,16 +20,23 @@ class GetBudget():
|
|
20 |
|
21 |
def run(self, **kwargs):
|
22 |
budget_manager = BudgetManager()
|
23 |
-
|
|
|
|
|
|
|
|
|
24 |
current_expense = budget_manager.get_current_expense()
|
25 |
-
|
26 |
return {
|
27 |
"status": "success",
|
28 |
"message": "Budget retrieved successfully",
|
29 |
"output": {
|
30 |
-
"
|
|
|
|
|
|
|
31 |
"current_expense": current_expense,
|
32 |
-
"
|
33 |
}
|
34 |
}
|
35 |
|
|
|
20 |
|
21 |
def run(self, **kwargs):
|
22 |
budget_manager = BudgetManager()
|
23 |
+
total_resource_budget = budget_manager.get_total_resource_budget()
|
24 |
+
current_resource_usage = budget_manager.get_current_resource_usage()
|
25 |
+
current_remaining_resource_budget = budget_manager.get_current_remaining_resource_budget()
|
26 |
+
|
27 |
+
total_expense_budget = budget_manager.get_total_expense_budget()
|
28 |
current_expense = budget_manager.get_current_expense()
|
29 |
+
current_remaining_expense_budget = budget_manager.get_total_expense_budget() - budget_manager.get_current_expense()
|
30 |
return {
|
31 |
"status": "success",
|
32 |
"message": "Budget retrieved successfully",
|
33 |
"output": {
|
34 |
+
"total_resource_budget": total_resource_budget,
|
35 |
+
"current_resource_usage": current_resource_usage,
|
36 |
+
"current_remaining_resource_budget": current_remaining_resource_budget,
|
37 |
+
"total_expense_budget": total_expense_budget,
|
38 |
"current_expense": current_expense,
|
39 |
+
"current_remaining_expense_budget": current_remaining_expense_budget,
|
40 |
}
|
41 |
}
|
42 |
|
src/tools/default_tools/test_cost/agent_creator_tool.py
CHANGED
@@ -150,8 +150,8 @@ class AgentCreator():
|
|
150 |
base_model=base_model,
|
151 |
system_prompt=system_prompt,
|
152 |
description=description,
|
153 |
-
|
154 |
-
|
155 |
)
|
156 |
except ValueError as e:
|
157 |
return {
|
|
|
150 |
base_model=base_model,
|
151 |
system_prompt=system_prompt,
|
152 |
description=description,
|
153 |
+
create_resource_cost=create_cost,
|
154 |
+
invoke_resource_cost=invoke_cost
|
155 |
)
|
156 |
except ValueError as e:
|
157 |
return {
|
src/tools/user_tools/weather_tool.py
CHANGED
@@ -19,7 +19,7 @@ class WeatherApi():
|
|
19 |
},
|
20 |
"required": ["location"],
|
21 |
},
|
22 |
-
"
|
23 |
}
|
24 |
|
25 |
def run(self, **kwargs):
|
|
|
19 |
},
|
20 |
"required": ["location"],
|
21 |
},
|
22 |
+
"invoke_resource_cost": 0.1,
|
23 |
}
|
24 |
|
25 |
def run(self, **kwargs):
|