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,496 @@
|
|
|
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 inspect
|
|
17
|
+
import logging
|
|
18
|
+
import types
|
|
19
|
+
from functools import lru_cache
|
|
20
|
+
from typing import Any
|
|
21
|
+
from typing import TypeVar
|
|
22
|
+
from typing import get_args
|
|
23
|
+
from typing import get_origin
|
|
24
|
+
|
|
25
|
+
from pydantic import BaseModel
|
|
26
|
+
from pydantic import ValidationError
|
|
27
|
+
from pydantic import create_model
|
|
28
|
+
from pydantic.fields import FieldInfo
|
|
29
|
+
|
|
30
|
+
from nat.utils.type_utils import DecomposedType
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TypeIntrospectionMixin:
|
|
36
|
+
"""Hybrid mixin class providing type introspection capabilities for generic classes.
|
|
37
|
+
|
|
38
|
+
This mixin combines the DecomposedType class utilities with MRO traversal
|
|
39
|
+
to properly handle complex inheritance chains like HeaderRedactionProcessor or ProcessingExporter.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def _extract_types_from_signature_method(self) -> tuple[type[Any], type[Any]] | None:
|
|
43
|
+
"""Extract input/output types from the signature method.
|
|
44
|
+
|
|
45
|
+
This method looks for a signature method (either defined via _signature_method class
|
|
46
|
+
attribute or discovered generically) and extracts input/output types from
|
|
47
|
+
its method signature.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
tuple[type[Any], type[Any]] | None: (input_type, output_type) or None if not found.
|
|
51
|
+
"""
|
|
52
|
+
# First, try to get the signature method name from the class
|
|
53
|
+
signature_method_name = getattr(self.__class__, '_signature_method', None)
|
|
54
|
+
|
|
55
|
+
# If not defined, try to discover it generically
|
|
56
|
+
if not signature_method_name:
|
|
57
|
+
signature_method_name = self._discover_signature_method()
|
|
58
|
+
|
|
59
|
+
if not signature_method_name:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
# Get the method and inspect its signature
|
|
63
|
+
try:
|
|
64
|
+
method = getattr(self, signature_method_name)
|
|
65
|
+
sig = inspect.signature(method)
|
|
66
|
+
|
|
67
|
+
# Find the first parameter that's not 'self'
|
|
68
|
+
params = list(sig.parameters.values())
|
|
69
|
+
input_param = None
|
|
70
|
+
for param in params:
|
|
71
|
+
if param.name != 'self':
|
|
72
|
+
input_param = param
|
|
73
|
+
break
|
|
74
|
+
|
|
75
|
+
if not input_param or input_param.annotation == inspect.Parameter.empty:
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
# Get return type
|
|
79
|
+
return_annotation = sig.return_annotation
|
|
80
|
+
if return_annotation == inspect.Signature.empty:
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
input_type = input_param.annotation
|
|
84
|
+
output_type = return_annotation
|
|
85
|
+
|
|
86
|
+
# Resolve any TypeVars if needed (including nested ones)
|
|
87
|
+
if isinstance(input_type, TypeVar) or isinstance(
|
|
88
|
+
output_type, TypeVar) or self._contains_typevar(input_type) or self._contains_typevar(output_type):
|
|
89
|
+
# Try to resolve using the MRO approach as fallback
|
|
90
|
+
typevar_mapping = self._build_typevar_mapping()
|
|
91
|
+
input_type = self._resolve_typevar_recursively(input_type, typevar_mapping)
|
|
92
|
+
output_type = self._resolve_typevar_recursively(output_type, typevar_mapping)
|
|
93
|
+
|
|
94
|
+
# Only return if we have concrete types
|
|
95
|
+
if not isinstance(input_type, TypeVar) and not isinstance(output_type, TypeVar):
|
|
96
|
+
return input_type, output_type
|
|
97
|
+
|
|
98
|
+
except (AttributeError, TypeError) as e:
|
|
99
|
+
logger.debug("Failed to extract types from signature method '%s': %s", signature_method_name, e)
|
|
100
|
+
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
def _discover_signature_method(self) -> str | None:
|
|
104
|
+
"""Discover any method suitable for type introspection.
|
|
105
|
+
|
|
106
|
+
Looks for any method with the signature pattern: method(self, param: Type) -> ReturnType
|
|
107
|
+
Any method matching this pattern is functionally equivalent for type introspection purposes.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
str | None: Method name or None if not found
|
|
111
|
+
"""
|
|
112
|
+
# Look through all methods to find ones that match the input/output pattern
|
|
113
|
+
candidates = []
|
|
114
|
+
|
|
115
|
+
for cls in self.__class__.__mro__:
|
|
116
|
+
for name, method in inspect.getmembers(cls, inspect.isfunction):
|
|
117
|
+
# Skip private methods except dunder methods
|
|
118
|
+
if name.startswith('_') and not name.startswith('__'):
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
# Skip methods that were defined in TypeIntrospectionMixin
|
|
122
|
+
if hasattr(method, '__qualname__') and 'TypeIntrospectionMixin' in method.__qualname__:
|
|
123
|
+
logger.debug("Skipping method '%s' defined in TypeIntrospectionMixin", name)
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
# Let signature analysis determine suitability - method names don't matter
|
|
127
|
+
try:
|
|
128
|
+
sig = inspect.signature(method)
|
|
129
|
+
params = list(sig.parameters.values())
|
|
130
|
+
|
|
131
|
+
# Look for methods with exactly one non-self parameter and a return annotation
|
|
132
|
+
non_self_params = [p for p in params if p.name != 'self']
|
|
133
|
+
if (len(non_self_params) == 1 and non_self_params[0].annotation != inspect.Parameter.empty
|
|
134
|
+
and sig.return_annotation != inspect.Signature.empty):
|
|
135
|
+
|
|
136
|
+
# Prioritize abstract methods
|
|
137
|
+
is_abstract = getattr(method, '__isabstractmethod__', False)
|
|
138
|
+
candidates.append((name, is_abstract, cls))
|
|
139
|
+
|
|
140
|
+
except (TypeError, ValueError) as e:
|
|
141
|
+
logger.debug("Failed to inspect signature of method '%s': %s", name, e)
|
|
142
|
+
|
|
143
|
+
if not candidates:
|
|
144
|
+
logger.debug("No candidates found for signature method")
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
# Any method with the right signature will work for type introspection
|
|
148
|
+
# Prioritize abstract methods if available, otherwise use the first valid one
|
|
149
|
+
candidates.sort(key=lambda x: not x[1]) # Abstract methods first
|
|
150
|
+
return candidates[0][0]
|
|
151
|
+
|
|
152
|
+
def _resolve_typevar_recursively(self, type_arg: Any, typevar_mapping: dict[TypeVar, type[Any]]) -> Any:
|
|
153
|
+
"""Recursively resolve TypeVars within complex types.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
type_arg (Any): The type argument to resolve (could be a TypeVar, generic type, etc.)
|
|
157
|
+
typevar_mapping (dict[TypeVar, type[Any]]): Current mapping of TypeVars to concrete types
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Any: The resolved type with all TypeVars substituted
|
|
161
|
+
"""
|
|
162
|
+
# If it's a TypeVar, resolve it
|
|
163
|
+
if isinstance(type_arg, TypeVar):
|
|
164
|
+
return typevar_mapping.get(type_arg, type_arg)
|
|
165
|
+
|
|
166
|
+
# If it's a generic type, decompose and resolve its arguments
|
|
167
|
+
try:
|
|
168
|
+
decomposed = DecomposedType(type_arg)
|
|
169
|
+
if decomposed.is_generic and decomposed.args:
|
|
170
|
+
# Recursively resolve all type arguments
|
|
171
|
+
resolved_args = []
|
|
172
|
+
for arg in decomposed.args:
|
|
173
|
+
resolved_arg = self._resolve_typevar_recursively(arg, typevar_mapping)
|
|
174
|
+
resolved_args.append(resolved_arg)
|
|
175
|
+
|
|
176
|
+
# Reconstruct the generic type with resolved arguments
|
|
177
|
+
if decomposed.origin:
|
|
178
|
+
return decomposed.origin[tuple(resolved_args)]
|
|
179
|
+
|
|
180
|
+
except (TypeError, AttributeError) as e:
|
|
181
|
+
# If we can't decompose or reconstruct, return as-is
|
|
182
|
+
logger.debug("Failed to decompose or reconstruct type '%s': %s", type_arg, e)
|
|
183
|
+
|
|
184
|
+
return type_arg
|
|
185
|
+
|
|
186
|
+
def _contains_typevar(self, type_arg: Any) -> bool:
|
|
187
|
+
"""Check if a type contains any TypeVars (including nested ones).
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
type_arg (Any): The type to check
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
bool: True if the type contains any TypeVars
|
|
194
|
+
"""
|
|
195
|
+
if isinstance(type_arg, TypeVar):
|
|
196
|
+
return True
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
decomposed = DecomposedType(type_arg)
|
|
200
|
+
if decomposed.is_generic and decomposed.args:
|
|
201
|
+
return any(self._contains_typevar(arg) for arg in decomposed.args)
|
|
202
|
+
except (TypeError, AttributeError) as e:
|
|
203
|
+
logger.debug("Failed to decompose or reconstruct type '%s': %s", type_arg, e)
|
|
204
|
+
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
def _build_typevar_mapping(self) -> dict[TypeVar, type[Any]]:
|
|
208
|
+
"""Build TypeVar to concrete type mapping from MRO traversal.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
dict[TypeVar, type[Any]]: Mapping of TypeVars to concrete types
|
|
212
|
+
"""
|
|
213
|
+
typevar_mapping = {}
|
|
214
|
+
|
|
215
|
+
# First, check if the instance has concrete type arguments from __orig_class__
|
|
216
|
+
# This handles cases like BatchingProcessor[str]() where we need to map T -> str
|
|
217
|
+
orig_class = getattr(self, '__orig_class__', None)
|
|
218
|
+
if orig_class:
|
|
219
|
+
class_origin = get_origin(orig_class)
|
|
220
|
+
class_args = get_args(orig_class)
|
|
221
|
+
class_params = getattr(class_origin, '__parameters__', None)
|
|
222
|
+
|
|
223
|
+
if class_args and class_params:
|
|
224
|
+
# Map class-level TypeVars to their concrete arguments
|
|
225
|
+
for param, arg in zip(class_params, class_args):
|
|
226
|
+
typevar_mapping[param] = arg
|
|
227
|
+
|
|
228
|
+
# Then traverse the MRO to build the complete mapping
|
|
229
|
+
for cls in self.__class__.__mro__:
|
|
230
|
+
for base in getattr(cls, '__orig_bases__', []):
|
|
231
|
+
decomposed_base = DecomposedType(base)
|
|
232
|
+
|
|
233
|
+
if (decomposed_base.is_generic and decomposed_base.origin
|
|
234
|
+
and hasattr(decomposed_base.origin, '__parameters__')):
|
|
235
|
+
type_params = decomposed_base.origin.__parameters__
|
|
236
|
+
# Map each TypeVar to its concrete argument
|
|
237
|
+
for param, arg in zip(type_params, decomposed_base.args):
|
|
238
|
+
if param not in typevar_mapping: # Keep the most specific mapping
|
|
239
|
+
# If arg is also a TypeVar, try to resolve it
|
|
240
|
+
if isinstance(arg, TypeVar) and arg in typevar_mapping:
|
|
241
|
+
typevar_mapping[param] = typevar_mapping[arg]
|
|
242
|
+
else:
|
|
243
|
+
typevar_mapping[param] = arg
|
|
244
|
+
|
|
245
|
+
return typevar_mapping
|
|
246
|
+
|
|
247
|
+
def _extract_instance_types_from_mro(self) -> tuple[type[Any], type[Any]] | None:
|
|
248
|
+
"""Extract Generic[InputT, OutputT] types by traversing the MRO.
|
|
249
|
+
|
|
250
|
+
This handles complex inheritance chains by looking for the base
|
|
251
|
+
class and resolving TypeVars through the inheritance hierarchy.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
tuple[type[Any], type[Any]] | None: (input_type, output_type) or None if not found
|
|
255
|
+
"""
|
|
256
|
+
# Use the centralized TypeVar mapping
|
|
257
|
+
typevar_mapping = self._build_typevar_mapping()
|
|
258
|
+
|
|
259
|
+
# Now find the first generic base with exactly 2 parameters, starting from the base classes
|
|
260
|
+
# This ensures we get the fundamental input/output types rather than specialized ones
|
|
261
|
+
for cls in reversed(self.__class__.__mro__):
|
|
262
|
+
for base in getattr(cls, '__orig_bases__', []):
|
|
263
|
+
decomposed_base = DecomposedType(base)
|
|
264
|
+
|
|
265
|
+
# Look for any generic with exactly 2 parameters (likely InputT, OutputT pattern)
|
|
266
|
+
if decomposed_base.is_generic and len(decomposed_base.args) == 2:
|
|
267
|
+
input_type = decomposed_base.args[0]
|
|
268
|
+
output_type = decomposed_base.args[1]
|
|
269
|
+
|
|
270
|
+
# Resolve TypeVars to concrete types using recursive resolution
|
|
271
|
+
input_type = self._resolve_typevar_recursively(input_type, typevar_mapping)
|
|
272
|
+
output_type = self._resolve_typevar_recursively(output_type, typevar_mapping)
|
|
273
|
+
|
|
274
|
+
# Only return if we have concrete types (not TypeVars)
|
|
275
|
+
if not isinstance(input_type, TypeVar) and not isinstance(output_type, TypeVar):
|
|
276
|
+
return input_type, output_type
|
|
277
|
+
|
|
278
|
+
return None
|
|
279
|
+
|
|
280
|
+
@lru_cache
|
|
281
|
+
def _extract_input_output_types(self) -> tuple[type[Any], type[Any]]:
|
|
282
|
+
"""Extract both input and output types using available approaches.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
tuple[type[Any], type[Any]]: (input_type, output_type)
|
|
286
|
+
|
|
287
|
+
Raises:
|
|
288
|
+
ValueError: If types cannot be extracted
|
|
289
|
+
"""
|
|
290
|
+
# First try the signature-based approach
|
|
291
|
+
result = self._extract_types_from_signature_method()
|
|
292
|
+
if result:
|
|
293
|
+
return result
|
|
294
|
+
|
|
295
|
+
# Fallback to MRO-based approach for complex inheritance
|
|
296
|
+
result = self._extract_instance_types_from_mro()
|
|
297
|
+
if result:
|
|
298
|
+
return result
|
|
299
|
+
|
|
300
|
+
raise ValueError(f"Could not extract input/output types from {self.__class__.__name__}. "
|
|
301
|
+
f"Ensure class inherits from a generic like Processor[InputT, OutputT] "
|
|
302
|
+
f"or has a signature method with type annotations")
|
|
303
|
+
|
|
304
|
+
@property
|
|
305
|
+
def input_type(self) -> type[Any]:
|
|
306
|
+
"""Get the input type of the instance.
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
type[Any]: The input type
|
|
310
|
+
"""
|
|
311
|
+
return self._extract_input_output_types()[0]
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def output_type(self) -> type[Any]:
|
|
315
|
+
"""Get the output type of the instance.
|
|
316
|
+
|
|
317
|
+
Returns:
|
|
318
|
+
type[Any]: The output type
|
|
319
|
+
"""
|
|
320
|
+
return self._extract_input_output_types()[1]
|
|
321
|
+
|
|
322
|
+
@lru_cache
|
|
323
|
+
def _get_union_info(self, type_obj: type[Any]) -> tuple[bool, tuple[type, ...] | None]:
|
|
324
|
+
"""Get union information for a type.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
type_obj (type[Any]): The type to analyze
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
tuple[bool, tuple[type, ...] | None]: (is_union, union_types_or_none)
|
|
331
|
+
"""
|
|
332
|
+
decomposed = DecomposedType(type_obj)
|
|
333
|
+
return decomposed.is_union, decomposed.args if decomposed.is_union else None
|
|
334
|
+
|
|
335
|
+
@property
|
|
336
|
+
def has_union_input(self) -> bool:
|
|
337
|
+
"""Check if the input type is a union type.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
bool: True if the input type is a union type, False otherwise
|
|
341
|
+
"""
|
|
342
|
+
return self._get_union_info(self.input_type)[0]
|
|
343
|
+
|
|
344
|
+
@property
|
|
345
|
+
def has_union_output(self) -> bool:
|
|
346
|
+
"""Check if the output type is a union type.
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
bool: True if the output type is a union type, False otherwise
|
|
350
|
+
"""
|
|
351
|
+
return self._get_union_info(self.output_type)[0]
|
|
352
|
+
|
|
353
|
+
@property
|
|
354
|
+
def input_union_types(self) -> tuple[type, ...] | None:
|
|
355
|
+
"""Get the individual types in an input union.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
tuple[type, ...] | None: The individual types in an input union or None if not found
|
|
359
|
+
"""
|
|
360
|
+
return self._get_union_info(self.input_type)[1]
|
|
361
|
+
|
|
362
|
+
@property
|
|
363
|
+
def output_union_types(self) -> tuple[type, ...] | None:
|
|
364
|
+
"""Get the individual types in an output union.
|
|
365
|
+
|
|
366
|
+
Returns:
|
|
367
|
+
tuple[type, ...] | None: The individual types in an output union or None if not found
|
|
368
|
+
"""
|
|
369
|
+
return self._get_union_info(self.output_type)[1]
|
|
370
|
+
|
|
371
|
+
def is_compatible_with_input(self, source_type: type) -> bool:
|
|
372
|
+
"""Check if a source type is compatible with this instance's input type.
|
|
373
|
+
|
|
374
|
+
Uses Pydantic-based type compatibility checking for strict type matching.
|
|
375
|
+
This focuses on proper type relationships rather than batch compatibility.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
source_type (type): The source type to check
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
bool: True if the source type is compatible with the input type, False otherwise
|
|
382
|
+
"""
|
|
383
|
+
return self._is_pydantic_type_compatible(source_type, self.input_type)
|
|
384
|
+
|
|
385
|
+
def is_output_compatible_with(self, target_type: type) -> bool:
|
|
386
|
+
"""Check if this instance's output type is compatible with a target type.
|
|
387
|
+
|
|
388
|
+
Uses Pydantic-based type compatibility checking for strict type matching.
|
|
389
|
+
This focuses on proper type relationships rather than batch compatibility.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
target_type (type): The target type to check
|
|
393
|
+
|
|
394
|
+
Returns:
|
|
395
|
+
bool: True if the output type is compatible with the target type, False otherwise
|
|
396
|
+
"""
|
|
397
|
+
return self._is_pydantic_type_compatible(self.output_type, target_type)
|
|
398
|
+
|
|
399
|
+
def _is_pydantic_type_compatible(self, source_type: type, target_type: type) -> bool:
|
|
400
|
+
"""Check strict type compatibility without batch compatibility hacks.
|
|
401
|
+
|
|
402
|
+
This focuses on proper type relationships: exact matches and subclass relationships.
|
|
403
|
+
|
|
404
|
+
Args:
|
|
405
|
+
source_type (type): The source type to check
|
|
406
|
+
target_type (type): The target type to check compatibility with
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
bool: True if types are compatible, False otherwise
|
|
410
|
+
"""
|
|
411
|
+
# Direct equality check (most common case)
|
|
412
|
+
if source_type == target_type:
|
|
413
|
+
return True
|
|
414
|
+
|
|
415
|
+
# Subclass relationship check
|
|
416
|
+
try:
|
|
417
|
+
if issubclass(source_type, target_type):
|
|
418
|
+
return True
|
|
419
|
+
except TypeError:
|
|
420
|
+
# Generic types can't use issubclass, they're only compatible if equal
|
|
421
|
+
logger.debug("Generic type %s cannot be used with issubclass, they're only compatible if equal",
|
|
422
|
+
source_type)
|
|
423
|
+
|
|
424
|
+
return False
|
|
425
|
+
|
|
426
|
+
@lru_cache
|
|
427
|
+
def _get_input_validator(self) -> type[BaseModel]:
|
|
428
|
+
"""Create a Pydantic model for validating input types.
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
type[BaseModel]: The Pydantic model for validating input types
|
|
432
|
+
"""
|
|
433
|
+
input_type = self.input_type
|
|
434
|
+
return create_model(f"{self.__class__.__name__}InputValidator", input=(input_type, FieldInfo()))
|
|
435
|
+
|
|
436
|
+
@lru_cache
|
|
437
|
+
def _get_output_validator(self) -> type[BaseModel]:
|
|
438
|
+
"""Create a Pydantic model for validating output types.
|
|
439
|
+
|
|
440
|
+
Returns:
|
|
441
|
+
type[BaseModel]: The Pydantic model for validating output types
|
|
442
|
+
"""
|
|
443
|
+
output_type = self.output_type
|
|
444
|
+
return create_model(f"{self.__class__.__name__}OutputValidator", output=(output_type, FieldInfo()))
|
|
445
|
+
|
|
446
|
+
def validate_input_type(self, item: Any) -> bool:
|
|
447
|
+
"""Validate that an item matches the expected input type using Pydantic.
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
item (Any): The item to validate
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
bool: True if the item matches the input type, False otherwise
|
|
454
|
+
"""
|
|
455
|
+
try:
|
|
456
|
+
validator = self._get_input_validator()
|
|
457
|
+
validator(input=item)
|
|
458
|
+
return True
|
|
459
|
+
except ValidationError:
|
|
460
|
+
logger.warning("Item %s is not compatible with input type %s", item, self.input_type)
|
|
461
|
+
return False
|
|
462
|
+
|
|
463
|
+
def validate_output_type(self, item: Any) -> bool:
|
|
464
|
+
"""Validate that an item matches the expected output type using Pydantic.
|
|
465
|
+
|
|
466
|
+
Args:
|
|
467
|
+
item (Any): The item to validate
|
|
468
|
+
|
|
469
|
+
Returns:
|
|
470
|
+
bool: True if the item matches the output type, False otherwise
|
|
471
|
+
"""
|
|
472
|
+
try:
|
|
473
|
+
validator = self._get_output_validator()
|
|
474
|
+
validator(output=item)
|
|
475
|
+
return True
|
|
476
|
+
except ValidationError:
|
|
477
|
+
logger.warning("Item %s is not compatible with output type %s", item, self.output_type)
|
|
478
|
+
return False
|
|
479
|
+
|
|
480
|
+
@lru_cache
|
|
481
|
+
def extract_non_optional_type(self, type_obj: type | types.UnionType) -> Any:
|
|
482
|
+
"""Extract the non-None type from Optional[T] or Union[T, None] types.
|
|
483
|
+
|
|
484
|
+
This is useful when you need to pass a type to a system that doesn't
|
|
485
|
+
understand Optional types (like registries that expect concrete types).
|
|
486
|
+
|
|
487
|
+
Args:
|
|
488
|
+
type_obj (type | types.UnionType): The type to extract from (could be Optional[T] or Union[T, None])
|
|
489
|
+
|
|
490
|
+
Returns:
|
|
491
|
+
Any: The actual type without None, or the original type if not a union with None
|
|
492
|
+
"""
|
|
493
|
+
decomposed = DecomposedType(type_obj) # type: ignore[arg-type]
|
|
494
|
+
if decomposed.is_optional:
|
|
495
|
+
return decomposed.get_optional_type().type
|
|
496
|
+
return type_obj
|
|
@@ -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.
|