aiqtoolkit 1.2.0rc4__py3-none-any.whl → 1.2rc9__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 (441) hide show
  1. aiqtoolkit-1.2rc9.dist-info/METADATA +29 -0
  2. aiqtoolkit-1.2rc9.dist-info/RECORD +4 -0
  3. aiqtoolkit-1.2rc9.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 -96
  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 -335
  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 -76
  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 -567
  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 -215
  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 -151
  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/dump_distro_mapping.py +0 -32
  409. aiq/utils/exception_handlers/__init__.py +0 -0
  410. aiq/utils/exception_handlers/automatic_retries.py +0 -289
  411. aiq/utils/exception_handlers/mcp.py +0 -211
  412. aiq/utils/exception_handlers/schemas.py +0 -114
  413. aiq/utils/io/__init__.py +0 -0
  414. aiq/utils/io/model_processing.py +0 -28
  415. aiq/utils/io/yaml_tools.py +0 -119
  416. aiq/utils/log_utils.py +0 -37
  417. aiq/utils/metadata_utils.py +0 -74
  418. aiq/utils/optional_imports.py +0 -142
  419. aiq/utils/producer_consumer_queue.py +0 -178
  420. aiq/utils/reactive/__init__.py +0 -0
  421. aiq/utils/reactive/base/__init__.py +0 -0
  422. aiq/utils/reactive/base/observable_base.py +0 -65
  423. aiq/utils/reactive/base/observer_base.py +0 -55
  424. aiq/utils/reactive/base/subject_base.py +0 -79
  425. aiq/utils/reactive/observable.py +0 -59
  426. aiq/utils/reactive/observer.py +0 -76
  427. aiq/utils/reactive/subject.py +0 -131
  428. aiq/utils/reactive/subscription.py +0 -49
  429. aiq/utils/settings/__init__.py +0 -0
  430. aiq/utils/settings/global_settings.py +0 -197
  431. aiq/utils/string_utils.py +0 -38
  432. aiq/utils/type_converter.py +0 -290
  433. aiq/utils/type_utils.py +0 -484
  434. aiq/utils/url_utils.py +0 -27
  435. aiqtoolkit-1.2.0rc4.dist-info/METADATA +0 -363
  436. aiqtoolkit-1.2.0rc4.dist-info/RECORD +0 -438
  437. aiqtoolkit-1.2.0rc4.dist-info/entry_points.txt +0 -20
  438. aiqtoolkit-1.2.0rc4.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
  439. aiqtoolkit-1.2.0rc4.dist-info/licenses/LICENSE.md +0 -201
  440. aiqtoolkit-1.2.0rc4.dist-info/top_level.txt +0 -1
  441. {aiqtoolkit-1.2.0rc4.dist-info → aiqtoolkit-1.2rc9.dist-info}/WHEEL +0 -0
@@ -1,355 +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.agents import AgentAction
22
- from langchain_core.agents import AgentFinish
23
- from langchain_core.callbacks.base import AsyncCallbackHandler
24
- from langchain_core.language_models import BaseChatModel
25
- from langchain_core.messages.ai import AIMessage
26
- from langchain_core.messages.base import BaseMessage
27
- from langchain_core.messages.human import HumanMessage
28
- from langchain_core.messages.tool import ToolMessage
29
- from langchain_core.prompts import ChatPromptTemplate
30
- from langchain_core.prompts import MessagesPlaceholder
31
- from langchain_core.runnables.config import RunnableConfig
32
- from langchain_core.tools import BaseTool
33
- from pydantic import BaseModel
34
- from pydantic import Field
35
-
36
- from aiq.agent.base import AGENT_CALL_LOG_MESSAGE
37
- from aiq.agent.base import AGENT_LOG_PREFIX
38
- from aiq.agent.base import INPUT_SCHEMA_MESSAGE
39
- from aiq.agent.base import NO_INPUT_ERROR_MESSAGE
40
- from aiq.agent.base import TOOL_NOT_FOUND_ERROR_MESSAGE
41
- from aiq.agent.base import AgentDecision
42
- from aiq.agent.dual_node import DualNodeAgent
43
- from aiq.agent.react_agent.output_parser import ReActOutputParser
44
- from aiq.agent.react_agent.output_parser import ReActOutputParserException
45
- from aiq.agent.react_agent.prompt import SYSTEM_PROMPT
46
- from aiq.agent.react_agent.prompt import USER_PROMPT
47
- from aiq.agent.react_agent.register import ReActAgentWorkflowConfig
48
-
49
- logger = logging.getLogger(__name__)
50
-
51
-
52
- class ReActGraphState(BaseModel):
53
- """State schema for the ReAct Agent Graph"""
54
- messages: list[BaseMessage] = Field(default_factory=list) # input and output of the ReAct Agent
55
- agent_scratchpad: list[AgentAction] = Field(default_factory=list) # agent thoughts / intermediate steps
56
- tool_responses: list[BaseMessage] = Field(default_factory=list) # the responses from any tool calls
57
-
58
-
59
- class ReActAgentGraph(DualNodeAgent):
60
- """Configurable LangGraph ReAct Agent. A ReAct Agent performs reasoning inbetween tool calls, and utilizes the tool
61
- names and descriptions to select the optimal tool. Supports retrying on output parsing errors. Argument
62
- "detailed_logs" toggles logging of inputs, outputs, and intermediate steps."""
63
-
64
- def __init__(self,
65
- llm: BaseChatModel,
66
- prompt: ChatPromptTemplate,
67
- tools: list[BaseTool],
68
- use_tool_schema: bool = True,
69
- callbacks: list[AsyncCallbackHandler] | None = None,
70
- detailed_logs: bool = False,
71
- retry_agent_response_parsing_errors: bool = True,
72
- parse_agent_response_max_retries: int = 1,
73
- tool_call_max_retries: int = 1,
74
- pass_tool_call_errors_to_agent: bool = True):
75
- super().__init__(llm=llm, tools=tools, callbacks=callbacks, detailed_logs=detailed_logs)
76
- self.parse_agent_response_max_retries = (parse_agent_response_max_retries
77
- if retry_agent_response_parsing_errors else 1)
78
- self.tool_call_max_retries = tool_call_max_retries
79
- self.pass_tool_call_errors_to_agent = pass_tool_call_errors_to_agent
80
- logger.debug(
81
- "%s Filling the prompt variables 'tools' and 'tool_names', using the tools provided in the config.",
82
- AGENT_LOG_PREFIX)
83
- tool_names = ",".join([tool.name for tool in tools[:-1]]) + ',' + tools[-1].name # prevent trailing ","
84
- if not use_tool_schema:
85
- tool_names_and_descriptions = "\n".join(
86
- [f"{tool.name}: {tool.description}"
87
- for tool in tools[:-1]]) + "\n" + f"{tools[-1].name}: {tools[-1].description}" # prevent trailing "\n"
88
- else:
89
- logger.debug("%s Adding the tools' input schema to the tools' description", AGENT_LOG_PREFIX)
90
- tool_names_and_descriptions = "\n".join([
91
- f"{tool.name}: {tool.description}. {INPUT_SCHEMA_MESSAGE.format(schema=tool.input_schema.model_fields)}"
92
- for tool in tools[:-1]
93
- ]) + "\n" + (f"{tools[-1].name}: {tools[-1].description}. "
94
- f"{INPUT_SCHEMA_MESSAGE.format(schema=tools[-1].input_schema.model_fields)}")
95
- prompt = prompt.partial(tools=tool_names_and_descriptions, tool_names=tool_names)
96
- # construct the ReAct Agent
97
- bound_llm = llm.bind(stop=["Observation:"]) # type: ignore
98
- self.agent = prompt | bound_llm
99
- self.tools_dict = {tool.name: tool for tool in tools}
100
- logger.debug("%s Initialized ReAct Agent Graph", AGENT_LOG_PREFIX)
101
-
102
- def _get_tool(self, tool_name: str):
103
- try:
104
- return self.tools_dict.get(tool_name)
105
- except Exception as ex:
106
- logger.exception("%s Unable to find tool with the name %s\n%s",
107
- AGENT_LOG_PREFIX,
108
- tool_name,
109
- ex,
110
- exc_info=True)
111
- raise ex
112
-
113
- async def agent_node(self, state: ReActGraphState):
114
- try:
115
- logger.debug("%s Starting the ReAct Agent Node", AGENT_LOG_PREFIX)
116
- # keeping a working state allows us to resolve parsing errors without polluting the agent scratchpad
117
- # the agent "forgets" about the parsing error after solving it - prevents hallucinations in next cycles
118
- working_state = []
119
- # Starting from attempt 1 instead of 0 for logging
120
- for attempt in range(1, self.parse_agent_response_max_retries + 1):
121
- # the first time we are invoking the ReAct Agent, it won't have any intermediate steps / agent thoughts
122
- if len(state.agent_scratchpad) == 0 and len(working_state) == 0:
123
- # the user input comes from the "messages" state channel
124
- if len(state.messages) == 0:
125
- raise RuntimeError('No input received in state: "messages"')
126
- # to check is any human input passed or not, if no input passed Agent will return the state
127
- content = str(state.messages[0].content)
128
- if content.strip() == "":
129
- logger.error("%s No human input passed to the agent.", AGENT_LOG_PREFIX)
130
- state.messages += [AIMessage(content=NO_INPUT_ERROR_MESSAGE)]
131
- return state
132
- question = content
133
- logger.debug("%s Querying agent, attempt: %s", AGENT_LOG_PREFIX, attempt)
134
-
135
- output_message = await self._stream_llm(
136
- self.agent,
137
- {"question": question},
138
- RunnableConfig(callbacks=self.callbacks) # type: ignore
139
- )
140
-
141
- if self.detailed_logs:
142
- logger.info(AGENT_CALL_LOG_MESSAGE, question, output_message.content)
143
- else:
144
- # ReAct Agents require agentic cycles
145
- # in an agentic cycle, preserve the agent's thoughts from the previous cycles,
146
- # and give the agent the response from the tool it called
147
- agent_scratchpad = []
148
- for index, intermediate_step in enumerate(state.agent_scratchpad):
149
- agent_thoughts = AIMessage(content=intermediate_step.log)
150
- agent_scratchpad.append(agent_thoughts)
151
- tool_response_content = str(state.tool_responses[index].content)
152
- tool_response = HumanMessage(content=tool_response_content)
153
- agent_scratchpad.append(tool_response)
154
- agent_scratchpad += working_state
155
- question = str(state.messages[0].content)
156
- logger.debug("%s Querying agent, attempt: %s", AGENT_LOG_PREFIX, attempt)
157
-
158
- output_message = await self._stream_llm(self.agent, {
159
- "question": question, "agent_scratchpad": agent_scratchpad
160
- },
161
- RunnableConfig(callbacks=self.callbacks))
162
-
163
- if self.detailed_logs:
164
- logger.info(AGENT_CALL_LOG_MESSAGE, question, output_message.content)
165
- logger.debug("%s The agent's scratchpad (with tool result) was:\n%s",
166
- AGENT_LOG_PREFIX,
167
- agent_scratchpad)
168
- try:
169
- # check if the agent has the final answer yet
170
- logger.debug("%s Successfully obtained agent response. Parsing agent's response", AGENT_LOG_PREFIX)
171
- agent_output = await ReActOutputParser().aparse(output_message.content)
172
- logger.debug("%s Successfully parsed agent response after %s attempts", AGENT_LOG_PREFIX, attempt)
173
- if isinstance(agent_output, AgentFinish):
174
- final_answer = agent_output.return_values.get('output', output_message.content)
175
- logger.debug("%s The agent has finished, and has the final answer", AGENT_LOG_PREFIX)
176
- # this is where we handle the final output of the Agent, we can clean-up/format/postprocess here
177
- # the final answer goes in the "messages" state channel
178
- state.messages += [AIMessage(content=final_answer)]
179
- else:
180
- # the agent wants to call a tool, ensure the thoughts are preserved for the next agentic cycle
181
- agent_output.log = output_message.content
182
- logger.debug("%s The agent wants to call a tool: %s", AGENT_LOG_PREFIX, agent_output.tool)
183
- state.agent_scratchpad += [agent_output]
184
-
185
- return state
186
- except ReActOutputParserException as ex:
187
- # the agent output did not meet the expected ReAct output format. This can happen for a few reasons:
188
- # the agent mentioned a tool, but already has the final answer, this can happen with Llama models
189
- # - the ReAct Agent already has the answer, and is reflecting on how it obtained the answer
190
- # the agent might have also missed Action or Action Input in its output
191
- logger.debug("%s Error parsing agent output\nObservation:%s\nAgent Output:\n%s",
192
- AGENT_LOG_PREFIX,
193
- ex.observation,
194
- output_message.content)
195
- if attempt == self.parse_agent_response_max_retries:
196
- logger.warning(
197
- "%s Failed to parse agent output after %d attempts, consider enabling or "
198
- "increasing parse_agent_response_max_retries",
199
- AGENT_LOG_PREFIX,
200
- attempt)
201
- # the final answer goes in the "messages" state channel
202
- combined_content = str(ex.observation) + '\n' + str(output_message.content)
203
- output_message.content = combined_content
204
- state.messages += [output_message]
205
- return state
206
- # retry parsing errors, if configured
207
- logger.info("%s Retrying ReAct Agent, including output parsing Observation", AGENT_LOG_PREFIX)
208
- working_state.append(output_message)
209
- working_state.append(HumanMessage(content=str(ex.observation)))
210
- except Exception as ex:
211
- logger.exception("%s Failed to call agent_node: %s", AGENT_LOG_PREFIX, ex, exc_info=True)
212
- raise ex
213
-
214
- async def conditional_edge(self, state: ReActGraphState):
215
- try:
216
- logger.debug("%s Starting the ReAct Conditional Edge", AGENT_LOG_PREFIX)
217
- if len(state.messages) > 1:
218
- # the ReAct Agent has finished executing, the last agent output was AgentFinish
219
- last_message_content = str(state.messages[-1].content)
220
- logger.debug("%s Final answer:\n%s", AGENT_LOG_PREFIX, last_message_content)
221
- return AgentDecision.END
222
- # else the agent wants to call a tool
223
- agent_output = state.agent_scratchpad[-1]
224
- logger.debug("%s The agent wants to call: %s with input: %s",
225
- AGENT_LOG_PREFIX,
226
- agent_output.tool,
227
- agent_output.tool_input)
228
- return AgentDecision.TOOL
229
- except Exception as ex:
230
- logger.exception("Failed to determine whether agent is calling a tool: %s", ex, exc_info=True)
231
- logger.warning("%s Ending graph traversal", AGENT_LOG_PREFIX)
232
- return AgentDecision.END
233
-
234
- async def tool_node(self, state: ReActGraphState):
235
-
236
- logger.debug("%s Starting the Tool Call Node", AGENT_LOG_PREFIX)
237
- if len(state.agent_scratchpad) == 0:
238
- raise RuntimeError('No tool input received in state: "agent_scratchpad"')
239
- agent_thoughts = state.agent_scratchpad[-1]
240
- # the agent can run any installed tool, simply install the tool and add it to the config file
241
- requested_tool = self._get_tool(agent_thoughts.tool)
242
- if not requested_tool:
243
- configured_tool_names = list(self.tools_dict.keys())
244
- logger.warning(
245
- "%s ReAct Agent wants to call tool %s. In the ReAct Agent's configuration within the config file,"
246
- "there is no tool with that name: %s",
247
- AGENT_LOG_PREFIX,
248
- agent_thoughts.tool,
249
- configured_tool_names)
250
- tool_response = ToolMessage(name='agent_error',
251
- tool_call_id='agent_error',
252
- content=TOOL_NOT_FOUND_ERROR_MESSAGE.format(tool_name=agent_thoughts.tool,
253
- tools=configured_tool_names))
254
- state.tool_responses += [tool_response]
255
- return state
256
-
257
- logger.debug("%s Calling tool %s with input: %s",
258
- AGENT_LOG_PREFIX,
259
- requested_tool.name,
260
- agent_thoughts.tool_input)
261
-
262
- # Run the tool. Try to use structured input, if possible.
263
- try:
264
- tool_input_str = str(agent_thoughts.tool_input).strip().replace("'", '"')
265
- tool_input_dict = json.loads(tool_input_str) if tool_input_str != 'None' else tool_input_str
266
- logger.debug("%s Successfully parsed structured tool input from Action Input", AGENT_LOG_PREFIX)
267
-
268
- tool_response = await self._call_tool(requested_tool,
269
- tool_input_dict,
270
- RunnableConfig(callbacks=self.callbacks),
271
- max_retries=self.tool_call_max_retries)
272
-
273
- if self.detailed_logs:
274
- self._log_tool_response(requested_tool.name, tool_input_dict, str(tool_response.content))
275
-
276
- except JSONDecodeError as ex:
277
- logger.debug(
278
- "%s Unable to parse structured tool input from Action Input. Using Action Input as is."
279
- "\nParsing error: %s",
280
- AGENT_LOG_PREFIX,
281
- ex,
282
- exc_info=True)
283
- tool_input_str = str(agent_thoughts.tool_input)
284
-
285
- tool_response = await self._call_tool(requested_tool,
286
- tool_input_str,
287
- RunnableConfig(callbacks=self.callbacks),
288
- max_retries=self.tool_call_max_retries)
289
-
290
- if self.detailed_logs:
291
- self._log_tool_response(requested_tool.name, tool_input_str, str(tool_response.content))
292
-
293
- if not self.pass_tool_call_errors_to_agent:
294
- if tool_response.status == "error":
295
- logger.error("%s Tool %s failed: %s", AGENT_LOG_PREFIX, requested_tool.name, tool_response.content)
296
- raise RuntimeError("Tool call failed: " + str(tool_response.content))
297
-
298
- state.tool_responses += [tool_response]
299
- return state
300
-
301
- async def build_graph(self):
302
- try:
303
- await super()._build_graph(state_schema=ReActGraphState)
304
- logger.debug("%s ReAct Graph built and compiled successfully", AGENT_LOG_PREFIX)
305
- return self.graph
306
- except Exception as ex:
307
- logger.exception("%s Failed to build ReAct Graph: %s", AGENT_LOG_PREFIX, ex, exc_info=ex)
308
- raise ex
309
-
310
- @staticmethod
311
- def validate_system_prompt(system_prompt: str) -> bool:
312
- errors = []
313
- if not system_prompt:
314
- errors.append("The system prompt cannot be empty.")
315
- required_prompt_variables = {
316
- "{tools}": "The system prompt must contain {tools} so the agent knows about configured tools.",
317
- "{tool_names}": "The system prompt must contain {tool_names} so the agent knows tool names."
318
- }
319
- for variable_name, error_message in required_prompt_variables.items():
320
- if variable_name not in system_prompt:
321
- errors.append(error_message)
322
- if errors:
323
- error_text = "\n".join(errors)
324
- logger.exception("%s %s", AGENT_LOG_PREFIX, error_text)
325
- raise ValueError(error_text)
326
- return True
327
-
328
-
329
- def create_react_agent_prompt(config: ReActAgentWorkflowConfig) -> ChatPromptTemplate:
330
- """
331
- Create a ReAct Agent prompt from the config.
332
-
333
- Args:
334
- config (ReActAgentWorkflowConfig): The config to use for the prompt.
335
-
336
- Returns:
337
- ChatPromptTemplate: The ReAct Agent prompt.
338
- """
339
- # the ReAct Agent prompt can be customized via config option system_prompt and additional_instructions.
340
-
341
- if config.system_prompt:
342
- prompt_str = config.system_prompt
343
- else:
344
- prompt_str = SYSTEM_PROMPT
345
-
346
- if config.additional_instructions:
347
- prompt_str += f" {config.additional_instructions}"
348
-
349
- valid_prompt = ReActAgentGraph.validate_system_prompt(prompt_str)
350
- if not valid_prompt:
351
- logger.exception("%s Invalid system_prompt", AGENT_LOG_PREFIX)
352
- raise ValueError("Invalid system_prompt")
353
- prompt = ChatPromptTemplate([("system", prompt_str), ("user", USER_PROMPT),
354
- MessagesPlaceholder(variable_name='agent_scratchpad', optional=True)])
355
- return prompt
@@ -1,104 +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 re
17
-
18
- from langchain.agents.agent import AgentOutputParser
19
- from langchain_core.agents import AgentAction
20
- from langchain_core.agents import AgentFinish
21
- from langchain_core.exceptions import LangChainException
22
-
23
- from .prompt import SYSTEM_PROMPT
24
-
25
- FINAL_ANSWER_ACTION = "Final Answer:"
26
- MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE = "Invalid Format: Missing 'Action:' after 'Thought:'"
27
- MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE = "Invalid Format: Missing 'Action Input:' after 'Action:'"
28
- FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE = ("Parsing LLM output produced both a final answer and a parse-able "
29
- "action:")
30
-
31
-
32
- class ReActOutputParserException(ValueError, LangChainException):
33
-
34
- def __init__(self,
35
- observation=None,
36
- missing_action=False,
37
- missing_action_input=False,
38
- final_answer_and_action=False):
39
- self.observation = observation
40
- self.missing_action = missing_action
41
- self.missing_action_input = missing_action_input
42
- self.final_answer_and_action = final_answer_and_action
43
-
44
-
45
- class ReActOutputParser(AgentOutputParser):
46
- """Parses ReAct-style LLM calls that have a single tool input.
47
-
48
- Expects output to be in one of two formats.
49
-
50
- If the output signals that an action should be taken,
51
- should be in the below format. This will result in an AgentAction
52
- being returned.
53
-
54
- ```
55
- Thought: agent thought here
56
- Action: search
57
- Action Input: what is the temperature in SF?
58
- Observation: Waiting for the tool response...
59
- ```
60
-
61
- If the output signals that a final answer should be given,
62
- should be in the below format. This will result in an AgentFinish
63
- being returned.
64
-
65
- ```
66
- Thought: agent thought here
67
- Final Answer: The temperature is 100 degrees
68
- ```
69
-
70
- """
71
-
72
- def get_format_instructions(self) -> str:
73
- return SYSTEM_PROMPT
74
-
75
- def parse(self, text: str) -> AgentAction | AgentFinish:
76
- includes_answer = FINAL_ANSWER_ACTION in text
77
- regex = r"Action\s*\d*\s*:[\s]*(.*?)\s*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*?)(?=\s*[\n|\s]\s*Observation\b|$)"
78
- action_match = re.search(regex, text, re.DOTALL)
79
- if action_match:
80
- if includes_answer:
81
- raise ReActOutputParserException(
82
- final_answer_and_action=True,
83
- observation=f"{FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: {text}")
84
- action = action_match.group(1).strip()
85
- action_input = action_match.group(2)
86
- tool_input = action_input.strip(" ")
87
- tool_input = tool_input.strip('"')
88
-
89
- return AgentAction(action, tool_input, text)
90
-
91
- if includes_answer:
92
- return AgentFinish({"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()}, text)
93
-
94
- if not re.search(r"Action\s*\d*\s*:[\s]*(.*?)", text, re.DOTALL):
95
- raise ReActOutputParserException(observation=MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE,
96
- missing_action=True)
97
- if not re.search(r"[\s]*Action\s*\d*\s*Input\s*\d*\s*:[\s]*(.*)", text, re.DOTALL):
98
- raise ReActOutputParserException(observation=MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE,
99
- missing_action_input=True)
100
- raise ReActOutputParserException(f"Could not parse LLM output: `{text}`")
101
-
102
- @property
103
- def _type(self) -> str:
104
- return "react-input"
@@ -1,41 +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
- # flake8: noqa
17
-
18
- SYSTEM_PROMPT = """
19
- Answer the following questions as best you can. You may ask the human to use the following tools:
20
-
21
- {tools}
22
-
23
- You may respond in one of two formats.
24
- Use the following format exactly to ask the human to use a tool:
25
-
26
- Question: the input question you must answer
27
- Thought: you should always think about what to do
28
- Action: the action to take, should be one of [{tool_names}]
29
- Action Input: the input to the action (if there is no required input, include "Action Input: None")
30
- Observation: wait for the human to respond with the result from the tool, do not assume the response
31
-
32
- ... (this Thought/Action/Action Input/Observation can repeat N times. If you do not need to use a tool, or after asking the human to use any tools and waiting for the human to respond, you might know the final answer.)
33
- Use the following format once you have the final answer:
34
-
35
- Thought: I now know the final answer
36
- Final Answer: the final answer to the original input question
37
- """
38
-
39
- USER_PROMPT = """
40
- Question: {question}
41
- """
@@ -1,149 +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
-
18
- from pydantic import AliasChoices
19
- from pydantic import Field
20
-
21
- from aiq.builder.builder import Builder
22
- from aiq.builder.framework_enum import LLMFrameworkEnum
23
- from aiq.builder.function_info import FunctionInfo
24
- from aiq.cli.register_workflow import register_function
25
- from aiq.data_models.api_server import AIQChatRequest
26
- from aiq.data_models.api_server import AIQChatResponse
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
- from aiq.utils.type_converter import GlobalTypeConverter
31
-
32
- logger = logging.getLogger(__name__)
33
-
34
-
35
- class ReActAgentWorkflowConfig(FunctionBaseConfig, name="react_agent"):
36
- """
37
- Defines an AIQ Toolkit function that uses a ReAct Agent performs reasoning inbetween tool calls, and utilizes the
38
- tool names and descriptions to select the optimal tool.
39
- """
40
-
41
- tool_names: list[FunctionRef] = Field(default_factory=list,
42
- description="The list of tools to provide to the react agent.")
43
- llm_name: LLMRef = Field(description="The LLM model to use with the react agent.")
44
- verbose: bool = Field(default=False, description="Set the verbosity of the react agent's logging.")
45
- retry_agent_response_parsing_errors: bool = Field(
46
- default=True,
47
- validation_alias=AliasChoices("retry_agent_response_parsing_errors", "retry_parsing_errors"),
48
- description="Whether to retry when encountering parsing errors in the agent's response.")
49
- parse_agent_response_max_retries: int = Field(
50
- default=1,
51
- validation_alias=AliasChoices("parse_agent_response_max_retries", "max_retries"),
52
- description="Maximum number of times the Agent may retry parsing errors. "
53
- "Prevents the Agent from getting into infinite hallucination loops.")
54
- tool_call_max_retries: int = Field(default=1, description="The number of retries before raising a tool call error.")
55
- max_tool_calls: int = Field(default=15,
56
- validation_alias=AliasChoices("max_tool_calls", "max_iterations"),
57
- description="Maximum number of tool calls before stopping the agent.")
58
- pass_tool_call_errors_to_agent: bool = Field(
59
- default=True,
60
- description="Whether to pass tool call errors to agent. If False, failed tool calls will raise an exception.")
61
- include_tool_input_schema_in_tool_description: bool = Field(
62
- default=True, description="Specify inclusion of tool input schemas in the prompt.")
63
- description: str = Field(default="ReAct Agent Workflow", description="The description of this functions use.")
64
- system_prompt: str | None = Field(
65
- default=None,
66
- description="Provides the SYSTEM_PROMPT to use with the agent") # defaults to SYSTEM_PROMPT in prompt.py
67
- max_history: int = Field(default=15, description="Maximum number of messages to keep in the conversation history.")
68
- use_openai_api: bool = Field(default=False,
69
- description=("Use OpenAI API for the input/output types to the function. "
70
- "If False, strings will be used."))
71
- additional_instructions: str | None = Field(
72
- default=None, description="Additional instructions to provide to the agent in addition to the base prompt.")
73
-
74
-
75
- @register_function(config_type=ReActAgentWorkflowConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN])
76
- async def react_agent_workflow(config: ReActAgentWorkflowConfig, builder: Builder):
77
- from langchain.schema import BaseMessage
78
- from langchain_core.messages import trim_messages
79
- from langgraph.graph.graph import CompiledGraph
80
-
81
- from aiq.agent.base import AGENT_LOG_PREFIX
82
- from aiq.agent.react_agent.agent import ReActAgentGraph
83
- from aiq.agent.react_agent.agent import ReActGraphState
84
- from aiq.agent.react_agent.agent import create_react_agent_prompt
85
-
86
- prompt = create_react_agent_prompt(config)
87
-
88
- # we can choose an LLM for the ReAct agent in the config file
89
- llm = await builder.get_llm(config.llm_name, wrapper_type=LLMFrameworkEnum.LANGCHAIN)
90
- # the agent can run any installed tool, simply install the tool and add it to the config file
91
- # the sample tool provided can easily be copied or changed
92
- tools = builder.get_tools(tool_names=config.tool_names, wrapper_type=LLMFrameworkEnum.LANGCHAIN)
93
- if not tools:
94
- raise ValueError(f"No tools specified for ReAct Agent '{config.llm_name}'")
95
- # configure callbacks, for sending intermediate steps
96
- # construct the ReAct Agent Graph from the configured llm, prompt, and tools
97
- graph: CompiledGraph = await ReActAgentGraph(
98
- llm=llm,
99
- prompt=prompt,
100
- tools=tools,
101
- use_tool_schema=config.include_tool_input_schema_in_tool_description,
102
- detailed_logs=config.verbose,
103
- retry_agent_response_parsing_errors=config.retry_agent_response_parsing_errors,
104
- parse_agent_response_max_retries=config.parse_agent_response_max_retries,
105
- tool_call_max_retries=config.tool_call_max_retries,
106
- pass_tool_call_errors_to_agent=config.pass_tool_call_errors_to_agent).build_graph()
107
-
108
- async def _response_fn(input_message: AIQChatRequest) -> AIQChatResponse:
109
- try:
110
- # initialize the starting state with the user query
111
- messages: list[BaseMessage] = trim_messages(messages=[m.model_dump() for m in input_message.messages],
112
- max_tokens=config.max_history,
113
- strategy="last",
114
- token_counter=len,
115
- start_on="human",
116
- include_system=True)
117
-
118
- state = ReActGraphState(messages=messages)
119
-
120
- # run the ReAct Agent Graph
121
- state = await graph.ainvoke(state, config={'recursion_limit': (config.max_tool_calls + 1) * 2})
122
- # setting recursion_limit: 4 allows 1 tool call
123
- # - allows the ReAct Agent to perform 1 cycle / call 1 single tool,
124
- # - but stops the agent when it tries to call a tool a second time
125
-
126
- # get and return the output from the state
127
- state = ReActGraphState(**state)
128
- output_message = state.messages[-1] # pylint: disable=E1136
129
- return AIQChatResponse.from_string(str(output_message.content))
130
-
131
- except Exception as ex:
132
- logger.exception("%s ReAct Agent failed with exception: %s", AGENT_LOG_PREFIX, ex, exc_info=ex)
133
- # here, we can implement custom error messages
134
- if config.verbose:
135
- return AIQChatResponse.from_string(str(ex))
136
- return AIQChatResponse.from_string("I seem to be having a problem.")
137
-
138
- if (config.use_openai_api):
139
- yield FunctionInfo.from_fn(_response_fn, description=config.description)
140
- else:
141
-
142
- async def _str_api_fn(input_message: str) -> str:
143
- oai_input = GlobalTypeConverter.get().try_convert(input_message, to_type=AIQChatRequest)
144
-
145
- oai_output = await _response_fn(oai_input)
146
-
147
- return GlobalTypeConverter.get().try_convert(oai_output, to_type=str)
148
-
149
- yield FunctionInfo.from_fn(_str_api_fn, description=config.description)
File without changes