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.
Files changed (138) hide show
  1. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/PKG-INFO +1 -1
  2. versionhq-1.2.1.8/docs/core/Agent.md → versionhq-1.2.1.10/docs/core/agent/index.md +116 -88
  3. versionhq-1.2.1.8/docs/core/task.md → versionhq-1.2.1.10/docs/core/task/index.md +1 -1
  4. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/mkdocs.yml +7 -4
  5. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/pyproject.toml +1 -1
  6. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/__init__.py +1 -1
  7. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/draft.py +28 -17
  8. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/model.py +14 -7
  9. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/PKG-INFO +1 -1
  10. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/SOURCES.txt +3 -3
  11. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/formation_test.py +0 -1
  12. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task_graph/doc_test.py +1 -5
  13. versionhq-1.2.1.10/tests/task_graph/task_graph_test.py +27 -0
  14. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/uv.lock +31 -31
  15. versionhq-1.2.1.8/tests/task_graph/task_graph_test.py +0 -18
  16. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.env.sample +0 -0
  17. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/deploy_docs.yml +0 -0
  18. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/publish.yml +0 -0
  19. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/publish_testpypi.yml +0 -0
  20. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/run_tests.yml +0 -0
  21. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.github/workflows/security_check.yml +0 -0
  22. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.gitignore +0 -0
  23. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.pre-commit-config.yaml +0 -0
  24. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/.python-version +0 -0
  25. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/LICENSE +0 -0
  26. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/README.md +0 -0
  27. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/SECURITY.md +0 -0
  28. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/db/preprocess.py +0 -0
  29. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/CNAME +0 -0
  30. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/_logos/favicon.ico +0 -0
  31. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/_logos/logo192.png +0 -0
  32. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/task/evaluation.md +0 -0
  33. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/task/response-field.md +0 -0
  34. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/task/task-output.md +0 -0
  35. /versionhq-1.2.1.8/docs/core/task-graph.md → /versionhq-1.2.1.10/docs/core/task-graph/index.md +0 -0
  36. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/core/tool.md +0 -0
  37. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/index.md +0 -0
  38. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/quickstart.md +0 -0
  39. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/stylesheets/main.css +0 -0
  40. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/docs/tags.md +0 -0
  41. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/requirements-dev.txt +0 -0
  42. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/requirements.txt +0 -0
  43. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/runtime.txt +0 -0
  44. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/setup.cfg +0 -0
  45. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/__init__.py +0 -0
  46. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/i18n.py +0 -0
  47. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/logger.py +0 -0
  48. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/process_config.py +0 -0
  49. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/usage_metrics.py +0 -0
  50. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/_utils/vars.py +0 -0
  51. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/TEMPLATES/Backstory.py +0 -0
  52. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/TEMPLATES/__init__.py +0 -0
  53. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/__init__.py +0 -0
  54. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/inhouse_agents.py +0 -0
  55. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/model.py +0 -0
  56. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/parser.py +0 -0
  57. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent/rpm_controller.py +0 -0
  58. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent_network/__init__.py +0 -0
  59. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/agent_network/model.py +0 -0
  60. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/cli/__init__.py +0 -0
  61. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/__init__.py +0 -0
  62. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/customer/__init__.py +0 -0
  63. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/customer/model.py +0 -0
  64. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/product/__init__.py +0 -0
  65. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/product/model.py +0 -0
  66. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/workflow/__init__.py +0 -0
  67. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/clients/workflow/model.py +0 -0
  68. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/__init__.py +0 -0
  69. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/_utils.py +0 -0
  70. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/embedding.py +0 -0
  71. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/model.py +0 -0
  72. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/source.py +0 -0
  73. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/source_docling.py +0 -0
  74. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/knowledge/storage.py +0 -0
  75. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/llm/__init__.py +0 -0
  76. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/llm/llm_vars.py +0 -0
  77. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/llm/model.py +0 -0
  78. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/memory/__init__.py +0 -0
  79. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/memory/contextual_memory.py +0 -0
  80. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/memory/model.py +0 -0
  81. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/__init__.py +0 -0
  82. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/base.py +0 -0
  83. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/ltm_sqlite_storage.py +0 -0
  84. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/mem0_storage.py +0 -0
  85. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/rag_storage.py +0 -0
  86. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/task_output_storage.py +0 -0
  87. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/storage/utils.py +0 -0
  88. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/TEMPLATES/Description.py +0 -0
  89. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/__init__.py +0 -0
  90. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/evaluate.py +0 -0
  91. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/formation.py +0 -0
  92. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/formatter.py +0 -0
  93. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/log_handler.py +0 -0
  94. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/model.py +0 -0
  95. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task/structured_response.py +0 -0
  96. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/__init__.py +0 -0
  97. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/task_graph/colors.py +0 -0
  98. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/__init__.py +0 -0
  99. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/cache_handler.py +0 -0
  100. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/composio_tool.py +0 -0
  101. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/composio_tool_vars.py +0 -0
  102. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/decorator.py +0 -0
  103. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/model.py +0 -0
  104. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq/tool/tool_handler.py +0 -0
  105. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/dependency_links.txt +0 -0
  106. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/requires.txt +0 -0
  107. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/src/versionhq.egg-info/top_level.txt +0 -0
  108. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/__init__.py +0 -0
  109. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent/__init__.py +0 -0
  110. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent/agent_test.py +0 -0
  111. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent/doc_test.py +0 -0
  112. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent_network/Prompts/Demo_test.py +0 -0
  113. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent_network/__init__.py +0 -0
  114. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/agent_network/agent_network_test.py +0 -0
  115. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/cli/__init__.py +0 -0
  116. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/clients/customer_test.py +0 -0
  117. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/clients/product_test.py +0 -0
  118. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/clients/workflow_test.py +0 -0
  119. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/conftest.py +0 -0
  120. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/doc_test.py +0 -0
  121. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/knowledge/__init__.py +0 -0
  122. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/knowledge/knowledge_test.py +0 -0
  123. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/knowledge/mock_report_compressed.pdf +0 -0
  124. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/llm/__init__.py +0 -0
  125. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/llm/llm_test.py +0 -0
  126. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/memory/__init__.py +0 -0
  127. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/memory/memory_test.py +0 -0
  128. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/__init__.py +0 -0
  129. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/doc_taskoutput_test.py +0 -0
  130. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/doc_test.py +0 -0
  131. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/llm_connection_test.py +0 -0
  132. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task/task_test.py +0 -0
  133. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/task_graph/__init__.py +0 -0
  134. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/__init__.py +0 -0
  135. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/composio_test.py +0 -0
  136. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/doc_test.py +0 -0
  137. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/tool/tool_test.py +0 -0
  138. {versionhq-1.2.1.8 → versionhq-1.2.1.10}/tests/usecase_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: versionhq
3
- Version: 1.2.1.8
3
+ Version: 1.2.1.10
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
@@ -27,9 +27,9 @@ agent = vhq.Agent(
27
27
 
28
28
  <hr />
29
29
 
30
- ## Customization
30
+ ## Customizing
31
31
 
32
- ### Model optimization
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
- ### Switching models
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
- ### Developer Prompt (System Prompt)
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
- ## Task Execution Rules
134
+ <hr />
135
+
136
+ ## Executing Tasks
131
137
 
132
- ### Delegation
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
- ### Max Retry Limit
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
- ### Maximum Number of Iterations (MaxIt)
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
- ### Callbacks
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
- ### Context Window
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
- ### Max Tokens
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
- ### Maximum Execution Time
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
- ### Maximum RPM (Requests Per Minute)
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
- ### Other LLM Configuration
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
- ### Knowledge Sources
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
- ## Memory
402
+ ## Accessing Memories
377
403
 
378
- ### Store task execution results in memory
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
- ### RAG Storage
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
- ### Model configuration
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
- ### Updating model values
481
+ **Updating existing agents**
454
482
 
455
483
  `[class method]`<bold>`update(self, **kwargs) -> Self`</bold>
456
484
 
@@ -435,7 +435,7 @@ Refer <a href="/core/task/task-output">TaskOutput</a> class for details.
435
435
  <hr>
436
436
 
437
437
 
438
- ## Ref
438
+ ## Reference
439
439
 
440
440
  ### Variables
441
441
 
@@ -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: 'core/agent.md'
114
- - Task Graph: 'core/task-graph.md'
114
+ - Agent:
115
+ - 'core/agent/index.md'
116
+ - Task Graph:
117
+ - 'core/task-graph/index.md'
115
118
  - Task:
116
- - Task: 'core/task.md'
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
- - Examples:
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.8"
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"
@@ -31,7 +31,7 @@ from versionhq.task.formation import form_agent_network
31
31
  from versionhq.task_graph.draft import workflow
32
32
 
33
33
 
34
- __version__ = "1.2.1.8"
34
+ __version__ = "1.2.1.10"
35
35
  __all__ = [
36
36
  "Agent",
37
37
 
@@ -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}. The workflow should consist of a list of tasks, 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. Use 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.",
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 = [Task(name=item["name"], description=item["description"]) for item in task_items]
70
- nodes = [Node(task=task) for task in tasks]
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
- concl=final_output,
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 k, v in task_graph.nodes.items() if v.task.name == res["name"]][0]
83
- target = [v for k, v in task_graph.nodes.items() if v.task.name == target_task_name][0]
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(source_node_identifier=source.identifier, target_node_identifier=target.identifier, dependency_type=dependency_type)
95
+ task_graph.add_dependency(
96
+ source_node_identifier=source.identifier, target_node_identifier=target.identifier, dependency_type=dependency_type)
97
+
86
98
 
87
- ## test purpose
88
- # task_graph.visualize()
99
+ task_graph.visualize()
89
100
 
90
- # if human:
91
- # print('Proceed? Y/n:')
92
- # x = input()
101
+ if human:
102
+ print('Proceed? Y/n:')
103
+ x = input()
93
104
 
94
- # if x.lower() == "y":
95
- # print("ok. generating agent network")
105
+ if x.lower() == "y":
106
+ print("ok. generating agent network")
96
107
 
97
- # else:
98
- # request = input("request?")
99
- # print('ok. regenerating the graph based on your input: ', request)
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, model_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
- self._save(title=f"vhq-Diagram {str(self.id)}")
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: versionhq
3
- Version: 1.2.1.8
3
+ Version: 1.2.1.10
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
@@ -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
@@ -33,7 +33,6 @@ def _test_specific_formation():
33
33
  task="Describe the color of the sky by weather condition",
34
34
  expected_outcome="Dict that pairs color of the sky with specific weather condition",
35
35
  formation=item,
36
-
37
36
  )
38
37
 
39
38
  assert isinstance(network, vhq.AgentNetwork)
@@ -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()]