nvidia-nat 1.4.0a20251120__py3-none-any.whl → 1.4.0a20260113__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiq/__init__.py +1 -1
- nat/{front_ends/mcp → agent/auto_memory_wrapper}/__init__.py +1 -1
- nat/agent/auto_memory_wrapper/agent.py +278 -0
- nat/agent/auto_memory_wrapper/register.py +227 -0
- nat/agent/auto_memory_wrapper/state.py +30 -0
- nat/agent/base.py +1 -1
- nat/agent/dual_node.py +1 -1
- nat/agent/prompt_optimizer/prompt.py +1 -1
- nat/agent/prompt_optimizer/register.py +1 -1
- nat/agent/react_agent/agent.py +16 -9
- nat/agent/react_agent/output_parser.py +2 -2
- nat/agent/react_agent/prompt.py +3 -2
- nat/agent/react_agent/register.py +2 -2
- nat/agent/react_agent/register_per_user_agent.py +104 -0
- nat/agent/reasoning_agent/reasoning_agent.py +1 -1
- nat/agent/register.py +3 -1
- nat/agent/responses_api_agent/__init__.py +1 -1
- nat/agent/responses_api_agent/register.py +1 -1
- nat/agent/rewoo_agent/agent.py +9 -4
- nat/agent/rewoo_agent/prompt.py +1 -1
- nat/agent/rewoo_agent/register.py +1 -1
- nat/agent/tool_calling_agent/agent.py +5 -4
- nat/agent/tool_calling_agent/register.py +1 -1
- nat/authentication/__init__.py +1 -1
- nat/authentication/api_key/__init__.py +1 -1
- nat/authentication/api_key/api_key_auth_provider.py +1 -1
- nat/authentication/api_key/api_key_auth_provider_config.py +22 -7
- nat/authentication/api_key/register.py +1 -1
- nat/authentication/credential_validator/__init__.py +1 -1
- nat/authentication/credential_validator/bearer_token_validator.py +1 -1
- nat/authentication/exceptions/__init__.py +1 -1
- nat/authentication/exceptions/api_key_exceptions.py +1 -1
- nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
- nat/authentication/http_basic_auth/register.py +1 -1
- nat/authentication/interfaces.py +1 -1
- nat/authentication/oauth2/__init__.py +1 -1
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +1 -1
- nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +1 -1
- nat/authentication/oauth2/oauth2_resource_server_config.py +1 -1
- nat/authentication/oauth2/register.py +1 -1
- nat/authentication/register.py +1 -1
- nat/builder/builder.py +511 -1
- nat/builder/child_builder.py +385 -0
- nat/builder/component_utils.py +28 -4
- nat/builder/context.py +17 -1
- nat/builder/embedder.py +1 -1
- nat/builder/eval_builder.py +19 -7
- nat/builder/evaluator.py +1 -1
- nat/builder/framework_enum.py +2 -1
- nat/builder/front_end.py +1 -1
- nat/builder/function.py +40 -3
- nat/builder/function_base.py +1 -1
- nat/builder/function_info.py +1 -1
- nat/builder/intermediate_step_manager.py +1 -1
- nat/builder/llm.py +1 -1
- nat/builder/per_user_workflow_builder.py +843 -0
- nat/builder/retriever.py +1 -1
- nat/builder/sync_builder.py +571 -0
- nat/builder/user_interaction_manager.py +1 -1
- nat/builder/workflow.py +1 -1
- nat/builder/workflow_builder.py +536 -424
- nat/cli/__init__.py +1 -1
- nat/cli/cli_utils/config_override.py +1 -1
- nat/cli/cli_utils/validation.py +32 -1
- nat/cli/commands/configure/channel/add.py +1 -1
- nat/cli/commands/configure/channel/channel.py +1 -1
- nat/cli/commands/configure/channel/remove.py +1 -1
- nat/cli/commands/configure/channel/update.py +1 -1
- nat/cli/commands/configure/configure.py +1 -1
- nat/cli/commands/evaluate.py +87 -13
- nat/cli/commands/finetune.py +132 -0
- nat/cli/commands/info/__init__.py +1 -1
- nat/cli/commands/info/info.py +1 -1
- nat/cli/commands/info/list_channels.py +1 -1
- nat/cli/commands/info/list_components.py +1 -1
- nat/cli/commands/object_store/__init__.py +1 -1
- nat/cli/commands/object_store/object_store.py +1 -1
- nat/cli/commands/optimize.py +1 -1
- nat/cli/commands/{mcp → red_teaming}/__init__.py +1 -1
- nat/cli/commands/red_teaming/red_teaming.py +138 -0
- nat/cli/commands/red_teaming/red_teaming_utils.py +73 -0
- nat/cli/commands/registry/__init__.py +1 -1
- nat/cli/commands/registry/publish.py +1 -1
- nat/cli/commands/registry/pull.py +1 -1
- nat/cli/commands/registry/registry.py +1 -1
- nat/cli/commands/registry/remove.py +1 -1
- nat/cli/commands/registry/search.py +1 -1
- nat/cli/commands/sizing/__init__.py +1 -1
- nat/cli/commands/sizing/calc.py +1 -1
- nat/cli/commands/sizing/sizing.py +1 -1
- nat/cli/commands/start.py +1 -1
- nat/cli/commands/uninstall.py +1 -1
- nat/cli/commands/validate.py +1 -1
- nat/cli/commands/workflow/__init__.py +1 -1
- nat/cli/commands/workflow/workflow.py +1 -1
- nat/cli/commands/workflow/workflow_commands.py +3 -2
- nat/cli/entrypoint.py +15 -37
- nat/cli/main.py +2 -2
- nat/cli/plugin_loader.py +69 -0
- nat/cli/register_workflow.py +183 -5
- nat/cli/type_registry.py +169 -3
- nat/control_flow/register.py +1 -1
- nat/control_flow/router_agent/agent.py +1 -1
- nat/control_flow/router_agent/prompt.py +1 -1
- nat/control_flow/router_agent/register.py +1 -1
- nat/control_flow/sequential_executor.py +28 -7
- nat/data_models/__init__.py +1 -1
- nat/data_models/agent.py +1 -1
- nat/data_models/api_server.py +38 -3
- nat/data_models/authentication.py +1 -1
- nat/data_models/common.py +1 -1
- nat/data_models/component.py +7 -1
- nat/data_models/component_ref.py +34 -1
- nat/data_models/config.py +62 -1
- nat/data_models/dataset_handler.py +15 -2
- nat/data_models/discovery_metadata.py +1 -1
- nat/data_models/embedder.py +1 -1
- nat/data_models/evaluate.py +6 -1
- nat/data_models/evaluator.py +1 -1
- nat/data_models/finetuning.py +260 -0
- nat/data_models/front_end.py +1 -1
- nat/data_models/function.py +1 -1
- nat/data_models/function_dependencies.py +1 -1
- nat/data_models/gated_field_mixin.py +1 -1
- nat/data_models/interactive.py +1 -1
- nat/data_models/intermediate_step.py +29 -2
- nat/data_models/invocation_node.py +1 -1
- nat/data_models/llm.py +1 -1
- nat/data_models/logging.py +1 -1
- nat/data_models/memory.py +1 -1
- nat/data_models/middleware.py +3 -1
- nat/data_models/object_store.py +1 -1
- nat/data_models/openai_mcp.py +1 -1
- nat/data_models/optimizable.py +1 -1
- nat/data_models/optimizer.py +1 -1
- nat/data_models/profiler.py +1 -1
- nat/data_models/registry_handler.py +1 -1
- nat/data_models/retriever.py +1 -1
- nat/data_models/retry_mixin.py +1 -1
- nat/data_models/runtime_enum.py +1 -1
- nat/data_models/span.py +1 -1
- nat/data_models/step_adaptor.py +1 -1
- nat/data_models/streaming.py +1 -1
- nat/data_models/swe_bench_model.py +1 -1
- nat/data_models/telemetry_exporter.py +1 -1
- nat/data_models/thinking_mixin.py +1 -1
- nat/data_models/ttc_strategy.py +1 -1
- nat/embedder/azure_openai_embedder.py +1 -1
- nat/embedder/nim_embedder.py +1 -1
- nat/embedder/openai_embedder.py +1 -1
- nat/embedder/register.py +1 -1
- nat/eval/__init__.py +1 -1
- nat/eval/config.py +8 -1
- nat/eval/dataset_handler/dataset_downloader.py +1 -1
- nat/eval/dataset_handler/dataset_filter.py +1 -1
- nat/eval/dataset_handler/dataset_handler.py +4 -2
- nat/eval/evaluate.py +217 -80
- nat/eval/evaluator/__init__.py +1 -1
- nat/eval/evaluator/base_evaluator.py +2 -2
- nat/eval/evaluator/evaluator_model.py +3 -2
- nat/eval/intermediate_step_adapter.py +1 -1
- nat/eval/llm_validator.py +336 -0
- nat/eval/rag_evaluator/evaluate.py +17 -10
- nat/eval/rag_evaluator/register.py +1 -1
- nat/eval/red_teaming_evaluator/__init__.py +14 -0
- nat/eval/red_teaming_evaluator/data_models.py +66 -0
- nat/eval/red_teaming_evaluator/evaluate.py +327 -0
- nat/eval/red_teaming_evaluator/filter_conditions.py +75 -0
- nat/eval/red_teaming_evaluator/register.py +55 -0
- nat/eval/register.py +2 -1
- nat/eval/remote_workflow.py +1 -1
- nat/eval/runners/__init__.py +1 -1
- nat/eval/runners/config.py +1 -1
- nat/eval/runners/multi_eval_runner.py +1 -1
- nat/eval/runners/red_teaming_runner/__init__.py +24 -0
- nat/eval/runners/red_teaming_runner/config.py +282 -0
- nat/eval/runners/red_teaming_runner/report_utils.py +707 -0
- nat/eval/runners/red_teaming_runner/runner.py +867 -0
- nat/eval/runtime_evaluator/__init__.py +1 -1
- nat/eval/runtime_evaluator/evaluate.py +1 -1
- nat/eval/runtime_evaluator/register.py +1 -1
- nat/eval/runtime_event_subscriber.py +1 -1
- nat/eval/swe_bench_evaluator/evaluate.py +1 -1
- nat/eval/swe_bench_evaluator/register.py +1 -1
- nat/eval/trajectory_evaluator/evaluate.py +2 -2
- nat/eval/trajectory_evaluator/register.py +1 -1
- nat/eval/tunable_rag_evaluator/evaluate.py +5 -5
- nat/eval/tunable_rag_evaluator/register.py +1 -1
- nat/eval/usage_stats.py +1 -1
- nat/eval/utils/eval_trace_ctx.py +1 -1
- nat/eval/utils/output_uploader.py +1 -1
- nat/eval/utils/tqdm_position_registry.py +1 -1
- nat/eval/utils/weave_eval.py +1 -1
- nat/experimental/decorators/experimental_warning_decorator.py +1 -1
- nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +1 -1
- nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +1 -1
- nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +1 -1
- nat/experimental/test_time_compute/functions/execute_score_select_function.py +1 -1
- nat/experimental/test_time_compute/functions/multi_llm_judge_function.py +88 -0
- nat/experimental/test_time_compute/functions/plan_select_execute_function.py +1 -1
- nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +1 -1
- nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
- nat/experimental/test_time_compute/models/editor_config.py +1 -1
- nat/experimental/test_time_compute/models/scoring_config.py +1 -1
- nat/experimental/test_time_compute/models/search_config.py +20 -2
- nat/experimental/test_time_compute/models/selection_config.py +33 -2
- nat/experimental/test_time_compute/models/stage_enums.py +1 -1
- nat/experimental/test_time_compute/models/strategy_base.py +1 -1
- nat/experimental/test_time_compute/models/tool_use_config.py +1 -1
- nat/experimental/test_time_compute/models/ttc_item.py +1 -1
- nat/experimental/test_time_compute/register.py +4 -1
- nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +1 -1
- nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +1 -1
- nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +1 -1
- nat/experimental/test_time_compute/search/multi_llm_generation.py +115 -0
- nat/experimental/test_time_compute/search/multi_llm_planner.py +1 -1
- nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +1 -1
- nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +1 -1
- nat/experimental/test_time_compute/selection/best_of_n_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +1 -1
- nat/experimental/test_time_compute/selection/llm_judge_selection.py +127 -0
- nat/experimental/test_time_compute/selection/threshold_selector.py +1 -1
- nat/finetuning/__init__.py +24 -0
- nat/finetuning/finetuning_runtime.py +143 -0
- nat/finetuning/interfaces/__init__.py +24 -0
- nat/finetuning/interfaces/finetuning_runner.py +261 -0
- nat/finetuning/interfaces/trainer_adapter.py +103 -0
- nat/finetuning/interfaces/trajectory_builder.py +115 -0
- nat/finetuning/utils/__init__.py +15 -0
- nat/finetuning/utils/parsers/__init__.py +15 -0
- nat/finetuning/utils/parsers/adk_parser.py +141 -0
- nat/finetuning/utils/parsers/base_parser.py +238 -0
- nat/finetuning/utils/parsers/common.py +91 -0
- nat/finetuning/utils/parsers/langchain_parser.py +267 -0
- nat/finetuning/utils/parsers/llama_index_parser.py +218 -0
- nat/front_ends/__init__.py +1 -1
- nat/front_ends/console/__init__.py +1 -1
- nat/front_ends/console/authentication_flow_handler.py +1 -1
- nat/front_ends/console/console_front_end_config.py +4 -1
- nat/front_ends/console/console_front_end_plugin.py +5 -4
- nat/front_ends/console/register.py +1 -1
- nat/front_ends/cron/__init__.py +1 -1
- nat/front_ends/fastapi/__init__.py +1 -1
- nat/front_ends/fastapi/async_job.py +128 -0
- nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +1 -1
- nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +13 -9
- nat/front_ends/fastapi/dask_client_mixin.py +1 -1
- nat/front_ends/fastapi/fastapi_front_end_config.py +1 -1
- nat/front_ends/fastapi/fastapi_front_end_controller.py +1 -1
- nat/front_ends/fastapi/fastapi_front_end_plugin.py +25 -30
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +195 -60
- nat/front_ends/fastapi/html_snippets/__init__.py +1 -1
- nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +1 -1
- nat/front_ends/fastapi/intermediate_steps_subscriber.py +12 -1
- nat/front_ends/fastapi/job_store.py +23 -11
- nat/front_ends/fastapi/main.py +1 -1
- nat/front_ends/fastapi/message_handler.py +27 -4
- nat/front_ends/fastapi/message_validator.py +54 -2
- nat/front_ends/fastapi/register.py +1 -1
- nat/front_ends/fastapi/response_helpers.py +16 -15
- nat/front_ends/fastapi/step_adaptor.py +1 -1
- nat/front_ends/fastapi/utils.py +1 -1
- nat/front_ends/register.py +1 -2
- nat/front_ends/simple_base/__init__.py +1 -1
- nat/front_ends/simple_base/simple_front_end_plugin_base.py +6 -4
- nat/llm/aws_bedrock_llm.py +1 -1
- nat/llm/azure_openai_llm.py +10 -1
- nat/llm/dynamo_llm.py +363 -0
- nat/llm/huggingface_llm.py +177 -0
- nat/llm/litellm_llm.py +1 -1
- nat/llm/nim_llm.py +1 -1
- nat/llm/openai_llm.py +1 -1
- nat/llm/register.py +3 -1
- nat/llm/utils/__init__.py +1 -1
- nat/llm/utils/env_config_value.py +1 -1
- nat/llm/utils/error.py +1 -1
- nat/llm/utils/thinking.py +1 -1
- nat/memory/__init__.py +1 -1
- nat/memory/interfaces.py +1 -1
- nat/memory/models.py +1 -1
- nat/meta/pypi.md +1 -1
- nat/middleware/__init__.py +5 -5
- nat/middleware/cache/__init__.py +14 -0
- nat/middleware/{cache_middleware.py → cache/cache_middleware.py} +39 -42
- nat/middleware/cache/cache_middleware_config.py +44 -0
- nat/middleware/cache/register.py +33 -0
- nat/middleware/defense/__init__.py +14 -0
- nat/middleware/defense/defense_middleware.py +362 -0
- nat/middleware/defense/defense_middleware_content_guard.py +455 -0
- nat/middleware/defense/defense_middleware_data_models.py +91 -0
- nat/middleware/defense/defense_middleware_output_verifier.py +440 -0
- nat/middleware/defense/defense_middleware_pii.py +356 -0
- nat/middleware/defense/register.py +82 -0
- nat/middleware/dynamic/__init__.py +14 -0
- nat/middleware/dynamic/dynamic_function_middleware.py +962 -0
- nat/middleware/dynamic/dynamic_middleware_config.py +132 -0
- nat/middleware/dynamic/register.py +34 -0
- nat/middleware/function_middleware.py +236 -52
- nat/middleware/logging/__init__.py +14 -0
- nat/middleware/logging/logging_middleware.py +67 -0
- nat/middleware/logging/logging_middleware_config.py +28 -0
- nat/middleware/logging/register.py +33 -0
- nat/middleware/middleware.py +142 -28
- nat/middleware/red_teaming/__init__.py +14 -0
- nat/middleware/red_teaming/red_teaming_middleware.py +344 -0
- nat/middleware/red_teaming/red_teaming_middleware_config.py +112 -0
- nat/middleware/red_teaming/register.py +47 -0
- nat/middleware/register.py +7 -20
- nat/middleware/utils/__init__.py +14 -0
- nat/middleware/utils/workflow_inventory.py +155 -0
- nat/object_store/__init__.py +1 -1
- nat/object_store/in_memory_object_store.py +1 -1
- nat/object_store/interfaces.py +1 -1
- nat/object_store/models.py +1 -1
- nat/object_store/register.py +1 -1
- nat/observability/__init__.py +1 -1
- nat/observability/exporter/__init__.py +1 -1
- nat/observability/exporter/base_exporter.py +1 -1
- nat/observability/exporter/exporter.py +1 -1
- nat/observability/exporter/file_exporter.py +1 -1
- nat/observability/exporter/processing_exporter.py +1 -1
- nat/observability/exporter/raw_exporter.py +1 -1
- nat/observability/exporter/span_exporter.py +7 -1
- nat/observability/exporter_manager.py +1 -1
- nat/observability/mixin/__init__.py +1 -1
- nat/observability/mixin/batch_config_mixin.py +1 -1
- nat/observability/mixin/collector_config_mixin.py +1 -1
- nat/observability/mixin/file_mixin.py +1 -1
- nat/observability/mixin/file_mode.py +1 -1
- nat/observability/mixin/redaction_config_mixin.py +1 -1
- nat/observability/mixin/resource_conflict_mixin.py +1 -1
- nat/observability/mixin/serialize_mixin.py +1 -1
- nat/observability/mixin/tagging_config_mixin.py +1 -1
- nat/observability/mixin/type_introspection_mixin.py +1 -1
- nat/observability/processor/__init__.py +1 -1
- nat/observability/processor/batching_processor.py +1 -1
- nat/observability/processor/callback_processor.py +1 -1
- nat/observability/processor/falsy_batch_filter_processor.py +1 -1
- nat/observability/processor/intermediate_step_serializer.py +1 -1
- nat/observability/processor/processor.py +1 -1
- nat/observability/processor/processor_factory.py +1 -1
- nat/observability/processor/redaction/__init__.py +1 -1
- nat/observability/processor/redaction/contextual_redaction_processor.py +1 -1
- nat/observability/processor/redaction/contextual_span_redaction_processor.py +1 -1
- nat/observability/processor/redaction/redaction_processor.py +1 -1
- nat/observability/processor/redaction/span_header_redaction_processor.py +1 -1
- nat/observability/processor/span_tagging_processor.py +1 -1
- nat/observability/register.py +1 -1
- nat/observability/utils/__init__.py +1 -1
- nat/observability/utils/dict_utils.py +1 -1
- nat/observability/utils/time_utils.py +1 -1
- nat/profiler/calc/__init__.py +1 -1
- nat/profiler/calc/calc_runner.py +3 -3
- nat/profiler/calc/calculations.py +1 -1
- nat/profiler/calc/data_models.py +1 -1
- nat/profiler/calc/plot.py +30 -3
- nat/profiler/callbacks/agno_callback_handler.py +1 -1
- nat/profiler/callbacks/base_callback_class.py +1 -1
- nat/profiler/callbacks/langchain_callback_handler.py +33 -3
- nat/profiler/callbacks/llama_index_callback_handler.py +13 -10
- nat/profiler/callbacks/semantic_kernel_callback_handler.py +1 -1
- nat/profiler/callbacks/token_usage_base_model.py +1 -1
- nat/profiler/data_frame_row.py +1 -1
- nat/profiler/data_models.py +1 -1
- nat/profiler/decorators/framework_wrapper.py +16 -1
- nat/profiler/decorators/function_tracking.py +1 -1
- nat/profiler/forecasting/config.py +1 -1
- nat/profiler/forecasting/model_trainer.py +1 -1
- nat/profiler/forecasting/models/__init__.py +1 -1
- nat/profiler/forecasting/models/forecasting_base_model.py +1 -1
- nat/profiler/forecasting/models/linear_model.py +1 -1
- nat/profiler/forecasting/models/random_forest_regressor.py +1 -1
- nat/profiler/inference_metrics_model.py +1 -1
- nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/data_models.py +1 -1
- nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +1 -1
- nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +1 -1
- nat/profiler/inference_optimization/llm_metrics.py +1 -1
- nat/profiler/inference_optimization/prompt_caching.py +1 -1
- nat/profiler/inference_optimization/token_uniqueness.py +1 -1
- nat/profiler/inference_optimization/workflow_runtimes.py +1 -1
- nat/profiler/intermediate_property_adapter.py +1 -1
- nat/profiler/parameter_optimization/optimizable_utils.py +1 -1
- nat/profiler/parameter_optimization/optimizer_runtime.py +1 -1
- nat/profiler/parameter_optimization/parameter_optimizer.py +1 -1
- nat/profiler/parameter_optimization/parameter_selection.py +1 -1
- nat/profiler/parameter_optimization/pareto_visualizer.py +1 -1
- nat/profiler/parameter_optimization/prompt_optimizer.py +1 -1
- nat/profiler/parameter_optimization/update_helpers.py +1 -1
- nat/profiler/profile_runner.py +1 -1
- nat/profiler/utils.py +1 -1
- nat/registry_handlers/local/local_handler.py +1 -1
- nat/registry_handlers/local/register_local.py +1 -1
- nat/registry_handlers/metadata_factory.py +1 -1
- nat/registry_handlers/package_utils.py +1 -1
- nat/registry_handlers/pypi/pypi_handler.py +1 -1
- nat/registry_handlers/pypi/register_pypi.py +1 -1
- nat/registry_handlers/register.py +1 -1
- nat/registry_handlers/registry_handler_base.py +1 -1
- nat/registry_handlers/rest/register_rest.py +1 -1
- nat/registry_handlers/rest/rest_handler.py +1 -1
- nat/registry_handlers/schemas/headers.py +1 -1
- nat/registry_handlers/schemas/package.py +1 -1
- nat/registry_handlers/schemas/publish.py +1 -1
- nat/registry_handlers/schemas/pull.py +1 -1
- nat/registry_handlers/schemas/remove.py +1 -1
- nat/registry_handlers/schemas/search.py +1 -1
- nat/registry_handlers/schemas/status.py +1 -1
- nat/retriever/interface.py +1 -1
- nat/retriever/milvus/__init__.py +1 -1
- nat/retriever/milvus/register.py +1 -1
- nat/retriever/milvus/retriever.py +1 -1
- nat/retriever/models.py +1 -1
- nat/retriever/nemo_retriever/__init__.py +1 -1
- nat/retriever/nemo_retriever/register.py +1 -1
- nat/retriever/nemo_retriever/retriever.py +5 -5
- nat/retriever/register.py +1 -1
- nat/runtime/__init__.py +1 -1
- nat/runtime/loader.py +10 -3
- nat/runtime/metrics.py +180 -0
- nat/runtime/runner.py +1 -5
- nat/runtime/session.py +451 -32
- nat/runtime/user_metadata.py +1 -1
- nat/settings/global_settings.py +1 -1
- nat/tool/chat_completion.py +1 -1
- nat/tool/code_execution/README.md +1 -1
- nat/tool/code_execution/code_sandbox.py +1 -1
- nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +1 -1
- nat/tool/code_execution/local_sandbox/__init__.py +1 -1
- nat/tool/code_execution/local_sandbox/local_sandbox_server.py +1 -1
- nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +1 -1
- nat/tool/code_execution/register.py +1 -1
- nat/tool/code_execution/utils.py +1 -1
- nat/tool/datetime_tools.py +1 -1
- nat/tool/document_search.py +1 -1
- nat/tool/github_tools.py +1 -1
- nat/tool/memory_tools/add_memory_tool.py +1 -1
- nat/tool/memory_tools/delete_memory_tool.py +1 -1
- nat/tool/memory_tools/get_memory_tool.py +1 -1
- nat/tool/nvidia_rag.py +2 -2
- nat/tool/register.py +1 -1
- nat/tool/retriever.py +1 -1
- nat/tool/server_tools.py +1 -1
- nat/utils/__init__.py +8 -5
- nat/utils/callable_utils.py +1 -1
- nat/utils/data_models/schema_validator.py +1 -1
- nat/utils/debugging_utils.py +1 -1
- nat/utils/decorators.py +1 -1
- nat/utils/dump_distro_mapping.py +1 -1
- nat/utils/exception_handlers/automatic_retries.py +3 -3
- nat/utils/exception_handlers/schemas.py +1 -1
- nat/utils/io/model_processing.py +1 -1
- nat/utils/io/supress_logs.py +33 -0
- nat/utils/io/yaml_tools.py +1 -1
- nat/utils/log_levels.py +1 -1
- nat/utils/log_utils.py +13 -1
- nat/utils/metadata_utils.py +1 -1
- nat/utils/optional_imports.py +1 -1
- nat/utils/producer_consumer_queue.py +1 -1
- nat/utils/reactive/base/observable_base.py +1 -1
- nat/utils/reactive/base/observer_base.py +1 -1
- nat/utils/reactive/base/subject_base.py +1 -1
- nat/utils/reactive/observable.py +1 -1
- nat/utils/reactive/observer.py +1 -1
- nat/utils/reactive/subject.py +1 -1
- nat/utils/reactive/subscription.py +1 -1
- nat/utils/responses_api.py +1 -1
- nat/utils/settings/global_settings.py +1 -1
- nat/utils/string_utils.py +1 -1
- nat/utils/type_converter.py +18 -5
- nat/utils/type_utils.py +1 -1
- nat/utils/url_utils.py +1 -1
- {nvidia_nat-1.4.0a20251120.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/METADATA +39 -14
- nvidia_nat-1.4.0a20260113.dist-info/RECORD +547 -0
- nvidia_nat-1.4.0a20260113.dist-info/entry_points.txt +38 -0
- nat/cli/commands/mcp/mcp.py +0 -986
- nat/front_ends/mcp/introspection_token_verifier.py +0 -73
- nat/front_ends/mcp/mcp_front_end_config.py +0 -109
- nat/front_ends/mcp/mcp_front_end_plugin.py +0 -155
- nat/front_ends/mcp/mcp_front_end_plugin_worker.py +0 -388
- nat/front_ends/mcp/memory_profiler.py +0 -320
- nat/front_ends/mcp/register.py +0 -27
- nat/front_ends/mcp/tool_converter.py +0 -321
- nvidia_nat-1.4.0a20251120.dist-info/RECORD +0 -488
- nvidia_nat-1.4.0a20251120.dist-info/entry_points.txt +0 -23
- {nvidia_nat-1.4.0a20251120.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.4.0a20251120.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
- {nvidia_nat-1.4.0a20251120.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE.md +0 -0
- {nvidia_nat-1.4.0a20251120.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
"""Common utilities shared across all parser implementations."""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def extract_content(data: Any) -> str:
|
|
25
|
+
"""Extract string content from various data formats.
|
|
26
|
+
|
|
27
|
+
This is a shared utility used by all parser implementations.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
data: The data to extract content from. Can be a string, dict, list,
|
|
31
|
+
or object with content/text attributes.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
The extracted content as a string.
|
|
35
|
+
"""
|
|
36
|
+
if isinstance(data, str):
|
|
37
|
+
return data
|
|
38
|
+
elif isinstance(data, dict):
|
|
39
|
+
# Try common content fields
|
|
40
|
+
for key in ["content", "text", "message", "output"]:
|
|
41
|
+
if key in data:
|
|
42
|
+
return str(data[key])
|
|
43
|
+
# Check for blocks format
|
|
44
|
+
if "blocks" in data:
|
|
45
|
+
blocks = data["blocks"]
|
|
46
|
+
if isinstance(blocks, list):
|
|
47
|
+
return ''.join(block.get('text', '') if isinstance(block, dict) else str(block) for block in blocks)
|
|
48
|
+
# Fallback to JSON representation
|
|
49
|
+
return json.dumps(data)
|
|
50
|
+
elif isinstance(data, list):
|
|
51
|
+
# Join list items if they're strings
|
|
52
|
+
if all(isinstance(item, str) for item in data):
|
|
53
|
+
return "\n".join(data)
|
|
54
|
+
# Otherwise convert to JSON
|
|
55
|
+
return json.dumps(data)
|
|
56
|
+
elif hasattr(data, 'content'):
|
|
57
|
+
return str(data.content)
|
|
58
|
+
elif hasattr(data, 'text'):
|
|
59
|
+
return str(data.text)
|
|
60
|
+
else:
|
|
61
|
+
return str(data)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def parse_generic_message(message: IntermediateStep) -> dict:
|
|
65
|
+
"""Parse messages that don't fit standard patterns.
|
|
66
|
+
|
|
67
|
+
This is a shared utility used by all parser implementations for handling
|
|
68
|
+
event types that don't have specialized parsers.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
message: An IntermediateStep object representing a message.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
A dictionary with 'role' and 'content' keys.
|
|
75
|
+
"""
|
|
76
|
+
result = {"role": "user"} # Default to user role
|
|
77
|
+
|
|
78
|
+
# Try to extract content from various fields
|
|
79
|
+
if message.data:
|
|
80
|
+
if message.data.output:
|
|
81
|
+
result["content"] = extract_content(message.data.output)
|
|
82
|
+
elif message.data.input:
|
|
83
|
+
result["content"] = extract_content(message.data.input)
|
|
84
|
+
elif message.data.chunk:
|
|
85
|
+
result["content"] = extract_content(message.data.chunk)
|
|
86
|
+
else:
|
|
87
|
+
result["content"] = ""
|
|
88
|
+
else:
|
|
89
|
+
result["content"] = ""
|
|
90
|
+
|
|
91
|
+
return result
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from langchain_core.messages import AIMessage
|
|
18
|
+
from langchain_core.messages import AIMessageChunk
|
|
19
|
+
from langchain_core.messages import BaseMessage
|
|
20
|
+
from langchain_core.messages import FunctionMessage
|
|
21
|
+
from langchain_core.messages import HumanMessage
|
|
22
|
+
from langchain_core.messages import SystemMessage
|
|
23
|
+
from langchain_core.messages import ToolMessage
|
|
24
|
+
|
|
25
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
26
|
+
from nat.data_models.intermediate_step import IntermediateStepType
|
|
27
|
+
from nat.finetuning.utils.parsers.common import extract_content
|
|
28
|
+
from nat.finetuning.utils.parsers.common import parse_generic_message
|
|
29
|
+
|
|
30
|
+
# Re-export for backwards compatibility and internal use
|
|
31
|
+
_extract_content = extract_content
|
|
32
|
+
_parse_generic_message = parse_generic_message
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def parse_to_openai_message(message: IntermediateStep) -> dict | list[dict]:
|
|
36
|
+
"""
|
|
37
|
+
Convert IntermediateStep to OpenAI-compatible message dictionary.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
message: An IntermediateStep object representing a single message.
|
|
41
|
+
previous_message: Previous message for context (reserved for future).
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
A dictionary formatted for OpenAI API consumption.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
# Handle different event types to determine role and extract content
|
|
48
|
+
if message.event_type == IntermediateStepType.LLM_END:
|
|
49
|
+
# Assistant message with potential tool calls
|
|
50
|
+
result = _parse_assistant_message(message)
|
|
51
|
+
elif message.event_type == IntermediateStepType.TOOL_END:
|
|
52
|
+
# Tool response message
|
|
53
|
+
result = _parse_tool_message(message)
|
|
54
|
+
elif message.event_type == IntermediateStepType.LLM_START:
|
|
55
|
+
# Extract user/system messages from the input
|
|
56
|
+
result = _parse_input_message(message)
|
|
57
|
+
# drop logprobs field if exists
|
|
58
|
+
if "logprobs" in result:
|
|
59
|
+
del result["logprobs"]
|
|
60
|
+
else:
|
|
61
|
+
# For other types, try to infer from the data
|
|
62
|
+
result = _parse_generic_message(message)
|
|
63
|
+
|
|
64
|
+
return result
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _parse_assistant_message(message: IntermediateStep) -> dict:
|
|
68
|
+
"""Parse an assistant message from LLM_END event."""
|
|
69
|
+
result = {"role": "assistant"}
|
|
70
|
+
# Get the generation from payload if available
|
|
71
|
+
if message.data and message.data.payload:
|
|
72
|
+
payload = message.data.payload
|
|
73
|
+
msg = None
|
|
74
|
+
if isinstance(payload, dict) and "message" in payload:
|
|
75
|
+
# Handle dict payloads
|
|
76
|
+
try:
|
|
77
|
+
msg = AIMessage(**payload["message"])
|
|
78
|
+
except Exception as _:
|
|
79
|
+
try:
|
|
80
|
+
msg = AIMessageChunk(**payload["message"])
|
|
81
|
+
except Exception as _:
|
|
82
|
+
msg = None
|
|
83
|
+
|
|
84
|
+
# Handle ChatGeneration objects from LangChain
|
|
85
|
+
if hasattr(payload, 'message'):
|
|
86
|
+
msg = payload.message
|
|
87
|
+
if msg:
|
|
88
|
+
# Extract content
|
|
89
|
+
if isinstance(msg, AIMessage):
|
|
90
|
+
result["content"] = msg.content or ""
|
|
91
|
+
|
|
92
|
+
# Extract tool calls if present
|
|
93
|
+
if hasattr(msg, 'tool_calls') and msg.tool_calls:
|
|
94
|
+
result["tool_calls"] = msg.tool_calls
|
|
95
|
+
elif 'tool_calls' in msg.additional_kwargs:
|
|
96
|
+
tool_calls = msg.additional_kwargs['tool_calls']
|
|
97
|
+
result["tool_calls"] = tool_calls
|
|
98
|
+
|
|
99
|
+
# Extract function call if present
|
|
100
|
+
if hasattr(msg, 'function_call') and msg.function_call:
|
|
101
|
+
result["function_call"] = msg.function_call
|
|
102
|
+
elif 'function_call' in msg.additional_kwargs:
|
|
103
|
+
func_call = msg.additional_kwargs['function_call']
|
|
104
|
+
result["function_call"] = func_call
|
|
105
|
+
else:
|
|
106
|
+
# Fallback to extracting content as string
|
|
107
|
+
result["content"] = str(getattr(msg, 'content', msg))
|
|
108
|
+
|
|
109
|
+
# Extract logprobs if available
|
|
110
|
+
gen_info = getattr(msg, 'response_metadata', None)
|
|
111
|
+
if gen_info and 'logprobs' in gen_info:
|
|
112
|
+
result["logprobs"] = gen_info['logprobs']
|
|
113
|
+
|
|
114
|
+
elif message.data and message.data.output:
|
|
115
|
+
# Fallback to output field
|
|
116
|
+
result["content"] = _extract_content(message.data.output)
|
|
117
|
+
else:
|
|
118
|
+
result["content"] = ""
|
|
119
|
+
|
|
120
|
+
# Check for logprobs in data field
|
|
121
|
+
logprobs = (getattr(message.data, 'logprobs', None) if message.data else None)
|
|
122
|
+
if logprobs:
|
|
123
|
+
result["logprobs"] = logprobs
|
|
124
|
+
|
|
125
|
+
# if not logprobs, set to empty dict to avoid issues downstream
|
|
126
|
+
if "logprobs" not in result:
|
|
127
|
+
result["logprobs"] = {}
|
|
128
|
+
|
|
129
|
+
return result
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _parse_tool_message(message: IntermediateStep) -> dict:
|
|
133
|
+
"""Parse a tool response message from TOOL_END event."""
|
|
134
|
+
result = {"role": "tool"}
|
|
135
|
+
|
|
136
|
+
# Extract tool output as content
|
|
137
|
+
if message.data:
|
|
138
|
+
if message.data.output:
|
|
139
|
+
result["content"] = _extract_content(message.data.output)
|
|
140
|
+
elif message.data.payload:
|
|
141
|
+
result["content"] = _extract_content(message.data.payload)
|
|
142
|
+
else:
|
|
143
|
+
result["content"] = ""
|
|
144
|
+
else:
|
|
145
|
+
result["content"] = ""
|
|
146
|
+
|
|
147
|
+
# Add tool_call_id if available from metadata or UUID
|
|
148
|
+
if message.metadata and hasattr(message.metadata, 'tool_call_id'):
|
|
149
|
+
result["tool_call_id"] = message.metadata.tool_call_id
|
|
150
|
+
else:
|
|
151
|
+
result["tool_call_id"] = 0
|
|
152
|
+
|
|
153
|
+
return result
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _parse_input_message(message: IntermediateStep) -> dict | list[dict]:
|
|
157
|
+
"""Parse user or system messages from LLM_START event."""
|
|
158
|
+
if not message.data or not message.data.input:
|
|
159
|
+
return {"role": "user", "content": ""}
|
|
160
|
+
|
|
161
|
+
input_data = message.data.input
|
|
162
|
+
|
|
163
|
+
# Handle list of messages
|
|
164
|
+
if isinstance(input_data, list) and len(input_data) > 0:
|
|
165
|
+
# Get the last message in the list
|
|
166
|
+
messages = []
|
|
167
|
+
for msg in input_data:
|
|
168
|
+
last_msg = msg
|
|
169
|
+
# Handle BaseMessage objects
|
|
170
|
+
if isinstance(last_msg, BaseMessage):
|
|
171
|
+
messages.append(_parse_langchain_message(last_msg))
|
|
172
|
+
# Handle dict messages
|
|
173
|
+
elif isinstance(last_msg, dict):
|
|
174
|
+
messages.append(_parse_dict_message(last_msg))
|
|
175
|
+
# Handle string messages
|
|
176
|
+
elif isinstance(last_msg, str):
|
|
177
|
+
messages.append({"role": "user", "content": last_msg})
|
|
178
|
+
else:
|
|
179
|
+
messages.append({"role": "user", "content": str(last_msg)})
|
|
180
|
+
return messages
|
|
181
|
+
# Handle single message
|
|
182
|
+
elif isinstance(input_data, BaseMessage):
|
|
183
|
+
return _parse_langchain_message(input_data)
|
|
184
|
+
elif isinstance(input_data, dict):
|
|
185
|
+
return _parse_dict_message(input_data)
|
|
186
|
+
else:
|
|
187
|
+
return {"role": "user", "content": _extract_content(input_data)}
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _parse_langchain_message(msg: BaseMessage) -> dict:
|
|
191
|
+
"""Parse a LangChain BaseMessage object."""
|
|
192
|
+
result = {}
|
|
193
|
+
|
|
194
|
+
# Determine role based on message type
|
|
195
|
+
if isinstance(msg, HumanMessage):
|
|
196
|
+
result["role"] = "user"
|
|
197
|
+
elif isinstance(msg, AIMessage):
|
|
198
|
+
result["role"] = "assistant"
|
|
199
|
+
elif isinstance(msg, SystemMessage):
|
|
200
|
+
result["role"] = "system"
|
|
201
|
+
elif isinstance(msg, ToolMessage):
|
|
202
|
+
result["role"] = "tool"
|
|
203
|
+
# Add tool_call_id if present
|
|
204
|
+
if hasattr(msg, 'tool_call_id'):
|
|
205
|
+
result["tool_call_id"] = msg.tool_call_id
|
|
206
|
+
elif isinstance(msg, FunctionMessage):
|
|
207
|
+
result["role"] = "function"
|
|
208
|
+
# Add name if present
|
|
209
|
+
if hasattr(msg, 'name'):
|
|
210
|
+
result["name"] = msg.name
|
|
211
|
+
else:
|
|
212
|
+
# Default to user role for unknown message types
|
|
213
|
+
result["role"] = "user"
|
|
214
|
+
|
|
215
|
+
# Extract content
|
|
216
|
+
result["content"] = msg.content or ""
|
|
217
|
+
|
|
218
|
+
# Handle tool calls for AI messages
|
|
219
|
+
if isinstance(msg, AIMessage):
|
|
220
|
+
if hasattr(msg, 'tool_calls') and msg.tool_calls:
|
|
221
|
+
result["tool_calls"] = msg.tool_calls
|
|
222
|
+
elif 'tool_calls' in msg.additional_kwargs:
|
|
223
|
+
result["tool_calls"] = msg.additional_kwargs['tool_calls']
|
|
224
|
+
|
|
225
|
+
if hasattr(msg, 'function_call') and msg.function_call:
|
|
226
|
+
result["function_call"] = msg.function_call
|
|
227
|
+
elif 'function_call' in msg.additional_kwargs:
|
|
228
|
+
result["function_call"] = msg.additional_kwargs['function_call']
|
|
229
|
+
|
|
230
|
+
return result
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _parse_dict_message(msg_dict: dict) -> dict:
|
|
234
|
+
"""Parse a dictionary-based message."""
|
|
235
|
+
result = {}
|
|
236
|
+
|
|
237
|
+
# Extract role
|
|
238
|
+
#result["role"] = msg_dict.get("role", "user")
|
|
239
|
+
if "role" in msg_dict:
|
|
240
|
+
role = msg_dict["role"]
|
|
241
|
+
elif "type" in msg_dict:
|
|
242
|
+
role = msg_dict["type"]
|
|
243
|
+
else:
|
|
244
|
+
role = "user"
|
|
245
|
+
|
|
246
|
+
if role == 'ai':
|
|
247
|
+
role = 'assistant'
|
|
248
|
+
elif role == 'human':
|
|
249
|
+
role = 'user'
|
|
250
|
+
|
|
251
|
+
result["role"] = role
|
|
252
|
+
|
|
253
|
+
# Extract content
|
|
254
|
+
if "content" in msg_dict:
|
|
255
|
+
result["content"] = msg_dict["content"]
|
|
256
|
+
elif "text" in msg_dict:
|
|
257
|
+
result["content"] = msg_dict["text"]
|
|
258
|
+
else:
|
|
259
|
+
result["content"] = ""
|
|
260
|
+
|
|
261
|
+
# Copy over optional fields
|
|
262
|
+
optional_fields = ["tool_calls", "tool_call_id", "function_call", "name", "logprobs"]
|
|
263
|
+
for field in optional_fields:
|
|
264
|
+
if field in msg_dict:
|
|
265
|
+
result[field] = msg_dict[field]
|
|
266
|
+
|
|
267
|
+
return result
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES.
|
|
2
|
+
# All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
from llama_index.core.llms import ChatResponse
|
|
18
|
+
|
|
19
|
+
from nat.data_models.intermediate_step import IntermediateStep
|
|
20
|
+
from nat.data_models.intermediate_step import IntermediateStepType
|
|
21
|
+
from nat.finetuning.utils.parsers.common import extract_content
|
|
22
|
+
from nat.finetuning.utils.parsers.common import parse_generic_message
|
|
23
|
+
|
|
24
|
+
# Re-export for backwards compatibility and internal use
|
|
25
|
+
_extract_content = extract_content
|
|
26
|
+
_parse_generic_message = parse_generic_message
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def parse_to_openai_message(message: IntermediateStep) -> dict: # noqa: ARG001
|
|
30
|
+
"""
|
|
31
|
+
Convert IntermediateStep to OpenAI-compatible message dictionary.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
message: An IntermediateStep object representing a single message.
|
|
35
|
+
previous_message: Previous message for context (reserved for future).
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
A dictionary formatted for OpenAI API consumption.
|
|
39
|
+
"""
|
|
40
|
+
result = {}
|
|
41
|
+
|
|
42
|
+
# Handle different event types to determine role and extract content
|
|
43
|
+
if message.event_type == IntermediateStepType.LLM_END:
|
|
44
|
+
# Assistant message from ChatResponse
|
|
45
|
+
result = _parse_assistant_message(message)
|
|
46
|
+
elif message.event_type == IntermediateStepType.TOOL_END:
|
|
47
|
+
# Tool/Function response message
|
|
48
|
+
result = _parse_tool_message(message)
|
|
49
|
+
elif message.event_type == IntermediateStepType.LLM_START:
|
|
50
|
+
# Extract user/system messages from the input
|
|
51
|
+
result = _parse_input_message(message)
|
|
52
|
+
else:
|
|
53
|
+
# For other types, try to infer from the data
|
|
54
|
+
result = _parse_generic_message(message)
|
|
55
|
+
|
|
56
|
+
return result
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _parse_assistant_message(message: IntermediateStep) -> dict:
|
|
60
|
+
"""Parse an assistant message from LLM_END event."""
|
|
61
|
+
result = {"role": "assistant"}
|
|
62
|
+
|
|
63
|
+
# Get the ChatResponse from payload if available
|
|
64
|
+
if message.data and message.data.payload:
|
|
65
|
+
payload = message.data.payload
|
|
66
|
+
|
|
67
|
+
# Handle ChatResponse objects from LlamaIndex
|
|
68
|
+
if isinstance(payload, ChatResponse):
|
|
69
|
+
# Extract content from message blocks
|
|
70
|
+
content = ""
|
|
71
|
+
msg = getattr(payload, 'message', None)
|
|
72
|
+
if msg and hasattr(msg, 'blocks'):
|
|
73
|
+
try:
|
|
74
|
+
content = ''.join(block.text for block in msg.blocks)
|
|
75
|
+
except (AttributeError, TypeError):
|
|
76
|
+
# Fallback to str representation
|
|
77
|
+
content = str(msg) if msg else ""
|
|
78
|
+
elif msg:
|
|
79
|
+
# Direct message content
|
|
80
|
+
content = str(msg)
|
|
81
|
+
result["content"] = content
|
|
82
|
+
|
|
83
|
+
# Check for tool calls in additional_kwargs
|
|
84
|
+
if (hasattr(payload, 'message') and hasattr(payload.message, 'additional_kwargs')):
|
|
85
|
+
additional_kwargs = payload.message.additional_kwargs
|
|
86
|
+
if 'tool_calls' in additional_kwargs:
|
|
87
|
+
result["tool_calls"] = additional_kwargs['tool_calls']
|
|
88
|
+
if 'function_call' in additional_kwargs:
|
|
89
|
+
func_call = additional_kwargs['function_call']
|
|
90
|
+
result["function_call"] = func_call
|
|
91
|
+
|
|
92
|
+
# Extract logprobs if available
|
|
93
|
+
raw_attr = getattr(payload, 'raw', None)
|
|
94
|
+
try:
|
|
95
|
+
choice = raw_attr.choices[0] if raw_attr and hasattr(raw_attr, 'choices') else None
|
|
96
|
+
if choice and hasattr(choice, 'logprobs') and choice.logprobs:
|
|
97
|
+
result["logprobs"] = choice.logprobs
|
|
98
|
+
except (AttributeError, IndexError):
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
elif message.data and message.data.output:
|
|
102
|
+
# Fallback to output field
|
|
103
|
+
result["content"] = _extract_content(message.data.output)
|
|
104
|
+
else:
|
|
105
|
+
result["content"] = ""
|
|
106
|
+
|
|
107
|
+
# if not logprobs, set to empty dict to avoid issues downstream
|
|
108
|
+
if "logprobs" not in result:
|
|
109
|
+
result["logprobs"] = {}
|
|
110
|
+
|
|
111
|
+
return result
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _parse_tool_message(message: IntermediateStep) -> dict:
|
|
115
|
+
"""Parse a tool/function response message from TOOL_END event."""
|
|
116
|
+
result = {"role": "function"}
|
|
117
|
+
|
|
118
|
+
# Extract function output as content
|
|
119
|
+
if message.data:
|
|
120
|
+
if message.data.output:
|
|
121
|
+
result["content"] = _extract_content(message.data.output)
|
|
122
|
+
elif message.data.payload:
|
|
123
|
+
result["content"] = _extract_content(message.data.payload)
|
|
124
|
+
else:
|
|
125
|
+
result["content"] = ""
|
|
126
|
+
else:
|
|
127
|
+
result["content"] = ""
|
|
128
|
+
|
|
129
|
+
# Add function name if available
|
|
130
|
+
if message.name:
|
|
131
|
+
result["name"] = message.name
|
|
132
|
+
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _parse_input_message(message: IntermediateStep) -> dict:
|
|
137
|
+
"""Parse user or system messages from LLM_START event."""
|
|
138
|
+
if not message.data or not message.data.input:
|
|
139
|
+
return {"role": "user", "content": ""}
|
|
140
|
+
|
|
141
|
+
input_data = message.data.input
|
|
142
|
+
|
|
143
|
+
# LlamaIndex typically stores messages as strings in the input
|
|
144
|
+
if isinstance(input_data, str):
|
|
145
|
+
# Check if it looks like a system message (heuristic)
|
|
146
|
+
lower_input = input_data.lower()
|
|
147
|
+
if (lower_input.startswith("system:") or "system prompt" in lower_input):
|
|
148
|
+
return {"role": "system", "content": input_data}
|
|
149
|
+
else:
|
|
150
|
+
return {"role": "user", "content": input_data}
|
|
151
|
+
|
|
152
|
+
# Handle list of messages (from EventPayload.MESSAGES)
|
|
153
|
+
elif isinstance(input_data, list) and len(input_data) > 0:
|
|
154
|
+
# Get the last message in the list
|
|
155
|
+
last_msg = input_data[-1]
|
|
156
|
+
|
|
157
|
+
# Try to parse the message
|
|
158
|
+
if hasattr(last_msg, 'role') and hasattr(last_msg, 'content'):
|
|
159
|
+
# LlamaIndex ChatMessage object
|
|
160
|
+
role = str(last_msg.role).lower()
|
|
161
|
+
# Map LlamaIndex roles to OpenAI roles
|
|
162
|
+
role_mapping = {
|
|
163
|
+
'user': 'user',
|
|
164
|
+
'assistant': 'assistant',
|
|
165
|
+
'system': 'system',
|
|
166
|
+
'human': 'user',
|
|
167
|
+
'ai': 'assistant',
|
|
168
|
+
'chatbot': 'assistant'
|
|
169
|
+
}
|
|
170
|
+
role = role_mapping.get(role, 'user')
|
|
171
|
+
return {"role": role, "content": str(last_msg.content)}
|
|
172
|
+
else:
|
|
173
|
+
# Convert to string if not a message object
|
|
174
|
+
return {"role": "user", "content": str(last_msg)}
|
|
175
|
+
|
|
176
|
+
# Handle dict messages
|
|
177
|
+
elif isinstance(input_data, dict):
|
|
178
|
+
return _parse_dict_message(input_data)
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
return {"role": "user", "content": _extract_content(input_data)}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _parse_dict_message(msg_dict: dict) -> dict:
|
|
185
|
+
"""Parse a dictionary-based message."""
|
|
186
|
+
result = {}
|
|
187
|
+
|
|
188
|
+
# Extract role
|
|
189
|
+
result["role"] = msg_dict.get("role", "user")
|
|
190
|
+
|
|
191
|
+
# Extract content
|
|
192
|
+
if "content" in msg_dict:
|
|
193
|
+
result["content"] = msg_dict["content"]
|
|
194
|
+
elif "text" in msg_dict:
|
|
195
|
+
result["content"] = msg_dict["text"]
|
|
196
|
+
elif "blocks" in msg_dict:
|
|
197
|
+
# Handle LlamaIndex block format
|
|
198
|
+
blocks = msg_dict["blocks"]
|
|
199
|
+
if isinstance(blocks, list):
|
|
200
|
+
content_parts = []
|
|
201
|
+
for block in blocks:
|
|
202
|
+
if isinstance(block, dict) and "text" in block:
|
|
203
|
+
content_parts.append(block["text"])
|
|
204
|
+
elif hasattr(block, 'text'):
|
|
205
|
+
content_parts.append(block.text)
|
|
206
|
+
result["content"] = ''.join(content_parts)
|
|
207
|
+
else:
|
|
208
|
+
result["content"] = ""
|
|
209
|
+
else:
|
|
210
|
+
result["content"] = ""
|
|
211
|
+
|
|
212
|
+
# Copy over optional fields
|
|
213
|
+
optional_fields = ["tool_calls", "function_call", "name", "logprobs"]
|
|
214
|
+
for field in optional_fields:
|
|
215
|
+
if field in msg_dict:
|
|
216
|
+
result[field] = msg_dict[field]
|
|
217
|
+
|
|
218
|
+
return result
|
nat/front_ends/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -30,3 +30,6 @@ class ConsoleFrontEndConfig(FrontEndBaseConfig, name="console"):
|
|
|
30
30
|
description="A single input to submit the the workflow.")
|
|
31
31
|
input_file: Path | None = Field(default=None,
|
|
32
32
|
description="Path to a json file of inputs to submit to the workflow.")
|
|
33
|
+
user_id: str = Field(default="nat_run_user_id",
|
|
34
|
+
description="User ID to use for the workflow session. "
|
|
35
|
+
"Defaults to 'nat_run_user_id' for single-user CLI execution.")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -70,6 +70,7 @@ class ConsoleFrontEndPlugin(SimpleFrontEndPluginBase[ConsoleFrontEndConfig]):
|
|
|
70
70
|
async def run_single_query(query):
|
|
71
71
|
|
|
72
72
|
async with session_manager.session(
|
|
73
|
+
user_id=self.front_end_config.user_id,
|
|
73
74
|
user_input_callback=prompt_for_input_cli,
|
|
74
75
|
user_authentication_callback=self.auth_flow_handler.authenticate) as session:
|
|
75
76
|
async with session.run(query) as runner:
|
|
@@ -89,9 +90,9 @@ class ConsoleFrontEndPlugin(SimpleFrontEndPluginBase[ConsoleFrontEndConfig]):
|
|
|
89
90
|
|
|
90
91
|
# Run the workflow
|
|
91
92
|
with open(self.front_end_config.input_file, encoding="utf-8") as f:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
async with session_manager.session(user_id=self.front_end_config.user_id) as session:
|
|
94
|
+
async with session.run(f) as runner:
|
|
95
|
+
runner_outputs = await runner.result(to_type=str)
|
|
95
96
|
else:
|
|
96
97
|
assert False, "Should not reach here. Should have been caught by pre_run"
|
|
97
98
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
nat/front_ends/cron/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|