nvidia-nat 1.1.0a20251020__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.
- aiq/__init__.py +66 -0
- nat/agent/__init__.py +0 -0
- nat/agent/base.py +265 -0
- nat/agent/dual_node.py +72 -0
- nat/agent/prompt_optimizer/__init__.py +0 -0
- nat/agent/prompt_optimizer/prompt.py +68 -0
- nat/agent/prompt_optimizer/register.py +149 -0
- nat/agent/react_agent/__init__.py +0 -0
- nat/agent/react_agent/agent.py +394 -0
- nat/agent/react_agent/output_parser.py +104 -0
- nat/agent/react_agent/prompt.py +44 -0
- nat/agent/react_agent/register.py +168 -0
- nat/agent/reasoning_agent/__init__.py +0 -0
- nat/agent/reasoning_agent/reasoning_agent.py +227 -0
- nat/agent/register.py +23 -0
- nat/agent/rewoo_agent/__init__.py +0 -0
- nat/agent/rewoo_agent/agent.py +593 -0
- nat/agent/rewoo_agent/prompt.py +107 -0
- nat/agent/rewoo_agent/register.py +175 -0
- nat/agent/tool_calling_agent/__init__.py +0 -0
- nat/agent/tool_calling_agent/agent.py +246 -0
- nat/agent/tool_calling_agent/register.py +129 -0
- nat/authentication/__init__.py +14 -0
- nat/authentication/api_key/__init__.py +14 -0
- nat/authentication/api_key/api_key_auth_provider.py +96 -0
- nat/authentication/api_key/api_key_auth_provider_config.py +124 -0
- nat/authentication/api_key/register.py +26 -0
- nat/authentication/credential_validator/__init__.py +14 -0
- nat/authentication/credential_validator/bearer_token_validator.py +557 -0
- nat/authentication/exceptions/__init__.py +14 -0
- nat/authentication/exceptions/api_key_exceptions.py +38 -0
- nat/authentication/http_basic_auth/__init__.py +0 -0
- nat/authentication/http_basic_auth/http_basic_auth_provider.py +81 -0
- nat/authentication/http_basic_auth/register.py +30 -0
- nat/authentication/interfaces.py +96 -0
- nat/authentication/oauth2/__init__.py +14 -0
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +140 -0
- nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +39 -0
- nat/authentication/oauth2/oauth2_resource_server_config.py +124 -0
- nat/authentication/oauth2/register.py +25 -0
- nat/authentication/register.py +20 -0
- nat/builder/__init__.py +0 -0
- nat/builder/builder.py +317 -0
- nat/builder/component_utils.py +320 -0
- nat/builder/context.py +321 -0
- nat/builder/embedder.py +24 -0
- nat/builder/eval_builder.py +166 -0
- nat/builder/evaluator.py +29 -0
- nat/builder/framework_enum.py +25 -0
- nat/builder/front_end.py +73 -0
- nat/builder/function.py +714 -0
- nat/builder/function_base.py +380 -0
- nat/builder/function_info.py +625 -0
- nat/builder/intermediate_step_manager.py +206 -0
- nat/builder/llm.py +25 -0
- nat/builder/retriever.py +25 -0
- nat/builder/user_interaction_manager.py +78 -0
- nat/builder/workflow.py +160 -0
- nat/builder/workflow_builder.py +1365 -0
- nat/cli/__init__.py +14 -0
- nat/cli/cli_utils/__init__.py +0 -0
- nat/cli/cli_utils/config_override.py +231 -0
- nat/cli/cli_utils/validation.py +37 -0
- nat/cli/commands/__init__.py +0 -0
- nat/cli/commands/configure/__init__.py +0 -0
- nat/cli/commands/configure/channel/__init__.py +0 -0
- nat/cli/commands/configure/channel/add.py +28 -0
- nat/cli/commands/configure/channel/channel.py +34 -0
- nat/cli/commands/configure/channel/remove.py +30 -0
- nat/cli/commands/configure/channel/update.py +30 -0
- nat/cli/commands/configure/configure.py +33 -0
- nat/cli/commands/evaluate.py +139 -0
- nat/cli/commands/info/__init__.py +14 -0
- nat/cli/commands/info/info.py +47 -0
- nat/cli/commands/info/list_channels.py +32 -0
- nat/cli/commands/info/list_components.py +128 -0
- nat/cli/commands/mcp/__init__.py +14 -0
- nat/cli/commands/mcp/mcp.py +986 -0
- nat/cli/commands/object_store/__init__.py +14 -0
- nat/cli/commands/object_store/object_store.py +227 -0
- nat/cli/commands/optimize.py +90 -0
- nat/cli/commands/registry/__init__.py +14 -0
- nat/cli/commands/registry/publish.py +88 -0
- nat/cli/commands/registry/pull.py +118 -0
- nat/cli/commands/registry/registry.py +36 -0
- nat/cli/commands/registry/remove.py +108 -0
- nat/cli/commands/registry/search.py +153 -0
- nat/cli/commands/sizing/__init__.py +14 -0
- nat/cli/commands/sizing/calc.py +297 -0
- nat/cli/commands/sizing/sizing.py +27 -0
- nat/cli/commands/start.py +257 -0
- nat/cli/commands/uninstall.py +81 -0
- nat/cli/commands/validate.py +47 -0
- nat/cli/commands/workflow/__init__.py +14 -0
- nat/cli/commands/workflow/templates/__init__.py.j2 +0 -0
- nat/cli/commands/workflow/templates/config.yml.j2 +17 -0
- nat/cli/commands/workflow/templates/pyproject.toml.j2 +25 -0
- nat/cli/commands/workflow/templates/register.py.j2 +4 -0
- nat/cli/commands/workflow/templates/workflow.py.j2 +50 -0
- nat/cli/commands/workflow/workflow.py +37 -0
- nat/cli/commands/workflow/workflow_commands.py +403 -0
- nat/cli/entrypoint.py +141 -0
- nat/cli/main.py +60 -0
- nat/cli/register_workflow.py +522 -0
- nat/cli/type_registry.py +1069 -0
- nat/control_flow/__init__.py +0 -0
- nat/control_flow/register.py +20 -0
- nat/control_flow/router_agent/__init__.py +0 -0
- nat/control_flow/router_agent/agent.py +329 -0
- nat/control_flow/router_agent/prompt.py +48 -0
- nat/control_flow/router_agent/register.py +91 -0
- nat/control_flow/sequential_executor.py +166 -0
- nat/data_models/__init__.py +14 -0
- nat/data_models/agent.py +34 -0
- nat/data_models/api_server.py +843 -0
- nat/data_models/authentication.py +245 -0
- nat/data_models/common.py +171 -0
- nat/data_models/component.py +60 -0
- nat/data_models/component_ref.py +179 -0
- nat/data_models/config.py +434 -0
- nat/data_models/dataset_handler.py +169 -0
- nat/data_models/discovery_metadata.py +305 -0
- nat/data_models/embedder.py +27 -0
- nat/data_models/evaluate.py +130 -0
- nat/data_models/evaluator.py +26 -0
- nat/data_models/front_end.py +26 -0
- nat/data_models/function.py +64 -0
- nat/data_models/function_dependencies.py +80 -0
- nat/data_models/gated_field_mixin.py +242 -0
- nat/data_models/interactive.py +246 -0
- nat/data_models/intermediate_step.py +302 -0
- nat/data_models/invocation_node.py +38 -0
- nat/data_models/llm.py +27 -0
- nat/data_models/logging.py +26 -0
- nat/data_models/memory.py +27 -0
- nat/data_models/object_store.py +44 -0
- nat/data_models/optimizable.py +119 -0
- nat/data_models/optimizer.py +149 -0
- nat/data_models/profiler.py +54 -0
- nat/data_models/registry_handler.py +26 -0
- nat/data_models/retriever.py +30 -0
- nat/data_models/retry_mixin.py +35 -0
- nat/data_models/span.py +228 -0
- nat/data_models/step_adaptor.py +64 -0
- nat/data_models/streaming.py +33 -0
- nat/data_models/swe_bench_model.py +54 -0
- nat/data_models/telemetry_exporter.py +26 -0
- nat/data_models/temperature_mixin.py +44 -0
- nat/data_models/thinking_mixin.py +86 -0
- nat/data_models/top_p_mixin.py +44 -0
- nat/data_models/ttc_strategy.py +30 -0
- nat/embedder/__init__.py +0 -0
- nat/embedder/azure_openai_embedder.py +46 -0
- nat/embedder/nim_embedder.py +59 -0
- nat/embedder/openai_embedder.py +42 -0
- nat/embedder/register.py +22 -0
- nat/eval/__init__.py +14 -0
- nat/eval/config.py +62 -0
- nat/eval/dataset_handler/__init__.py +0 -0
- nat/eval/dataset_handler/dataset_downloader.py +106 -0
- nat/eval/dataset_handler/dataset_filter.py +52 -0
- nat/eval/dataset_handler/dataset_handler.py +431 -0
- nat/eval/evaluate.py +565 -0
- nat/eval/evaluator/__init__.py +14 -0
- nat/eval/evaluator/base_evaluator.py +77 -0
- nat/eval/evaluator/evaluator_model.py +58 -0
- nat/eval/intermediate_step_adapter.py +99 -0
- nat/eval/rag_evaluator/__init__.py +0 -0
- nat/eval/rag_evaluator/evaluate.py +178 -0
- nat/eval/rag_evaluator/register.py +143 -0
- nat/eval/register.py +26 -0
- nat/eval/remote_workflow.py +133 -0
- nat/eval/runners/__init__.py +14 -0
- nat/eval/runners/config.py +39 -0
- nat/eval/runners/multi_eval_runner.py +54 -0
- nat/eval/runtime_evaluator/__init__.py +14 -0
- nat/eval/runtime_evaluator/evaluate.py +123 -0
- nat/eval/runtime_evaluator/register.py +100 -0
- nat/eval/runtime_event_subscriber.py +52 -0
- nat/eval/swe_bench_evaluator/__init__.py +0 -0
- nat/eval/swe_bench_evaluator/evaluate.py +215 -0
- nat/eval/swe_bench_evaluator/register.py +36 -0
- nat/eval/trajectory_evaluator/__init__.py +0 -0
- nat/eval/trajectory_evaluator/evaluate.py +75 -0
- nat/eval/trajectory_evaluator/register.py +40 -0
- nat/eval/tunable_rag_evaluator/__init__.py +0 -0
- nat/eval/tunable_rag_evaluator/evaluate.py +242 -0
- nat/eval/tunable_rag_evaluator/register.py +52 -0
- nat/eval/usage_stats.py +41 -0
- nat/eval/utils/__init__.py +0 -0
- nat/eval/utils/eval_trace_ctx.py +89 -0
- nat/eval/utils/output_uploader.py +140 -0
- nat/eval/utils/tqdm_position_registry.py +40 -0
- nat/eval/utils/weave_eval.py +193 -0
- nat/experimental/__init__.py +0 -0
- nat/experimental/decorators/__init__.py +0 -0
- nat/experimental/decorators/experimental_warning_decorator.py +154 -0
- nat/experimental/test_time_compute/__init__.py +0 -0
- nat/experimental/test_time_compute/editing/__init__.py +0 -0
- nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +147 -0
- nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +204 -0
- nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +107 -0
- nat/experimental/test_time_compute/functions/__init__.py +0 -0
- nat/experimental/test_time_compute/functions/execute_score_select_function.py +105 -0
- nat/experimental/test_time_compute/functions/plan_select_execute_function.py +228 -0
- nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +205 -0
- nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +146 -0
- nat/experimental/test_time_compute/models/__init__.py +0 -0
- nat/experimental/test_time_compute/models/editor_config.py +132 -0
- nat/experimental/test_time_compute/models/scoring_config.py +112 -0
- nat/experimental/test_time_compute/models/search_config.py +120 -0
- nat/experimental/test_time_compute/models/selection_config.py +154 -0
- nat/experimental/test_time_compute/models/stage_enums.py +43 -0
- nat/experimental/test_time_compute/models/strategy_base.py +67 -0
- nat/experimental/test_time_compute/models/tool_use_config.py +41 -0
- nat/experimental/test_time_compute/models/ttc_item.py +48 -0
- nat/experimental/test_time_compute/register.py +35 -0
- nat/experimental/test_time_compute/scoring/__init__.py +0 -0
- nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +168 -0
- nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +168 -0
- nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +111 -0
- nat/experimental/test_time_compute/search/__init__.py +0 -0
- nat/experimental/test_time_compute/search/multi_llm_planner.py +128 -0
- nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +122 -0
- nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +128 -0
- nat/experimental/test_time_compute/selection/__init__.py +0 -0
- nat/experimental/test_time_compute/selection/best_of_n_selector.py +63 -0
- nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +131 -0
- nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +157 -0
- nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +128 -0
- nat/experimental/test_time_compute/selection/threshold_selector.py +58 -0
- nat/front_ends/__init__.py +14 -0
- nat/front_ends/console/__init__.py +14 -0
- nat/front_ends/console/authentication_flow_handler.py +285 -0
- nat/front_ends/console/console_front_end_config.py +32 -0
- nat/front_ends/console/console_front_end_plugin.py +108 -0
- nat/front_ends/console/register.py +25 -0
- nat/front_ends/cron/__init__.py +14 -0
- nat/front_ends/fastapi/__init__.py +14 -0
- nat/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
- nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +27 -0
- nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +142 -0
- nat/front_ends/fastapi/dask_client_mixin.py +65 -0
- nat/front_ends/fastapi/fastapi_front_end_config.py +272 -0
- nat/front_ends/fastapi/fastapi_front_end_controller.py +68 -0
- nat/front_ends/fastapi/fastapi_front_end_plugin.py +247 -0
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +1257 -0
- nat/front_ends/fastapi/html_snippets/__init__.py +14 -0
- nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +35 -0
- nat/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
- nat/front_ends/fastapi/job_store.py +602 -0
- nat/front_ends/fastapi/main.py +64 -0
- nat/front_ends/fastapi/message_handler.py +344 -0
- nat/front_ends/fastapi/message_validator.py +351 -0
- nat/front_ends/fastapi/register.py +25 -0
- nat/front_ends/fastapi/response_helpers.py +195 -0
- nat/front_ends/fastapi/step_adaptor.py +319 -0
- nat/front_ends/fastapi/utils.py +57 -0
- nat/front_ends/mcp/__init__.py +14 -0
- nat/front_ends/mcp/introspection_token_verifier.py +73 -0
- nat/front_ends/mcp/mcp_front_end_config.py +90 -0
- nat/front_ends/mcp/mcp_front_end_plugin.py +113 -0
- nat/front_ends/mcp/mcp_front_end_plugin_worker.py +268 -0
- nat/front_ends/mcp/memory_profiler.py +320 -0
- nat/front_ends/mcp/register.py +27 -0
- nat/front_ends/mcp/tool_converter.py +290 -0
- nat/front_ends/register.py +21 -0
- nat/front_ends/simple_base/__init__.py +14 -0
- nat/front_ends/simple_base/simple_front_end_plugin_base.py +56 -0
- nat/llm/__init__.py +0 -0
- nat/llm/aws_bedrock_llm.py +69 -0
- nat/llm/azure_openai_llm.py +57 -0
- nat/llm/litellm_llm.py +69 -0
- nat/llm/nim_llm.py +58 -0
- nat/llm/openai_llm.py +54 -0
- nat/llm/register.py +27 -0
- nat/llm/utils/__init__.py +14 -0
- nat/llm/utils/env_config_value.py +93 -0
- nat/llm/utils/error.py +17 -0
- nat/llm/utils/thinking.py +215 -0
- nat/memory/__init__.py +20 -0
- nat/memory/interfaces.py +183 -0
- nat/memory/models.py +112 -0
- nat/meta/pypi.md +58 -0
- nat/object_store/__init__.py +20 -0
- nat/object_store/in_memory_object_store.py +76 -0
- nat/object_store/interfaces.py +84 -0
- nat/object_store/models.py +38 -0
- nat/object_store/register.py +19 -0
- nat/observability/__init__.py +14 -0
- nat/observability/exporter/__init__.py +14 -0
- nat/observability/exporter/base_exporter.py +449 -0
- nat/observability/exporter/exporter.py +78 -0
- nat/observability/exporter/file_exporter.py +33 -0
- nat/observability/exporter/processing_exporter.py +550 -0
- nat/observability/exporter/raw_exporter.py +52 -0
- nat/observability/exporter/span_exporter.py +308 -0
- nat/observability/exporter_manager.py +335 -0
- nat/observability/mixin/__init__.py +14 -0
- nat/observability/mixin/batch_config_mixin.py +26 -0
- nat/observability/mixin/collector_config_mixin.py +23 -0
- nat/observability/mixin/file_mixin.py +288 -0
- nat/observability/mixin/file_mode.py +23 -0
- nat/observability/mixin/redaction_config_mixin.py +42 -0
- nat/observability/mixin/resource_conflict_mixin.py +134 -0
- nat/observability/mixin/serialize_mixin.py +61 -0
- nat/observability/mixin/tagging_config_mixin.py +62 -0
- nat/observability/mixin/type_introspection_mixin.py +496 -0
- nat/observability/processor/__init__.py +14 -0
- nat/observability/processor/batching_processor.py +308 -0
- nat/observability/processor/callback_processor.py +42 -0
- nat/observability/processor/falsy_batch_filter_processor.py +55 -0
- nat/observability/processor/intermediate_step_serializer.py +28 -0
- nat/observability/processor/processor.py +74 -0
- nat/observability/processor/processor_factory.py +70 -0
- nat/observability/processor/redaction/__init__.py +24 -0
- nat/observability/processor/redaction/contextual_redaction_processor.py +125 -0
- nat/observability/processor/redaction/contextual_span_redaction_processor.py +66 -0
- nat/observability/processor/redaction/redaction_processor.py +177 -0
- nat/observability/processor/redaction/span_header_redaction_processor.py +92 -0
- nat/observability/processor/span_tagging_processor.py +68 -0
- nat/observability/register.py +114 -0
- nat/observability/utils/__init__.py +14 -0
- nat/observability/utils/dict_utils.py +236 -0
- nat/observability/utils/time_utils.py +31 -0
- nat/plugins/.namespace +1 -0
- nat/profiler/__init__.py +0 -0
- nat/profiler/calc/__init__.py +14 -0
- nat/profiler/calc/calc_runner.py +626 -0
- nat/profiler/calc/calculations.py +288 -0
- nat/profiler/calc/data_models.py +188 -0
- nat/profiler/calc/plot.py +345 -0
- nat/profiler/callbacks/__init__.py +0 -0
- nat/profiler/callbacks/agno_callback_handler.py +295 -0
- nat/profiler/callbacks/base_callback_class.py +20 -0
- nat/profiler/callbacks/langchain_callback_handler.py +297 -0
- nat/profiler/callbacks/llama_index_callback_handler.py +205 -0
- nat/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
- nat/profiler/callbacks/token_usage_base_model.py +27 -0
- nat/profiler/data_frame_row.py +51 -0
- nat/profiler/data_models.py +24 -0
- nat/profiler/decorators/__init__.py +0 -0
- nat/profiler/decorators/framework_wrapper.py +180 -0
- nat/profiler/decorators/function_tracking.py +411 -0
- nat/profiler/forecasting/__init__.py +0 -0
- nat/profiler/forecasting/config.py +18 -0
- nat/profiler/forecasting/model_trainer.py +75 -0
- nat/profiler/forecasting/models/__init__.py +22 -0
- nat/profiler/forecasting/models/forecasting_base_model.py +42 -0
- nat/profiler/forecasting/models/linear_model.py +197 -0
- nat/profiler/forecasting/models/random_forest_regressor.py +269 -0
- nat/profiler/inference_metrics_model.py +28 -0
- nat/profiler/inference_optimization/__init__.py +0 -0
- nat/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
- nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +460 -0
- nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
- nat/profiler/inference_optimization/data_models.py +386 -0
- nat/profiler/inference_optimization/experimental/__init__.py +0 -0
- nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
- nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +404 -0
- nat/profiler/inference_optimization/llm_metrics.py +212 -0
- nat/profiler/inference_optimization/prompt_caching.py +163 -0
- nat/profiler/inference_optimization/token_uniqueness.py +107 -0
- nat/profiler/inference_optimization/workflow_runtimes.py +72 -0
- nat/profiler/intermediate_property_adapter.py +102 -0
- nat/profiler/parameter_optimization/__init__.py +0 -0
- nat/profiler/parameter_optimization/optimizable_utils.py +93 -0
- nat/profiler/parameter_optimization/optimizer_runtime.py +67 -0
- nat/profiler/parameter_optimization/parameter_optimizer.py +153 -0
- nat/profiler/parameter_optimization/parameter_selection.py +107 -0
- nat/profiler/parameter_optimization/pareto_visualizer.py +380 -0
- nat/profiler/parameter_optimization/prompt_optimizer.py +384 -0
- nat/profiler/parameter_optimization/update_helpers.py +66 -0
- nat/profiler/profile_runner.py +478 -0
- nat/profiler/utils.py +186 -0
- nat/registry_handlers/__init__.py +0 -0
- nat/registry_handlers/local/__init__.py +0 -0
- nat/registry_handlers/local/local_handler.py +176 -0
- nat/registry_handlers/local/register_local.py +37 -0
- nat/registry_handlers/metadata_factory.py +60 -0
- nat/registry_handlers/package_utils.py +570 -0
- nat/registry_handlers/pypi/__init__.py +0 -0
- nat/registry_handlers/pypi/pypi_handler.py +248 -0
- nat/registry_handlers/pypi/register_pypi.py +40 -0
- nat/registry_handlers/register.py +20 -0
- nat/registry_handlers/registry_handler_base.py +157 -0
- nat/registry_handlers/rest/__init__.py +0 -0
- nat/registry_handlers/rest/register_rest.py +56 -0
- nat/registry_handlers/rest/rest_handler.py +236 -0
- nat/registry_handlers/schemas/__init__.py +0 -0
- nat/registry_handlers/schemas/headers.py +42 -0
- nat/registry_handlers/schemas/package.py +68 -0
- nat/registry_handlers/schemas/publish.py +68 -0
- nat/registry_handlers/schemas/pull.py +82 -0
- nat/registry_handlers/schemas/remove.py +36 -0
- nat/registry_handlers/schemas/search.py +91 -0
- nat/registry_handlers/schemas/status.py +47 -0
- nat/retriever/__init__.py +0 -0
- nat/retriever/interface.py +41 -0
- nat/retriever/milvus/__init__.py +14 -0
- nat/retriever/milvus/register.py +81 -0
- nat/retriever/milvus/retriever.py +228 -0
- nat/retriever/models.py +77 -0
- nat/retriever/nemo_retriever/__init__.py +14 -0
- nat/retriever/nemo_retriever/register.py +60 -0
- nat/retriever/nemo_retriever/retriever.py +190 -0
- nat/retriever/register.py +21 -0
- nat/runtime/__init__.py +14 -0
- nat/runtime/loader.py +220 -0
- nat/runtime/runner.py +292 -0
- nat/runtime/session.py +223 -0
- nat/runtime/user_metadata.py +130 -0
- nat/settings/__init__.py +0 -0
- nat/settings/global_settings.py +329 -0
- nat/test/.namespace +1 -0
- nat/tool/__init__.py +0 -0
- nat/tool/chat_completion.py +77 -0
- nat/tool/code_execution/README.md +151 -0
- nat/tool/code_execution/__init__.py +0 -0
- nat/tool/code_execution/code_sandbox.py +267 -0
- nat/tool/code_execution/local_sandbox/.gitignore +1 -0
- nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
- nat/tool/code_execution/local_sandbox/__init__.py +13 -0
- nat/tool/code_execution/local_sandbox/local_sandbox_server.py +198 -0
- nat/tool/code_execution/local_sandbox/sandbox.requirements.txt +6 -0
- nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +50 -0
- nat/tool/code_execution/register.py +74 -0
- nat/tool/code_execution/test_code_execution_sandbox.py +414 -0
- nat/tool/code_execution/utils.py +100 -0
- nat/tool/datetime_tools.py +82 -0
- nat/tool/document_search.py +141 -0
- nat/tool/github_tools.py +450 -0
- nat/tool/memory_tools/__init__.py +0 -0
- nat/tool/memory_tools/add_memory_tool.py +79 -0
- nat/tool/memory_tools/delete_memory_tool.py +66 -0
- nat/tool/memory_tools/get_memory_tool.py +72 -0
- nat/tool/nvidia_rag.py +95 -0
- nat/tool/register.py +31 -0
- nat/tool/retriever.py +95 -0
- nat/tool/server_tools.py +66 -0
- nat/utils/__init__.py +0 -0
- nat/utils/callable_utils.py +70 -0
- nat/utils/data_models/__init__.py +0 -0
- nat/utils/data_models/schema_validator.py +58 -0
- nat/utils/debugging_utils.py +43 -0
- nat/utils/decorators.py +210 -0
- nat/utils/dump_distro_mapping.py +32 -0
- nat/utils/exception_handlers/__init__.py +0 -0
- nat/utils/exception_handlers/automatic_retries.py +342 -0
- nat/utils/exception_handlers/schemas.py +114 -0
- nat/utils/io/__init__.py +0 -0
- nat/utils/io/model_processing.py +28 -0
- nat/utils/io/yaml_tools.py +119 -0
- nat/utils/log_levels.py +25 -0
- nat/utils/log_utils.py +37 -0
- nat/utils/metadata_utils.py +74 -0
- nat/utils/optional_imports.py +142 -0
- nat/utils/producer_consumer_queue.py +178 -0
- nat/utils/reactive/__init__.py +0 -0
- nat/utils/reactive/base/__init__.py +0 -0
- nat/utils/reactive/base/observable_base.py +65 -0
- nat/utils/reactive/base/observer_base.py +55 -0
- nat/utils/reactive/base/subject_base.py +79 -0
- nat/utils/reactive/observable.py +59 -0
- nat/utils/reactive/observer.py +76 -0
- nat/utils/reactive/subject.py +131 -0
- nat/utils/reactive/subscription.py +49 -0
- nat/utils/settings/__init__.py +0 -0
- nat/utils/settings/global_settings.py +195 -0
- nat/utils/string_utils.py +38 -0
- nat/utils/type_converter.py +299 -0
- nat/utils/type_utils.py +488 -0
- nat/utils/url_utils.py +27 -0
- nvidia_nat-1.1.0a20251020.dist-info/METADATA +195 -0
- nvidia_nat-1.1.0a20251020.dist-info/RECORD +480 -0
- nvidia_nat-1.1.0a20251020.dist-info/WHEEL +5 -0
- nvidia_nat-1.1.0a20251020.dist-info/entry_points.txt +22 -0
- nvidia_nat-1.1.0a20251020.dist-info/licenses/LICENSE-3rd-party.txt +5478 -0
- nvidia_nat-1.1.0a20251020.dist-info/licenses/LICENSE.md +201 -0
- nvidia_nat-1.1.0a20251020.dist-info/top_level.txt +2 -0
nat/runtime/runner.py
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
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
|
+
import logging
|
|
17
|
+
import typing
|
|
18
|
+
import uuid
|
|
19
|
+
from enum import Enum
|
|
20
|
+
|
|
21
|
+
from nat.builder.context import Context
|
|
22
|
+
from nat.builder.context import ContextState
|
|
23
|
+
from nat.builder.function import Function
|
|
24
|
+
from nat.data_models.intermediate_step import IntermediateStepPayload
|
|
25
|
+
from nat.data_models.intermediate_step import IntermediateStepType
|
|
26
|
+
from nat.data_models.intermediate_step import StreamEventData
|
|
27
|
+
from nat.data_models.intermediate_step import TraceMetadata
|
|
28
|
+
from nat.data_models.invocation_node import InvocationNode
|
|
29
|
+
from nat.observability.exporter_manager import ExporterManager
|
|
30
|
+
from nat.utils.reactive.subject import Subject
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UserManagerBase:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RunnerState(Enum):
|
|
40
|
+
UNINITIALIZED = 0
|
|
41
|
+
INITIALIZED = 1
|
|
42
|
+
RUNNING = 2
|
|
43
|
+
COMPLETED = 3
|
|
44
|
+
FAILED = 4
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_T = typing.TypeVar("_T")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Runner:
|
|
51
|
+
|
|
52
|
+
def __init__(self,
|
|
53
|
+
input_message: typing.Any,
|
|
54
|
+
entry_fn: Function,
|
|
55
|
+
context_state: ContextState,
|
|
56
|
+
exporter_manager: ExporterManager):
|
|
57
|
+
"""
|
|
58
|
+
The Runner class is used to run a workflow. It handles converting input and output data types and running the
|
|
59
|
+
workflow with the specified concurrency.
|
|
60
|
+
|
|
61
|
+
Parameters
|
|
62
|
+
----------
|
|
63
|
+
input_message : typing.Any
|
|
64
|
+
The input message to the workflow
|
|
65
|
+
entry_fn : Function
|
|
66
|
+
The entry function to the workflow
|
|
67
|
+
context_state : ContextState
|
|
68
|
+
The context state to use
|
|
69
|
+
exporter_manager : ExporterManager
|
|
70
|
+
The exporter manager to use
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
if (entry_fn is None):
|
|
74
|
+
raise ValueError("entry_fn cannot be None")
|
|
75
|
+
|
|
76
|
+
self._entry_fn = entry_fn
|
|
77
|
+
self._context_state = context_state
|
|
78
|
+
self._context = Context(self._context_state)
|
|
79
|
+
|
|
80
|
+
self._state = RunnerState.UNINITIALIZED
|
|
81
|
+
|
|
82
|
+
self._input_message_token = None
|
|
83
|
+
|
|
84
|
+
# Before we start, we need to convert the input message to the workflow input type
|
|
85
|
+
self._input_message = input_message
|
|
86
|
+
|
|
87
|
+
self._exporter_manager = exporter_manager
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def context(self) -> Context:
|
|
91
|
+
return self._context
|
|
92
|
+
|
|
93
|
+
def convert(self, value: typing.Any, to_type: type[_T]) -> _T:
|
|
94
|
+
return self._entry_fn.convert(value, to_type)
|
|
95
|
+
|
|
96
|
+
async def __aenter__(self):
|
|
97
|
+
|
|
98
|
+
# Set the input message on the context
|
|
99
|
+
self._input_message_token = self._context_state.input_message.set(self._input_message)
|
|
100
|
+
|
|
101
|
+
# Create reactive event stream
|
|
102
|
+
self._context_state.event_stream.set(Subject())
|
|
103
|
+
self._context_state.active_function.set(InvocationNode(
|
|
104
|
+
function_name="root",
|
|
105
|
+
function_id="root",
|
|
106
|
+
))
|
|
107
|
+
|
|
108
|
+
if (self._state == RunnerState.UNINITIALIZED):
|
|
109
|
+
self._state = RunnerState.INITIALIZED
|
|
110
|
+
else:
|
|
111
|
+
raise ValueError("Cannot enter the context more than once")
|
|
112
|
+
|
|
113
|
+
return self
|
|
114
|
+
|
|
115
|
+
async def __aexit__(self, exc_type, exc_value, traceback):
|
|
116
|
+
|
|
117
|
+
if (self._input_message_token is None):
|
|
118
|
+
raise ValueError("Cannot exit the context without entering it")
|
|
119
|
+
|
|
120
|
+
self._context_state.input_message.reset(self._input_message_token)
|
|
121
|
+
|
|
122
|
+
if (self._state not in (RunnerState.COMPLETED, RunnerState.FAILED)):
|
|
123
|
+
raise ValueError("Cannot exit the context without completing the workflow")
|
|
124
|
+
|
|
125
|
+
@typing.overload
|
|
126
|
+
async def result(self) -> typing.Any:
|
|
127
|
+
...
|
|
128
|
+
|
|
129
|
+
@typing.overload
|
|
130
|
+
async def result(self, to_type: type[_T]) -> _T:
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
async def result(self, to_type: type | None = None):
|
|
134
|
+
|
|
135
|
+
if (self._state != RunnerState.INITIALIZED):
|
|
136
|
+
raise ValueError("Cannot run the workflow without entering the context")
|
|
137
|
+
|
|
138
|
+
token_run_id = None
|
|
139
|
+
token_trace_id = None
|
|
140
|
+
try:
|
|
141
|
+
self._state = RunnerState.RUNNING
|
|
142
|
+
|
|
143
|
+
if (not self._entry_fn.has_single_output):
|
|
144
|
+
raise ValueError("Workflow does not support single output")
|
|
145
|
+
|
|
146
|
+
# Establish workflow run and trace identifiers
|
|
147
|
+
existing_run_id = self._context_state.workflow_run_id.get()
|
|
148
|
+
existing_trace_id = self._context_state.workflow_trace_id.get()
|
|
149
|
+
|
|
150
|
+
workflow_run_id = existing_run_id or str(uuid.uuid4())
|
|
151
|
+
|
|
152
|
+
workflow_trace_id = existing_trace_id or uuid.uuid4().int
|
|
153
|
+
|
|
154
|
+
token_run_id = self._context_state.workflow_run_id.set(workflow_run_id)
|
|
155
|
+
token_trace_id = self._context_state.workflow_trace_id.set(workflow_trace_id)
|
|
156
|
+
|
|
157
|
+
# Prepare workflow-level intermediate step identifiers
|
|
158
|
+
workflow_step_uuid = str(uuid.uuid4())
|
|
159
|
+
workflow_name = getattr(self._entry_fn, 'instance_name', None) or "workflow"
|
|
160
|
+
|
|
161
|
+
async with self._exporter_manager.start(context_state=self._context_state):
|
|
162
|
+
# Emit WORKFLOW_START
|
|
163
|
+
start_metadata = TraceMetadata(
|
|
164
|
+
provided_metadata={
|
|
165
|
+
"workflow_run_id": workflow_run_id,
|
|
166
|
+
"workflow_trace_id": f"{workflow_trace_id:032x}",
|
|
167
|
+
"conversation_id": self._context_state.conversation_id.get(),
|
|
168
|
+
})
|
|
169
|
+
self._context.intermediate_step_manager.push_intermediate_step(
|
|
170
|
+
IntermediateStepPayload(UUID=workflow_step_uuid,
|
|
171
|
+
event_type=IntermediateStepType.WORKFLOW_START,
|
|
172
|
+
name=workflow_name,
|
|
173
|
+
metadata=start_metadata))
|
|
174
|
+
|
|
175
|
+
result = await self._entry_fn.ainvoke(self._input_message, to_type=to_type) # type: ignore
|
|
176
|
+
|
|
177
|
+
# Emit WORKFLOW_END with output
|
|
178
|
+
end_metadata = TraceMetadata(
|
|
179
|
+
provided_metadata={
|
|
180
|
+
"workflow_run_id": workflow_run_id,
|
|
181
|
+
"workflow_trace_id": f"{workflow_trace_id:032x}",
|
|
182
|
+
"conversation_id": self._context_state.conversation_id.get(),
|
|
183
|
+
})
|
|
184
|
+
self._context.intermediate_step_manager.push_intermediate_step(
|
|
185
|
+
IntermediateStepPayload(UUID=workflow_step_uuid,
|
|
186
|
+
event_type=IntermediateStepType.WORKFLOW_END,
|
|
187
|
+
name=workflow_name,
|
|
188
|
+
metadata=end_metadata,
|
|
189
|
+
data=StreamEventData(output=result)))
|
|
190
|
+
|
|
191
|
+
event_stream = self._context_state.event_stream.get()
|
|
192
|
+
if event_stream:
|
|
193
|
+
event_stream.on_complete()
|
|
194
|
+
|
|
195
|
+
self._state = RunnerState.COMPLETED
|
|
196
|
+
|
|
197
|
+
return result
|
|
198
|
+
except Exception as e:
|
|
199
|
+
logger.error("Error running workflow: %s", e)
|
|
200
|
+
event_stream = self._context_state.event_stream.get()
|
|
201
|
+
if event_stream:
|
|
202
|
+
event_stream.on_complete()
|
|
203
|
+
self._state = RunnerState.FAILED
|
|
204
|
+
raise
|
|
205
|
+
finally:
|
|
206
|
+
if token_run_id is not None:
|
|
207
|
+
self._context_state.workflow_run_id.reset(token_run_id)
|
|
208
|
+
if token_trace_id is not None:
|
|
209
|
+
self._context_state.workflow_trace_id.reset(token_trace_id)
|
|
210
|
+
|
|
211
|
+
async def result_stream(self, to_type: type | None = None):
|
|
212
|
+
|
|
213
|
+
if (self._state != RunnerState.INITIALIZED):
|
|
214
|
+
raise ValueError("Cannot run the workflow without entering the context")
|
|
215
|
+
|
|
216
|
+
token_run_id = None
|
|
217
|
+
token_trace_id = None
|
|
218
|
+
try:
|
|
219
|
+
self._state = RunnerState.RUNNING
|
|
220
|
+
|
|
221
|
+
if (not self._entry_fn.has_streaming_output):
|
|
222
|
+
raise ValueError("Workflow does not support streaming output")
|
|
223
|
+
|
|
224
|
+
# Establish workflow run and trace identifiers
|
|
225
|
+
existing_run_id = self._context_state.workflow_run_id.get()
|
|
226
|
+
existing_trace_id = self._context_state.workflow_trace_id.get()
|
|
227
|
+
|
|
228
|
+
workflow_run_id = existing_run_id or str(uuid.uuid4())
|
|
229
|
+
|
|
230
|
+
workflow_trace_id = existing_trace_id or uuid.uuid4().int
|
|
231
|
+
|
|
232
|
+
token_run_id = self._context_state.workflow_run_id.set(workflow_run_id)
|
|
233
|
+
token_trace_id = self._context_state.workflow_trace_id.set(workflow_trace_id)
|
|
234
|
+
|
|
235
|
+
# Prepare workflow-level intermediate step identifiers
|
|
236
|
+
workflow_step_uuid = str(uuid.uuid4())
|
|
237
|
+
workflow_name = getattr(self._entry_fn, 'instance_name', None) or "workflow"
|
|
238
|
+
|
|
239
|
+
# Run the workflow
|
|
240
|
+
async with self._exporter_manager.start(context_state=self._context_state):
|
|
241
|
+
# Emit WORKFLOW_START
|
|
242
|
+
start_metadata = TraceMetadata(
|
|
243
|
+
provided_metadata={
|
|
244
|
+
"workflow_run_id": workflow_run_id,
|
|
245
|
+
"workflow_trace_id": f"{workflow_trace_id:032x}",
|
|
246
|
+
"conversation_id": self._context_state.conversation_id.get(),
|
|
247
|
+
})
|
|
248
|
+
self._context.intermediate_step_manager.push_intermediate_step(
|
|
249
|
+
IntermediateStepPayload(UUID=workflow_step_uuid,
|
|
250
|
+
event_type=IntermediateStepType.WORKFLOW_START,
|
|
251
|
+
name=workflow_name,
|
|
252
|
+
metadata=start_metadata))
|
|
253
|
+
|
|
254
|
+
async for m in self._entry_fn.astream(self._input_message, to_type=to_type): # type: ignore
|
|
255
|
+
yield m
|
|
256
|
+
|
|
257
|
+
# Emit WORKFLOW_END
|
|
258
|
+
end_metadata = TraceMetadata(
|
|
259
|
+
provided_metadata={
|
|
260
|
+
"workflow_run_id": workflow_run_id,
|
|
261
|
+
"workflow_trace_id": f"{workflow_trace_id:032x}",
|
|
262
|
+
"conversation_id": self._context_state.conversation_id.get(),
|
|
263
|
+
})
|
|
264
|
+
self._context.intermediate_step_manager.push_intermediate_step(
|
|
265
|
+
IntermediateStepPayload(UUID=workflow_step_uuid,
|
|
266
|
+
event_type=IntermediateStepType.WORKFLOW_END,
|
|
267
|
+
name=workflow_name,
|
|
268
|
+
metadata=end_metadata))
|
|
269
|
+
self._state = RunnerState.COMPLETED
|
|
270
|
+
|
|
271
|
+
# Close the intermediate stream
|
|
272
|
+
event_stream = self._context_state.event_stream.get()
|
|
273
|
+
if event_stream:
|
|
274
|
+
event_stream.on_complete()
|
|
275
|
+
|
|
276
|
+
except Exception as e:
|
|
277
|
+
logger.error("Error running workflow: %s", e)
|
|
278
|
+
event_stream = self._context_state.event_stream.get()
|
|
279
|
+
if event_stream:
|
|
280
|
+
event_stream.on_complete()
|
|
281
|
+
self._state = RunnerState.FAILED
|
|
282
|
+
raise
|
|
283
|
+
finally:
|
|
284
|
+
if token_run_id is not None:
|
|
285
|
+
self._context_state.workflow_run_id.reset(token_run_id)
|
|
286
|
+
if token_trace_id is not None:
|
|
287
|
+
self._context_state.workflow_trace_id.reset(token_trace_id)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# Compatibility aliases with previous releases
|
|
291
|
+
AIQRunnerState = RunnerState
|
|
292
|
+
AIQRunner = Runner
|
nat/runtime/session.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
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 asyncio
|
|
17
|
+
import contextvars
|
|
18
|
+
import typing
|
|
19
|
+
import uuid
|
|
20
|
+
from collections.abc import Awaitable
|
|
21
|
+
from collections.abc import Callable
|
|
22
|
+
from contextlib import asynccontextmanager
|
|
23
|
+
from contextlib import nullcontext
|
|
24
|
+
|
|
25
|
+
from fastapi import WebSocket
|
|
26
|
+
from starlette.requests import HTTPConnection
|
|
27
|
+
from starlette.requests import Request
|
|
28
|
+
|
|
29
|
+
from nat.builder.context import Context
|
|
30
|
+
from nat.builder.context import ContextState
|
|
31
|
+
from nat.builder.workflow import Workflow
|
|
32
|
+
from nat.data_models.authentication import AuthenticatedContext
|
|
33
|
+
from nat.data_models.authentication import AuthFlowType
|
|
34
|
+
from nat.data_models.authentication import AuthProviderBaseConfig
|
|
35
|
+
from nat.data_models.config import Config
|
|
36
|
+
from nat.data_models.interactive import HumanResponse
|
|
37
|
+
from nat.data_models.interactive import InteractionPrompt
|
|
38
|
+
|
|
39
|
+
_T = typing.TypeVar("_T")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class UserManagerBase:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SessionManager:
|
|
47
|
+
|
|
48
|
+
def __init__(self, workflow: Workflow, max_concurrency: int = 8):
|
|
49
|
+
"""
|
|
50
|
+
The SessionManager class is used to run and manage a user workflow session. It runs and manages the context,
|
|
51
|
+
and configuration of a workflow with the specified concurrency.
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
----------
|
|
55
|
+
workflow : Workflow
|
|
56
|
+
The workflow to run
|
|
57
|
+
max_concurrency : int, optional
|
|
58
|
+
The maximum number of simultaneous workflow invocations, by default 8
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
if (workflow is None):
|
|
62
|
+
raise ValueError("Workflow cannot be None")
|
|
63
|
+
|
|
64
|
+
self._workflow: Workflow = workflow
|
|
65
|
+
|
|
66
|
+
self._max_concurrency = max_concurrency
|
|
67
|
+
self._context_state = ContextState.get()
|
|
68
|
+
self._context = Context(self._context_state)
|
|
69
|
+
|
|
70
|
+
# We save the context because Uvicorn spawns a new process
|
|
71
|
+
# for each request, and we need to restore the context vars
|
|
72
|
+
self._saved_context = contextvars.copy_context()
|
|
73
|
+
|
|
74
|
+
if (max_concurrency > 0):
|
|
75
|
+
self._semaphore = asyncio.Semaphore(max_concurrency)
|
|
76
|
+
else:
|
|
77
|
+
# If max_concurrency is 0, then we don't need to limit the concurrency but we still need a context
|
|
78
|
+
self._semaphore = nullcontext()
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def config(self) -> Config:
|
|
82
|
+
return self._workflow.config
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def workflow(self) -> Workflow:
|
|
86
|
+
return self._workflow
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def context(self) -> Context:
|
|
90
|
+
return self._context
|
|
91
|
+
|
|
92
|
+
@asynccontextmanager
|
|
93
|
+
async def session(self,
|
|
94
|
+
user_manager=None,
|
|
95
|
+
http_connection: HTTPConnection | None = None,
|
|
96
|
+
user_message_id: str | None = None,
|
|
97
|
+
conversation_id: str | None = None,
|
|
98
|
+
user_input_callback: Callable[[InteractionPrompt], Awaitable[HumanResponse]] = None,
|
|
99
|
+
user_authentication_callback: Callable[[AuthProviderBaseConfig, AuthFlowType],
|
|
100
|
+
Awaitable[AuthenticatedContext | None]] = None):
|
|
101
|
+
|
|
102
|
+
token_user_input = None
|
|
103
|
+
if user_input_callback is not None:
|
|
104
|
+
token_user_input = self._context_state.user_input_callback.set(user_input_callback)
|
|
105
|
+
|
|
106
|
+
token_user_manager = None
|
|
107
|
+
if user_manager is not None:
|
|
108
|
+
token_user_manager = self._context_state.user_manager.set(user_manager)
|
|
109
|
+
|
|
110
|
+
token_user_authentication = None
|
|
111
|
+
if user_authentication_callback is not None:
|
|
112
|
+
token_user_authentication = self._context_state.user_auth_callback.set(user_authentication_callback)
|
|
113
|
+
|
|
114
|
+
if isinstance(http_connection, WebSocket):
|
|
115
|
+
self.set_metadata_from_websocket(http_connection, user_message_id, conversation_id)
|
|
116
|
+
|
|
117
|
+
if isinstance(http_connection, Request):
|
|
118
|
+
self.set_metadata_from_http_request(http_connection)
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
yield self
|
|
122
|
+
finally:
|
|
123
|
+
if token_user_manager is not None:
|
|
124
|
+
self._context_state.user_manager.reset(token_user_manager)
|
|
125
|
+
if token_user_input is not None:
|
|
126
|
+
self._context_state.user_input_callback.reset(token_user_input)
|
|
127
|
+
if token_user_authentication is not None:
|
|
128
|
+
self._context_state.user_auth_callback.reset(token_user_authentication)
|
|
129
|
+
|
|
130
|
+
@asynccontextmanager
|
|
131
|
+
async def run(self, message):
|
|
132
|
+
"""
|
|
133
|
+
Start a workflow run
|
|
134
|
+
"""
|
|
135
|
+
async with self._semaphore:
|
|
136
|
+
# Apply the saved context
|
|
137
|
+
for k, v in self._saved_context.items():
|
|
138
|
+
k.set(v)
|
|
139
|
+
|
|
140
|
+
async with self._workflow.run(message) as runner:
|
|
141
|
+
yield runner
|
|
142
|
+
|
|
143
|
+
def set_metadata_from_http_request(self, request: Request) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Extracts and sets user metadata request attributes from a HTTP request.
|
|
146
|
+
If request is None, no attributes are set.
|
|
147
|
+
"""
|
|
148
|
+
self._context.metadata._request.method = getattr(request, "method", None)
|
|
149
|
+
self._context.metadata._request.url_path = request.url.path
|
|
150
|
+
self._context.metadata._request.url_port = request.url.port
|
|
151
|
+
self._context.metadata._request.url_scheme = request.url.scheme
|
|
152
|
+
self._context.metadata._request.headers = request.headers
|
|
153
|
+
self._context.metadata._request.query_params = request.query_params
|
|
154
|
+
self._context.metadata._request.path_params = request.path_params
|
|
155
|
+
self._context.metadata._request.client_host = request.client.host
|
|
156
|
+
self._context.metadata._request.client_port = request.client.port
|
|
157
|
+
self._context.metadata._request.cookies = request.cookies
|
|
158
|
+
|
|
159
|
+
if request.headers.get("conversation-id"):
|
|
160
|
+
self._context_state.conversation_id.set(request.headers["conversation-id"])
|
|
161
|
+
|
|
162
|
+
if request.headers.get("user-message-id"):
|
|
163
|
+
self._context_state.user_message_id.set(request.headers["user-message-id"])
|
|
164
|
+
|
|
165
|
+
# W3C Trace Context header: traceparent: 00-<trace-id>-<span-id>-<flags>
|
|
166
|
+
traceparent = request.headers.get("traceparent")
|
|
167
|
+
if traceparent:
|
|
168
|
+
try:
|
|
169
|
+
parts = traceparent.split("-")
|
|
170
|
+
if len(parts) >= 4:
|
|
171
|
+
trace_id_hex = parts[1]
|
|
172
|
+
if len(trace_id_hex) == 32:
|
|
173
|
+
trace_id_int = uuid.UUID(trace_id_hex).int
|
|
174
|
+
self._context_state.workflow_trace_id.set(trace_id_int)
|
|
175
|
+
except Exception:
|
|
176
|
+
pass
|
|
177
|
+
|
|
178
|
+
if not self._context_state.workflow_trace_id.get():
|
|
179
|
+
workflow_trace_id = request.headers.get("workflow-trace-id")
|
|
180
|
+
if workflow_trace_id:
|
|
181
|
+
try:
|
|
182
|
+
self._context_state.workflow_trace_id.set(uuid.UUID(workflow_trace_id).int)
|
|
183
|
+
except Exception:
|
|
184
|
+
pass
|
|
185
|
+
|
|
186
|
+
workflow_run_id = request.headers.get("workflow-run-id")
|
|
187
|
+
if workflow_run_id:
|
|
188
|
+
self._context_state.workflow_run_id.set(workflow_run_id)
|
|
189
|
+
|
|
190
|
+
def set_metadata_from_websocket(self,
|
|
191
|
+
websocket: WebSocket,
|
|
192
|
+
user_message_id: str | None,
|
|
193
|
+
conversation_id: str | None) -> None:
|
|
194
|
+
"""
|
|
195
|
+
Extracts and sets user metadata for WebSocket connections.
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
# Extract cookies from WebSocket headers (similar to HTTP request)
|
|
199
|
+
if websocket and hasattr(websocket, 'scope') and 'headers' in websocket.scope:
|
|
200
|
+
cookies = {}
|
|
201
|
+
for header_name, header_value in websocket.scope.get('headers', []):
|
|
202
|
+
if header_name == b'cookie':
|
|
203
|
+
cookie_header = header_value.decode('utf-8')
|
|
204
|
+
# Parse cookie header: "name1=value1; name2=value2"
|
|
205
|
+
for cookie in cookie_header.split(';'):
|
|
206
|
+
cookie = cookie.strip()
|
|
207
|
+
if '=' in cookie:
|
|
208
|
+
name, value = cookie.split('=', 1)
|
|
209
|
+
cookies[name.strip()] = value.strip()
|
|
210
|
+
|
|
211
|
+
# Set cookies in metadata (same as HTTP request)
|
|
212
|
+
self._context.metadata._request.cookies = cookies
|
|
213
|
+
self._context_state.metadata.set(self._context.metadata)
|
|
214
|
+
|
|
215
|
+
if conversation_id is not None:
|
|
216
|
+
self._context_state.conversation_id.set(conversation_id)
|
|
217
|
+
|
|
218
|
+
if user_message_id is not None:
|
|
219
|
+
self._context_state.user_message_id.set(user_message_id)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Compatibility aliases with previous releases
|
|
223
|
+
AIQSessionManager = SessionManager
|
|
@@ -0,0 +1,130 @@
|
|
|
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 starlette.datastructures import Headers
|
|
17
|
+
from starlette.datastructures import QueryParams
|
|
18
|
+
|
|
19
|
+
from nat.data_models.api_server import Request
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RequestAttributes:
|
|
23
|
+
"""
|
|
24
|
+
The RequestAttributes class is responsible for managing user http and webscoket session
|
|
25
|
+
metadata. It provides a way to store and expose session attributes to workflow tools.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self) -> None:
|
|
29
|
+
self._request: Request = Request()
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def method(self) -> str | None:
|
|
33
|
+
"""
|
|
34
|
+
This property retrieves the HTTP method of the request.
|
|
35
|
+
It can be GET, POST, PUT, DELETE, etc.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
str | None
|
|
39
|
+
"""
|
|
40
|
+
return self._request.method
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def url_path(self) -> str | None:
|
|
44
|
+
"""
|
|
45
|
+
This property retrieves the path from the URL of the request.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
str | None
|
|
49
|
+
"""
|
|
50
|
+
return self._request.url_path
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def url_port(self) -> int | None:
|
|
54
|
+
"""
|
|
55
|
+
This property retrieves the port number from the URL of the request.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
int | None
|
|
59
|
+
"""
|
|
60
|
+
return self._request.url_port
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def url_scheme(self) -> str | None:
|
|
64
|
+
"""
|
|
65
|
+
This property retrieves the scheme from the URL of the request.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
str | None
|
|
69
|
+
"""
|
|
70
|
+
return self._request.url_scheme
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def headers(self) -> Headers | None:
|
|
74
|
+
"""
|
|
75
|
+
This property retrieves the headers from the request stored in a dictionary-like object.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Headers | None
|
|
79
|
+
"""
|
|
80
|
+
return self._request.headers
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def query_params(self) -> QueryParams | None:
|
|
84
|
+
"""
|
|
85
|
+
This property retrieves the query parameters from the request stored in a dictionary-like object.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
QueryParams | None
|
|
89
|
+
"""
|
|
90
|
+
return self._request.query_params
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def path_params(self) -> dict[str, str] | None:
|
|
94
|
+
"""
|
|
95
|
+
This property retrieves the path parameters from the request stored in a dictionary-like object.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
dict[str, str] | None
|
|
99
|
+
"""
|
|
100
|
+
return self._request.path_params
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def client_host(self) -> str | None:
|
|
104
|
+
"""
|
|
105
|
+
This property retrieves the clients remote hostname or IP address.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
str | None
|
|
109
|
+
"""
|
|
110
|
+
return self._request.client_host
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def client_port(self) -> int | None:
|
|
114
|
+
"""
|
|
115
|
+
This property retrieves the clients remote port number from which the client is connecting to.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
int | None
|
|
119
|
+
"""
|
|
120
|
+
return self._request.client_port
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def cookies(self) -> dict[str, str] | None:
|
|
124
|
+
"""
|
|
125
|
+
This property retrieves the cookies from the request stored in a dictionary-like object.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
dict[str, str] | None
|
|
129
|
+
"""
|
|
130
|
+
return self._request.cookies
|
nat/settings/__init__.py
ADDED
|
File without changes
|