nvidia-nat 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.
Files changed (435) hide show
  1. aiq/agent/__init__.py +0 -0
  2. aiq/agent/base.py +239 -0
  3. aiq/agent/dual_node.py +67 -0
  4. aiq/agent/react_agent/__init__.py +0 -0
  5. aiq/agent/react_agent/agent.py +355 -0
  6. aiq/agent/react_agent/output_parser.py +104 -0
  7. aiq/agent/react_agent/prompt.py +41 -0
  8. aiq/agent/react_agent/register.py +149 -0
  9. aiq/agent/reasoning_agent/__init__.py +0 -0
  10. aiq/agent/reasoning_agent/reasoning_agent.py +225 -0
  11. aiq/agent/register.py +23 -0
  12. aiq/agent/rewoo_agent/__init__.py +0 -0
  13. aiq/agent/rewoo_agent/agent.py +411 -0
  14. aiq/agent/rewoo_agent/prompt.py +108 -0
  15. aiq/agent/rewoo_agent/register.py +158 -0
  16. aiq/agent/tool_calling_agent/__init__.py +0 -0
  17. aiq/agent/tool_calling_agent/agent.py +119 -0
  18. aiq/agent/tool_calling_agent/register.py +106 -0
  19. aiq/authentication/__init__.py +14 -0
  20. aiq/authentication/api_key/__init__.py +14 -0
  21. aiq/authentication/api_key/api_key_auth_provider.py +96 -0
  22. aiq/authentication/api_key/api_key_auth_provider_config.py +124 -0
  23. aiq/authentication/api_key/register.py +26 -0
  24. aiq/authentication/exceptions/__init__.py +14 -0
  25. aiq/authentication/exceptions/api_key_exceptions.py +38 -0
  26. aiq/authentication/http_basic_auth/__init__.py +0 -0
  27. aiq/authentication/http_basic_auth/http_basic_auth_provider.py +81 -0
  28. aiq/authentication/http_basic_auth/register.py +30 -0
  29. aiq/authentication/interfaces.py +93 -0
  30. aiq/authentication/oauth2/__init__.py +14 -0
  31. aiq/authentication/oauth2/oauth2_auth_code_flow_provider.py +107 -0
  32. aiq/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +39 -0
  33. aiq/authentication/oauth2/register.py +25 -0
  34. aiq/authentication/register.py +21 -0
  35. aiq/builder/__init__.py +0 -0
  36. aiq/builder/builder.py +285 -0
  37. aiq/builder/component_utils.py +316 -0
  38. aiq/builder/context.py +264 -0
  39. aiq/builder/embedder.py +24 -0
  40. aiq/builder/eval_builder.py +161 -0
  41. aiq/builder/evaluator.py +29 -0
  42. aiq/builder/framework_enum.py +24 -0
  43. aiq/builder/front_end.py +73 -0
  44. aiq/builder/function.py +344 -0
  45. aiq/builder/function_base.py +380 -0
  46. aiq/builder/function_info.py +627 -0
  47. aiq/builder/intermediate_step_manager.py +174 -0
  48. aiq/builder/llm.py +25 -0
  49. aiq/builder/retriever.py +25 -0
  50. aiq/builder/user_interaction_manager.py +74 -0
  51. aiq/builder/workflow.py +148 -0
  52. aiq/builder/workflow_builder.py +1117 -0
  53. aiq/cli/__init__.py +14 -0
  54. aiq/cli/cli_utils/__init__.py +0 -0
  55. aiq/cli/cli_utils/config_override.py +231 -0
  56. aiq/cli/cli_utils/validation.py +37 -0
  57. aiq/cli/commands/__init__.py +0 -0
  58. aiq/cli/commands/configure/__init__.py +0 -0
  59. aiq/cli/commands/configure/channel/__init__.py +0 -0
  60. aiq/cli/commands/configure/channel/add.py +28 -0
  61. aiq/cli/commands/configure/channel/channel.py +36 -0
  62. aiq/cli/commands/configure/channel/remove.py +30 -0
  63. aiq/cli/commands/configure/channel/update.py +30 -0
  64. aiq/cli/commands/configure/configure.py +33 -0
  65. aiq/cli/commands/evaluate.py +139 -0
  66. aiq/cli/commands/info/__init__.py +14 -0
  67. aiq/cli/commands/info/info.py +39 -0
  68. aiq/cli/commands/info/list_channels.py +32 -0
  69. aiq/cli/commands/info/list_components.py +129 -0
  70. aiq/cli/commands/info/list_mcp.py +213 -0
  71. aiq/cli/commands/registry/__init__.py +14 -0
  72. aiq/cli/commands/registry/publish.py +88 -0
  73. aiq/cli/commands/registry/pull.py +118 -0
  74. aiq/cli/commands/registry/registry.py +38 -0
  75. aiq/cli/commands/registry/remove.py +108 -0
  76. aiq/cli/commands/registry/search.py +155 -0
  77. aiq/cli/commands/sizing/__init__.py +14 -0
  78. aiq/cli/commands/sizing/calc.py +297 -0
  79. aiq/cli/commands/sizing/sizing.py +27 -0
  80. aiq/cli/commands/start.py +246 -0
  81. aiq/cli/commands/uninstall.py +81 -0
  82. aiq/cli/commands/validate.py +47 -0
  83. aiq/cli/commands/workflow/__init__.py +14 -0
  84. aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
  85. aiq/cli/commands/workflow/templates/config.yml.j2 +16 -0
  86. aiq/cli/commands/workflow/templates/pyproject.toml.j2 +22 -0
  87. aiq/cli/commands/workflow/templates/register.py.j2 +5 -0
  88. aiq/cli/commands/workflow/templates/workflow.py.j2 +36 -0
  89. aiq/cli/commands/workflow/workflow.py +37 -0
  90. aiq/cli/commands/workflow/workflow_commands.py +313 -0
  91. aiq/cli/entrypoint.py +135 -0
  92. aiq/cli/main.py +44 -0
  93. aiq/cli/register_workflow.py +488 -0
  94. aiq/cli/type_registry.py +1000 -0
  95. aiq/data_models/__init__.py +14 -0
  96. aiq/data_models/api_server.py +694 -0
  97. aiq/data_models/authentication.py +231 -0
  98. aiq/data_models/common.py +171 -0
  99. aiq/data_models/component.py +54 -0
  100. aiq/data_models/component_ref.py +168 -0
  101. aiq/data_models/config.py +406 -0
  102. aiq/data_models/dataset_handler.py +123 -0
  103. aiq/data_models/discovery_metadata.py +335 -0
  104. aiq/data_models/embedder.py +27 -0
  105. aiq/data_models/evaluate.py +127 -0
  106. aiq/data_models/evaluator.py +26 -0
  107. aiq/data_models/front_end.py +26 -0
  108. aiq/data_models/function.py +30 -0
  109. aiq/data_models/function_dependencies.py +72 -0
  110. aiq/data_models/interactive.py +246 -0
  111. aiq/data_models/intermediate_step.py +302 -0
  112. aiq/data_models/invocation_node.py +38 -0
  113. aiq/data_models/llm.py +27 -0
  114. aiq/data_models/logging.py +26 -0
  115. aiq/data_models/memory.py +27 -0
  116. aiq/data_models/object_store.py +44 -0
  117. aiq/data_models/profiler.py +54 -0
  118. aiq/data_models/registry_handler.py +26 -0
  119. aiq/data_models/retriever.py +30 -0
  120. aiq/data_models/retry_mixin.py +35 -0
  121. aiq/data_models/span.py +187 -0
  122. aiq/data_models/step_adaptor.py +64 -0
  123. aiq/data_models/streaming.py +33 -0
  124. aiq/data_models/swe_bench_model.py +54 -0
  125. aiq/data_models/telemetry_exporter.py +26 -0
  126. aiq/data_models/ttc_strategy.py +30 -0
  127. aiq/embedder/__init__.py +0 -0
  128. aiq/embedder/langchain_client.py +41 -0
  129. aiq/embedder/nim_embedder.py +59 -0
  130. aiq/embedder/openai_embedder.py +43 -0
  131. aiq/embedder/register.py +24 -0
  132. aiq/eval/__init__.py +14 -0
  133. aiq/eval/config.py +60 -0
  134. aiq/eval/dataset_handler/__init__.py +0 -0
  135. aiq/eval/dataset_handler/dataset_downloader.py +106 -0
  136. aiq/eval/dataset_handler/dataset_filter.py +52 -0
  137. aiq/eval/dataset_handler/dataset_handler.py +254 -0
  138. aiq/eval/evaluate.py +506 -0
  139. aiq/eval/evaluator/__init__.py +14 -0
  140. aiq/eval/evaluator/base_evaluator.py +73 -0
  141. aiq/eval/evaluator/evaluator_model.py +45 -0
  142. aiq/eval/intermediate_step_adapter.py +99 -0
  143. aiq/eval/rag_evaluator/__init__.py +0 -0
  144. aiq/eval/rag_evaluator/evaluate.py +178 -0
  145. aiq/eval/rag_evaluator/register.py +143 -0
  146. aiq/eval/register.py +23 -0
  147. aiq/eval/remote_workflow.py +133 -0
  148. aiq/eval/runners/__init__.py +14 -0
  149. aiq/eval/runners/config.py +39 -0
  150. aiq/eval/runners/multi_eval_runner.py +54 -0
  151. aiq/eval/runtime_event_subscriber.py +52 -0
  152. aiq/eval/swe_bench_evaluator/__init__.py +0 -0
  153. aiq/eval/swe_bench_evaluator/evaluate.py +215 -0
  154. aiq/eval/swe_bench_evaluator/register.py +36 -0
  155. aiq/eval/trajectory_evaluator/__init__.py +0 -0
  156. aiq/eval/trajectory_evaluator/evaluate.py +75 -0
  157. aiq/eval/trajectory_evaluator/register.py +40 -0
  158. aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
  159. aiq/eval/tunable_rag_evaluator/evaluate.py +245 -0
  160. aiq/eval/tunable_rag_evaluator/register.py +52 -0
  161. aiq/eval/usage_stats.py +41 -0
  162. aiq/eval/utils/__init__.py +0 -0
  163. aiq/eval/utils/output_uploader.py +140 -0
  164. aiq/eval/utils/tqdm_position_registry.py +40 -0
  165. aiq/eval/utils/weave_eval.py +184 -0
  166. aiq/experimental/__init__.py +0 -0
  167. aiq/experimental/decorators/__init__.py +0 -0
  168. aiq/experimental/decorators/experimental_warning_decorator.py +130 -0
  169. aiq/experimental/test_time_compute/__init__.py +0 -0
  170. aiq/experimental/test_time_compute/editing/__init__.py +0 -0
  171. aiq/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +147 -0
  172. aiq/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +204 -0
  173. aiq/experimental/test_time_compute/editing/motivation_aware_summarization.py +107 -0
  174. aiq/experimental/test_time_compute/functions/__init__.py +0 -0
  175. aiq/experimental/test_time_compute/functions/execute_score_select_function.py +105 -0
  176. aiq/experimental/test_time_compute/functions/its_tool_orchestration_function.py +205 -0
  177. aiq/experimental/test_time_compute/functions/its_tool_wrapper_function.py +146 -0
  178. aiq/experimental/test_time_compute/functions/plan_select_execute_function.py +224 -0
  179. aiq/experimental/test_time_compute/models/__init__.py +0 -0
  180. aiq/experimental/test_time_compute/models/editor_config.py +132 -0
  181. aiq/experimental/test_time_compute/models/scoring_config.py +112 -0
  182. aiq/experimental/test_time_compute/models/search_config.py +120 -0
  183. aiq/experimental/test_time_compute/models/selection_config.py +154 -0
  184. aiq/experimental/test_time_compute/models/stage_enums.py +43 -0
  185. aiq/experimental/test_time_compute/models/strategy_base.py +66 -0
  186. aiq/experimental/test_time_compute/models/tool_use_config.py +41 -0
  187. aiq/experimental/test_time_compute/models/ttc_item.py +48 -0
  188. aiq/experimental/test_time_compute/register.py +36 -0
  189. aiq/experimental/test_time_compute/scoring/__init__.py +0 -0
  190. aiq/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +168 -0
  191. aiq/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +168 -0
  192. aiq/experimental/test_time_compute/scoring/motivation_aware_scorer.py +111 -0
  193. aiq/experimental/test_time_compute/search/__init__.py +0 -0
  194. aiq/experimental/test_time_compute/search/multi_llm_planner.py +128 -0
  195. aiq/experimental/test_time_compute/search/multi_query_retrieval_search.py +122 -0
  196. aiq/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +128 -0
  197. aiq/experimental/test_time_compute/selection/__init__.py +0 -0
  198. aiq/experimental/test_time_compute/selection/best_of_n_selector.py +63 -0
  199. aiq/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +131 -0
  200. aiq/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +159 -0
  201. aiq/experimental/test_time_compute/selection/llm_based_plan_selector.py +128 -0
  202. aiq/experimental/test_time_compute/selection/threshold_selector.py +58 -0
  203. aiq/front_ends/__init__.py +14 -0
  204. aiq/front_ends/console/__init__.py +14 -0
  205. aiq/front_ends/console/authentication_flow_handler.py +233 -0
  206. aiq/front_ends/console/console_front_end_config.py +32 -0
  207. aiq/front_ends/console/console_front_end_plugin.py +96 -0
  208. aiq/front_ends/console/register.py +25 -0
  209. aiq/front_ends/cron/__init__.py +14 -0
  210. aiq/front_ends/fastapi/__init__.py +14 -0
  211. aiq/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
  212. aiq/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +27 -0
  213. aiq/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +107 -0
  214. aiq/front_ends/fastapi/fastapi_front_end_config.py +234 -0
  215. aiq/front_ends/fastapi/fastapi_front_end_controller.py +68 -0
  216. aiq/front_ends/fastapi/fastapi_front_end_plugin.py +116 -0
  217. aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +1092 -0
  218. aiq/front_ends/fastapi/html_snippets/__init__.py +14 -0
  219. aiq/front_ends/fastapi/html_snippets/auth_code_grant_success.py +35 -0
  220. aiq/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
  221. aiq/front_ends/fastapi/job_store.py +183 -0
  222. aiq/front_ends/fastapi/main.py +72 -0
  223. aiq/front_ends/fastapi/message_handler.py +298 -0
  224. aiq/front_ends/fastapi/message_validator.py +345 -0
  225. aiq/front_ends/fastapi/register.py +25 -0
  226. aiq/front_ends/fastapi/response_helpers.py +195 -0
  227. aiq/front_ends/fastapi/step_adaptor.py +321 -0
  228. aiq/front_ends/mcp/__init__.py +14 -0
  229. aiq/front_ends/mcp/mcp_front_end_config.py +32 -0
  230. aiq/front_ends/mcp/mcp_front_end_plugin.py +93 -0
  231. aiq/front_ends/mcp/register.py +27 -0
  232. aiq/front_ends/mcp/tool_converter.py +242 -0
  233. aiq/front_ends/register.py +22 -0
  234. aiq/front_ends/simple_base/__init__.py +14 -0
  235. aiq/front_ends/simple_base/simple_front_end_plugin_base.py +54 -0
  236. aiq/llm/__init__.py +0 -0
  237. aiq/llm/aws_bedrock_llm.py +57 -0
  238. aiq/llm/nim_llm.py +46 -0
  239. aiq/llm/openai_llm.py +46 -0
  240. aiq/llm/register.py +23 -0
  241. aiq/llm/utils/__init__.py +14 -0
  242. aiq/llm/utils/env_config_value.py +94 -0
  243. aiq/llm/utils/error.py +17 -0
  244. aiq/memory/__init__.py +20 -0
  245. aiq/memory/interfaces.py +183 -0
  246. aiq/memory/models.py +112 -0
  247. aiq/meta/module_to_distro.json +3 -0
  248. aiq/meta/pypi.md +58 -0
  249. aiq/object_store/__init__.py +20 -0
  250. aiq/object_store/in_memory_object_store.py +76 -0
  251. aiq/object_store/interfaces.py +84 -0
  252. aiq/object_store/models.py +36 -0
  253. aiq/object_store/register.py +20 -0
  254. aiq/observability/__init__.py +14 -0
  255. aiq/observability/exporter/__init__.py +14 -0
  256. aiq/observability/exporter/base_exporter.py +449 -0
  257. aiq/observability/exporter/exporter.py +78 -0
  258. aiq/observability/exporter/file_exporter.py +33 -0
  259. aiq/observability/exporter/processing_exporter.py +322 -0
  260. aiq/observability/exporter/raw_exporter.py +52 -0
  261. aiq/observability/exporter/span_exporter.py +265 -0
  262. aiq/observability/exporter_manager.py +335 -0
  263. aiq/observability/mixin/__init__.py +14 -0
  264. aiq/observability/mixin/batch_config_mixin.py +26 -0
  265. aiq/observability/mixin/collector_config_mixin.py +23 -0
  266. aiq/observability/mixin/file_mixin.py +288 -0
  267. aiq/observability/mixin/file_mode.py +23 -0
  268. aiq/observability/mixin/resource_conflict_mixin.py +134 -0
  269. aiq/observability/mixin/serialize_mixin.py +61 -0
  270. aiq/observability/mixin/type_introspection_mixin.py +183 -0
  271. aiq/observability/processor/__init__.py +14 -0
  272. aiq/observability/processor/batching_processor.py +310 -0
  273. aiq/observability/processor/callback_processor.py +42 -0
  274. aiq/observability/processor/intermediate_step_serializer.py +28 -0
  275. aiq/observability/processor/processor.py +71 -0
  276. aiq/observability/register.py +96 -0
  277. aiq/observability/utils/__init__.py +14 -0
  278. aiq/observability/utils/dict_utils.py +236 -0
  279. aiq/observability/utils/time_utils.py +31 -0
  280. aiq/plugins/.namespace +1 -0
  281. aiq/profiler/__init__.py +0 -0
  282. aiq/profiler/calc/__init__.py +14 -0
  283. aiq/profiler/calc/calc_runner.py +627 -0
  284. aiq/profiler/calc/calculations.py +288 -0
  285. aiq/profiler/calc/data_models.py +188 -0
  286. aiq/profiler/calc/plot.py +345 -0
  287. aiq/profiler/callbacks/__init__.py +0 -0
  288. aiq/profiler/callbacks/agno_callback_handler.py +295 -0
  289. aiq/profiler/callbacks/base_callback_class.py +20 -0
  290. aiq/profiler/callbacks/langchain_callback_handler.py +290 -0
  291. aiq/profiler/callbacks/llama_index_callback_handler.py +205 -0
  292. aiq/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
  293. aiq/profiler/callbacks/token_usage_base_model.py +27 -0
  294. aiq/profiler/data_frame_row.py +51 -0
  295. aiq/profiler/data_models.py +24 -0
  296. aiq/profiler/decorators/__init__.py +0 -0
  297. aiq/profiler/decorators/framework_wrapper.py +131 -0
  298. aiq/profiler/decorators/function_tracking.py +254 -0
  299. aiq/profiler/forecasting/__init__.py +0 -0
  300. aiq/profiler/forecasting/config.py +18 -0
  301. aiq/profiler/forecasting/model_trainer.py +75 -0
  302. aiq/profiler/forecasting/models/__init__.py +22 -0
  303. aiq/profiler/forecasting/models/forecasting_base_model.py +40 -0
  304. aiq/profiler/forecasting/models/linear_model.py +196 -0
  305. aiq/profiler/forecasting/models/random_forest_regressor.py +268 -0
  306. aiq/profiler/inference_metrics_model.py +28 -0
  307. aiq/profiler/inference_optimization/__init__.py +0 -0
  308. aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
  309. aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +460 -0
  310. aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
  311. aiq/profiler/inference_optimization/data_models.py +386 -0
  312. aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
  313. aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
  314. aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +405 -0
  315. aiq/profiler/inference_optimization/llm_metrics.py +212 -0
  316. aiq/profiler/inference_optimization/prompt_caching.py +163 -0
  317. aiq/profiler/inference_optimization/token_uniqueness.py +107 -0
  318. aiq/profiler/inference_optimization/workflow_runtimes.py +72 -0
  319. aiq/profiler/intermediate_property_adapter.py +102 -0
  320. aiq/profiler/profile_runner.py +473 -0
  321. aiq/profiler/utils.py +184 -0
  322. aiq/registry_handlers/__init__.py +0 -0
  323. aiq/registry_handlers/local/__init__.py +0 -0
  324. aiq/registry_handlers/local/local_handler.py +176 -0
  325. aiq/registry_handlers/local/register_local.py +37 -0
  326. aiq/registry_handlers/metadata_factory.py +60 -0
  327. aiq/registry_handlers/package_utils.py +567 -0
  328. aiq/registry_handlers/pypi/__init__.py +0 -0
  329. aiq/registry_handlers/pypi/pypi_handler.py +251 -0
  330. aiq/registry_handlers/pypi/register_pypi.py +40 -0
  331. aiq/registry_handlers/register.py +21 -0
  332. aiq/registry_handlers/registry_handler_base.py +157 -0
  333. aiq/registry_handlers/rest/__init__.py +0 -0
  334. aiq/registry_handlers/rest/register_rest.py +56 -0
  335. aiq/registry_handlers/rest/rest_handler.py +237 -0
  336. aiq/registry_handlers/schemas/__init__.py +0 -0
  337. aiq/registry_handlers/schemas/headers.py +42 -0
  338. aiq/registry_handlers/schemas/package.py +68 -0
  339. aiq/registry_handlers/schemas/publish.py +63 -0
  340. aiq/registry_handlers/schemas/pull.py +82 -0
  341. aiq/registry_handlers/schemas/remove.py +36 -0
  342. aiq/registry_handlers/schemas/search.py +91 -0
  343. aiq/registry_handlers/schemas/status.py +47 -0
  344. aiq/retriever/__init__.py +0 -0
  345. aiq/retriever/interface.py +37 -0
  346. aiq/retriever/milvus/__init__.py +14 -0
  347. aiq/retriever/milvus/register.py +81 -0
  348. aiq/retriever/milvus/retriever.py +228 -0
  349. aiq/retriever/models.py +74 -0
  350. aiq/retriever/nemo_retriever/__init__.py +14 -0
  351. aiq/retriever/nemo_retriever/register.py +60 -0
  352. aiq/retriever/nemo_retriever/retriever.py +190 -0
  353. aiq/retriever/register.py +22 -0
  354. aiq/runtime/__init__.py +14 -0
  355. aiq/runtime/loader.py +215 -0
  356. aiq/runtime/runner.py +190 -0
  357. aiq/runtime/session.py +158 -0
  358. aiq/runtime/user_metadata.py +130 -0
  359. aiq/settings/__init__.py +0 -0
  360. aiq/settings/global_settings.py +318 -0
  361. aiq/test/.namespace +1 -0
  362. aiq/tool/__init__.py +0 -0
  363. aiq/tool/chat_completion.py +74 -0
  364. aiq/tool/code_execution/README.md +151 -0
  365. aiq/tool/code_execution/__init__.py +0 -0
  366. aiq/tool/code_execution/code_sandbox.py +267 -0
  367. aiq/tool/code_execution/local_sandbox/.gitignore +1 -0
  368. aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
  369. aiq/tool/code_execution/local_sandbox/__init__.py +13 -0
  370. aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +198 -0
  371. aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +6 -0
  372. aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +50 -0
  373. aiq/tool/code_execution/register.py +74 -0
  374. aiq/tool/code_execution/test_code_execution_sandbox.py +414 -0
  375. aiq/tool/code_execution/utils.py +100 -0
  376. aiq/tool/datetime_tools.py +42 -0
  377. aiq/tool/document_search.py +141 -0
  378. aiq/tool/github_tools/__init__.py +0 -0
  379. aiq/tool/github_tools/create_github_commit.py +133 -0
  380. aiq/tool/github_tools/create_github_issue.py +87 -0
  381. aiq/tool/github_tools/create_github_pr.py +106 -0
  382. aiq/tool/github_tools/get_github_file.py +106 -0
  383. aiq/tool/github_tools/get_github_issue.py +166 -0
  384. aiq/tool/github_tools/get_github_pr.py +256 -0
  385. aiq/tool/github_tools/update_github_issue.py +100 -0
  386. aiq/tool/mcp/__init__.py +14 -0
  387. aiq/tool/mcp/exceptions.py +142 -0
  388. aiq/tool/mcp/mcp_client.py +255 -0
  389. aiq/tool/mcp/mcp_tool.py +96 -0
  390. aiq/tool/memory_tools/__init__.py +0 -0
  391. aiq/tool/memory_tools/add_memory_tool.py +79 -0
  392. aiq/tool/memory_tools/delete_memory_tool.py +67 -0
  393. aiq/tool/memory_tools/get_memory_tool.py +72 -0
  394. aiq/tool/nvidia_rag.py +95 -0
  395. aiq/tool/register.py +38 -0
  396. aiq/tool/retriever.py +89 -0
  397. aiq/tool/server_tools.py +66 -0
  398. aiq/utils/__init__.py +0 -0
  399. aiq/utils/data_models/__init__.py +0 -0
  400. aiq/utils/data_models/schema_validator.py +58 -0
  401. aiq/utils/debugging_utils.py +43 -0
  402. aiq/utils/dump_distro_mapping.py +32 -0
  403. aiq/utils/exception_handlers/__init__.py +0 -0
  404. aiq/utils/exception_handlers/automatic_retries.py +289 -0
  405. aiq/utils/exception_handlers/mcp.py +211 -0
  406. aiq/utils/exception_handlers/schemas.py +114 -0
  407. aiq/utils/io/__init__.py +0 -0
  408. aiq/utils/io/model_processing.py +28 -0
  409. aiq/utils/io/yaml_tools.py +119 -0
  410. aiq/utils/log_utils.py +37 -0
  411. aiq/utils/metadata_utils.py +74 -0
  412. aiq/utils/optional_imports.py +142 -0
  413. aiq/utils/producer_consumer_queue.py +178 -0
  414. aiq/utils/reactive/__init__.py +0 -0
  415. aiq/utils/reactive/base/__init__.py +0 -0
  416. aiq/utils/reactive/base/observable_base.py +65 -0
  417. aiq/utils/reactive/base/observer_base.py +55 -0
  418. aiq/utils/reactive/base/subject_base.py +79 -0
  419. aiq/utils/reactive/observable.py +59 -0
  420. aiq/utils/reactive/observer.py +76 -0
  421. aiq/utils/reactive/subject.py +131 -0
  422. aiq/utils/reactive/subscription.py +49 -0
  423. aiq/utils/settings/__init__.py +0 -0
  424. aiq/utils/settings/global_settings.py +197 -0
  425. aiq/utils/string_utils.py +38 -0
  426. aiq/utils/type_converter.py +290 -0
  427. aiq/utils/type_utils.py +484 -0
  428. aiq/utils/url_utils.py +27 -0
  429. nvidia_nat-1.2.0rc5.dist-info/METADATA +363 -0
  430. nvidia_nat-1.2.0rc5.dist-info/RECORD +435 -0
  431. nvidia_nat-1.2.0rc5.dist-info/WHEEL +5 -0
  432. nvidia_nat-1.2.0rc5.dist-info/entry_points.txt +20 -0
  433. nvidia_nat-1.2.0rc5.dist-info/licenses/LICENSE-3rd-party.txt +3686 -0
  434. nvidia_nat-1.2.0rc5.dist-info/licenses/LICENSE.md +201 -0
  435. nvidia_nat-1.2.0rc5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,104 @@
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"
@@ -0,0 +1,41 @@
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
+ """
@@ -0,0 +1,149 @@
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
@@ -0,0 +1,225 @@
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 ADDED
@@ -0,0 +1,23 @@
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