versionhq 1.2.1.8__tar.gz → 1.2.1.10__tar.gz
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-1.2.1.8 → versionhq-1.2.1.10}/PKG-INFO +1 -1
- versionhq-1.2.1.8/docs/core/Agent.md → versionhq-1.2.1.10/docs/core/agent/index.md +116 -88
- versionhq-1.2.1.8/docs/core/task.md → versionhq-1.2.1.10/docs/core/task/index.md +1 -1
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/mkdocs.yml +7 -4
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/pyproject.toml +1 -1
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/__init__.py +1 -1
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/draft.py +28 -17
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/model.py +14 -7
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/PKG-INFO +1 -1
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/SOURCES.txt +3 -3
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/formation_test.py +0 -1
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task_graph/doc_test.py +1 -5
- versionhq-1.2.1.10/tests/task_graph/task_graph_test.py +27 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/uv.lock +31 -31
- versionhq-1.2.1.8/tests/task_graph/task_graph_test.py +0 -18
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.env.sample +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/deploy_docs.yml +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/publish.yml +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/publish_testpypi.yml +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/run_tests.yml +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/security_check.yml +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.gitignore +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.pre-commit-config.yaml +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.python-version +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/LICENSE +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/README.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/SECURITY.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/db/preprocess.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/CNAME +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/_logos/favicon.ico +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/_logos/logo192.png +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/task/evaluation.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/task/response-field.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/task/task-output.md +0 -0
- /versionhq-1.2.1.8/docs/core/task-graph.md → /versionhq-1.2.1.10/docs/core/task-graph/index.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/tool.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/index.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/quickstart.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/stylesheets/main.css +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/tags.md +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/requirements-dev.txt +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/requirements.txt +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/runtime.txt +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/setup.cfg +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/i18n.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/logger.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/process_config.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/usage_metrics.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/vars.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/TEMPLATES/Backstory.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/TEMPLATES/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/inhouse_agents.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/parser.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/rpm_controller.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent_network/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent_network/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/cli/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/customer/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/customer/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/product/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/product/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/workflow/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/workflow/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/_utils.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/embedding.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/source.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/source_docling.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/storage.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/llm/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/llm/llm_vars.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/llm/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/memory/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/memory/contextual_memory.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/memory/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/base.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/ltm_sqlite_storage.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/mem0_storage.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/rag_storage.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/task_output_storage.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/utils.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/TEMPLATES/Description.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/evaluate.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/formation.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/formatter.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/log_handler.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/structured_response.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/colors.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/cache_handler.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/composio_tool.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/composio_tool_vars.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/decorator.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/model.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/tool_handler.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/dependency_links.txt +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/requires.txt +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/top_level.txt +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent/agent_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent/doc_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent_network/Prompts/Demo_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent_network/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent_network/agent_network_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/cli/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/clients/customer_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/clients/product_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/clients/workflow_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/conftest.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/doc_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/knowledge/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/knowledge/knowledge_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/knowledge/mock_report_compressed.pdf +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/llm/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/llm/llm_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/memory/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/memory/memory_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/doc_taskoutput_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/doc_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/llm_connection_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/task_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task_graph/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/__init__.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/composio_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/doc_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/tool_test.py +0 -0
- {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/usecase_test.py +0 -0
@@ -27,9 +27,9 @@ agent = vhq.Agent(
|
|
27
27
|
|
28
28
|
<hr />
|
29
29
|
|
30
|
-
##
|
30
|
+
## Customizing
|
31
31
|
|
32
|
-
|
32
|
+
**Model Optimization**
|
33
33
|
|
34
34
|
`[var]`<bold>`llm: Optional[str | LLM | Dict[str, Any]] = "gpt-4o"`</bold>
|
35
35
|
|
@@ -47,7 +47,9 @@ agent = vhq.Agent(
|
|
47
47
|
)
|
48
48
|
```
|
49
49
|
|
50
|
-
|
50
|
+
<hr/>
|
51
|
+
|
52
|
+
**Switching Models**
|
51
53
|
|
52
54
|
`[class method]`<bold>`update_llm(self, llm: Any = None, llm_config: Optional[Dict[str, Any]] = None) -> Self`<bold>
|
53
55
|
|
@@ -69,12 +71,14 @@ assert agent.llm.max_tokens == 3000
|
|
69
71
|
|
70
72
|
<hr/>
|
71
73
|
|
72
|
-
|
74
|
+
**Developer Prompt (System Prompt)**
|
73
75
|
|
74
76
|
`[var]`<bold>`backstory: Optional[str] = TEMPLATE_BACKSTORY`<bold>
|
75
77
|
|
76
78
|
Backstory will be drafted automatically using the given role, goal and other values in the Agent model, and converted into the **developer prompt** when the agent executes the task.
|
77
79
|
|
80
|
+
<hr/>
|
81
|
+
|
78
82
|
**Backstory template (full) for auto drafting:**
|
79
83
|
|
80
84
|
```python
|
@@ -127,9 +131,11 @@ agent = vhq.Agent(
|
|
127
131
|
)
|
128
132
|
```
|
129
133
|
|
130
|
-
|
134
|
+
<hr />
|
135
|
+
|
136
|
+
## Executing Tasks
|
131
137
|
|
132
|
-
|
138
|
+
**Delegation**
|
133
139
|
|
134
140
|
`[var]`<bold>`allow_delegation: [bool] = False`</bold>
|
135
141
|
|
@@ -145,7 +151,9 @@ agent = vhq.Agent(
|
|
145
151
|
)
|
146
152
|
```
|
147
153
|
|
148
|
-
|
154
|
+
<hr />
|
155
|
+
|
156
|
+
**Max Retry Limit**
|
149
157
|
|
150
158
|
`[var]`<bold>`max_retry_limit: Optional[int] = 2`</bold>
|
151
159
|
|
@@ -161,7 +169,9 @@ agent = vhq.Agent(
|
|
161
169
|
)
|
162
170
|
```
|
163
171
|
|
164
|
-
|
172
|
+
<hr />
|
173
|
+
|
174
|
+
**Maximum Number of Iterations (maxit)**
|
165
175
|
|
166
176
|
`[var]`<bold>`maxit: Optional[int] = 25`</bold>
|
167
177
|
|
@@ -179,76 +189,9 @@ agent = vhq.Agent(
|
|
179
189
|
)
|
180
190
|
```
|
181
191
|
|
182
|
-
|
183
|
-
|
184
|
-
`[var]`<bold>`callbacks: Optional[List[Callable]] = None`</bold>
|
185
|
-
|
186
|
-
You can add callback functions that the agent will run after executing any task.
|
187
|
-
|
188
|
-
By default, raw response from the agent will be added to the arguments of the callback function.
|
189
|
-
|
190
|
-
e.g. Format a response after executing the task:
|
191
|
-
|
192
|
-
```python
|
193
|
-
import json
|
194
|
-
import versionhq as vhq
|
195
|
-
from typing import Dict, Any
|
196
|
-
|
197
|
-
|
198
|
-
def format_response(res: str = None) -> str | Dict[str, Any]:
|
199
|
-
try:
|
200
|
-
r = json.dumps(eval(res))
|
201
|
-
formatted_res = json.loads(r)
|
202
|
-
return formatted_res
|
203
|
-
except:
|
204
|
-
return res
|
205
|
-
|
206
|
-
agent = vhq.Agent(
|
207
|
-
role="Marketing Analyst",
|
208
|
-
goal="Coping with increased price competition in saturated markets.",
|
209
|
-
callbacks=[format_response]
|
210
|
-
)
|
211
|
-
```
|
212
|
-
|
213
|
-
**Multiple callbacks to call**
|
214
|
-
|
215
|
-
The callback functions are called in order of the list index referring to the task response and response from the previous callback functions by default.
|
216
|
-
|
217
|
-
e.g. Validate an initial response from the assigned agent, and format the response.
|
218
|
-
|
219
|
-
```python
|
220
|
-
import json
|
221
|
-
from typing import Dict, Any
|
222
|
-
import versionhq as vhq
|
223
|
-
|
224
|
-
def assessment(res: str) -> str:
|
225
|
-
try:
|
226
|
-
sub_agent = vhq.Agent(role="Validator", goal="Validate the given solutions.")
|
227
|
-
task = vhq.Task(
|
228
|
-
description=f"Assess the given solution based on feasibilities and fits to client's strategies, then refine the solution if necessary.\nSolution: {res}"
|
229
|
-
)
|
230
|
-
r = task.sync_execute(agent=sub_agent)
|
231
|
-
return r.raw
|
232
|
-
|
233
|
-
except:
|
234
|
-
return res
|
235
|
-
|
236
|
-
def format_response(res: str = None) -> str | Dict[str, Any]:
|
237
|
-
try:
|
238
|
-
r = json.dumps(eval(res))
|
239
|
-
formatted_res = json.loads(r)
|
240
|
-
return formatted_res
|
241
|
-
except:
|
242
|
-
return res
|
243
|
-
|
244
|
-
agent = vhq.Agent(
|
245
|
-
role="Marketing Analyst",
|
246
|
-
goal="Build solutions to address increased price competition in saturated markets",
|
247
|
-
callbacks=[assessment, format_response] # add multiple funcs as callbacks - executed in order of index
|
248
|
-
)
|
249
|
-
```
|
192
|
+
<hr />
|
250
193
|
|
251
|
-
|
194
|
+
**Context Window**
|
252
195
|
|
253
196
|
`[var]`<bold>`respect_context_window: [bool] = True`</bold>
|
254
197
|
|
@@ -260,7 +203,10 @@ By default, the agent will follow **the 80% rule** - where they only use 80% of
|
|
260
203
|
|
261
204
|
You can turn off this rule by setting `respect_context_window` False to have larger context window.
|
262
205
|
|
263
|
-
|
206
|
+
|
207
|
+
<hr />
|
208
|
+
|
209
|
+
**Max Tokens**
|
264
210
|
|
265
211
|
`[var]`<bold>`max_tokens: Optional[int] = None`</bold>
|
266
212
|
|
@@ -268,7 +214,10 @@ Max tokens defines the maximum number of tokens in the generated response. Token
|
|
268
214
|
|
269
215
|
By default, the agent will follow the default max_tokens of the model, but you can specify the max token to limit the length of the generated output.
|
270
216
|
|
271
|
-
|
217
|
+
|
218
|
+
<hr />
|
219
|
+
|
220
|
+
**Maximum Execution Time**
|
272
221
|
|
273
222
|
`[var]`<bold>`max_execution_times: Optional[int] = None`</bold>
|
274
223
|
|
@@ -276,7 +225,10 @@ The maximum amount of wall clock time to spend in the execution loop.
|
|
276
225
|
|
277
226
|
By default, the agent will follow the default setting of the model.
|
278
227
|
|
279
|
-
|
228
|
+
|
229
|
+
<hr />
|
230
|
+
|
231
|
+
**Maximum RPM (Requests Per Minute)**
|
280
232
|
|
281
233
|
`[var]`<bold>`max_rpm: Optional[int] = None`</bold>
|
282
234
|
|
@@ -284,7 +236,9 @@ The maximum number of requests that the agent can send to the LLM.
|
|
284
236
|
|
285
237
|
By default, the agent will follow the default setting of the model. When the value is given, we let the model sleep for 60 seconds when the number of executions exceeds the maximum requests per minute.
|
286
238
|
|
287
|
-
|
239
|
+
<hr />
|
240
|
+
|
241
|
+
**Other LLM Configuration**
|
288
242
|
|
289
243
|
`[var]`<bold>`llm_config: Optional[Dict[str, Any]] = None`</bold>
|
290
244
|
|
@@ -326,12 +280,84 @@ print(agent.llm)
|
|
326
280
|
# max_completion_tokens=10000,
|
327
281
|
# )
|
328
282
|
```
|
283
|
+
<hr >
|
284
|
+
|
285
|
+
## Callbacks
|
286
|
+
|
287
|
+
`[var]`<bold>`callbacks: Optional[List[Callable]] = None`</bold>
|
288
|
+
|
289
|
+
You can add callback functions that the agent will run after executing any task.
|
290
|
+
|
291
|
+
By default, raw response from the agent will be added to the arguments of the callback function.
|
292
|
+
|
293
|
+
e.g. Format a response after executing the task:
|
294
|
+
|
295
|
+
```python
|
296
|
+
import json
|
297
|
+
import versionhq as vhq
|
298
|
+
from typing import Dict, Any
|
299
|
+
|
300
|
+
|
301
|
+
def format_response(res: str = None) -> str | Dict[str, Any]:
|
302
|
+
try:
|
303
|
+
r = json.dumps(eval(res))
|
304
|
+
formatted_res = json.loads(r)
|
305
|
+
return formatted_res
|
306
|
+
except:
|
307
|
+
return res
|
308
|
+
|
309
|
+
agent = vhq.Agent(
|
310
|
+
role="Marketing Analyst",
|
311
|
+
goal="Coping with increased price competition in saturated markets.",
|
312
|
+
callbacks=[format_response]
|
313
|
+
)
|
314
|
+
```
|
315
|
+
|
316
|
+
<hr />
|
317
|
+
|
318
|
+
**Multiple callbacks to call**
|
319
|
+
|
320
|
+
The callback functions are called in order of the list index referring to the task response and response from the previous callback functions by default.
|
321
|
+
|
322
|
+
e.g. Validate an initial response from the assigned agent, and format the response.
|
323
|
+
|
324
|
+
```python
|
325
|
+
import json
|
326
|
+
from typing import Dict, Any
|
327
|
+
import versionhq as vhq
|
328
|
+
|
329
|
+
def assessment(res: str) -> str:
|
330
|
+
try:
|
331
|
+
sub_agent = vhq.Agent(role="Validator", goal="Validate the given solutions.")
|
332
|
+
task = vhq.Task(
|
333
|
+
description=f"Assess the given solution based on feasibilities and fits to client's strategies, then refine the solution if necessary.\nSolution: {res}"
|
334
|
+
)
|
335
|
+
r = task.sync_execute(agent=sub_agent)
|
336
|
+
return r.raw
|
337
|
+
|
338
|
+
except:
|
339
|
+
return res
|
340
|
+
|
341
|
+
def format_response(res: str = None) -> str | Dict[str, Any]:
|
342
|
+
try:
|
343
|
+
r = json.dumps(eval(res))
|
344
|
+
formatted_res = json.loads(r)
|
345
|
+
return formatted_res
|
346
|
+
except:
|
347
|
+
return res
|
348
|
+
|
349
|
+
agent = vhq.Agent(
|
350
|
+
role="Marketing Analyst",
|
351
|
+
goal="Build solutions to address increased price competition in saturated markets",
|
352
|
+
callbacks=[assessment, format_response] # add multiple funcs as callbacks - executed in order of index
|
353
|
+
)
|
354
|
+
```
|
329
355
|
|
330
356
|
<hr />
|
331
357
|
|
332
|
-
## Knowledge
|
358
|
+
## Building Knowledge
|
333
359
|
|
334
|
-
|
360
|
+
**Knowlege Source**
|
335
361
|
|
336
362
|
`[var]`<bold>`knowledge_sources: Optional[List[KnowledgeSource]] = None`</bold>
|
337
363
|
|
@@ -373,9 +399,9 @@ assert "gold" in res.raw == True
|
|
373
399
|
|
374
400
|
<hr />
|
375
401
|
|
376
|
-
##
|
402
|
+
## Accessing Memories
|
377
403
|
|
378
|
-
|
404
|
+
Store task execution results in memory
|
379
405
|
|
380
406
|
`[var]`<bold>`use_memory: bool = False`</bold>
|
381
407
|
|
@@ -397,7 +423,9 @@ print(agent.long_term_memory)
|
|
397
423
|
# returns LongTermMemory object.
|
398
424
|
```
|
399
425
|
|
400
|
-
|
426
|
+
<hr />
|
427
|
+
|
428
|
+
**RAG Storage**
|
401
429
|
|
402
430
|
When the agent is not given any `memory_config` values, they will create `RAGStorage` to store memory:
|
403
431
|
|
@@ -418,7 +446,7 @@ MEM0 Storage
|
|
418
446
|
|
419
447
|
## Utilities
|
420
448
|
|
421
|
-
|
449
|
+
**Model configuration**
|
422
450
|
|
423
451
|
`[var]`<bold>`config: Optional[Dict[str, Any]] = None`</bold>
|
424
452
|
|
@@ -450,7 +478,7 @@ agent = vhq.Agent(
|
|
450
478
|
|
451
479
|
<hr />
|
452
480
|
|
453
|
-
|
481
|
+
**Updating existing agents**
|
454
482
|
|
455
483
|
`[class method]`<bold>`update(self, **kwargs) -> Self`</bold>
|
456
484
|
|
@@ -94,6 +94,7 @@ theme:
|
|
94
94
|
- header.autohide
|
95
95
|
- navigation.tabs
|
96
96
|
- navigation.path
|
97
|
+
- navigation.expand
|
97
98
|
- navigation.top
|
98
99
|
- navigation.footer
|
99
100
|
- navigation.indexes
|
@@ -110,16 +111,18 @@ nav:
|
|
110
111
|
- Home: 'index.md'
|
111
112
|
- Quick Start: 'quickstart.md'
|
112
113
|
- Core Components:
|
113
|
-
- Agent:
|
114
|
-
|
114
|
+
- Agent:
|
115
|
+
- 'core/agent/index.md'
|
116
|
+
- Task Graph:
|
117
|
+
- 'core/task-graph/index.md'
|
115
118
|
- Task:
|
116
|
-
-
|
119
|
+
- 'core/task/index.md'
|
117
120
|
- ResponseField: 'core/task/response-field.md'
|
118
121
|
- TaskOutput: 'core/task/task-output.md'
|
119
122
|
- Evaluation: 'core/task/evaluation.md'
|
120
123
|
- Tool: 'core/tool.md'
|
121
124
|
- Tags: 'tags.md'
|
122
|
-
-
|
125
|
+
- Cases:
|
123
126
|
- Playground: https://versi0n.io/playground
|
124
127
|
- Experiment - Agent Performance: https://github.com/versionHQ/exp-agent-performance
|
125
128
|
- Change Log: https://github.com/versionHQ/multi-agent-system/releases
|
@@ -15,7 +15,7 @@ exclude = ["test*", "__pycache__", "*.egg-info"]
|
|
15
15
|
|
16
16
|
[project]
|
17
17
|
name = "versionhq"
|
18
|
-
version = "1.2.1.
|
18
|
+
version = "1.2.1.10"
|
19
19
|
authors = [{ name = "Kuriko Iwai", email = "kuriko@versi0n.io" }]
|
20
20
|
description = "An agentic orchestration framework for building agent networks that handle task automation."
|
21
21
|
readme = "README.md"
|
@@ -49,11 +49,12 @@ def workflow(final_output: Type[BaseModel], context: Any = None, human: bool = T
|
|
49
49
|
)
|
50
50
|
|
51
51
|
task = Task(
|
52
|
-
description=f"Design a resource-efficient workflow to achieve the following goal: {final_output_prompt}.
|
52
|
+
description=dedent(f"Design a resource-efficient workflow to achieve the following goal: {final_output_prompt}. The workflow should consist of a list of detailed tasks that represent decision making points, each with the following information:\nname: A concise name of the task\ndescription: A concise description of the task.\nconnections: A list of target tasks that this task connects to.\ndependency_types: The type of dependency between this task and each of its connected task. \noutput: key output from the task.\n\nUse the following dependency types: {dep_type_prompt}.\n\nPrioritize minimizing resource consumption (computation, memory, and data transfer) when defining tasks, connections, and dependencies. Consider how data is passed between tasks and aim to reduce unnecessary data duplication or transfer. Explain any design choices made to optimize resource usage."),
|
53
53
|
response_fields=[
|
54
54
|
ResponseField(title="tasks", data_type=list, items=dict, properties=[
|
55
55
|
ResponseField(title="name", data_type=str),
|
56
56
|
ResponseField(title="description", data_type=str),
|
57
|
+
ResponseField(title="output", data_type=str),
|
57
58
|
ResponseField(title="connections", data_type=list, items=str),
|
58
59
|
ResponseField(title="dependency_types", data_type=list, items=str),
|
59
60
|
]
|
@@ -66,11 +67,20 @@ def workflow(final_output: Type[BaseModel], context: Any = None, human: bool = T
|
|
66
67
|
return None
|
67
68
|
|
68
69
|
task_items = res.json_dict["tasks"]
|
69
|
-
tasks = [
|
70
|
-
|
70
|
+
tasks, nodes = [], []
|
71
|
+
for item in task_items:
|
72
|
+
class Output(BaseModel):
|
73
|
+
item["output"]: str
|
74
|
+
|
75
|
+
task = Task(name=item["name"], description=item["description"], pydantic_output=Output)
|
76
|
+
tasks.append(task)
|
77
|
+
nodes.append(Node(task=task))
|
78
|
+
|
79
|
+
|
71
80
|
task_graph = TaskGraph(
|
72
81
|
nodes={node.identifier: node for node in nodes},
|
73
|
-
|
82
|
+
concl_format=final_output,
|
83
|
+
concl=None,
|
74
84
|
should_reform=True,
|
75
85
|
)
|
76
86
|
|
@@ -79,23 +89,24 @@ def workflow(final_output: Type[BaseModel], context: Any = None, human: bool = T
|
|
79
89
|
dependency_types = [DependencyType[dt] if DependencyType[dt] else DependencyType.FINISH_TO_START for dt in res["dependency_types"]]
|
80
90
|
|
81
91
|
for i, target_task_name in enumerate(res["connections"]):
|
82
|
-
source = [v for
|
83
|
-
target = [v for
|
92
|
+
source = [v for v in task_graph.nodes.values() if v.task.name == res["name"]][0]
|
93
|
+
target = [v for v in task_graph.nodes.values() if v.task.name == target_task_name][0]
|
84
94
|
dependency_type = dependency_types[i]
|
85
|
-
task_graph.add_dependency(
|
95
|
+
task_graph.add_dependency(
|
96
|
+
source_node_identifier=source.identifier, target_node_identifier=target.identifier, dependency_type=dependency_type)
|
97
|
+
|
86
98
|
|
87
|
-
|
88
|
-
# task_graph.visualize()
|
99
|
+
task_graph.visualize()
|
89
100
|
|
90
|
-
|
91
|
-
|
92
|
-
|
101
|
+
if human:
|
102
|
+
print('Proceed? Y/n:')
|
103
|
+
x = input()
|
93
104
|
|
94
|
-
|
95
|
-
|
105
|
+
if x.lower() == "y":
|
106
|
+
print("ok. generating agent network")
|
96
107
|
|
97
|
-
|
98
|
-
|
99
|
-
|
108
|
+
else:
|
109
|
+
request = input("request?")
|
110
|
+
print('ok. regenerating the graph based on your input: ', request)
|
100
111
|
|
101
112
|
return task_graph
|
@@ -1,12 +1,14 @@
|
|
1
|
+
import matplotlib
|
2
|
+
matplotlib.use('agg')
|
3
|
+
|
1
4
|
import enum
|
2
5
|
import uuid
|
3
6
|
import networkx as nx
|
4
7
|
import matplotlib.pyplot as plt
|
5
8
|
from abc import ABC
|
6
9
|
from typing import List, Any, Optional, Callable, Dict, Type, Tuple
|
7
|
-
from typing_extensions import Self
|
8
10
|
|
9
|
-
from pydantic import BaseModel, InstanceOf, Field, UUID4, field_validator
|
11
|
+
from pydantic import BaseModel, InstanceOf, Field, UUID4, field_validator
|
10
12
|
from pydantic_core import PydanticCustomError
|
11
13
|
|
12
14
|
from versionhq.task.model import Task, TaskOutput
|
@@ -60,7 +62,7 @@ class Node(BaseModel):
|
|
60
62
|
def is_independent(self) -> bool:
|
61
63
|
return not self.in_degree_nodes and not self.out_degree_nodes
|
62
64
|
|
63
|
-
def handle_task_execution(self, agent: Agent = None, context: str = None) -> TaskOutput | None:
|
65
|
+
def handle_task_execution(self, agent: Agent = None, context: str = None, format: Type[BaseModel] = None) -> TaskOutput | None:
|
64
66
|
"""
|
65
67
|
Start task execution and update status accordingly.
|
66
68
|
"""
|
@@ -72,6 +74,7 @@ class Node(BaseModel):
|
|
72
74
|
self.status = TaskStatus.ERROR
|
73
75
|
return None
|
74
76
|
|
77
|
+
self.task.pydantic_output = self.task.pydantic_output if self.task.pydantic_output else format if type(format) == BaseModel else None
|
75
78
|
res = self.task.execute(agent=agent, context=context)
|
76
79
|
self.status = TaskStatus.COMPLETED if res else TaskStatus.ERROR
|
77
80
|
return res
|
@@ -176,7 +179,7 @@ class Edge(BaseModel):
|
|
176
179
|
return False
|
177
180
|
|
178
181
|
|
179
|
-
def activate(self) -> TaskOutput | None:
|
182
|
+
def activate(self, format: Type[BaseModel] = None) -> TaskOutput | None:
|
180
183
|
"""
|
181
184
|
Activates the edge to initiate task execution of the target node.
|
182
185
|
"""
|
@@ -194,7 +197,7 @@ class Edge(BaseModel):
|
|
194
197
|
time.sleep(self.lag)
|
195
198
|
|
196
199
|
context = self.source.task.output.raw if self.data_transfer else None
|
197
|
-
res = self.target.handle_task_execution(context=context)
|
200
|
+
res = self.target.handle_task_execution(context=context, format=format)
|
198
201
|
return res
|
199
202
|
|
200
203
|
|
@@ -398,7 +401,7 @@ class TaskGraph(Graph):
|
|
398
401
|
return self._return_node_object(identifier).status
|
399
402
|
|
400
403
|
|
401
|
-
def visualize(self, layout: str = None):
|
404
|
+
def visualize(self, layout: str = None, should_save: bool = False):
|
402
405
|
from matplotlib.lines import Line2D
|
403
406
|
from versionhq.task_graph.colors import white, black, darkgrey, grey, primary, orange, lightgreen, green, darkgreen, darkergreen
|
404
407
|
|
@@ -475,7 +478,9 @@ class TaskGraph(Graph):
|
|
475
478
|
|
476
479
|
plt.legend(handles=legend_elements, loc='lower right')
|
477
480
|
plt.title(f"vhq-Diagram {str(self.id)}")
|
478
|
-
|
481
|
+
|
482
|
+
if should_save:
|
483
|
+
self._save(title=f"vhq-Diagram {str(self.id)}")
|
479
484
|
plt.show(block=False)
|
480
485
|
|
481
486
|
|
@@ -559,5 +564,7 @@ class TaskGraph(Graph):
|
|
559
564
|
node_identifier = edge.target.identifier
|
560
565
|
self.outputs.update({ node_identifier: res })
|
561
566
|
|
567
|
+
self.concl = res
|
568
|
+
self.concl_template = self.concl_template if self.concl_template else res.pydantic.__class__ if res.pydantic else None
|
562
569
|
# last_task_output = [v for v in self.outputs.values()][len([v for v in self.outputs.values()]) - 1] if [v for v in self.outputs.values()] else None
|
563
570
|
return res, self.outputs
|
@@ -23,13 +23,13 @@ docs/quickstart.md
|
|
23
23
|
docs/tags.md
|
24
24
|
docs/_logos/favicon.ico
|
25
25
|
docs/_logos/logo192.png
|
26
|
-
docs/core/Agent.md
|
27
|
-
docs/core/task-graph.md
|
28
|
-
docs/core/task.md
|
29
26
|
docs/core/tool.md
|
27
|
+
docs/core/agent/index.md
|
30
28
|
docs/core/task/evaluation.md
|
29
|
+
docs/core/task/index.md
|
31
30
|
docs/core/task/response-field.md
|
32
31
|
docs/core/task/task-output.md
|
32
|
+
docs/core/task-graph/index.md
|
33
33
|
docs/stylesheets/main.css
|
34
34
|
src/versionhq/__init__.py
|
35
35
|
src/versionhq.egg-info/PKG-INFO
|
@@ -31,8 +31,4 @@ def test_create_and_activate_network():
|
|
31
31
|
|
32
32
|
assert last_task_output is not None and isinstance(last_task_output, vhq.TaskOutput)
|
33
33
|
assert [k in task_graph.nodes.keys() and v and isinstance(v, vhq.TaskOutput) for k, v in outputs.items()]
|
34
|
-
|
35
|
-
task_graph.visualize()
|
36
|
-
|
37
|
-
|
38
|
-
test_create_and_activate_network()
|
34
|
+
assert task_graph.concl == last_task_output and task_graph.concl_template == None
|
@@ -0,0 +1,27 @@
|
|
1
|
+
from unittest.mock import patch
|
2
|
+
|
3
|
+
|
4
|
+
def test_draft():
|
5
|
+
import versionhq as vhq
|
6
|
+
from pydantic import BaseModel
|
7
|
+
|
8
|
+
class Trip(BaseModel):
|
9
|
+
name: str
|
10
|
+
location: str
|
11
|
+
description: str
|
12
|
+
date: str
|
13
|
+
cousine: str
|
14
|
+
why_its_suitable: str
|
15
|
+
|
16
|
+
|
17
|
+
with patch('builtins.input', return_value='Y'):
|
18
|
+
task_graph = vhq.workflow(
|
19
|
+
Trip,
|
20
|
+
context="Planning a suprise day trip for my friend to celebrate her birthday. We live in CA and we like to have Korean food.",
|
21
|
+
human=True
|
22
|
+
)
|
23
|
+
|
24
|
+
assert task_graph
|
25
|
+
assert [k == node.identifier and node.task and isinstance(node, vhq.Node) for k, node in task_graph.nodes.items()]
|
26
|
+
assert [isinstance(edge.dependency_type, vhq.DependencyType) and isinstance(edge, vhq.Edge) for k, edge in task_graph.edges.items()]
|
27
|
+
assert [k in task_graph.nodes.keys() and v.status == vhq.TaskStatus.NOT_STARTED for k, v in task_graph.nodes.items()]
|