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,161 @@
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 dataclasses
17
+ import logging
18
+ from contextlib import asynccontextmanager
19
+ from pathlib import Path
20
+
21
+ from aiq.builder.builder import EvalBuilder
22
+ from aiq.builder.evaluator import EvaluatorInfo
23
+ from aiq.builder.framework_enum import LLMFrameworkEnum
24
+ from aiq.builder.workflow_builder import WorkflowBuilder
25
+ from aiq.cli.type_registry import TypeRegistry
26
+ from aiq.data_models.config import AIQConfig
27
+ from aiq.data_models.config import GeneralConfig
28
+ from aiq.data_models.evaluate import EvalGeneralConfig
29
+ from aiq.data_models.evaluator import EvaluatorBaseConfig
30
+ from aiq.data_models.function import EmptyFunctionConfig
31
+ from aiq.utils.type_utils import override
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ @dataclasses.dataclass
37
+ class ConfiguredEvaluator:
38
+ config: EvaluatorBaseConfig
39
+ instance: EvaluatorInfo
40
+
41
+
42
+ class WorkflowEvalBuilder(WorkflowBuilder, EvalBuilder):
43
+
44
+ def __init__(self,
45
+ general_config: GeneralConfig | None = None,
46
+ eval_general_config: EvalGeneralConfig | None = None,
47
+ registry: TypeRegistry | None = None):
48
+ super().__init__(general_config=general_config, registry=registry)
49
+ self.eval_general_config = eval_general_config
50
+ self._evaluators: dict[str, ConfiguredEvaluator] = {}
51
+
52
+ @override
53
+ async def add_evaluator(self, name: str, config: EvaluatorBaseConfig):
54
+ if name in self._evaluators:
55
+ raise ValueError(f"Evaluator `{name}` already exists in the list of evaluators")
56
+
57
+ try:
58
+ evaluator_info = self._registry.get_evaluator(type(config))
59
+ info_obj = await self._get_exit_stack().enter_async_context(evaluator_info.build_fn(config, self))
60
+
61
+ # Store the evaluator
62
+ self._evaluators[name] = ConfiguredEvaluator(config=config, instance=info_obj)
63
+ except Exception as e:
64
+ logger.error("Error %s adding evaluator `%s` with config `%s`", e, name, config, exc_info=True)
65
+ raise
66
+
67
+ @override
68
+ def get_evaluator(self, evaluator_name: str) -> EvaluatorInfo:
69
+
70
+ if (evaluator_name not in self._evaluators):
71
+ raise ValueError(f"Evaluator `{evaluator_name}` not found")
72
+
73
+ return self._evaluators[evaluator_name].instance
74
+
75
+ @override
76
+ def get_evaluator_config(self, evaluator_name: str) -> EvaluatorBaseConfig:
77
+
78
+ if evaluator_name not in self._evaluators:
79
+ raise ValueError(f"Evaluator `{evaluator_name}` not found")
80
+
81
+ # Return the tool configuration object
82
+ return self._evaluators[evaluator_name].config
83
+
84
+ @override
85
+ def get_max_concurrency(self) -> int:
86
+ return self.eval_general_config.max_concurrency
87
+
88
+ @override
89
+ def get_output_dir(self) -> Path:
90
+ return self.eval_general_config.output_dir
91
+
92
+ @override
93
+ def get_all_tools(self, wrapper_type: LLMFrameworkEnum | str):
94
+ tools = []
95
+ tool_wrapper_reg = self._registry.get_tool_wrapper(llm_framework=wrapper_type)
96
+ for fn_name in self._functions:
97
+ fn = self.get_function(fn_name)
98
+ try:
99
+ tools.append(tool_wrapper_reg.build_fn(fn_name, fn, self))
100
+ except Exception:
101
+ logger.exception("Error fetching tool `%s`", fn_name, exc_info=True)
102
+
103
+ return tools
104
+
105
+ def _log_build_failure_evaluator(self,
106
+ failing_evaluator_name: str,
107
+ completed_evaluators: list[str],
108
+ remaining_evaluators: list[str],
109
+ original_error: Exception) -> None:
110
+ """
111
+ Log comprehensive evaluator build failure information.
112
+
113
+ Args:
114
+ failing_evaluator_name (str): The name of the evaluator that failed to build
115
+ completed_evaluators (list[str]): List of evaluator names that were successfully built
116
+ remaining_evaluators (list[str]): List of evaluator names still to be built
117
+ original_error (Exception): The original exception that caused the failure
118
+ """
119
+ # Convert evaluator names to (name, type) tuples for consistent logging
120
+ completed_components = [(name, "evaluator") for name in completed_evaluators]
121
+ remaining_components = [(name, "evaluator") for name in remaining_evaluators]
122
+
123
+ # Use the inherited common logging method from WorkflowBuilder
124
+ self._log_build_failure(failing_evaluator_name,
125
+ "evaluator",
126
+ completed_components,
127
+ remaining_components,
128
+ original_error)
129
+
130
+ async def populate_builder(self, config: AIQConfig):
131
+ # Skip setting workflow if workflow config is EmptyFunctionConfig
132
+ skip_workflow = isinstance(config.workflow, EmptyFunctionConfig)
133
+
134
+ await super().populate_builder(config, skip_workflow)
135
+
136
+ # Initialize progress tracking for evaluators
137
+ completed_evaluators = []
138
+ remaining_evaluators = list(config.eval.evaluators.keys())
139
+
140
+ # Instantiate the evaluators with enhanced error logging
141
+ for name, evaluator_config in config.eval.evaluators.items():
142
+ try:
143
+ # Remove from remaining as we start building
144
+ remaining_evaluators.remove(name)
145
+
146
+ await self.add_evaluator(name, evaluator_config)
147
+
148
+ # Add to completed after successful build
149
+ completed_evaluators.append(name)
150
+
151
+ except Exception as e:
152
+ self._log_build_failure_evaluator(name, completed_evaluators, remaining_evaluators, e)
153
+ raise
154
+
155
+ @classmethod
156
+ @asynccontextmanager
157
+ async def from_config(cls, config: AIQConfig):
158
+
159
+ async with cls(config.general, config.eval.general, registry=None) as builder:
160
+ await builder.populate_builder(config)
161
+ yield builder
@@ -0,0 +1,29 @@
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
+ from collections.abc import Callable
17
+
18
+ from aiq.data_models.evaluator import EvaluatorBaseConfig
19
+ from aiq.eval.evaluator.evaluator_model import EvalInput
20
+ from aiq.eval.evaluator.evaluator_model import EvalOutput
21
+
22
+
23
+ class EvaluatorInfo:
24
+
25
+ def __init__(self, *, config: EvaluatorBaseConfig, evaluate_fn: Callable[[EvalInput], EvalOutput],
26
+ description: str):
27
+ self.config = config
28
+ self.evaluate_fn = evaluate_fn
29
+ self.description = description
@@ -0,0 +1,24 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-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
+ from enum import Enum
17
+
18
+
19
+ class LLMFrameworkEnum(str, Enum):
20
+ LANGCHAIN = "langchain"
21
+ LLAMA_INDEX = "llama_index"
22
+ CREWAI = "crewai"
23
+ SEMANTIC_KERNEL = "semantic_kernel"
24
+ AGNO = "agno"
@@ -0,0 +1,73 @@
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 typing
17
+ from abc import ABC
18
+ from abc import abstractmethod
19
+
20
+ from aiq.data_models.front_end import FrontEndConfigT
21
+
22
+ if (typing.TYPE_CHECKING):
23
+ from aiq.data_models.config import AIQConfig
24
+
25
+
26
+ class FrontEndBase(typing.Generic[FrontEndConfigT], ABC):
27
+
28
+ def __init__(self, full_config: "AIQConfig"):
29
+ """
30
+ Initializes the FrontEndBase object with the specified AIQ Toolkit configuration.
31
+
32
+ Parameters
33
+ ----------
34
+ full_config : AIQConfig
35
+ The configuration object to use for the front end.
36
+ """
37
+
38
+ super().__init__()
39
+
40
+ self._full_config: "AIQConfig" = full_config
41
+ self._front_end_config: FrontEndConfigT = typing.cast(FrontEndConfigT, full_config.general.front_end)
42
+
43
+ @property
44
+ def front_end_config(self) -> FrontEndConfigT:
45
+ """
46
+ Returns the front end configuration object extracted from the AIQ Toolkit configuration.
47
+
48
+ Returns
49
+ -------
50
+ FrontEndConfigT
51
+ The front end configuration object.
52
+ """
53
+ return self._front_end_config
54
+
55
+ @property
56
+ def full_config(self) -> "AIQConfig":
57
+ """
58
+ Returns the full AIQ Toolkit configuration object.
59
+
60
+ Returns
61
+ -------
62
+ AIQConfig
63
+ The full AIQ Toolkit configuration object.
64
+ """
65
+
66
+ return self._full_config
67
+
68
+ @abstractmethod
69
+ async def run(self):
70
+ """
71
+ Runs the specified configuration file, launching the workflow until the front end is complete.
72
+ """
73
+ pass
@@ -0,0 +1,344 @@
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 typing
18
+ from abc import ABC
19
+ from abc import abstractmethod
20
+ from collections.abc import AsyncGenerator
21
+ from collections.abc import Awaitable
22
+ from collections.abc import Callable
23
+
24
+ from pydantic import BaseModel
25
+
26
+ from aiq.builder.context import AIQContext
27
+ from aiq.builder.function_base import FunctionBase
28
+ from aiq.builder.function_base import InputT
29
+ from aiq.builder.function_base import SingleOutputT
30
+ from aiq.builder.function_base import StreamingOutputT
31
+ from aiq.builder.function_info import FunctionInfo
32
+ from aiq.data_models.function import FunctionBaseConfig
33
+
34
+ _InvokeFnT = Callable[[InputT], Awaitable[SingleOutputT]]
35
+ _StreamFnT = Callable[[InputT], AsyncGenerator[StreamingOutputT]]
36
+
37
+ _T = typing.TypeVar("_T")
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+
42
+ class Function(FunctionBase[InputT, StreamingOutputT, SingleOutputT], ABC):
43
+
44
+ def __init__(self,
45
+ *,
46
+ config: FunctionBaseConfig,
47
+ description: str | None,
48
+ input_schema: type[BaseModel] | None = None,
49
+ streaming_output_schema: type[BaseModel] | type[None] | None = None,
50
+ single_output_schema: type[BaseModel] | type[None] | None = None,
51
+ converters: list[Callable[[typing.Any], typing.Any]] | None = None,
52
+ instance_name: str | None = None):
53
+
54
+ super().__init__(input_schema=input_schema,
55
+ streaming_output_schema=streaming_output_schema,
56
+ single_output_schema=single_output_schema,
57
+ converters=converters)
58
+
59
+ self.config = config
60
+ self.description = description
61
+ self.instance_name = instance_name or config.type
62
+ self._context = AIQContext.get()
63
+
64
+ def convert(self, value: typing.Any, to_type: type[_T]) -> _T:
65
+ """
66
+ Converts the given value to the specified type using the function's converter.
67
+
68
+ Parameters
69
+ ----------
70
+ value : typing.Any
71
+ The value to convert.
72
+ to_type : type
73
+ The type to convert the value to.
74
+
75
+ Returns
76
+ -------
77
+ _T
78
+ The converted value.
79
+
80
+ Raises
81
+ ------
82
+ ValueError
83
+ If the value cannot be converted to the specified type (when `to_type` is specified).
84
+ """
85
+
86
+ return self._converter.convert(value, to_type=to_type)
87
+
88
+ def try_convert(self, value: typing.Any, to_type: type[_T]) -> _T | typing.Any:
89
+ """
90
+ Converts the given value to the specified type using graceful error handling.
91
+ If conversion fails, returns the original value and continues processing.
92
+
93
+ Parameters
94
+ ----------
95
+ value : typing.Any
96
+ The value to convert.
97
+ to_type : type
98
+ The type to convert the value to.
99
+
100
+ Returns
101
+ -------
102
+ _T | typing.Any
103
+ The converted value, or original value if conversion fails.
104
+ """
105
+ return self._converter.try_convert(value, to_type=to_type)
106
+
107
+ @abstractmethod
108
+ async def _ainvoke(self, value: InputT) -> SingleOutputT:
109
+ pass
110
+
111
+ @typing.overload
112
+ async def ainvoke(self, value: InputT | typing.Any) -> SingleOutputT:
113
+ ...
114
+
115
+ @typing.overload
116
+ async def ainvoke(self, value: InputT | typing.Any, to_type: type[_T]) -> _T:
117
+ ...
118
+
119
+ @typing.final
120
+ async def ainvoke(self, value: InputT | typing.Any, to_type: type | None = None):
121
+ """
122
+ Runs the function with the given input and returns a single output from the function. This is the
123
+ main entry point for running a function.
124
+
125
+ Parameters
126
+ ----------
127
+ value : InputT | typing.Any
128
+ The input to the function.
129
+ to_type : type | None, optional
130
+ The type to convert the output to using the function's converter. When not specified, the
131
+ output will match `single_output_type`.
132
+
133
+ Returns
134
+ -------
135
+ typing.Any
136
+ The output of the function optionally converted to the specified type.
137
+
138
+ Raises
139
+ ------
140
+ ValueError
141
+ If the output of the function cannot be converted to the specified type.
142
+ """
143
+
144
+ with self._context.push_active_function(self.instance_name,
145
+ input_data=value) as manager: # Set the current invocation context
146
+ try:
147
+ converted_input: InputT = self._convert_input(value)
148
+
149
+ result = await self._ainvoke(converted_input)
150
+
151
+ if to_type is not None and not isinstance(result, to_type):
152
+ result = self.convert(result, to_type)
153
+
154
+ manager.set_output(result)
155
+
156
+ return result
157
+ except Exception as e:
158
+ logger.error("Error with ainvoke in function with input: %s.", value, exc_info=True)
159
+ raise e
160
+
161
+ @typing.final
162
+ async def acall_invoke(self, *args, **kwargs):
163
+ """
164
+ A wrapper around `ainvoke` that allows for calling the function with arbitrary arguments and keyword arguments.
165
+ This is useful in scenarios where the function might be called by an LLM or other system which gives varying
166
+ inputs to the function. The function will attempt to convert the args and kwargs to the input schema of the
167
+ function.
168
+
169
+ Returns
170
+ -------
171
+ SingleOutputT
172
+ The output of the function.
173
+ """
174
+
175
+ if (len(args) == 1 and not kwargs):
176
+ # If only one argument is passed, assume it is the input just like ainvoke
177
+ return await self.ainvoke(value=args[0])
178
+
179
+ if (not args and kwargs):
180
+ # If only kwargs are passed, assume we are calling a function with named arguments in a dict
181
+ # This will rely on the processing in ainvoke to convert from dict to the correct input type
182
+ return await self.ainvoke(value=kwargs)
183
+
184
+ # Possibly have both args and kwargs, final attempt is to use the input schema object constructor.
185
+ try:
186
+ input_obj = self.input_schema(*args, **kwargs)
187
+
188
+ return await self.ainvoke(value=input_obj)
189
+ except Exception as e:
190
+ logger.error(
191
+ "Error in acall_invoke() converting input to function schema. Both args and kwargs were "
192
+ "supplied which could not be converted to the input schema. args: %s\nkwargs: %s\nschema: %s",
193
+ args,
194
+ kwargs,
195
+ self.input_schema)
196
+ raise e
197
+
198
+ @abstractmethod
199
+ async def _astream(self, value: InputT) -> AsyncGenerator[StreamingOutputT]:
200
+ yield # type: ignore
201
+
202
+ @typing.overload
203
+ async def astream(self, value: InputT | typing.Any) -> AsyncGenerator[SingleOutputT]:
204
+ ...
205
+
206
+ @typing.overload
207
+ async def astream(self, value: InputT | typing.Any, to_type: type[_T]) -> AsyncGenerator[_T]:
208
+ ...
209
+
210
+ @typing.final
211
+ async def astream(self, value: InputT | typing.Any, to_type: type | None = None):
212
+ """
213
+ Runs the function with the given input and returns a stream of outputs from the function. This is the main entry
214
+ point for running a function with streaming output.
215
+
216
+ Parameters
217
+ ----------
218
+ value : InputT | typing.Any
219
+ The input to the function.
220
+ to_type : type | None, optional
221
+ The type to convert the output to using the function's converter. When not specified, the
222
+ output will match `streaming_output_type`.
223
+
224
+ Yields
225
+ ------
226
+ typing.Any
227
+ The output of the function optionally converted to the specified type.
228
+
229
+ Raises
230
+ ------
231
+ ValueError
232
+ If the output of the function cannot be converted to the specified type (when `to_type` is specified).
233
+ """
234
+
235
+ with self._context.push_active_function(self.instance_name, input_data=value) as manager:
236
+ try:
237
+ converted_input: InputT = self._convert_input(value)
238
+
239
+ # Collect streaming outputs to capture the final result
240
+ final_output: list[typing.Any] = []
241
+
242
+ async for data in self._astream(converted_input):
243
+ if to_type is not None and not isinstance(data, to_type):
244
+ converted_data = self.convert(data, to_type=to_type)
245
+ final_output.append(converted_data)
246
+ yield converted_data
247
+ else:
248
+ final_output.append(data)
249
+ yield data
250
+
251
+ # Set the final output for intermediate step tracking
252
+ manager.set_output(final_output)
253
+
254
+ except Exception as e:
255
+ logger.error("Error with astream in function with input: %s.", value, exc_info=True)
256
+ raise e
257
+
258
+ @typing.final
259
+ async def acall_stream(self, *args, **kwargs):
260
+ """
261
+ A wrapper around `astream` that allows for calling the function with arbitrary arguments and keyword arguments.
262
+ This is useful in scenarios where the function might be called by an LLM or other system which gives varying
263
+ inputs to the function. The function will attempt to convert the args and kwargs to the input schema of the
264
+ function.
265
+
266
+ Yields
267
+ ------
268
+ StreamingOutputT
269
+ The output of the function.
270
+ """
271
+
272
+ if (len(args) == 1 and not kwargs):
273
+ # If only one argument is passed, assume it is the input just like ainvoke
274
+ async for x in self.astream(value=args[0]):
275
+ yield x
276
+
277
+ elif (not args and kwargs):
278
+ # If only kwargs are passed, assume we are calling a function with named arguments in a dict
279
+ # This will rely on the processing in ainvoke to convert from dict to the correct input type
280
+ async for x in self.astream(value=kwargs):
281
+ yield x
282
+
283
+ # Possibly have both args and kwargs, final attempt is to use the input schema object constructor.
284
+ else:
285
+ try:
286
+ input_obj = self.input_schema(*args, **kwargs)
287
+
288
+ async for x in self.astream(value=input_obj):
289
+ yield x
290
+ except Exception as e:
291
+ logger.error(
292
+ "Error in acall_stream() converting input to function schema. Both args and kwargs were "
293
+ "supplied which could not be converted to the input schema. args: %s\nkwargs: %s\nschema: %s",
294
+ args,
295
+ kwargs,
296
+ self.input_schema)
297
+ raise e
298
+
299
+
300
+ class LambdaFunction(Function[InputT, StreamingOutputT, SingleOutputT]):
301
+
302
+ def __init__(self, *, config: FunctionBaseConfig, info: FunctionInfo, instance_name: str | None = None):
303
+
304
+ super().__init__(config=config,
305
+ description=info.description,
306
+ input_schema=info.input_schema,
307
+ streaming_output_schema=info.stream_output_schema,
308
+ single_output_schema=info.single_output_schema,
309
+ converters=info.converters,
310
+ instance_name=instance_name)
311
+
312
+ self._info = info
313
+ self._ainvoke_fn: _InvokeFnT = info.single_fn
314
+ self._astream_fn: _StreamFnT = info.stream_fn
315
+
316
+ @property
317
+ def has_streaming_output(self) -> bool:
318
+ return self._astream_fn is not None
319
+
320
+ @property
321
+ def has_single_output(self) -> bool:
322
+ return self._ainvoke_fn is not None
323
+
324
+ async def _ainvoke(self, value: InputT) -> SingleOutputT:
325
+ return await self._ainvoke_fn(value)
326
+
327
+ async def _astream(self, value: InputT) -> AsyncGenerator[StreamingOutputT]:
328
+ async for x in self._astream_fn(value):
329
+ yield x
330
+
331
+ @staticmethod
332
+ def from_info(*,
333
+ config: FunctionBaseConfig,
334
+ info: FunctionInfo,
335
+ instance_name: str | None = None) -> 'LambdaFunction[InputT, StreamingOutputT, SingleOutputT]':
336
+
337
+ input_type: type = info.input_type
338
+ streaming_output_type = info.stream_output_type
339
+ single_output_type = info.single_output_type
340
+
341
+ class FunctionImpl(LambdaFunction[input_type, streaming_output_type, single_output_type]):
342
+ pass
343
+
344
+ return FunctionImpl(config=config, info=info, instance_name=instance_name)