aiqtoolkit 1.2.0rc3__py3-none-any.whl → 1.2.0rc5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiqtoolkit might be problematic. Click here for more details.

Files changed (440) hide show
  1. aiqtoolkit-1.2.0rc5.dist-info/METADATA +29 -0
  2. aiqtoolkit-1.2.0rc5.dist-info/RECORD +4 -0
  3. aiqtoolkit-1.2.0rc5.dist-info/top_level.txt +1 -0
  4. aiq/agent/__init__.py +0 -0
  5. aiq/agent/base.py +0 -239
  6. aiq/agent/dual_node.py +0 -67
  7. aiq/agent/react_agent/__init__.py +0 -0
  8. aiq/agent/react_agent/agent.py +0 -355
  9. aiq/agent/react_agent/output_parser.py +0 -104
  10. aiq/agent/react_agent/prompt.py +0 -41
  11. aiq/agent/react_agent/register.py +0 -149
  12. aiq/agent/reasoning_agent/__init__.py +0 -0
  13. aiq/agent/reasoning_agent/reasoning_agent.py +0 -225
  14. aiq/agent/register.py +0 -23
  15. aiq/agent/rewoo_agent/__init__.py +0 -0
  16. aiq/agent/rewoo_agent/agent.py +0 -411
  17. aiq/agent/rewoo_agent/prompt.py +0 -108
  18. aiq/agent/rewoo_agent/register.py +0 -158
  19. aiq/agent/tool_calling_agent/__init__.py +0 -0
  20. aiq/agent/tool_calling_agent/agent.py +0 -119
  21. aiq/agent/tool_calling_agent/register.py +0 -106
  22. aiq/authentication/__init__.py +0 -14
  23. aiq/authentication/api_key/__init__.py +0 -14
  24. aiq/authentication/api_key/api_key_auth_provider.py +0 -92
  25. aiq/authentication/api_key/api_key_auth_provider_config.py +0 -124
  26. aiq/authentication/api_key/register.py +0 -26
  27. aiq/authentication/exceptions/__init__.py +0 -14
  28. aiq/authentication/exceptions/api_key_exceptions.py +0 -38
  29. aiq/authentication/exceptions/auth_code_grant_exceptions.py +0 -86
  30. aiq/authentication/exceptions/call_back_exceptions.py +0 -38
  31. aiq/authentication/exceptions/request_exceptions.py +0 -54
  32. aiq/authentication/http_basic_auth/__init__.py +0 -0
  33. aiq/authentication/http_basic_auth/http_basic_auth_provider.py +0 -81
  34. aiq/authentication/http_basic_auth/register.py +0 -30
  35. aiq/authentication/interfaces.py +0 -93
  36. aiq/authentication/oauth2/__init__.py +0 -14
  37. aiq/authentication/oauth2/oauth2_auth_code_flow_provider.py +0 -107
  38. aiq/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +0 -39
  39. aiq/authentication/oauth2/register.py +0 -25
  40. aiq/authentication/register.py +0 -21
  41. aiq/builder/__init__.py +0 -0
  42. aiq/builder/builder.py +0 -285
  43. aiq/builder/component_utils.py +0 -316
  44. aiq/builder/context.py +0 -264
  45. aiq/builder/embedder.py +0 -24
  46. aiq/builder/eval_builder.py +0 -161
  47. aiq/builder/evaluator.py +0 -29
  48. aiq/builder/framework_enum.py +0 -24
  49. aiq/builder/front_end.py +0 -73
  50. aiq/builder/function.py +0 -344
  51. aiq/builder/function_base.py +0 -380
  52. aiq/builder/function_info.py +0 -627
  53. aiq/builder/intermediate_step_manager.py +0 -174
  54. aiq/builder/llm.py +0 -25
  55. aiq/builder/retriever.py +0 -25
  56. aiq/builder/user_interaction_manager.py +0 -74
  57. aiq/builder/workflow.py +0 -148
  58. aiq/builder/workflow_builder.py +0 -1117
  59. aiq/cli/__init__.py +0 -14
  60. aiq/cli/cli_utils/__init__.py +0 -0
  61. aiq/cli/cli_utils/config_override.py +0 -231
  62. aiq/cli/cli_utils/validation.py +0 -37
  63. aiq/cli/commands/__init__.py +0 -0
  64. aiq/cli/commands/configure/__init__.py +0 -0
  65. aiq/cli/commands/configure/channel/__init__.py +0 -0
  66. aiq/cli/commands/configure/channel/add.py +0 -28
  67. aiq/cli/commands/configure/channel/channel.py +0 -36
  68. aiq/cli/commands/configure/channel/remove.py +0 -30
  69. aiq/cli/commands/configure/channel/update.py +0 -30
  70. aiq/cli/commands/configure/configure.py +0 -33
  71. aiq/cli/commands/evaluate.py +0 -139
  72. aiq/cli/commands/info/__init__.py +0 -14
  73. aiq/cli/commands/info/info.py +0 -39
  74. aiq/cli/commands/info/list_channels.py +0 -32
  75. aiq/cli/commands/info/list_components.py +0 -129
  76. aiq/cli/commands/info/list_mcp.py +0 -213
  77. aiq/cli/commands/registry/__init__.py +0 -14
  78. aiq/cli/commands/registry/publish.py +0 -88
  79. aiq/cli/commands/registry/pull.py +0 -118
  80. aiq/cli/commands/registry/registry.py +0 -38
  81. aiq/cli/commands/registry/remove.py +0 -108
  82. aiq/cli/commands/registry/search.py +0 -155
  83. aiq/cli/commands/sizing/__init__.py +0 -14
  84. aiq/cli/commands/sizing/calc.py +0 -297
  85. aiq/cli/commands/sizing/sizing.py +0 -27
  86. aiq/cli/commands/start.py +0 -246
  87. aiq/cli/commands/uninstall.py +0 -81
  88. aiq/cli/commands/validate.py +0 -47
  89. aiq/cli/commands/workflow/__init__.py +0 -14
  90. aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
  91. aiq/cli/commands/workflow/templates/config.yml.j2 +0 -16
  92. aiq/cli/commands/workflow/templates/pyproject.toml.j2 +0 -22
  93. aiq/cli/commands/workflow/templates/register.py.j2 +0 -5
  94. aiq/cli/commands/workflow/templates/workflow.py.j2 +0 -36
  95. aiq/cli/commands/workflow/workflow.py +0 -37
  96. aiq/cli/commands/workflow/workflow_commands.py +0 -313
  97. aiq/cli/entrypoint.py +0 -135
  98. aiq/cli/main.py +0 -44
  99. aiq/cli/register_workflow.py +0 -488
  100. aiq/cli/type_registry.py +0 -1000
  101. aiq/data_models/__init__.py +0 -14
  102. aiq/data_models/api_server.py +0 -694
  103. aiq/data_models/authentication.py +0 -231
  104. aiq/data_models/common.py +0 -171
  105. aiq/data_models/component.py +0 -54
  106. aiq/data_models/component_ref.py +0 -168
  107. aiq/data_models/config.py +0 -406
  108. aiq/data_models/dataset_handler.py +0 -123
  109. aiq/data_models/discovery_metadata.py +0 -286
  110. aiq/data_models/embedder.py +0 -27
  111. aiq/data_models/evaluate.py +0 -127
  112. aiq/data_models/evaluator.py +0 -26
  113. aiq/data_models/front_end.py +0 -26
  114. aiq/data_models/function.py +0 -30
  115. aiq/data_models/function_dependencies.py +0 -72
  116. aiq/data_models/interactive.py +0 -246
  117. aiq/data_models/intermediate_step.py +0 -302
  118. aiq/data_models/invocation_node.py +0 -38
  119. aiq/data_models/its_strategy.py +0 -30
  120. aiq/data_models/llm.py +0 -27
  121. aiq/data_models/logging.py +0 -26
  122. aiq/data_models/memory.py +0 -27
  123. aiq/data_models/object_store.py +0 -44
  124. aiq/data_models/profiler.py +0 -54
  125. aiq/data_models/registry_handler.py +0 -26
  126. aiq/data_models/retriever.py +0 -30
  127. aiq/data_models/retry_mixin.py +0 -35
  128. aiq/data_models/span.py +0 -187
  129. aiq/data_models/step_adaptor.py +0 -64
  130. aiq/data_models/streaming.py +0 -33
  131. aiq/data_models/swe_bench_model.py +0 -54
  132. aiq/data_models/telemetry_exporter.py +0 -26
  133. aiq/embedder/__init__.py +0 -0
  134. aiq/embedder/langchain_client.py +0 -41
  135. aiq/embedder/nim_embedder.py +0 -59
  136. aiq/embedder/openai_embedder.py +0 -43
  137. aiq/embedder/register.py +0 -24
  138. aiq/eval/__init__.py +0 -14
  139. aiq/eval/config.py +0 -60
  140. aiq/eval/dataset_handler/__init__.py +0 -0
  141. aiq/eval/dataset_handler/dataset_downloader.py +0 -106
  142. aiq/eval/dataset_handler/dataset_filter.py +0 -52
  143. aiq/eval/dataset_handler/dataset_handler.py +0 -254
  144. aiq/eval/evaluate.py +0 -506
  145. aiq/eval/evaluator/__init__.py +0 -14
  146. aiq/eval/evaluator/base_evaluator.py +0 -73
  147. aiq/eval/evaluator/evaluator_model.py +0 -45
  148. aiq/eval/intermediate_step_adapter.py +0 -99
  149. aiq/eval/rag_evaluator/__init__.py +0 -0
  150. aiq/eval/rag_evaluator/evaluate.py +0 -178
  151. aiq/eval/rag_evaluator/register.py +0 -143
  152. aiq/eval/register.py +0 -23
  153. aiq/eval/remote_workflow.py +0 -133
  154. aiq/eval/runners/__init__.py +0 -14
  155. aiq/eval/runners/config.py +0 -39
  156. aiq/eval/runners/multi_eval_runner.py +0 -54
  157. aiq/eval/runtime_event_subscriber.py +0 -52
  158. aiq/eval/swe_bench_evaluator/__init__.py +0 -0
  159. aiq/eval/swe_bench_evaluator/evaluate.py +0 -215
  160. aiq/eval/swe_bench_evaluator/register.py +0 -36
  161. aiq/eval/trajectory_evaluator/__init__.py +0 -0
  162. aiq/eval/trajectory_evaluator/evaluate.py +0 -75
  163. aiq/eval/trajectory_evaluator/register.py +0 -40
  164. aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
  165. aiq/eval/tunable_rag_evaluator/evaluate.py +0 -245
  166. aiq/eval/tunable_rag_evaluator/register.py +0 -52
  167. aiq/eval/usage_stats.py +0 -41
  168. aiq/eval/utils/__init__.py +0 -0
  169. aiq/eval/utils/output_uploader.py +0 -140
  170. aiq/eval/utils/tqdm_position_registry.py +0 -40
  171. aiq/eval/utils/weave_eval.py +0 -184
  172. aiq/experimental/__init__.py +0 -0
  173. aiq/experimental/decorators/__init__.py +0 -0
  174. aiq/experimental/decorators/experimental_warning_decorator.py +0 -130
  175. aiq/experimental/inference_time_scaling/__init__.py +0 -0
  176. aiq/experimental/inference_time_scaling/editing/__init__.py +0 -0
  177. aiq/experimental/inference_time_scaling/editing/iterative_plan_refinement_editor.py +0 -147
  178. aiq/experimental/inference_time_scaling/editing/llm_as_a_judge_editor.py +0 -204
  179. aiq/experimental/inference_time_scaling/editing/motivation_aware_summarization.py +0 -107
  180. aiq/experimental/inference_time_scaling/functions/__init__.py +0 -0
  181. aiq/experimental/inference_time_scaling/functions/execute_score_select_function.py +0 -105
  182. aiq/experimental/inference_time_scaling/functions/its_tool_orchestration_function.py +0 -205
  183. aiq/experimental/inference_time_scaling/functions/its_tool_wrapper_function.py +0 -146
  184. aiq/experimental/inference_time_scaling/functions/plan_select_execute_function.py +0 -224
  185. aiq/experimental/inference_time_scaling/models/__init__.py +0 -0
  186. aiq/experimental/inference_time_scaling/models/editor_config.py +0 -132
  187. aiq/experimental/inference_time_scaling/models/its_item.py +0 -48
  188. aiq/experimental/inference_time_scaling/models/scoring_config.py +0 -112
  189. aiq/experimental/inference_time_scaling/models/search_config.py +0 -120
  190. aiq/experimental/inference_time_scaling/models/selection_config.py +0 -154
  191. aiq/experimental/inference_time_scaling/models/stage_enums.py +0 -43
  192. aiq/experimental/inference_time_scaling/models/strategy_base.py +0 -66
  193. aiq/experimental/inference_time_scaling/models/tool_use_config.py +0 -41
  194. aiq/experimental/inference_time_scaling/register.py +0 -36
  195. aiq/experimental/inference_time_scaling/scoring/__init__.py +0 -0
  196. aiq/experimental/inference_time_scaling/scoring/llm_based_agent_scorer.py +0 -168
  197. aiq/experimental/inference_time_scaling/scoring/llm_based_plan_scorer.py +0 -168
  198. aiq/experimental/inference_time_scaling/scoring/motivation_aware_scorer.py +0 -111
  199. aiq/experimental/inference_time_scaling/search/__init__.py +0 -0
  200. aiq/experimental/inference_time_scaling/search/multi_llm_planner.py +0 -128
  201. aiq/experimental/inference_time_scaling/search/multi_query_retrieval_search.py +0 -122
  202. aiq/experimental/inference_time_scaling/search/single_shot_multi_plan_planner.py +0 -128
  203. aiq/experimental/inference_time_scaling/selection/__init__.py +0 -0
  204. aiq/experimental/inference_time_scaling/selection/best_of_n_selector.py +0 -63
  205. aiq/experimental/inference_time_scaling/selection/llm_based_agent_output_selector.py +0 -131
  206. aiq/experimental/inference_time_scaling/selection/llm_based_output_merging_selector.py +0 -159
  207. aiq/experimental/inference_time_scaling/selection/llm_based_plan_selector.py +0 -128
  208. aiq/experimental/inference_time_scaling/selection/threshold_selector.py +0 -58
  209. aiq/front_ends/__init__.py +0 -14
  210. aiq/front_ends/console/__init__.py +0 -14
  211. aiq/front_ends/console/authentication_flow_handler.py +0 -233
  212. aiq/front_ends/console/console_front_end_config.py +0 -32
  213. aiq/front_ends/console/console_front_end_plugin.py +0 -96
  214. aiq/front_ends/console/register.py +0 -25
  215. aiq/front_ends/cron/__init__.py +0 -14
  216. aiq/front_ends/fastapi/__init__.py +0 -14
  217. aiq/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
  218. aiq/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +0 -27
  219. aiq/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +0 -107
  220. aiq/front_ends/fastapi/fastapi_front_end_config.py +0 -234
  221. aiq/front_ends/fastapi/fastapi_front_end_controller.py +0 -68
  222. aiq/front_ends/fastapi/fastapi_front_end_plugin.py +0 -116
  223. aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +0 -1092
  224. aiq/front_ends/fastapi/html_snippets/__init__.py +0 -14
  225. aiq/front_ends/fastapi/html_snippets/auth_code_grant_success.py +0 -35
  226. aiq/front_ends/fastapi/intermediate_steps_subscriber.py +0 -80
  227. aiq/front_ends/fastapi/job_store.py +0 -183
  228. aiq/front_ends/fastapi/main.py +0 -72
  229. aiq/front_ends/fastapi/message_handler.py +0 -298
  230. aiq/front_ends/fastapi/message_validator.py +0 -345
  231. aiq/front_ends/fastapi/register.py +0 -25
  232. aiq/front_ends/fastapi/response_helpers.py +0 -195
  233. aiq/front_ends/fastapi/step_adaptor.py +0 -321
  234. aiq/front_ends/mcp/__init__.py +0 -14
  235. aiq/front_ends/mcp/mcp_front_end_config.py +0 -32
  236. aiq/front_ends/mcp/mcp_front_end_plugin.py +0 -93
  237. aiq/front_ends/mcp/register.py +0 -27
  238. aiq/front_ends/mcp/tool_converter.py +0 -242
  239. aiq/front_ends/register.py +0 -22
  240. aiq/front_ends/simple_base/__init__.py +0 -14
  241. aiq/front_ends/simple_base/simple_front_end_plugin_base.py +0 -54
  242. aiq/llm/__init__.py +0 -0
  243. aiq/llm/aws_bedrock_llm.py +0 -57
  244. aiq/llm/nim_llm.py +0 -46
  245. aiq/llm/openai_llm.py +0 -46
  246. aiq/llm/register.py +0 -23
  247. aiq/llm/utils/__init__.py +0 -14
  248. aiq/llm/utils/env_config_value.py +0 -94
  249. aiq/llm/utils/error.py +0 -17
  250. aiq/memory/__init__.py +0 -20
  251. aiq/memory/interfaces.py +0 -183
  252. aiq/memory/models.py +0 -112
  253. aiq/meta/module_to_distro.json +0 -3
  254. aiq/meta/pypi.md +0 -58
  255. aiq/object_store/__init__.py +0 -20
  256. aiq/object_store/in_memory_object_store.py +0 -74
  257. aiq/object_store/interfaces.py +0 -84
  258. aiq/object_store/models.py +0 -36
  259. aiq/object_store/register.py +0 -20
  260. aiq/observability/__init__.py +0 -14
  261. aiq/observability/exporter/__init__.py +0 -14
  262. aiq/observability/exporter/base_exporter.py +0 -449
  263. aiq/observability/exporter/exporter.py +0 -78
  264. aiq/observability/exporter/file_exporter.py +0 -33
  265. aiq/observability/exporter/processing_exporter.py +0 -322
  266. aiq/observability/exporter/raw_exporter.py +0 -52
  267. aiq/observability/exporter/span_exporter.py +0 -265
  268. aiq/observability/exporter_manager.py +0 -335
  269. aiq/observability/mixin/__init__.py +0 -14
  270. aiq/observability/mixin/batch_config_mixin.py +0 -26
  271. aiq/observability/mixin/collector_config_mixin.py +0 -23
  272. aiq/observability/mixin/file_mixin.py +0 -288
  273. aiq/observability/mixin/file_mode.py +0 -23
  274. aiq/observability/mixin/resource_conflict_mixin.py +0 -134
  275. aiq/observability/mixin/serialize_mixin.py +0 -61
  276. aiq/observability/mixin/type_introspection_mixin.py +0 -183
  277. aiq/observability/processor/__init__.py +0 -14
  278. aiq/observability/processor/batching_processor.py +0 -309
  279. aiq/observability/processor/callback_processor.py +0 -42
  280. aiq/observability/processor/intermediate_step_serializer.py +0 -28
  281. aiq/observability/processor/processor.py +0 -71
  282. aiq/observability/register.py +0 -96
  283. aiq/observability/utils/__init__.py +0 -14
  284. aiq/observability/utils/dict_utils.py +0 -236
  285. aiq/observability/utils/time_utils.py +0 -31
  286. aiq/plugins/.namespace +0 -1
  287. aiq/profiler/__init__.py +0 -0
  288. aiq/profiler/calc/__init__.py +0 -14
  289. aiq/profiler/calc/calc_runner.py +0 -627
  290. aiq/profiler/calc/calculations.py +0 -288
  291. aiq/profiler/calc/data_models.py +0 -188
  292. aiq/profiler/calc/plot.py +0 -345
  293. aiq/profiler/callbacks/__init__.py +0 -0
  294. aiq/profiler/callbacks/agno_callback_handler.py +0 -295
  295. aiq/profiler/callbacks/base_callback_class.py +0 -20
  296. aiq/profiler/callbacks/langchain_callback_handler.py +0 -290
  297. aiq/profiler/callbacks/llama_index_callback_handler.py +0 -205
  298. aiq/profiler/callbacks/semantic_kernel_callback_handler.py +0 -238
  299. aiq/profiler/callbacks/token_usage_base_model.py +0 -27
  300. aiq/profiler/data_frame_row.py +0 -51
  301. aiq/profiler/data_models.py +0 -24
  302. aiq/profiler/decorators/__init__.py +0 -0
  303. aiq/profiler/decorators/framework_wrapper.py +0 -131
  304. aiq/profiler/decorators/function_tracking.py +0 -254
  305. aiq/profiler/forecasting/__init__.py +0 -0
  306. aiq/profiler/forecasting/config.py +0 -18
  307. aiq/profiler/forecasting/model_trainer.py +0 -75
  308. aiq/profiler/forecasting/models/__init__.py +0 -22
  309. aiq/profiler/forecasting/models/forecasting_base_model.py +0 -40
  310. aiq/profiler/forecasting/models/linear_model.py +0 -196
  311. aiq/profiler/forecasting/models/random_forest_regressor.py +0 -268
  312. aiq/profiler/inference_metrics_model.py +0 -28
  313. aiq/profiler/inference_optimization/__init__.py +0 -0
  314. aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
  315. aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +0 -460
  316. aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +0 -258
  317. aiq/profiler/inference_optimization/data_models.py +0 -386
  318. aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
  319. aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +0 -468
  320. aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +0 -405
  321. aiq/profiler/inference_optimization/llm_metrics.py +0 -212
  322. aiq/profiler/inference_optimization/prompt_caching.py +0 -163
  323. aiq/profiler/inference_optimization/token_uniqueness.py +0 -107
  324. aiq/profiler/inference_optimization/workflow_runtimes.py +0 -72
  325. aiq/profiler/intermediate_property_adapter.py +0 -102
  326. aiq/profiler/profile_runner.py +0 -473
  327. aiq/profiler/utils.py +0 -184
  328. aiq/registry_handlers/__init__.py +0 -0
  329. aiq/registry_handlers/local/__init__.py +0 -0
  330. aiq/registry_handlers/local/local_handler.py +0 -176
  331. aiq/registry_handlers/local/register_local.py +0 -37
  332. aiq/registry_handlers/metadata_factory.py +0 -60
  333. aiq/registry_handlers/package_utils.py +0 -198
  334. aiq/registry_handlers/pypi/__init__.py +0 -0
  335. aiq/registry_handlers/pypi/pypi_handler.py +0 -251
  336. aiq/registry_handlers/pypi/register_pypi.py +0 -40
  337. aiq/registry_handlers/register.py +0 -21
  338. aiq/registry_handlers/registry_handler_base.py +0 -157
  339. aiq/registry_handlers/rest/__init__.py +0 -0
  340. aiq/registry_handlers/rest/register_rest.py +0 -56
  341. aiq/registry_handlers/rest/rest_handler.py +0 -237
  342. aiq/registry_handlers/schemas/__init__.py +0 -0
  343. aiq/registry_handlers/schemas/headers.py +0 -42
  344. aiq/registry_handlers/schemas/package.py +0 -68
  345. aiq/registry_handlers/schemas/publish.py +0 -63
  346. aiq/registry_handlers/schemas/pull.py +0 -82
  347. aiq/registry_handlers/schemas/remove.py +0 -36
  348. aiq/registry_handlers/schemas/search.py +0 -91
  349. aiq/registry_handlers/schemas/status.py +0 -47
  350. aiq/retriever/__init__.py +0 -0
  351. aiq/retriever/interface.py +0 -37
  352. aiq/retriever/milvus/__init__.py +0 -14
  353. aiq/retriever/milvus/register.py +0 -81
  354. aiq/retriever/milvus/retriever.py +0 -228
  355. aiq/retriever/models.py +0 -74
  356. aiq/retriever/nemo_retriever/__init__.py +0 -14
  357. aiq/retriever/nemo_retriever/register.py +0 -60
  358. aiq/retriever/nemo_retriever/retriever.py +0 -190
  359. aiq/retriever/register.py +0 -22
  360. aiq/runtime/__init__.py +0 -14
  361. aiq/runtime/loader.py +0 -194
  362. aiq/runtime/runner.py +0 -190
  363. aiq/runtime/session.py +0 -158
  364. aiq/runtime/user_metadata.py +0 -130
  365. aiq/settings/__init__.py +0 -0
  366. aiq/settings/global_settings.py +0 -318
  367. aiq/test/.namespace +0 -1
  368. aiq/tool/__init__.py +0 -0
  369. aiq/tool/chat_completion.py +0 -74
  370. aiq/tool/code_execution/README.md +0 -152
  371. aiq/tool/code_execution/__init__.py +0 -0
  372. aiq/tool/code_execution/code_sandbox.py +0 -267
  373. aiq/tool/code_execution/local_sandbox/.gitignore +0 -1
  374. aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +0 -60
  375. aiq/tool/code_execution/local_sandbox/__init__.py +0 -13
  376. aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +0 -198
  377. aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +0 -6
  378. aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +0 -50
  379. aiq/tool/code_execution/register.py +0 -74
  380. aiq/tool/code_execution/test_code_execution_sandbox.py +0 -414
  381. aiq/tool/code_execution/utils.py +0 -100
  382. aiq/tool/datetime_tools.py +0 -42
  383. aiq/tool/document_search.py +0 -141
  384. aiq/tool/github_tools/__init__.py +0 -0
  385. aiq/tool/github_tools/create_github_commit.py +0 -133
  386. aiq/tool/github_tools/create_github_issue.py +0 -87
  387. aiq/tool/github_tools/create_github_pr.py +0 -106
  388. aiq/tool/github_tools/get_github_file.py +0 -106
  389. aiq/tool/github_tools/get_github_issue.py +0 -166
  390. aiq/tool/github_tools/get_github_pr.py +0 -256
  391. aiq/tool/github_tools/update_github_issue.py +0 -100
  392. aiq/tool/mcp/__init__.py +0 -14
  393. aiq/tool/mcp/exceptions.py +0 -142
  394. aiq/tool/mcp/mcp_client.py +0 -255
  395. aiq/tool/mcp/mcp_tool.py +0 -96
  396. aiq/tool/memory_tools/__init__.py +0 -0
  397. aiq/tool/memory_tools/add_memory_tool.py +0 -79
  398. aiq/tool/memory_tools/delete_memory_tool.py +0 -67
  399. aiq/tool/memory_tools/get_memory_tool.py +0 -72
  400. aiq/tool/nvidia_rag.py +0 -95
  401. aiq/tool/register.py +0 -38
  402. aiq/tool/retriever.py +0 -89
  403. aiq/tool/server_tools.py +0 -66
  404. aiq/utils/__init__.py +0 -0
  405. aiq/utils/data_models/__init__.py +0 -0
  406. aiq/utils/data_models/schema_validator.py +0 -58
  407. aiq/utils/debugging_utils.py +0 -43
  408. aiq/utils/exception_handlers/__init__.py +0 -0
  409. aiq/utils/exception_handlers/automatic_retries.py +0 -289
  410. aiq/utils/exception_handlers/mcp.py +0 -211
  411. aiq/utils/exception_handlers/schemas.py +0 -114
  412. aiq/utils/io/__init__.py +0 -0
  413. aiq/utils/io/model_processing.py +0 -28
  414. aiq/utils/io/yaml_tools.py +0 -119
  415. aiq/utils/log_utils.py +0 -37
  416. aiq/utils/metadata_utils.py +0 -74
  417. aiq/utils/optional_imports.py +0 -142
  418. aiq/utils/producer_consumer_queue.py +0 -178
  419. aiq/utils/reactive/__init__.py +0 -0
  420. aiq/utils/reactive/base/__init__.py +0 -0
  421. aiq/utils/reactive/base/observable_base.py +0 -65
  422. aiq/utils/reactive/base/observer_base.py +0 -55
  423. aiq/utils/reactive/base/subject_base.py +0 -79
  424. aiq/utils/reactive/observable.py +0 -59
  425. aiq/utils/reactive/observer.py +0 -76
  426. aiq/utils/reactive/subject.py +0 -131
  427. aiq/utils/reactive/subscription.py +0 -49
  428. aiq/utils/settings/__init__.py +0 -0
  429. aiq/utils/settings/global_settings.py +0 -197
  430. aiq/utils/string_utils.py +0 -38
  431. aiq/utils/type_converter.py +0 -290
  432. aiq/utils/type_utils.py +0 -484
  433. aiq/utils/url_utils.py +0 -27
  434. aiqtoolkit-1.2.0rc3.dist-info/METADATA +0 -363
  435. aiqtoolkit-1.2.0rc3.dist-info/RECORD +0 -437
  436. aiqtoolkit-1.2.0rc3.dist-info/entry_points.txt +0 -20
  437. aiqtoolkit-1.2.0rc3.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
  438. aiqtoolkit-1.2.0rc3.dist-info/licenses/LICENSE.md +0 -201
  439. aiqtoolkit-1.2.0rc3.dist-info/top_level.txt +0 -1
  440. {aiqtoolkit-1.2.0rc3.dist-info → aiqtoolkit-1.2.0rc5.dist-info}/WHEEL +0 -0
@@ -1,225 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- import logging
17
- import re
18
- from collections.abc import AsyncGenerator
19
-
20
- from pydantic import Field
21
-
22
- from aiq.builder.builder import Builder
23
- from aiq.builder.framework_enum import LLMFrameworkEnum
24
- from aiq.builder.function_info import FunctionInfo
25
- from aiq.cli.register_workflow import register_function
26
- from aiq.data_models.api_server import AIQChatRequest
27
- from aiq.data_models.component_ref import FunctionRef
28
- from aiq.data_models.component_ref import LLMRef
29
- from aiq.data_models.function import FunctionBaseConfig
30
-
31
- logger = logging.getLogger(__name__)
32
-
33
-
34
- class ReasoningFunctionConfig(FunctionBaseConfig, name="reasoning_agent"):
35
- """
36
- Defines an AIQ Toolkit function that performs reasoning on the input data.
37
- Output is passed to the next function in the workflow.
38
-
39
- Designed to be used with an InterceptingFunction.
40
- """
41
-
42
- llm_name: LLMRef = Field(description="The name of the LLM to use for reasoning.")
43
- augmented_fn: FunctionRef = Field(description="The name of the function to reason on.")
44
- verbose: bool = Field(default=False, description="Whether to log detailed information.")
45
- reasoning_prompt_template: str = Field(
46
- default=("You are an expert reasoning model task with creating a detailed execution plan"
47
- " for a system that has the following description:\n\n"
48
- "**Description:** \n{augmented_function_desc}\n\n"
49
- "Given the following input and a list of available tools, please provide a detailed step-by-step plan"
50
- " that an instruction following system can use to address the input. Ensure the plan includes:\n\n"
51
- "1. Identifying the key components of the input.\n"
52
- "2. Determining the most suitable tools for each task.\n"
53
- "3. Outlining the sequence of actions to be taken.\n\n"
54
- "**Input:** \n{input_text}\n\n"
55
- "**Tools and description of the tool:** \n{tools}\n\n"
56
- "An example plan could look like this:\n\n"
57
- "1. Call tool A with input X\n"
58
- "2. Call tool B with input Y\n"
59
- "3. Interpret the output of tool A and B\n"
60
- "4. Return the final result"
61
- "\n\n **PLAN:**\n"),
62
- description="The reasoning model prompt template.")
63
-
64
- instruction_prompt_template: str = Field(
65
- default=("Answer the following question based on message history: {input_text}"
66
- "\n\nHere is a plan for execution that you could use to guide you if you wanted to:"
67
- "\n\n{reasoning_output}"
68
- "\n\nNOTE: Remember to follow your guidance on how to format output, etc."
69
- "\n\n You must respond with the answer to the original question directly to the user."),
70
- description="The instruction prompt template.")
71
-
72
-
73
- @register_function(config_type=ReasoningFunctionConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN])
74
- async def build_reasoning_function(config: ReasoningFunctionConfig, builder: Builder):
75
- """
76
- Build a ReasoningFunction from the provided config.
77
-
78
- Args:
79
- config (ReasoningFunctionConfig): The config for the ReasoningFunction.
80
- builder (Builder): The Builder instance to use for building the function.
81
-
82
- Returns:
83
- ReasoningFunction: The built ReasoningFunction.
84
- """
85
- from langchain_core.language_models import BaseChatModel
86
- from langchain_core.prompts import PromptTemplate
87
-
88
- from aiq.agent.base import AGENT_LOG_PREFIX
89
-
90
- def remove_r1_think_tags(text: str):
91
- pattern = r'(<think>)?.*?</think>\s*(.*)'
92
-
93
- # Add re.DOTALL flag to make . match newlines
94
- match = re.match(pattern, text, re.DOTALL)
95
-
96
- if match:
97
- return match.group(2)
98
-
99
- return text
100
-
101
- # Get the LLM to use for reasoning
102
- llm: BaseChatModel = await builder.get_llm(config.llm_name, wrapper_type=LLMFrameworkEnum.LANGCHAIN)
103
-
104
- # Get the augmented function's description
105
- augmented_function = builder.get_function(config.augmented_fn)
106
-
107
- # For now, we rely on runtime checking for type conversion
108
-
109
- if augmented_function.description and augmented_function.description != "":
110
- augmented_function_desc = augmented_function.description
111
- else:
112
- raise ValueError(f"Function {config.augmented_fn} does not have a description. Cannot augment "
113
- f"function without a description.")
114
-
115
- # Get the function dependencies of the augmented function
116
- function_used_tools = builder.get_function_dependencies(config.augmented_fn).functions
117
- tool_names_with_desc: list[tuple[str, str]] = []
118
-
119
- for tool in function_used_tools:
120
- tool_impl = builder.get_function(tool)
121
- tool_names_with_desc.append((tool, tool_impl.description if hasattr(tool_impl, "description") else ""))
122
-
123
- # Draft the reasoning prompt for the augmented function
124
- template = PromptTemplate(template=config.reasoning_prompt_template,
125
- input_variables=["augmented_function_desc", "input_text", "tools"],
126
- validate_template=True)
127
-
128
- downstream_template = PromptTemplate(template=config.instruction_prompt_template,
129
- input_variables=["input_text", "reasoning_output"],
130
- validate_template=True)
131
-
132
- streaming_inner_fn = None
133
- single_inner_fn = None
134
-
135
- if augmented_function.has_streaming_output:
136
-
137
- async def streaming_inner(
138
- input_message: AIQChatRequest) -> AsyncGenerator[augmented_function.streaming_output_type]:
139
- """
140
- Perform reasoning on the input text.
141
-
142
- Args:
143
- input_message (AIQChatRequest): The input text to reason on.
144
- """
145
-
146
- input_text = "".join([str(message.model_dump()) + "\n" for message in input_message.messages])
147
-
148
- prompt = await template.ainvoke(
149
- input={
150
- "augmented_function_desc": augmented_function_desc,
151
- "input_text": input_text,
152
- "tools": "\n".join([f"- {tool[0]}: {tool[1]}" for tool in tool_names_with_desc])
153
- })
154
-
155
- prompt = prompt.to_string()
156
-
157
- # Get the reasoning output from the LLM
158
- reasoning_output = ""
159
-
160
- async for chunk in llm.astream(prompt):
161
- reasoning_output += chunk.content
162
-
163
- reasoning_output = remove_r1_think_tags(reasoning_output)
164
-
165
- output = await downstream_template.ainvoke(input={
166
- "input_text": input_text, "reasoning_output": reasoning_output
167
- })
168
-
169
- output = output.to_string()
170
-
171
- if config.verbose:
172
- logger.info("%s Reasoning plan and input to agent: \n\n%s", AGENT_LOG_PREFIX, output)
173
-
174
- async for chunk in augmented_function.acall_stream(output):
175
- yield chunk
176
-
177
- streaming_inner_fn = streaming_inner
178
-
179
- if augmented_function.has_single_output:
180
-
181
- async def single_inner(input_message: AIQChatRequest) -> augmented_function.single_output_type:
182
- """
183
- Perform reasoning on the input text.
184
-
185
- Args:
186
- input_message (AIQChatRequest): The input text to reason on.
187
- """
188
-
189
- input_text = "".join([str(message.model_dump()) + "\n" for message in input_message.messages])
190
-
191
- prompt = await template.ainvoke(
192
- input={
193
- "augmented_function_desc": augmented_function_desc,
194
- "input_text": input_text,
195
- "tools": "\n".join([f"- {tool[0]}: {tool[1]}" for tool in tool_names_with_desc])
196
- })
197
-
198
- prompt = prompt.to_string()
199
-
200
- # Get the reasoning output from the LLM
201
- reasoning_output = ""
202
-
203
- async for chunk in llm.astream(prompt):
204
- reasoning_output += chunk.content
205
-
206
- reasoning_output = remove_r1_think_tags(reasoning_output)
207
-
208
- output = await downstream_template.ainvoke(input={
209
- "input_text": input_text, "reasoning_output": reasoning_output
210
- })
211
-
212
- output = output.to_string()
213
-
214
- if config.verbose:
215
- logger.info("%s Reasoning plan and input to agent: \n\n%s", AGENT_LOG_PREFIX, output)
216
-
217
- return await augmented_function.acall_invoke(output)
218
-
219
- single_inner_fn = single_inner
220
-
221
- yield FunctionInfo.create(
222
- single_fn=single_inner_fn,
223
- stream_fn=streaming_inner_fn,
224
- description=("Reasoning function that generates a detailed execution plan for a system based on the input."),
225
- converters=augmented_function.converter_list)
aiq/agent/register.py DELETED
@@ -1,23 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- # pylint: disable=unused-import
17
- # flake8: noqa
18
-
19
- # Import any workflows which need to be automatically registered here
20
- from .react_agent import register as react_agent
21
- from .reasoning_agent import reasoning_agent
22
- from .rewoo_agent import register as rewoo_agent
23
- from .tool_calling_agent import register as tool_calling_agent
File without changes
@@ -1,411 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- import json
17
- # pylint: disable=R0917
18
- import logging
19
- from json import JSONDecodeError
20
-
21
- from langchain_core.callbacks.base import AsyncCallbackHandler
22
- from langchain_core.language_models import BaseChatModel
23
- from langchain_core.messages.ai import AIMessage
24
- from langchain_core.messages.human import HumanMessage
25
- from langchain_core.messages.tool import ToolMessage
26
- from langchain_core.prompts.chat import ChatPromptTemplate
27
- from langchain_core.runnables.config import RunnableConfig
28
- from langchain_core.tools import BaseTool
29
- from langgraph.graph import StateGraph
30
- from pydantic import BaseModel
31
- from pydantic import Field
32
-
33
- from aiq.agent.base import AGENT_CALL_LOG_MESSAGE
34
- from aiq.agent.base import AGENT_LOG_PREFIX
35
- from aiq.agent.base import INPUT_SCHEMA_MESSAGE
36
- from aiq.agent.base import NO_INPUT_ERROR_MESSAGE
37
- from aiq.agent.base import TOOL_NOT_FOUND_ERROR_MESSAGE
38
- from aiq.agent.base import AgentDecision
39
- from aiq.agent.base import BaseAgent
40
-
41
- logger = logging.getLogger(__name__)
42
-
43
-
44
- class ReWOOGraphState(BaseModel):
45
- """State schema for the ReWOO Agent Graph"""
46
- task: HumanMessage = Field(default_factory=lambda: HumanMessage(content="")) # the task provided by user
47
- plan: AIMessage = Field(
48
- default_factory=lambda: AIMessage(content="")) # the plan generated by the planner to solve the task
49
- steps: AIMessage = Field(
50
- default_factory=lambda: AIMessage(content="")) # the steps to solve the task, parsed from the plan
51
- intermediate_results: dict[str, ToolMessage] = Field(default_factory=dict) # the intermediate results of each step
52
- result: AIMessage = Field(
53
- default_factory=lambda: AIMessage(content="")) # the final result of the task, generated by the solver
54
-
55
-
56
- class ReWOOAgentGraph(BaseAgent):
57
- """Configurable LangGraph ReWOO Agent. A ReWOO Agent performs reasoning by interacting with other objects or tools
58
- and utilizes their outputs to make decisions. Supports retrying on output parsing errors. Argument
59
- "detailed_logs" toggles logging of inputs, outputs, and intermediate steps."""
60
-
61
- def __init__(self,
62
- llm: BaseChatModel,
63
- planner_prompt: ChatPromptTemplate,
64
- solver_prompt: ChatPromptTemplate,
65
- tools: list[BaseTool],
66
- use_tool_schema: bool = True,
67
- callbacks: list[AsyncCallbackHandler] | None = None,
68
- detailed_logs: bool = False):
69
- super().__init__(llm=llm, tools=tools, callbacks=callbacks, detailed_logs=detailed_logs)
70
-
71
- logger.debug(
72
- "%s Filling the prompt variables 'tools' and 'tool_names', using the tools provided in the config.",
73
- AGENT_LOG_PREFIX)
74
- tool_names = ",".join([tool.name for tool in tools[:-1]]) + ',' + tools[-1].name # prevent trailing ","
75
- if not use_tool_schema:
76
- tool_names_and_descriptions = "\n".join(
77
- [f"{tool.name}: {tool.description}"
78
- for tool in tools[:-1]]) + "\n" + f"{tools[-1].name}: {tools[-1].description}" # prevent trailing "\n"
79
- else:
80
- logger.debug("%s Adding the tools' input schema to the tools' description", AGENT_LOG_PREFIX)
81
- tool_names_and_descriptions = "\n".join([
82
- f"{tool.name}: {tool.description}. {INPUT_SCHEMA_MESSAGE.format(schema=tool.input_schema.model_fields)}"
83
- for tool in tools[:-1]
84
- ]) + "\n" + (f"{tools[-1].name}: {tools[-1].description}. "
85
- f"{INPUT_SCHEMA_MESSAGE.format(schema=tools[-1].input_schema.model_fields)}")
86
-
87
- self.planner_prompt = planner_prompt.partial(tools=tool_names_and_descriptions, tool_names=tool_names)
88
- self.solver_prompt = solver_prompt
89
- self.tools_dict = {tool.name: tool for tool in tools}
90
-
91
- logger.debug("%s Initialized ReWOO Agent Graph", AGENT_LOG_PREFIX)
92
-
93
- def _get_tool(self, tool_name: str):
94
- try:
95
- return self.tools_dict.get(tool_name)
96
- except Exception as ex:
97
- logger.exception("%s Unable to find tool with the name %s\n%s",
98
- AGENT_LOG_PREFIX,
99
- tool_name,
100
- ex,
101
- exc_info=True)
102
- raise ex
103
-
104
- @staticmethod
105
- def _get_current_step(state: ReWOOGraphState) -> int:
106
- steps = state.steps.content
107
- if len(steps) == 0:
108
- raise RuntimeError('No steps received in ReWOOGraphState')
109
-
110
- if len(state.intermediate_results) == len(steps):
111
- # all steps are done
112
- return -1
113
-
114
- return len(state.intermediate_results)
115
-
116
- @staticmethod
117
- def _parse_planner_output(planner_output: str) -> AIMessage:
118
-
119
- try:
120
- steps = json.loads(planner_output)
121
- except json.JSONDecodeError as ex:
122
- raise ValueError(f"The output of planner is invalid JSON format: {planner_output}") from ex
123
-
124
- return AIMessage(content=steps)
125
-
126
- @staticmethod
127
- def _replace_placeholder(placeholder: str, tool_input: str | dict, tool_output: str | dict) -> str | dict:
128
-
129
- # Replace the placeholders in the tool input with the previous tool output
130
- if isinstance(tool_input, dict):
131
- for key, value in tool_input.items():
132
- if value is not None:
133
- if value == placeholder:
134
- tool_input[key] = tool_output
135
- elif placeholder in value:
136
- # If the placeholder is part of the value, replace it with the stringified output
137
- tool_input[key] = value.replace(placeholder, str(tool_output))
138
-
139
- elif isinstance(tool_input, str):
140
- tool_input = tool_input.replace(placeholder, str(tool_output))
141
-
142
- else:
143
- assert False, f"Unexpected type for tool_input: {type(tool_input)}"
144
- return tool_input
145
-
146
- @staticmethod
147
- def _parse_tool_input(tool_input: str | dict):
148
-
149
- # If the input is already a dictionary, return it as is
150
- if isinstance(tool_input, dict):
151
- logger.debug("%s Tool input is already a dictionary. Use the tool input as is.", AGENT_LOG_PREFIX)
152
- return tool_input
153
-
154
- # If the input is a string, attempt to parse it as JSON
155
- try:
156
- tool_input = tool_input.strip()
157
- # If the input is already a valid JSON string, load it
158
- tool_input_parsed = json.loads(tool_input)
159
- logger.debug("%s Successfully parsed structured tool input", AGENT_LOG_PREFIX)
160
-
161
- except JSONDecodeError:
162
- try:
163
- # Replace single quotes with double quotes and attempt parsing again
164
- tool_input_fixed = tool_input.replace("'", '"')
165
- tool_input_parsed = json.loads(tool_input_fixed)
166
- logger.debug(
167
- "%s Successfully parsed structured tool input after replacing single quotes with double quotes",
168
- AGENT_LOG_PREFIX)
169
-
170
- except JSONDecodeError:
171
- # If it still fails, fall back to using the input as a raw string
172
- tool_input_parsed = tool_input
173
- logger.debug("%s Unable to parse structured tool input. Using raw tool input as is.", AGENT_LOG_PREFIX)
174
-
175
- return tool_input_parsed
176
-
177
- async def planner_node(self, state: ReWOOGraphState):
178
- try:
179
- logger.debug("%s Starting the ReWOO Planner Node", AGENT_LOG_PREFIX)
180
-
181
- planner = self.planner_prompt | self.llm
182
- task = str(state.task.content)
183
- if not task:
184
- logger.error("%s No task provided to the ReWOO Agent. Please provide a valid task.", AGENT_LOG_PREFIX)
185
- return {"result": NO_INPUT_ERROR_MESSAGE}
186
-
187
- plan = await self._stream_llm(
188
- planner,
189
- {"task": task},
190
- RunnableConfig(callbacks=self.callbacks) # type: ignore
191
- )
192
-
193
- steps = self._parse_planner_output(str(plan.content))
194
-
195
- if self.detailed_logs:
196
- agent_response_log_message = AGENT_CALL_LOG_MESSAGE % (task, str(plan.content))
197
- logger.info("ReWOO agent planner output: %s", agent_response_log_message)
198
-
199
- return {"plan": plan, "steps": steps}
200
-
201
- except Exception as ex:
202
- logger.exception("%s Failed to call planner_node: %s", AGENT_LOG_PREFIX, ex, exc_info=True)
203
- raise ex
204
-
205
- async def executor_node(self, state: ReWOOGraphState):
206
- try:
207
- logger.debug("%s Starting the ReWOO Executor Node", AGENT_LOG_PREFIX)
208
-
209
- current_step = self._get_current_step(state)
210
- # The executor node should not be invoked after all steps are finished
211
- if current_step < 0:
212
- logger.error("%s ReWOO Executor is invoked with an invalid step number: %s",
213
- AGENT_LOG_PREFIX,
214
- current_step)
215
- raise RuntimeError(f"ReWOO Executor is invoked with an invalid step number: {current_step}")
216
-
217
- steps_content = state.steps.content
218
- if isinstance(steps_content, list) and current_step < len(steps_content):
219
- step = steps_content[current_step]
220
- if isinstance(step, dict) and "evidence" in step:
221
- step_info = step["evidence"]
222
- placeholder = step_info.get("placeholder", "")
223
- tool = step_info.get("tool", "")
224
- tool_input = step_info.get("tool_input", "")
225
- else:
226
- logger.error("%s Invalid step format at index %s", AGENT_LOG_PREFIX, current_step)
227
- return {"intermediate_results": state.intermediate_results}
228
- else:
229
- logger.error("%s Invalid steps content or index %s", AGENT_LOG_PREFIX, current_step)
230
- return {"intermediate_results": state.intermediate_results}
231
-
232
- intermediate_results = state.intermediate_results
233
-
234
- # Replace the placeholder in the tool input with the previous tool output
235
- for _placeholder, _tool_output in intermediate_results.items():
236
- _tool_output = _tool_output.content
237
- # If the content is a list, get the first element which should be a dict
238
- if isinstance(_tool_output, list):
239
- _tool_output = _tool_output[0]
240
- assert isinstance(_tool_output, dict)
241
-
242
- tool_input = self._replace_placeholder(_placeholder, tool_input, _tool_output)
243
-
244
- requested_tool = self._get_tool(tool)
245
- if not requested_tool:
246
- configured_tool_names = list(self.tools_dict.keys())
247
- logger.warning(
248
- "%s ReWOO Agent wants to call tool %s. In the ReWOO Agent's configuration within the config file,"
249
- "there is no tool with that name: %s",
250
- AGENT_LOG_PREFIX,
251
- tool,
252
- configured_tool_names)
253
-
254
- intermediate_results[placeholder] = ToolMessage(content=TOOL_NOT_FOUND_ERROR_MESSAGE.format(
255
- tool_name=tool, tools=configured_tool_names),
256
- tool_call_id=tool)
257
- return {"intermediate_results": intermediate_results}
258
-
259
- if self.detailed_logs:
260
- logger.debug("%s Calling tool %s with input: %s", AGENT_LOG_PREFIX, requested_tool.name, tool_input)
261
-
262
- # Run the tool. Try to use structured input, if possible
263
- tool_input_parsed = self._parse_tool_input(tool_input)
264
- tool_response = await self._call_tool(requested_tool,
265
- tool_input_parsed,
266
- RunnableConfig(callbacks=self.callbacks),
267
- max_retries=3)
268
-
269
- # ToolMessage only accepts str or list[str | dict] as content.
270
- # Convert into list if the response is a dict.
271
- if isinstance(tool_response, dict):
272
- tool_response = [tool_response]
273
-
274
- tool_response_message = ToolMessage(name=tool, tool_call_id=tool, content=tool_response)
275
-
276
- if self.detailed_logs:
277
- self._log_tool_response(requested_tool.name, tool_input_parsed, str(tool_response))
278
-
279
- intermediate_results[placeholder] = tool_response_message
280
- return {"intermediate_results": intermediate_results}
281
-
282
- except Exception as ex:
283
- logger.exception("%s Failed to call executor_node: %s", AGENT_LOG_PREFIX, ex, exc_info=True)
284
- raise ex
285
-
286
- async def solver_node(self, state: ReWOOGraphState):
287
- try:
288
- logger.debug("%s Starting the ReWOO Solver Node", AGENT_LOG_PREFIX)
289
-
290
- plan = ""
291
- # Add the tool outputs of each step to the plan
292
- for step in state.steps.content:
293
- step_info = step["evidence"]
294
- placeholder = step_info.get("placeholder", "")
295
- tool_input = step_info.get("tool_input", "")
296
-
297
- intermediate_results = state.intermediate_results
298
- for _placeholder, _tool_output in intermediate_results.items():
299
- _tool_output = _tool_output.content
300
- # If the content is a list, get the first element which should be a dict
301
- if isinstance(_tool_output, list):
302
- _tool_output = _tool_output[0]
303
- assert isinstance(_tool_output, dict)
304
-
305
- tool_input = self._replace_placeholder(_placeholder, tool_input, _tool_output)
306
-
307
- placeholder = placeholder.replace(_placeholder, str(_tool_output))
308
-
309
- _plan = step.get("plan")
310
- tool = step_info.get("tool")
311
- plan += f"Plan: {_plan}\n{placeholder} = {tool}[{tool_input}]"
312
-
313
- task = str(state.task.content)
314
- solver_prompt = self.solver_prompt.partial(plan=plan)
315
- solver = solver_prompt | self.llm
316
-
317
- output_message = await self._stream_llm(solver, {"task": task},
318
- RunnableConfig(callbacks=self.callbacks)) # type: ignore
319
-
320
- if self.detailed_logs:
321
- solver_output_log_message = AGENT_CALL_LOG_MESSAGE % (task, str(output_message.content))
322
- logger.info("ReWOO agent solver output: %s", solver_output_log_message)
323
-
324
- return {"result": output_message}
325
-
326
- except Exception as ex:
327
- logger.exception("%s Failed to call solver_node: %s", AGENT_LOG_PREFIX, ex, exc_info=True)
328
- raise ex
329
-
330
- async def conditional_edge(self, state: ReWOOGraphState):
331
- try:
332
- logger.debug("%s Starting the ReWOO Conditional Edge", AGENT_LOG_PREFIX)
333
-
334
- current_step = self._get_current_step(state)
335
- if current_step == -1:
336
- logger.debug("%s The ReWOO Executor has finished its task", AGENT_LOG_PREFIX)
337
- return AgentDecision.END
338
-
339
- logger.debug("%s The ReWOO Executor is still working on the task", AGENT_LOG_PREFIX)
340
- return AgentDecision.TOOL
341
-
342
- except Exception as ex:
343
- logger.exception("%s Failed to determine whether agent is calling a tool: %s",
344
- AGENT_LOG_PREFIX,
345
- ex,
346
- exc_info=True)
347
- logger.warning("%s Ending graph traversal", AGENT_LOG_PREFIX)
348
- return AgentDecision.END
349
-
350
- async def _build_graph(self, state_schema):
351
- try:
352
- logger.debug("%s Building and compiling the ReWOO Graph", AGENT_LOG_PREFIX)
353
-
354
- graph = StateGraph(state_schema)
355
- graph.add_node("planner", self.planner_node)
356
- graph.add_node("executor", self.executor_node)
357
- graph.add_node("solver", self.solver_node)
358
-
359
- graph.add_edge("planner", "executor")
360
- conditional_edge_possible_outputs = {AgentDecision.TOOL: "executor", AgentDecision.END: "solver"}
361
- graph.add_conditional_edges("executor", self.conditional_edge, conditional_edge_possible_outputs)
362
-
363
- graph.set_entry_point("planner")
364
- graph.set_finish_point("solver")
365
-
366
- self.graph = graph.compile()
367
- logger.debug("%s ReWOO Graph built and compiled successfully", AGENT_LOG_PREFIX)
368
-
369
- return self.graph
370
-
371
- except Exception as ex:
372
- logger.exception("%s Failed to build ReWOO Graph: %s", AGENT_LOG_PREFIX, ex, exc_info=ex)
373
- raise ex
374
-
375
- async def build_graph(self):
376
- try:
377
- await self._build_graph(state_schema=ReWOOGraphState)
378
- logger.debug("%s ReWOO Graph built and compiled successfully", AGENT_LOG_PREFIX)
379
- return self.graph
380
- except Exception as ex:
381
- logger.exception("%s Failed to build ReWOO Graph: %s", AGENT_LOG_PREFIX, ex, exc_info=ex)
382
- raise ex
383
-
384
- @staticmethod
385
- def validate_planner_prompt(planner_prompt: str) -> bool:
386
- errors = []
387
- if not planner_prompt:
388
- errors.append("The planner prompt cannot be empty.")
389
- required_prompt_variables = {
390
- "{tools}": "The planner prompt must contain {tools} so the planner agent knows about configured tools.",
391
- "{tool_names}": "The planner prompt must contain {tool_names} so the planner agent knows tool names."
392
- }
393
- for variable_name, error_message in required_prompt_variables.items():
394
- if variable_name not in planner_prompt:
395
- errors.append(error_message)
396
- if errors:
397
- error_text = "\n".join(errors)
398
- logger.exception("%s %s", AGENT_LOG_PREFIX, error_text)
399
- raise ValueError(error_text)
400
- return True
401
-
402
- @staticmethod
403
- def validate_solver_prompt(solver_prompt: str) -> bool:
404
- errors = []
405
- if not solver_prompt:
406
- errors.append("The solver prompt cannot be empty.")
407
- if errors:
408
- error_text = "\n".join(errors)
409
- logger.exception("%s %s", AGENT_LOG_PREFIX, error_text)
410
- raise ValueError(error_text)
411
- return True