versionhq 1.2.4.5__tar.gz → 1.2.4.6__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 (175) hide show
  1. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/PKG-INFO +1 -1
  2. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent/index.md +1 -1
  3. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent-network/ref.md +11 -11
  4. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/reference.md +4 -3
  5. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/pyproject.toml +1 -1
  6. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/__init__.py +12 -3
  7. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_prompt/auto_feedback.py +1 -1
  8. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_prompt/model.py +11 -8
  9. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/__init__.py +2 -0
  10. versionhq-1.2.4.6/src/versionhq/_utils/convert_img_url.py +15 -0
  11. versionhq-1.2.4.6/src/versionhq/_utils/is_valid_enum.py +25 -0
  12. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/llm_as_a_judge.py +0 -1
  13. versionhq-1.2.4.6/src/versionhq/_utils/usage_metrics.py +93 -0
  14. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/model.py +91 -27
  15. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent_network/formation.py +3 -9
  16. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent_network/model.py +3 -4
  17. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/customer/__init__.py +2 -2
  18. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/product/model.py +4 -4
  19. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/workflow/model.py +1 -1
  20. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/llm/llm_vars.py +0 -2
  21. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/task_output_storage.py +2 -2
  22. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task/model.py +72 -59
  23. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task_graph/model.py +30 -26
  24. {versionhq-1.2.4.5/tests/agent → versionhq-1.2.4.6/src/versionhq/tool/composio}/__init__.py +0 -0
  25. versionhq-1.2.4.5/src/versionhq/tool/composio_tool.py → versionhq-1.2.4.6/src/versionhq/tool/composio/model.py +4 -5
  26. versionhq-1.2.4.6/src/versionhq/tool/gpt/__init__.py +6 -0
  27. versionhq-1.2.4.6/src/versionhq/tool/gpt/_enum.py +28 -0
  28. versionhq-1.2.4.6/src/versionhq/tool/gpt/cup.py +145 -0
  29. versionhq-1.2.4.6/src/versionhq/tool/gpt/file_search.py +163 -0
  30. versionhq-1.2.4.6/src/versionhq/tool/gpt/web_search.py +89 -0
  31. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq.egg-info/PKG-INFO +1 -1
  32. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq.egg-info/SOURCES.txt +11 -2
  33. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/_prompt/auto_feedback_test.py +1 -1
  34. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/agent/agent_test.py +1 -2
  35. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/agent/doc_test.py +1 -4
  36. {versionhq-1.2.4.5/tests/knowledge → versionhq-1.2.4.6/tests/cli}/__init__.py +0 -0
  37. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/clients/product_test.py +1 -1
  38. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/clients/workflow_test.py +1 -1
  39. {versionhq-1.2.4.5/tests/llm → versionhq-1.2.4.6/tests/knowledge}/__init__.py +0 -0
  40. {versionhq-1.2.4.5/tests/memory → versionhq-1.2.4.6/tests/llm}/__init__.py +0 -0
  41. {versionhq-1.2.4.5/tests/task → versionhq-1.2.4.6/tests/memory}/__init__.py +0 -0
  42. {versionhq-1.2.4.5/tests/task_graph → versionhq-1.2.4.6/tests/task}/__init__.py +0 -0
  43. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task/doc_test.py +5 -8
  44. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task/eval_test.py +1 -2
  45. {versionhq-1.2.4.5/tests/tool → versionhq-1.2.4.6/tests/task_graph}/__init__.py +0 -0
  46. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task_graph/doc_test.py +4 -6
  47. versionhq-1.2.4.6/tests/tool/__init__.py +0 -0
  48. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/tool/composio_test.py +4 -4
  49. versionhq-1.2.4.6/tests/tool/gpt_test.py +143 -0
  50. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/usecase_test.py +4 -7
  51. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/uv.lock +13 -13
  52. versionhq-1.2.4.5/src/versionhq/_utils/usage_metrics.py +0 -72
  53. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.env.sample +0 -0
  54. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.github/workflows/deploy_docs.yml +0 -0
  55. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.github/workflows/publish.yml +0 -0
  56. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.github/workflows/publish_testpypi.yml +0 -0
  57. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.github/workflows/run_tests.yml +0 -0
  58. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.github/workflows/security_check.yml +0 -0
  59. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.gitignore +0 -0
  60. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.pre-commit-config.yaml +0 -0
  61. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/.python-version +0 -0
  62. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/LICENSE +0 -0
  63. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/README.md +0 -0
  64. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/SECURITY.md +0 -0
  65. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/db/preprocess.py +0 -0
  66. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/CNAME +0 -0
  67. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/_logos/favicon.ico +0 -0
  68. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/_logos/logo192.png +0 -0
  69. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent/config.md +0 -0
  70. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent/task-handling.md +0 -0
  71. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent-network/config.md +0 -0
  72. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent-network/form.md +0 -0
  73. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/agent-network/index.md +0 -0
  74. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/knowledge.md +0 -0
  75. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/llm/index.md +0 -0
  76. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/memory.md +0 -0
  77. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/rag-tool.md +0 -0
  78. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/evaluation.md +0 -0
  79. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/index.md +0 -0
  80. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/response-field.md +0 -0
  81. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/task-execution.md +0 -0
  82. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/task-output.md +0 -0
  83. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task/task-strc-response.md +0 -0
  84. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/task-graph/index.md +0 -0
  85. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/core/tool.md +0 -0
  86. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/index.md +0 -0
  87. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/quickstart.md +0 -0
  88. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/stylesheets/main.css +0 -0
  89. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/docs/tags.md +0 -0
  90. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/mkdocs.yml +0 -0
  91. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/requirements-dev.txt +0 -0
  92. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/requirements.txt +0 -0
  93. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/runtime.txt +0 -0
  94. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/setup.cfg +0 -0
  95. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_prompt/constants.py +0 -0
  96. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/i18n.py +0 -0
  97. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/is_valid_url.py +0 -0
  98. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/logger.py +0 -0
  99. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/process_config.py +0 -0
  100. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/_utils/vars.py +0 -0
  101. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/TEMPLATES/Backstory.py +0 -0
  102. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/TEMPLATES/__init__.py +0 -0
  103. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/__init__.py +0 -0
  104. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/inhouse_agents.py +0 -0
  105. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/parser.py +0 -0
  106. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent/rpm_controller.py +0 -0
  107. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/agent_network/__init__.py +0 -0
  108. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/cli/__init__.py +0 -0
  109. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/__init__.py +0 -0
  110. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/customer/model.py +0 -0
  111. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/product/__init__.py +0 -0
  112. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/clients/workflow/__init__.py +0 -0
  113. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/__init__.py +0 -0
  114. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/_utils.py +0 -0
  115. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/embedding.py +0 -0
  116. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/model.py +0 -0
  117. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/source.py +0 -0
  118. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/source_docling.py +0 -0
  119. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/knowledge/storage.py +0 -0
  120. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/llm/__init__.py +0 -0
  121. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/llm/model.py +0 -0
  122. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/memory/__init__.py +0 -0
  123. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/memory/contextual_memory.py +0 -0
  124. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/memory/model.py +0 -0
  125. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/__init__.py +0 -0
  126. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/base.py +0 -0
  127. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/ltm_sqlite_storage.py +0 -0
  128. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/mem0_storage.py +0 -0
  129. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/rag_storage.py +0 -0
  130. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/storage/utils.py +0 -0
  131. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task/TEMPLATES/Description.py +0 -0
  132. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task/__init__.py +0 -0
  133. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task/evaluation.py +0 -0
  134. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task/formatter.py +0 -0
  135. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task/structured_response.py +0 -0
  136. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task_graph/__init__.py +0 -0
  137. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task_graph/colors.py +0 -0
  138. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/task_graph/draft.py +0 -0
  139. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/tool/__init__.py +0 -0
  140. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/tool/cache_handler.py +0 -0
  141. /versionhq-1.2.4.5/src/versionhq/tool/composio_tool_vars.py → /versionhq-1.2.4.6/src/versionhq/tool/composio/params.py +0 -0
  142. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/tool/decorator.py +0 -0
  143. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/tool/model.py +0 -0
  144. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/tool/rag_tool.py +0 -0
  145. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq/tool/tool_handler.py +0 -0
  146. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq.egg-info/dependency_links.txt +0 -0
  147. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq.egg-info/requires.txt +0 -0
  148. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/src/versionhq.egg-info/top_level.txt +0 -0
  149. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/__init__.py +0 -0
  150. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/_prompt/prompt_test.py +0 -0
  151. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/_sample/sample.csv +0 -0
  152. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/_sample/sample.json +0 -0
  153. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/_sample/sample.mp3 +0 -0
  154. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/_sample/screenshot.png +0 -0
  155. {versionhq-1.2.4.5/tests/agent_network → versionhq-1.2.4.6/tests/agent}/__init__.py +0 -0
  156. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/agent_network/Prompts/Demo_test.py +0 -0
  157. {versionhq-1.2.4.5/tests/cli → versionhq-1.2.4.6/tests/agent_network}/__init__.py +0 -0
  158. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/agent_network/agent_network_test.py +0 -0
  159. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/agent_network/doc_test.py +0 -0
  160. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/clients/customer_test.py +0 -0
  161. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/conftest.py +0 -0
  162. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/doc_test.py +0 -0
  163. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/formation_test.py +0 -0
  164. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/knowledge/knowledge_test.py +0 -0
  165. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/knowledge/mock_report_compressed.pdf +0 -0
  166. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/llm/llm_connection_test.py +0 -0
  167. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/llm/llm_test.py +0 -0
  168. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/memory/memory_test.py +0 -0
  169. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task/doc_eval_test.py +0 -0
  170. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task/doc_taskoutput_test.py +0 -0
  171. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task/task_test.py +0 -0
  172. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/task_graph/task_graph_test.py +0 -0
  173. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/tool/doc_test.py +0 -0
  174. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/tool/rag_tool_test.py +0 -0
  175. {versionhq-1.2.4.5 → versionhq-1.2.4.6}/tests/tool/tool_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: versionhq
3
- Version: 1.2.4.5
3
+ Version: 1.2.4.6
4
4
  Summary: Autonomous agent networks for task automation with multi-step reasoning.
5
5
  Author-email: Kuriko Iwai <kuriko@versi0n.io>
6
6
  License: MIT License
@@ -14,7 +14,7 @@ A Pydantic class to store an `Agent` object that handles `Task` execution.
14
14
 
15
15
  By defining its role and goal in a simple sentence, the AI agent will be set up to run on <bold>`gpt-4o`</bold> by default.
16
16
 
17
- Calling `.start()` method can start the agent operation, then generate response in text and JSON formats stored in the `TaskOutput` object.
17
+ Calling `.start()` method can start the agent operation and generate response in text and JSON formats stored in the `TaskOutput` object.
18
18
 
19
19
  ```python
20
20
  import versionhq as vhq
@@ -22,7 +22,7 @@ tags:
22
22
  | **`pre_launch_callbacks`** | List[Callable[..., Any]] | list() | Stores callbacks to run before the network launch. |
23
23
  | **`post_launch_callbacks`** | List[Callable[..., Any]] | list() | Stores callbacks to run after the network launch. |
24
24
  | **`step_callbacks`** | Callable[..., Any] | None | Stores callbacks to run at every step of each member agent takes during the activation. |
25
- | **`cache`** | bool | True | Whether to store cache. |
25
+ | **`cache`** | bool | True | Whether to store cache. |
26
26
  | **`execution_logs`** | List[Dict[str, Any]] | list() | Stores a list of execution logs of all the tasks in the network. |
27
27
 
28
28
 
@@ -50,13 +50,13 @@ tags:
50
50
 
51
51
  ### Variable
52
52
 
53
- | <div style="width:200px">**Variable**</div> | **Data Type** | **Default** | **Description** |
54
- | :--- | :--- | :--- | :--- |
55
- | **`agent`** | InstanceOf[`Agent`] | None | Agent as a member |
56
- | **`is_manager`** | bool | False | Whether the member is a manager. |
57
- | **`can_share_knowledge`** | bool | True | Whether the member can share its knowledge among the other network members. |
58
- | **`can_share_memory`** | bool | True | Whether the member can share its memories among the other network members. |
59
- | **`tasks`** | List[InstanceOf[`Task`]] | list() | Assinged tasks. |
53
+ | <div style="width:200px">**Variable**</div> | **Data Type** | **Default** | **Description** |
54
+ | :--- | :--- | :--- | :--- |
55
+ | **`agent`** | InstanceOf[`Agent`] | None | Agent as a member |
56
+ | **`is_manager`** | bool | False | Whether the member is a manager. |
57
+ | **`can_share_knowledge`** | bool | True | Whether the member can share its knowledge among the other network members. |
58
+ | **`can_share_memory`** | bool | True | Whether the member can share its memories among the other network members. |
59
+ | **`tasks`** | List[InstanceOf[`Task`]] | list() | Assinged tasks. |
60
60
 
61
61
 
62
62
  ### Properties
@@ -109,7 +109,7 @@ tags:
109
109
  | :--- | :--- | :--- | :--- |
110
110
  | **`update`** | **kwargs: Any | Self | Updates agents with given kwargs. Invalid keys will be ignored. |
111
111
  | **`start`** | context: Any = None <br> tool_res_as_final: bool = False | `TaskOutput` \| None | Starts to operate the agent. |
112
- | **`execute_task`** | task: [Task] <br> context: Any = None <br> task_tools: Optional[List[Tool \| ToolSet]] = list() | str | Returns response from the model in plane text format. |
112
+ | **`execute_task`** | task: [Task] <br> context: Any = None | Tuple[str, str, Any, UsageMetrics] | Returns response from the model in plane text format. |
113
113
 
114
114
 
115
115
  ### Properties
@@ -122,7 +122,7 @@ tags:
122
122
  ## ENUM `Formation`
123
123
 
124
124
  ```python
125
- class Formation(str, Enum):
125
+ class Formation(IntEnum):
126
126
  SOLO = 1
127
127
  SUPERVISING = 2
128
128
  SQUAD = 3
@@ -133,7 +133,7 @@ class Formation(str, Enum):
133
133
  ## ENUM `TaskHandlingProcess`
134
134
 
135
135
  ```python
136
- class TaskHandlingProcess(str, Enum):
136
+ class TaskHandlingProcess(IntEnum):
137
137
  HIERARCHY = 1
138
138
  SEQUENTIAL = 2
139
139
  CONSENSUAL = 3
@@ -8,7 +8,7 @@
8
8
  | **`name`** | Optional[str] | None | Stores a task name (Inherited as `node` identifier if the task is dependent) |
9
9
  | **`description`** | str | None | Required field to store a concise task description |
10
10
  | **`response_schema`** | Optional[Type[BaseModel] \| List[ResponseField]] | None | Response schema for structured output. |
11
- | **`tools`** | Optional[List[BaseTool \| ToolSet]] | None | Tools, tool sets, or RAG tools |
11
+ | **`tools`** | Optional[List[Any]] | None | Tools, tool sets, or RAG tools |
12
12
  | **`can_use_agent_tools`** | bool | True | Whether to use the agent tools |
13
13
  | **`tool_res_as_final`** | bool | False | Whether to make a tool output as a final response from the agent |
14
14
  | **`image`** | Optional[str] | None | Absolute file path or URL to the image file |
@@ -69,10 +69,11 @@
69
69
  | **`raw`** | str | None | Stores response in plane text format. `None` or `""` when the model returned errors.|
70
70
  | **`json_dict`** | Dict[str, Any] | None | Stores response in JSON serializable dictionary. |
71
71
  | **`pydantic`** | Type[`BaseModel`] | None | Populates the given response schema in pydantic class |
72
- | **`tool_output`** | Optional[Any] | None | Stores results from the tools of the task or agents ONLY when `tool_res_as_final` set as `True`. |
72
+ | **`tool_output`** | Optional[Any] | None | Stores results from the tools of the task or agents when `tool_res_as_final` == True |
73
73
  | **`callback_output`** | Optional[Any] | None | Stores results from callback functions if any. |
74
- | **`latency`** | Optional[float] | None | Stores job latency in milseconds. |
74
+ | **`annotations`** | Optional[Dict[str, Any]] | None | Stores annotations given by the model. |
75
75
  | **`evaluation`** | Optional[InstanceOf[`Evaluation`]] | None | Stores overall evaluations and usage of the task output. |
76
+ | **`usage`** | Optional[InstanceOf[`UsageMetrics]`] | None | Usage related values. |
76
77
 
77
78
 
78
79
  ### Class Methods
@@ -15,7 +15,7 @@ exclude = ["test*", "__pycache__", "*.egg-info"]
15
15
 
16
16
  [project]
17
17
  name = "versionhq"
18
- version = "1.2.4.5"
18
+ version = "1.2.4.6"
19
19
  authors = [{ name = "Kuriko Iwai", email = "kuriko@versi0n.io" }]
20
20
  description = "Autonomous agent networks for task automation with multi-step reasoning."
21
21
  readme = "README.md"
@@ -24,7 +24,10 @@ from versionhq.tool.model import Tool, ToolSet
24
24
  from versionhq.tool.rag_tool import RagTool
25
25
  from versionhq.tool.cache_handler import CacheHandler
26
26
  from versionhq.tool.tool_handler import ToolHandler
27
- from versionhq.tool.composio_tool import ComposioHandler
27
+ from versionhq.tool.composio.model import ComposioBaseTool
28
+ from versionhq.tool.gpt.cup import GPTToolCUP, CUPToolSchema
29
+ from versionhq.tool.gpt.file_search import GPTToolFileSearch, FilterSchema
30
+ from versionhq.tool.gpt.web_search import GPTToolWebSearch
28
31
  from versionhq.memory.contextual_memory import ContextualMemory
29
32
  from versionhq.memory.model import ShortTermMemory,LongTermMemory, UserMemory, MemoryItem
30
33
 
@@ -32,7 +35,7 @@ from versionhq.agent_network.formation import form_agent_network
32
35
  from versionhq.task_graph.draft import workflow
33
36
 
34
37
 
35
- __version__ = "1.2.4.5"
38
+ __version__ = "1.2.4.6"
36
39
  __all__ = [
37
40
  "Agent",
38
41
 
@@ -85,7 +88,13 @@ __all__ = [
85
88
  "RagTool",
86
89
  "CacheHandler",
87
90
  "ToolHandler",
88
- "ComposioHandler",
91
+ "ComposioBaseTool",
92
+
93
+ "GPTToolCUP",
94
+ "CUPToolSchema",
95
+ "GPTToolFileSearch",
96
+ "FilterSchema",
97
+ "GPTToolWebSearch",
89
98
 
90
99
  "ContextualMemory",
91
100
  "ShortTermMemory",
@@ -5,7 +5,7 @@ from pydantic import InstanceOf, Field
5
5
 
6
6
  from versionhq.agent.model import Agent
7
7
  from versionhq.task.model import Task
8
- from versionhq.task_graph.model import TaskGraph, Node, DependencyType, ReformTriggerEvent
8
+ from versionhq.task_graph.model import TaskGraph, Node, DependencyType
9
9
  from versionhq._prompt.model import Prompt
10
10
  from versionhq._prompt.constants import REFLECT, INTEGRATE, parameter_sets
11
11
 
@@ -4,7 +4,7 @@ from textwrap import dedent
4
4
 
5
5
  from pydantic import InstanceOf, BaseModel
6
6
 
7
- from versionhq._utils import is_valid_url
7
+ from versionhq._utils import is_valid_url, convert_img_url
8
8
 
9
9
 
10
10
  class Prompt:
@@ -99,12 +99,9 @@ Ref. Output image: {output_formats_to_follow}
99
99
  content_messages = {}
100
100
 
101
101
  if self.task.image:
102
- with open(self.task.image, "rb") as file:
103
- content = file.read()
104
- if content:
105
- encoded_file = base64.b64encode(content).decode("utf-8")
106
- img_url = f"data:image/jpeg;base64,{encoded_file}"
107
- content_messages.update({ "type": "image_url", "image_url": { "url": img_url }})
102
+ img_url = convert_img_url(self.task.image)
103
+ if img_url:
104
+ content_messages.update({ "type": "image_url", "image_url": { "url": img_url }})
108
105
 
109
106
  if self.task.file:
110
107
  if is_valid_url(self.task.file):
@@ -146,7 +143,7 @@ Ref. Output image: {output_formats_to_follow}
146
143
  return "\n".join(task_slices)
147
144
 
148
145
 
149
- def format_core(self, rag_tools: List[Any] = None) -> Tuple[str, str, List[Dict[str, str]]]:
146
+ def format_core(self, rag_tools: List[Any] = None, gpt_tools: List[Any] = None) -> Tuple[str, str, List[Dict[str, str]]]:
150
147
  """Formats prompt messages sent to the LLM, then returns task prompt, developer prompt, and messages."""
151
148
 
152
149
  from versionhq.knowledge._utils import extract_knowledge_context
@@ -168,6 +165,12 @@ Ref. Output image: {output_formats_to_follow}
168
165
  if rag_tool_context:
169
166
  user_prompt += ",".join(rag_tool_context) if isinstance(rag_tool_context, list) else str(rag_tool_context)
170
167
 
168
+ if gpt_tools:
169
+ for item in gpt_tools:
170
+ raw, _, _ = item.run()
171
+ if raw:
172
+ user_prompt += str(raw)
173
+
171
174
  if self.agent.with_memory == True:
172
175
  contextual_memory = ContextualMemory(
173
176
  memory_config=self.agent.memory_config, stm=self.agent.short_term_memory, ltm=self.agent.long_term_memory, um=self.agent.user_memory
@@ -3,3 +3,5 @@ from versionhq._utils.process_config import process_config
3
3
  from versionhq._utils.vars import KNOWLEDGE_DIRECTORY, MAX_FILE_NAME_LENGTH
4
4
  from versionhq._utils.is_valid_url import is_valid_url
5
5
  from versionhq._utils.usage_metrics import UsageMetrics, ErrorType
6
+ from versionhq._utils.convert_img_url import convert_img_url
7
+ from versionhq._utils.is_valid_enum import is_valid_enum
@@ -0,0 +1,15 @@
1
+ import base64
2
+
3
+ def convert_img_url(img_url: str) -> str | None:
4
+ try:
5
+ with open(img_url, "rb") as file:
6
+ content = file.read()
7
+ if content:
8
+ encoded_file = base64.b64encode(content).decode("utf-8")
9
+ img_url = f"data:image/jpeg;base64,{encoded_file}"
10
+ return img_url
11
+
12
+ else: return None
13
+
14
+ except:
15
+ return None
@@ -0,0 +1,25 @@
1
+ from enum import Enum, IntEnum
2
+ from typing import Any
3
+
4
+
5
+ def is_valid_enum(enum: Enum | IntEnum, key: str = None, val: str | Enum | IntEnum = None) -> bool:
6
+ if not enum: return False
7
+
8
+ if key:
9
+ key = key.upper()
10
+ matched = [k for k in enum._member_map_.keys() if hasattr(enum, "_member_map_") and k == key]
11
+ return bool(matched)
12
+
13
+ elif val:
14
+ match val:
15
+ case str():
16
+ matched = [k for k in enum._value2member_map_.keys() if hasattr(enum, "_value2member_map_") and k == val]
17
+ return bool(matched)
18
+
19
+ case Enum() | IntEnum():
20
+ return val in enum
21
+
22
+ case _:
23
+ return False
24
+
25
+ else: return False
@@ -2,7 +2,6 @@ import json
2
2
  import numpy as np
3
3
  from sklearn.metrics import precision_score, recall_score, roc_auc_score, cohen_kappa_score
4
4
  from typing import List, Tuple, Dict, Any
5
- from pathlib import Path
6
5
 
7
6
 
8
7
  class LLMJudge:
@@ -0,0 +1,93 @@
1
+ import uuid
2
+ import datetime
3
+ from enum import IntEnum
4
+ from typing import Dict, List
5
+ from typing_extensions import Self
6
+
7
+ from pydantic import BaseModel, UUID4, InstanceOf
8
+
9
+
10
+ class ErrorType(IntEnum):
11
+ FORMAT = 1
12
+ TOOL = 2
13
+ API = 3
14
+ OVERFITTING = 4
15
+ HUMAN_INTERACTION = 5
16
+
17
+
18
+ class UsageMetrics(BaseModel):
19
+ """A Pydantic model to manage token usage, errors, job latency."""
20
+
21
+ id: UUID4 = uuid.uuid4() # stores task id or task graph id
22
+ total_tokens: int = 0
23
+ prompt_tokens: int = 0
24
+ completion_tokens: int = 0
25
+ input_tokens: int = 0
26
+ output_tokens: int = 0
27
+ successful_requests: int = 0
28
+ total_errors: int = 0
29
+ error_breakdown: Dict[ErrorType, int] = dict()
30
+ latency: float = 0.0 # in ms
31
+
32
+
33
+ def record_token_usage(self, *args, **kwargs) -> None:
34
+ """Records usage metrics from the raw response of the model."""
35
+
36
+ if args:
37
+ for item in args:
38
+ match item:
39
+ case dict():
40
+ if hasattr(self, k):
41
+ setattr(self, k, int(getattr(self, k)) + int(v))
42
+ case UsageMetrics():
43
+ self = self.aggregate(metrics=item)
44
+ case _:
45
+ try:
46
+ self.completion_tokens += item.completion_tokens if hasattr(item, "completion_tokens") else 0
47
+ self.prompt_tokens += item.prompt_tokens if hasattr(item, "prompt_tokens") else 0
48
+ self.total_tokens += item.total_tokens if hasattr(item, "total_tokens") else 0
49
+ self.input_tokens += item.input_tokens if hasattr(item, "input_tokens") else 0
50
+ self.output_tokens += item.output_tokens if hasattr(item, "output_tokens") else 0
51
+ except:
52
+ pass
53
+ if kwargs:
54
+ for k, v in kwargs.items():
55
+ if hasattr(self, k):
56
+ setattr(self, k, int(getattr(self, k)) + int(v))
57
+
58
+
59
+ def record_errors(self, type: ErrorType = None) -> None:
60
+ self.total_errors += 1
61
+ if type:
62
+ if type in self.error_breakdown:
63
+ self.error_breakdown[type] += 1
64
+ else:
65
+ self.error_breakdown[type] = 1
66
+
67
+
68
+ def record_latency(self, start_dt: datetime.datetime, end_dt: datetime.datetime) -> None:
69
+ self.latency += round((end_dt - start_dt).total_seconds() * 1000, 3)
70
+
71
+
72
+ def aggregate(self, metrics: InstanceOf["UsageMetrics"]) -> Self:
73
+ if not metrics:
74
+ return self
75
+
76
+ self.total_tokens += metrics.total_tokens
77
+ self.prompt_tokens += metrics.prompt_tokens
78
+ self.completion_tokens += metrics.completion_tokens
79
+ self.input_tokens += metrics.input_tokens
80
+ self.output_tokens += metrics.output_tokens
81
+ self.successful_requests += metrics.successful_requests
82
+ self.total_errors += metrics.total_errors
83
+ self.latency += metrics.latency
84
+ self.latency = round(self.latency, 3)
85
+
86
+ if metrics.error_breakdown:
87
+ for k, v in metrics.error_breakdown.items():
88
+ if self.error_breakdown and k in self.error_breakdown:
89
+ self.error_breakdown[k] += int(v)
90
+ else:
91
+ self.error_breakdown.update({ k: v })
92
+
93
+ return self
@@ -11,7 +11,7 @@ from versionhq.agent.rpm_controller import RPMController
11
11
  from versionhq.tool.model import Tool, ToolSet, BaseTool
12
12
  from versionhq.knowledge.model import BaseKnowledgeSource, Knowledge
13
13
  from versionhq.memory.model import ShortTermMemory, LongTermMemory, UserMemory
14
- from versionhq._utils import Logger, process_config, is_valid_url, ErrorType
14
+ from versionhq._utils import Logger, process_config, is_valid_url, ErrorType, UsageMetrics
15
15
 
16
16
 
17
17
  load_dotenv(override=True)
@@ -124,6 +124,9 @@ class Agent(BaseModel):
124
124
  Similar to the LLM set up, when the agent has tools, we will declare them using the Tool class.
125
125
  """
126
126
  from versionhq.tool.rag_tool import RagTool
127
+ from versionhq.tool.gpt.web_search import GPTToolWebSearch
128
+ from versionhq.tool.gpt.file_search import GPTToolFileSearch
129
+ from versionhq.tool.gpt.cup import GPTToolCUP
127
130
 
128
131
  if not self.tools:
129
132
  return self
@@ -131,7 +134,7 @@ class Agent(BaseModel):
131
134
  tool_list = []
132
135
  for item in self.tools:
133
136
  match item:
134
- case RagTool() | BaseTool():
137
+ case RagTool() | BaseTool() | GPTToolCUP() | GPTToolFileSearch() | GPTToolWebSearch():
135
138
  tool_list.append(item)
136
139
 
137
140
  case Tool():
@@ -353,8 +356,8 @@ class Agent(BaseModel):
353
356
  response_format: Optional[Dict[str, Any]] = None,
354
357
  tools: Optional[List[InstanceOf[Tool]| InstanceOf[ToolSet] | Type[Tool]]] = None,
355
358
  tool_res_as_final: bool = False,
356
- task: Any = None
357
- ) -> Dict[str, Any]:
359
+ # task: Any = None
360
+ ) -> Tuple[str, UsageMetrics]:
358
361
  """
359
362
  Create formatted prompts using the developer prompt and the agent's backstory, then call the base model.
360
363
  - Execute the task up to `self.max_retry_limit` times in case of receiving an error or empty response.
@@ -364,6 +367,7 @@ class Agent(BaseModel):
364
367
  task_execution_counter = 0
365
368
  iterations = 0
366
369
  raw_response = None
370
+ usage = UsageMetrics()
367
371
 
368
372
  try:
369
373
  if self._rpm_controller and self.max_rpm:
@@ -373,17 +377,17 @@ class Agent(BaseModel):
373
377
 
374
378
  if tool_res_as_final:
375
379
  raw_response = self.func_calling_llm.call(messages=messages, tools=tools, tool_res_as_final=True)
376
- task._usage.record_token_usage(token_usages=self.func_calling_llm._usages)
380
+ usage.record_token_usage(*self.func_calling_llm._usages)
377
381
  else:
378
382
  raw_response = self.llm.call(messages=messages, response_format=response_format, tools=tools)
379
- task._usage.record_token_usage(token_usages=self.llm._usages)
383
+ usage.record_token_usage(*self.llm._usages)
380
384
 
381
385
  task_execution_counter += 1
382
386
  Logger(**self._logger_config, filename=self.key).log(level="info", message=f"Agent response: {raw_response}", color="green")
383
- return raw_response
387
+ return raw_response, usage
384
388
 
385
389
  except Exception as e:
386
- task._usage.record_errors(type=ErrorType.API)
390
+ usage.record_errors(type=ErrorType.API)
387
391
  Logger(**self._logger_config, filename=self.key).log(level="error", message=f"An error occured. The agent will retry: {str(e)}", color="red")
388
392
 
389
393
  while not raw_response and task_execution_counter <= self.max_retry_limit:
@@ -392,12 +396,12 @@ class Agent(BaseModel):
392
396
  self._rpm_controller.check_or_wait()
393
397
 
394
398
  raw_response = self.llm.call(messages=messages, response_format=response_format, tools=tools)
395
- task._tokens = self.llm._tokens
399
+ usage.record_token_usage(*self.llm._usages)
396
400
  iterations += 1
397
401
 
398
402
  task_execution_counter += 1
399
403
  Logger(**self._logger_config, filename=self.key).log(level="info", message=f"Agent #{task_execution_counter} response: {raw_response}", color="green")
400
- return raw_response
404
+ return raw_response, usage
401
405
 
402
406
  if not raw_response:
403
407
  Logger(**self._logger_config, filename=self.key).log(level="error", message="Received None or empty response from the model", color="red")
@@ -423,6 +427,57 @@ class Agent(BaseModel):
423
427
  return self.set_up_llm()
424
428
 
425
429
 
430
+ def _sort_tools(self, task = None) -> Tuple[List[Any], List[Any], List[Any]]:
431
+ """Sorts agent and task tools by class."""
432
+
433
+ from versionhq.tool.rag_tool import RagTool
434
+ from versionhq.tool.gpt.web_search import GPTToolWebSearch
435
+ from versionhq.tool.gpt.file_search import GPTToolFileSearch
436
+ from versionhq.tool.gpt.cup import GPTToolCUP
437
+
438
+ all_tools = []
439
+ if task: all_tools = task.tools + self.tools if task.can_use_agent_tools else task.tools
440
+ else: all_tools = self.tools
441
+
442
+ rag_tools, gpt_tools, tools = [], [], []
443
+ if all_tools:
444
+ for item in all_tools:
445
+ match item:
446
+ case RagTool():
447
+ rag_tools.append(item)
448
+
449
+ case GPTToolCUP() | GPTToolFileSearch() | GPTToolWebSearch():
450
+ gpt_tools.append(item)
451
+
452
+ case Tool() | BaseTool() | ToolSet():
453
+ tools.append(item)
454
+
455
+ return rag_tools, gpt_tools, tools
456
+
457
+
458
+ def _handle_gpt_tools(self, gpt_tools: list[Any] = None) -> Any: # TaskOutput
459
+ """Generates k, v pairs from multiple GPT tool results and stores them in TaskOutput class."""
460
+
461
+ from versionhq.task.model import TaskOutput
462
+ from versionhq._utils import UsageMetrics
463
+
464
+ if not gpt_tools:
465
+ return
466
+
467
+ tool_res = dict()
468
+ annotation_set = dict()
469
+ total_usage = UsageMetrics()
470
+
471
+ for i, item in enumerate(gpt_tools):
472
+ raw, annotations, usage = item.run()
473
+ tool_res.update({ str(i): raw })
474
+ annotation_set.update({ str(i): annotations })
475
+ total_usage.aggregate(metrics=usage)
476
+
477
+ res = TaskOutput(raw=str(tool_res), tool_output=tool_res, usage=total_usage, annotations=annotation_set)
478
+ return res
479
+
480
+
426
481
  def update(self, **kwargs) -> Self:
427
482
  """
428
483
  Update the existing agent. Address variables that require runnning set_up_x methods first, then update remaining variables.
@@ -482,15 +537,21 @@ class Agent(BaseModel):
482
537
  image: str = None,
483
538
  file: str = None,
484
539
  audio: str = None
485
- ) -> Tuple[Any | None, Any | None]:
540
+ ) -> Any:
486
541
  """
487
542
  Defines and executes a task, then returns TaskOutput object with the generated task.
488
543
  """
489
544
 
545
+ from versionhq.task.model import Task
546
+
490
547
  if not self.role:
491
- return None
548
+ return None, None
492
549
 
493
- from versionhq.task.model import Task
550
+ _, gpt_tools, _ = self._sort_tools()
551
+
552
+ if gpt_tools and tool_res_as_final == True:
553
+ res = self._handle_gpt_tools(gpt_tools=gpt_tools)
554
+ return res
494
555
 
495
556
  class Output(BaseModel):
496
557
  result: str
@@ -503,44 +564,47 @@ class Agent(BaseModel):
503
564
  image=image, #REFINEME - query memory/knowledge or self create
504
565
  file=file,
505
566
  audio=audio,
567
+ can_use_agent_tools=True if self.tools else False,
506
568
  )
507
569
  res = task.execute(agent=self, context=context)
508
- return res, task
570
+ return res
509
571
 
510
572
 
511
- def execute_task(self, task, context: Optional[Any] = None, task_tools: Optional[List[Tool | ToolSet]] = list()) -> str:
573
+ def execute_task(self, task, context: Optional[Any] = None) -> Tuple[str, str, Any, UsageMetrics]:
512
574
  """Handling task execution."""
513
575
 
514
- from versionhq.task.model import Task
515
- from versionhq.tool.rag_tool import RagTool
516
576
  from versionhq._prompt.model import Prompt
577
+ from versionhq.task.model import Task
517
578
 
518
579
  task: InstanceOf[Task] = task
519
- all_tools: Optional[List[Tool | ToolSet | RagTool | Type[BaseTool]]] = task_tools + self.tools if task.can_use_agent_tools else task_tools
520
- rag_tools: Optional[List[RagTool]] = [item for item in all_tools if isinstance(item, RagTool)] if all_tools else None
521
- tools: Optional[List[Tool | ToolSet | RagTool | Type[BaseTool]]] = [item for item in all_tools if not isinstance(item, RagTool)] if all_tools else None
580
+ rag_tools, gpt_tools, tools = self._sort_tools(task=task)
581
+ raw_response = ""
582
+ user_prompt, dev_prompt = "", ""
583
+ usage = UsageMetrics(id=task.id)
522
584
 
523
585
  if self.max_rpm and self._rpm_controller:
524
586
  self._rpm_controller._reset_request_count()
525
587
 
526
- user_prompt, dev_prompt, messages = Prompt(task=task, agent=self, context=context).format_core(rag_tools=rag_tools)
588
+ if task.tool_res_as_final == True and gpt_tools:
589
+ self._times_executed += 1
590
+ res = self._handle_gpt_tools(gpt_tools=gpt_tools)
591
+ return user_prompt, dev_prompt, res, res.usage
592
+
593
+ user_prompt, dev_prompt, messages = Prompt(task=task, agent=self, context=context).format_core(rag_tools=rag_tools, gpt_tools=gpt_tools)
527
594
 
528
595
  try:
529
596
  self._times_executed += 1
530
- raw_response = self._invoke(
597
+ raw_response, usage = self._invoke(
531
598
  messages=messages,
532
599
  response_format=task._structure_response_format(model_provider=self.llm.provider),
533
600
  tools=tools,
534
601
  tool_res_as_final=task.tool_res_as_final,
535
- task=task
536
602
  )
537
- if raw_response:
538
- task._usage.successful_requests += 1
539
603
 
540
604
  except Exception as e:
541
605
  self._times_executed += 1
542
606
  Logger(**self._logger_config, filename=self.key).log(level="error", message=f"The agent failed to execute the task. Error: {str(e)}", color="red")
543
- user_prompt, dev_prompt, raw_response = self.execute_task(task, context, task_tools)
607
+ user_prompt, dev_prompt, raw_response, usage = self.execute_task(task, context)
544
608
 
545
609
  if self._times_executed > self.max_retry_limit:
546
610
  Logger(**self._logger_config, filename=self.key).log(level="error", message=f"Max retry limit has exceeded.", color="red")
@@ -549,7 +613,7 @@ class Agent(BaseModel):
549
613
  if self.max_rpm and self._rpm_controller:
550
614
  self._rpm_controller.stop_rpm_counter()
551
615
 
552
- return user_prompt, dev_prompt, raw_response
616
+ return user_prompt, dev_prompt, raw_response, usage
553
617
 
554
618
 
555
619
  @property
@@ -7,7 +7,7 @@ from versionhq.task.model import Task
7
7
  from versionhq.agent.model import Agent
8
8
  from versionhq.agent_network.model import AgentNetwork, Member, Formation
9
9
  from versionhq.agent.inhouse_agents import vhq_formation_planner
10
- from versionhq._utils import Logger
10
+ from versionhq._utils import Logger, is_valid_enum
11
11
 
12
12
  import chromadb
13
13
  chromadb.api.client.SharedSystemClient.clear_system_cache()
@@ -83,14 +83,6 @@ def form_agent_network(
83
83
 
84
84
  res = vhq_task.execute(agent=vhq_formation_planner, context=context)
85
85
 
86
- formation_keys = []
87
- if hasattr(res.pydantic, "formation"):
88
- formation_keys = [k for k in Formation._member_map_.keys() if k == res.pydantic.formation.upper()]
89
- elif "formation" in res.json_dict:
90
- formation_keys = [k for k in Formation._member_map_.keys() if k == res.json_dict["formation"].upper()]
91
-
92
- _formation = Formation[formation_keys[0]] if formation_keys else Formation.SUPERVISING
93
-
94
86
  network_tasks = []
95
87
  members = []
96
88
  leader = res._fetch_value_of(key="leader_agent")
@@ -98,6 +90,8 @@ def form_agent_network(
98
90
  created_agents = [Agent(role=str(item), goal=str(item)) for item in agent_roles] if agent_roles else []
99
91
  task_descriptions = res._fetch_value_of(key="task_descriptions")
100
92
  task_outcomes = res._fetch_value_of(key="task_outcomes")
93
+ formation_key = res.json_dict["formation"] if "formation" in res.json_dict else None
94
+ _formation = Formation[formation_key] if is_valid_enum(key=formation_key, enum=Formation) else Formation.SUPERVISING
101
95
 
102
96
  if agents:
103
97
  for i, agent in enumerate(created_agents):
@@ -1,7 +1,6 @@
1
1
  import uuid
2
2
  import warnings
3
- from enum import Enum
4
- from concurrent.futures import Future
3
+ from enum import IntEnum
5
4
  from hashlib import md5
6
5
  from typing import Any, Dict, List, Callable, Optional, Tuple
7
6
  from typing_extensions import Self
@@ -30,7 +29,7 @@ GenerateSchema.match_type = match_type
30
29
  warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")
31
30
 
32
31
 
33
- class Formation(str, Enum):
32
+ class Formation(IntEnum):
34
33
  SOLO = 1
35
34
  SUPERVISING = 2
36
35
  SQUAD = 3
@@ -38,7 +37,7 @@ class Formation(str, Enum):
38
37
  HYBRID = 10
39
38
 
40
39
 
41
- class TaskHandlingProcess(str, Enum):
40
+ class TaskHandlingProcess(IntEnum):
42
41
  """
43
42
  A class representing task handling processes to tackle multiple tasks.
44
43
  When the agent network has multiple tasks that connect with edges, follow the edge conditions.
@@ -1,7 +1,7 @@
1
- from enum import Enum
1
+ from enum import IntEnum
2
2
 
3
3
 
4
- class Status(str, Enum):
4
+ class Status(IntEnum):
5
5
  NOT_ASSIGNED = 0
6
6
  READY_TO_DEPLOY = 1
7
7
  ACTIVE_ON_WORKFLOW = 2