versionhq 1.1.9.14__py3-none-any.whl → 1.1.10.3__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/logger.py +1 -6
- versionhq/_utils/process_config.py +9 -12
- versionhq/agent/TEMPLATES/Backstory.py +4 -3
- versionhq/agent/model.py +143 -109
- versionhq/clients/product/model.py +1 -1
- versionhq/clients/workflow/model.py +1 -1
- versionhq/llm/{llm_variables.py → llm_vars.py} +102 -40
- versionhq/llm/model.py +112 -76
- versionhq/task/model.py +286 -142
- versionhq/task/structured_response.py +142 -0
- versionhq/team/model.py +2 -5
- versionhq/team/team_planner.py +12 -13
- versionhq/tool/__init__.py +0 -56
- versionhq/tool/cache_handler.py +40 -0
- versionhq/tool/composio_tool.py +3 -2
- versionhq/tool/composio_tool_vars.py +56 -0
- versionhq/tool/decorator.py +5 -6
- versionhq/tool/model.py +243 -97
- versionhq/tool/tool_handler.py +11 -19
- {versionhq-1.1.9.14.dist-info → versionhq-1.1.10.3.dist-info}/LICENSE +0 -0
- {versionhq-1.1.9.14.dist-info → versionhq-1.1.10.3.dist-info}/METADATA +26 -25
- versionhq-1.1.10.3.dist-info/RECORD +45 -0
- versionhq/_utils/cache_handler.py +0 -13
- versionhq-1.1.9.14.dist-info/RECORD +0 -43
- {versionhq-1.1.9.14.dist-info → versionhq-1.1.10.3.dist-info}/WHEEL +0 -0
- {versionhq-1.1.9.14.dist-info → versionhq-1.1.10.3.dist-info}/top_level.txt +0 -0
versionhq/tool/model.py
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
from abc import ABC, abstractmethod
|
2
2
|
from inspect import signature
|
3
|
-
from typing import Any, Dict, Callable, Type, Optional, get_args, get_origin
|
3
|
+
from typing import Any, Dict, Callable, Type, Optional, get_args, get_origin, get_type_hints
|
4
4
|
from typing_extensions import Self
|
5
|
-
from pydantic import InstanceOf, BaseModel, ConfigDict, Field, field_validator, model_validator
|
5
|
+
from pydantic import InstanceOf, BaseModel, ConfigDict, Field, field_validator, model_validator, PrivateAttr, create_model
|
6
|
+
from pydantic_core import PydanticCustomError
|
6
7
|
|
7
|
-
from versionhq.
|
8
|
+
from versionhq.llm.llm_vars import SchemaType
|
9
|
+
from versionhq.tool.cache_handler import CacheHandler
|
10
|
+
from versionhq._utils.logger import Logger
|
8
11
|
|
9
12
|
|
10
13
|
class BaseTool(ABC, BaseModel):
|
@@ -12,16 +15,27 @@ class BaseTool(ABC, BaseModel):
|
|
12
15
|
Abstract class for Tool class.
|
13
16
|
"""
|
14
17
|
|
15
|
-
class
|
18
|
+
class ArgsSchemaPlaceholder(BaseModel):
|
16
19
|
pass
|
17
20
|
|
18
|
-
|
21
|
+
_logger: Logger = PrivateAttr(default_factory=lambda: Logger(verbose=True))
|
22
|
+
|
23
|
+
object_type: str = Field(default="function")
|
24
|
+
name: str = Field(default=None)
|
25
|
+
description: str = Field(default=None)
|
26
|
+
properties: Dict[str, Any] = Field(default_factory=dict, description="for llm func calling")
|
27
|
+
args_schema: Type[BaseModel] = Field(default_factory=ArgsSchemaPlaceholder)
|
28
|
+
|
29
|
+
tool_handler: Optional[Dict[str, Any] | Any] = Field(default=None, description="store tool_handler to record the tool usage")
|
30
|
+
should_cache: bool = Field(default=True, description="whether the tool usage should be cached")
|
31
|
+
cache_function: Callable = lambda _args=None, _result=None: True
|
32
|
+
cache_handler: Optional[InstanceOf[CacheHandler]] = Field(default=None)
|
19
33
|
|
20
34
|
|
21
35
|
@field_validator("args_schema", mode="before")
|
22
36
|
@classmethod
|
23
37
|
def _default_args_schema(cls, v: Type[BaseModel]) -> Type[BaseModel]:
|
24
|
-
if not isinstance(v, cls.
|
38
|
+
if not isinstance(v, cls.ArgsSchemaPlaceholder):
|
25
39
|
return v
|
26
40
|
|
27
41
|
return type(
|
@@ -31,21 +45,29 @@ class BaseTool(ABC, BaseModel):
|
|
31
45
|
)
|
32
46
|
|
33
47
|
|
34
|
-
@
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
@field_validator("properties", mode="before")
|
49
|
+
@classmethod
|
50
|
+
def _default_properties(cls, v: Dict[str, Any]) -> Dict[str, Any]:
|
51
|
+
p, r = dict(), list()
|
52
|
+
for k, v in cls._run.__annotations__.items():
|
53
|
+
if k != "return":
|
54
|
+
p.update({ k: { "type": SchemaType(type(v)).convert(), "name": k, }} )
|
55
|
+
r.append(k)
|
56
|
+
|
57
|
+
return {
|
58
|
+
"type": cls.object_type,
|
59
|
+
"function": {
|
60
|
+
"name": cls.name.replace(" ", "_"),
|
61
|
+
"description": cls.description,
|
62
|
+
"parameters": {
|
63
|
+
"type": "object",
|
64
|
+
"properties": p,
|
65
|
+
"required": r,
|
66
|
+
"additionalProperties": False
|
67
|
+
},
|
68
|
+
"strict": True
|
69
|
+
}
|
70
|
+
}
|
49
71
|
|
50
72
|
@model_validator(mode="after")
|
51
73
|
def set_up_tool_handler(self) -> Self:
|
@@ -59,13 +81,9 @@ class Tool(BaseTool):
|
|
59
81
|
|
60
82
|
return self
|
61
83
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if self.function is None:
|
66
|
-
self.function = self._run
|
67
|
-
self._set_args_schema_from_func()
|
68
|
-
return self
|
84
|
+
@abstractmethod
|
85
|
+
def _run(self, *args: Any, **kwargs: Any,) -> Any:
|
86
|
+
"""any handling"""
|
69
87
|
|
70
88
|
|
71
89
|
@staticmethod
|
@@ -95,108 +113,236 @@ class Tool(BaseTool):
|
|
95
113
|
import json
|
96
114
|
raw_args = json.loads(raw_args)
|
97
115
|
except json.JSONDecodeError as e:
|
98
|
-
raise ValueError(f"Failed to parse arguments as JSON: {e}")
|
116
|
+
raise ValueError(f"Failed to parse arguments as JSON: {str(e)}")
|
99
117
|
|
100
118
|
try:
|
101
119
|
validated_args = self.args_schema.model_validate(raw_args)
|
102
120
|
return validated_args.model_dump()
|
103
121
|
|
104
122
|
except Exception as e:
|
105
|
-
raise ValueError(f"Arguments validation failed: {e}")
|
123
|
+
raise ValueError(f"Arguments validation failed: {str(e)}")
|
106
124
|
|
107
125
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
126
|
+
def _create_schema(self) -> type[BaseModel]:
|
127
|
+
"""
|
128
|
+
Create a Pydantic schema from a function's signature
|
129
|
+
"""
|
130
|
+
import inspect
|
131
|
+
|
132
|
+
sig = inspect.signature(self.func)
|
133
|
+
type_hints = get_type_hints(self.func)
|
134
|
+
fields = {}
|
135
|
+
for param_name, param in sig.parameters.items():
|
136
|
+
if param_name in ("self", "cls"):
|
137
|
+
continue
|
138
|
+
|
139
|
+
annotation = type_hints.get(param_name, Any)
|
140
|
+
default = ... if param.default == param.empty else param.default
|
141
|
+
fields[param_name] = (annotation, Field(default=default))
|
142
|
+
|
143
|
+
schema_name = f"{self.func.__name__.title()}Schema"
|
144
|
+
return create_model(schema_name, **fields)
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
class Tool(BaseTool):
|
149
|
+
func: Callable = Field(default=None)
|
150
|
+
|
151
|
+
|
152
|
+
@model_validator(mode="after")
|
153
|
+
def validate_func(self) -> Self:
|
154
|
+
if not self.func and not self._run:
|
155
|
+
self._logger.log(level="error", message=f"Tool must have a function", color="red")
|
156
|
+
raise PydanticCustomError("function_missing", f"Function is missing in the tool.", {})
|
157
|
+
|
158
|
+
elif self.func and not isinstance(self.func, Callable):
|
159
|
+
self._logger.log(level="error", message=f"The tool is missing a valid function", color="red")
|
160
|
+
raise PydanticCustomError("invalid_function", f"The value in the function field must be callable.", {})
|
161
|
+
|
162
|
+
else:
|
163
|
+
try:
|
164
|
+
self.args_schema = self._create_schema_from_function()
|
165
|
+
self._validate_function_signature()
|
166
|
+
|
167
|
+
except Exception as e:
|
168
|
+
self._logger.log(level="error", message=f"The tool is missing a valid function: {str(e)}", color="red")
|
169
|
+
raise PydanticCustomError("invalid_function", f"Invalid function: {str(e)}", {})
|
170
|
+
|
171
|
+
return self
|
172
|
+
|
173
|
+
|
174
|
+
@model_validator(mode="after")
|
175
|
+
def set_up_name(self) -> Self:
|
176
|
+
if not self.name:
|
177
|
+
self.name = self.func.__name__ if self.func else ""
|
178
|
+
|
179
|
+
return self
|
180
|
+
|
181
|
+
|
182
|
+
@model_validator(mode="after")
|
183
|
+
def set_up_description(self) -> Self:
|
184
|
+
if not self.description:
|
185
|
+
if not self.args_schema:
|
186
|
+
self.args_schema = self._default_args_schema(self)
|
187
|
+
|
188
|
+
args_schema = {
|
189
|
+
name: {
|
190
|
+
"description": field.description,
|
191
|
+
"type": self._get_arg_annotations(field.annotation),
|
192
|
+
}
|
193
|
+
for name, field in self.args_schema.model_fields.items()
|
194
|
+
}
|
195
|
+
self.description = f"Tool: {self.name}\nArgs: {args_schema}"
|
196
|
+
|
197
|
+
return self
|
198
|
+
|
199
|
+
|
200
|
+
@model_validator(mode="after")
|
201
|
+
def set_up_args_schema(self) -> Self:
|
202
|
+
"""
|
203
|
+
Set up args schema based on the given function.
|
204
|
+
"""
|
205
|
+
if self.func:
|
206
|
+
self.args_schema = self._create_schema_from_function()
|
207
|
+
return self
|
208
|
+
|
209
|
+
|
210
|
+
@model_validator(mode="after")
|
211
|
+
def set_up_func_calling_properties(self) -> Self:
|
212
|
+
"""
|
213
|
+
Format function_calling params from args_schema.
|
214
|
+
"""
|
215
|
+
|
216
|
+
p, r = dict(), list()
|
217
|
+
if self.args_schema:
|
218
|
+
for name, field in self.args_schema.model_fields.items():
|
219
|
+
if name != "kwargs" and name != "args":
|
220
|
+
p.update(
|
221
|
+
{
|
222
|
+
name: {
|
223
|
+
"description": field.description if field.description else "",
|
224
|
+
"type": SchemaType(self._get_arg_annotations(field.annotation)).convert(),
|
225
|
+
}
|
226
|
+
}
|
227
|
+
)
|
228
|
+
r.append(name)
|
229
|
+
|
230
|
+
properties = {
|
231
|
+
"type": self.object_type,
|
232
|
+
"function": {
|
233
|
+
"name": self.name.replace(" ", "_"),
|
234
|
+
"description": self.description if self.description else "a tool function to execute",
|
235
|
+
"parameters": {
|
236
|
+
"type": "object",
|
237
|
+
"properties": p,
|
238
|
+
"required": r,
|
239
|
+
"additionalProperties": False
|
240
|
+
},
|
241
|
+
"strict": True,
|
242
|
+
},
|
243
|
+
}
|
244
|
+
self.properties = properties
|
117
245
|
return self
|
118
246
|
|
119
247
|
|
248
|
+
def _create_schema_from_function(self) -> type[BaseModel]:
|
249
|
+
"""
|
250
|
+
Create a Pydantic schema from a function's signature
|
251
|
+
"""
|
252
|
+
import inspect
|
253
|
+
|
254
|
+
sig = inspect.signature(self.func)
|
255
|
+
type_hints = get_type_hints(self.func)
|
256
|
+
fields = {}
|
257
|
+
for param_name, param in sig.parameters.items():
|
258
|
+
if param_name in ("self", "cls"):
|
259
|
+
continue
|
260
|
+
|
261
|
+
annotation = type_hints.get(param_name, Any)
|
262
|
+
default = ... if param.default == param.empty else param.default
|
263
|
+
fields[param_name] = (annotation, Field(default=default))
|
264
|
+
|
265
|
+
schema_name = f"{self.func.__name__.title()}Schema"
|
266
|
+
return create_model(schema_name, **fields)
|
267
|
+
|
268
|
+
|
269
|
+
def _validate_function_signature(self) -> None:
|
270
|
+
"""
|
271
|
+
Validate that the function signature matches the args schema.
|
272
|
+
"""
|
273
|
+
|
274
|
+
import inspect
|
275
|
+
|
276
|
+
sig = inspect.signature(self.func)
|
277
|
+
schema_fields = self.args_schema.model_fields
|
278
|
+
|
279
|
+
for param_name, param in sig.parameters.items():
|
280
|
+
if param_name in ("self", "cls"):
|
281
|
+
continue
|
282
|
+
|
283
|
+
if param.kind in (inspect.Parameter.VAR_KEYWORD, inspect.Parameter.VAR_POSITIONAL):
|
284
|
+
continue
|
285
|
+
|
286
|
+
if param.default == inspect.Parameter.empty:
|
287
|
+
if param_name not in schema_fields:
|
288
|
+
raise ValueError(f"Required function parameter '{param_name}' not found in args_schema")
|
289
|
+
|
290
|
+
|
120
291
|
def _run(self, *args: Any, **kwargs: Any) -> Any:
|
121
|
-
return self.
|
292
|
+
return self.func(*args, **kwargs)
|
122
293
|
|
123
294
|
|
124
|
-
def
|
295
|
+
def _handle_toolset(self, params: Dict[str, Any] = None) -> Any:
|
125
296
|
"""
|
126
|
-
|
297
|
+
Read the cache from the ToolHandler instance or execute _run() method.
|
127
298
|
"""
|
128
|
-
from versionhq.tool.tool_handler import ToolHandler
|
129
299
|
|
130
|
-
|
131
|
-
tool_set = ToolSet(tool=self, kwargs={})
|
300
|
+
from versionhq.tool.tool_handler import ToolHandler
|
132
301
|
|
133
|
-
if self.
|
134
|
-
|
302
|
+
if not self.args_schema:
|
303
|
+
self.args_schema = self._create_schema_from_function()
|
135
304
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
305
|
+
result = None
|
306
|
+
acceptable_args = self.args_schema.model_json_schema()["properties"].keys()
|
307
|
+
acceptable_kwargs = { k: v for k, v in params.items() if k in acceptable_args } if params else dict()
|
308
|
+
parsed_kwargs = self._parse_args(raw_args=acceptable_kwargs)
|
309
|
+
tool_set = ToolSet(tool=self, kwargs=acceptable_kwargs)
|
140
310
|
|
141
|
-
|
142
|
-
|
143
|
-
|
311
|
+
if self.tool_handler and isinstance(self.tool_handler, ToolHandler):
|
312
|
+
if self.tool_handler.has_called_before(tool_set):
|
313
|
+
self.tool_handler.error = "Agent execution error"
|
144
314
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
result = self.function(**parsed_kwargs) if self.function else None
|
315
|
+
elif self.tool_handler.cache:
|
316
|
+
result = self.tool_handler.cache.read(tool_name=tool_set.tool.name, input=str(tool_set.kwargs))
|
317
|
+
if not result:
|
318
|
+
result = self.func(**parsed_kwargs)
|
150
319
|
|
151
320
|
else:
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
321
|
+
result = self.func(**parsed_kwargs)
|
322
|
+
|
323
|
+
else:
|
324
|
+
tool_handler = ToolHandler(last_used_tool=tool_set, cache_handler=self.cache_handler, should_cache=self.should_cache)
|
325
|
+
self.tool_handler = tool_handler
|
326
|
+
result = self.func(**parsed_kwargs)
|
156
327
|
|
157
328
|
|
158
329
|
if self.should_cache is True:
|
159
|
-
self.tool_handler.record_last_tool_used(tool_set, result, self.should_cache)
|
330
|
+
self.tool_handler.record_last_tool_used(last_used_tool=tool_set, output=result, should_cache=self.should_cache)
|
160
331
|
|
161
332
|
return result
|
162
333
|
|
163
334
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
}
|
171
|
-
for name, field in self.args_schema.model_fields.items()
|
172
|
-
}
|
173
|
-
|
174
|
-
return f"Tool Name: {self.name}\nTool Arguments: {args_schema}\nGoal: {self.goal}"
|
335
|
+
def run(self, params: Dict[str, Any] = None) -> Any:
|
336
|
+
"""
|
337
|
+
Execute a tool using a toolset and cached tools
|
338
|
+
"""
|
339
|
+
result = self._handle_toolset(params)
|
340
|
+
return result
|
175
341
|
|
176
342
|
|
177
343
|
class ToolSet(BaseModel):
|
178
344
|
"""
|
179
|
-
Store the tool called and any kwargs used.
|
345
|
+
Store the tool called and any kwargs used. (The tool name and kwargs will be stored in the cache.)
|
180
346
|
"""
|
181
|
-
tool: InstanceOf[Tool] |
|
182
|
-
kwargs: Optional[Dict[str, Any]] = Field(..., description="kwargs passed to the tool")
|
183
|
-
|
184
|
-
|
185
|
-
class InstructorToolSet(BaseModel):
|
186
|
-
tool: InstanceOf[Tool] | Any = Field(..., description="store the tool instance to be called.")
|
347
|
+
tool: InstanceOf[Tool] | Type[Tool] = Field(..., description="store the tool instance to be called.")
|
187
348
|
kwargs: Optional[Dict[str, Any]] = Field(..., description="kwargs passed to the tool")
|
188
|
-
|
189
|
-
|
190
|
-
class CacheTool(BaseModel):
|
191
|
-
"""
|
192
|
-
Default tools to hit the cache.
|
193
|
-
"""
|
194
|
-
|
195
|
-
name: str = "Hit Cache"
|
196
|
-
cache_handler: CacheHandler = Field(default_factory=CacheHandler)
|
197
|
-
|
198
|
-
def hit_cache(self, key):
|
199
|
-
split = key.split("tool:")
|
200
|
-
tool = split[1].split("|input:")[0].strip()
|
201
|
-
tool_input = split[1].split("|input:")[1].strip()
|
202
|
-
return self.cache_handler.read(tool, tool_input)
|
versionhq/tool/tool_handler.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from typing import Optional, Any
|
2
2
|
from pydantic import InstanceOf
|
3
3
|
|
4
|
-
from versionhq.tool.model import ToolSet
|
5
|
-
from versionhq.
|
4
|
+
from versionhq.tool.model import ToolSet
|
5
|
+
from versionhq.tool.cache_handler import CacheHandler, CacheTool
|
6
6
|
|
7
7
|
|
8
8
|
class ToolHandler:
|
@@ -10,34 +10,26 @@ class ToolHandler:
|
|
10
10
|
Record the tool usage by ToolSet instance with cache and error recording.
|
11
11
|
"""
|
12
12
|
|
13
|
-
last_used_tool: InstanceOf[ToolSet]
|
14
|
-
cache:
|
13
|
+
last_used_tool: InstanceOf[ToolSet]
|
14
|
+
cache: InstanceOf[CacheHandler] = CacheHandler()
|
15
15
|
error: Optional[str]
|
16
16
|
should_cache: bool
|
17
17
|
|
18
|
-
def __init__(
|
19
|
-
self,
|
20
|
-
last_used_tool: InstanceOf[ToolSet] | InstanceOf[InstructorToolSet] = None,
|
21
|
-
cache_handler: Optional[CacheHandler] = None,
|
22
|
-
should_cache: bool = True
|
23
|
-
):
|
24
|
-
self.cache = cache_handler
|
18
|
+
def __init__(self, last_used_tool: InstanceOf[ToolSet] = None, cache_handler: InstanceOf[CacheHandler] = None, should_cache: bool = True):
|
25
19
|
self.last_used_tool = last_used_tool
|
20
|
+
self.cache = cache_handler if cache_handler else CacheHandler()
|
26
21
|
self.should_cache = should_cache
|
27
22
|
|
28
23
|
|
29
|
-
def record_last_tool_used(
|
30
|
-
self, last_used_tool: InstanceOf[ToolSet] | InstanceOf[InstructorToolSet], output: str, should_cache: bool = True
|
31
|
-
) -> Any:
|
32
|
-
from versionhq.tool.model import CacheTool
|
33
|
-
|
24
|
+
def record_last_tool_used(self, last_used_tool: InstanceOf[ToolSet], output: str, should_cache: bool = True) -> None:
|
34
25
|
self.last_used_tool = last_used_tool
|
35
26
|
|
36
|
-
if
|
37
|
-
self.cache
|
27
|
+
if should_cache:
|
28
|
+
self.cache = CacheHandler()
|
29
|
+
self.cache.add(tool_name=last_used_tool.tool.name, input=str(last_used_tool.kwargs), output=output)
|
38
30
|
|
39
31
|
|
40
|
-
def has_called_before(self, tool_set: ToolSet = None) -> bool:
|
32
|
+
def has_called_before(self, tool_set: InstanceOf[ToolSet] = None) -> bool:
|
41
33
|
if tool_set is None or not self.last_used_tool:
|
42
34
|
return False
|
43
35
|
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: versionhq
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.10.3
|
4
4
|
Summary: LLM orchestration frameworks for model-agnostic AI agents that handle complex outbound workflows
|
5
5
|
Author-email: Kuriko Iwai <kuriko@versi0n.io>
|
6
6
|
License: MIT License
|
@@ -26,6 +26,7 @@ License: MIT License
|
|
26
26
|
SOFTWARE.
|
27
27
|
|
28
28
|
Project-URL: Homepage, https://versi0n.io
|
29
|
+
Project-URL: Documentation, https://chief-oxygen-8a2.notion.site/Documentation-17e923685cf98001a5fad5c4b2acd79b?pvs=73
|
29
30
|
Project-URL: Repository, https://github.com/versionHQ/multi-agent-system
|
30
31
|
Project-URL: Issues, https://github.com/versionHQ/multi-agent-system/issues
|
31
32
|
Keywords: orchestration framework,orchestration,ai agent,multi-agent system,RAG,agent
|
@@ -60,7 +61,7 @@ Requires-Dist: composio-langchain>=0.6.12
|
|
60
61
|
|
61
62
|

|
62
63
|
[](https://github.com/versionHQ/multi-agent-system/actions/workflows/publish.yml)
|
63
|
-

|
64
65
|

|
65
66
|

|
66
67
|
|
@@ -76,8 +77,9 @@ Messaging workflows are created at individual level, and will be deployed on thi
|
|
76
77
|
|
77
78
|
- [PyPI](https://pypi.org/project/versionhq/)
|
78
79
|
- [Github (LLM orchestration)](https://github.com/versionHQ/multi-agent-system)
|
79
|
-
- [
|
80
|
-
- [
|
80
|
+
- [Doc](https://chief-oxygen-8a2.notion.site/Documentation-17e923685cf98001a5fad5c4b2acd79b?pvs=4)
|
81
|
+
<!-- - [Github (Test client app)](https://github.com/versionHQ/test-client-app) -->
|
82
|
+
- [Use case](https://versi0n.io/): Client web app for the outbound messaging automation
|
81
83
|
|
82
84
|
|
83
85
|
<hr />
|
@@ -152,6 +154,9 @@ Multiple `agents` can form a `team` to complete complex tasks together.
|
|
152
154
|
from versionhq.agent.model import Agent
|
153
155
|
from versionhq.task.model import Task, ResponseField
|
154
156
|
|
157
|
+
def my_callback_func():
|
158
|
+
"""callback func"""
|
159
|
+
|
155
160
|
agent = Agent(
|
156
161
|
role="demo",
|
157
162
|
goal="amazing project goal",
|
@@ -162,13 +167,11 @@ Multiple `agents` can form a `team` to complete complex tasks together.
|
|
162
167
|
|
163
168
|
task = Task(
|
164
169
|
description="Amazing task",
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
ResponseField(title="test1", type=str, required=True),
|
169
|
-
ResponseField(title="test2", type=list, required=True),
|
170
|
+
response_fields=[
|
171
|
+
ResponseField(title="test1", data_type=str, required=True),
|
172
|
+
ResponseField(title="test2", data_type=list, items=str, required=True),
|
170
173
|
],
|
171
|
-
|
174
|
+
callbacks=[my_callback_func]
|
172
175
|
)
|
173
176
|
res = task.execute_sync(agent=agent, context="amazing context to consider.")
|
174
177
|
return res.to_dict()
|
@@ -192,13 +195,13 @@ This will return a dictionary with keys defined in the `ResponseField`.
|
|
192
195
|
|
193
196
|
task_1 = Task(
|
194
197
|
description="Analyze the client's business model.",
|
195
|
-
|
198
|
+
response_fields=[ResponseField(title="test1", data_type=str, required=True),],
|
196
199
|
allow_delegation=True
|
197
200
|
)
|
198
201
|
|
199
202
|
task_2 = Task(
|
200
203
|
description="Define the cohort.",
|
201
|
-
|
204
|
+
response_fields=[ResponseField(title="test1", data_type=int, required=True),],
|
202
205
|
allow_delegation=False
|
203
206
|
)
|
204
207
|
|
@@ -234,7 +237,7 @@ Tasks can be delegated to a team manager, peers in the team, or completely new a
|
|
234
237
|
- [Composio](https://composio.dev/): Conect RAG agents with external tools, Apps, and APIs to perform actions and receive triggers. We use [tools](https://composio.dev/tools) and [RAG tools](https://app.composio.dev/app/ragtool) from Composio toolset.
|
235
238
|
|
236
239
|
**Deployment**
|
237
|
-
- Python: Primary programming language.
|
240
|
+
- Python: Primary programming language. v3.13 is recommended.
|
238
241
|
- [uv](https://docs.astral.sh/uv/): Python package installer and resolver
|
239
242
|
- [pre-commit](https://pre-commit.com/): Manage and maintain pre-commit hooks
|
240
243
|
- [setuptools](https://pypi.org/project/setuptools/): Build python modules
|
@@ -306,19 +309,17 @@ src/
|
|
306
309
|
|
307
310
|
## Contributing
|
308
311
|
|
309
|
-
1.
|
310
|
-
|
311
|
-
2. Create your feature branch (`git checkout -b feature/your-amazing-feature`)
|
312
|
+
1. Create your feature branch (`git checkout -b feature/your-amazing-feature`)
|
312
313
|
|
313
|
-
|
314
|
+
2. Create amazing features
|
314
315
|
|
315
|
-
|
316
|
+
3. Test the features using the `tests` directory.
|
316
317
|
|
317
318
|
- Add a test function to respective components in the `tests` directory.
|
318
|
-
- Add your `LITELLM_API_KEY`, `OPENAI_API_KEY`, `COMPOSIO_API_KEY`, `DEFAULT_USER_ID` to the Github `repository secrets`
|
319
|
+
- Add your `LITELLM_API_KEY`, `OPENAI_API_KEY`, `COMPOSIO_API_KEY`, `DEFAULT_USER_ID` to the Github `repository secrets` located at settings > secrets & variables > Actions.
|
319
320
|
- Run a test.
|
320
321
|
```
|
321
|
-
uv run pytest tests -vv
|
322
|
+
uv run pytest tests -vv --cache-clear
|
322
323
|
```
|
323
324
|
|
324
325
|
**pytest**
|
@@ -326,10 +327,10 @@ src/
|
|
326
327
|
* When adding a new file to `tests`, name the file ended with `_test.py`.
|
327
328
|
* When adding a new feature to the file, name the feature started with `test_`.
|
328
329
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
330
|
+
4. Pull the latest version of source code from the main branch (`git pull origin main`) *Address conflicts if any.
|
331
|
+
5. Commit your changes (`git add .` / `git commit -m 'Add your-amazing-feature'`)
|
332
|
+
6. Push to the branch (`git push origin feature/your-amazing-feature`)
|
333
|
+
7. Open a pull request
|
333
334
|
|
334
335
|
|
335
336
|
**Optional**
|
@@ -342,7 +343,7 @@ src/
|
|
342
343
|
```
|
343
344
|
The frontend will be available at `http://localhost:3000`.
|
344
345
|
|
345
|
-
* `production` is available at `https://versi0n.io`. Currently, we are running alpha test.
|
346
|
+
* `production` use case is available at `https://versi0n.io`. Currently, we are running alpha test.
|
346
347
|
|
347
348
|
|
348
349
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
versionhq/__init__.py,sha256=lctzH-NkGs_wSYgbGkPFDcsPpGvFwE8UegxnHsiRp0E,951
|
2
|
+
versionhq/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
versionhq/_utils/i18n.py,sha256=TwA_PnYfDLA6VqlUDPuybdV9lgi3Frh_ASsb_X8jJo8,1483
|
4
|
+
versionhq/_utils/logger.py,sha256=U-MpeGueA6YS8Ptfy0VnU_ePsZP-8Pvkvi0tZ4s_UMg,1438
|
5
|
+
versionhq/_utils/process_config.py,sha256=jbPGXK2Kb4iyCugJ3FwRJuU0wL5Trq2x4xFQz2uOyFY,746
|
6
|
+
versionhq/_utils/rpm_controller.py,sha256=dUgFd6JtdjiLLTRmrjsBHdTaLn73XFuKpLbJh7thf2A,2289
|
7
|
+
versionhq/_utils/usage_metrics.py,sha256=hhq1OCW8Z4V93vwW2O2j528EyjOlF8wlTsX5IL-7asA,1106
|
8
|
+
versionhq/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
versionhq/agent/model.py,sha256=tdqrnSA212I-oG1GLDw_9AjymjYxbKLBmsXJrghIxhM,19592
|
10
|
+
versionhq/agent/parser.py,sha256=Z_swUPO3piJQuYU8oVYwXWeR2zjmNb4PxbXZeR-GlIg,4694
|
11
|
+
versionhq/agent/TEMPLATES/Backstory.py,sha256=Gub3SUbdrNAwV0ITLYdZFJ4VFZRDfDRPdBZrtlknrds,554
|
12
|
+
versionhq/agent/TEMPLATES/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
versionhq/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
versionhq/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
versionhq/clients/customer/__init__.py,sha256=-YXh1FQfvpfLacK8SUC7bD7Wx_eIEi4yrkCC_cUasFg,217
|
16
|
+
versionhq/clients/customer/model.py,sha256=_AtaVVMm9MgCwrQ-HTRQ2oXUMKrSCEfZwE2JdRz3xTw,2508
|
17
|
+
versionhq/clients/product/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
versionhq/clients/product/model.py,sha256=hLTvvQsatNuq0DtyTqpP_gRKgnv6N4uRjavnGfk7b6Y,3695
|
19
|
+
versionhq/clients/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
+
versionhq/clients/workflow/model.py,sha256=FNftenLLoha0bkivrjId32awLHAkBwIT8iNljdic_bw,6003
|
21
|
+
versionhq/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
+
versionhq/llm/llm_vars.py,sha256=PO__b-h5e-6oQ-uoIgXx3lPSAUPUwXYfdVRW73fvX14,8761
|
23
|
+
versionhq/llm/model.py,sha256=0vjFM_BC4B6URG2PRZLydmL8bE_hqsCYFyQHNt4GfGg,13408
|
24
|
+
versionhq/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
+
versionhq/storage/task_output_storage.py,sha256=xoBJHeqUyQt6iJoR1WQTghP-fyxXL66qslpX1QC2-4o,4827
|
26
|
+
versionhq/task/__init__.py,sha256=l2r_g01i91JAGlOoHZP_Gh2WCk6mo9D19lcqt7sKMpQ,186
|
27
|
+
versionhq/task/formatter.py,sha256=N8Kmk9vtrMtBdgJ8J7RmlKNMdZWSmV8O1bDexmCWgU0,643
|
28
|
+
versionhq/task/log_handler.py,sha256=KJRrcNZgFSKhlNzvtYFnvtp6xukaF1s7ifX9u4zWrN8,1683
|
29
|
+
versionhq/task/model.py,sha256=uBB98fIWoqHmnWzYYRgYeG1sw9yLrrwTjWsweMoRlf0,25231
|
30
|
+
versionhq/task/structured_response.py,sha256=FbDDnTixghowYNr95FigzpxNIc_A6pPzVVCu8kDgruM,4790
|
31
|
+
versionhq/team/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
32
|
+
versionhq/team/model.py,sha256=NzcRXWwP0adWL9vsnsmI-A5dOcE3199FGmGgemUB2VA,20043
|
33
|
+
versionhq/team/team_planner.py,sha256=XkM93ItI59cuEzMN1s1jJ-B4LyalSZnAlYBY5SUCbVs,3603
|
34
|
+
versionhq/tool/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
+
versionhq/tool/cache_handler.py,sha256=iL8FH7X0G-cdT0uhJwzuhLDaadTXOdfybZcDy151-es,1085
|
36
|
+
versionhq/tool/composio_tool.py,sha256=38mEiVvTkuw1BLD233Bl1Gwxbpss1yfQiZLTWwX6BdA,8648
|
37
|
+
versionhq/tool/composio_tool_vars.py,sha256=FvBuEXsOQUYnN7RTFxT20kAkiEYkxWKkiVtgpqOzKZQ,1843
|
38
|
+
versionhq/tool/decorator.py,sha256=C4ZM7Xi2gwtEMaSeRo-geo_g_MAkY77WkSLkAuY0AyI,1205
|
39
|
+
versionhq/tool/model.py,sha256=5qG-OH7zohvepPDOjdjDulhEqmNUM4osiyk5LaxmSiU,12333
|
40
|
+
versionhq/tool/tool_handler.py,sha256=2m41K8qo5bGCCbwMFferEjT-XZ-mE9F0mDUOBkgivOI,1416
|
41
|
+
versionhq-1.1.10.3.dist-info/LICENSE,sha256=7CCXuMrAjPVsUvZrsBq9DsxI2rLDUSYXR_qj4yO_ZII,1077
|
42
|
+
versionhq-1.1.10.3.dist-info/METADATA,sha256=HF7BiaGsEsAIlgHVlFq3IzIs5cpsOBzNqe56pv6teY4,16356
|
43
|
+
versionhq-1.1.10.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
44
|
+
versionhq-1.1.10.3.dist-info/top_level.txt,sha256=DClQwxDWqIUGeRJkA8vBlgeNsYZs4_nJWMonzFt5Wj0,10
|
45
|
+
versionhq-1.1.10.3.dist-info/RECORD,,
|