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,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.
|
|
@@ -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.
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from nat.authentication.interfaces import FlowHandlerBase
|
|
17
|
+
from nat.data_models.authentication import AuthenticatedContext
|
|
18
|
+
from nat.data_models.authentication import AuthFlowType
|
|
19
|
+
from nat.data_models.authentication import AuthProviderBaseConfig
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class HTTPAuthenticationFlowHandler(FlowHandlerBase):
|
|
23
|
+
|
|
24
|
+
async def authenticate(self, config: AuthProviderBaseConfig, method: AuthFlowType) -> AuthenticatedContext:
|
|
25
|
+
|
|
26
|
+
raise NotImplementedError(f"Authentication method '{method}' is not supported by the HTTP frontend."
|
|
27
|
+
f" Do you have WebSockets enabled?")
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import logging
|
|
18
|
+
import secrets
|
|
19
|
+
from collections.abc import Awaitable
|
|
20
|
+
from collections.abc import Callable
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from dataclasses import field
|
|
23
|
+
|
|
24
|
+
import pkce
|
|
25
|
+
from authlib.common.errors import AuthlibBaseError as OAuthError
|
|
26
|
+
from authlib.integrations.httpx_client import AsyncOAuth2Client
|
|
27
|
+
|
|
28
|
+
from nat.authentication.interfaces import FlowHandlerBase
|
|
29
|
+
from nat.authentication.oauth2.oauth2_auth_code_flow_provider_config import OAuth2AuthCodeFlowProviderConfig
|
|
30
|
+
from nat.data_models.authentication import AuthenticatedContext
|
|
31
|
+
from nat.data_models.authentication import AuthFlowType
|
|
32
|
+
from nat.data_models.interactive import _HumanPromptOAuthConsent
|
|
33
|
+
from nat.front_ends.fastapi.message_handler import WebSocketMessageHandler
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class FlowState:
|
|
40
|
+
future: asyncio.Future = field(default_factory=asyncio.Future, init=False)
|
|
41
|
+
challenge: str | None = None
|
|
42
|
+
verifier: str | None = None
|
|
43
|
+
client: AsyncOAuth2Client | None = None
|
|
44
|
+
config: OAuth2AuthCodeFlowProviderConfig | None = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class WebSocketAuthenticationFlowHandler(FlowHandlerBase):
|
|
48
|
+
|
|
49
|
+
def __init__(self,
|
|
50
|
+
add_flow_cb: Callable[[str, FlowState], Awaitable[None]],
|
|
51
|
+
remove_flow_cb: Callable[[str], Awaitable[None]],
|
|
52
|
+
web_socket_message_handler: WebSocketMessageHandler):
|
|
53
|
+
|
|
54
|
+
self._add_flow_cb: Callable[[str, FlowState], Awaitable[None]] = add_flow_cb
|
|
55
|
+
self._remove_flow_cb: Callable[[str], Awaitable[None]] = remove_flow_cb
|
|
56
|
+
self._web_socket_message_handler: WebSocketMessageHandler = web_socket_message_handler
|
|
57
|
+
|
|
58
|
+
async def authenticate(self, config: OAuth2AuthCodeFlowProviderConfig,
|
|
59
|
+
method: AuthFlowType) -> AuthenticatedContext:
|
|
60
|
+
if method == AuthFlowType.OAUTH2_AUTHORIZATION_CODE:
|
|
61
|
+
return await self._handle_oauth2_auth_code_flow(config)
|
|
62
|
+
|
|
63
|
+
raise NotImplementedError(f"Authentication method '{method}' is not supported by the websocket frontend.")
|
|
64
|
+
|
|
65
|
+
def create_oauth_client(self, config: OAuth2AuthCodeFlowProviderConfig) -> AsyncOAuth2Client:
|
|
66
|
+
try:
|
|
67
|
+
return AsyncOAuth2Client(client_id=config.client_id,
|
|
68
|
+
client_secret=config.client_secret,
|
|
69
|
+
redirect_uri=config.redirect_uri,
|
|
70
|
+
scope=" ".join(config.scopes) if config.scopes else None,
|
|
71
|
+
token_endpoint=config.token_url,
|
|
72
|
+
code_challenge_method='S256' if config.use_pkce else None,
|
|
73
|
+
token_endpoint_auth_method=config.token_endpoint_auth_method)
|
|
74
|
+
except (OAuthError, ValueError, TypeError) as e:
|
|
75
|
+
raise RuntimeError(f"Invalid OAuth2 configuration: {e}") from e
|
|
76
|
+
except Exception as e:
|
|
77
|
+
raise RuntimeError(f"Failed to create OAuth2 client: {e}") from e
|
|
78
|
+
|
|
79
|
+
def _create_authorization_url(self,
|
|
80
|
+
client: AsyncOAuth2Client,
|
|
81
|
+
config: OAuth2AuthCodeFlowProviderConfig,
|
|
82
|
+
state: str,
|
|
83
|
+
verifier: str = None,
|
|
84
|
+
challenge: str = None) -> str:
|
|
85
|
+
"""
|
|
86
|
+
Create OAuth authorization URL with proper error handling.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
client: The OAuth2 client instance
|
|
90
|
+
config: OAuth2 configuration
|
|
91
|
+
state: OAuth state parameter
|
|
92
|
+
verifier: PKCE verifier (if using PKCE)
|
|
93
|
+
challenge: PKCE challenge (if using PKCE)
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
The authorization URL
|
|
97
|
+
"""
|
|
98
|
+
try:
|
|
99
|
+
authorization_url, _ = client.create_authorization_url(
|
|
100
|
+
config.authorization_url,
|
|
101
|
+
state=state,
|
|
102
|
+
code_verifier=verifier if config.use_pkce else None,
|
|
103
|
+
code_challenge=challenge if config.use_pkce else None,
|
|
104
|
+
**(config.authorization_kwargs or {})
|
|
105
|
+
)
|
|
106
|
+
return authorization_url
|
|
107
|
+
except (OAuthError, ValueError, TypeError) as e:
|
|
108
|
+
raise RuntimeError(f"Error creating OAuth authorization URL: {e}") from e
|
|
109
|
+
|
|
110
|
+
async def _handle_oauth2_auth_code_flow(self, config: OAuth2AuthCodeFlowProviderConfig) -> AuthenticatedContext:
|
|
111
|
+
|
|
112
|
+
state = secrets.token_urlsafe(16)
|
|
113
|
+
flow_state = FlowState(config=config)
|
|
114
|
+
|
|
115
|
+
flow_state.client = self.create_oauth_client(config)
|
|
116
|
+
|
|
117
|
+
if config.use_pkce:
|
|
118
|
+
verifier, challenge = pkce.generate_pkce_pair()
|
|
119
|
+
flow_state.verifier = verifier
|
|
120
|
+
flow_state.challenge = challenge
|
|
121
|
+
|
|
122
|
+
authorization_url = self._create_authorization_url(client=flow_state.client,
|
|
123
|
+
config=config,
|
|
124
|
+
state=state,
|
|
125
|
+
verifier=flow_state.verifier,
|
|
126
|
+
challenge=flow_state.challenge)
|
|
127
|
+
|
|
128
|
+
await self._add_flow_cb(state, flow_state)
|
|
129
|
+
await self._web_socket_message_handler.create_websocket_message(_HumanPromptOAuthConsent(text=authorization_url)
|
|
130
|
+
)
|
|
131
|
+
try:
|
|
132
|
+
token = await asyncio.wait_for(flow_state.future, timeout=300)
|
|
133
|
+
except TimeoutError as exc:
|
|
134
|
+
raise RuntimeError("Authentication flow timed out after 5 minutes.") from exc
|
|
135
|
+
finally:
|
|
136
|
+
|
|
137
|
+
await self._remove_flow_cb(state)
|
|
138
|
+
|
|
139
|
+
return AuthenticatedContext(headers={"Authorization": f"Bearer {token['access_token']}"},
|
|
140
|
+
metadata={
|
|
141
|
+
"expires_at": token.get("expires_at"), "raw_token": token
|
|
142
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
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 typing
|
|
17
|
+
from abc import ABC
|
|
18
|
+
from collections.abc import AsyncGenerator
|
|
19
|
+
from collections.abc import Generator
|
|
20
|
+
from contextlib import asynccontextmanager
|
|
21
|
+
from contextlib import contextmanager
|
|
22
|
+
|
|
23
|
+
if typing.TYPE_CHECKING:
|
|
24
|
+
from dask.distributed import Client
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class DaskClientMixin(ABC):
|
|
28
|
+
|
|
29
|
+
@asynccontextmanager
|
|
30
|
+
async def client(self, address: str) -> AsyncGenerator["Client"]:
|
|
31
|
+
"""
|
|
32
|
+
Async context manager for obtaining a Dask client.
|
|
33
|
+
|
|
34
|
+
Yields
|
|
35
|
+
------
|
|
36
|
+
Client
|
|
37
|
+
An async Dask client connected to the scheduler. The client is automatically closed when exiting the
|
|
38
|
+
context manager.
|
|
39
|
+
"""
|
|
40
|
+
from dask.distributed import Client
|
|
41
|
+
client = await Client(address=address, asynchronous=True)
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
yield client
|
|
45
|
+
finally:
|
|
46
|
+
await client.close()
|
|
47
|
+
|
|
48
|
+
@contextmanager
|
|
49
|
+
def blocking_client(self, address: str) -> Generator["Client"]:
|
|
50
|
+
"""
|
|
51
|
+
context manager for obtaining a blocking Dask client.
|
|
52
|
+
|
|
53
|
+
Yields
|
|
54
|
+
------
|
|
55
|
+
Client
|
|
56
|
+
A blocking Dask client connected to the scheduler. The client is automatically closed when exiting the
|
|
57
|
+
context manager.
|
|
58
|
+
"""
|
|
59
|
+
from dask.distributed import Client
|
|
60
|
+
client = Client(address=address)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
yield client
|
|
64
|
+
finally:
|
|
65
|
+
client.close()
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
import typing
|
|
20
|
+
from datetime import datetime
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
from pydantic import BaseModel
|
|
24
|
+
from pydantic import Field
|
|
25
|
+
from pydantic import field_validator
|
|
26
|
+
|
|
27
|
+
from nat.data_models.component_ref import ObjectStoreRef
|
|
28
|
+
from nat.data_models.front_end import FrontEndBaseConfig
|
|
29
|
+
from nat.data_models.step_adaptor import StepAdaptorConfig
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
YAML_EXTENSIONS = (".yaml", ".yml")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _is_reserved(path: Path) -> bool:
|
|
37
|
+
"""
|
|
38
|
+
Check if a path is reserved in the current Python version and platform.
|
|
39
|
+
|
|
40
|
+
On Windows, this function checks if the path is reserved in the current Python version.
|
|
41
|
+
On other platforms, returns False
|
|
42
|
+
"""
|
|
43
|
+
if sys.platform != "win32":
|
|
44
|
+
return False
|
|
45
|
+
if sys.version_info >= (3, 13):
|
|
46
|
+
return os.path.isreserved(path)
|
|
47
|
+
return path.is_reserved()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class EvaluateRequest(BaseModel):
|
|
51
|
+
"""Request model for the evaluate endpoint."""
|
|
52
|
+
config_file: str = Field(description="Path to the configuration file for evaluation")
|
|
53
|
+
job_id: str | None = Field(default=None, description="Unique identifier for the evaluation job")
|
|
54
|
+
reps: int = Field(default=1, gt=0, description="Number of repetitions for the evaluation, defaults to 1")
|
|
55
|
+
expiry_seconds: int = Field(
|
|
56
|
+
default=3600,
|
|
57
|
+
gt=0,
|
|
58
|
+
description="Optional time (in seconds) before the job expires. Clamped between 600 (10 min) and 86400 (24h).")
|
|
59
|
+
|
|
60
|
+
@field_validator('job_id', mode='after')
|
|
61
|
+
@classmethod
|
|
62
|
+
def validate_job_id(cls, job_id: str):
|
|
63
|
+
job_id = job_id.strip()
|
|
64
|
+
job_id_path = Path(job_id)
|
|
65
|
+
if len(job_id_path.parts) > 1 or job_id_path.resolve().name != job_id:
|
|
66
|
+
raise ValueError(
|
|
67
|
+
f"Job ID '{job_id}' contains invalid characters. Only alphanumeric characters and underscores are"
|
|
68
|
+
" allowed.")
|
|
69
|
+
|
|
70
|
+
if _is_reserved(job_id_path):
|
|
71
|
+
# reserved names is Windows specific
|
|
72
|
+
raise ValueError(f"Job ID '{job_id}' is a reserved name. Please choose a different name.")
|
|
73
|
+
|
|
74
|
+
return job_id
|
|
75
|
+
|
|
76
|
+
@field_validator('config_file', mode='after')
|
|
77
|
+
@classmethod
|
|
78
|
+
def validate_config_file(cls, config_file: str):
|
|
79
|
+
config_file = config_file.strip()
|
|
80
|
+
config_file_path = Path(config_file).resolve()
|
|
81
|
+
|
|
82
|
+
# Ensure the config file is a YAML file
|
|
83
|
+
if config_file_path.suffix.lower() not in YAML_EXTENSIONS:
|
|
84
|
+
raise ValueError(f"Config file '{config_file}' must be a YAML file with one of the following extensions: "
|
|
85
|
+
f"{', '.join(YAML_EXTENSIONS)}")
|
|
86
|
+
|
|
87
|
+
if _is_reserved(config_file_path):
|
|
88
|
+
# reserved names is Windows specific
|
|
89
|
+
raise ValueError(f"Config file '{config_file}' is a reserved name. Please choose a different name.")
|
|
90
|
+
|
|
91
|
+
if not config_file_path.exists():
|
|
92
|
+
raise ValueError(f"Config file '{config_file}' does not exist. Please provide a valid path.")
|
|
93
|
+
|
|
94
|
+
return config_file
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class BaseAsyncResponse(BaseModel):
|
|
98
|
+
"""Base model for async responses."""
|
|
99
|
+
job_id: str = Field(description="Unique identifier for the job")
|
|
100
|
+
status: str = Field(description="Current status of the job")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class EvaluateResponse(BaseAsyncResponse):
|
|
104
|
+
"""Response model for the evaluate endpoint."""
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class AsyncGenerateResponse(BaseAsyncResponse):
|
|
109
|
+
"""Response model for the async generation endpoint."""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class BaseAsyncStatusResponse(BaseModel):
|
|
114
|
+
"""Base model for async status responses."""
|
|
115
|
+
job_id: str = Field(description="Unique identifier for the evaluation job")
|
|
116
|
+
status: str = Field(description="Current status of the evaluation job")
|
|
117
|
+
error: str | None = Field(default=None, description="Error message if the job failed")
|
|
118
|
+
created_at: datetime = Field(description="Timestamp when the job was created")
|
|
119
|
+
updated_at: datetime = Field(description="Timestamp when the job was last updated")
|
|
120
|
+
expires_at: datetime | None = Field(default=None, description="Timestamp when the job will expire")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class EvaluateStatusResponse(BaseAsyncStatusResponse):
|
|
124
|
+
"""Response model for the evaluate status endpoint."""
|
|
125
|
+
config_file: str = Field(description="Path to the configuration file used for evaluation")
|
|
126
|
+
output_path: str | None = Field(default=None,
|
|
127
|
+
description="Path to the output file if the job completed successfully")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class AsyncGenerationStatusResponse(BaseAsyncStatusResponse):
|
|
131
|
+
output: dict | None = Field(
|
|
132
|
+
default=None,
|
|
133
|
+
description="Output of the generate request, this is only available if the job completed successfully.")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class FastApiFrontEndConfig(FrontEndBaseConfig, name="fastapi"):
|
|
137
|
+
"""
|
|
138
|
+
A FastAPI based front end that allows a NAT workflow to be served as a microservice.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
class EndpointBase(BaseModel):
|
|
142
|
+
|
|
143
|
+
method: typing.Literal["GET", "POST", "PUT", "DELETE"]
|
|
144
|
+
description: str
|
|
145
|
+
path: str | None = Field(
|
|
146
|
+
default=None,
|
|
147
|
+
description=("Path for the default workflow. If None, no workflow endpoint is created."),
|
|
148
|
+
)
|
|
149
|
+
websocket_path: str | None = Field(
|
|
150
|
+
default=None,
|
|
151
|
+
description=("Path for the websocket. If None, no websocket is created."),
|
|
152
|
+
)
|
|
153
|
+
openai_api_path: str | None = Field(
|
|
154
|
+
default=None,
|
|
155
|
+
description=("Path for the default workflow using the OpenAI API Specification. "
|
|
156
|
+
"If None, no workflow endpoint with the OpenAI API Specification is created."),
|
|
157
|
+
)
|
|
158
|
+
openai_api_v1_path: str | None = Field(
|
|
159
|
+
default=None,
|
|
160
|
+
description=("Path for the OpenAI v1 Chat Completions API compatible endpoint. "
|
|
161
|
+
"If provided, creates a single endpoint that handles both streaming and "
|
|
162
|
+
"non-streaming requests based on the 'stream' parameter, following the "
|
|
163
|
+
"OpenAI Chat Completions API specification exactly."),
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
class Endpoint(EndpointBase):
|
|
167
|
+
function_name: str = Field(description="The name of the function to call for this endpoint")
|
|
168
|
+
|
|
169
|
+
class CrossOriginResourceSharing(BaseModel):
|
|
170
|
+
allow_origins: list[str] | None = Field(
|
|
171
|
+
default=None, description=" A list of origins that should be permitted to make cross-origin requests.")
|
|
172
|
+
allow_origin_regex: str | None = Field(
|
|
173
|
+
default=None,
|
|
174
|
+
description="A permitted regex string to match against origins to make cross-origin requests",
|
|
175
|
+
)
|
|
176
|
+
allow_methods: list[str] | None = Field(
|
|
177
|
+
default_factory=lambda: ['GET'],
|
|
178
|
+
description="A list of HTTP methods that should be allowed for cross-origin requests.")
|
|
179
|
+
allow_headers: list[str] | None = Field(
|
|
180
|
+
default_factory=list,
|
|
181
|
+
description="A list of HTTP request headers that should be supported for cross-origin requests.")
|
|
182
|
+
allow_credentials: bool | None = Field(
|
|
183
|
+
default=False,
|
|
184
|
+
description="Indicate that cookies should be supported for cross-origin requests.",
|
|
185
|
+
)
|
|
186
|
+
expose_headers: list[str] | None = Field(
|
|
187
|
+
default_factory=list,
|
|
188
|
+
description="Indicate any response headers that should be made accessible to the browser.",
|
|
189
|
+
)
|
|
190
|
+
max_age: int | None = Field(
|
|
191
|
+
default=600,
|
|
192
|
+
description="Sets a maximum time in seconds for browsers to cache CORS responses.",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
root_path: str = Field(default="", description="The root path for the API")
|
|
196
|
+
host: str = Field(default="localhost", description="Host to bind the server to")
|
|
197
|
+
port: int = Field(default=8000, description="Port to bind the server to", ge=0, le=65535)
|
|
198
|
+
reload: bool = Field(default=False, description="Enable auto-reload for development")
|
|
199
|
+
workers: int = Field(default=1, description="Number of workers to run", ge=1)
|
|
200
|
+
scheduler_address: str | None = Field(
|
|
201
|
+
default=None,
|
|
202
|
+
description=("Address of the Dask scheduler to use for async jobs. If None, a Dask local cluster is created. "
|
|
203
|
+
"Note: This requires the optional dask dependency to be installed."))
|
|
204
|
+
db_url: str | None = Field(
|
|
205
|
+
default=None,
|
|
206
|
+
description=
|
|
207
|
+
"SQLAlchemy database URL for storing async job metadata, if unset a temporary SQLite database is used.")
|
|
208
|
+
max_running_async_jobs: int = Field(
|
|
209
|
+
default=10,
|
|
210
|
+
description=(
|
|
211
|
+
"Maximum number of async jobs to run concurrently, this controls the number of dask workers created. "
|
|
212
|
+
"This parameter is only used when scheduler_address is `None` and a Dask local cluster is created."),
|
|
213
|
+
ge=1)
|
|
214
|
+
dask_log_level: str = Field(
|
|
215
|
+
default="WARNING",
|
|
216
|
+
description="Logging level for Dask.",
|
|
217
|
+
)
|
|
218
|
+
step_adaptor: StepAdaptorConfig = StepAdaptorConfig()
|
|
219
|
+
|
|
220
|
+
workflow: typing.Annotated[EndpointBase, Field(description="Endpoint for the default workflow.")] = EndpointBase(
|
|
221
|
+
method="POST",
|
|
222
|
+
path="/generate",
|
|
223
|
+
websocket_path="/websocket",
|
|
224
|
+
openai_api_path="/chat",
|
|
225
|
+
openai_api_v1_path="/v1/chat/completions",
|
|
226
|
+
description="Executes the default NAT workflow from the loaded configuration ",
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
evaluate: typing.Annotated[EndpointBase, Field(description="Endpoint for evaluating workflows.")] = EndpointBase(
|
|
230
|
+
method="POST",
|
|
231
|
+
path="/evaluate",
|
|
232
|
+
description="Evaluates the performance and accuracy of the workflow on a dataset",
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
oauth2_callback_path: str | None = Field(
|
|
236
|
+
default="/auth/redirect",
|
|
237
|
+
description="OAuth2.0 authentication callback endpoint. If None, no OAuth2 callback endpoint is created.")
|
|
238
|
+
|
|
239
|
+
endpoints: list[Endpoint] = Field(
|
|
240
|
+
default_factory=list,
|
|
241
|
+
description=("Additional endpoints to add to the FastAPI app which run functions within the NAT configuration. "
|
|
242
|
+
"Each endpoint must have a unique path."))
|
|
243
|
+
|
|
244
|
+
cors: CrossOriginResourceSharing = Field(
|
|
245
|
+
default_factory=CrossOriginResourceSharing,
|
|
246
|
+
description="Cross origin resource sharing configuration for the FastAPI app")
|
|
247
|
+
|
|
248
|
+
use_gunicorn: bool = Field(
|
|
249
|
+
default=False,
|
|
250
|
+
description="Use Gunicorn to run the FastAPI app",
|
|
251
|
+
)
|
|
252
|
+
runner_class: str | None = Field(
|
|
253
|
+
default=None,
|
|
254
|
+
description=("The NAT runner class to use when launching the FastAPI app from multiple processes. "
|
|
255
|
+
"Each runner is responsible for loading and running the NAT workflow. "
|
|
256
|
+
"Note: This is different from the worker class used by Gunicorn."),
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
object_store: ObjectStoreRef | None = Field(
|
|
260
|
+
default=None,
|
|
261
|
+
description=(
|
|
262
|
+
"Object store reference for the FastAPI app. If present, static files can be uploaded via a POST "
|
|
263
|
+
"request to '/static' and files will be served from the object store. The files will be served from the "
|
|
264
|
+
"object store at '/static/{file_name}'."))
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# Compatibility aliases with previous releases
|
|
268
|
+
AIQEvaluateRequest = EvaluateRequest
|
|
269
|
+
AIQEvaluateResponse = EvaluateResponse
|
|
270
|
+
AIQAsyncGenerateResponse = AsyncGenerateResponse
|
|
271
|
+
AIQEvaluateStatusResponse = EvaluateStatusResponse
|
|
272
|
+
AIQAsyncGenerationStatusResponse = AsyncGenerationStatusResponse
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
import logging
|
|
18
|
+
|
|
19
|
+
from fastapi import FastAPI
|
|
20
|
+
from uvicorn import Config
|
|
21
|
+
from uvicorn import Server
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class _FastApiFrontEndController:
|
|
27
|
+
"""
|
|
28
|
+
_FastApiFrontEndController class controls the spawing and tear down of the API server in environments where
|
|
29
|
+
the server is needed and not already running.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, app: FastAPI):
|
|
33
|
+
self._app: FastAPI = app
|
|
34
|
+
self._server: Server | None = None
|
|
35
|
+
self._server_background_task: asyncio.Task | None = None
|
|
36
|
+
|
|
37
|
+
async def start_server(self, host: str, port: int) -> None:
|
|
38
|
+
"""Starts the API server."""
|
|
39
|
+
|
|
40
|
+
server_host = host
|
|
41
|
+
server_port = port
|
|
42
|
+
|
|
43
|
+
config = Config(app=self._app, host=server_host, port=server_port, log_level="warning")
|
|
44
|
+
self._server = Server(config=config)
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
self._server_background_task = asyncio.create_task(self._server.serve())
|
|
48
|
+
except asyncio.CancelledError as e:
|
|
49
|
+
error_message = f"Task error occurred while starting API server: {str(e)}"
|
|
50
|
+
logger.error(error_message)
|
|
51
|
+
raise RuntimeError(error_message) from e
|
|
52
|
+
except Exception as e:
|
|
53
|
+
error_message = f"Unexpected error occurred while starting API server: {str(e)}"
|
|
54
|
+
logger.exception(error_message)
|
|
55
|
+
raise RuntimeError(error_message) from e
|
|
56
|
+
|
|
57
|
+
async def stop_server(self) -> None:
|
|
58
|
+
"""Stops the API server."""
|
|
59
|
+
if not self._server or not self._server_background_task:
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
self._server.should_exit = True
|
|
64
|
+
await self._server_background_task
|
|
65
|
+
except asyncio.CancelledError as e:
|
|
66
|
+
logger.exception("Server shutdown failed: %s", str(e))
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.exception("Unexpected error occurred: %s", str(e))
|