versionhq 1.2.1.0__py3-none-any.whl → 1.2.1.1__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 +9 -9
- versionhq/agent/inhouse_agents.py +7 -0
- versionhq/agent/model.py +2 -2
- versionhq/{team → agent_network}/model.py +88 -68
- versionhq/clients/workflow/model.py +10 -10
- versionhq/knowledge/source.py +2 -2
- versionhq/knowledge/source_docling.py +1 -1
- versionhq/memory/model.py +1 -1
- versionhq/task/formation.py +10 -10
- versionhq/task/model.py +7 -7
- versionhq/{graph → task_graph}/model.py +1 -21
- {versionhq-1.2.1.0.dist-info → versionhq-1.2.1.1.dist-info}/METADATA +34 -25
- {versionhq-1.2.1.0.dist-info → versionhq-1.2.1.1.dist-info}/RECORD +18 -19
- versionhq/team/team_planner.py +0 -92
- /versionhq/{graph → agent_network}/__init__.py +0 -0
- /versionhq/{team → task_graph}/__init__.py +0 -0
- {versionhq-1.2.1.0.dist-info → versionhq-1.2.1.1.dist-info}/LICENSE +0 -0
- {versionhq-1.2.1.0.dist-info → versionhq-1.2.1.1.dist-info}/WHEEL +0 -0
- {versionhq-1.2.1.0.dist-info → versionhq-1.2.1.1.dist-info}/top_level.txt +0 -0
versionhq/__init__.py
CHANGED
@@ -8,6 +8,7 @@ from dotenv import load_dotenv
|
|
8
8
|
load_dotenv(override=True)
|
9
9
|
|
10
10
|
from versionhq.agent.model import Agent
|
11
|
+
from versionhq.agent_network.model import AgentNetwork, NetworkOutput, Formation, Member, TaskHandlingProcess
|
11
12
|
from versionhq.llm.model import LLM
|
12
13
|
from versionhq.llm.llm_vars import LLM_CONTEXT_WINDOW_SIZES, PARAMS, PROVIDERS, MODELS
|
13
14
|
from versionhq.clients.customer.model import Customer
|
@@ -16,10 +17,9 @@ from versionhq.clients.workflow.model import MessagingWorkflow, MessagingCompone
|
|
16
17
|
from versionhq.knowledge.model import Knowledge, KnowledgeStorage
|
17
18
|
from versionhq.knowledge.source import PDFKnowledgeSource, CSVKnowledgeSource, JSONKnowledgeSource, TextFileKnowledgeSource, ExcelKnowledgeSource, StringKnowledgeSource
|
18
19
|
from versionhq.knowledge.source_docling import DoclingSource
|
19
|
-
from versionhq.
|
20
|
+
from versionhq.task_graph.model import TaskStatus, TaskGraph, Node, Edge, DependencyType
|
20
21
|
from versionhq.task.model import Task, TaskOutput, ResponseField, TaskExecutionType
|
21
22
|
from versionhq.task.evaluate import Evaluation, EvaluationItem
|
22
|
-
from versionhq.team.model import Team, TeamOutput, Formation, Member, TaskHandlingProcess
|
23
23
|
from versionhq.tool.model import Tool, ToolSet
|
24
24
|
from versionhq.tool.cache_handler import CacheHandler
|
25
25
|
from versionhq.tool.tool_handler import ToolHandler
|
@@ -30,10 +30,16 @@ from versionhq.memory.model import ShortTermMemory,LongTermMemory, UserMemory, M
|
|
30
30
|
from versionhq.task.formation import form_agent_network
|
31
31
|
|
32
32
|
|
33
|
-
__version__ = "1.2.1.
|
33
|
+
__version__ = "1.2.1.1"
|
34
34
|
__all__ = [
|
35
35
|
"Agent",
|
36
36
|
|
37
|
+
"AgentNetwork",
|
38
|
+
"NetworkOutput",
|
39
|
+
"Formation",
|
40
|
+
"Member",
|
41
|
+
"TaskHandlingProcess",
|
42
|
+
|
37
43
|
"LLM",
|
38
44
|
"LLM_CONTEXT_WINDOW_SIZES",
|
39
45
|
"PARAMS",
|
@@ -70,12 +76,6 @@ __all__ = [
|
|
70
76
|
"Evaluation",
|
71
77
|
"EvaluationItem",
|
72
78
|
|
73
|
-
"Team",
|
74
|
-
"TeamOutput",
|
75
|
-
"Formation",
|
76
|
-
"Member",
|
77
|
-
"TaskHandlingProcess",
|
78
|
-
|
79
79
|
"Tool",
|
80
80
|
"ToolSet",
|
81
81
|
"CacheHandler",
|
@@ -39,3 +39,10 @@ vhq_formation_planner = Agent(
|
|
39
39
|
"Random is a formation where a single agent handles tasks, asking help from other agents without sharing its memory or knowledge. Typical usecase is that an email agent drafts promo message for the given audience, asking insights on tones from other email agents which oversee other customer clusters, or an agent calls the external, third party agent to deploy the campaign. ",
|
40
40
|
]
|
41
41
|
)
|
42
|
+
|
43
|
+
|
44
|
+
vhq_agent_creator = Agent(
|
45
|
+
role="vhq-Agent Creator",
|
46
|
+
goal="build an agent that can handle the given task",
|
47
|
+
llm="gemini/gemini-2.0-flash-exp",
|
48
|
+
)
|
versionhq/agent/model.py
CHANGED
@@ -95,7 +95,7 @@ class Agent(BaseModel):
|
|
95
95
|
user_prompt_template: Optional[str] = Field(default=None, description="user prompt template")
|
96
96
|
|
97
97
|
# task execution rules
|
98
|
-
|
98
|
+
network: Optional[List[Any]] = Field(default=None, description="store a list of agent networks that the agent belong as a member")
|
99
99
|
allow_delegation: bool = Field(default=False,description="if the agent can delegate the task to another agent or ask some help")
|
100
100
|
max_retry_limit: int = Field(default=2 ,description="max. number of retry for the task execution when an error occurs")
|
101
101
|
maxit: Optional[int] = Field(default=25,description="max. number of total optimization loops conducted when an error occurs")
|
@@ -553,7 +553,7 @@ class Agent(BaseModel):
|
|
553
553
|
|
554
554
|
|
555
555
|
## comment out for now
|
556
|
-
# if self.
|
556
|
+
# if self.network and self.network._train:
|
557
557
|
# task_prompt = self._training_handler(task_prompt=task_prompt)
|
558
558
|
# else:
|
559
559
|
# task_prompt = self._use_trained_data(task_prompt=task_prompt)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import uuid
|
2
2
|
import warnings
|
3
3
|
from enum import Enum
|
4
|
-
from dotenv import load_dotenv
|
5
4
|
from concurrent.futures import Future
|
6
5
|
from hashlib import md5
|
7
6
|
from typing import Any, Dict, List, Callable, Optional, Tuple
|
@@ -10,9 +9,8 @@ from pydantic._internal._generate_schema import GenerateSchema
|
|
10
9
|
from pydantic_core import PydanticCustomError, core_schema
|
11
10
|
|
12
11
|
from versionhq.agent.model import Agent
|
13
|
-
from versionhq.task.model import Task, TaskOutput, TaskExecutionType
|
12
|
+
from versionhq.task.model import Task, TaskOutput, TaskExecutionType, ResponseField
|
14
13
|
from versionhq.task.formatter import create_raw_outputs
|
15
|
-
from versionhq.team.team_planner import TeamPlanner
|
16
14
|
from versionhq._utils.logger import Logger
|
17
15
|
from versionhq._utils.usage_metrics import UsageMetrics
|
18
16
|
|
@@ -41,21 +39,21 @@ class Formation(str, Enum):
|
|
41
39
|
class TaskHandlingProcess(str, Enum):
|
42
40
|
"""
|
43
41
|
A class representing task handling processes to tackle multiple tasks.
|
44
|
-
When the
|
42
|
+
When the agent network has multiple tasks that connect with edges, follow the edge conditions.
|
45
43
|
"""
|
46
44
|
SEQUENT = 1
|
47
45
|
HIERARCHY = 2
|
48
46
|
CONSENSUAL = 3 # either from managers or peers or (human) - most likely controlled by edge
|
49
47
|
|
50
48
|
|
51
|
-
class
|
49
|
+
class NetworkOutput(TaskOutput):
|
52
50
|
"""
|
53
|
-
A class to store output from the
|
51
|
+
A class to store output from the network, inherited from TaskOutput class.
|
54
52
|
"""
|
55
53
|
|
56
|
-
|
54
|
+
network_id: UUID4 = Field(default_factory=uuid.uuid4, frozen=True, description="store the network ID as an identifier that generate the output")
|
57
55
|
task_description: str = Field(default=None, description="store initial request (task description) from the client")
|
58
|
-
task_outputs: list[TaskOutput] = Field(default=list, description="store TaskOutput objects of all tasks that the
|
56
|
+
task_outputs: list[TaskOutput] = Field(default=list, description="store TaskOutput objects of all tasks that the network has executed")
|
59
57
|
# token_usage: UsageMetrics = Field(default=dict, description="processed token summary")
|
60
58
|
|
61
59
|
def return_all_task_outputs(self) -> List[Dict[str, Any]]:
|
@@ -71,18 +69,18 @@ class TeamOutput(TaskOutput):
|
|
71
69
|
elif self.json_dict and key in self.json_dict:
|
72
70
|
return self.json_dict[key]
|
73
71
|
else:
|
74
|
-
raise KeyError(f"Key '{key}' not found in the
|
72
|
+
raise KeyError(f"Key '{key}' not found in the output.")
|
75
73
|
|
76
74
|
|
77
75
|
|
78
76
|
class Member(BaseModel):
|
79
77
|
"""
|
80
|
-
A class to store a member in the
|
78
|
+
A class to store a member (agent) in the network, with its tasks and memory/knowledge share settings.
|
81
79
|
"""
|
82
80
|
agent: Agent | None = Field(default=None)
|
83
81
|
is_manager: bool = Field(default=False)
|
84
|
-
can_share_knowledge: bool = Field(default=True, description="whether to share the agent's knowledge in the
|
85
|
-
can_share_memory: bool = Field(default=True, description="whether to share the agent's memory in the
|
82
|
+
can_share_knowledge: bool = Field(default=True, description="whether to share the agent's knowledge in the network")
|
83
|
+
can_share_memory: bool = Field(default=True, description="whether to share the agent's memory in the network")
|
86
84
|
tasks: Optional[List[Task]] = Field(default_factory=list, description="tasks explicitly assigned to the agent")
|
87
85
|
|
88
86
|
@property
|
@@ -90,10 +88,10 @@ class Member(BaseModel):
|
|
90
88
|
return bool(self.tasks)
|
91
89
|
|
92
90
|
|
93
|
-
class
|
91
|
+
class AgentNetwork(BaseModel):
|
94
92
|
"""
|
95
|
-
A class to store a
|
96
|
-
Tasks can be 1. multiple individual tasks, 2. multiple dependant tasks connected via
|
93
|
+
A class to store a agent network with agent members and their tasks.
|
94
|
+
Tasks can be 1. multiple individual tasks, 2. multiple dependant tasks connected via TaskGraph, and 3. hybrid.
|
97
95
|
"""
|
98
96
|
|
99
97
|
__hash__ = object.__hash__
|
@@ -108,8 +106,7 @@ class Team(BaseModel):
|
|
108
106
|
should_reform: bool = Field(default=False, description="True if task exe. failed or eval scores below threshold")
|
109
107
|
|
110
108
|
# formation planning
|
111
|
-
|
112
|
-
team_tasks: Optional[List[Task]] = Field(default_factory=list, description="tasks without dedicated agents to handle")
|
109
|
+
network_tasks: Optional[List[Task]] = Field(default_factory=list, description="tasks without dedicated agents")
|
113
110
|
|
114
111
|
# task execution rules
|
115
112
|
prompt_file: str = Field(default="", description="absolute path to the prompt json file")
|
@@ -118,11 +115,11 @@ class Team(BaseModel):
|
|
118
115
|
# callbacks
|
119
116
|
pre_launch_callbacks: List[Callable[[Optional[Dict[str, Any]]], Optional[Dict[str, Any]]]] = Field(
|
120
117
|
default_factory=list,
|
121
|
-
description="list of callback functions to be executed before the
|
118
|
+
description="list of callback functions to be executed before the network launch. i.e., adjust inputs"
|
122
119
|
)
|
123
|
-
post_launch_callbacks: List[Callable[[
|
120
|
+
post_launch_callbacks: List[Callable[[NetworkOutput], NetworkOutput]] = Field(
|
124
121
|
default_factory=list,
|
125
|
-
description="list of callback functions to be executed after the
|
122
|
+
description="list of callback functions to be executed after the network launch. i.e., store the result in repo"
|
126
123
|
)
|
127
124
|
step_callback: Optional[Any] = Field(default=None, description="callback to be executed after each step for all agents execution")
|
128
125
|
|
@@ -146,19 +143,19 @@ class Team(BaseModel):
|
|
146
143
|
@model_validator(mode="after")
|
147
144
|
def assess_tasks(self):
|
148
145
|
"""
|
149
|
-
Validates if the model recognize all tasks that the
|
146
|
+
Validates if the model recognize all tasks that the network needs to handle.
|
150
147
|
"""
|
151
148
|
|
152
149
|
if self.tasks:
|
153
|
-
if all(task in self.tasks for task in self.
|
154
|
-
raise PydanticCustomError("task_validation_error", "`
|
150
|
+
if all(task in self.tasks for task in self.network_tasks) == False:
|
151
|
+
raise PydanticCustomError("task_validation_error", "`network_tasks` needs to be recognized in the task.", {})
|
155
152
|
|
156
153
|
|
157
154
|
num_member_tasks = 0
|
158
155
|
for member in self.members:
|
159
156
|
num_member_tasks += len(member.tasks)
|
160
157
|
|
161
|
-
# if len(self.tasks) != len(self.
|
158
|
+
# if len(self.tasks) != len(self.network_tasks) + num_member_tasks:
|
162
159
|
# raise PydanticCustomError("task_validation_error", "Some tasks are missing.", {})
|
163
160
|
return self
|
164
161
|
|
@@ -166,7 +163,7 @@ class Team(BaseModel):
|
|
166
163
|
@model_validator(mode="after")
|
167
164
|
def check_manager(self):
|
168
165
|
"""
|
169
|
-
Check if the
|
166
|
+
Check if the agent network has a manager
|
170
167
|
"""
|
171
168
|
if self.process == TaskHandlingProcess.HIERARCHY or self.formation == Formation.SUPERVISING:
|
172
169
|
if not self.managers:
|
@@ -174,9 +171,9 @@ class Team(BaseModel):
|
|
174
171
|
raise PydanticCustomError("missing_manager", "`manager` is required when using hierarchical process.", {})
|
175
172
|
|
176
173
|
## comment out for the formation flexibilities
|
177
|
-
# if self.managers and (self.manager_tasks is None or self.
|
174
|
+
# if self.managers and (self.manager_tasks is None or self.network_tasks is None):
|
178
175
|
# self._logger.log(level="error", message="The manager is idling. At least 1 task needs to be assigned to the manager.", color="red")
|
179
|
-
# raise PydanticCustomError("missing_manager_task", "manager needs to have at least one manager task or
|
176
|
+
# raise PydanticCustomError("missing_manager_task", "manager needs to have at least one manager task or network task.", {})
|
180
177
|
|
181
178
|
return self
|
182
179
|
|
@@ -184,9 +181,9 @@ class Team(BaseModel):
|
|
184
181
|
@model_validator(mode="after")
|
185
182
|
def validate_task_member_paring(self):
|
186
183
|
"""
|
187
|
-
Sequential task processing without any
|
184
|
+
Sequential task processing without any network_tasks require a task-agent pairing.
|
188
185
|
"""
|
189
|
-
if self.process == TaskHandlingProcess.SEQUENT and self.
|
186
|
+
if self.process == TaskHandlingProcess.SEQUENT and self.network_tasks is None:
|
190
187
|
for task in self.tasks:
|
191
188
|
if not [member.task == task for member in self.members]:
|
192
189
|
self._logger.log(level="error", message=f"The following task needs a dedicated agent to be assinged: {task.description}", color="red")
|
@@ -196,7 +193,7 @@ class Team(BaseModel):
|
|
196
193
|
@model_validator(mode="after")
|
197
194
|
def validate_end_with_at_most_one_async_task(self):
|
198
195
|
"""
|
199
|
-
Validates that the
|
196
|
+
Validates that the agent network completes max. one asynchronous task by counting tasks traversed backward
|
200
197
|
"""
|
201
198
|
|
202
199
|
async_task_count = 0
|
@@ -209,10 +206,43 @@ class Team(BaseModel):
|
|
209
206
|
break
|
210
207
|
|
211
208
|
if async_task_count > 1:
|
212
|
-
raise PydanticCustomError("async_task_count", "The
|
209
|
+
raise PydanticCustomError("async_task_count", "The agent network must end with at maximum one asynchronous task.", {})
|
213
210
|
return self
|
214
211
|
|
215
212
|
|
213
|
+
@staticmethod
|
214
|
+
def handle_assigning_agents(unassigned_tasks: List[Task]) -> List[Member]:
|
215
|
+
"""
|
216
|
+
Build an agent and assign it with a task. Return a list of Member connecting the agent created and the task given.
|
217
|
+
"""
|
218
|
+
|
219
|
+
from versionhq.agent.inhouse_agents import vhq_agent_creator
|
220
|
+
|
221
|
+
new_member_list: List[Member] = []
|
222
|
+
|
223
|
+
for unassgined_task in unassigned_tasks:
|
224
|
+
task = Task(
|
225
|
+
description=f"""
|
226
|
+
Based on the following task summary, draft a AI agent's role and goal in concise manner.
|
227
|
+
Task summary: {unassgined_task.summary}
|
228
|
+
""",
|
229
|
+
response_fields=[
|
230
|
+
ResponseField(title="goal", data_type=str, required=True),
|
231
|
+
ResponseField(title="role", data_type=str, required=True),
|
232
|
+
],
|
233
|
+
)
|
234
|
+
res = task.execute(agent=vhq_agent_creator)
|
235
|
+
agent = Agent(
|
236
|
+
role=res.json_dict["role"] if "role" in res.json_dict else res.raw,
|
237
|
+
goal=res.json_dict["goal"] if "goal" in res.json_dict else task.description
|
238
|
+
)
|
239
|
+
if agent.id:
|
240
|
+
member = Member(agent=agent, tasks=[unassgined_task], is_manager=False)
|
241
|
+
new_member_list.append(member)
|
242
|
+
|
243
|
+
return new_member_list
|
244
|
+
|
245
|
+
|
216
246
|
def _get_responsible_agent(self, task: Task) -> Agent | None:
|
217
247
|
if task is None:
|
218
248
|
return None
|
@@ -226,17 +256,16 @@ class Team(BaseModel):
|
|
226
256
|
|
227
257
|
def _assign_tasks(self) -> None:
|
228
258
|
"""
|
229
|
-
Form a
|
230
|
-
1. Idling managers to take the
|
231
|
-
2. Idling members to take the remaining tasks starting from the
|
259
|
+
Form a agent network considering given agents and tasks, and update `self.members` field:
|
260
|
+
1. Idling managers to take the network tasks.
|
261
|
+
2. Idling members to take the remaining tasks starting from the network tasks to member tasks.
|
232
262
|
3. Create agents to handle the rest tasks.
|
233
263
|
"""
|
234
264
|
|
235
|
-
team_planner = TeamPlanner(tasks=self.tasks, planner_llm=self.planner_llm)
|
236
265
|
idling_managers: List[Member] = [member for member in self.members if member.is_idling and member.is_manager == True]
|
237
266
|
idling_members: List[Member] = [member for member in self.members if member.is_idling and member.is_manager == False]
|
238
|
-
unassigned_tasks: List[Task] = self.
|
239
|
-
|
267
|
+
unassigned_tasks: List[Task] = self.network_tasks + self.member_tasks_without_agent if self.network_tasks else self.member_tasks_without_agent
|
268
|
+
new_members: List[Member] = []
|
240
269
|
|
241
270
|
if idling_managers:
|
242
271
|
idling_managers[0].tasks.extend(unassigned_tasks)
|
@@ -245,9 +274,9 @@ class Team(BaseModel):
|
|
245
274
|
idling_members[0].tasks.extend(unassigned_tasks)
|
246
275
|
|
247
276
|
else:
|
248
|
-
|
249
|
-
if
|
250
|
-
self.members +=
|
277
|
+
new_members = self.handle_assigning_agents(unassigned_tasks=unassigned_tasks)
|
278
|
+
if new_members:
|
279
|
+
self.members += new_members
|
251
280
|
|
252
281
|
|
253
282
|
# task execution
|
@@ -268,7 +297,7 @@ class Team(BaseModel):
|
|
268
297
|
|
269
298
|
def _calculate_usage_metrics(self) -> UsageMetrics:
|
270
299
|
"""
|
271
|
-
Calculate and return the usage metrics that consumed by the
|
300
|
+
Calculate and return the usage metrics that consumed by the agent network.
|
272
301
|
"""
|
273
302
|
total_usage_metrics = UsageMetrics()
|
274
303
|
|
@@ -288,12 +317,12 @@ class Team(BaseModel):
|
|
288
317
|
return total_usage_metrics
|
289
318
|
|
290
319
|
|
291
|
-
def _execute_tasks(self, tasks: List[Task], start_index: Optional[int] = 0, was_replayed: bool = False) ->
|
320
|
+
def _execute_tasks(self, tasks: List[Task], start_index: Optional[int] = 0, was_replayed: bool = False) -> NetworkOutput:
|
292
321
|
"""
|
293
|
-
Executes tasks sequentially and returns the final output in
|
322
|
+
Executes tasks sequentially and returns the final output in NetworkOutput class.
|
294
323
|
When we have a manager agent, we will start from executing manager agent's tasks.
|
295
324
|
Priority:
|
296
|
-
1.
|
325
|
+
1. Network tasks > 2. Manager task > 3. Member tasks (in order of index)
|
297
326
|
"""
|
298
327
|
|
299
328
|
task_outputs: List[TaskOutput] = []
|
@@ -330,6 +359,7 @@ class Team(BaseModel):
|
|
330
359
|
else:
|
331
360
|
context = create_raw_outputs(tasks=[task,], task_outputs=([last_sync_output,] if last_sync_output else [] ))
|
332
361
|
task_output = task.execute(agent=responsible_agent, context=context)
|
362
|
+
|
333
363
|
if self.managers and responsible_agent in [manager.agent for manager in self.managers]:
|
334
364
|
lead_task_output = task_output
|
335
365
|
|
@@ -341,15 +371,15 @@ class Team(BaseModel):
|
|
341
371
|
task_outputs = self._process_async_tasks(futures, was_replayed)
|
342
372
|
|
343
373
|
if not task_outputs:
|
344
|
-
self._logger.log(level="error", message="Missing task
|
345
|
-
raise ValueError("
|
374
|
+
self._logger.log(level="error", message="Missing task outputs.", color="red")
|
375
|
+
raise ValueError("Missing task outputs")
|
346
376
|
|
347
377
|
final_task_output = lead_task_output if lead_task_output is not None else task_outputs[0] #! REFINEME
|
348
378
|
|
349
379
|
# token_usage = self._calculate_usage_metrics() #! combining with Eval
|
350
380
|
|
351
|
-
return
|
352
|
-
|
381
|
+
return NetworkOutput(
|
382
|
+
network_id=self.id,
|
353
383
|
raw=final_task_output.raw,
|
354
384
|
json_dict=final_task_output.json_dict,
|
355
385
|
pydantic=final_task_output.pydantic,
|
@@ -358,33 +388,23 @@ class Team(BaseModel):
|
|
358
388
|
)
|
359
389
|
|
360
390
|
|
361
|
-
|
362
|
-
def launch(self, kwargs_pre: Optional[Dict[str, str]] = None, kwargs_post: Optional[Dict[str, Any]] = None) -> TeamOutput:
|
391
|
+
def launch(self, kwargs_pre: Optional[Dict[str, str]] = None, kwargs_post: Optional[Dict[str, Any]] = None) -> NetworkOutput:
|
363
392
|
"""
|
364
|
-
|
365
|
-
0. Assign an agent to a task - using conditions (manager prioritizes team_tasks) and planner_llm.
|
366
|
-
1. Address `pre_launch_callbacks` if any.
|
367
|
-
2. Handle team members' tasks in accordance with the process.
|
368
|
-
3. Address `post_launch_callbacks` if any.
|
393
|
+
Launch the agent network - executing tasks and recording their outputs.
|
369
394
|
"""
|
370
395
|
|
371
396
|
metrics: List[UsageMetrics] = []
|
372
397
|
|
373
|
-
if self.
|
398
|
+
if self.network_tasks or self.member_tasks_without_agent:
|
374
399
|
self._assign_tasks()
|
375
400
|
|
376
401
|
if kwargs_pre is not None:
|
377
402
|
for func in self.pre_launch_callbacks:
|
378
403
|
func(**kwargs_pre)
|
379
404
|
|
380
|
-
# self._execution_span = self._telemetry.team_execution_span(self, inputs)
|
381
|
-
# self._task_output_handler.reset()
|
382
|
-
# self._logging_color = "bold_purple"
|
383
|
-
# i18n = I18N(prompt_file=self.prompt_file)
|
384
|
-
|
385
405
|
for member in self.members:
|
386
406
|
agent = member.agent
|
387
|
-
agent.
|
407
|
+
agent.network = self
|
388
408
|
|
389
409
|
if self.step_callback:
|
390
410
|
agent.callbacks.append(self.step_callback)
|
@@ -421,7 +441,7 @@ class Team(BaseModel):
|
|
421
441
|
@property
|
422
442
|
def manager_tasks(self) -> List[Task]:
|
423
443
|
"""
|
424
|
-
Tasks (incl.
|
444
|
+
Tasks (incl. network tasks) handled by managers in the agent network.
|
425
445
|
"""
|
426
446
|
res = list()
|
427
447
|
|
@@ -436,22 +456,22 @@ class Team(BaseModel):
|
|
436
456
|
@property
|
437
457
|
def tasks(self) -> List[Task]:
|
438
458
|
"""
|
439
|
-
Return all the tasks that the
|
440
|
-
1.
|
459
|
+
Return all the tasks that the agent network needs to handle in order of priority:
|
460
|
+
1. network_tasks, -> assigned to the member
|
441
461
|
2. manager_task,
|
442
462
|
3. members' tasks
|
443
463
|
"""
|
444
464
|
|
445
|
-
|
465
|
+
network_tasks = self.network_tasks
|
446
466
|
manager_tasks = self.manager_tasks
|
447
467
|
member_tasks = []
|
448
468
|
|
449
469
|
for member in self.members:
|
450
470
|
if member.is_manager == False and member.tasks:
|
451
|
-
a = [item for item in member.tasks if item not in
|
471
|
+
a = [item for item in member.tasks if item not in network_tasks and item not in manager_tasks]
|
452
472
|
member_tasks += a
|
453
473
|
|
454
|
-
return
|
474
|
+
return network_tasks + manager_tasks + member_tasks
|
455
475
|
|
456
476
|
|
457
477
|
@property
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import uuid
|
2
2
|
from abc import ABC
|
3
|
-
from datetime import
|
4
|
-
from typing import Any, Dict, List,
|
3
|
+
from datetime import datetime
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
5
|
from typing_extensions import Self
|
6
6
|
from pydantic import UUID4, InstanceOf, BaseModel, ConfigDict, Field, field_validator, model_validator
|
7
7
|
from pydantic_core import PydanticCustomError
|
@@ -9,7 +9,7 @@ from pydantic_core import PydanticCustomError
|
|
9
9
|
from versionhq.clients.product.model import Product
|
10
10
|
from versionhq.clients.customer.model import Customer
|
11
11
|
from versionhq.agent.model import Agent
|
12
|
-
from versionhq.
|
12
|
+
from versionhq.agent_network.model import AgentNetwork
|
13
13
|
from versionhq.tool.composio_tool_vars import ComposioAppName
|
14
14
|
|
15
15
|
|
@@ -102,8 +102,8 @@ class MessagingWorkflow(ABC, BaseModel):
|
|
102
102
|
messaging_components: List[MessagingComponent] = Field(default_factory=list, description="store messaging components in the workflow")
|
103
103
|
|
104
104
|
# responsible tean or agents
|
105
|
-
|
106
|
-
agents: Optional[List[Agent]] = Field(default=None, description="store responsible agents. None when the
|
105
|
+
agent_network: Optional[AgentNetwork] = Field(default=None, description="store a responsibile agent network to autopilot the workflow")
|
106
|
+
agents: Optional[List[Agent]] = Field(default=None, description="store responsible agents. None when the `agent_network` fields has a value")
|
107
107
|
|
108
108
|
# metrics
|
109
109
|
destination: Optional[ComposioAppName | str] = Field(default=None, description="destination service to launch the workflow")
|
@@ -140,16 +140,16 @@ class MessagingWorkflow(ABC, BaseModel):
|
|
140
140
|
return self
|
141
141
|
|
142
142
|
|
143
|
-
def
|
143
|
+
def reassign_agent(self, agents: List[Agent] = None, agent_network: AgentNetwork = None) -> None:
|
144
144
|
"""
|
145
|
-
|
145
|
+
Switch agents
|
146
146
|
"""
|
147
147
|
|
148
|
-
if not agents and not
|
149
|
-
raise ValueError("
|
148
|
+
if not agents and not agent_network:
|
149
|
+
raise ValueError("Missing agent or agent network to assign.")
|
150
150
|
|
151
151
|
self.agents = agents
|
152
|
-
self.
|
152
|
+
self.agent_network = agent_network
|
153
153
|
self.updated_at = datetime.datetime.now()
|
154
154
|
|
155
155
|
|
versionhq/knowledge/source.py
CHANGED
@@ -265,7 +265,7 @@ class PDFKnowledgeSource(BaseFileKnowledgeSource):
|
|
265
265
|
import os
|
266
266
|
os.system("uv add pdfplumber --optional pdfplumber")
|
267
267
|
except:
|
268
|
-
raise ImportError("pdfplumber is not installed. Please install it with: uv add pdfplumber
|
268
|
+
raise ImportError("pdfplumber is not installed. Please install it with: $ uv add versionhq[pdfplumber]")
|
269
269
|
|
270
270
|
|
271
271
|
def add(self) -> None:
|
@@ -394,7 +394,7 @@ class ExcelKnowledgeSource(BaseFileKnowledgeSource):
|
|
394
394
|
except:
|
395
395
|
missing_package = str(e).split()[-1]
|
396
396
|
raise ImportError(
|
397
|
-
f"{missing_package} is not installed. Please install it with:
|
397
|
+
f"{missing_package} is not installed. Please install it with: $ uv add versionhq[{missing_package}]"
|
398
398
|
)
|
399
399
|
|
400
400
|
|
@@ -56,7 +56,7 @@ class DoclingSource(BaseKnowledgeSource):
|
|
56
56
|
super().__init__(*args, **kwargs)
|
57
57
|
|
58
58
|
else:
|
59
|
-
raise ImportError("The docling package is required. Please install the package using: $ uv add docling
|
59
|
+
raise ImportError("The docling package is required. Please install the package using: $ uv add versionhq[docling]")
|
60
60
|
# else:
|
61
61
|
# super().__init__(*args, **kwargs)
|
62
62
|
|
versionhq/memory/model.py
CHANGED
@@ -125,7 +125,7 @@ class ShortTermMemory(Memory):
|
|
125
125
|
|
126
126
|
from versionhq.storage.mem0_storage import Mem0Storage
|
127
127
|
except:
|
128
|
-
raise ImportError("Mem0 is not installed. Please install it with
|
128
|
+
raise ImportError("Mem0 is not installed. Please install it with `$ uv add versionhq[mem0ai]`.")
|
129
129
|
|
130
130
|
storage = Mem0Storage(type="stm", agent=agent)
|
131
131
|
else:
|
versionhq/task/formation.py
CHANGED
@@ -5,7 +5,7 @@ from pydantic import BaseModel
|
|
5
5
|
|
6
6
|
from versionhq.task.model import Task
|
7
7
|
from versionhq.agent.model import Agent
|
8
|
-
from versionhq.
|
8
|
+
from versionhq.agent_network.model import AgentNetwork, Member, Formation
|
9
9
|
from versionhq.agent.inhouse_agents import vhq_formation_planner
|
10
10
|
from versionhq._utils import Logger
|
11
11
|
|
@@ -16,7 +16,7 @@ def form_agent_network(
|
|
16
16
|
agents: List[Agent] = None,
|
17
17
|
context: str = None,
|
18
18
|
formation: Type[Formation] = None
|
19
|
-
) ->
|
19
|
+
) -> AgentNetwork | None:
|
20
20
|
"""
|
21
21
|
Make a formation of agents from the given task description, expected outcome, agents (optional), and context (optional).
|
22
22
|
"""
|
@@ -91,7 +91,7 @@ def form_agent_network(
|
|
91
91
|
created_agents = [Agent(role=item, goal=item) for item in res.pydantic.agent_roles]
|
92
92
|
created_tasks = [Task(description=item) for item in res.pydantic.task_descriptions]
|
93
93
|
|
94
|
-
|
94
|
+
network_tasks = []
|
95
95
|
members = []
|
96
96
|
leader = str(res.pydantic.leader_agent)
|
97
97
|
|
@@ -106,11 +106,11 @@ def form_agent_network(
|
|
106
106
|
|
107
107
|
|
108
108
|
if len(created_agents) < len(created_tasks):
|
109
|
-
|
109
|
+
network_tasks.extend(created_tasks[len(created_agents):len(created_tasks)])
|
110
110
|
|
111
111
|
members.sort(key=lambda x: x.is_manager == False)
|
112
|
-
|
113
|
-
return
|
112
|
+
network = AgentNetwork(members=members, formation=_formation, network_tasks=network_tasks)
|
113
|
+
return network
|
114
114
|
|
115
115
|
else:
|
116
116
|
res = res.json_dict
|
@@ -122,7 +122,7 @@ def form_agent_network(
|
|
122
122
|
created_agents = [Agent(role=item, goal=item) for item in res["agent_roles"]]
|
123
123
|
created_tasks = [Task(description=item) for item in res["task_descriptions"]]
|
124
124
|
|
125
|
-
|
125
|
+
network_tasks = []
|
126
126
|
members = []
|
127
127
|
leader = str(res["leader_agent"])
|
128
128
|
|
@@ -136,11 +136,11 @@ def form_agent_network(
|
|
136
136
|
members.append(member)
|
137
137
|
|
138
138
|
if len(created_agents) < len(created_tasks):
|
139
|
-
|
139
|
+
network_tasks.extend(created_tasks[len(created_agents):len(created_tasks)])
|
140
140
|
|
141
141
|
members.sort(key=lambda x: x.is_manager == False)
|
142
|
-
|
143
|
-
return
|
142
|
+
network = AgentNetwork(members=members, formation=_formation, network_tasks=network_tasks)
|
143
|
+
return network
|
144
144
|
|
145
145
|
|
146
146
|
except Exception as e:
|
versionhq/task/model.py
CHANGED
@@ -613,7 +613,7 @@ Ref. Output image: {output_formats_to_follow}
|
|
613
613
|
"""
|
614
614
|
|
615
615
|
from versionhq.agent.model import Agent
|
616
|
-
from versionhq.
|
616
|
+
from versionhq.agent_network.model import AgentNetwork
|
617
617
|
|
618
618
|
self.prompt_context = context
|
619
619
|
task_output: InstanceOf[TaskOutput] = None
|
@@ -626,15 +626,15 @@ Ref. Output image: {output_formats_to_follow}
|
|
626
626
|
if isinstance(item, ToolSet) or isinstance(item, Tool) or type(item) == Tool:
|
627
627
|
task_tools.append(item)
|
628
628
|
|
629
|
-
if self.allow_delegation:
|
629
|
+
if self.allow_delegation == True:
|
630
630
|
agent_to_delegate = None
|
631
631
|
|
632
|
-
if hasattr(agent, "
|
633
|
-
if agent.
|
634
|
-
idling_manager_agents = [manager.agent for manager in agent.
|
635
|
-
agent_to_delegate = idling_manager_agents[0] if idling_manager_agents else agent.
|
632
|
+
if hasattr(agent, "network") and isinstance(agent.network, AgentNetwork):
|
633
|
+
if agent.network.managers:
|
634
|
+
idling_manager_agents = [manager.agent for manager in agent.network.managers if manager.is_idling]
|
635
|
+
agent_to_delegate = idling_manager_agents[0] if idling_manager_agents else agent.network.managers[0]
|
636
636
|
else:
|
637
|
-
peers = [member.agent for member in agent.
|
637
|
+
peers = [member.agent for member in agent.network.members if member.is_manager == False and member.agent.id is not agent.id]
|
638
638
|
if len(peers) > 0:
|
639
639
|
agent_to_delegate = peers[0]
|
640
640
|
else:
|
@@ -5,7 +5,7 @@ import matplotlib.pyplot as plt
|
|
5
5
|
from abc import ABC
|
6
6
|
from typing import List, Any, Optional, Callable, Dict, Type, Tuple
|
7
7
|
|
8
|
-
from pydantic import BaseModel, InstanceOf, Field, UUID4,
|
8
|
+
from pydantic import BaseModel, InstanceOf, Field, UUID4, field_validator
|
9
9
|
from pydantic_core import PydanticCustomError
|
10
10
|
|
11
11
|
from versionhq.task.model import Task, TaskOutput
|
@@ -13,26 +13,6 @@ from versionhq.agent.model import Agent
|
|
13
13
|
from versionhq._utils.logger import Logger
|
14
14
|
|
15
15
|
|
16
|
-
def gen_network():
|
17
|
-
goal = "make a promo plan to increase gross sales of Temu, an ecommerce site with affordable items."
|
18
|
-
agent = Agent(
|
19
|
-
role="Network Generator", goal="draft a best graph with nodes (tasks) and edges", llm="gemini-2.0", maxit=1,
|
20
|
-
knowledge_sources=["https://en.wikipedia.org/wiki/Graph_theory", "https://www.temu.com", ]
|
21
|
-
)
|
22
|
-
class Outcome(BaseModel):
|
23
|
-
task_descriptions: list[str]
|
24
|
-
|
25
|
-
|
26
|
-
task = Task(
|
27
|
-
description=" Create a team of specialized agents designed to automate the following task and deliver the expected outcome. Consider the necessary roles for each agent with a clear task description. If you think we neeed a leader to handle the automation, return a leader_agent role as well, but if not, leave the a leader_agent role blank. ",
|
28
|
-
pydantic_output=Outcome
|
29
|
-
)
|
30
|
-
task = Task(
|
31
|
-
description="Form best network with nodes and edges for the task described as following: Draft a promo plan for the client.",
|
32
|
-
pydantic_output=Edge
|
33
|
-
)
|
34
|
-
res = task.execute(agent=agent)
|
35
|
-
|
36
16
|
class TaskStatus(enum.Enum):
|
37
17
|
"""
|
38
18
|
Enum to track the task execution status
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: versionhq
|
3
|
-
Version: 1.2.1.
|
3
|
+
Version: 1.2.1.1
|
4
4
|
Summary: An agentic orchestration framework for building agent networks that handle task automation.
|
5
5
|
Author-email: Kuriko Iwai <kuriko@versi0n.io>
|
6
6
|
License: MIT License
|
@@ -115,6 +115,7 @@ A Python framework for agentic orchestration that handles complex task automatio
|
|
115
115
|
- [Forming a agent network](#forming-a-agent-network)
|
116
116
|
- [Executing tasks](#executing-tasks)
|
117
117
|
- [Supervising](#supervising)
|
118
|
+
- [Supervising](#supervising-1)
|
118
119
|
- [Technologies Used](#technologies-used)
|
119
120
|
- [Project Structure](#project-structure)
|
120
121
|
- [Setting Up a Project](#setting-up-a-project)
|
@@ -305,42 +306,50 @@ This will return a `TaskOutput` object that stores response in plane text, JSON,
|
|
305
306
|
|
306
307
|
### Supervising
|
307
308
|
|
308
|
-
|
309
|
-
import versionhq as vhq
|
309
|
+
## Supervising
|
310
310
|
|
311
|
-
|
312
|
-
agent_b = vhq.Agent(role="agent b", goal="My amazing goals", llm="llm-of-your-choice")
|
311
|
+
To create an agent network with one or more manager agents, designate members using the `is_manager` tag.
|
313
312
|
|
314
|
-
|
315
|
-
|
316
|
-
response_fields=[vhq.ResponseField(title="test1", data_type=str, required=True),],
|
317
|
-
allow_delegation=True
|
318
|
-
)
|
313
|
+
```python
|
314
|
+
import versionhq as vhq
|
319
315
|
|
320
|
-
|
321
|
-
|
322
|
-
response_fields=[ResponseField(title="test1", data_type=int, required=True),],
|
323
|
-
allow_delegation=False
|
324
|
-
)
|
316
|
+
agent_a = vhq.Agent(role="agent a", goal="My amazing goals", llm="llm-of-your-choice")
|
317
|
+
agent_b = vhq.Agent(role="agent b", goal="My amazing goals", llm="llm-of-your-choice")
|
325
318
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
319
|
+
task_1 = vhq.Task(
|
320
|
+
description="Analyze the client's business model.",
|
321
|
+
response_fields=[vhq.ResponseField(title="test1", data_type=str, required=True),],
|
322
|
+
allow_delegation=True
|
323
|
+
)
|
324
|
+
|
325
|
+
task_2 = vhq.Task(
|
326
|
+
description="Define a cohort.",
|
327
|
+
response_fields=[vhq.ResponseField(title="test1", data_type=int, required=True),],
|
328
|
+
allow_delegation=False
|
329
|
+
)
|
330
|
+
|
331
|
+
network =vhq.AgentNetwork(
|
332
|
+
members=[
|
333
|
+
vhq.Member(agent=agent_a, is_manager=False, tasks=[task_1]),
|
334
|
+
vhq.Member(agent=agent_b, is_manager=True, tasks=[task_2]), # Agent B as a manager
|
335
|
+
],
|
336
|
+
)
|
337
|
+
res = network.launch()
|
338
|
+
|
339
|
+
assert isinstance(res, vhq.NetworkOutput)
|
340
|
+
assert not [item for item in task_1.processed_agents if "vhq-Delegated-Agent" == item]
|
341
|
+
assert [item for item in task_1.processed_agents if "agent b" == item]
|
342
|
+
```
|
334
343
|
|
335
344
|
This will return a list with dictionaries with keys defined in the `ResponseField` of each task.
|
336
345
|
|
337
|
-
Tasks can be delegated to a
|
346
|
+
Tasks can be delegated to a manager, peers within the agent network, or a completely new agent.
|
338
347
|
|
339
348
|
<hr />
|
340
349
|
|
341
350
|
## Technologies Used
|
342
351
|
|
343
|
-
**Graph
|
352
|
+
**Task Graph**
|
344
353
|
|
345
354
|
* [NetworkX](https://networkx.org/documentation/stable/reference/introduction.html): A Python package to analyze, create, and manipulate complex graph networks.
|
346
355
|
* [Matplotlib](https://matplotlib.org/stable/index.html): Visualization library
|
@@ -1,4 +1,4 @@
|
|
1
|
-
versionhq/__init__.py,sha256=
|
1
|
+
versionhq/__init__.py,sha256=Ct-oSIm8Mw2K2UH9CNTtuKaLgwUTIcUa3ogDAFQYHZo,2817
|
2
2
|
versionhq/_utils/__init__.py,sha256=dzoZr4cBlh-2QZuPzTdehPUCe9lP1dmRtauD7qTjUaA,158
|
3
3
|
versionhq/_utils/i18n.py,sha256=TwA_PnYfDLA6VqlUDPuybdV9lgi3Frh_ASsb_X8jJo8,1483
|
4
4
|
versionhq/_utils/logger.py,sha256=2qkODR6y8ApOoMjQZVecTboXvCLrMy2v_mTSOnNMKFY,1581
|
@@ -6,12 +6,14 @@ versionhq/_utils/process_config.py,sha256=jbPGXK2Kb4iyCugJ3FwRJuU0wL5Trq2x4xFQz2
|
|
6
6
|
versionhq/_utils/usage_metrics.py,sha256=NXF18dn5NNvGK7EsQ4AAghpR8ppYOjMx6ABenLLHnmM,1066
|
7
7
|
versionhq/_utils/vars.py,sha256=bZ5Dx_bFKlt3hi4-NNGXqdk7B23If_WaTIju2fiTyPQ,57
|
8
8
|
versionhq/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
versionhq/agent/inhouse_agents.py,sha256=
|
10
|
-
versionhq/agent/model.py,sha256=
|
9
|
+
versionhq/agent/inhouse_agents.py,sha256=snDtgDmvZB2bZKH_RTcz5uFOMl3MTjLJwTQBebFt8hk,2532
|
10
|
+
versionhq/agent/model.py,sha256=HiEQulVjXx6fWGaP-DBWmiZv5uwXFPd4S8jyBU3ydm0,25442
|
11
11
|
versionhq/agent/parser.py,sha256=riG0dkdQCxH7uJ0AbdVdg7WvL0BXhUgJht0VtQvxJBc,4082
|
12
12
|
versionhq/agent/rpm_controller.py,sha256=grezIxyBci_lDlwAlgWFRyR5KOocXeOhYkgN02dNFNE,2360
|
13
13
|
versionhq/agent/TEMPLATES/Backstory.py,sha256=IAhGnnt6VUMe3wO6IzeyZPDNu7XE7Uiu3VEXUreOcKs,532
|
14
14
|
versionhq/agent/TEMPLATES/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
versionhq/agent_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
+
versionhq/agent_network/model.py,sha256=P3Ntr_OIK60EXjEfaEm31HTBFypZfVr__0aC4VBt9G0,19353
|
15
17
|
versionhq/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
18
|
versionhq/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
19
|
versionhq/clients/customer/__init__.py,sha256=-YXh1FQfvpfLacK8SUC7bD7Wx_eIEi4yrkCC_cUasFg,217
|
@@ -19,22 +21,20 @@ versionhq/clients/customer/model.py,sha256=_AtaVVMm9MgCwrQ-HTRQ2oXUMKrSCEfZwE2Jd
|
|
19
21
|
versionhq/clients/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
22
|
versionhq/clients/product/model.py,sha256=3w__pug9XRe4LIm9wX8C8WKqi40r081Eb1q2vWk9UaU,3694
|
21
23
|
versionhq/clients/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
-
versionhq/clients/workflow/model.py,sha256=
|
23
|
-
versionhq/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
-
versionhq/graph/model.py,sha256=k4NbNn0D3r3ujfkQHOsfiiEJRxZx7iK5DczBnOyn1ik,23912
|
24
|
+
versionhq/clients/workflow/model.py,sha256=fqmTx8Y6P6i-sK045ENO88GDbf4WYY4hUA26RfEH8Ek,6011
|
25
25
|
versionhq/knowledge/__init__.py,sha256=qW7IgssTA4_bFFV9ziOcYRfGjlq1c8bkb-HnfWknpuQ,567
|
26
26
|
versionhq/knowledge/_utils.py,sha256=YWRF8U533cfZes_gZqUvdj-K24MD2ri1R0gjc_aPYyc,402
|
27
27
|
versionhq/knowledge/embedding.py,sha256=KfHc__1THxb5jrg1EMrF-v944RDuIr2hE0l-MtM3Bp0,6826
|
28
28
|
versionhq/knowledge/model.py,sha256=w29mrJv1kiznCh4P4yJMUQxIuyRw1Sk0XYtBXzCxaG4,1786
|
29
|
-
versionhq/knowledge/source.py,sha256
|
30
|
-
versionhq/knowledge/source_docling.py,sha256=
|
29
|
+
versionhq/knowledge/source.py,sha256=-hEUPtJUHHMx4rUKtiHl19J8xAMw-WVBw34zwa2jZ08,13630
|
30
|
+
versionhq/knowledge/source_docling.py,sha256=mg7bgvKePHn2LlA_XzSFCbS0zOo9xfu_aNOf5cEo6c4,5421
|
31
31
|
versionhq/knowledge/storage.py,sha256=7oxCg3W9mFjYH1YmuH9kFtTbNxquzYFjuUjd_TlsB9E,8170
|
32
32
|
versionhq/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
33
|
versionhq/llm/llm_vars.py,sha256=wjQK20cKvph6Vq1v71o4d16zBGcHlwq0bzOT_zWno7w,7041
|
34
34
|
versionhq/llm/model.py,sha256=wlzDUMEyIOm808d1vzqu9gmbB4ch-s_EUvwFR60gR80,17177
|
35
35
|
versionhq/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
36
|
versionhq/memory/contextual_memory.py,sha256=tCsOOAUnfrOL7YiakqGoi3uShzzS870TmGnlGd3z_A4,3556
|
37
|
-
versionhq/memory/model.py,sha256=
|
37
|
+
versionhq/memory/model.py,sha256=MPO8dDP5eAuk9td6bMOq5j2huLzCADFJDrTujHhcWQY,8150
|
38
38
|
versionhq/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
39
|
versionhq/storage/base.py,sha256=p-Jas0fXQan_qotnRD6seQxrT2lj-uw9-SmHQhdppcs,355
|
40
40
|
versionhq/storage/ltm_sqlite_storage.py,sha256=wdUiuwHfJocdk0UGqyrdU4S5Nae1rgsoRNu3LWmGFcI,3951
|
@@ -44,15 +44,14 @@ versionhq/storage/task_output_storage.py,sha256=E1t_Fkt78dPYIOl3MP7LfQ8oGtjlzxBu
|
|
44
44
|
versionhq/storage/utils.py,sha256=ByYXPoEIGJYLUqz-DWjbCAnneNrH1otiYbp12SCILpM,747
|
45
45
|
versionhq/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
46
46
|
versionhq/task/evaluate.py,sha256=WdUgjbZL62XrxyWe5MTz29scfzwmuAHGxJ7GvAB8Fmk,3954
|
47
|
-
versionhq/task/formation.py,sha256=
|
47
|
+
versionhq/task/formation.py,sha256=gBrFmMHvoyqdK9wEa9aBkZImEQV3GMDDX6-RDpw0pEo,6421
|
48
48
|
versionhq/task/formatter.py,sha256=N8Kmk9vtrMtBdgJ8J7RmlKNMdZWSmV8O1bDexmCWgU0,643
|
49
49
|
versionhq/task/log_handler.py,sha256=LT7YnO7gcPR9IZS7eRvMjnHh8crMBFtqduxd8dxIbkk,1680
|
50
|
-
versionhq/task/model.py,sha256=
|
50
|
+
versionhq/task/model.py,sha256=oPnShLU6huN2cfuEiHVO8Zl9_w44G9ZsWEWMBjpHfK4,30675
|
51
51
|
versionhq/task/structured_response.py,sha256=4q-hQPu7oMMHHXEzh9YW4SJ7N5eCZ7OfZ65juyl_jCI,5000
|
52
52
|
versionhq/task/TEMPLATES/Description.py,sha256=V-4kh8xpQTKOcDMi2xnuP-fcNk6kuoz1_5tYBlDLQWQ,420
|
53
|
-
versionhq/
|
54
|
-
versionhq/
|
55
|
-
versionhq/team/team_planner.py,sha256=Zc3zvhPR7T0O8RQoq9CKOrvrll4klemY1rONLFeJ96M,3663
|
53
|
+
versionhq/task_graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
|
+
versionhq/task_graph/model.py,sha256=TsszoTJFeJ4TfSdLAjcGa9QSQyf9Uy3WmechTw0qL3k,22832
|
56
55
|
versionhq/tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
56
|
versionhq/tool/cache_handler.py,sha256=iL8FH7X0G-cdT0uhJwzuhLDaadTXOdfybZcDy151-es,1085
|
58
57
|
versionhq/tool/composio_tool.py,sha256=38mEiVvTkuw1BLD233Bl1Gwxbpss1yfQiZLTWwX6BdA,8648
|
@@ -60,8 +59,8 @@ versionhq/tool/composio_tool_vars.py,sha256=FvBuEXsOQUYnN7RTFxT20kAkiEYkxWKkiVtg
|
|
60
59
|
versionhq/tool/decorator.py,sha256=C4ZM7Xi2gwtEMaSeRo-geo_g_MAkY77WkSLkAuY0AyI,1205
|
61
60
|
versionhq/tool/model.py,sha256=PO4zNWBZcJhYVur381YL1dy6zqurio2jWjtbxOxZMGI,12194
|
62
61
|
versionhq/tool/tool_handler.py,sha256=2m41K8qo5bGCCbwMFferEjT-XZ-mE9F0mDUOBkgivOI,1416
|
63
|
-
versionhq-1.2.1.
|
64
|
-
versionhq-1.2.1.
|
65
|
-
versionhq-1.2.1.
|
66
|
-
versionhq-1.2.1.
|
67
|
-
versionhq-1.2.1.
|
62
|
+
versionhq-1.2.1.1.dist-info/LICENSE,sha256=cRoGGdM73IiDs6nDWKqPlgSv7aR4n-qBXYnJlCMHCeE,1082
|
63
|
+
versionhq-1.2.1.1.dist-info/METADATA,sha256=cjE8Ov1BpANLgfAZAbHO0XmorFk9nAR-rVyJg1AczVc,22166
|
64
|
+
versionhq-1.2.1.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
65
|
+
versionhq-1.2.1.1.dist-info/top_level.txt,sha256=DClQwxDWqIUGeRJkA8vBlgeNsYZs4_nJWMonzFt5Wj0,10
|
66
|
+
versionhq-1.2.1.1.dist-info/RECORD,,
|
versionhq/team/team_planner.py
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from typing import Any, List, Optional, Dict
|
3
|
-
from pydantic import BaseModel, Field
|
4
|
-
|
5
|
-
|
6
|
-
class TeamPlanner:
|
7
|
-
"""
|
8
|
-
A class to handle agent formations based on the given task description.
|
9
|
-
1) complexity
|
10
|
-
2) agent built (or use given agents)
|
11
|
-
3) knowledge, memory sharing
|
12
|
-
4) form a team
|
13
|
-
"""
|
14
|
-
|
15
|
-
from versionhq.task.model import Task, ResponseField, TaskOutput
|
16
|
-
from versionhq.agent.model import Agent
|
17
|
-
|
18
|
-
|
19
|
-
def __init__(self, tasks: List[Task], planner_llm: Optional[Any] = None):
|
20
|
-
self.tasks = tasks
|
21
|
-
self.planner_llm = planner_llm if planner_llm else os.environ.get("DEFAULT_MODEL_NAME")
|
22
|
-
|
23
|
-
|
24
|
-
def _handle_assign_agents(self, unassigned_tasks: List[Task]) -> List[Any]:
|
25
|
-
"""
|
26
|
-
Build an agent and assign it a task, then return a list of Member connecting the agent created and the task given.
|
27
|
-
"""
|
28
|
-
|
29
|
-
from versionhq.agent.model import Agent
|
30
|
-
from versionhq.task.model import Task, ResponseField
|
31
|
-
from versionhq.team.model import Member
|
32
|
-
|
33
|
-
new_member_list: List[Member] = []
|
34
|
-
agent_creator = Agent(
|
35
|
-
role="agent_creator",
|
36
|
-
goal="build an ai agent that can competitively handle the task given",
|
37
|
-
llm=self.planner_llm,
|
38
|
-
)
|
39
|
-
|
40
|
-
for unassgined_task in unassigned_tasks:
|
41
|
-
task = Task(
|
42
|
-
description=f"""
|
43
|
-
Based on the following task summary, draft a AI agent's role and goal in concise manner.
|
44
|
-
Task summary: {unassgined_task.summary}
|
45
|
-
""",
|
46
|
-
response_fields=[
|
47
|
-
ResponseField(title="goal", data_type=str, required=True),
|
48
|
-
ResponseField(title="role", data_type=str, required=True),
|
49
|
-
],
|
50
|
-
)
|
51
|
-
res = task.execute(agent=agent_creator)
|
52
|
-
agent = Agent(
|
53
|
-
role=res.json_dict["role"] if "role" in res.json_dict else res.raw,
|
54
|
-
goal=res.json_dict["goal"] if "goal" in res.json_dict else task.description
|
55
|
-
)
|
56
|
-
if agent.id:
|
57
|
-
team_member = Member(agent=agent, tasks=[unassgined_task], is_manager=False)
|
58
|
-
new_member_list.append(team_member)
|
59
|
-
|
60
|
-
return new_member_list
|
61
|
-
|
62
|
-
|
63
|
-
def _handle_task_planning(self, context: Optional[str] = None, tools: Optional[str] = None) -> TaskOutput:
|
64
|
-
"""
|
65
|
-
Handles the team planning by creating detailed step-by-step plans for each task.
|
66
|
-
"""
|
67
|
-
|
68
|
-
from versionhq.agent.model import Agent
|
69
|
-
from versionhq.task.model import Task
|
70
|
-
|
71
|
-
team_planner = Agent(
|
72
|
-
role="team planner",
|
73
|
-
goal="Plan extremely detailed, step-by-step plan based on the tasks and tools available to each agent so that they can perform the tasks in an exemplary manner and assign a task to each agent.",
|
74
|
-
llm=self.planner_llm,
|
75
|
-
)
|
76
|
-
|
77
|
-
task_summary_list = [task.summary for task in self.tasks]
|
78
|
-
|
79
|
-
class TeamPlanIdea(BaseModel):
|
80
|
-
plan: str | Dict[str, Any] = Field(default=None, description="a decriptive plan to be executed by the team")
|
81
|
-
|
82
|
-
|
83
|
-
task = Task(
|
84
|
-
description=f"""
|
85
|
-
Based on the following task summaries, create the most descriptive plan that the team can execute most efficiently. Take all the task summaries - task's description and tools available - into consideration. Your answer only contains a dictionary.
|
86
|
-
|
87
|
-
Task summaries: {" ".join(task_summary_list)}
|
88
|
-
""",
|
89
|
-
pydantic_output=TeamPlanIdea
|
90
|
-
)
|
91
|
-
output = task.execute(agent=team_planner, context=context, tools=tools)
|
92
|
-
return output
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|