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
|
@@ -0,0 +1,125 @@
|
|
|
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 collections.abc import Callable
|
|
19
|
+
from typing import Any
|
|
20
|
+
from typing import TypeVar
|
|
21
|
+
|
|
22
|
+
from nat.observability.processor.redaction.redaction_processor import RedactionContext
|
|
23
|
+
from nat.observability.processor.redaction.redaction_processor import RedactionContextState
|
|
24
|
+
from nat.observability.processor.redaction.redaction_processor import RedactionInputT
|
|
25
|
+
from nat.observability.processor.redaction.redaction_processor import RedactionProcessor
|
|
26
|
+
from nat.utils.type_utils import override
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
# Type variable for the data type extracted from context
|
|
31
|
+
RedactionDataT = TypeVar('RedactionDataT')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ContextualRedactionProcessor(RedactionProcessor[RedactionInputT, RedactionDataT]):
|
|
35
|
+
"""Generic processor with context-aware caching for any data type.
|
|
36
|
+
|
|
37
|
+
Provides a framework for redaction processors that need to:
|
|
38
|
+
- Extract data from the request context (headers, cookies, query params, etc.)
|
|
39
|
+
- Execute callbacks to determine redaction decisions
|
|
40
|
+
- Cache results within the request context to avoid redundant callback executions
|
|
41
|
+
- Handle race conditions with atomic operations
|
|
42
|
+
|
|
43
|
+
This class handles all the generic caching, context management, and callback
|
|
44
|
+
execution logic. Subclasses only need to implement data extraction and validation.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
callback: Callable that determines if redaction should occur based on extracted data
|
|
48
|
+
enabled: Whether the processor is enabled
|
|
49
|
+
force_redact: If True, always redact regardless of data checks
|
|
50
|
+
redaction_value: The value to replace redacted attributes with
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
callback: Callable[..., Any],
|
|
56
|
+
enabled: bool,
|
|
57
|
+
force_redact: bool,
|
|
58
|
+
redaction_value: str,
|
|
59
|
+
):
|
|
60
|
+
self.callback = callback
|
|
61
|
+
self.enabled = enabled
|
|
62
|
+
self.force_redact = force_redact
|
|
63
|
+
self.redaction_value = redaction_value
|
|
64
|
+
self._redaction_context = RedactionContext(RedactionContextState())
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def extract_data_from_context(self) -> RedactionDataT | None:
|
|
68
|
+
"""Extract the relevant data from the context for redaction decision.
|
|
69
|
+
|
|
70
|
+
This method must be implemented by subclasses to extract their specific
|
|
71
|
+
data type (headers, cookies, query params, etc.) from the request context
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
RedactionDataT | None: The extracted data, or None if no relevant data found
|
|
75
|
+
"""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
@abstractmethod
|
|
79
|
+
def validate_data(self, data: RedactionDataT) -> bool:
|
|
80
|
+
"""Validate that the extracted data is suitable for callback execution.
|
|
81
|
+
|
|
82
|
+
This method allows subclasses to implement their own validation logic
|
|
83
|
+
(e.g., checking if headers exist, if cookies are not empty, etc.).
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
data (RedactionDataT): The extracted data to validate
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
bool: True if the data is valid for callback execution, False otherwise
|
|
90
|
+
"""
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
@override
|
|
94
|
+
async def should_redact(self, item: RedactionInputT) -> bool:
|
|
95
|
+
"""Determine if this span should be redacted based on extracted data.
|
|
96
|
+
|
|
97
|
+
Extracts the relevant data from the context, validates it, and passes it to the
|
|
98
|
+
callback function to determine if redaction should occur. Results are cached
|
|
99
|
+
within the request context to avoid redundant callback executions.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
item (RedactionInputT): The item to check
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
bool: True if the span should be redacted, False otherwise
|
|
106
|
+
"""
|
|
107
|
+
# If force_redact is enabled, always redact regardless of other conditions
|
|
108
|
+
if self.force_redact:
|
|
109
|
+
return True
|
|
110
|
+
|
|
111
|
+
if not self.enabled:
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
# Extract data using subclass implementation
|
|
115
|
+
data = self.extract_data_from_context()
|
|
116
|
+
if data is None:
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
# Validate data using subclass implementation
|
|
120
|
+
if not self.validate_data(data):
|
|
121
|
+
return False
|
|
122
|
+
|
|
123
|
+
# Use the generic caching framework for callback execution
|
|
124
|
+
async with self._redaction_context.redaction_manager() as manager:
|
|
125
|
+
return await manager.redaction_check(self.callback, data)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from collections.abc import Callable
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
from nat.data_models.span import Span
|
|
20
|
+
from nat.observability.processor.redaction.contextual_redaction_processor import ContextualRedactionProcessor
|
|
21
|
+
from nat.observability.processor.redaction.redaction_processor import RedactionDataT
|
|
22
|
+
from nat.utils.type_utils import override
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ContextualSpanRedactionProcessor(ContextualRedactionProcessor[Span, RedactionDataT]):
|
|
26
|
+
"""Processor that redacts the Span based on the Span attributes.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
attributes: List of span attribute keys to redact
|
|
30
|
+
callback: Callable that determines if redaction should occur
|
|
31
|
+
enabled: Whether the processor is enabled
|
|
32
|
+
force_redact: If True, always redact regardless of callback
|
|
33
|
+
redaction_value: The value to replace redacted attributes with
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self,
|
|
37
|
+
attributes: list[str],
|
|
38
|
+
callback: Callable[..., Any],
|
|
39
|
+
enabled: bool,
|
|
40
|
+
force_redact: bool,
|
|
41
|
+
redaction_value: str,
|
|
42
|
+
redaction_tag: str | None = None):
|
|
43
|
+
super().__init__(callback=callback, enabled=enabled, force_redact=force_redact, redaction_value=redaction_value)
|
|
44
|
+
self.attributes = attributes
|
|
45
|
+
self.redaction_tag = redaction_tag
|
|
46
|
+
|
|
47
|
+
@override
|
|
48
|
+
async def redact_item(self, item: Span) -> Span:
|
|
49
|
+
"""Redact specified attributes in the span.
|
|
50
|
+
|
|
51
|
+
Replaces the values of configured attributes with the redaction value.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
item (Span): The span to redact
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Span: The span with redacted attributes
|
|
58
|
+
"""
|
|
59
|
+
for key in self.attributes:
|
|
60
|
+
if key in item.attributes:
|
|
61
|
+
item.set_attribute(key, self.redaction_value)
|
|
62
|
+
|
|
63
|
+
if self.redaction_tag:
|
|
64
|
+
item.set_attribute(self.redaction_tag, True)
|
|
65
|
+
|
|
66
|
+
return item
|
|
@@ -0,0 +1,177 @@
|
|
|
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 collections.abc import AsyncGenerator
|
|
19
|
+
from collections.abc import Callable
|
|
20
|
+
from contextlib import asynccontextmanager
|
|
21
|
+
from contextvars import ContextVar
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
from dataclasses import field
|
|
24
|
+
from typing import Any
|
|
25
|
+
from typing import Generic
|
|
26
|
+
from typing import TypeVar
|
|
27
|
+
|
|
28
|
+
from nat.observability.processor.processor import Processor
|
|
29
|
+
from nat.utils.callable_utils import ainvoke_any
|
|
30
|
+
from nat.utils.type_utils import override
|
|
31
|
+
|
|
32
|
+
RedactionInputT = TypeVar('RedactionInputT')
|
|
33
|
+
RedactionDataT = TypeVar('RedactionDataT')
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class RedactionProcessor(Processor[RedactionInputT, RedactionInputT], Generic[RedactionInputT, RedactionDataT]):
|
|
39
|
+
"""Abstract base class for redaction processors."""
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
async def should_redact(self, item: RedactionInputT) -> bool:
|
|
43
|
+
"""Determine if this item should be redacted.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
item (RedactionInputT): The item to check.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
bool: True if the item should be redacted, False otherwise.
|
|
50
|
+
"""
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
async def redact_item(self, item: RedactionInputT) -> RedactionInputT:
|
|
55
|
+
"""Redact the item.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
item (RedactionInputT): The item to redact.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
RedactionInputT: The redacted item.
|
|
62
|
+
"""
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
@override
|
|
66
|
+
async def process(self, item: RedactionInputT) -> RedactionInputT:
|
|
67
|
+
"""Perform redaction on the item if it should be redacted.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
item (RedactionInputT): The item to process.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
RedactionInputT: The processed item.
|
|
74
|
+
"""
|
|
75
|
+
if await self.should_redact(item):
|
|
76
|
+
return await self.redact_item(item)
|
|
77
|
+
return item
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class RedactionContextState:
|
|
82
|
+
"""Generic context state for redaction results.
|
|
83
|
+
|
|
84
|
+
Stores the redaction result in a context variable to avoid redundant
|
|
85
|
+
callback executions within the same request context.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
redaction_result: ContextVar[bool
|
|
89
|
+
| None] = field(default_factory=lambda: ContextVar("redaction_result", default=None))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class RedactionManager(Generic[RedactionDataT]):
|
|
93
|
+
"""Generic manager for atomic redaction operations.
|
|
94
|
+
|
|
95
|
+
Handles state mutations and ensures atomic callback execution
|
|
96
|
+
with proper result caching within a request context.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
RedactionDataT: The type of data being processed for redaction decisions.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, context_state: RedactionContextState):
|
|
103
|
+
self._context_state = context_state
|
|
104
|
+
|
|
105
|
+
def set_redaction_result(self, result: bool) -> None:
|
|
106
|
+
"""Set the redaction result in the context.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
result (bool): The redaction result to cache.
|
|
110
|
+
"""
|
|
111
|
+
self._context_state.redaction_result.set(result)
|
|
112
|
+
|
|
113
|
+
def clear_redaction_result(self) -> None:
|
|
114
|
+
"""Clear the cached redaction result from the context."""
|
|
115
|
+
self._context_state.redaction_result.set(None)
|
|
116
|
+
|
|
117
|
+
async def redaction_check(self, callback: Callable[..., Any], data: RedactionDataT) -> bool:
|
|
118
|
+
"""Execute redaction callback with atomic result caching.
|
|
119
|
+
|
|
120
|
+
Checks for existing cached results first, then executes the callback
|
|
121
|
+
and caches the result atomically. Since data is static per request,
|
|
122
|
+
subsequent calls within the same context return the cached result.
|
|
123
|
+
|
|
124
|
+
Supports sync/async functions, generators, and async generators.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
callback (Callable[..., Any]): The callback to execute (sync/async function, generator, etc.).
|
|
128
|
+
data (RedactionDataT): The data to pass to the callback for redaction decision.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
bool: True if the item should be redacted, False otherwise.
|
|
132
|
+
"""
|
|
133
|
+
# Check if we already have a result for this context
|
|
134
|
+
existing_result = self._context_state.redaction_result.get()
|
|
135
|
+
if existing_result is not None:
|
|
136
|
+
return existing_result
|
|
137
|
+
|
|
138
|
+
# Execute callback and cache result
|
|
139
|
+
result_value = await ainvoke_any(callback, data)
|
|
140
|
+
result = bool(result_value)
|
|
141
|
+
self.set_redaction_result(result)
|
|
142
|
+
return result
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class RedactionContext(Generic[RedactionDataT]):
|
|
146
|
+
"""Generic context provider for redaction operations.
|
|
147
|
+
|
|
148
|
+
Provides read-only access to redaction state and manages the
|
|
149
|
+
RedactionManager lifecycle through async context managers.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
RedactionDataT: The type of data being processed for redaction decisions.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
def __init__(self, context: RedactionContextState):
|
|
156
|
+
self._context_state: RedactionContextState = context
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def redaction_result(self) -> bool | None:
|
|
160
|
+
"""Get the current redaction result from context.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
bool | None: The cached redaction result, or None if not set.
|
|
164
|
+
"""
|
|
165
|
+
return self._context_state.redaction_result.get()
|
|
166
|
+
|
|
167
|
+
@asynccontextmanager
|
|
168
|
+
async def redaction_manager(self) -> AsyncGenerator[RedactionManager[RedactionDataT], None]:
|
|
169
|
+
"""Provide a redaction manager within an async context.
|
|
170
|
+
|
|
171
|
+
Creates and yields a RedactionManager instance for atomic
|
|
172
|
+
redaction operations within the current context.
|
|
173
|
+
|
|
174
|
+
Yields:
|
|
175
|
+
RedactionManager[RedactionDataT]: Manager instance for redaction operations.
|
|
176
|
+
"""
|
|
177
|
+
yield RedactionManager(self._context_state)
|
|
@@ -0,0 +1,92 @@
|
|
|
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 collections.abc import Callable
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from starlette.datastructures import Headers
|
|
21
|
+
|
|
22
|
+
from nat.builder.context import Context
|
|
23
|
+
from nat.observability.processor.redaction.contextual_span_redaction_processor import ContextualSpanRedactionProcessor
|
|
24
|
+
from nat.utils.type_utils import override
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SpanHeaderRedactionProcessor(ContextualSpanRedactionProcessor[dict[str, Any]]):
|
|
30
|
+
"""Processor that redacts the Span based on multiple headers and callback logic.
|
|
31
|
+
|
|
32
|
+
Uses context-scoped atomic updates to avoid redundant callback executions within a single context.
|
|
33
|
+
Since headers are static per request, the callback result is cached for the entire context using
|
|
34
|
+
an asynccontextmanager to ensure atomic operations.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
headers: List of header keys to extract and pass to the callback
|
|
38
|
+
attributes: List of Span attribute keys to redact
|
|
39
|
+
callback: Callable that determines if redaction should occur
|
|
40
|
+
enabled: Whether the processor is enabled (default: True)
|
|
41
|
+
force_redact: If True, always redact regardless of header checks (default: False)
|
|
42
|
+
redaction_value: The value to replace redacted attributes with (default: "[REDACTED]")
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self,
|
|
46
|
+
headers: list[str],
|
|
47
|
+
attributes: list[str],
|
|
48
|
+
callback: Callable[..., Any],
|
|
49
|
+
enabled: bool = True,
|
|
50
|
+
force_redact: bool = False,
|
|
51
|
+
redaction_value: str = "[REDACTED]",
|
|
52
|
+
redaction_tag: str | None = None):
|
|
53
|
+
# Initialize the base class with common parameters
|
|
54
|
+
super().__init__(attributes=attributes,
|
|
55
|
+
callback=callback,
|
|
56
|
+
enabled=enabled,
|
|
57
|
+
force_redact=force_redact,
|
|
58
|
+
redaction_value=redaction_value,
|
|
59
|
+
redaction_tag=redaction_tag)
|
|
60
|
+
# Store header-specific configuration
|
|
61
|
+
self.headers = headers
|
|
62
|
+
|
|
63
|
+
@override
|
|
64
|
+
def extract_data_from_context(self) -> dict[str, Any] | None:
|
|
65
|
+
"""Extract header data from the context.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
dict[str, Any] | None: Dictionary of header names to values, or None if no headers.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
context = Context.get()
|
|
72
|
+
headers: Headers | None = context.metadata.headers
|
|
73
|
+
|
|
74
|
+
if headers is None or not self.headers:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
header_map: dict[str, Any] = {header: headers.get(header, None) for header in self.headers}
|
|
78
|
+
|
|
79
|
+
return header_map
|
|
80
|
+
|
|
81
|
+
@override
|
|
82
|
+
def validate_data(self, data: dict[str, Any]) -> bool:
|
|
83
|
+
"""Validate that the extracted headers are suitable for callback execution.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
data (dict[str, Any]): The extracted header dictionary.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
bool: True if headers exist and are not all None, False otherwise.
|
|
90
|
+
"""
|
|
91
|
+
# Skip callback if no headers were found (all None values)
|
|
92
|
+
return bool(data) and not all(value is None for value in data.values())
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
from collections.abc import Mapping
|
|
19
|
+
from enum import Enum
|
|
20
|
+
|
|
21
|
+
from nat.data_models.span import Span
|
|
22
|
+
from nat.observability.processor.processor import Processor
|
|
23
|
+
from nat.utils.type_utils import override
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SpanTaggingProcessor(Processor[Span, Span]):
|
|
29
|
+
"""Processor that tags spans with multiple key-value metadata attributes.
|
|
30
|
+
|
|
31
|
+
This processor adds custom tags to spans by setting attributes with a configurable prefix.
|
|
32
|
+
Tags are applied for each key-value pair in the tags dictionary. The processor uses
|
|
33
|
+
a span prefix (configurable via NAT_SPAN_PREFIX environment variable) to namespace
|
|
34
|
+
the tag attributes.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
tags: Mapping of tag keys to their values. Values can be enums (converted to strings) or strings
|
|
38
|
+
span_prefix: The prefix to use for tag attributes (default: from NAT_SPAN_PREFIX env var or "nat")
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, tags: Mapping[str, Enum | str] | None = None, span_prefix: str | None = None):
|
|
42
|
+
self.tags = tags or {}
|
|
43
|
+
|
|
44
|
+
if span_prefix is None:
|
|
45
|
+
span_prefix = os.getenv("NAT_SPAN_PREFIX", "nat").strip() or "nat"
|
|
46
|
+
|
|
47
|
+
self._span_prefix = span_prefix
|
|
48
|
+
|
|
49
|
+
@override
|
|
50
|
+
async def process(self, item: Span) -> Span:
|
|
51
|
+
"""Tag the span with all configured tags.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
item (Span): The span to tag
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Span: The tagged span with all configured tags applied
|
|
58
|
+
"""
|
|
59
|
+
for tag_key, tag_value in self.tags.items():
|
|
60
|
+
key = str(tag_key).strip()
|
|
61
|
+
if not key:
|
|
62
|
+
continue
|
|
63
|
+
value_str = str(tag_value.value) if isinstance(tag_value, Enum) else str(tag_value)
|
|
64
|
+
if value_str == "":
|
|
65
|
+
continue
|
|
66
|
+
item.set_attribute(f"{self._span_prefix}.{key}", value_str)
|
|
67
|
+
|
|
68
|
+
return item
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
from pydantic import Field
|
|
19
|
+
|
|
20
|
+
from nat.builder.builder import Builder
|
|
21
|
+
from nat.cli.register_workflow import register_logging_method
|
|
22
|
+
from nat.cli.register_workflow import register_telemetry_exporter
|
|
23
|
+
from nat.data_models.logging import LoggingBaseConfig
|
|
24
|
+
from nat.data_models.telemetry_exporter import TelemetryExporterBaseConfig
|
|
25
|
+
from nat.observability.mixin.file_mode import FileMode
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class FileTelemetryExporterConfig(TelemetryExporterBaseConfig, name="file"):
|
|
31
|
+
"""A telemetry exporter that writes runtime traces to local files with optional rolling."""
|
|
32
|
+
|
|
33
|
+
output_path: str = Field(description="Output path for logs. When rolling is disabled: exact file path. "
|
|
34
|
+
"When rolling is enabled: directory path or file path (directory + base name).")
|
|
35
|
+
project: str = Field(description="Name to affiliate with this application.")
|
|
36
|
+
mode: FileMode = Field(
|
|
37
|
+
default=FileMode.APPEND,
|
|
38
|
+
description="File write mode: 'append' to add to existing file or 'overwrite' to start fresh.")
|
|
39
|
+
enable_rolling: bool = Field(default=False, description="Enable rolling log files based on size limits.")
|
|
40
|
+
max_file_size: int = Field(
|
|
41
|
+
default=10 * 1024 * 1024, # 10MB
|
|
42
|
+
description="Maximum file size in bytes before rolling to a new file.")
|
|
43
|
+
max_files: int = Field(default=5, description="Maximum number of rolled files to keep.")
|
|
44
|
+
cleanup_on_init: bool = Field(default=False, description="Clean up old files during initialization.")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@register_telemetry_exporter(config_type=FileTelemetryExporterConfig)
|
|
48
|
+
async def file_telemetry_exporter(config: FileTelemetryExporterConfig, builder: Builder):
|
|
49
|
+
"""
|
|
50
|
+
Build and return a FileExporter for file-based telemetry export with optional rolling.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
from nat.observability.exporter.file_exporter import FileExporter
|
|
54
|
+
|
|
55
|
+
yield FileExporter(output_path=config.output_path,
|
|
56
|
+
project=config.project,
|
|
57
|
+
mode=config.mode,
|
|
58
|
+
enable_rolling=config.enable_rolling,
|
|
59
|
+
max_file_size=config.max_file_size,
|
|
60
|
+
max_files=config.max_files,
|
|
61
|
+
cleanup_on_init=config.cleanup_on_init)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ConsoleLoggingMethodConfig(LoggingBaseConfig, name="console"):
|
|
65
|
+
"""A logger to write runtime logs to the console."""
|
|
66
|
+
|
|
67
|
+
level: str = Field(description="The logging level of console logger.")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@register_logging_method(config_type=ConsoleLoggingMethodConfig)
|
|
71
|
+
async def console_logging_method(config: ConsoleLoggingMethodConfig, builder: Builder):
|
|
72
|
+
"""
|
|
73
|
+
Build and return a StreamHandler for console-based logging.
|
|
74
|
+
"""
|
|
75
|
+
import sys
|
|
76
|
+
|
|
77
|
+
level = getattr(logging, config.level.upper(), logging.INFO)
|
|
78
|
+
handler = logging.StreamHandler(stream=sys.stdout)
|
|
79
|
+
handler.setLevel(level)
|
|
80
|
+
|
|
81
|
+
# Set formatter to match the default CLI format
|
|
82
|
+
formatter = logging.Formatter(
|
|
83
|
+
fmt="%(asctime)s - %(levelname)-8s - %(name)s:%(lineno)d - %(message)s",
|
|
84
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
85
|
+
)
|
|
86
|
+
handler.setFormatter(formatter)
|
|
87
|
+
|
|
88
|
+
yield handler
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class FileLoggingMethod(LoggingBaseConfig, name="file"):
|
|
92
|
+
"""A logger to write runtime logs to a file."""
|
|
93
|
+
|
|
94
|
+
path: str = Field(description="The file path to save the logging output.")
|
|
95
|
+
level: str = Field(description="The logging level of file logger.")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@register_logging_method(config_type=FileLoggingMethod)
|
|
99
|
+
async def file_logging_method(config: FileLoggingMethod, builder: Builder):
|
|
100
|
+
"""
|
|
101
|
+
Build and return a FileHandler for file-based logging.
|
|
102
|
+
"""
|
|
103
|
+
level = getattr(logging, config.level.upper(), logging.INFO)
|
|
104
|
+
handler = logging.FileHandler(filename=config.path, mode="a", encoding="utf-8")
|
|
105
|
+
handler.setLevel(level)
|
|
106
|
+
|
|
107
|
+
# Set formatter to match the default CLI format
|
|
108
|
+
formatter = logging.Formatter(
|
|
109
|
+
fmt="%(asctime)s - %(levelname)-8s - %(name)s:%(lineno)d - %(message)s",
|
|
110
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
111
|
+
)
|
|
112
|
+
handler.setFormatter(formatter)
|
|
113
|
+
|
|
114
|
+
yield handler
|
|
@@ -0,0 +1,14 @@
|
|
|
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.
|