versionhq 1.1.6.3__py3-none-any.whl → 1.1.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- versionhq/__init__.py +1 -1
- versionhq/_utils/usage_metrics.py +4 -12
- versionhq/agent/TEMPLATES/Backstory.py +7 -0
- versionhq/agent/TEMPLATES/__init__.py +0 -0
- versionhq/agent/model.py +95 -158
- versionhq/llm/model.py +1 -0
- versionhq/task/model.py +122 -150
- versionhq/team/model.py +70 -145
- versionhq/team/team_planner.py +2 -2
- versionhq/tool/model.py +6 -16
- {versionhq-1.1.6.3.dist-info → versionhq-1.1.7.0.dist-info}/METADATA +67 -45
- {versionhq-1.1.6.3.dist-info → versionhq-1.1.7.0.dist-info}/RECORD +15 -13
- {versionhq-1.1.6.3.dist-info → versionhq-1.1.7.0.dist-info}/LICENSE +0 -0
- {versionhq-1.1.6.3.dist-info → versionhq-1.1.7.0.dist-info}/WHEEL +0 -0
- {versionhq-1.1.6.3.dist-info → versionhq-1.1.7.0.dist-info}/top_level.txt +0 -0
versionhq/__init__.py
CHANGED
@@ -7,18 +7,10 @@ class UsageMetrics(BaseModel):
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
total_tokens: int = Field(default=0, description="Total number of tokens used")
|
10
|
-
prompt_tokens: int = Field(
|
11
|
-
|
12
|
-
)
|
13
|
-
|
14
|
-
default=0, description="Number of cached prompt tokens used"
|
15
|
-
)
|
16
|
-
completion_tokens: int = Field(
|
17
|
-
default=0, description="Number of tokens used in completions"
|
18
|
-
)
|
19
|
-
successful_requests: int = Field(
|
20
|
-
default=0, description="Number of successful requests made"
|
21
|
-
)
|
10
|
+
prompt_tokens: int = Field(default=0, description="Number of tokens used in prompts")
|
11
|
+
cached_prompt_tokens: int = Field(default=0, description="Number of cached prompt tokens used")
|
12
|
+
completion_tokens: int = Field(default=0, description="Number of tokens used in completions")
|
13
|
+
successful_requests: int = Field(default=0, description="Number of successful requests made")
|
22
14
|
|
23
15
|
def add_usage_metrics(self, usage_metrics: "UsageMetrics"):
|
24
16
|
"""
|
@@ -0,0 +1,7 @@
|
|
1
|
+
BACKSTORY="""You are a {role} with deep understanding of {knowledge} and highly skilled in {skillsets}.
|
2
|
+
You have access to call the RAG tools that can {rag_tool_overview}. By leveraging these tools, your knowledge, and skillsets, you can identify competitive strategies that have been proven effective to achieve the goal: {goal}. Take these into consideration, create innovative solutions.
|
3
|
+
"""
|
4
|
+
|
5
|
+
|
6
|
+
# developing strategies to improve cohort retention and customer lifetime value
|
7
|
+
# ingest past successful campaigns
|
File without changes
|
versionhq/agent/model.py
CHANGED
@@ -3,7 +3,8 @@ import uuid
|
|
3
3
|
from abc import ABC
|
4
4
|
from typing import Any, Dict, List, Optional, TypeVar, Union
|
5
5
|
from dotenv import load_dotenv
|
6
|
-
from pydantic import UUID4, BaseModel, Field, InstanceOf, PrivateAttr, model_validator
|
6
|
+
from pydantic import UUID4, BaseModel, Field, InstanceOf, PrivateAttr, model_validator, field_validator
|
7
|
+
from pydantic_core import PydanticCustomError
|
7
8
|
|
8
9
|
from versionhq._utils.cache_handler import CacheHandler
|
9
10
|
from versionhq._utils.logger import Logger
|
@@ -77,8 +78,9 @@ class TokenProcess:
|
|
77
78
|
# @track_agent()
|
78
79
|
class Agent(ABC, BaseModel):
|
79
80
|
"""
|
80
|
-
|
81
|
-
|
81
|
+
Agent class that run on LLM.
|
82
|
+
Agents execute tasks alone or in the team, using RAG tools and knowledge base if any.
|
83
|
+
Agents will prioritize team tasks when they belong to the team.
|
82
84
|
* (Temp) Comment out all the optional fields except for Team and LLM settings for convenience.
|
83
85
|
"""
|
84
86
|
|
@@ -90,96 +92,68 @@ class Agent(ABC, BaseModel):
|
|
90
92
|
_times_executed: int = PrivateAttr(default=0)
|
91
93
|
|
92
94
|
id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True)
|
93
|
-
agent_ops_agent_name: str = None
|
94
|
-
agent_ops_agent_id: str = None
|
95
95
|
role: str = Field(description="role of the agent - used in summary and logs")
|
96
|
-
goal: str = Field(
|
97
|
-
|
98
|
-
)
|
99
|
-
|
96
|
+
goal: str = Field(description="concise goal of the agent (details are set in the Task instance)")
|
97
|
+
backstory: Optional[str] = Field(default=None, description="system context passed to the LLM")
|
98
|
+
knowledge: Optional[str] = Field(default=None)
|
99
|
+
skillsets: Optional[List[str]] = Field(default_factory=list)
|
100
100
|
|
101
101
|
# tools
|
102
102
|
tools: Optional[List[Any]] = Field(default_factory=list)
|
103
|
-
tool_handler: InstanceOf[ToolHandler] = Field(
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
)
|
111
|
-
|
112
|
-
default=False,
|
113
|
-
description="Enable agent to delegate and ask questions among each other",
|
114
|
-
)
|
115
|
-
allow_code_execution: Optional[bool] = Field(
|
116
|
-
default=False, description="Enable code execution for the agent."
|
117
|
-
)
|
118
|
-
max_retry_limit: int = Field(
|
119
|
-
default=2,
|
120
|
-
description="max. number of retries for the task execution when an error occurs. cascaed to the `invoke` function",
|
121
|
-
)
|
122
|
-
max_iter: Optional[int] = Field(
|
123
|
-
default=25,
|
124
|
-
description="max. number of iterations for an agent to execute a task",
|
125
|
-
)
|
126
|
-
step_callback: Optional[Any] = Field(
|
127
|
-
default=None,
|
128
|
-
description="Callback to be executed after each step of the agent execution",
|
129
|
-
)
|
103
|
+
tool_handler: InstanceOf[ToolHandler] = Field(default=None, description="handle tool cache and last used tool")
|
104
|
+
|
105
|
+
# team, task execution rules
|
106
|
+
team: Optional[List[Any]] = Field(default=None, description="Team to which the agent belongs")
|
107
|
+
allow_delegation: bool = Field(default=False,description="Enable agent to delegate and ask questions among each other")
|
108
|
+
allow_code_execution: Optional[bool] = Field(default=False, description="Enable code execution for the agent.")
|
109
|
+
max_retry_limit: int = Field(default=2,description="max. number of retries for the task execution when an error occurs. cascaed to the `invoke` function")
|
110
|
+
max_iter: Optional[int] = Field(default=25,description="max. number of iterations for an agent to execute a task")
|
111
|
+
step_callback: Optional[Any] = Field(default=None,description="Callback to be executed after each step of the agent execution")
|
130
112
|
|
131
113
|
# llm settings cascaded to the LLM model
|
132
114
|
llm: Union[str, InstanceOf[LLM], Any] = Field(default=None)
|
133
115
|
function_calling_llm: Union[str, InstanceOf[LLM], Any] = Field(default=None)
|
134
|
-
respect_context_window: bool = Field(
|
135
|
-
|
136
|
-
|
137
|
-
)
|
138
|
-
max_tokens: Optional[int] = Field(
|
139
|
-
default=None, description="max. number of tokens for the agent's execution"
|
140
|
-
)
|
141
|
-
max_execution_time: Optional[int] = Field(
|
142
|
-
default=None, description="max. execution time for an agent to execute a task"
|
143
|
-
)
|
144
|
-
max_rpm: Optional[int] = Field(
|
145
|
-
default=None,
|
146
|
-
description="max. number of requests per minute for the agent execution",
|
147
|
-
)
|
116
|
+
respect_context_window: bool = Field(default=True,description="Keep messages under the context window size by summarizing content")
|
117
|
+
max_tokens: Optional[int] = Field(default=None, description="max. number of tokens for the agent's execution")
|
118
|
+
max_execution_time: Optional[int] = Field(default=None, description="max. execution time for an agent to execute a task")
|
119
|
+
max_rpm: Optional[int] = Field(default=None, description="max. number of requests per minute for the agent execution")
|
148
120
|
|
149
121
|
# prompt rules
|
150
|
-
use_system_prompt: Optional[bool] = Field(
|
151
|
-
|
152
|
-
)
|
153
|
-
|
154
|
-
default=None, description="System format for the agent."
|
155
|
-
)
|
156
|
-
prompt_template: Optional[str] = Field(
|
157
|
-
default=None, description="Prompt format for the agent."
|
158
|
-
)
|
159
|
-
response_template: Optional[str] = Field(
|
160
|
-
default=None, description="Response format for the agent."
|
161
|
-
)
|
122
|
+
use_system_prompt: Optional[bool] = Field(default=True, description="Use system prompt for the agent")
|
123
|
+
system_template: Optional[str] = Field(default=None, description="System format for the agent.")
|
124
|
+
prompt_template: Optional[str] = Field(default=None, description="Prompt format for the agent.")
|
125
|
+
response_template: Optional[str] = Field(default=None, description="Response format for the agent.")
|
162
126
|
|
163
127
|
# config, cache, error handling
|
164
|
-
config: Optional[Dict[str, Any]] = Field(
|
165
|
-
|
166
|
-
)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
)
|
173
|
-
formatting_errors: int = Field(
|
174
|
-
default=0, description="Number of formatting errors."
|
175
|
-
)
|
176
|
-
verbose: bool = Field(
|
177
|
-
default=True, description="Verbose mode for the Agent Execution"
|
178
|
-
)
|
128
|
+
config: Optional[Dict[str, Any]] = Field(default=None, exclude=True, description="Configuration for the agent")
|
129
|
+
cache: bool = Field(default=True, description="Whether the agent should use a cache for tool usage.")
|
130
|
+
cache_handler: InstanceOf[CacheHandler] = Field(default=None, description="An instance of the CacheHandler class.")
|
131
|
+
formatting_errors: int = Field(default=0, description="Number of formatting errors.")
|
132
|
+
verbose: bool = Field(default=True, description="Verbose mode for the Agent Execution")
|
133
|
+
agent_ops_agent_name: str = None
|
134
|
+
agent_ops_agent_id: str = None
|
135
|
+
|
179
136
|
|
180
137
|
def __repr__(self):
|
181
138
|
return f"Agent(role={self.role}, goal={self.goal}, backstory={self.backstory})"
|
182
139
|
|
140
|
+
|
141
|
+
@field_validator("id", mode="before")
|
142
|
+
@classmethod
|
143
|
+
def _deny_user_set_id(cls, v: Optional[UUID4]) -> None:
|
144
|
+
if v:
|
145
|
+
raise PydanticCustomError("may_not_set_field", "This field is not to be set by the user.", {})
|
146
|
+
|
147
|
+
|
148
|
+
@model_validator(mode="after")
|
149
|
+
def validate_required_fields(self):
|
150
|
+
required_fields = ["role", "goal"]
|
151
|
+
for field in required_fields:
|
152
|
+
if getattr(self, field) is None:
|
153
|
+
raise ValueError( f"{field} must be provided either directly or through config")
|
154
|
+
return self
|
155
|
+
|
156
|
+
|
183
157
|
@model_validator(mode="after")
|
184
158
|
def set_up_llm(self):
|
185
159
|
"""
|
@@ -189,61 +163,27 @@ class Agent(ABC, BaseModel):
|
|
189
163
|
"""
|
190
164
|
|
191
165
|
self.agent_ops_agent_name = self.role
|
192
|
-
unaccepted_attributes = [
|
193
|
-
|
194
|
-
"AWS_SECRET_ACCESS_KEY",
|
195
|
-
"AWS_REGION_NAME",
|
196
|
-
]
|
197
|
-
callbacks = (
|
198
|
-
[
|
199
|
-
self.step_callback,
|
200
|
-
]
|
201
|
-
if self.step_callback is not None
|
202
|
-
else []
|
203
|
-
)
|
166
|
+
unaccepted_attributes = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION_NAME"]
|
167
|
+
callbacks = ([self.step_callback,]if self.step_callback is not None else [])
|
204
168
|
|
205
169
|
if isinstance(self.llm, LLM):
|
206
170
|
self.llm.timeout = self.max_execution_time
|
207
|
-
self.llm.
|
208
|
-
self.llm.context_window_size = (
|
209
|
-
self.llm.get_context_window_size()
|
210
|
-
if self.respect_context_window == True
|
211
|
-
else DEFAULT_CONTEXT_WINDOW
|
212
|
-
)
|
171
|
+
self.llm.max_tokens = self.max_tokens
|
172
|
+
self.llm.context_window_size = (self.llm.get_context_window_size() if self.respect_context_window == True else DEFAULT_CONTEXT_WINDOW)
|
213
173
|
self.llm.callbacks = callbacks
|
214
174
|
|
215
|
-
elif isinstance(self.llm, str):
|
216
|
-
|
217
|
-
model=self.llm,
|
218
|
-
timeout=self.max_execution_time,
|
219
|
-
max_tokens=self.max_tokens,
|
220
|
-
callbacks=callbacks,
|
221
|
-
)
|
222
|
-
|
223
|
-
context_window_size = (
|
224
|
-
self.llm.get_context_window_size()
|
225
|
-
if self.respect_context_window == True
|
226
|
-
else DEFAULT_CONTEXT_WINDOW
|
227
|
-
)
|
228
|
-
self.llm.context_window_size = context_window_size
|
229
|
-
|
230
|
-
elif self.llm is None:
|
231
|
-
model_name = os.environ.get(
|
232
|
-
"LITELLM_MODEL_NAME", os.environ.get("MODEL", "gpt-4o-mini")
|
233
|
-
)
|
175
|
+
elif isinstance(self.llm, str) or self.llm is None:
|
176
|
+
model_name = os.environ.get("LITELLM_MODEL_NAME", os.environ.get("MODEL", "gpt-3.5-turbo"))
|
234
177
|
llm_params = {
|
235
|
-
"model": model_name,
|
178
|
+
"model": model_name if self.llm is None else self.llm,
|
236
179
|
"timeout": self.max_execution_time,
|
237
180
|
"max_tokens": self.max_tokens,
|
238
181
|
"callbacks": callbacks,
|
182
|
+
"api_key": os.environ.get("LITELLM_API_KEY", None),
|
183
|
+
"base_url": os.environ.get("OPENAI_API_BASE", os.environ.get("OPENAI_BASE_URL", None))
|
239
184
|
}
|
240
|
-
api_base = os.environ.get(
|
241
|
-
"OPENAI_API_BASE", os.environ.get("OPENAI_BASE_URL", None)
|
242
|
-
)
|
243
|
-
if api_base:
|
244
|
-
llm_params["base_url"] = api_base
|
245
185
|
|
246
|
-
set_provider = model_name.split("/")[0] if "/" in model_name else "openai"
|
186
|
+
set_provider = model_name.split("/")[0] if "/" in model_name else "openai" #! REFINEME
|
247
187
|
for provider, env_vars in LLM_VARS.items():
|
248
188
|
if provider == set_provider:
|
249
189
|
for env_var in env_vars:
|
@@ -252,17 +192,9 @@ class Agent(ABC, BaseModel):
|
|
252
192
|
if key_name and key_name not in unaccepted_attributes:
|
253
193
|
env_value = os.environ.get(key_name)
|
254
194
|
if env_value:
|
255
|
-
key_name = (
|
256
|
-
|
257
|
-
)
|
258
|
-
key_name = (
|
259
|
-
"api_base" if "API_BASE" in key_name else key_name
|
260
|
-
)
|
261
|
-
key_name = (
|
262
|
-
"api_version"
|
263
|
-
if "API_VERSION" in key_name
|
264
|
-
else key_name
|
265
|
-
)
|
195
|
+
key_name = ("api_key" if "API_KEY" in key_name else key_name)
|
196
|
+
key_name = ("api_base" if "API_BASE" in key_name else key_name)
|
197
|
+
key_name = ("api_version" if "API_VERSION" in key_name else key_name)
|
266
198
|
llm_params[key_name] = env_value
|
267
199
|
elif env_var.get("default", False):
|
268
200
|
for key, value in env_var.items():
|
@@ -270,34 +202,22 @@ class Agent(ABC, BaseModel):
|
|
270
202
|
if key in os.environ:
|
271
203
|
llm_params[key] = value
|
272
204
|
self.llm = LLM(**llm_params)
|
273
|
-
context_window_size = (
|
274
|
-
self.llm.get_context_window_size()
|
275
|
-
if self.respect_context_window == True
|
276
|
-
else DEFAULT_CONTEXT_WINDOW
|
277
|
-
)
|
205
|
+
context_window_size = (self.llm.get_context_window_size() if self.respect_context_window == True else DEFAULT_CONTEXT_WINDOW)
|
278
206
|
self.llm.context_window_size = context_window_size
|
279
207
|
|
280
208
|
else:
|
281
209
|
llm_params = {
|
282
|
-
"model": (
|
283
|
-
|
284
|
-
or getattr(self.llm, "deployment_name")
|
285
|
-
or str(self.llm)
|
286
|
-
),
|
287
|
-
"max_tokens": (
|
288
|
-
getattr(self.llm, "max_tokens") or self.max_tokens or 3000
|
289
|
-
),
|
210
|
+
"model": (getattr(self.llm, "model_name") or getattr(self.llm, "deployment_name") or str(self.llm)),
|
211
|
+
"max_tokens": (getattr(self.llm, "max_tokens") or self.max_tokens or 3000),
|
290
212
|
"timeout": getattr(self.llm, "timeout", self.max_execution_time),
|
291
213
|
"callbacks": getattr(self.llm, "callbacks") or callbacks,
|
292
214
|
"temperature": getattr(self.llm, "temperature", None),
|
293
215
|
"logprobs": getattr(self.llm, "logprobs", None),
|
294
|
-
"api_key": getattr(self.llm, "api_key", None),
|
216
|
+
"api_key": getattr(self.llm, "api_key", os.environ.get("LITELLM_API_KEY", None)),
|
295
217
|
"base_url": getattr(self.llm, "base_url", None),
|
296
218
|
"organization": getattr(self.llm, "organization", None),
|
297
219
|
}
|
298
|
-
llm_params = {
|
299
|
-
k: v for k, v in llm_params.items() if v is not None
|
300
|
-
} # factor out None values
|
220
|
+
llm_params = { k: v for k, v in llm_params.items() if v is not None }
|
301
221
|
self.llm = LLM(**llm_params)
|
302
222
|
|
303
223
|
"""
|
@@ -348,6 +268,7 @@ class Agent(ABC, BaseModel):
|
|
348
268
|
)
|
349
269
|
return self
|
350
270
|
|
271
|
+
|
351
272
|
@model_validator(mode="after")
|
352
273
|
def set_up_tools(self):
|
353
274
|
"""
|
@@ -371,13 +292,30 @@ class Agent(ABC, BaseModel):
|
|
371
292
|
|
372
293
|
return self
|
373
294
|
|
295
|
+
|
296
|
+
@model_validator(mode="after")
|
297
|
+
def set_up_backstory(self):
|
298
|
+
"""
|
299
|
+
Set up the backstory using a templated BACKSTORY when the backstory is None
|
300
|
+
"""
|
301
|
+
|
302
|
+
if self.backstory is None:
|
303
|
+
from versionhq.agent.TEMPLATES.Backstory import BACKSTORY
|
304
|
+
backstory = BACKSTORY.format(
|
305
|
+
role=self.role,
|
306
|
+
knowledge=self.knowledge if isinstance(self.knowledge, str) else None,
|
307
|
+
skillsets=", ".join([item for item in self.skillsets]),
|
308
|
+
rag_tool_overview=", ".join([item.name for item in self.tools]),
|
309
|
+
goal=self.goal,
|
310
|
+
)
|
311
|
+
self.backstory = backstory
|
312
|
+
|
313
|
+
return self
|
314
|
+
|
315
|
+
|
374
316
|
def invoke(
|
375
|
-
|
376
|
-
|
377
|
-
output_formats: List[TaskOutputFormat],
|
378
|
-
response_fields: List[ResponseField],
|
379
|
-
**kwargs,
|
380
|
-
) -> Dict[str, Any]:
|
317
|
+
self, prompts: str, output_formats: List[TaskOutputFormat], response_fields: List[ResponseField], **kwargs
|
318
|
+
) -> Dict[str, Any]:
|
381
319
|
"""
|
382
320
|
Receive the system prompt in string and create formatted prompts using the system prompt and the agent's backstory.
|
383
321
|
Then call the base model.
|
@@ -402,9 +340,7 @@ class Agent(ABC, BaseModel):
|
|
402
340
|
task_execution_counter += 1
|
403
341
|
print("Agent's #1 res: ", response)
|
404
342
|
|
405
|
-
if (
|
406
|
-
response is None or response == ""
|
407
|
-
) and task_execution_counter < self.max_retry_limit:
|
343
|
+
if (response is None or response == "") and task_execution_counter < self.max_retry_limit:
|
408
344
|
while task_execution_counter <= self.max_retry_limit:
|
409
345
|
response = self.llm.call(
|
410
346
|
messages=messages,
|
@@ -421,6 +357,7 @@ class Agent(ABC, BaseModel):
|
|
421
357
|
|
422
358
|
return {"output": response.output if hasattr(response, "output") else response}
|
423
359
|
|
360
|
+
|
424
361
|
def execute_task(self, task, context: Optional[str] = None) -> str:
|
425
362
|
"""
|
426
363
|
Execute the task and return the output in string.
|