nvidia-nat 1.2.0a20250813__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.
- nat/agent/__init__.py +0 -0
- nat/agent/base.py +239 -0
- nat/agent/dual_node.py +67 -0
- nat/agent/react_agent/__init__.py +0 -0
- nat/agent/react_agent/agent.py +355 -0
- nat/agent/react_agent/output_parser.py +104 -0
- nat/agent/react_agent/prompt.py +41 -0
- nat/agent/react_agent/register.py +149 -0
- nat/agent/reasoning_agent/__init__.py +0 -0
- nat/agent/reasoning_agent/reasoning_agent.py +225 -0
- nat/agent/register.py +23 -0
- nat/agent/rewoo_agent/__init__.py +0 -0
- nat/agent/rewoo_agent/agent.py +411 -0
- nat/agent/rewoo_agent/prompt.py +108 -0
- nat/agent/rewoo_agent/register.py +158 -0
- nat/agent/tool_calling_agent/__init__.py +0 -0
- nat/agent/tool_calling_agent/agent.py +119 -0
- nat/agent/tool_calling_agent/register.py +106 -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/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 +93 -0
- nat/authentication/oauth2/__init__.py +14 -0
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +107 -0
- nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +39 -0
- nat/authentication/oauth2/register.py +25 -0
- nat/authentication/register.py +21 -0
- nat/builder/__init__.py +0 -0
- nat/builder/builder.py +285 -0
- nat/builder/component_utils.py +316 -0
- nat/builder/context.py +270 -0
- nat/builder/embedder.py +24 -0
- nat/builder/eval_builder.py +161 -0
- nat/builder/evaluator.py +29 -0
- nat/builder/framework_enum.py +24 -0
- nat/builder/front_end.py +73 -0
- nat/builder/function.py +344 -0
- nat/builder/function_base.py +380 -0
- nat/builder/function_info.py +627 -0
- nat/builder/intermediate_step_manager.py +174 -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 +148 -0
- nat/builder/workflow_builder.py +1117 -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 +36 -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 +39 -0
- nat/cli/commands/info/list_channels.py +32 -0
- nat/cli/commands/info/list_components.py +129 -0
- nat/cli/commands/info/list_mcp.py +304 -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 +38 -0
- nat/cli/commands/registry/remove.py +108 -0
- nat/cli/commands/registry/search.py +155 -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 +246 -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 +16 -0
- nat/cli/commands/workflow/templates/pyproject.toml.j2 +22 -0
- nat/cli/commands/workflow/templates/register.py.j2 +5 -0
- nat/cli/commands/workflow/templates/workflow.py.j2 +36 -0
- nat/cli/commands/workflow/workflow.py +37 -0
- nat/cli/commands/workflow/workflow_commands.py +317 -0
- nat/cli/entrypoint.py +135 -0
- nat/cli/main.py +57 -0
- nat/cli/register_workflow.py +488 -0
- nat/cli/type_registry.py +1000 -0
- nat/data_models/__init__.py +14 -0
- nat/data_models/api_server.py +709 -0
- nat/data_models/authentication.py +231 -0
- nat/data_models/common.py +171 -0
- nat/data_models/component.py +58 -0
- nat/data_models/component_ref.py +168 -0
- nat/data_models/config.py +410 -0
- nat/data_models/dataset_handler.py +123 -0
- nat/data_models/discovery_metadata.py +334 -0
- nat/data_models/embedder.py +27 -0
- nat/data_models/evaluate.py +127 -0
- nat/data_models/evaluator.py +26 -0
- nat/data_models/front_end.py +26 -0
- nat/data_models/function.py +30 -0
- nat/data_models/function_dependencies.py +72 -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/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 +190 -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/ttc_strategy.py +30 -0
- nat/embedder/__init__.py +0 -0
- nat/embedder/langchain_client.py +41 -0
- nat/embedder/nim_embedder.py +59 -0
- nat/embedder/openai_embedder.py +43 -0
- nat/embedder/register.py +24 -0
- nat/eval/__init__.py +14 -0
- nat/eval/config.py +60 -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 +254 -0
- nat/eval/evaluate.py +510 -0
- nat/eval/evaluator/__init__.py +14 -0
- nat/eval/evaluator/base_evaluator.py +77 -0
- nat/eval/evaluator/evaluator_model.py +45 -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 +23 -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_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 +245 -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/output_uploader.py +140 -0
- nat/eval/utils/tqdm_position_registry.py +40 -0
- nat/eval/utils/weave_eval.py +184 -0
- nat/experimental/__init__.py +0 -0
- nat/experimental/decorators/__init__.py +0 -0
- nat/experimental/decorators/experimental_warning_decorator.py +134 -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 +224 -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 +66 -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 +36 -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 +159 -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 +233 -0
- nat/front_ends/console/console_front_end_config.py +32 -0
- nat/front_ends/console/console_front_end_plugin.py +96 -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 +107 -0
- nat/front_ends/fastapi/fastapi_front_end_config.py +242 -0
- nat/front_ends/fastapi/fastapi_front_end_controller.py +68 -0
- nat/front_ends/fastapi/fastapi_front_end_plugin.py +116 -0
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +1087 -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 +183 -0
- nat/front_ends/fastapi/main.py +72 -0
- nat/front_ends/fastapi/message_handler.py +309 -0
- nat/front_ends/fastapi/message_validator.py +354 -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/mcp/__init__.py +14 -0
- nat/front_ends/mcp/mcp_front_end_config.py +35 -0
- nat/front_ends/mcp/mcp_front_end_plugin.py +81 -0
- nat/front_ends/mcp/mcp_front_end_plugin_worker.py +143 -0
- nat/front_ends/mcp/register.py +27 -0
- nat/front_ends/mcp/tool_converter.py +242 -0
- nat/front_ends/register.py +22 -0
- nat/front_ends/simple_base/__init__.py +14 -0
- nat/front_ends/simple_base/simple_front_end_plugin_base.py +54 -0
- nat/llm/__init__.py +0 -0
- nat/llm/aws_bedrock_llm.py +57 -0
- nat/llm/nim_llm.py +46 -0
- nat/llm/openai_llm.py +46 -0
- nat/llm/register.py +23 -0
- nat/llm/utils/__init__.py +14 -0
- nat/llm/utils/env_config_value.py +94 -0
- nat/llm/utils/error.py +17 -0
- nat/memory/__init__.py +20 -0
- nat/memory/interfaces.py +183 -0
- nat/memory/models.py +112 -0
- nat/meta/module_to_distro.json +4 -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 +36 -0
- nat/object_store/register.py +20 -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 +322 -0
- nat/observability/exporter/raw_exporter.py +52 -0
- nat/observability/exporter/span_exporter.py +288 -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/resource_conflict_mixin.py +134 -0
- nat/observability/mixin/serialize_mixin.py +61 -0
- nat/observability/mixin/type_introspection_mixin.py +183 -0
- nat/observability/processor/__init__.py +14 -0
- nat/observability/processor/batching_processor.py +310 -0
- nat/observability/processor/callback_processor.py +42 -0
- nat/observability/processor/intermediate_step_serializer.py +28 -0
- nat/observability/processor/processor.py +71 -0
- nat/observability/register.py +96 -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 +627 -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 +290 -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 +131 -0
- nat/profiler/decorators/function_tracking.py +254 -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 +40 -0
- nat/profiler/forecasting/models/linear_model.py +196 -0
- nat/profiler/forecasting/models/random_forest_regressor.py +268 -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 +405 -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/profile_runner.py +473 -0
- nat/profiler/utils.py +184 -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 +571 -0
- nat/registry_handlers/pypi/__init__.py +0 -0
- nat/registry_handlers/pypi/pypi_handler.py +251 -0
- nat/registry_handlers/pypi/register_pypi.py +40 -0
- nat/registry_handlers/register.py +21 -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 +237 -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 +22 -0
- nat/runtime/__init__.py +14 -0
- nat/runtime/loader.py +219 -0
- nat/runtime/runner.py +195 -0
- nat/runtime/session.py +162 -0
- nat/runtime/user_metadata.py +130 -0
- nat/settings/__init__.py +0 -0
- nat/settings/global_settings.py +318 -0
- nat/test/.namespace +1 -0
- nat/tool/__init__.py +0 -0
- nat/tool/chat_completion.py +74 -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 +42 -0
- nat/tool/document_search.py +141 -0
- nat/tool/github_tools/__init__.py +0 -0
- nat/tool/github_tools/create_github_commit.py +133 -0
- nat/tool/github_tools/create_github_issue.py +87 -0
- nat/tool/github_tools/create_github_pr.py +106 -0
- nat/tool/github_tools/get_github_file.py +106 -0
- nat/tool/github_tools/get_github_issue.py +166 -0
- nat/tool/github_tools/get_github_pr.py +256 -0
- nat/tool/github_tools/update_github_issue.py +100 -0
- nat/tool/mcp/__init__.py +14 -0
- nat/tool/mcp/exceptions.py +142 -0
- nat/tool/mcp/mcp_client.py +255 -0
- nat/tool/mcp/mcp_tool.py +96 -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 +67 -0
- nat/tool/memory_tools/get_memory_tool.py +72 -0
- nat/tool/nvidia_rag.py +95 -0
- nat/tool/register.py +38 -0
- nat/tool/retriever.py +94 -0
- nat/tool/server_tools.py +66 -0
- nat/utils/__init__.py +0 -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/dump_distro_mapping.py +32 -0
- nat/utils/exception_handlers/__init__.py +0 -0
- nat/utils/exception_handlers/automatic_retries.py +289 -0
- nat/utils/exception_handlers/mcp.py +211 -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_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 +197 -0
- nat/utils/string_utils.py +38 -0
- nat/utils/type_converter.py +290 -0
- nat/utils/type_utils.py +484 -0
- nat/utils/url_utils.py +27 -0
- nvidia_nat-1.2.0a20250813.dist-info/METADATA +363 -0
- nvidia_nat-1.2.0a20250813.dist-info/RECORD +436 -0
- nvidia_nat-1.2.0a20250813.dist-info/WHEEL +5 -0
- nvidia_nat-1.2.0a20250813.dist-info/entry_points.txt +21 -0
- nvidia_nat-1.2.0a20250813.dist-info/licenses/LICENSE-3rd-party.txt +3686 -0
- nvidia_nat-1.2.0a20250813.dist-info/licenses/LICENSE.md +201 -0
- nvidia_nat-1.2.0a20250813.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from abc import ABC
|
|
18
|
+
from abc import abstractmethod
|
|
19
|
+
from collections.abc import AsyncGenerator
|
|
20
|
+
|
|
21
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Exporter(ABC):
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
async def start(self) -> AsyncGenerator[None]:
|
|
30
|
+
"""Subscribes to event stream and starts the exporter.
|
|
31
|
+
|
|
32
|
+
This is an async context manager that should be used with 'async with'.
|
|
33
|
+
The exporter is automatically stopped when exiting the context.
|
|
34
|
+
|
|
35
|
+
Usage::
|
|
36
|
+
|
|
37
|
+
.. code-block:: python
|
|
38
|
+
|
|
39
|
+
async with exporter.start():
|
|
40
|
+
# Exporter is now running and subscribed to events
|
|
41
|
+
# Your workflow code here
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
Note:
|
|
45
|
+
Implementations should use the @asynccontextmanager decorator.
|
|
46
|
+
"""
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
async def stop(self) -> None:
|
|
51
|
+
"""Unsubscribes to the event stream and stops the exporter."""
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def export(self, event: IntermediateStep) -> None:
|
|
56
|
+
"""This method is called on each event from the event stream to initiate the trace export.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
event (IntermediateStep): The event to be exported.
|
|
60
|
+
"""
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def on_error(self, exc: Exception) -> None:
|
|
65
|
+
"""Handle an error in the event subscription.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
exc (Exception): The error to handle.
|
|
69
|
+
"""
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def on_complete(self) -> None:
|
|
74
|
+
"""Handle the completion of the event stream.
|
|
75
|
+
|
|
76
|
+
This method is called when the event stream is complete.
|
|
77
|
+
"""
|
|
78
|
+
pass
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
from nat.builder.context import ContextState
|
|
19
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
20
|
+
from nat.observability.exporter.raw_exporter import RawExporter
|
|
21
|
+
from nat.observability.mixin.file_mixin import FileExportMixin
|
|
22
|
+
from nat.observability.processor.intermediate_step_serializer import IntermediateStepSerializer
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FileExporter(FileExportMixin, RawExporter[IntermediateStep, str]): # pylint: disable=R0901
|
|
28
|
+
"""A File exporter that exports telemetry traces to a local file."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, context_state: ContextState | None = None, **file_kwargs):
|
|
31
|
+
super().__init__(context_state=context_state, **file_kwargs)
|
|
32
|
+
self._processor = IntermediateStepSerializer()
|
|
33
|
+
self.add_processor(self._processor)
|
|
@@ -0,0 +1,322 @@
|
|
|
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 logging
|
|
18
|
+
from abc import abstractmethod
|
|
19
|
+
from collections.abc import Coroutine
|
|
20
|
+
from typing import Any
|
|
21
|
+
from typing import Generic
|
|
22
|
+
from typing import TypeVar
|
|
23
|
+
|
|
24
|
+
from nat.builder.context import ContextState
|
|
25
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
26
|
+
from nat.observability.exporter.base_exporter import BaseExporter
|
|
27
|
+
from nat.observability.mixin.type_introspection_mixin import TypeIntrospectionMixin
|
|
28
|
+
from nat.observability.processor.callback_processor import CallbackProcessor
|
|
29
|
+
from nat.observability.processor.processor import Processor
|
|
30
|
+
from nat.utils.type_utils import DecomposedType
|
|
31
|
+
from nat.utils.type_utils import override
|
|
32
|
+
|
|
33
|
+
PipelineInputT = TypeVar("PipelineInputT")
|
|
34
|
+
PipelineOutputT = TypeVar("PipelineOutputT")
|
|
35
|
+
|
|
36
|
+
logger = logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ProcessingExporter(Generic[PipelineInputT, PipelineOutputT], BaseExporter, TypeIntrospectionMixin):
|
|
40
|
+
"""A base class for telemetry exporters with processing pipeline support.
|
|
41
|
+
|
|
42
|
+
This class extends BaseExporter to add processor pipeline functionality.
|
|
43
|
+
It manages a chain of processors that can transform items before export.
|
|
44
|
+
|
|
45
|
+
The generic types work as follows:
|
|
46
|
+
- PipelineInputT: The type of items that enter the processing pipeline (e.g., Span)
|
|
47
|
+
- PipelineOutputT: The type of items after processing through the pipeline (e.g., converted format)
|
|
48
|
+
|
|
49
|
+
Key Features:
|
|
50
|
+
- Processor pipeline management (add, remove, clear)
|
|
51
|
+
- Type compatibility validation between processors
|
|
52
|
+
- Pipeline processing with error handling
|
|
53
|
+
- Automatic type validation before export
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def __init__(self, context_state: ContextState | None = None):
|
|
57
|
+
"""Initialize the processing exporter.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
context_state: The context state to use for the exporter.
|
|
61
|
+
"""
|
|
62
|
+
super().__init__(context_state)
|
|
63
|
+
self._processors: list[Processor] = [] # List of processors that implement process(item) -> item
|
|
64
|
+
|
|
65
|
+
def add_processor(self, processor: Processor) -> None:
|
|
66
|
+
"""Add a processor to the processing pipeline.
|
|
67
|
+
|
|
68
|
+
Processors are executed in the order they are added.
|
|
69
|
+
Processors can transform between any types (T -> U).
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
processor: The processor to add to the pipeline
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
# Check if the processor is compatible with the last processor in the pipeline
|
|
76
|
+
if len(self._processors) > 0:
|
|
77
|
+
try:
|
|
78
|
+
if not issubclass(processor.input_class, self._processors[-1].output_class):
|
|
79
|
+
raise ValueError(f"Processor {processor.__class__.__name__} input type {processor.input_type} "
|
|
80
|
+
f"is not compatible with the {self._processors[-1].__class__.__name__} "
|
|
81
|
+
f"output type {self._processors[-1].output_type}")
|
|
82
|
+
except TypeError:
|
|
83
|
+
# Handle cases where input_class or output_class are generic types that can't be used with issubclass
|
|
84
|
+
# Fall back to type comparison for generic types
|
|
85
|
+
logger.warning(
|
|
86
|
+
"Cannot use issubclass() for type compatibility check between "
|
|
87
|
+
"%s (%s) and %s (%s). Skipping compatibility check.",
|
|
88
|
+
processor.__class__.__name__,
|
|
89
|
+
processor.input_type,
|
|
90
|
+
self._processors[-1].__class__.__name__,
|
|
91
|
+
self._processors[-1].output_type)
|
|
92
|
+
self._processors.append(processor)
|
|
93
|
+
|
|
94
|
+
# Set up pipeline continuation callback for processors that support it
|
|
95
|
+
if isinstance(processor, CallbackProcessor):
|
|
96
|
+
# Create a callback that continues processing through the rest of the pipeline
|
|
97
|
+
async def pipeline_callback(item):
|
|
98
|
+
await self._continue_pipeline_after(processor, item)
|
|
99
|
+
|
|
100
|
+
processor.set_done_callback(pipeline_callback)
|
|
101
|
+
|
|
102
|
+
def remove_processor(self, processor: Processor) -> None:
|
|
103
|
+
"""Remove a processor from the processing pipeline.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
processor: The processor to remove from the pipeline
|
|
107
|
+
"""
|
|
108
|
+
if processor in self._processors:
|
|
109
|
+
self._processors.remove(processor)
|
|
110
|
+
|
|
111
|
+
def clear_processors(self) -> None:
|
|
112
|
+
"""Clear all processors from the pipeline."""
|
|
113
|
+
self._processors.clear()
|
|
114
|
+
|
|
115
|
+
async def _pre_start(self) -> None:
|
|
116
|
+
if len(self._processors) > 0:
|
|
117
|
+
first_processor = self._processors[0]
|
|
118
|
+
last_processor = self._processors[-1]
|
|
119
|
+
|
|
120
|
+
# validate that the first processor's input type is compatible with the exporter's input type
|
|
121
|
+
try:
|
|
122
|
+
if not issubclass(first_processor.input_class, self.input_class):
|
|
123
|
+
raise ValueError(f"Processor {first_processor.__class__.__name__} input type "
|
|
124
|
+
f"{first_processor.input_type} is not compatible with the "
|
|
125
|
+
f"{self.input_type} input type")
|
|
126
|
+
except TypeError as e:
|
|
127
|
+
# Handle cases where classes are generic types that can't be used with issubclass
|
|
128
|
+
logger.warning(
|
|
129
|
+
"Cannot validate type compatibility between %s (%s) "
|
|
130
|
+
"and exporter (%s): %s. Skipping validation.",
|
|
131
|
+
first_processor.__class__.__name__,
|
|
132
|
+
first_processor.input_type,
|
|
133
|
+
self.input_type,
|
|
134
|
+
e)
|
|
135
|
+
|
|
136
|
+
# Validate that the last processor's output type is compatible with the exporter's output type
|
|
137
|
+
try:
|
|
138
|
+
if not DecomposedType.is_type_compatible(last_processor.output_type, self.output_type):
|
|
139
|
+
raise ValueError(f"Processor {last_processor.__class__.__name__} output type "
|
|
140
|
+
f"{last_processor.output_type} is not compatible with the "
|
|
141
|
+
f"{self.output_type} output type")
|
|
142
|
+
except TypeError as e:
|
|
143
|
+
# Handle cases where classes are generic types that can't be used with issubclass
|
|
144
|
+
logger.warning(
|
|
145
|
+
"Cannot validate type compatibility between %s (%s) "
|
|
146
|
+
"and exporter (%s): %s. Skipping validation.",
|
|
147
|
+
last_processor.__class__.__name__,
|
|
148
|
+
last_processor.output_type,
|
|
149
|
+
self.output_type,
|
|
150
|
+
e)
|
|
151
|
+
|
|
152
|
+
async def _process_pipeline(self, item: PipelineInputT) -> PipelineOutputT:
|
|
153
|
+
"""Process item through all registered processors.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
item (PipelineInputT): The item to process (starts as PipelineInputT, can transform to PipelineOutputT)
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
PipelineOutputT: The processed item after running through all processors
|
|
160
|
+
"""
|
|
161
|
+
return await self._process_through_processors(self._processors, item) # type: ignore
|
|
162
|
+
|
|
163
|
+
async def _process_through_processors(self, processors: list[Processor], item: Any) -> Any:
|
|
164
|
+
"""Process an item through a list of processors.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
processors (list[Processor]): List of processors to run the item through
|
|
168
|
+
item (Any): The item to process
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
The processed item after running through all processors
|
|
172
|
+
"""
|
|
173
|
+
processed_item = item
|
|
174
|
+
for processor in processors:
|
|
175
|
+
try:
|
|
176
|
+
processed_item = await processor.process(processed_item)
|
|
177
|
+
except Exception as e:
|
|
178
|
+
logger.error("Error in processor %s: %s", processor.__class__.__name__, e, exc_info=True)
|
|
179
|
+
# Continue with unprocessed item rather than failing
|
|
180
|
+
return processed_item
|
|
181
|
+
|
|
182
|
+
async def _export_final_item(self, processed_item: Any, raise_on_invalid: bool = False) -> None:
|
|
183
|
+
"""Export a processed item with proper type handling.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
processed_item (Any): The item to export
|
|
187
|
+
raise_on_invalid (bool): If True, raise ValueError for invalid types instead of logging warning
|
|
188
|
+
"""
|
|
189
|
+
if isinstance(processed_item, list):
|
|
190
|
+
if len(processed_item) > 0:
|
|
191
|
+
await self.export_processed(processed_item)
|
|
192
|
+
else:
|
|
193
|
+
logger.debug("Skipping export of empty batch")
|
|
194
|
+
elif isinstance(processed_item, self.output_class):
|
|
195
|
+
await self.export_processed(processed_item)
|
|
196
|
+
else:
|
|
197
|
+
if raise_on_invalid:
|
|
198
|
+
raise ValueError(f"Processed item {processed_item} is not a valid output type. "
|
|
199
|
+
f"Expected {self.output_class} or list[{self.output_class}]")
|
|
200
|
+
logger.warning("Processed item %s is not a valid output type for export", processed_item)
|
|
201
|
+
|
|
202
|
+
async def _continue_pipeline_after(self, source_processor: Processor, item: Any) -> None:
|
|
203
|
+
"""Continue processing an item through the pipeline after a specific processor.
|
|
204
|
+
|
|
205
|
+
This is used when processors (like BatchingProcessor) need to inject items
|
|
206
|
+
back into the pipeline flow to continue through downstream processors.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
source_processor (Processor): The processor that generated the item
|
|
210
|
+
item (Any): The item to continue processing through the remaining pipeline
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
# Find the source processor's position
|
|
214
|
+
try:
|
|
215
|
+
source_index = self._processors.index(source_processor)
|
|
216
|
+
except ValueError:
|
|
217
|
+
logger.error("Source processor %s not found in pipeline", source_processor.__class__.__name__)
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
# Process through remaining processors (skip the source processor)
|
|
221
|
+
remaining_processors = self._processors[source_index + 1:]
|
|
222
|
+
processed_item = await self._process_through_processors(remaining_processors, item)
|
|
223
|
+
|
|
224
|
+
# Export the final result
|
|
225
|
+
await self._export_final_item(processed_item)
|
|
226
|
+
|
|
227
|
+
except Exception as e:
|
|
228
|
+
logger.error("Failed to continue pipeline processing after %s: %s",
|
|
229
|
+
source_processor.__class__.__name__,
|
|
230
|
+
e,
|
|
231
|
+
exc_info=True)
|
|
232
|
+
|
|
233
|
+
async def _export_with_processing(self, item: PipelineInputT) -> None:
|
|
234
|
+
"""Export an item after processing it through the pipeline.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
item: The item to export
|
|
238
|
+
"""
|
|
239
|
+
try:
|
|
240
|
+
# Then, run through the processor pipeline
|
|
241
|
+
final_item: PipelineOutputT = await self._process_pipeline(item)
|
|
242
|
+
|
|
243
|
+
# Handle different output types from batch processors
|
|
244
|
+
if isinstance(final_item, list) and len(final_item) == 0:
|
|
245
|
+
logger.debug("Skipping export of empty batch from processor pipeline")
|
|
246
|
+
return
|
|
247
|
+
|
|
248
|
+
await self._export_final_item(final_item, raise_on_invalid=True)
|
|
249
|
+
|
|
250
|
+
except Exception as e:
|
|
251
|
+
logger.error("Failed to export item '%s': %s", item, e, exc_info=True)
|
|
252
|
+
raise
|
|
253
|
+
|
|
254
|
+
@override
|
|
255
|
+
def export(self, event: IntermediateStep) -> None:
|
|
256
|
+
"""Export an IntermediateStep event through the processing pipeline.
|
|
257
|
+
|
|
258
|
+
This method converts the IntermediateStep to the expected PipelineInputT type,
|
|
259
|
+
processes it through the pipeline, and exports the result.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
event (IntermediateStep): The event to be exported.
|
|
263
|
+
"""
|
|
264
|
+
# Convert IntermediateStep to PipelineInputT and create export task
|
|
265
|
+
if isinstance(event, self.input_class):
|
|
266
|
+
input_item: PipelineInputT = event # type: ignore
|
|
267
|
+
coro = self._export_with_processing(input_item)
|
|
268
|
+
self._create_export_task(coro)
|
|
269
|
+
else:
|
|
270
|
+
logger.warning("Event %s is not compatible with input type %s", event, self.input_type)
|
|
271
|
+
|
|
272
|
+
@abstractmethod
|
|
273
|
+
async def export_processed(self, item: PipelineOutputT | list[PipelineOutputT]) -> None:
|
|
274
|
+
"""Export the processed item.
|
|
275
|
+
|
|
276
|
+
This method must be implemented by concrete exporters to handle
|
|
277
|
+
the actual export logic after the item has been processed through the pipeline.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
item: The processed item to export (PipelineOutputT type)
|
|
281
|
+
"""
|
|
282
|
+
pass
|
|
283
|
+
|
|
284
|
+
def _create_export_task(self, coro: Coroutine):
|
|
285
|
+
"""Create task with minimal overhead but proper tracking."""
|
|
286
|
+
if not self._running:
|
|
287
|
+
logger.warning("%s: Attempted to create export task while not running", self.name)
|
|
288
|
+
return
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
task = asyncio.create_task(coro)
|
|
292
|
+
self._tasks.add(task)
|
|
293
|
+
task.add_done_callback(self._tasks.discard)
|
|
294
|
+
|
|
295
|
+
except Exception as e:
|
|
296
|
+
logger.error("%s: Failed to create task: %s", self.name, e, exc_info=True)
|
|
297
|
+
raise
|
|
298
|
+
|
|
299
|
+
@override
|
|
300
|
+
async def _cleanup(self):
|
|
301
|
+
"""Enhanced cleanup that shuts down all shutdown-aware processors.
|
|
302
|
+
|
|
303
|
+
Each processor is responsible for its own cleanup, including routing
|
|
304
|
+
any final batches through the remaining pipeline via their done callbacks.
|
|
305
|
+
"""
|
|
306
|
+
# Shutdown all processors that support it
|
|
307
|
+
shutdown_tasks = []
|
|
308
|
+
for processor in getattr(self, '_processors', []):
|
|
309
|
+
shutdown_method = getattr(processor, 'shutdown', None)
|
|
310
|
+
if shutdown_method:
|
|
311
|
+
logger.debug("Shutting down processor: %s", processor.__class__.__name__)
|
|
312
|
+
shutdown_tasks.append(shutdown_method())
|
|
313
|
+
|
|
314
|
+
if shutdown_tasks:
|
|
315
|
+
try:
|
|
316
|
+
await asyncio.gather(*shutdown_tasks, return_exceptions=True)
|
|
317
|
+
logger.debug("Successfully shut down %d processors", len(shutdown_tasks))
|
|
318
|
+
except Exception as e:
|
|
319
|
+
logger.error("Error shutting down processors: %s", e, exc_info=True)
|
|
320
|
+
|
|
321
|
+
# Call parent cleanup
|
|
322
|
+
await super()._cleanup()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from abc import abstractmethod
|
|
18
|
+
from typing import TypeVar
|
|
19
|
+
|
|
20
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
21
|
+
from nat.observability.exporter.processing_exporter import ProcessingExporter
|
|
22
|
+
from nat.utils.type_utils import override
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
InputT = TypeVar("InputT")
|
|
27
|
+
OutputT = TypeVar("OutputT")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RawExporter(ProcessingExporter[InputT, OutputT]):
|
|
31
|
+
"""A base class for exporting raw intermediate steps.
|
|
32
|
+
|
|
33
|
+
This class provides a base implementation for telemetry exporters that
|
|
34
|
+
work directly with IntermediateStep objects. It can optionally process
|
|
35
|
+
them through a pipeline before export.
|
|
36
|
+
|
|
37
|
+
The flow is: IntermediateStep -> [Processing Pipeline] -> OutputT -> Export
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
context_state (AIQContextState, optional): The context state to use for the exporter. Defaults to None.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
async def export_processed(self, item: OutputT):
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
@override
|
|
48
|
+
def export(self, event: IntermediateStep):
|
|
49
|
+
if not isinstance(event, IntermediateStep):
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
self._create_export_task(self._export_with_processing(event)) # type: ignore
|