nvidia-nat 1.4.0a20251112__py3-none-any.whl → 1.4.0a20260113__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiq/__init__.py +1 -1
- nat/{front_ends/mcp → agent/auto_memory_wrapper}/__init__.py +1 -1
- nat/agent/auto_memory_wrapper/agent.py +278 -0
- nat/agent/auto_memory_wrapper/register.py +227 -0
- nat/agent/auto_memory_wrapper/state.py +30 -0
- nat/agent/base.py +1 -1
- nat/agent/dual_node.py +1 -1
- nat/agent/prompt_optimizer/prompt.py +1 -1
- nat/agent/prompt_optimizer/register.py +1 -1
- nat/agent/react_agent/agent.py +16 -9
- nat/agent/react_agent/output_parser.py +2 -2
- nat/agent/react_agent/prompt.py +3 -2
- nat/agent/react_agent/register.py +2 -2
- nat/agent/react_agent/register_per_user_agent.py +104 -0
- nat/agent/reasoning_agent/reasoning_agent.py +1 -1
- nat/agent/register.py +3 -1
- nat/agent/responses_api_agent/__init__.py +1 -1
- nat/agent/responses_api_agent/register.py +1 -1
- nat/agent/rewoo_agent/agent.py +9 -4
- nat/agent/rewoo_agent/prompt.py +1 -1
- nat/agent/rewoo_agent/register.py +1 -1
- nat/agent/tool_calling_agent/agent.py +5 -4
- nat/agent/tool_calling_agent/register.py +1 -1
- nat/authentication/__init__.py +1 -1
- nat/authentication/api_key/__init__.py +1 -1
- nat/authentication/api_key/api_key_auth_provider.py +1 -1
- nat/authentication/api_key/api_key_auth_provider_config.py +22 -7
- nat/authentication/api_key/register.py +1 -1
- nat/authentication/credential_validator/__init__.py +1 -1
- nat/authentication/credential_validator/bearer_token_validator.py +1 -1
- nat/authentication/exceptions/__init__.py +1 -1
- nat/authentication/exceptions/api_key_exceptions.py +1 -1
- nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
- nat/authentication/http_basic_auth/register.py +1 -1
- nat/authentication/interfaces.py +1 -1
- nat/authentication/oauth2/__init__.py +1 -1
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +1 -1
- nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +1 -1
- nat/authentication/oauth2/oauth2_resource_server_config.py +1 -1
- nat/authentication/oauth2/register.py +1 -1
- nat/authentication/register.py +1 -1
- nat/builder/builder.py +563 -1
- nat/builder/child_builder.py +385 -0
- nat/builder/component_utils.py +34 -4
- nat/builder/context.py +34 -1
- nat/builder/embedder.py +1 -1
- nat/builder/eval_builder.py +19 -7
- nat/builder/evaluator.py +1 -1
- nat/builder/framework_enum.py +3 -1
- nat/builder/front_end.py +1 -1
- nat/builder/function.py +113 -5
- nat/builder/function_base.py +1 -1
- nat/builder/function_info.py +1 -1
- nat/builder/intermediate_step_manager.py +1 -1
- nat/builder/llm.py +1 -1
- nat/builder/per_user_workflow_builder.py +843 -0
- nat/builder/retriever.py +1 -1
- nat/builder/sync_builder.py +571 -0
- nat/builder/user_interaction_manager.py +1 -1
- nat/builder/workflow.py +5 -3
- nat/builder/workflow_builder.py +619 -378
- nat/cli/__init__.py +1 -1
- nat/cli/cli_utils/config_override.py +1 -1
- nat/cli/cli_utils/validation.py +32 -1
- nat/cli/commands/configure/channel/add.py +1 -1
- nat/cli/commands/configure/channel/channel.py +1 -1
- nat/cli/commands/configure/channel/remove.py +1 -1
- nat/cli/commands/configure/channel/update.py +1 -1
- nat/cli/commands/configure/configure.py +1 -1
- nat/cli/commands/evaluate.py +87 -13
- nat/cli/commands/finetune.py +132 -0
- nat/cli/commands/info/__init__.py +1 -1
- nat/cli/commands/info/info.py +1 -1
- nat/cli/commands/info/list_channels.py +1 -1
- nat/cli/commands/info/list_components.py +1 -1
- nat/cli/commands/object_store/__init__.py +1 -1
- nat/cli/commands/object_store/object_store.py +1 -1
- nat/cli/commands/optimize.py +1 -1
- nat/cli/commands/{mcp → red_teaming}/__init__.py +1 -1
- nat/cli/commands/red_teaming/red_teaming.py +138 -0
- nat/cli/commands/red_teaming/red_teaming_utils.py +73 -0
- nat/cli/commands/registry/__init__.py +1 -1
- nat/cli/commands/registry/publish.py +1 -1
- nat/cli/commands/registry/pull.py +1 -1
- nat/cli/commands/registry/registry.py +1 -1
- nat/cli/commands/registry/remove.py +1 -1
- nat/cli/commands/registry/search.py +1 -1
- nat/cli/commands/sizing/__init__.py +1 -1
- nat/cli/commands/sizing/calc.py +1 -1
- nat/cli/commands/sizing/sizing.py +1 -1
- nat/cli/commands/start.py +1 -1
- nat/cli/commands/uninstall.py +1 -1
- nat/cli/commands/validate.py +1 -1
- nat/cli/commands/workflow/__init__.py +1 -1
- nat/cli/commands/workflow/workflow.py +1 -1
- nat/cli/commands/workflow/workflow_commands.py +3 -2
- nat/cli/entrypoint.py +15 -37
- nat/cli/main.py +2 -2
- nat/cli/plugin_loader.py +69 -0
- nat/cli/register_workflow.py +233 -5
- nat/cli/type_registry.py +237 -3
- nat/control_flow/register.py +1 -1
- nat/control_flow/router_agent/agent.py +1 -1
- nat/control_flow/router_agent/prompt.py +1 -1
- nat/control_flow/router_agent/register.py +1 -1
- nat/control_flow/sequential_executor.py +28 -7
- nat/data_models/__init__.py +1 -1
- nat/data_models/agent.py +1 -1
- nat/data_models/api_server.py +38 -3
- nat/data_models/authentication.py +1 -1
- nat/data_models/common.py +1 -1
- nat/data_models/component.py +9 -1
- nat/data_models/component_ref.py +45 -1
- nat/data_models/config.py +78 -1
- nat/data_models/dataset_handler.py +15 -2
- nat/data_models/discovery_metadata.py +1 -1
- nat/data_models/embedder.py +1 -1
- nat/data_models/evaluate.py +6 -1
- nat/data_models/evaluator.py +1 -1
- nat/data_models/finetuning.py +260 -0
- nat/data_models/front_end.py +1 -1
- nat/data_models/function.py +15 -2
- nat/data_models/function_dependencies.py +1 -1
- nat/data_models/gated_field_mixin.py +1 -1
- nat/data_models/interactive.py +1 -1
- nat/data_models/intermediate_step.py +29 -2
- nat/data_models/invocation_node.py +1 -1
- nat/data_models/llm.py +1 -1
- nat/data_models/logging.py +1 -1
- nat/data_models/memory.py +1 -1
- nat/data_models/middleware.py +37 -0
- nat/data_models/object_store.py +1 -1
- nat/data_models/openai_mcp.py +1 -1
- nat/data_models/optimizable.py +1 -1
- nat/data_models/optimizer.py +1 -1
- nat/data_models/profiler.py +1 -1
- nat/data_models/registry_handler.py +1 -1
- nat/data_models/retriever.py +1 -1
- nat/data_models/retry_mixin.py +1 -1
- nat/data_models/runtime_enum.py +26 -0
- nat/data_models/span.py +1 -1
- nat/data_models/step_adaptor.py +1 -1
- nat/data_models/streaming.py +1 -1
- nat/data_models/swe_bench_model.py +1 -1
- nat/data_models/telemetry_exporter.py +1 -1
- nat/data_models/thinking_mixin.py +1 -1
- nat/data_models/ttc_strategy.py +1 -1
- nat/embedder/azure_openai_embedder.py +1 -1
- nat/embedder/nim_embedder.py +1 -1
- nat/embedder/openai_embedder.py +1 -1
- nat/embedder/register.py +1 -1
- nat/eval/__init__.py +1 -1
- nat/eval/config.py +8 -1
- nat/eval/dataset_handler/dataset_downloader.py +1 -1
- nat/eval/dataset_handler/dataset_filter.py +1 -1
- nat/eval/dataset_handler/dataset_handler.py +4 -2
- nat/eval/evaluate.py +226 -81
- nat/eval/evaluator/__init__.py +1 -1
- nat/eval/evaluator/base_evaluator.py +2 -2
- nat/eval/evaluator/evaluator_model.py +3 -2
- nat/eval/intermediate_step_adapter.py +1 -1
- nat/eval/llm_validator.py +336 -0
- nat/eval/rag_evaluator/evaluate.py +17 -10
- nat/eval/rag_evaluator/register.py +1 -1
- nat/eval/red_teaming_evaluator/__init__.py +14 -0
- nat/eval/red_teaming_evaluator/data_models.py +66 -0
- nat/eval/red_teaming_evaluator/evaluate.py +327 -0
- nat/eval/red_teaming_evaluator/filter_conditions.py +75 -0
- nat/eval/red_teaming_evaluator/register.py +55 -0
- nat/eval/register.py +2 -1
- nat/eval/remote_workflow.py +1 -1
- nat/eval/runners/__init__.py +1 -1
- nat/eval/runners/config.py +1 -1
- nat/eval/runners/multi_eval_runner.py +1 -1
- nat/eval/runners/red_teaming_runner/__init__.py +24 -0
- nat/eval/runners/red_teaming_runner/config.py +282 -0
- nat/eval/runners/red_teaming_runner/report_utils.py +707 -0
- nat/eval/runners/red_teaming_runner/runner.py +867 -0
- nat/eval/runtime_evaluator/__init__.py +1 -1
- nat/eval/runtime_evaluator/evaluate.py +1 -1
- nat/eval/runtime_evaluator/register.py +1 -1
- nat/eval/runtime_event_subscriber.py +1 -1
- nat/eval/swe_bench_evaluator/evaluate.py +1 -1
- nat/eval/swe_bench_evaluator/register.py +1 -1
- nat/eval/trajectory_evaluator/evaluate.py +2 -2
- nat/eval/trajectory_evaluator/register.py +1 -1
- nat/eval/tunable_rag_evaluator/evaluate.py +5 -5
- nat/eval/tunable_rag_evaluator/register.py +1 -1
- nat/eval/usage_stats.py +1 -1
- nat/eval/utils/eval_trace_ctx.py +1 -1
- nat/eval/utils/output_uploader.py +1 -1
- nat/eval/utils/tqdm_position_registry.py +1 -1
- nat/eval/utils/weave_eval.py +1 -1
- nat/experimental/decorators/experimental_warning_decorator.py +1 -1
- nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +1 -1
- nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +1 -1
- nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +1 -1
- nat/experimental/test_time_compute/functions/execute_score_select_function.py +1 -1
- nat/experimental/test_time_compute/functions/multi_llm_judge_function.py +88 -0
- nat/experimental/test_time_compute/functions/plan_select_execute_function.py +1 -1
- nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +1 -1
- nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
- nat/experimental/test_time_compute/models/editor_config.py +1 -1
- nat/experimental/test_time_compute/models/scoring_config.py +1 -1
- nat/experimental/test_time_compute/models/search_config.py +20 -2
- nat/experimental/test_time_compute/models/selection_config.py +33 -2
- nat/experimental/test_time_compute/models/stage_enums.py +1 -1
- nat/experimental/test_time_compute/models/strategy_base.py +1 -1
- nat/experimental/test_time_compute/models/tool_use_config.py +1 -1
- nat/experimental/test_time_compute/models/ttc_item.py +1 -1
- nat/experimental/test_time_compute/register.py +4 -1
- nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +1 -1
- nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +1 -1
- nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +1 -1
- nat/experimental/test_time_compute/search/multi_llm_generation.py +115 -0
- nat/experimental/test_time_compute/search/multi_llm_planner.py +1 -1
- nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +1 -1
- nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +1 -1
- nat/experimental/test_time_compute/selection/best_of_n_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_judge_selection.py +127 -0
- nat/experimental/test_time_compute/selection/threshold_selector.py +1 -1
- nat/finetuning/__init__.py +24 -0
- nat/finetuning/finetuning_runtime.py +143 -0
- nat/finetuning/interfaces/__init__.py +24 -0
- nat/finetuning/interfaces/finetuning_runner.py +261 -0
- nat/finetuning/interfaces/trainer_adapter.py +103 -0
- nat/finetuning/interfaces/trajectory_builder.py +115 -0
- nat/finetuning/utils/__init__.py +15 -0
- nat/finetuning/utils/parsers/__init__.py +15 -0
- nat/finetuning/utils/parsers/adk_parser.py +141 -0
- nat/finetuning/utils/parsers/base_parser.py +238 -0
- nat/finetuning/utils/parsers/common.py +91 -0
- nat/finetuning/utils/parsers/langchain_parser.py +267 -0
- nat/finetuning/utils/parsers/llama_index_parser.py +218 -0
- nat/front_ends/__init__.py +1 -1
- nat/front_ends/console/__init__.py +1 -1
- nat/front_ends/console/authentication_flow_handler.py +1 -1
- nat/front_ends/console/console_front_end_config.py +4 -1
- nat/front_ends/console/console_front_end_plugin.py +5 -4
- nat/front_ends/console/register.py +1 -1
- nat/front_ends/cron/__init__.py +1 -1
- nat/front_ends/fastapi/__init__.py +1 -1
- nat/front_ends/fastapi/async_job.py +128 -0
- nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +1 -1
- nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +13 -9
- nat/front_ends/fastapi/dask_client_mixin.py +1 -1
- nat/front_ends/fastapi/fastapi_front_end_config.py +23 -1
- nat/front_ends/fastapi/fastapi_front_end_controller.py +1 -1
- nat/front_ends/fastapi/fastapi_front_end_plugin.py +25 -30
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +318 -59
- nat/front_ends/fastapi/html_snippets/__init__.py +1 -1
- nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +1 -1
- nat/front_ends/fastapi/intermediate_steps_subscriber.py +12 -1
- nat/front_ends/fastapi/job_store.py +23 -11
- nat/front_ends/fastapi/main.py +1 -1
- nat/front_ends/fastapi/message_handler.py +27 -4
- nat/front_ends/fastapi/message_validator.py +54 -2
- nat/front_ends/fastapi/register.py +1 -1
- nat/front_ends/fastapi/response_helpers.py +16 -15
- nat/front_ends/fastapi/step_adaptor.py +1 -1
- nat/front_ends/fastapi/utils.py +1 -1
- nat/front_ends/register.py +1 -2
- nat/front_ends/simple_base/__init__.py +1 -1
- nat/front_ends/simple_base/simple_front_end_plugin_base.py +6 -4
- nat/llm/aws_bedrock_llm.py +1 -1
- nat/llm/azure_openai_llm.py +10 -1
- nat/llm/dynamo_llm.py +363 -0
- nat/llm/huggingface_llm.py +177 -0
- nat/llm/litellm_llm.py +1 -1
- nat/llm/nim_llm.py +1 -1
- nat/llm/openai_llm.py +1 -1
- nat/llm/register.py +3 -1
- nat/llm/utils/__init__.py +1 -1
- nat/llm/utils/env_config_value.py +1 -1
- nat/llm/utils/error.py +1 -1
- nat/llm/utils/thinking.py +1 -1
- nat/memory/__init__.py +1 -1
- nat/memory/interfaces.py +1 -1
- nat/memory/models.py +1 -1
- nat/meta/pypi.md +1 -1
- nat/middleware/__init__.py +35 -0
- nat/middleware/cache/__init__.py +14 -0
- nat/middleware/cache/cache_middleware.py +253 -0
- nat/middleware/cache/cache_middleware_config.py +44 -0
- nat/middleware/cache/register.py +33 -0
- nat/middleware/defense/__init__.py +14 -0
- nat/middleware/defense/defense_middleware.py +362 -0
- nat/middleware/defense/defense_middleware_content_guard.py +455 -0
- nat/middleware/defense/defense_middleware_data_models.py +91 -0
- nat/middleware/defense/defense_middleware_output_verifier.py +440 -0
- nat/middleware/defense/defense_middleware_pii.py +356 -0
- nat/middleware/defense/register.py +82 -0
- nat/middleware/dynamic/__init__.py +14 -0
- nat/middleware/dynamic/dynamic_function_middleware.py +962 -0
- nat/middleware/dynamic/dynamic_middleware_config.py +132 -0
- nat/middleware/dynamic/register.py +34 -0
- nat/middleware/function_middleware.py +370 -0
- nat/middleware/logging/__init__.py +14 -0
- nat/middleware/logging/logging_middleware.py +67 -0
- nat/middleware/logging/logging_middleware_config.py +28 -0
- nat/middleware/logging/register.py +33 -0
- nat/middleware/middleware.py +298 -0
- nat/middleware/red_teaming/__init__.py +14 -0
- nat/middleware/red_teaming/red_teaming_middleware.py +344 -0
- nat/middleware/red_teaming/red_teaming_middleware_config.py +112 -0
- nat/middleware/red_teaming/register.py +47 -0
- nat/middleware/register.py +22 -0
- nat/middleware/utils/__init__.py +14 -0
- nat/middleware/utils/workflow_inventory.py +155 -0
- nat/object_store/__init__.py +1 -1
- nat/object_store/in_memory_object_store.py +1 -1
- nat/object_store/interfaces.py +1 -1
- nat/object_store/models.py +1 -1
- nat/object_store/register.py +1 -1
- nat/observability/__init__.py +1 -1
- nat/observability/exporter/__init__.py +1 -1
- nat/observability/exporter/base_exporter.py +1 -1
- nat/observability/exporter/exporter.py +1 -1
- nat/observability/exporter/file_exporter.py +1 -1
- nat/observability/exporter/processing_exporter.py +1 -1
- nat/observability/exporter/raw_exporter.py +1 -1
- nat/observability/exporter/span_exporter.py +7 -1
- nat/observability/exporter_manager.py +1 -1
- nat/observability/mixin/__init__.py +1 -1
- nat/observability/mixin/batch_config_mixin.py +1 -1
- nat/observability/mixin/collector_config_mixin.py +1 -1
- nat/observability/mixin/file_mixin.py +1 -1
- nat/observability/mixin/file_mode.py +1 -1
- nat/observability/mixin/redaction_config_mixin.py +1 -1
- nat/observability/mixin/resource_conflict_mixin.py +1 -1
- nat/observability/mixin/serialize_mixin.py +1 -1
- nat/observability/mixin/tagging_config_mixin.py +1 -1
- nat/observability/mixin/type_introspection_mixin.py +1 -1
- nat/observability/processor/__init__.py +1 -1
- nat/observability/processor/batching_processor.py +1 -1
- nat/observability/processor/callback_processor.py +1 -1
- nat/observability/processor/falsy_batch_filter_processor.py +1 -1
- nat/observability/processor/intermediate_step_serializer.py +1 -1
- nat/observability/processor/processor.py +1 -1
- nat/observability/processor/processor_factory.py +1 -1
- nat/observability/processor/redaction/__init__.py +1 -1
- nat/observability/processor/redaction/contextual_redaction_processor.py +1 -1
- nat/observability/processor/redaction/contextual_span_redaction_processor.py +1 -1
- nat/observability/processor/redaction/redaction_processor.py +1 -1
- nat/observability/processor/redaction/span_header_redaction_processor.py +1 -1
- nat/observability/processor/span_tagging_processor.py +1 -1
- nat/observability/register.py +1 -1
- nat/observability/utils/__init__.py +1 -1
- nat/observability/utils/dict_utils.py +1 -1
- nat/observability/utils/time_utils.py +1 -1
- nat/profiler/calc/__init__.py +1 -1
- nat/profiler/calc/calc_runner.py +3 -3
- nat/profiler/calc/calculations.py +1 -1
- nat/profiler/calc/data_models.py +1 -1
- nat/profiler/calc/plot.py +30 -3
- nat/profiler/callbacks/agno_callback_handler.py +1 -1
- nat/profiler/callbacks/base_callback_class.py +1 -1
- nat/profiler/callbacks/langchain_callback_handler.py +33 -3
- nat/profiler/callbacks/llama_index_callback_handler.py +13 -10
- nat/profiler/callbacks/semantic_kernel_callback_handler.py +1 -1
- nat/profiler/callbacks/token_usage_base_model.py +1 -1
- nat/profiler/data_frame_row.py +1 -1
- nat/profiler/data_models.py +1 -1
- nat/profiler/decorators/framework_wrapper.py +32 -1
- nat/profiler/decorators/function_tracking.py +1 -1
- nat/profiler/forecasting/config.py +1 -1
- nat/profiler/forecasting/model_trainer.py +1 -1
- nat/profiler/forecasting/models/__init__.py +1 -1
- nat/profiler/forecasting/models/forecasting_base_model.py +1 -1
- nat/profiler/forecasting/models/linear_model.py +1 -1
- nat/profiler/forecasting/models/random_forest_regressor.py +1 -1
- nat/profiler/inference_metrics_model.py +1 -1
- nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/data_models.py +1 -1
- nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +1 -1
- nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +1 -1
- nat/profiler/inference_optimization/llm_metrics.py +1 -1
- nat/profiler/inference_optimization/prompt_caching.py +1 -1
- nat/profiler/inference_optimization/token_uniqueness.py +1 -1
- nat/profiler/inference_optimization/workflow_runtimes.py +1 -1
- nat/profiler/intermediate_property_adapter.py +1 -1
- nat/profiler/parameter_optimization/optimizable_utils.py +1 -1
- nat/profiler/parameter_optimization/optimizer_runtime.py +1 -1
- nat/profiler/parameter_optimization/parameter_optimizer.py +1 -1
- nat/profiler/parameter_optimization/parameter_selection.py +1 -1
- nat/profiler/parameter_optimization/pareto_visualizer.py +1 -1
- nat/profiler/parameter_optimization/prompt_optimizer.py +1 -1
- nat/profiler/parameter_optimization/update_helpers.py +1 -1
- nat/profiler/profile_runner.py +1 -1
- nat/profiler/utils.py +1 -1
- nat/registry_handlers/local/local_handler.py +1 -1
- nat/registry_handlers/local/register_local.py +1 -1
- nat/registry_handlers/metadata_factory.py +1 -1
- nat/registry_handlers/package_utils.py +1 -1
- nat/registry_handlers/pypi/pypi_handler.py +1 -1
- nat/registry_handlers/pypi/register_pypi.py +1 -1
- nat/registry_handlers/register.py +1 -1
- nat/registry_handlers/registry_handler_base.py +1 -1
- nat/registry_handlers/rest/register_rest.py +1 -1
- nat/registry_handlers/rest/rest_handler.py +1 -1
- nat/registry_handlers/schemas/headers.py +1 -1
- nat/registry_handlers/schemas/package.py +1 -1
- nat/registry_handlers/schemas/publish.py +1 -1
- nat/registry_handlers/schemas/pull.py +1 -1
- nat/registry_handlers/schemas/remove.py +1 -1
- nat/registry_handlers/schemas/search.py +1 -1
- nat/registry_handlers/schemas/status.py +1 -1
- nat/retriever/interface.py +1 -1
- nat/retriever/milvus/__init__.py +1 -1
- nat/retriever/milvus/register.py +12 -4
- nat/retriever/milvus/retriever.py +103 -41
- nat/retriever/models.py +1 -1
- nat/retriever/nemo_retriever/__init__.py +1 -1
- nat/retriever/nemo_retriever/register.py +1 -1
- nat/retriever/nemo_retriever/retriever.py +5 -5
- nat/retriever/register.py +1 -1
- nat/runtime/__init__.py +1 -1
- nat/runtime/loader.py +10 -3
- nat/runtime/metrics.py +180 -0
- nat/runtime/runner.py +13 -6
- nat/runtime/session.py +458 -32
- nat/runtime/user_metadata.py +1 -1
- nat/settings/global_settings.py +1 -1
- nat/tool/chat_completion.py +1 -1
- nat/tool/code_execution/README.md +1 -1
- nat/tool/code_execution/code_sandbox.py +2 -2
- nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +1 -1
- nat/tool/code_execution/local_sandbox/__init__.py +1 -1
- nat/tool/code_execution/local_sandbox/local_sandbox_server.py +1 -1
- nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +1 -1
- nat/tool/code_execution/register.py +1 -1
- nat/tool/code_execution/utils.py +1 -1
- nat/tool/datetime_tools.py +1 -1
- nat/tool/document_search.py +1 -1
- nat/tool/github_tools.py +1 -1
- nat/tool/memory_tools/add_memory_tool.py +1 -1
- nat/tool/memory_tools/delete_memory_tool.py +1 -1
- nat/tool/memory_tools/get_memory_tool.py +1 -1
- nat/tool/nvidia_rag.py +2 -2
- nat/tool/register.py +1 -1
- nat/tool/retriever.py +1 -1
- nat/tool/server_tools.py +1 -1
- nat/utils/__init__.py +8 -5
- nat/utils/callable_utils.py +1 -1
- nat/utils/data_models/schema_validator.py +1 -1
- nat/utils/debugging_utils.py +1 -1
- nat/utils/decorators.py +1 -1
- nat/utils/dump_distro_mapping.py +1 -1
- nat/utils/exception_handlers/automatic_retries.py +3 -3
- nat/utils/exception_handlers/schemas.py +1 -1
- nat/utils/io/model_processing.py +1 -1
- nat/utils/io/supress_logs.py +33 -0
- nat/utils/io/yaml_tools.py +1 -1
- nat/utils/log_levels.py +1 -1
- nat/utils/log_utils.py +13 -1
- nat/utils/metadata_utils.py +1 -1
- nat/utils/optional_imports.py +1 -1
- nat/utils/producer_consumer_queue.py +1 -1
- nat/utils/reactive/base/observable_base.py +1 -1
- nat/utils/reactive/base/observer_base.py +1 -1
- nat/utils/reactive/base/subject_base.py +1 -1
- nat/utils/reactive/observable.py +1 -1
- nat/utils/reactive/observer.py +1 -1
- nat/utils/reactive/subject.py +1 -1
- nat/utils/reactive/subscription.py +1 -1
- nat/utils/responses_api.py +1 -1
- nat/utils/settings/global_settings.py +1 -1
- nat/utils/string_utils.py +1 -1
- nat/utils/type_converter.py +18 -5
- nat/utils/type_utils.py +1 -1
- nat/utils/url_utils.py +1 -1
- {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/METADATA +46 -15
- nvidia_nat-1.4.0a20260113.dist-info/RECORD +547 -0
- nvidia_nat-1.4.0a20260113.dist-info/entry_points.txt +38 -0
- nat/cli/commands/mcp/mcp.py +0 -986
- nat/front_ends/mcp/introspection_token_verifier.py +0 -73
- nat/front_ends/mcp/mcp_front_end_config.py +0 -109
- nat/front_ends/mcp/mcp_front_end_plugin.py +0 -151
- nat/front_ends/mcp/mcp_front_end_plugin_worker.py +0 -362
- nat/front_ends/mcp/memory_profiler.py +0 -320
- nat/front_ends/mcp/register.py +0 -27
- nat/front_ends/mcp/tool_converter.py +0 -321
- nvidia_nat-1.4.0a20251112.dist-info/RECORD +0 -481
- nvidia_nat-1.4.0a20251112.dist-info/entry_points.txt +0 -22
- {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
- {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE.md +0 -0
- {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""
|
|
16
|
+
PII Defense Middleware using Microsoft Presidio.
|
|
17
|
+
|
|
18
|
+
This middleware detects and anonymizes Personally Identifiable Information (PII)
|
|
19
|
+
in function outputs using Microsoft Presidio.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
import logging
|
|
23
|
+
from collections.abc import AsyncIterator
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
from pydantic import Field
|
|
27
|
+
|
|
28
|
+
from nat.middleware.defense.defense_middleware import DefenseMiddleware
|
|
29
|
+
from nat.middleware.defense.defense_middleware import DefenseMiddlewareConfig
|
|
30
|
+
from nat.middleware.defense.defense_middleware_data_models import PIIAnalysisResult
|
|
31
|
+
from nat.middleware.function_middleware import CallNext
|
|
32
|
+
from nat.middleware.function_middleware import CallNextStream
|
|
33
|
+
from nat.middleware.middleware import FunctionMiddlewareContext
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class PIIDefenseMiddlewareConfig(DefenseMiddlewareConfig, name="pii_defense"):
|
|
39
|
+
"""Configuration for PII Defense Middleware using Microsoft Presidio.
|
|
40
|
+
|
|
41
|
+
Detects PII in function outputs using Presidio's rule-based entity recognition (no LLM required).
|
|
42
|
+
|
|
43
|
+
See <https://github.com/microsoft/presidio> for more information about Presidio.
|
|
44
|
+
|
|
45
|
+
Actions:
|
|
46
|
+
- 'partial_compliance': Detect and log PII, but allow content to pass through
|
|
47
|
+
- 'refusal': Block content if PII detected (hard stop)
|
|
48
|
+
- 'redirection': Replace PII with anonymized placeholders (e.g., <EMAIL_ADDRESS>)
|
|
49
|
+
|
|
50
|
+
Note: Only output analysis is currently supported (target_location='output').
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
llm_name: str | None = Field(default=None, description="Not used for PII defense (Presidio is rule-based)")
|
|
54
|
+
entities: list[str] = Field(default_factory=lambda: [
|
|
55
|
+
"PERSON",
|
|
56
|
+
"EMAIL_ADDRESS",
|
|
57
|
+
"PHONE_NUMBER",
|
|
58
|
+
"CREDIT_CARD",
|
|
59
|
+
"US_SSN",
|
|
60
|
+
"LOCATION",
|
|
61
|
+
"IP_ADDRESS", ],
|
|
62
|
+
description="List of PII entities to detect")
|
|
63
|
+
score_threshold: float = Field(default=0.01, description="Minimum confidence score (0.0-1.0) for PII detection")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class PIIDefenseMiddleware(DefenseMiddleware):
|
|
67
|
+
"""PII Defense Middleware using Microsoft Presidio.
|
|
68
|
+
|
|
69
|
+
Detects PII in function outputs using Presidio's rule-based entity recognition.
|
|
70
|
+
Only output analysis is currently supported (``target_location='output'``).
|
|
71
|
+
|
|
72
|
+
See https://github.com/microsoft/presidio for more information about Presidio.
|
|
73
|
+
|
|
74
|
+
Streaming Behavior:
|
|
75
|
+
For 'refusal' and 'redirection' actions, chunks are buffered and checked
|
|
76
|
+
before yielding to prevent PII from being streamed to clients.
|
|
77
|
+
For 'partial_compliance' action, chunks are yielded immediately; violations
|
|
78
|
+
are logged but content passes through.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, config: PIIDefenseMiddlewareConfig, builder):
|
|
82
|
+
super().__init__(config, builder)
|
|
83
|
+
self.config: PIIDefenseMiddlewareConfig = config
|
|
84
|
+
self._analyzer = None
|
|
85
|
+
self._anonymizer = None
|
|
86
|
+
|
|
87
|
+
# PII Defense only supports output analysis
|
|
88
|
+
if config.target_location == "input":
|
|
89
|
+
raise ValueError("PIIDefenseMiddleware only supports target_location='output'. "
|
|
90
|
+
"Input analysis is not yet supported.")
|
|
91
|
+
|
|
92
|
+
logger.info(f"PIIDefenseMiddleware initialized: "
|
|
93
|
+
f"action={config.action}, entities={config.entities}, "
|
|
94
|
+
f"score_threshold={config.score_threshold}, target={config.target_function_or_group}")
|
|
95
|
+
|
|
96
|
+
def _lazy_load_presidio(self):
|
|
97
|
+
"""Lazy load Presidio components when first needed."""
|
|
98
|
+
if self._analyzer is None:
|
|
99
|
+
try:
|
|
100
|
+
from presidio_analyzer import AnalyzerEngine
|
|
101
|
+
from presidio_anonymizer import AnonymizerEngine
|
|
102
|
+
|
|
103
|
+
self._analyzer = AnalyzerEngine()
|
|
104
|
+
self._anonymizer = AnonymizerEngine()
|
|
105
|
+
logger.info("Presidio engines loaded successfully")
|
|
106
|
+
except ImportError as err:
|
|
107
|
+
raise ImportError("Microsoft Presidio is not installed. "
|
|
108
|
+
"Install it with: pip install presidio-analyzer presidio-anonymizer") from err
|
|
109
|
+
|
|
110
|
+
def _analyze_content(self, text: str) -> PIIAnalysisResult:
|
|
111
|
+
"""Analyze content for PII entities using Presidio.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
text: The text to analyze
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
PIIAnalysisResult with detection results and anonymized text.
|
|
118
|
+
"""
|
|
119
|
+
self._lazy_load_presidio()
|
|
120
|
+
from presidio_anonymizer.entities import OperatorConfig
|
|
121
|
+
|
|
122
|
+
# Analyze for PII with NO score threshold first (to see everything)
|
|
123
|
+
all_results = self._analyzer.analyze(text=text, entities=self.config.entities, language="en")
|
|
124
|
+
|
|
125
|
+
# Log ALL detections before filtering (without PII text for privacy)
|
|
126
|
+
logger.debug("PII Defense raw detections: %s", [(r.entity_type, r.score, r.start, r.end) for r in all_results])
|
|
127
|
+
|
|
128
|
+
# Filter by score threshold
|
|
129
|
+
results = [r for r in all_results if r.score >= self.config.score_threshold]
|
|
130
|
+
|
|
131
|
+
# Group by entity type (without PII text for privacy)
|
|
132
|
+
detected_entities = {}
|
|
133
|
+
for result in results:
|
|
134
|
+
entity_type = result.entity_type
|
|
135
|
+
if entity_type not in detected_entities:
|
|
136
|
+
detected_entities[entity_type] = []
|
|
137
|
+
detected_entities[entity_type].append({"score": result.score, "start": result.start, "end": result.end})
|
|
138
|
+
|
|
139
|
+
# Generate anonymized version (used when action='sanitize')
|
|
140
|
+
anonymized_text = text
|
|
141
|
+
if results:
|
|
142
|
+
# Use custom replacement operators for each entity type
|
|
143
|
+
operators = {}
|
|
144
|
+
for result in results:
|
|
145
|
+
operators[result.entity_type] = OperatorConfig("replace", {"new_value": f"<{result.entity_type}>"})
|
|
146
|
+
|
|
147
|
+
anonymized_text = self._anonymizer.anonymize(text=text, analyzer_results=results, operators=operators).text
|
|
148
|
+
|
|
149
|
+
return PIIAnalysisResult(pii_detected=len(results) > 0,
|
|
150
|
+
entities=detected_entities,
|
|
151
|
+
anonymized_text=anonymized_text,
|
|
152
|
+
original_text=text)
|
|
153
|
+
|
|
154
|
+
def _process_pii_detection(
|
|
155
|
+
self,
|
|
156
|
+
value: Any,
|
|
157
|
+
location: str,
|
|
158
|
+
context: FunctionMiddlewareContext,
|
|
159
|
+
) -> Any:
|
|
160
|
+
"""Process PII detection and sanitization for a given value.
|
|
161
|
+
|
|
162
|
+
This is a common helper method that handles:
|
|
163
|
+
- Field extraction (if target_field is specified)
|
|
164
|
+
- PII analysis
|
|
165
|
+
- Action handling (refusal, redirection, partial_compliance)
|
|
166
|
+
- Applying sanitized value back to original structure
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
value: The value to analyze (input or output)
|
|
170
|
+
location: Either "input" or "output" (for logging)
|
|
171
|
+
context: Function context metadata
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
The value after PII handling (may be unchanged, sanitized, or raise exception)
|
|
175
|
+
"""
|
|
176
|
+
# Extract field from value if target_field is specified
|
|
177
|
+
content_to_analyze, field_info = self._extract_field_from_value(value)
|
|
178
|
+
|
|
179
|
+
logger.info("PIIDefenseMiddleware: Checking %s %s for %s",
|
|
180
|
+
f"field '{self.config.target_field}'" if field_info else "entire",
|
|
181
|
+
location,
|
|
182
|
+
context.name)
|
|
183
|
+
# Analyze for PII (convert to string for Presidio)
|
|
184
|
+
content_text = str(content_to_analyze)
|
|
185
|
+
analysis_result = self._analyze_content(content_text)
|
|
186
|
+
|
|
187
|
+
if not analysis_result.pii_detected:
|
|
188
|
+
logger.info("PIIDefenseMiddleware: Verified %s of %s: No PII detected", location, context.name)
|
|
189
|
+
return value
|
|
190
|
+
|
|
191
|
+
# PII detected - handle based on action
|
|
192
|
+
entities = analysis_result.entities
|
|
193
|
+
# Build entities string efficiently without intermediate list
|
|
194
|
+
entities_str = ", ".join(f"{k}({len(v)})" for k, v in entities.items())
|
|
195
|
+
sanitized_content = self._handle_threat(content_to_analyze, analysis_result, context, location, entities_str)
|
|
196
|
+
|
|
197
|
+
# If field was extracted, apply sanitized value back to original structure
|
|
198
|
+
if field_info is not None:
|
|
199
|
+
return self._apply_field_result_to_value(value, field_info, sanitized_content)
|
|
200
|
+
else:
|
|
201
|
+
# No field extraction - return sanitized content directly
|
|
202
|
+
return sanitized_content
|
|
203
|
+
|
|
204
|
+
def _handle_threat(
|
|
205
|
+
self,
|
|
206
|
+
content: Any,
|
|
207
|
+
analysis_result: PIIAnalysisResult,
|
|
208
|
+
context: FunctionMiddlewareContext,
|
|
209
|
+
location: str,
|
|
210
|
+
entities_str: str,
|
|
211
|
+
) -> Any:
|
|
212
|
+
"""Handle detected PII threat based on configured action.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
content: The content with PII
|
|
216
|
+
analysis_result: Detection result from Presidio
|
|
217
|
+
context: Function context
|
|
218
|
+
location: Either "input" or "output" (for logging)
|
|
219
|
+
entities_str: String representation of detected entities
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Handled content (anonymized, original, or raises exception for refusal)
|
|
223
|
+
"""
|
|
224
|
+
if self.config.action == "refusal":
|
|
225
|
+
logger.error("PII Defense refusing %s of %s: %s", location, context.name, entities_str)
|
|
226
|
+
raise ValueError(f"PII detected in {location}: {entities_str}. Output refused.")
|
|
227
|
+
|
|
228
|
+
elif self.config.action == "redirection":
|
|
229
|
+
logger.warning("PII Defense detected PII in %s of %s: %s", location, context.name, entities_str)
|
|
230
|
+
logger.info("PII Defense anonymizing %s for %s", location, context.name)
|
|
231
|
+
str(content)
|
|
232
|
+
anonymized_content = analysis_result.anonymized_text
|
|
233
|
+
|
|
234
|
+
# Convert anonymized_text back to original type if needed
|
|
235
|
+
redirected_value = anonymized_content
|
|
236
|
+
if isinstance(content, int | float):
|
|
237
|
+
try:
|
|
238
|
+
redirected_value = type(content)(anonymized_content)
|
|
239
|
+
except (ValueError, TypeError):
|
|
240
|
+
logger.warning("Could not convert anonymized text '%s' to %s",
|
|
241
|
+
anonymized_content,
|
|
242
|
+
type(content).__name__)
|
|
243
|
+
redirected_value = anonymized_content
|
|
244
|
+
|
|
245
|
+
return redirected_value
|
|
246
|
+
|
|
247
|
+
else: # action == "partial_compliance"
|
|
248
|
+
logger.warning("PII Defense detected PII in %s of %s: %s", location, context.name, entities_str)
|
|
249
|
+
return content # No modification, just log
|
|
250
|
+
|
|
251
|
+
async def function_middleware_invoke(
|
|
252
|
+
self,
|
|
253
|
+
*args: Any,
|
|
254
|
+
call_next: CallNext,
|
|
255
|
+
context: FunctionMiddlewareContext,
|
|
256
|
+
**kwargs: Any,
|
|
257
|
+
) -> Any:
|
|
258
|
+
"""Intercept function calls to detect and anonymize PII in inputs or outputs.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
args: Positional arguments passed to the function (first arg is typically the input value).
|
|
262
|
+
call_next: Function to call the next middleware or the actual function.
|
|
263
|
+
context: Context containing function metadata.
|
|
264
|
+
kwargs: Keyword arguments passed to the function.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
The function result, with PII anonymized if action='redirection'.
|
|
268
|
+
"""
|
|
269
|
+
value = args[0] if args else None
|
|
270
|
+
|
|
271
|
+
# Check if this defense should apply to this function
|
|
272
|
+
if not self._should_apply_defense(context.name):
|
|
273
|
+
logger.debug("PIIDefenseMiddleware: Skipping %s (not targeted)", context.name)
|
|
274
|
+
return await call_next(value, *args[1:], **kwargs)
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
# Call the actual function
|
|
278
|
+
result = await call_next(value, *args[1:], **kwargs)
|
|
279
|
+
|
|
280
|
+
# Handle output analysis (only output is supported)
|
|
281
|
+
result = self._process_pii_detection(result, "output", context)
|
|
282
|
+
|
|
283
|
+
return result
|
|
284
|
+
|
|
285
|
+
except Exception:
|
|
286
|
+
logger.error(
|
|
287
|
+
"Failed to apply PII defense to function %s",
|
|
288
|
+
context.name,
|
|
289
|
+
exc_info=True,
|
|
290
|
+
)
|
|
291
|
+
raise
|
|
292
|
+
|
|
293
|
+
async def function_middleware_stream(
|
|
294
|
+
self,
|
|
295
|
+
*args: Any,
|
|
296
|
+
call_next: CallNextStream,
|
|
297
|
+
context: FunctionMiddlewareContext,
|
|
298
|
+
**kwargs: Any,
|
|
299
|
+
) -> AsyncIterator[Any]:
|
|
300
|
+
"""Intercept streaming calls to detect and anonymize PII in inputs or outputs.
|
|
301
|
+
|
|
302
|
+
For 'refusal' and 'redirection' actions: Chunks are buffered and checked before yielding.
|
|
303
|
+
For 'partial_compliance' action: Chunks are yielded immediately; violations are logged.
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
args: Positional arguments passed to the function (first arg is typically the input value).
|
|
307
|
+
call_next: Function to call the next middleware or the actual function.
|
|
308
|
+
context: Context containing function metadata.
|
|
309
|
+
kwargs: Keyword arguments passed to the function.
|
|
310
|
+
|
|
311
|
+
Yields:
|
|
312
|
+
The function result chunks, with PII anonymized if action='redirection'.
|
|
313
|
+
"""
|
|
314
|
+
value = args[0] if args else None
|
|
315
|
+
|
|
316
|
+
# Check if this defense should apply to this function
|
|
317
|
+
if not self._should_apply_defense(context.name):
|
|
318
|
+
logger.debug("PIIDefenseMiddleware: Skipping %s (not targeted)", context.name)
|
|
319
|
+
async for chunk in call_next(value, *args[1:], **kwargs):
|
|
320
|
+
yield chunk
|
|
321
|
+
return
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
buffer_chunks = self.config.action in ("refusal", "redirection")
|
|
325
|
+
accumulated_chunks: list[Any] = []
|
|
326
|
+
|
|
327
|
+
async for chunk in call_next(value, *args[1:], **kwargs):
|
|
328
|
+
if buffer_chunks:
|
|
329
|
+
accumulated_chunks.append(chunk)
|
|
330
|
+
else:
|
|
331
|
+
# partial_compliance: stream through, but still accumulate for analysis/logging
|
|
332
|
+
yield chunk
|
|
333
|
+
accumulated_chunks.append(chunk)
|
|
334
|
+
|
|
335
|
+
# Analyze the full output for PII
|
|
336
|
+
full_output = "".join(chunk if isinstance(chunk, str) else str(chunk) for chunk in accumulated_chunks)
|
|
337
|
+
processed_output = self._process_pii_detection(full_output, "output", context)
|
|
338
|
+
|
|
339
|
+
processed_str = str(processed_output)
|
|
340
|
+
if self.config.action == "redirection" and processed_str != full_output:
|
|
341
|
+
# Redirected: yield replacement once (and stop).
|
|
342
|
+
yield processed_output
|
|
343
|
+
return
|
|
344
|
+
|
|
345
|
+
if buffer_chunks:
|
|
346
|
+
# refusal: would have raised; safe content: preserve chunking
|
|
347
|
+
for chunk in accumulated_chunks:
|
|
348
|
+
yield chunk
|
|
349
|
+
|
|
350
|
+
except Exception:
|
|
351
|
+
logger.error(
|
|
352
|
+
"Failed to apply PII defense to streaming function %s",
|
|
353
|
+
context.name,
|
|
354
|
+
exc_info=True,
|
|
355
|
+
)
|
|
356
|
+
raise
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Registration module for defense middleware."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from collections.abc import AsyncGenerator
|
|
20
|
+
|
|
21
|
+
from nat.builder.builder import Builder
|
|
22
|
+
from nat.cli.register_workflow import register_middleware
|
|
23
|
+
from nat.middleware.defense.defense_middleware_content_guard import ContentSafetyGuardMiddleware
|
|
24
|
+
from nat.middleware.defense.defense_middleware_content_guard import ContentSafetyGuardMiddlewareConfig
|
|
25
|
+
from nat.middleware.defense.defense_middleware_output_verifier import OutputVerifierMiddleware
|
|
26
|
+
from nat.middleware.defense.defense_middleware_output_verifier import OutputVerifierMiddlewareConfig
|
|
27
|
+
from nat.middleware.defense.defense_middleware_pii import PIIDefenseMiddleware
|
|
28
|
+
from nat.middleware.defense.defense_middleware_pii import PIIDefenseMiddlewareConfig
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@register_middleware(config_type=ContentSafetyGuardMiddlewareConfig)
|
|
32
|
+
async def content_safety_guard_middleware(
|
|
33
|
+
config: ContentSafetyGuardMiddlewareConfig,
|
|
34
|
+
builder: Builder,
|
|
35
|
+
) -> AsyncGenerator[ContentSafetyGuardMiddleware, None]:
|
|
36
|
+
"""Build a Content Safety Guard middleware from configuration.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
config: The content safety guard middleware configuration
|
|
40
|
+
builder: The workflow builder used to resolve the LLM
|
|
41
|
+
|
|
42
|
+
Yields:
|
|
43
|
+
A configured Content Safety Guard middleware instance
|
|
44
|
+
"""
|
|
45
|
+
# Pass the builder and config, LLM will be loaded lazily
|
|
46
|
+
yield ContentSafetyGuardMiddleware(config=config, builder=builder)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@register_middleware(config_type=OutputVerifierMiddlewareConfig)
|
|
50
|
+
async def output_verifier_middleware(
|
|
51
|
+
config: OutputVerifierMiddlewareConfig,
|
|
52
|
+
builder: Builder,
|
|
53
|
+
) -> AsyncGenerator[OutputVerifierMiddleware, None]:
|
|
54
|
+
"""Build an Output Verifier middleware from configuration.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
config: The Output Verifier middleware configuration
|
|
58
|
+
builder: The workflow builder used to resolve the LLM
|
|
59
|
+
|
|
60
|
+
Yields:
|
|
61
|
+
A configured Output Verifier middleware instance
|
|
62
|
+
"""
|
|
63
|
+
# Pass the builder and config, LLM will be loaded lazily
|
|
64
|
+
yield OutputVerifierMiddleware(config=config, builder=builder)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@register_middleware(config_type=PIIDefenseMiddlewareConfig)
|
|
68
|
+
async def pii_defense_middleware(
|
|
69
|
+
config: PIIDefenseMiddlewareConfig,
|
|
70
|
+
builder: Builder,
|
|
71
|
+
) -> AsyncGenerator[PIIDefenseMiddleware, None]:
|
|
72
|
+
"""Build a PII Defense middleware from configuration.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
config: The PII Defense middleware configuration
|
|
76
|
+
builder: The workflow builder (not used for PII defense)
|
|
77
|
+
|
|
78
|
+
Yields:
|
|
79
|
+
A configured PII Defense middleware instance
|
|
80
|
+
"""
|
|
81
|
+
# Pass the builder and config, Presidio will be loaded lazily
|
|
82
|
+
yield PIIDefenseMiddleware(config=config, builder=builder)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|