versionhq 1.2.4.14__tar.gz → 1.2.4.15__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 (176) hide show
  1. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/PKG-INFO +2 -2
  2. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/pyproject.toml +2 -2
  3. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/requirements.txt +0 -1
  4. versionhq-1.2.4.15/requirements_tool.txt +4 -0
  5. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/__init__.py +3 -3
  6. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_prompt/model.py +27 -26
  7. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/model.py +6 -7
  8. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/llm/llm_vars.py +13 -3
  9. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/llm/model.py +50 -18
  10. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task/model.py +1 -0
  11. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/gpt/cua.py +14 -21
  12. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq.egg-info/PKG-INFO +2 -2
  13. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq.egg-info/SOURCES.txt +2 -1
  14. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq.egg-info/requires.txt +1 -1
  15. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/llm/llm_connection_test.py +2 -2
  16. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/llm/llm_test.py +2 -2
  17. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task/task_test.py +9 -0
  18. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/tool/gpt_test.py +10 -6
  19. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/uv.lock +81 -70
  20. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.env.sample +0 -0
  21. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.github/workflows/deploy_docs.yml +0 -0
  22. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.github/workflows/publish.yml +0 -0
  23. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.github/workflows/publish_testpypi.yml +0 -0
  24. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.github/workflows/run_tests.yml +0 -0
  25. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.github/workflows/security_check.yml +0 -0
  26. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.gitignore +0 -0
  27. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.pre-commit-config.yaml +0 -0
  28. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/.python-version +0 -0
  29. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/LICENSE +0 -0
  30. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/README.md +0 -0
  31. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/SECURITY.md +0 -0
  32. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/db/preprocess.py +0 -0
  33. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/CNAME +0 -0
  34. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/_logos/favicon.ico +0 -0
  35. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/_logos/logo192.png +0 -0
  36. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent/config.md +0 -0
  37. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent/index.md +0 -0
  38. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent/task-handling.md +0 -0
  39. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent-network/config.md +0 -0
  40. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent-network/form.md +0 -0
  41. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent-network/index.md +0 -0
  42. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/agent-network/ref.md +0 -0
  43. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/knowledge.md +0 -0
  44. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/llm/index.md +0 -0
  45. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/memory.md +0 -0
  46. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/rag-tool.md +0 -0
  47. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/evaluation.md +0 -0
  48. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/index.md +0 -0
  49. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/reference.md +0 -0
  50. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/response-field.md +0 -0
  51. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/task-execution.md +0 -0
  52. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/task-output.md +0 -0
  53. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task/task-strc-response.md +0 -0
  54. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/task-graph/index.md +0 -0
  55. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/core/tool.md +0 -0
  56. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/index.md +0 -0
  57. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/quickstart.md +0 -0
  58. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/stylesheets/main.css +0 -0
  59. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/docs/tags.md +0 -0
  60. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/mkdocs.yml +0 -0
  61. /versionhq-1.2.4.14/requirements-dev.txt → /versionhq-1.2.4.15/requirements_dev.txt +0 -0
  62. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/runtime.txt +0 -0
  63. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/setup.cfg +0 -0
  64. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_prompt/auto_feedback.py +0 -0
  65. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_prompt/constants.py +0 -0
  66. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/__init__.py +0 -0
  67. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/convert_img_url.py +0 -0
  68. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/handle_directory.py +0 -0
  69. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/i18n.py +0 -0
  70. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/is_valid_enum.py +0 -0
  71. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/is_valid_url.py +0 -0
  72. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/llm_as_a_judge.py +0 -0
  73. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/logger.py +0 -0
  74. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/process_config.py +0 -0
  75. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/usage_metrics.py +0 -0
  76. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/_utils/vars.py +0 -0
  77. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/TEMPLATES/Backstory.py +0 -0
  78. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/TEMPLATES/__init__.py +0 -0
  79. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/__init__.py +0 -0
  80. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/inhouse_agents.py +0 -0
  81. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/parser.py +0 -0
  82. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent/rpm_controller.py +0 -0
  83. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent_network/__init__.py +0 -0
  84. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent_network/formation.py +0 -0
  85. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/agent_network/model.py +0 -0
  86. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/cli/__init__.py +0 -0
  87. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/__init__.py +0 -0
  88. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/customer/__init__.py +0 -0
  89. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/customer/model.py +0 -0
  90. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/product/__init__.py +0 -0
  91. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/product/model.py +0 -0
  92. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/workflow/__init__.py +0 -0
  93. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/clients/workflow/model.py +0 -0
  94. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/__init__.py +0 -0
  95. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/_utils.py +0 -0
  96. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/embedding.py +0 -0
  97. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/model.py +0 -0
  98. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/source.py +0 -0
  99. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/source_docling.py +0 -0
  100. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/knowledge/storage.py +0 -0
  101. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/llm/__init__.py +0 -0
  102. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/memory/__init__.py +0 -0
  103. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/memory/contextual_memory.py +0 -0
  104. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/memory/model.py +0 -0
  105. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/__init__.py +0 -0
  106. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/base.py +0 -0
  107. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/ltm_sqlite_storage.py +0 -0
  108. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/mem0_storage.py +0 -0
  109. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/rag_storage.py +0 -0
  110. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/task_output_storage.py +0 -0
  111. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/storage/utils.py +0 -0
  112. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task/TEMPLATES/Description.py +0 -0
  113. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task/__init__.py +0 -0
  114. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task/evaluation.py +0 -0
  115. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task/formatter.py +0 -0
  116. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task/structured_response.py +0 -0
  117. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task_graph/__init__.py +0 -0
  118. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task_graph/colors.py +0 -0
  119. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task_graph/draft.py +0 -0
  120. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/task_graph/model.py +0 -0
  121. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/__init__.py +0 -0
  122. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/cache_handler.py +0 -0
  123. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/composio/__init__.py +0 -0
  124. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/composio/model.py +0 -0
  125. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/composio/params.py +0 -0
  126. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/decorator.py +0 -0
  127. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/gpt/__init__.py +0 -0
  128. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/gpt/_enum.py +0 -0
  129. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/gpt/file_search.py +0 -0
  130. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/gpt/web_search.py +0 -0
  131. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/model.py +0 -0
  132. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/rag_tool.py +0 -0
  133. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq/tool/tool_handler.py +0 -0
  134. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq.egg-info/dependency_links.txt +0 -0
  135. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/src/versionhq.egg-info/top_level.txt +0 -0
  136. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/__init__.py +0 -0
  137. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/_prompt/auto_feedback_test.py +0 -0
  138. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/_prompt/prompt_test.py +0 -0
  139. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/_sample/sample.csv +0 -0
  140. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/_sample/sample.json +0 -0
  141. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/_sample/sample.mp3 +0 -0
  142. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/_sample/screenshot.png +0 -0
  143. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent/__init__.py +0 -0
  144. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent/agent_test.py +0 -0
  145. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent/doc_test.py +0 -0
  146. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent_network/Prompts/Demo_test.py +0 -0
  147. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent_network/__init__.py +0 -0
  148. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent_network/agent_network_test.py +0 -0
  149. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/agent_network/doc_test.py +0 -0
  150. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/cli/__init__.py +0 -0
  151. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/clients/customer_test.py +0 -0
  152. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/clients/product_test.py +0 -0
  153. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/clients/workflow_test.py +0 -0
  154. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/conftest.py +0 -0
  155. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/doc_test.py +0 -0
  156. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/formation_test.py +0 -0
  157. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/knowledge/__init__.py +0 -0
  158. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/knowledge/knowledge_test.py +0 -0
  159. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/knowledge/mock_report_compressed.pdf +0 -0
  160. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/llm/__init__.py +0 -0
  161. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/memory/__init__.py +0 -0
  162. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/memory/memory_test.py +0 -0
  163. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task/__init__.py +0 -0
  164. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task/doc_eval_test.py +0 -0
  165. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task/doc_taskoutput_test.py +0 -0
  166. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task/doc_test.py +0 -0
  167. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task/eval_test.py +0 -0
  168. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task_graph/__init__.py +0 -0
  169. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task_graph/doc_test.py +0 -0
  170. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/task_graph/task_graph_test.py +0 -0
  171. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/tool/__init__.py +0 -0
  172. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/tool/composio_test.py +0 -0
  173. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/tool/doc_test.py +0 -0
  174. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/tool/rag_tool_test.py +0 -0
  175. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/tool/tool_test.py +0 -0
  176. {versionhq-1.2.4.14 → versionhq-1.2.4.15}/tests/usecase_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: versionhq
3
- Version: 1.2.4.14
3
+ Version: 1.2.4.15
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
@@ -77,7 +77,7 @@ Provides-Extra: tools
77
77
  Requires-Dist: html2text>=2024.2.26; extra == "tools"
78
78
  Requires-Dist: sec-api>=1.0.28; extra == "tools"
79
79
  Requires-Dist: pytest-playwright>=0.7.0; extra == "tools"
80
- Requires-Dist: selenium>=4.29.0; extra == "tools"
80
+ Requires-Dist: selenium>=4.30.0; extra == "tools"
81
81
  Provides-Extra: torch
82
82
  Requires-Dist: torch>=2.6.0; extra == "torch"
83
83
  Requires-Dist: torchvision>=0.21.0; extra == "torch"
@@ -15,7 +15,7 @@ exclude = ["test*", "__pycache__", "*.egg-info"]
15
15
 
16
16
  [project]
17
17
  name = "versionhq"
18
- version = "1.2.4.14"
18
+ version = "1.2.4.15"
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"
@@ -82,7 +82,7 @@ tools = [
82
82
  "html2text>=2024.2.26",
83
83
  "sec-api>=1.0.28",
84
84
  "pytest-playwright>=0.7.0",
85
- "selenium>=4.29.0",
85
+ "selenium>=4.30.0",
86
86
  ]
87
87
  torch = [
88
88
  "torch>=2.6.0",
@@ -19,4 +19,3 @@ boto3>=1.37.1
19
19
  scikit-learn>=1.6.1
20
20
  numpy>=1.26.4
21
21
  pandas>=2.2.3
22
- selenium==4.29.0
@@ -0,0 +1,4 @@
1
+ html2text>=2024.2.26
2
+ sec-api>=1.0.28
3
+ pytest-playwright>=0.7.0
4
+ selenium==4.30.0
@@ -10,7 +10,7 @@ load_dotenv(override=True)
10
10
  from versionhq.agent.model import Agent
11
11
  from versionhq.agent_network.model import AgentNetwork, Formation, Member, TaskHandlingProcess
12
12
  from versionhq.llm.model import LLM
13
- from versionhq.llm.llm_vars import LLM_CONTEXT_WINDOW_SIZES, MODEL_PARAMS, PROVIDERS, TEXT_MODELS
13
+ from versionhq.llm.llm_vars import LLM_CONTEXT_WINDOW_SIZES, MODEL_PARAMS, PROVIDERS, MODELS
14
14
  from versionhq.clients.customer.model import Customer
15
15
  from versionhq.clients.product.model import Product, ProductProvider
16
16
  from versionhq.clients.workflow.model import MessagingWorkflow, MessagingComponent
@@ -35,7 +35,7 @@ from versionhq.agent_network.formation import form_agent_network
35
35
  from versionhq.task_graph.draft import workflow
36
36
 
37
37
 
38
- __version__ = "1.2.4.14"
38
+ __version__ = "1.2.4.15"
39
39
  __all__ = [
40
40
  "Agent",
41
41
 
@@ -48,7 +48,7 @@ __all__ = [
48
48
  "LLM_CONTEXT_WINDOW_SIZES",
49
49
  "MODEL_PARAMS",
50
50
  "PROVIDERS",
51
- "TEXT_MODELS",
51
+ "MODELS",
52
52
 
53
53
  "Customer",
54
54
  "Product",
@@ -14,7 +14,6 @@ class Prompt:
14
14
  agent: Any = None
15
15
  context: Any = None
16
16
 
17
-
18
17
  def __init__(self, task, agent, context):
19
18
  from versionhq.agent.model import Agent
20
19
  from versionhq.task.model import Task
@@ -32,22 +31,24 @@ class Prompt:
32
31
  output_prompt = ""
33
32
  output_formats_to_follow = dict()
34
33
 
35
- if self.task.response_schema:
36
- if isinstance(self.task.response_schema, list):
37
- for item in self.task.response_schema:
38
- if isinstance(item, ResponseField):
39
- output_formats_to_follow[item.title] = f"<Return your answer in {item.data_type.__name__}>"
34
+ if self.task.is_multimodal == False:
35
+ if self.task.response_schema:
36
+ if isinstance(self.task.response_schema, list):
37
+ for item in self.task.response_schema:
38
+ if isinstance(item, ResponseField):
39
+ output_formats_to_follow[item.title] = f"<Return your answer in {item.data_type.__name__}>"
40
40
 
41
- elif issubclass(self.task.response_schema, BaseModel):
42
- for k, v in self.task.response_schema.model_fields.items():
43
- output_formats_to_follow[k] = f"<Return your answer in {v.annotation}>"
41
+ elif issubclass(self.task.response_schema, BaseModel):
42
+ for k, v in self.task.response_schema.model_fields.items():
43
+ output_formats_to_follow[k] = f"<Return your answer in {v.annotation}>"
44
44
 
45
- output_prompt = f"""Your response MUST be a valid JSON string that strictly follows the response format. Use double quotes for all keys and string values. Do not use single quotes, trailing commas, or any other non-standard JSON syntax.
46
- Ref. Output image: {output_formats_to_follow}
47
- """
48
- else:
49
- output_prompt = "You MUST return your response as a valid JSON serializable string, enclosed in double quotes. Use double quotes for all keys and string values. Do NOT use single quotes, trailing commas, or other non-standard JSON syntax."
45
+ output_prompt = f"""Your response MUST be a valid JSON string that strictly follows the response format. Use double quotes for all keys and string values. Do not use single quotes, trailing commas, or any other non-standard JSON syntax.
46
+ Ref. Output image: {output_formats_to_follow}"""
47
+ else:
48
+ output_prompt = "You MUST return your response as a valid JSON serializable string, enclosed in double quotes. Use double quotes for all keys and string values. Do NOT use single quotes, trailing commas, or other non-standard JSON syntax."
50
49
 
50
+ else:
51
+ output_prompt = "Return your response in concise manner."
51
52
  return dedent(output_prompt)
52
53
 
53
54
 
@@ -98,19 +99,20 @@ Ref. Output image: {output_formats_to_follow}
98
99
 
99
100
  content_messages = {}
100
101
 
101
- if self.task.image:
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 }})
102
+ if self.task.is_multimodal == False:
103
+ if self.task.image:
104
+ img_url = convert_img_url(self.task.image)
105
+ if img_url:
106
+ content_messages.update({ "type": "image_url", "image_url": { "url": img_url }})
105
107
 
106
- if self.task.file:
107
- if is_valid_url(self.task.file):
108
- content_messages.update({ "type": "image_url", "image_url": self.file })
108
+ if self.task.file:
109
+ if is_valid_url(self.task.file):
110
+ content_messages.update({ "type": "image_url", "image_url": self.file })
109
111
 
110
- if self.task.audio and self.agent.llm.provider == "gemini":
111
- audio_bytes = Path(self.task.audio).read_bytes()
112
- encoded_data = base64.b64encode(audio_bytes).decode("utf-8")
113
- content_messages.update({ "type": "image_url", "image_url": "data:audio/mp3;base64,{}".format(encoded_data)})
112
+ if self.task.audio and self.agent.llm.provider == "gemini":
113
+ audio_bytes = Path(self.task.audio).read_bytes()
114
+ encoded_data = base64.b64encode(audio_bytes).decode("utf-8")
115
+ content_messages.update({ "type": "image_url", "image_url": "data:audio/mp3;base64,{}".format(encoded_data)})
114
116
 
115
117
  return content_messages
116
118
 
@@ -188,7 +190,6 @@ Ref. Output image: {output_formats_to_follow}
188
190
  # else:
189
191
  # user_prompt = self.agent._use_trained_data(user_prompt=user_prompt)
190
192
 
191
-
192
193
  content_prompt = self._format_content_prompt()
193
194
 
194
195
  messages = []
@@ -356,12 +356,9 @@ class Agent(BaseModel):
356
356
  response_format: Optional[Dict[str, Any]] = None,
357
357
  tools: Optional[List[InstanceOf[Tool]| InstanceOf[ToolSet] | Type[Tool]]] = None,
358
358
  tool_res_as_final: bool = False,
359
+ file: str = None, # absolute path to the content file (for multimodal use)
359
360
  ) -> Tuple[str, UsageMetrics]:
360
- """
361
- Create formatted prompts using the developer prompt and the agent's backstory, then call the base model.
362
- - Execute the task up to `self.max_retry_limit` times in case of receiving an error or empty response.
363
- - Pass the task_tools to the model to let them execute.
364
- """
361
+ """Calls LLM."""
365
362
 
366
363
  task_execution_counter = 0
367
364
  iterations = 0
@@ -375,10 +372,10 @@ class Agent(BaseModel):
375
372
  Logger(**self._logger_config, filename=self.key).log(level="info", message=f"Messages sent to the model: {messages}", color="blue")
376
373
 
377
374
  if tool_res_as_final:
378
- raw_response = self.func_calling_llm.call(messages=messages, tools=tools, tool_res_as_final=True)
375
+ raw_response = self.func_calling_llm.call(messages=messages, tools=tools, tool_res_as_final=True, file=file)
379
376
  usage.record_token_usage(*self.func_calling_llm._usages)
380
377
  else:
381
- raw_response = self.llm.call(messages=messages, response_format=response_format, tools=tools)
378
+ raw_response = self.llm.call(messages=messages, response_format=response_format, tools=tools, file=file)
382
379
  usage.record_token_usage(*self.llm._usages)
383
380
 
384
381
  task_execution_counter += 1
@@ -582,6 +579,7 @@ class Agent(BaseModel):
582
579
  raw_response = ""
583
580
  user_prompt, dev_prompt = "", ""
584
581
  usage = UsageMetrics(id=task.id)
582
+ file = task.audio if task.is_multimodal and task.audio else task.image if task.is_multimodal and task.image else task.file if task.is_multimodal and task.file else None
585
583
 
586
584
  if self.max_rpm and self._rpm_controller:
587
585
  self._rpm_controller._reset_request_count()
@@ -600,6 +598,7 @@ class Agent(BaseModel):
600
598
  response_format=task._structure_response_format(model_provider=self.llm.provider),
601
599
  tools=tools,
602
600
  tool_res_as_final=task.tool_res_as_final,
601
+ file=file,
603
602
  )
604
603
 
605
604
  except Exception as e:
@@ -28,14 +28,13 @@ PROVIDERS = {
28
28
  "HF_ENDPOINT": "HF_ENDPOINT",
29
29
  },
30
30
  "azure": {
31
- "api_base": "AZURE_OPENAI_ENDPOINT",
31
+ "api_base": "AZURE_OPENAI_ENDPOINT_MODEL_NAME",
32
32
  "api_key": "AZURE_OPENAI_API_KEY",
33
33
  "api_version": "AZURE_OPENAI_API_VERSION",
34
34
  },
35
35
  "azure_ai": {
36
36
  "api_key": "AZURE_AI_API_KEY",
37
37
  "base_url": "AZURE_AI_API_BASE",
38
-
39
38
  }
40
39
  }
41
40
 
@@ -47,7 +46,7 @@ ENDPOINTS = [
47
46
 
48
47
 
49
48
  # Resaoning and text generation models
50
- TEXT_MODELS = {
49
+ MODELS = {
51
50
  "openai": [
52
51
  "gpt-4.5-preview-2025-02-27",
53
52
  "gpt-4",
@@ -96,6 +95,10 @@ TEXT_MODELS = {
96
95
  "bedrock/cohere.command-light-text-v14",
97
96
  ],
98
97
  "azure": [
98
+ "azure/whisper",
99
+ "azure/whisper-2",
100
+ "azure/gpt-4o-mini-audio-preview",
101
+
99
102
  "azure/DeepSeek-V3",
100
103
  "azure/DeepSeek-R1",
101
104
  "azure/Llama-3.3-70B-Instruct",
@@ -163,6 +166,13 @@ TEXT_MODELS = {
163
166
  }
164
167
 
165
168
 
169
+ AUDIO_TO_TEXT_MODELS = [
170
+ "azure/whisper",
171
+ "azure/whisper-2",
172
+ "azure/gpt-4o-mini-audio-preview",
173
+ ]
174
+
175
+
166
176
  """
167
177
  Max input token size by the model.
168
178
  """
@@ -12,9 +12,9 @@ import litellm
12
12
  from litellm import JSONSchemaValidationError, get_supported_openai_params, supports_response_schema
13
13
  from pydantic import BaseModel, Field, PrivateAttr, model_validator, ConfigDict
14
14
 
15
- from versionhq.llm.llm_vars import LLM_CONTEXT_WINDOW_SIZES, TEXT_MODELS, MODEL_PARAMS, PROVIDERS, ENDPOINTS
15
+ from versionhq.llm.llm_vars import LLM_CONTEXT_WINDOW_SIZES, MODELS, AUDIO_TO_TEXT_MODELS, MODEL_PARAMS, PROVIDERS, ENDPOINTS
16
16
  from versionhq.tool.model import Tool, ToolSet
17
- from versionhq._utils import Logger
17
+ from versionhq._utils import Logger, UsageMetrics, ErrorType
18
18
 
19
19
 
20
20
  load_dotenv(override=True)
@@ -115,7 +115,7 @@ class LLM(BaseModel):
115
115
  self.provider = DEFAULT_MODEL_PROVIDER_NAME
116
116
 
117
117
  else:
118
- provider_model_list = TEXT_MODELS.get(self.provider)
118
+ provider_model_list = MODELS.get(self.provider)
119
119
  if provider_model_list:
120
120
  self.model = provider_model_list[0]
121
121
  self.provider = self.provider
@@ -127,29 +127,29 @@ class LLM(BaseModel):
127
127
  elif self.model and self.provider is None:
128
128
  model_match = [
129
129
  item for item in [
130
- [val for val in v if val == self.model][0] for k, v in TEXT_MODELS.items() if [val for val in v if val == self.model]
130
+ [val for val in v if val == self.model][0] for k, v in MODELS.items() if [val for val in v if val == self.model]
131
131
  ] if item
132
132
  ]
133
133
  model_partial_match = [
134
134
  item for item in [
135
- [val for val in v if val.find(self.model) != -1][0] for k, v in TEXT_MODELS.items() if [val for val in v if val.find(self.model) != -1]
135
+ [val for val in v if val.find(self.model) != -1][0] for k, v in MODELS.items() if [val for val in v if val.find(self.model) != -1]
136
136
  ] if item
137
137
  ]
138
- provider_match = [k for k, v in TEXT_MODELS.items() if k == self.model]
138
+ provider_match = [k for k, v in MODELS.items() if k == self.model]
139
139
 
140
140
  if model_match:
141
141
  self.model = model_match[0]
142
- self.provider = [k for k, v in TEXT_MODELS.items() if self.model in v][0]
142
+ self.provider = [k for k, v in MODELS.items() if self.model in v][0]
143
143
 
144
144
  elif model_partial_match:
145
145
  self.model = model_partial_match[0]
146
- self.provider = [k for k, v in TEXT_MODELS.items() if [item for item in v if item.find(self.model) != -1]][0]
146
+ self.provider = [k for k, v in MODELS.items() if [item for item in v if item.find(self.model) != -1]][0]
147
147
 
148
148
  elif provider_match:
149
149
  provider = provider_match[0]
150
- if self.TEXT_MODELS.get(provider):
150
+ if self.MODELS.get(provider):
151
151
  self.provider = provider
152
- self.model = self.TEXT_MODELS.get(provider)[0]
152
+ self.model = self.MODELS.get(provider)[0]
153
153
  else:
154
154
  self.provider = DEFAULT_MODEL_PROVIDER_NAME
155
155
  self.model = DEFAULT_MODEL_NAME
@@ -159,7 +159,7 @@ class LLM(BaseModel):
159
159
  self.provider = DEFAULT_MODEL_PROVIDER_NAME
160
160
 
161
161
  else:
162
- provider_model_list = TEXT_MODELS.get(self.provider)
162
+ provider_model_list = MODELS.get(self.provider)
163
163
  if self.model not in provider_model_list:
164
164
  self._logger.log(level="warning", message=f"The provided model: {self._init_model_name} is not in the list. We will assign a default model.", color="yellow")
165
165
  self.model = DEFAULT_MODEL_NAME
@@ -232,7 +232,16 @@ class LLM(BaseModel):
232
232
 
233
233
  valid_cred = {}
234
234
  for k, v in cred.items():
235
- val = os.environ.get(v, None)
235
+ val = None
236
+ if '_MODEL_NAME' in v:
237
+ model_name = self.model.split('/')[-1] if self.model.split('/') else self.model
238
+ key = v.replace('_MODEL_NAME', f'_{model_name.replace("-", '_').replace(' ', '_').upper()}')
239
+ val = os.environ.get(key, None)
240
+ if not val:
241
+ val = os.environ.get(v.replace('_MODEL_NAME', ''), None)
242
+ else:
243
+ val = os.environ.get(v, None)
244
+
236
245
  if val:
237
246
  valid_cred[str(k)] = val
238
247
 
@@ -288,12 +297,12 @@ class LLM(BaseModel):
288
297
  messages: List[Dict[str, str]],
289
298
  response_format: Optional[Dict[str, Any]] = None,
290
299
  tools: Optional[List[Tool | ToolSet | Any ]] = None,
291
- config: Optional[Dict[str, Any]] = {}, # any other conditions to pass on to the model.
292
- tool_res_as_final: bool = False
300
+ config: Optional[Dict[str, Any]] = dict(),
301
+ tool_res_as_final: bool = False,
302
+ file: str = None
293
303
  ) -> str:
294
- """
295
- Execute LLM based on the agent's params and model params.
296
- """
304
+ """Configures and calls the LLM (chat, text generation, reasoning models)."""
305
+
297
306
  litellm.drop_params = True
298
307
  litellm.set_verbose = True
299
308
 
@@ -302,9 +311,32 @@ class LLM(BaseModel):
302
311
  self._set_callbacks(self.callbacks)
303
312
 
304
313
  try:
305
- res, tool_res = None, ""
314
+ res = None
315
+ tool_res = ""
306
316
  cred = self._set_credentials()
307
317
 
318
+ if file and self.model in AUDIO_TO_TEXT_MODELS:
319
+ params = self._create_valid_params(config=config)
320
+ audio_file = open(file, 'rb')
321
+ res = litellm.transcription(
322
+ model=self.model,
323
+ file=audio_file,
324
+ rompt=messages,
325
+ ustom_llm_provider=self.endpoint_provider,
326
+ response_format="json",
327
+ **cred
328
+ )
329
+ usage = UsageMetrics()
330
+ if res:
331
+ usage.latency = res._response_ms if hasattr(res, '_response_ms') else 0
332
+ self._usages.append(usage)
333
+ return res.text
334
+ else:
335
+ usage.record_errors(type=ErrorType.API)
336
+ self._usages.append(usage)
337
+ return None
338
+
339
+
308
340
  if self.provider == "gemini":
309
341
  self.response_format = { "type": "json_object" } if not tools and self.model != "gemini/gemini-2.0-flash-thinking-exp" else None
310
342
  elif response_format and "json_schema" in response_format:
@@ -314,6 +314,7 @@ class Task(BaseModel):
314
314
  name: Optional[str] = Field(default=None)
315
315
  description: str = Field(description="Description of the actual task")
316
316
  response_schema: Optional[Type[BaseModel] | List[ResponseField]] = Field(default=None, description="stores response format")
317
+ is_multimodal: bool = False
317
318
 
318
319
  # tool usage
319
320
  tools: Optional[List[Any]] = Field(default_factory=list, description="tools that the agent can use aside from their tools")
@@ -2,37 +2,32 @@ import base64
2
2
  import datetime
3
3
  import time
4
4
  import platform
5
- from typing import List, Dict, Any, Tuple
5
+ from typing import List, Dict, Any, Tuple, Literal, get_args
6
6
 
7
7
  from versionhq._utils import convert_img_url
8
8
  from versionhq.tool.gpt import openai_client
9
- from versionhq.tool.gpt._enum import GPTCUABrowserEnum, GPTCUATypeEnum, GPTSizeEnum
9
+ from versionhq.tool.gpt._enum import GPTSizeEnum
10
10
  from versionhq._utils import is_valid_enum, UsageMetrics, ErrorType, Logger, is_valid_url, handle_directory
11
11
 
12
- allowed_browsers = ['chromium', 'firefox']
13
-
12
+ BROWSER = Literal['chromium', 'firefox']
13
+ TYPE = Literal["computer_call_output", "computer_use_preview"]
14
+ ENV = Literal["browser", "mac", "windows", "ubuntu"]
14
15
 
15
16
  class CUAToolSchema:
16
- type: str = GPTCUATypeEnum.COMPUTER_USE_PREVIEW.value
17
+ type: TYPE = "computer_use_preview"
18
+ environment: ENV = "browser"
17
19
  display_width: int = 1024
18
20
  display_height: int = 768
19
- environment: str = GPTCUABrowserEnum.BROWSER.value
20
21
 
21
- def __init__(
22
- self,
23
- type: str | GPTCUATypeEnum = None,
24
- display_width: int = None,
25
- display_height: int = None,
26
- environment: str | GPTCUABrowserEnum = None
27
- ):
22
+ def __init__(self, type: str = None, display_width: int = None, display_height: int = None, environment: str = None):
28
23
  self.display_height = display_height if display_height else self.display_height
29
24
  self.display_width = display_width if display_width else self.display_width
30
25
 
31
- if type and is_valid_enum(enum=GPTCUATypeEnum, val=type):
32
- self.type = type.value if isinstance(type, GPTCUATypeEnum) else type
26
+ if type and type in get_args(TYPE):
27
+ self.type = type
33
28
 
34
- if environment and is_valid_enum(enum=GPTCUABrowserEnum, val=environment):
35
- self.environment = environment.value if isinstance(environment, GPTCUABrowserEnum) else environment
29
+ if environment and environment in get_args(ENV):
30
+ self.environment = environment
36
31
 
37
32
  @property
38
33
  def schema(self) -> Dict[str, Any]:
@@ -50,7 +45,7 @@ class GPTToolCUA:
50
45
  user_prompt: str = None
51
46
  img_url: str = None
52
47
  web_url: str = "https://www.google.com"
53
- browser: str = "firefox"
48
+ browser: BROWSER = "firefox"
54
49
  reasoning_effort: str = GPTSizeEnum.MEDIUM.value
55
50
  truncation: str = "auto"
56
51
 
@@ -75,7 +70,7 @@ class GPTToolCUA:
75
70
  ):
76
71
  self.user_prompt = user_prompt
77
72
  self.web_url = web_url if is_valid_url(web_url) else None
78
- self.browser = browser if browser in allowed_browsers else 'chromium'
73
+ self.browser = browser if browser in get_args(BROWSER) else 'chromium'
79
74
  self.truncation = truncation if truncation else self.truncation
80
75
  self._usage = _usage
81
76
  self._response_ids = list()
@@ -421,8 +416,6 @@ class GPTToolCUA:
421
416
  else:
422
417
  res, _, usage = self._run()
423
418
 
424
- print("res", res)
425
-
426
419
  self._usage.aggregate(metrics=usage)
427
420
  if not res:
428
421
  usage.record_errors(type=ErrorType.API)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: versionhq
3
- Version: 1.2.4.14
3
+ Version: 1.2.4.15
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
@@ -77,7 +77,7 @@ Provides-Extra: tools
77
77
  Requires-Dist: html2text>=2024.2.26; extra == "tools"
78
78
  Requires-Dist: sec-api>=1.0.28; extra == "tools"
79
79
  Requires-Dist: pytest-playwright>=0.7.0; extra == "tools"
80
- Requires-Dist: selenium>=4.29.0; extra == "tools"
80
+ Requires-Dist: selenium>=4.30.0; extra == "tools"
81
81
  Provides-Extra: torch
82
82
  Requires-Dist: torch>=2.6.0; extra == "torch"
83
83
  Requires-Dist: torchvision>=0.21.0; extra == "torch"
@@ -7,8 +7,9 @@ README.md
7
7
  SECURITY.md
8
8
  mkdocs.yml
9
9
  pyproject.toml
10
- requirements-dev.txt
11
10
  requirements.txt
11
+ requirements_dev.txt
12
+ requirements_tool.txt
12
13
  runtime.txt
13
14
  uv.lock
14
15
  .github/workflows/deploy_docs.yml
@@ -36,7 +36,7 @@ pygraphviz>=1.14
36
36
  html2text>=2024.2.26
37
37
  sec-api>=1.0.28
38
38
  pytest-playwright>=0.7.0
39
- selenium>=4.29.0
39
+ selenium>=4.30.0
40
40
 
41
41
  [torch]
42
42
  torch>=2.6.0
@@ -133,13 +133,13 @@ def _test_con_azure(simple_task, tool_task, schema_task, res_field_task):
133
133
  llms_to_test = [
134
134
  "azure/Phi-4-mini-instruct",
135
135
  "azure_ai/Phi-4-mini-instruct",
136
- "azure_ai/DeepSeek-V3"
136
+ "azure_ai/DeepSeek-V3",
137
137
  ]
138
138
  agents = [set_agent(llm=llm) for llm in llms_to_test]
139
139
 
140
140
  for agent in agents:
141
141
  assert isinstance(agent.llm, LLM)
142
- assert agent.llm.provider == "azure"
142
+ assert "azure" in agent.llm.provider
143
143
  assert agent.llm._init_model_name and agent.llm.provider and agent.llm.llm_config["max_tokens"] == agent.llm_config["max_tokens"]
144
144
 
145
145
  res_1 = simple_task.execute(agent=agent, context="running a test")
@@ -1,4 +1,4 @@
1
- from versionhq.llm.llm_vars import TEXT_MODELS, LLM_CONTEXT_WINDOW_SIZES
1
+ from versionhq.llm.llm_vars import MODELS, LLM_CONTEXT_WINDOW_SIZES
2
2
  from versionhq.llm.model import LLM, DEFAULT_CONTEXT_WINDOW_SIZE
3
3
 
4
4
 
@@ -11,7 +11,7 @@ def test_create_llm_from_valid_name():
11
11
  Make sure base params are set properly in the LLM class of all the models available in the framework.
12
12
  """
13
13
 
14
- for k, v in TEXT_MODELS.items():
14
+ for k, v in MODELS.items():
15
15
  for model_name in v:
16
16
  llm = LLM(model=model_name, callbacks=[dummy_func,])
17
17
 
@@ -188,3 +188,12 @@ def test_taskoutput_final_c():
188
188
 
189
189
  assert res.final == res.pydantic
190
190
  assert res._to_context_prompt() is not None
191
+
192
+
193
+ def test_multimodal():
194
+ import versionhq as vhq
195
+
196
+ agent = vhq.Agent(llm="azure/whisper", role="Transcripter")
197
+ task = vhq.Task(description="trasncript the audio", audio='tests/_sample/sample.mp3', is_multimodal=True)
198
+ res = task.execute(agent=agent)
199
+ assert res.raw is not None
@@ -83,7 +83,9 @@ def test_with_agent():
83
83
  agent.start(tool_res_as_final=True)
84
84
  mock_run.assert_called_once()
85
85
 
86
- with patch.object(Prompt, "format_core", return_value=("test", "test", ["test"])) as mock_prompt:
86
+
87
+ mock_value = ("test", "test", [{ "role": "assistant", "content": ""}])
88
+ with patch.object(Prompt, "format_core", return_value=mock_value) as mock_prompt:
87
89
  agent.start()
88
90
  mock_prompt.assert_called_once()
89
91
 
@@ -93,7 +95,7 @@ def test_with_agent():
93
95
  agent.start(tool_res_as_final=True)
94
96
  mock_run.assert_called_once()
95
97
 
96
- with patch.object(Prompt, "format_core", return_value=("test", "test", ["test"])) as mock_prompt:
98
+ with patch.object(Prompt, "format_core", return_value=mock_value) as mock_prompt:
97
99
  agent.start()
98
100
  mock_prompt.assert_called_once()
99
101
 
@@ -103,7 +105,7 @@ def test_with_agent():
103
105
  agent.start(tool_res_as_final=True)
104
106
  mock_run.assert_called_once()
105
107
 
106
- with patch.object(Prompt, "format_core", return_value=("test", "test", ["test"])) as mock_prompt:
108
+ with patch.object(Prompt, "format_core", return_value=mock_value) as mock_prompt:
107
109
  agent.start()
108
110
  mock_prompt.assert_called_once()
109
111
 
@@ -115,11 +117,13 @@ def test_with_task():
115
117
  tool_2 = vhq.GPTToolFileSearch(input="Search today's top news.", vector_store_ids="vs_dummy_id", max_num_results=5)
116
118
 
117
119
  task = vhq.Task(description="Test gpt tools", tools=[tool_1], tool_res_as_final=True)
120
+ mock_value = ("test", "test", [{ "role": "assistant", "content": ""}])
121
+
118
122
  with patch.object(vhq.Agent, "_handle_gpt_tools", return_value=(vhq.TaskOutput(raw="", usage=UsageMetrics()))) as mock_run:
119
123
  task.execute()
120
124
  mock_run.assert_called_once()
121
125
 
122
- with patch.object(Prompt, "format_core", return_value=("test", "test", ["test"])) as mock_prompt:
126
+ with patch.object(Prompt, "format_core", return_value=mock_value) as mock_prompt:
123
127
  task.tool_res_as_final = False
124
128
  task.execute()
125
129
  mock_prompt.assert_called_once()
@@ -130,7 +134,7 @@ def test_with_task():
130
134
  task.execute()
131
135
  mock_run.assert_called_once()
132
136
 
133
- with patch.object(Prompt, "format_core", return_value=("test", "test", ["test"])) as mock_prompt:
137
+ with patch.object(Prompt, "format_core", return_value=mock_value) as mock_prompt:
134
138
  task.tool_res_as_final = False
135
139
  task.execute()
136
140
  mock_prompt.assert_called_once()
@@ -141,7 +145,7 @@ def test_with_task():
141
145
  task.execute()
142
146
  mock_run.assert_called_once()
143
147
 
144
- with patch.object(Prompt, "format_core", return_value=("test", "test", ["test"])) as mock_prompt:
148
+ with patch.object(Prompt, "format_core", return_value=mock_value) as mock_prompt:
145
149
  task.tool_res_as_final = False
146
150
  task.execute()
147
151
  mock_prompt.assert_called_once()