nvidia-nat 1.4.0a20251112__py3-none-any.whl → 1.4.0a20260113__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 (492) hide show
  1. aiq/__init__.py +1 -1
  2. nat/{front_ends/mcp → agent/auto_memory_wrapper}/__init__.py +1 -1
  3. nat/agent/auto_memory_wrapper/agent.py +278 -0
  4. nat/agent/auto_memory_wrapper/register.py +227 -0
  5. nat/agent/auto_memory_wrapper/state.py +30 -0
  6. nat/agent/base.py +1 -1
  7. nat/agent/dual_node.py +1 -1
  8. nat/agent/prompt_optimizer/prompt.py +1 -1
  9. nat/agent/prompt_optimizer/register.py +1 -1
  10. nat/agent/react_agent/agent.py +16 -9
  11. nat/agent/react_agent/output_parser.py +2 -2
  12. nat/agent/react_agent/prompt.py +3 -2
  13. nat/agent/react_agent/register.py +2 -2
  14. nat/agent/react_agent/register_per_user_agent.py +104 -0
  15. nat/agent/reasoning_agent/reasoning_agent.py +1 -1
  16. nat/agent/register.py +3 -1
  17. nat/agent/responses_api_agent/__init__.py +1 -1
  18. nat/agent/responses_api_agent/register.py +1 -1
  19. nat/agent/rewoo_agent/agent.py +9 -4
  20. nat/agent/rewoo_agent/prompt.py +1 -1
  21. nat/agent/rewoo_agent/register.py +1 -1
  22. nat/agent/tool_calling_agent/agent.py +5 -4
  23. nat/agent/tool_calling_agent/register.py +1 -1
  24. nat/authentication/__init__.py +1 -1
  25. nat/authentication/api_key/__init__.py +1 -1
  26. nat/authentication/api_key/api_key_auth_provider.py +1 -1
  27. nat/authentication/api_key/api_key_auth_provider_config.py +22 -7
  28. nat/authentication/api_key/register.py +1 -1
  29. nat/authentication/credential_validator/__init__.py +1 -1
  30. nat/authentication/credential_validator/bearer_token_validator.py +1 -1
  31. nat/authentication/exceptions/__init__.py +1 -1
  32. nat/authentication/exceptions/api_key_exceptions.py +1 -1
  33. nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
  34. nat/authentication/http_basic_auth/register.py +1 -1
  35. nat/authentication/interfaces.py +1 -1
  36. nat/authentication/oauth2/__init__.py +1 -1
  37. nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +1 -1
  38. nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +1 -1
  39. nat/authentication/oauth2/oauth2_resource_server_config.py +1 -1
  40. nat/authentication/oauth2/register.py +1 -1
  41. nat/authentication/register.py +1 -1
  42. nat/builder/builder.py +563 -1
  43. nat/builder/child_builder.py +385 -0
  44. nat/builder/component_utils.py +34 -4
  45. nat/builder/context.py +34 -1
  46. nat/builder/embedder.py +1 -1
  47. nat/builder/eval_builder.py +19 -7
  48. nat/builder/evaluator.py +1 -1
  49. nat/builder/framework_enum.py +3 -1
  50. nat/builder/front_end.py +1 -1
  51. nat/builder/function.py +113 -5
  52. nat/builder/function_base.py +1 -1
  53. nat/builder/function_info.py +1 -1
  54. nat/builder/intermediate_step_manager.py +1 -1
  55. nat/builder/llm.py +1 -1
  56. nat/builder/per_user_workflow_builder.py +843 -0
  57. nat/builder/retriever.py +1 -1
  58. nat/builder/sync_builder.py +571 -0
  59. nat/builder/user_interaction_manager.py +1 -1
  60. nat/builder/workflow.py +5 -3
  61. nat/builder/workflow_builder.py +619 -378
  62. nat/cli/__init__.py +1 -1
  63. nat/cli/cli_utils/config_override.py +1 -1
  64. nat/cli/cli_utils/validation.py +32 -1
  65. nat/cli/commands/configure/channel/add.py +1 -1
  66. nat/cli/commands/configure/channel/channel.py +1 -1
  67. nat/cli/commands/configure/channel/remove.py +1 -1
  68. nat/cli/commands/configure/channel/update.py +1 -1
  69. nat/cli/commands/configure/configure.py +1 -1
  70. nat/cli/commands/evaluate.py +87 -13
  71. nat/cli/commands/finetune.py +132 -0
  72. nat/cli/commands/info/__init__.py +1 -1
  73. nat/cli/commands/info/info.py +1 -1
  74. nat/cli/commands/info/list_channels.py +1 -1
  75. nat/cli/commands/info/list_components.py +1 -1
  76. nat/cli/commands/object_store/__init__.py +1 -1
  77. nat/cli/commands/object_store/object_store.py +1 -1
  78. nat/cli/commands/optimize.py +1 -1
  79. nat/cli/commands/{mcp → red_teaming}/__init__.py +1 -1
  80. nat/cli/commands/red_teaming/red_teaming.py +138 -0
  81. nat/cli/commands/red_teaming/red_teaming_utils.py +73 -0
  82. nat/cli/commands/registry/__init__.py +1 -1
  83. nat/cli/commands/registry/publish.py +1 -1
  84. nat/cli/commands/registry/pull.py +1 -1
  85. nat/cli/commands/registry/registry.py +1 -1
  86. nat/cli/commands/registry/remove.py +1 -1
  87. nat/cli/commands/registry/search.py +1 -1
  88. nat/cli/commands/sizing/__init__.py +1 -1
  89. nat/cli/commands/sizing/calc.py +1 -1
  90. nat/cli/commands/sizing/sizing.py +1 -1
  91. nat/cli/commands/start.py +1 -1
  92. nat/cli/commands/uninstall.py +1 -1
  93. nat/cli/commands/validate.py +1 -1
  94. nat/cli/commands/workflow/__init__.py +1 -1
  95. nat/cli/commands/workflow/workflow.py +1 -1
  96. nat/cli/commands/workflow/workflow_commands.py +3 -2
  97. nat/cli/entrypoint.py +15 -37
  98. nat/cli/main.py +2 -2
  99. nat/cli/plugin_loader.py +69 -0
  100. nat/cli/register_workflow.py +233 -5
  101. nat/cli/type_registry.py +237 -3
  102. nat/control_flow/register.py +1 -1
  103. nat/control_flow/router_agent/agent.py +1 -1
  104. nat/control_flow/router_agent/prompt.py +1 -1
  105. nat/control_flow/router_agent/register.py +1 -1
  106. nat/control_flow/sequential_executor.py +28 -7
  107. nat/data_models/__init__.py +1 -1
  108. nat/data_models/agent.py +1 -1
  109. nat/data_models/api_server.py +38 -3
  110. nat/data_models/authentication.py +1 -1
  111. nat/data_models/common.py +1 -1
  112. nat/data_models/component.py +9 -1
  113. nat/data_models/component_ref.py +45 -1
  114. nat/data_models/config.py +78 -1
  115. nat/data_models/dataset_handler.py +15 -2
  116. nat/data_models/discovery_metadata.py +1 -1
  117. nat/data_models/embedder.py +1 -1
  118. nat/data_models/evaluate.py +6 -1
  119. nat/data_models/evaluator.py +1 -1
  120. nat/data_models/finetuning.py +260 -0
  121. nat/data_models/front_end.py +1 -1
  122. nat/data_models/function.py +15 -2
  123. nat/data_models/function_dependencies.py +1 -1
  124. nat/data_models/gated_field_mixin.py +1 -1
  125. nat/data_models/interactive.py +1 -1
  126. nat/data_models/intermediate_step.py +29 -2
  127. nat/data_models/invocation_node.py +1 -1
  128. nat/data_models/llm.py +1 -1
  129. nat/data_models/logging.py +1 -1
  130. nat/data_models/memory.py +1 -1
  131. nat/data_models/middleware.py +37 -0
  132. nat/data_models/object_store.py +1 -1
  133. nat/data_models/openai_mcp.py +1 -1
  134. nat/data_models/optimizable.py +1 -1
  135. nat/data_models/optimizer.py +1 -1
  136. nat/data_models/profiler.py +1 -1
  137. nat/data_models/registry_handler.py +1 -1
  138. nat/data_models/retriever.py +1 -1
  139. nat/data_models/retry_mixin.py +1 -1
  140. nat/data_models/runtime_enum.py +26 -0
  141. nat/data_models/span.py +1 -1
  142. nat/data_models/step_adaptor.py +1 -1
  143. nat/data_models/streaming.py +1 -1
  144. nat/data_models/swe_bench_model.py +1 -1
  145. nat/data_models/telemetry_exporter.py +1 -1
  146. nat/data_models/thinking_mixin.py +1 -1
  147. nat/data_models/ttc_strategy.py +1 -1
  148. nat/embedder/azure_openai_embedder.py +1 -1
  149. nat/embedder/nim_embedder.py +1 -1
  150. nat/embedder/openai_embedder.py +1 -1
  151. nat/embedder/register.py +1 -1
  152. nat/eval/__init__.py +1 -1
  153. nat/eval/config.py +8 -1
  154. nat/eval/dataset_handler/dataset_downloader.py +1 -1
  155. nat/eval/dataset_handler/dataset_filter.py +1 -1
  156. nat/eval/dataset_handler/dataset_handler.py +4 -2
  157. nat/eval/evaluate.py +226 -81
  158. nat/eval/evaluator/__init__.py +1 -1
  159. nat/eval/evaluator/base_evaluator.py +2 -2
  160. nat/eval/evaluator/evaluator_model.py +3 -2
  161. nat/eval/intermediate_step_adapter.py +1 -1
  162. nat/eval/llm_validator.py +336 -0
  163. nat/eval/rag_evaluator/evaluate.py +17 -10
  164. nat/eval/rag_evaluator/register.py +1 -1
  165. nat/eval/red_teaming_evaluator/__init__.py +14 -0
  166. nat/eval/red_teaming_evaluator/data_models.py +66 -0
  167. nat/eval/red_teaming_evaluator/evaluate.py +327 -0
  168. nat/eval/red_teaming_evaluator/filter_conditions.py +75 -0
  169. nat/eval/red_teaming_evaluator/register.py +55 -0
  170. nat/eval/register.py +2 -1
  171. nat/eval/remote_workflow.py +1 -1
  172. nat/eval/runners/__init__.py +1 -1
  173. nat/eval/runners/config.py +1 -1
  174. nat/eval/runners/multi_eval_runner.py +1 -1
  175. nat/eval/runners/red_teaming_runner/__init__.py +24 -0
  176. nat/eval/runners/red_teaming_runner/config.py +282 -0
  177. nat/eval/runners/red_teaming_runner/report_utils.py +707 -0
  178. nat/eval/runners/red_teaming_runner/runner.py +867 -0
  179. nat/eval/runtime_evaluator/__init__.py +1 -1
  180. nat/eval/runtime_evaluator/evaluate.py +1 -1
  181. nat/eval/runtime_evaluator/register.py +1 -1
  182. nat/eval/runtime_event_subscriber.py +1 -1
  183. nat/eval/swe_bench_evaluator/evaluate.py +1 -1
  184. nat/eval/swe_bench_evaluator/register.py +1 -1
  185. nat/eval/trajectory_evaluator/evaluate.py +2 -2
  186. nat/eval/trajectory_evaluator/register.py +1 -1
  187. nat/eval/tunable_rag_evaluator/evaluate.py +5 -5
  188. nat/eval/tunable_rag_evaluator/register.py +1 -1
  189. nat/eval/usage_stats.py +1 -1
  190. nat/eval/utils/eval_trace_ctx.py +1 -1
  191. nat/eval/utils/output_uploader.py +1 -1
  192. nat/eval/utils/tqdm_position_registry.py +1 -1
  193. nat/eval/utils/weave_eval.py +1 -1
  194. nat/experimental/decorators/experimental_warning_decorator.py +1 -1
  195. nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +1 -1
  196. nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +1 -1
  197. nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +1 -1
  198. nat/experimental/test_time_compute/functions/execute_score_select_function.py +1 -1
  199. nat/experimental/test_time_compute/functions/multi_llm_judge_function.py +88 -0
  200. nat/experimental/test_time_compute/functions/plan_select_execute_function.py +1 -1
  201. nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +1 -1
  202. nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
  203. nat/experimental/test_time_compute/models/editor_config.py +1 -1
  204. nat/experimental/test_time_compute/models/scoring_config.py +1 -1
  205. nat/experimental/test_time_compute/models/search_config.py +20 -2
  206. nat/experimental/test_time_compute/models/selection_config.py +33 -2
  207. nat/experimental/test_time_compute/models/stage_enums.py +1 -1
  208. nat/experimental/test_time_compute/models/strategy_base.py +1 -1
  209. nat/experimental/test_time_compute/models/tool_use_config.py +1 -1
  210. nat/experimental/test_time_compute/models/ttc_item.py +1 -1
  211. nat/experimental/test_time_compute/register.py +4 -1
  212. nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +1 -1
  213. nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +1 -1
  214. nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +1 -1
  215. nat/experimental/test_time_compute/search/multi_llm_generation.py +115 -0
  216. nat/experimental/test_time_compute/search/multi_llm_planner.py +1 -1
  217. nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +1 -1
  218. nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +1 -1
  219. nat/experimental/test_time_compute/selection/best_of_n_selector.py +1 -1
  220. nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +1 -1
  221. nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -1
  222. nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +1 -1
  223. nat/experimental/test_time_compute/selection/llm_judge_selection.py +127 -0
  224. nat/experimental/test_time_compute/selection/threshold_selector.py +1 -1
  225. nat/finetuning/__init__.py +24 -0
  226. nat/finetuning/finetuning_runtime.py +143 -0
  227. nat/finetuning/interfaces/__init__.py +24 -0
  228. nat/finetuning/interfaces/finetuning_runner.py +261 -0
  229. nat/finetuning/interfaces/trainer_adapter.py +103 -0
  230. nat/finetuning/interfaces/trajectory_builder.py +115 -0
  231. nat/finetuning/utils/__init__.py +15 -0
  232. nat/finetuning/utils/parsers/__init__.py +15 -0
  233. nat/finetuning/utils/parsers/adk_parser.py +141 -0
  234. nat/finetuning/utils/parsers/base_parser.py +238 -0
  235. nat/finetuning/utils/parsers/common.py +91 -0
  236. nat/finetuning/utils/parsers/langchain_parser.py +267 -0
  237. nat/finetuning/utils/parsers/llama_index_parser.py +218 -0
  238. nat/front_ends/__init__.py +1 -1
  239. nat/front_ends/console/__init__.py +1 -1
  240. nat/front_ends/console/authentication_flow_handler.py +1 -1
  241. nat/front_ends/console/console_front_end_config.py +4 -1
  242. nat/front_ends/console/console_front_end_plugin.py +5 -4
  243. nat/front_ends/console/register.py +1 -1
  244. nat/front_ends/cron/__init__.py +1 -1
  245. nat/front_ends/fastapi/__init__.py +1 -1
  246. nat/front_ends/fastapi/async_job.py +128 -0
  247. nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +1 -1
  248. nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +13 -9
  249. nat/front_ends/fastapi/dask_client_mixin.py +1 -1
  250. nat/front_ends/fastapi/fastapi_front_end_config.py +23 -1
  251. nat/front_ends/fastapi/fastapi_front_end_controller.py +1 -1
  252. nat/front_ends/fastapi/fastapi_front_end_plugin.py +25 -30
  253. nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +318 -59
  254. nat/front_ends/fastapi/html_snippets/__init__.py +1 -1
  255. nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +1 -1
  256. nat/front_ends/fastapi/intermediate_steps_subscriber.py +12 -1
  257. nat/front_ends/fastapi/job_store.py +23 -11
  258. nat/front_ends/fastapi/main.py +1 -1
  259. nat/front_ends/fastapi/message_handler.py +27 -4
  260. nat/front_ends/fastapi/message_validator.py +54 -2
  261. nat/front_ends/fastapi/register.py +1 -1
  262. nat/front_ends/fastapi/response_helpers.py +16 -15
  263. nat/front_ends/fastapi/step_adaptor.py +1 -1
  264. nat/front_ends/fastapi/utils.py +1 -1
  265. nat/front_ends/register.py +1 -2
  266. nat/front_ends/simple_base/__init__.py +1 -1
  267. nat/front_ends/simple_base/simple_front_end_plugin_base.py +6 -4
  268. nat/llm/aws_bedrock_llm.py +1 -1
  269. nat/llm/azure_openai_llm.py +10 -1
  270. nat/llm/dynamo_llm.py +363 -0
  271. nat/llm/huggingface_llm.py +177 -0
  272. nat/llm/litellm_llm.py +1 -1
  273. nat/llm/nim_llm.py +1 -1
  274. nat/llm/openai_llm.py +1 -1
  275. nat/llm/register.py +3 -1
  276. nat/llm/utils/__init__.py +1 -1
  277. nat/llm/utils/env_config_value.py +1 -1
  278. nat/llm/utils/error.py +1 -1
  279. nat/llm/utils/thinking.py +1 -1
  280. nat/memory/__init__.py +1 -1
  281. nat/memory/interfaces.py +1 -1
  282. nat/memory/models.py +1 -1
  283. nat/meta/pypi.md +1 -1
  284. nat/middleware/__init__.py +35 -0
  285. nat/middleware/cache/__init__.py +14 -0
  286. nat/middleware/cache/cache_middleware.py +253 -0
  287. nat/middleware/cache/cache_middleware_config.py +44 -0
  288. nat/middleware/cache/register.py +33 -0
  289. nat/middleware/defense/__init__.py +14 -0
  290. nat/middleware/defense/defense_middleware.py +362 -0
  291. nat/middleware/defense/defense_middleware_content_guard.py +455 -0
  292. nat/middleware/defense/defense_middleware_data_models.py +91 -0
  293. nat/middleware/defense/defense_middleware_output_verifier.py +440 -0
  294. nat/middleware/defense/defense_middleware_pii.py +356 -0
  295. nat/middleware/defense/register.py +82 -0
  296. nat/middleware/dynamic/__init__.py +14 -0
  297. nat/middleware/dynamic/dynamic_function_middleware.py +962 -0
  298. nat/middleware/dynamic/dynamic_middleware_config.py +132 -0
  299. nat/middleware/dynamic/register.py +34 -0
  300. nat/middleware/function_middleware.py +370 -0
  301. nat/middleware/logging/__init__.py +14 -0
  302. nat/middleware/logging/logging_middleware.py +67 -0
  303. nat/middleware/logging/logging_middleware_config.py +28 -0
  304. nat/middleware/logging/register.py +33 -0
  305. nat/middleware/middleware.py +298 -0
  306. nat/middleware/red_teaming/__init__.py +14 -0
  307. nat/middleware/red_teaming/red_teaming_middleware.py +344 -0
  308. nat/middleware/red_teaming/red_teaming_middleware_config.py +112 -0
  309. nat/middleware/red_teaming/register.py +47 -0
  310. nat/middleware/register.py +22 -0
  311. nat/middleware/utils/__init__.py +14 -0
  312. nat/middleware/utils/workflow_inventory.py +155 -0
  313. nat/object_store/__init__.py +1 -1
  314. nat/object_store/in_memory_object_store.py +1 -1
  315. nat/object_store/interfaces.py +1 -1
  316. nat/object_store/models.py +1 -1
  317. nat/object_store/register.py +1 -1
  318. nat/observability/__init__.py +1 -1
  319. nat/observability/exporter/__init__.py +1 -1
  320. nat/observability/exporter/base_exporter.py +1 -1
  321. nat/observability/exporter/exporter.py +1 -1
  322. nat/observability/exporter/file_exporter.py +1 -1
  323. nat/observability/exporter/processing_exporter.py +1 -1
  324. nat/observability/exporter/raw_exporter.py +1 -1
  325. nat/observability/exporter/span_exporter.py +7 -1
  326. nat/observability/exporter_manager.py +1 -1
  327. nat/observability/mixin/__init__.py +1 -1
  328. nat/observability/mixin/batch_config_mixin.py +1 -1
  329. nat/observability/mixin/collector_config_mixin.py +1 -1
  330. nat/observability/mixin/file_mixin.py +1 -1
  331. nat/observability/mixin/file_mode.py +1 -1
  332. nat/observability/mixin/redaction_config_mixin.py +1 -1
  333. nat/observability/mixin/resource_conflict_mixin.py +1 -1
  334. nat/observability/mixin/serialize_mixin.py +1 -1
  335. nat/observability/mixin/tagging_config_mixin.py +1 -1
  336. nat/observability/mixin/type_introspection_mixin.py +1 -1
  337. nat/observability/processor/__init__.py +1 -1
  338. nat/observability/processor/batching_processor.py +1 -1
  339. nat/observability/processor/callback_processor.py +1 -1
  340. nat/observability/processor/falsy_batch_filter_processor.py +1 -1
  341. nat/observability/processor/intermediate_step_serializer.py +1 -1
  342. nat/observability/processor/processor.py +1 -1
  343. nat/observability/processor/processor_factory.py +1 -1
  344. nat/observability/processor/redaction/__init__.py +1 -1
  345. nat/observability/processor/redaction/contextual_redaction_processor.py +1 -1
  346. nat/observability/processor/redaction/contextual_span_redaction_processor.py +1 -1
  347. nat/observability/processor/redaction/redaction_processor.py +1 -1
  348. nat/observability/processor/redaction/span_header_redaction_processor.py +1 -1
  349. nat/observability/processor/span_tagging_processor.py +1 -1
  350. nat/observability/register.py +1 -1
  351. nat/observability/utils/__init__.py +1 -1
  352. nat/observability/utils/dict_utils.py +1 -1
  353. nat/observability/utils/time_utils.py +1 -1
  354. nat/profiler/calc/__init__.py +1 -1
  355. nat/profiler/calc/calc_runner.py +3 -3
  356. nat/profiler/calc/calculations.py +1 -1
  357. nat/profiler/calc/data_models.py +1 -1
  358. nat/profiler/calc/plot.py +30 -3
  359. nat/profiler/callbacks/agno_callback_handler.py +1 -1
  360. nat/profiler/callbacks/base_callback_class.py +1 -1
  361. nat/profiler/callbacks/langchain_callback_handler.py +33 -3
  362. nat/profiler/callbacks/llama_index_callback_handler.py +13 -10
  363. nat/profiler/callbacks/semantic_kernel_callback_handler.py +1 -1
  364. nat/profiler/callbacks/token_usage_base_model.py +1 -1
  365. nat/profiler/data_frame_row.py +1 -1
  366. nat/profiler/data_models.py +1 -1
  367. nat/profiler/decorators/framework_wrapper.py +32 -1
  368. nat/profiler/decorators/function_tracking.py +1 -1
  369. nat/profiler/forecasting/config.py +1 -1
  370. nat/profiler/forecasting/model_trainer.py +1 -1
  371. nat/profiler/forecasting/models/__init__.py +1 -1
  372. nat/profiler/forecasting/models/forecasting_base_model.py +1 -1
  373. nat/profiler/forecasting/models/linear_model.py +1 -1
  374. nat/profiler/forecasting/models/random_forest_regressor.py +1 -1
  375. nat/profiler/inference_metrics_model.py +1 -1
  376. nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +1 -1
  377. nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
  378. nat/profiler/inference_optimization/data_models.py +1 -1
  379. nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +1 -1
  380. nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +1 -1
  381. nat/profiler/inference_optimization/llm_metrics.py +1 -1
  382. nat/profiler/inference_optimization/prompt_caching.py +1 -1
  383. nat/profiler/inference_optimization/token_uniqueness.py +1 -1
  384. nat/profiler/inference_optimization/workflow_runtimes.py +1 -1
  385. nat/profiler/intermediate_property_adapter.py +1 -1
  386. nat/profiler/parameter_optimization/optimizable_utils.py +1 -1
  387. nat/profiler/parameter_optimization/optimizer_runtime.py +1 -1
  388. nat/profiler/parameter_optimization/parameter_optimizer.py +1 -1
  389. nat/profiler/parameter_optimization/parameter_selection.py +1 -1
  390. nat/profiler/parameter_optimization/pareto_visualizer.py +1 -1
  391. nat/profiler/parameter_optimization/prompt_optimizer.py +1 -1
  392. nat/profiler/parameter_optimization/update_helpers.py +1 -1
  393. nat/profiler/profile_runner.py +1 -1
  394. nat/profiler/utils.py +1 -1
  395. nat/registry_handlers/local/local_handler.py +1 -1
  396. nat/registry_handlers/local/register_local.py +1 -1
  397. nat/registry_handlers/metadata_factory.py +1 -1
  398. nat/registry_handlers/package_utils.py +1 -1
  399. nat/registry_handlers/pypi/pypi_handler.py +1 -1
  400. nat/registry_handlers/pypi/register_pypi.py +1 -1
  401. nat/registry_handlers/register.py +1 -1
  402. nat/registry_handlers/registry_handler_base.py +1 -1
  403. nat/registry_handlers/rest/register_rest.py +1 -1
  404. nat/registry_handlers/rest/rest_handler.py +1 -1
  405. nat/registry_handlers/schemas/headers.py +1 -1
  406. nat/registry_handlers/schemas/package.py +1 -1
  407. nat/registry_handlers/schemas/publish.py +1 -1
  408. nat/registry_handlers/schemas/pull.py +1 -1
  409. nat/registry_handlers/schemas/remove.py +1 -1
  410. nat/registry_handlers/schemas/search.py +1 -1
  411. nat/registry_handlers/schemas/status.py +1 -1
  412. nat/retriever/interface.py +1 -1
  413. nat/retriever/milvus/__init__.py +1 -1
  414. nat/retriever/milvus/register.py +12 -4
  415. nat/retriever/milvus/retriever.py +103 -41
  416. nat/retriever/models.py +1 -1
  417. nat/retriever/nemo_retriever/__init__.py +1 -1
  418. nat/retriever/nemo_retriever/register.py +1 -1
  419. nat/retriever/nemo_retriever/retriever.py +5 -5
  420. nat/retriever/register.py +1 -1
  421. nat/runtime/__init__.py +1 -1
  422. nat/runtime/loader.py +10 -3
  423. nat/runtime/metrics.py +180 -0
  424. nat/runtime/runner.py +13 -6
  425. nat/runtime/session.py +458 -32
  426. nat/runtime/user_metadata.py +1 -1
  427. nat/settings/global_settings.py +1 -1
  428. nat/tool/chat_completion.py +1 -1
  429. nat/tool/code_execution/README.md +1 -1
  430. nat/tool/code_execution/code_sandbox.py +2 -2
  431. nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +1 -1
  432. nat/tool/code_execution/local_sandbox/__init__.py +1 -1
  433. nat/tool/code_execution/local_sandbox/local_sandbox_server.py +1 -1
  434. nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +1 -1
  435. nat/tool/code_execution/register.py +1 -1
  436. nat/tool/code_execution/utils.py +1 -1
  437. nat/tool/datetime_tools.py +1 -1
  438. nat/tool/document_search.py +1 -1
  439. nat/tool/github_tools.py +1 -1
  440. nat/tool/memory_tools/add_memory_tool.py +1 -1
  441. nat/tool/memory_tools/delete_memory_tool.py +1 -1
  442. nat/tool/memory_tools/get_memory_tool.py +1 -1
  443. nat/tool/nvidia_rag.py +2 -2
  444. nat/tool/register.py +1 -1
  445. nat/tool/retriever.py +1 -1
  446. nat/tool/server_tools.py +1 -1
  447. nat/utils/__init__.py +8 -5
  448. nat/utils/callable_utils.py +1 -1
  449. nat/utils/data_models/schema_validator.py +1 -1
  450. nat/utils/debugging_utils.py +1 -1
  451. nat/utils/decorators.py +1 -1
  452. nat/utils/dump_distro_mapping.py +1 -1
  453. nat/utils/exception_handlers/automatic_retries.py +3 -3
  454. nat/utils/exception_handlers/schemas.py +1 -1
  455. nat/utils/io/model_processing.py +1 -1
  456. nat/utils/io/supress_logs.py +33 -0
  457. nat/utils/io/yaml_tools.py +1 -1
  458. nat/utils/log_levels.py +1 -1
  459. nat/utils/log_utils.py +13 -1
  460. nat/utils/metadata_utils.py +1 -1
  461. nat/utils/optional_imports.py +1 -1
  462. nat/utils/producer_consumer_queue.py +1 -1
  463. nat/utils/reactive/base/observable_base.py +1 -1
  464. nat/utils/reactive/base/observer_base.py +1 -1
  465. nat/utils/reactive/base/subject_base.py +1 -1
  466. nat/utils/reactive/observable.py +1 -1
  467. nat/utils/reactive/observer.py +1 -1
  468. nat/utils/reactive/subject.py +1 -1
  469. nat/utils/reactive/subscription.py +1 -1
  470. nat/utils/responses_api.py +1 -1
  471. nat/utils/settings/global_settings.py +1 -1
  472. nat/utils/string_utils.py +1 -1
  473. nat/utils/type_converter.py +18 -5
  474. nat/utils/type_utils.py +1 -1
  475. nat/utils/url_utils.py +1 -1
  476. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/METADATA +46 -15
  477. nvidia_nat-1.4.0a20260113.dist-info/RECORD +547 -0
  478. nvidia_nat-1.4.0a20260113.dist-info/entry_points.txt +38 -0
  479. nat/cli/commands/mcp/mcp.py +0 -986
  480. nat/front_ends/mcp/introspection_token_verifier.py +0 -73
  481. nat/front_ends/mcp/mcp_front_end_config.py +0 -109
  482. nat/front_ends/mcp/mcp_front_end_plugin.py +0 -151
  483. nat/front_ends/mcp/mcp_front_end_plugin_worker.py +0 -362
  484. nat/front_ends/mcp/memory_profiler.py +0 -320
  485. nat/front_ends/mcp/register.py +0 -27
  486. nat/front_ends/mcp/tool_converter.py +0 -321
  487. nvidia_nat-1.4.0a20251112.dist-info/RECORD +0 -481
  488. nvidia_nat-1.4.0a20251112.dist-info/entry_points.txt +0 -22
  489. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/WHEEL +0 -0
  490. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
  491. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE.md +0 -0
  492. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -48,6 +48,7 @@ class MilvusRetrieverConfig(RetrieverBaseConfig, name="milvus_retriever"):
48
48
  description: str | None = Field(default=None,
49
49
  description="If present it will be used as the tool description",
50
50
  alias="collection_description")
51
+ use_async_client: bool = Field(default=False, description="Use AsyncMilvusClient for async I/O operations. ")
51
52
 
52
53
 
53
54
  @register_retriever_provider(config_type=MilvusRetrieverConfig)
@@ -58,13 +59,20 @@ async def milvus_retriever(retriever_config: MilvusRetrieverConfig, builder: Bui
58
59
 
59
60
  @register_retriever_client(config_type=MilvusRetrieverConfig, wrapper_type=None)
60
61
  async def milvus_retriever_client(config: MilvusRetrieverConfig, builder: Builder):
61
- from pymilvus import MilvusClient
62
-
63
62
  from nat.retriever.milvus.retriever import MilvusRetriever
64
63
 
65
64
  embedder = await builder.get_embedder(embedder_name=config.embedding_model, wrapper_type=LLMFrameworkEnum.LANGCHAIN)
66
65
 
67
- milvus_client = MilvusClient(uri=str(config.uri), **config.connection_args)
66
+ # Create Milvus client based on use_async_client flag
67
+ if config.use_async_client:
68
+ from pymilvus import AsyncMilvusClient
69
+
70
+ milvus_client = AsyncMilvusClient(uri=str(config.uri), **config.connection_args)
71
+ else:
72
+ from pymilvus import MilvusClient
73
+
74
+ milvus_client = MilvusClient(uri=str(config.uri), **config.connection_args)
75
+
68
76
  retriever = MilvusRetriever(
69
77
  client=milvus_client,
70
78
  embedder=embedder,
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,13 +13,18 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ import inspect
16
17
  import logging
17
18
  from functools import partial
19
+ from typing import TYPE_CHECKING
18
20
 
19
21
  from langchain_core.embeddings import Embeddings
20
- from pymilvus import MilvusClient
21
22
  from pymilvus.client.abstract import Hit
22
23
 
24
+ if TYPE_CHECKING:
25
+ from pymilvus import AsyncMilvusClient
26
+ from pymilvus import MilvusClient
27
+
23
28
  from nat.retriever.interface import Retriever
24
29
  from nat.retriever.models import Document
25
30
  from nat.retriever.models import RetrieverError
@@ -39,20 +44,27 @@ class MilvusRetriever(Retriever):
39
44
 
40
45
  def __init__(
41
46
  self,
42
- client: MilvusClient,
47
+ client: "MilvusClient | AsyncMilvusClient",
43
48
  embedder: Embeddings,
44
49
  content_field: str = "text",
45
50
  use_iterator: bool = False,
46
51
  ) -> None:
47
52
  """
48
- Initialize the Milvus Retriever using a preconfigured MilvusClient
53
+ Initialize the Milvus Retriever using a preconfigured MilvusClient or AsyncMilvusClient
49
54
 
50
55
  Args:
51
- client (MilvusClient): Preinstantiate pymilvus.MilvusClient object.
52
56
  """
53
- self._client = client
57
+ self._client: MilvusClient | AsyncMilvusClient = client
54
58
  self._embedder = embedder
55
59
 
60
+ # Detect if client is async by inspecting method capabilities
61
+ search_method = getattr(client, "search", None)
62
+ list_collections_method = getattr(client, "list_collections", None)
63
+ self._is_async = any(
64
+ inspect.iscoroutinefunction(method) for method in (search_method, list_collections_method)
65
+ if method is not None)
66
+ logger.info("Initialized Milvus Retriever with %s client", "async" if self._is_async else "sync")
67
+
56
68
  if use_iterator and "search_iterator" not in dir(self._client):
57
69
  raise ValueError("This version of the pymilvus.MilvusClient does not support the search iterator.")
58
70
 
@@ -60,7 +72,7 @@ class MilvusRetriever(Retriever):
60
72
  self._default_params = None
61
73
  self._bound_params = []
62
74
  self.content_field = content_field
63
- logger.info("Mivlus Retriever using %s for search.", self._search_func.__name__)
75
+ logger.info("Milvus Retriever using %s for search.", self._search_func.__name__)
64
76
 
65
77
  def bind(self, **kwargs) -> None:
66
78
  """
@@ -81,8 +93,13 @@ class MilvusRetriever(Retriever):
81
93
  """
82
94
  return [param for param in ["query", "collection_name", "top_k", "filters"] if param not in self._bound_params]
83
95
 
84
- def _validate_collection(self, collection_name: str) -> bool:
85
- return collection_name in self._client.list_collections()
96
+ async def _validate_collection(self, collection_name: str) -> bool:
97
+ """Validate that a collection exists."""
98
+ if self._is_async:
99
+ collections = await self._client.list_collections()
100
+ else:
101
+ collections = self._client.list_collections()
102
+ return collection_name in collections
86
103
 
87
104
  async def search(self, query: str, **kwargs):
88
105
  return await self._search_func(query=query, **kwargs)
@@ -108,39 +125,64 @@ class MilvusRetriever(Retriever):
108
125
  collection_name,
109
126
  top_k)
110
127
 
111
- if not self._validate_collection(collection_name):
128
+ if not await self._validate_collection(collection_name):
112
129
  raise CollectionNotFoundError(f"Collection: {collection_name} does not exist")
113
130
 
114
131
  # If no output fields are specified, return all of them
115
132
  if not output_fields:
116
- collection_schema = self._client.describe_collection(collection_name)
133
+ if self._is_async:
134
+ collection_schema = await self._client.describe_collection(collection_name)
135
+ else:
136
+ collection_schema = self._client.describe_collection(collection_name)
117
137
  output_fields = [
118
138
  field["name"] for field in collection_schema.get("fields") if field["name"] != vector_field_name
119
139
  ]
120
140
 
121
- search_vector = self._embedder.embed_query(query)
122
-
123
- search_iterator = self._client.search_iterator(
124
- collection_name=collection_name,
125
- data=[search_vector],
126
- batch_size=kwargs.get("batch_size", 1000),
127
- filter=filters,
128
- limit=top_k,
129
- output_fields=output_fields,
130
- search_params=search_params if search_params else {"metric_type": "L2"},
131
- timeout=timeout,
132
- anns_field=vector_field_name,
133
- round_decimal=kwargs.get("round_decimal", -1),
134
- partition_names=kwargs.get("partition_names", None),
135
- )
141
+ search_vector = await self._embedder.aembed_query(query)
142
+
143
+ # Create search iterator
144
+ if self._is_async:
145
+ search_iterator = await self._client.search_iterator(
146
+ collection_name=collection_name,
147
+ data=[search_vector],
148
+ batch_size=kwargs.get("batch_size", 1000),
149
+ filter=filters,
150
+ limit=top_k,
151
+ output_fields=output_fields,
152
+ search_params=search_params if search_params else {"metric_type": "L2"},
153
+ timeout=timeout,
154
+ anns_field=vector_field_name,
155
+ round_decimal=kwargs.get("round_decimal", -1),
156
+ partition_names=kwargs.get("partition_names", None),
157
+ )
158
+ else:
159
+ search_iterator = self._client.search_iterator(
160
+ collection_name=collection_name,
161
+ data=[search_vector],
162
+ batch_size=kwargs.get("batch_size", 1000),
163
+ filter=filters,
164
+ limit=top_k,
165
+ output_fields=output_fields,
166
+ search_params=search_params if search_params else {"metric_type": "L2"},
167
+ timeout=timeout,
168
+ anns_field=vector_field_name,
169
+ round_decimal=kwargs.get("round_decimal", -1),
170
+ partition_names=kwargs.get("partition_names", None),
171
+ )
136
172
 
137
173
  results = []
138
174
  try:
139
175
  while True:
140
- _res = search_iterator.next()
176
+ if self._is_async:
177
+ _res = await search_iterator.next()
178
+ else:
179
+ _res = search_iterator.next()
141
180
  res = _res.get_res()
142
181
  if len(_res) == 0:
143
- search_iterator.close()
182
+ if self._is_async:
183
+ await search_iterator.close()
184
+ else:
185
+ search_iterator.close()
144
186
  break
145
187
 
146
188
  if distance_cutoff and res[0][-1].distance > distance_cutoff:
@@ -176,10 +218,16 @@ class MilvusRetriever(Retriever):
176
218
  collection_name,
177
219
  top_k)
178
220
 
179
- if not self._validate_collection(collection_name):
221
+ if not await self._validate_collection(collection_name):
180
222
  raise CollectionNotFoundError(f"Collection: {collection_name} does not exist")
181
223
 
182
- available_fields = [v.get("name") for v in self._client.describe_collection(collection_name).get("fields", {})]
224
+ # Get collection schema
225
+ if self._is_async:
226
+ collection_schema = await self._client.describe_collection(collection_name)
227
+ else:
228
+ collection_schema = self._client.describe_collection(collection_name)
229
+
230
+ available_fields = [v.get("name") for v in collection_schema.get("fields", [])]
183
231
 
184
232
  if self.content_field not in available_fields:
185
233
  raise ValueError(f"The specified content field: {self.content_field} is not part of the schema.")
@@ -194,17 +242,31 @@ class MilvusRetriever(Retriever):
194
242
  if self.content_field not in output_fields:
195
243
  output_fields.append(self.content_field)
196
244
 
197
- search_vector = self._embedder.embed_query(query)
198
- res = self._client.search(
199
- collection_name=collection_name,
200
- data=[search_vector],
201
- filter=filters,
202
- output_fields=output_fields,
203
- search_params=search_params if search_params else {"metric_type": "L2"},
204
- timeout=timeout,
205
- anns_field=vector_field_name,
206
- limit=top_k,
207
- )
245
+ search_vector = await self._embedder.aembed_query(query)
246
+
247
+ # Perform search
248
+ if self._is_async:
249
+ res = await self._client.search(
250
+ collection_name=collection_name,
251
+ data=[search_vector],
252
+ filter=filters,
253
+ output_fields=output_fields,
254
+ search_params=search_params if search_params else {"metric_type": "L2"},
255
+ timeout=timeout,
256
+ anns_field=vector_field_name,
257
+ limit=top_k,
258
+ )
259
+ else:
260
+ res = self._client.search(
261
+ collection_name=collection_name,
262
+ data=[search_vector],
263
+ filter=filters,
264
+ output_fields=output_fields,
265
+ search_params=search_params if search_params else {"metric_type": "L2"},
266
+ timeout=timeout,
267
+ anns_field=vector_field_name,
268
+ limit=top_k,
269
+ )
208
270
 
209
271
  return _wrap_milvus_results(res[0], content_field=self.content_field)
210
272
 
nat/retriever/models.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -68,10 +68,10 @@ class NemoRetriever(Retriever):
68
68
 
69
69
  def bind(self, **kwargs) -> None:
70
70
  """
71
- Bind default values to the search method. Cannot bind the 'query' parameter.
71
+ Bind default values to the search method. Cannot bind the ``query`` parameter.
72
72
 
73
73
  Args:
74
- kwargs (dict): Key value pairs corresponding to the default values of search parameters.
74
+ kwargs: Key value pairs corresponding to the default values of search parameters.
75
75
  """
76
76
  if "query" in kwargs:
77
77
  kwargs = {k: v for k, v in kwargs.items() if k != "query"}
@@ -87,7 +87,7 @@ class NemoRetriever(Retriever):
87
87
 
88
88
  async def get_collections(self, client) -> list[Collection]:
89
89
  """
90
- Get a list of all available collections as pydantic `Collection` objects
90
+ Get a list of all available collections as pydantic Collection objects.
91
91
  """
92
92
  collection_response = await client.get(urljoin(self.base_url, "/v1/collections"))
93
93
  collection_response.raise_for_status()
@@ -102,7 +102,7 @@ class NemoRetriever(Retriever):
102
102
 
103
103
  async def get_collection_by_name(self, collection_name, client) -> Collection:
104
104
  """
105
- Retrieve a collection using it's name. Will return the first collection found if the name is ambiguous.
105
+ Retrieve a collection using its name. Will return the first collection found if the name is ambiguous.
106
106
  """
107
107
  collections = await self.get_collections(client)
108
108
  if (collection := next((c for c in collections if c.name == collection_name), None)) is None:
nat/retriever/register.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
nat/runtime/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
nat/runtime/loader.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -112,9 +112,16 @@ async def load_workflow(config_file: StrPath, max_concurrency: int = -1):
112
112
  config = load_config(config_file)
113
113
 
114
114
  # Must yield the workflow function otherwise it cleans up
115
- async with WorkflowBuilder.from_config(config=config) as workflow:
115
+ async with WorkflowBuilder.from_config(config=config) as builder:
116
116
 
117
- yield SessionManager(await workflow.build(), max_concurrency=max_concurrency)
117
+ session_manager = await SessionManager.create(config=config,
118
+ shared_builder=builder,
119
+ max_concurrency=max_concurrency)
120
+
121
+ try:
122
+ yield session_manager
123
+ finally:
124
+ await session_manager.shutdown()
118
125
 
119
126
 
120
127
  @lru_cache
nat/runtime/metrics.py ADDED
@@ -0,0 +1,180 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, 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
+ """Per-user workflow resource usage monitoring models and collector."""
16
+
17
+ from __future__ import annotations
18
+
19
+ import logging
20
+ from datetime import datetime
21
+ from typing import TYPE_CHECKING
22
+
23
+ from pydantic import BaseModel
24
+ from pydantic import Field
25
+
26
+ if TYPE_CHECKING:
27
+ from nat.runtime.session import SessionManager
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class PerUserSessionMetrics(BaseModel):
33
+ """Session lifecycle metrics for a per-user workflow."""
34
+
35
+ created_at: datetime = Field(description="When the per-user workflow was created")
36
+ last_activity: datetime = Field(description="Last time the workflow was accessed")
37
+ ref_count: int = Field(ge=0, description="Current number of active references (in-flight requests)")
38
+ is_active: bool = Field(description="Whether the workflow is currently being used")
39
+
40
+
41
+ class PerUserRequestMetrics(BaseModel):
42
+ """Request-level metrics for a per-user workflow."""
43
+
44
+ total_requests: int = Field(ge=0, default=0, description="Total number of requests processed")
45
+ active_requests: int = Field(ge=0, default=0, description="Number of currently active requests")
46
+ avg_latency_ms: float = Field(ge=0, default=0.0, description="Average request latency in milliseconds")
47
+ error_count: int = Field(ge=0, default=0, description="Total number of failed requests")
48
+
49
+
50
+ class PerUserMemoryMetrics(BaseModel):
51
+ """Memory/resource count metrics for a per-user workflow."""
52
+
53
+ per_user_functions_count: int = Field(ge=0, default=0, description="Number of per-user functions built")
54
+ per_user_function_groups_count: int = Field(ge=0, default=0, description="Number of per-user function groups built")
55
+ exit_stack_size: int = Field(ge=0, default=0, description="Number of resources in the async exit stack")
56
+
57
+
58
+ class PerUserResourceUsage(BaseModel):
59
+ """Combined resource usage metrics for a single per-user workflow."""
60
+
61
+ user_id: str = Field(description="The user identifier")
62
+ session: PerUserSessionMetrics = Field(description="Session lifecycle metrics")
63
+ requests: PerUserRequestMetrics = Field(description="Request-level metrics")
64
+ memory: PerUserMemoryMetrics = Field(description="Memory/resource count metrics")
65
+
66
+
67
+ class PerUserMonitorResponse(BaseModel):
68
+ """Response model for the /monitor/users endpoint."""
69
+
70
+ timestamp: datetime = Field(default_factory=datetime.now, description="When the metrics were collected")
71
+ total_active_users: int = Field(ge=0, description="Number of users with active per-user workflows")
72
+ users: list[PerUserResourceUsage] = Field(default_factory=list, description="Per-user resource usage details")
73
+
74
+
75
+ class PerUserMetricsCollector:
76
+ """Collector for per-user workflow metrics.
77
+
78
+ This class aggregates metrics from SessionManager's per-user builders
79
+ and provides methods to collect metrics for individual users or all users.
80
+ """
81
+
82
+ def __init__(self, session_manager: SessionManager):
83
+ """Initialize the collector with a SessionManager reference.
84
+
85
+ Args:
86
+ session_manager: The SessionManager instance to collect metrics from
87
+ """
88
+ self._session_manager = session_manager
89
+
90
+ async def collect_user_metrics(self, user_id: str) -> PerUserResourceUsage | None:
91
+ """Collect metrics for a specific user.
92
+
93
+ Args:
94
+ user_id: The user identifier to collect metrics for
95
+
96
+ Returns:
97
+ PerUserResourceUsage if user exists, None otherwise
98
+ """
99
+ async with self._session_manager._per_user_builders_lock:
100
+ if user_id not in self._session_manager._per_user_builders:
101
+ return None
102
+
103
+ builder_info = self._session_manager._per_user_builders[user_id]
104
+ return self._build_user_metrics(user_id, builder_info)
105
+
106
+ async def collect_all_metrics(self) -> PerUserMonitorResponse:
107
+ """Collect metrics for all active per-user workflows.
108
+
109
+ Returns:
110
+ PerUserMonitorResponse with all user metrics
111
+ """
112
+ users: list[PerUserResourceUsage] = []
113
+
114
+ async with self._session_manager._per_user_builders_lock:
115
+ for user_id, builder_info in self._session_manager._per_user_builders.items():
116
+ try:
117
+ user_metrics = self._build_user_metrics(user_id, builder_info)
118
+ users.append(user_metrics)
119
+ except Exception:
120
+ logger.exception("Failed to collect metrics for user %s", user_id)
121
+
122
+ return PerUserMonitorResponse(
123
+ timestamp=datetime.now(),
124
+ total_active_users=len(users),
125
+ users=users,
126
+ )
127
+
128
+ def _build_user_metrics(self, user_id: str, builder_info) -> PerUserResourceUsage:
129
+ """Build metrics for a single user from builder info.
130
+
131
+ Args:
132
+ user_id: The user identifier
133
+ builder_info: The PerUserBuilderInfo instance
134
+
135
+ Returns:
136
+ PerUserResourceUsage with all metrics
137
+ """
138
+ # Session metrics
139
+ session_metrics = PerUserSessionMetrics(
140
+ created_at=builder_info.created_at,
141
+ last_activity=builder_info.last_activity,
142
+ ref_count=builder_info.ref_count,
143
+ is_active=builder_info.ref_count > 0,
144
+ )
145
+
146
+ # Request metrics
147
+ avg_latency = (builder_info.total_latency_ms /
148
+ builder_info.total_requests if builder_info.total_requests > 0 else 0.0)
149
+
150
+ request_metrics = PerUserRequestMetrics(
151
+ total_requests=builder_info.total_requests,
152
+ active_requests=builder_info.ref_count,
153
+ avg_latency_ms=round(avg_latency, 2),
154
+ error_count=builder_info.error_count,
155
+ )
156
+
157
+ # Memory/resource count metrics from the builder
158
+ builder = builder_info.builder
159
+ per_user_functions_count = len(builder._per_user_functions)
160
+ per_user_function_groups_count = len(builder._per_user_function_groups)
161
+
162
+ # Count resources in exit stack (if accessible)
163
+ exit_stack = getattr(builder, '_exit_stack', None)
164
+ if exit_stack and hasattr(exit_stack, '_exit_callbacks'):
165
+ exit_stack_size = len(exit_stack._exit_callbacks)
166
+ else:
167
+ exit_stack_size = 0
168
+
169
+ memory_metrics = PerUserMemoryMetrics(
170
+ per_user_functions_count=per_user_functions_count,
171
+ per_user_function_groups_count=per_user_function_groups_count,
172
+ exit_stack_size=exit_stack_size,
173
+ )
174
+
175
+ return PerUserResourceUsage(
176
+ user_id=user_id,
177
+ session=session_metrics,
178
+ requests=request_metrics,
179
+ memory=memory_metrics,
180
+ )
nat/runtime/runner.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,16 +26,13 @@ from nat.data_models.intermediate_step import IntermediateStepType
26
26
  from nat.data_models.intermediate_step import StreamEventData
27
27
  from nat.data_models.intermediate_step import TraceMetadata
28
28
  from nat.data_models.invocation_node import InvocationNode
29
+ from nat.data_models.runtime_enum import RuntimeTypeEnum
29
30
  from nat.observability.exporter_manager import ExporterManager
30
31
  from nat.utils.reactive.subject import Subject
31
32
 
32
33
  logger = logging.getLogger(__name__)
33
34
 
34
35
 
35
- class UserManagerBase:
36
- pass
37
-
38
-
39
36
  class RunnerState(Enum):
40
37
  UNINITIALIZED = 0
41
38
  INITIALIZED = 1
@@ -53,7 +50,8 @@ class Runner:
53
50
  input_message: typing.Any,
54
51
  entry_fn: Function,
55
52
  context_state: ContextState,
56
- exporter_manager: ExporterManager):
53
+ exporter_manager: ExporterManager,
54
+ runtime_type: RuntimeTypeEnum = RuntimeTypeEnum.RUN_OR_SERVE):
57
55
  """
58
56
  The Runner class is used to run a workflow. It handles converting input and output data types and running the
59
57
  workflow with the specified concurrency.
@@ -68,6 +66,8 @@ class Runner:
68
66
  The context state to use
69
67
  exporter_manager : ExporterManager
70
68
  The exporter manager to use
69
+ runtime_type : RuntimeTypeEnum
70
+ The runtime type (RUN_OR_SERVE, EVALUATE, OTHER)
71
71
  """
72
72
 
73
73
  if (entry_fn is None):
@@ -86,6 +86,9 @@ class Runner:
86
86
 
87
87
  self._exporter_manager = exporter_manager
88
88
 
89
+ self._runtime_type = runtime_type
90
+ self._runtime_type_token = None
91
+
89
92
  @property
90
93
  def context(self) -> Context:
91
94
  return self._context
@@ -105,6 +108,8 @@ class Runner:
105
108
  function_id="root",
106
109
  ))
107
110
 
111
+ self._runtime_type_token = self._context_state.runtime_type.set(self._runtime_type)
112
+
108
113
  if (self._state == RunnerState.UNINITIALIZED):
109
114
  self._state = RunnerState.INITIALIZED
110
115
  else:
@@ -119,6 +124,8 @@ class Runner:
119
124
 
120
125
  self._context_state.input_message.reset(self._input_message_token)
121
126
 
127
+ self._context_state.runtime_type.reset(self._runtime_type_token)
128
+
122
129
  if (self._state not in (RunnerState.COMPLETED, RunnerState.FAILED)):
123
130
  raise ValueError("Cannot exit the context without completing the workflow")
124
131