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
aiq/__init__.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import importlib
|
|
17
|
+
import importlib.abc
|
|
18
|
+
import importlib.util
|
|
19
|
+
import sys
|
|
20
|
+
import warnings
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CompatFinder(importlib.abc.MetaPathFinder):
|
|
24
|
+
|
|
25
|
+
def __init__(self, alias_prefix, target_prefix):
|
|
26
|
+
self.alias_prefix = alias_prefix
|
|
27
|
+
self.target_prefix = target_prefix
|
|
28
|
+
|
|
29
|
+
def find_spec(self, fullname, path, target=None):
|
|
30
|
+
if fullname == self.alias_prefix or fullname.startswith(self.alias_prefix + "."):
|
|
31
|
+
# Map aiq.something -> nat.something
|
|
32
|
+
target_name = self.target_prefix + fullname[len(self.alias_prefix):]
|
|
33
|
+
spec = importlib.util.find_spec(target_name)
|
|
34
|
+
if spec is None:
|
|
35
|
+
return None
|
|
36
|
+
# Wrap the loader so it loads under the alias name
|
|
37
|
+
return importlib.util.spec_from_loader(fullname, CompatLoader(fullname, target_name))
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class CompatLoader(importlib.abc.Loader):
|
|
42
|
+
|
|
43
|
+
def __init__(self, alias_name, target_name):
|
|
44
|
+
self.alias_name = alias_name
|
|
45
|
+
self.target_name = target_name
|
|
46
|
+
|
|
47
|
+
def create_module(self, spec):
|
|
48
|
+
# Reuse the actual module so there's only one instance
|
|
49
|
+
target_module = importlib.import_module(self.target_name)
|
|
50
|
+
sys.modules[self.alias_name] = target_module
|
|
51
|
+
return target_module
|
|
52
|
+
|
|
53
|
+
def exec_module(self, module):
|
|
54
|
+
# Nothing to execute since the target is already loaded
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Register the compatibility finder
|
|
59
|
+
sys.meta_path.insert(0, CompatFinder("aiq", "nat"))
|
|
60
|
+
|
|
61
|
+
warnings.warn(
|
|
62
|
+
"!!! The 'aiq' namespace is deprecated and will be removed in a future release. "
|
|
63
|
+
"Please use the 'nat' namespace instead.",
|
|
64
|
+
DeprecationWarning,
|
|
65
|
+
stacklevel=2,
|
|
66
|
+
)
|
nat/agent/__init__.py
ADDED
|
File without changes
|
nat/agent/base.py
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
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 json
|
|
18
|
+
import logging
|
|
19
|
+
from abc import ABC
|
|
20
|
+
from abc import abstractmethod
|
|
21
|
+
from enum import Enum
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
from colorama import Fore
|
|
25
|
+
from langchain_core.callbacks import AsyncCallbackHandler
|
|
26
|
+
from langchain_core.language_models import BaseChatModel
|
|
27
|
+
from langchain_core.messages import AIMessage
|
|
28
|
+
from langchain_core.messages import BaseMessage
|
|
29
|
+
from langchain_core.messages import ToolMessage
|
|
30
|
+
from langchain_core.runnables import Runnable
|
|
31
|
+
from langchain_core.runnables import RunnableConfig
|
|
32
|
+
from langchain_core.tools import BaseTool
|
|
33
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
34
|
+
|
|
35
|
+
logger = logging.getLogger(__name__)
|
|
36
|
+
|
|
37
|
+
TOOL_NOT_FOUND_ERROR_MESSAGE = "There is no tool named {tool_name}. Tool must be one of {tools}."
|
|
38
|
+
INPUT_SCHEMA_MESSAGE = ". Arguments must be provided as a valid JSON object following this format: {schema}"
|
|
39
|
+
NO_INPUT_ERROR_MESSAGE = "No human input received to the agent, Please ask a valid question."
|
|
40
|
+
|
|
41
|
+
AGENT_LOG_PREFIX = "[AGENT]"
|
|
42
|
+
AGENT_CALL_LOG_MESSAGE = f"\n{'-' * 30}\n" + \
|
|
43
|
+
AGENT_LOG_PREFIX + "\n" + \
|
|
44
|
+
Fore.YELLOW + \
|
|
45
|
+
"Agent input: %s\n" + \
|
|
46
|
+
Fore.CYAN + \
|
|
47
|
+
"Agent's thoughts: \n%s" + \
|
|
48
|
+
Fore.RESET + \
|
|
49
|
+
f"\n{'-' * 30}"
|
|
50
|
+
|
|
51
|
+
TOOL_CALL_LOG_MESSAGE = f"\n{'-' * 30}\n" + \
|
|
52
|
+
AGENT_LOG_PREFIX + "\n" + \
|
|
53
|
+
Fore.WHITE + \
|
|
54
|
+
"Calling tools: %s\n" + \
|
|
55
|
+
Fore.YELLOW + \
|
|
56
|
+
"Tool's input: %s\n" + \
|
|
57
|
+
Fore.CYAN + \
|
|
58
|
+
"Tool's response: \n%s" + \
|
|
59
|
+
Fore.RESET + \
|
|
60
|
+
f"\n{'-' * 30}"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class AgentDecision(Enum):
|
|
64
|
+
TOOL = "tool"
|
|
65
|
+
END = "finished"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class BaseAgent(ABC):
|
|
69
|
+
|
|
70
|
+
def __init__(self,
|
|
71
|
+
llm: BaseChatModel,
|
|
72
|
+
tools: list[BaseTool],
|
|
73
|
+
callbacks: list[AsyncCallbackHandler] | None = None,
|
|
74
|
+
detailed_logs: bool = False,
|
|
75
|
+
log_response_max_chars: int = 1000) -> None:
|
|
76
|
+
logger.debug("Initializing Agent Graph")
|
|
77
|
+
self.llm = llm
|
|
78
|
+
self.tools = tools
|
|
79
|
+
self.callbacks = callbacks or []
|
|
80
|
+
self.detailed_logs = detailed_logs
|
|
81
|
+
self.log_response_max_chars = log_response_max_chars
|
|
82
|
+
self.graph = None
|
|
83
|
+
|
|
84
|
+
async def _stream_llm(self,
|
|
85
|
+
runnable: Any,
|
|
86
|
+
inputs: dict[str, Any],
|
|
87
|
+
config: RunnableConfig | None = None) -> AIMessage:
|
|
88
|
+
"""
|
|
89
|
+
Stream from LLM runnable. Retry logic is handled automatically by the underlying LLM client.
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
runnable : Any
|
|
94
|
+
The LLM runnable (prompt | llm or similar)
|
|
95
|
+
inputs : Dict[str, Any]
|
|
96
|
+
The inputs to pass to the runnable
|
|
97
|
+
config : RunnableConfig | None
|
|
98
|
+
The config to pass to the runnable (should include callbacks)
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
AIMessage
|
|
103
|
+
The LLM response
|
|
104
|
+
"""
|
|
105
|
+
output_message = ""
|
|
106
|
+
async for event in runnable.astream(inputs, config=config):
|
|
107
|
+
output_message += event.content
|
|
108
|
+
|
|
109
|
+
return AIMessage(content=output_message)
|
|
110
|
+
|
|
111
|
+
async def _call_llm(self, llm: Runnable, inputs: dict[str, Any], config: RunnableConfig | None = None) -> AIMessage:
|
|
112
|
+
"""
|
|
113
|
+
Call the LLM directly. Retry logic is handled automatically by the underlying LLM client.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
llm : Runnable
|
|
118
|
+
The LLM runnable (prompt | llm or similar)
|
|
119
|
+
inputs : dict[str, Any]
|
|
120
|
+
The inputs to pass to the runnable
|
|
121
|
+
config : RunnableConfig | None
|
|
122
|
+
The config to pass to the runnable (should include callbacks)
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
AIMessage
|
|
127
|
+
The LLM response
|
|
128
|
+
"""
|
|
129
|
+
response = await llm.ainvoke(inputs, config=config)
|
|
130
|
+
return AIMessage(content=str(response.content))
|
|
131
|
+
|
|
132
|
+
async def _call_tool(self,
|
|
133
|
+
tool: BaseTool,
|
|
134
|
+
tool_input: dict[str, Any] | str,
|
|
135
|
+
config: RunnableConfig | None = None,
|
|
136
|
+
max_retries: int = 3) -> ToolMessage:
|
|
137
|
+
"""
|
|
138
|
+
Call a tool with retry logic and error handling.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
tool : BaseTool
|
|
143
|
+
The tool to call
|
|
144
|
+
tool_input : Union[Dict[str, Any], str]
|
|
145
|
+
The input to pass to the tool
|
|
146
|
+
config : RunnableConfig | None
|
|
147
|
+
The config to pass to the tool
|
|
148
|
+
max_retries : int
|
|
149
|
+
Maximum number of retry attempts (default: 3)
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
ToolMessage
|
|
154
|
+
The tool response
|
|
155
|
+
"""
|
|
156
|
+
last_exception = None
|
|
157
|
+
|
|
158
|
+
for attempt in range(1, max_retries + 1):
|
|
159
|
+
try:
|
|
160
|
+
response = await tool.ainvoke(tool_input, config=config)
|
|
161
|
+
|
|
162
|
+
# Handle empty responses
|
|
163
|
+
if response is None or (isinstance(response, str) and response == ""):
|
|
164
|
+
return ToolMessage(name=tool.name,
|
|
165
|
+
tool_call_id=tool.name,
|
|
166
|
+
content=f"The tool {tool.name} provided an empty response.")
|
|
167
|
+
|
|
168
|
+
# ToolMessage only accepts str or list[str | dict] as content.
|
|
169
|
+
# Convert into list if the response is a dict.
|
|
170
|
+
if isinstance(response, dict):
|
|
171
|
+
response = [response]
|
|
172
|
+
|
|
173
|
+
return ToolMessage(name=tool.name, tool_call_id=tool.name, content=response)
|
|
174
|
+
|
|
175
|
+
except Exception as e:
|
|
176
|
+
last_exception = e
|
|
177
|
+
|
|
178
|
+
# If this was the last attempt, don't sleep
|
|
179
|
+
if attempt == max_retries:
|
|
180
|
+
break
|
|
181
|
+
|
|
182
|
+
logger.warning("%s Tool call attempt %d/%d failed for tool %s: %s",
|
|
183
|
+
AGENT_LOG_PREFIX,
|
|
184
|
+
attempt,
|
|
185
|
+
max_retries,
|
|
186
|
+
tool.name,
|
|
187
|
+
str(e))
|
|
188
|
+
|
|
189
|
+
# Exponential backoff: 2^attempt seconds
|
|
190
|
+
sleep_time = 2**attempt
|
|
191
|
+
logger.debug("%s Retrying tool call for %s in %d seconds...", AGENT_LOG_PREFIX, tool.name, sleep_time)
|
|
192
|
+
await asyncio.sleep(sleep_time)
|
|
193
|
+
|
|
194
|
+
# All retries exhausted, return error message
|
|
195
|
+
error_content = f"Tool call failed after all retry attempts. Last error: {str(last_exception)}"
|
|
196
|
+
logger.error("%s %s", AGENT_LOG_PREFIX, error_content, exc_info=True)
|
|
197
|
+
return ToolMessage(name=tool.name, tool_call_id=tool.name, content=error_content, status="error")
|
|
198
|
+
|
|
199
|
+
def _log_tool_response(self, tool_name: str, tool_input: Any, tool_response: str) -> None:
|
|
200
|
+
"""
|
|
201
|
+
Log tool response with consistent formatting and length limits.
|
|
202
|
+
|
|
203
|
+
Parameters
|
|
204
|
+
----------
|
|
205
|
+
tool_name : str
|
|
206
|
+
The name of the tool that was called
|
|
207
|
+
tool_input : Any
|
|
208
|
+
The input that was passed to the tool
|
|
209
|
+
tool_response : str
|
|
210
|
+
The response from the tool
|
|
211
|
+
"""
|
|
212
|
+
if self.detailed_logs:
|
|
213
|
+
# Truncate tool response if too long
|
|
214
|
+
display_response = tool_response[:self.log_response_max_chars] + "...(rest of response truncated)" if len(
|
|
215
|
+
tool_response) > self.log_response_max_chars else tool_response
|
|
216
|
+
|
|
217
|
+
# Format the tool input for display
|
|
218
|
+
tool_input_str = str(tool_input)
|
|
219
|
+
|
|
220
|
+
tool_response_log_message = TOOL_CALL_LOG_MESSAGE % (tool_name, tool_input_str, display_response)
|
|
221
|
+
logger.info(tool_response_log_message)
|
|
222
|
+
|
|
223
|
+
def _parse_json(self, json_string: str) -> dict[str, Any]:
|
|
224
|
+
"""
|
|
225
|
+
Safely parse JSON with graceful error handling.
|
|
226
|
+
If JSON parsing fails, returns an empty dict or error info.
|
|
227
|
+
|
|
228
|
+
Parameters
|
|
229
|
+
----------
|
|
230
|
+
json_string : str
|
|
231
|
+
The JSON string to parse
|
|
232
|
+
|
|
233
|
+
Returns
|
|
234
|
+
-------
|
|
235
|
+
Dict[str, Any]
|
|
236
|
+
The parsed JSON or error information
|
|
237
|
+
"""
|
|
238
|
+
try:
|
|
239
|
+
return json.loads(json_string)
|
|
240
|
+
except json.JSONDecodeError as e:
|
|
241
|
+
logger.warning("%s JSON parsing failed, returning the original string: %s", AGENT_LOG_PREFIX, str(e))
|
|
242
|
+
return {"error": f"JSON parsing failed: {str(e)}", "original_string": json_string}
|
|
243
|
+
except Exception as e:
|
|
244
|
+
logger.warning("%s Unexpected error during JSON parsing: %s", AGENT_LOG_PREFIX, str(e))
|
|
245
|
+
return {"error": f"Unexpected parsing error: {str(e)}", "original_string": json_string}
|
|
246
|
+
|
|
247
|
+
def _get_chat_history(self, messages: list[BaseMessage]) -> str:
|
|
248
|
+
"""
|
|
249
|
+
Get the chat history excluding the last message.
|
|
250
|
+
|
|
251
|
+
Parameters
|
|
252
|
+
----------
|
|
253
|
+
messages : list[BaseMessage]
|
|
254
|
+
The messages to get the chat history from
|
|
255
|
+
|
|
256
|
+
Returns
|
|
257
|
+
-------
|
|
258
|
+
str
|
|
259
|
+
The chat history excluding the last message
|
|
260
|
+
"""
|
|
261
|
+
return "\n".join([f"{message.type}: {message.content}" for message in messages[:-1]])
|
|
262
|
+
|
|
263
|
+
@abstractmethod
|
|
264
|
+
async def _build_graph(self, state_schema: type) -> CompiledStateGraph:
|
|
265
|
+
pass
|
nat/agent/dual_node.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from abc import abstractmethod
|
|
18
|
+
|
|
19
|
+
from langchain_core.callbacks import AsyncCallbackHandler
|
|
20
|
+
from langchain_core.language_models import BaseChatModel
|
|
21
|
+
from langchain_core.tools import BaseTool
|
|
22
|
+
from langgraph.graph import StateGraph
|
|
23
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
24
|
+
from pydantic import BaseModel
|
|
25
|
+
|
|
26
|
+
from .base import AgentDecision
|
|
27
|
+
from .base import BaseAgent
|
|
28
|
+
|
|
29
|
+
log = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DualNodeAgent(BaseAgent):
|
|
33
|
+
|
|
34
|
+
def __init__(self,
|
|
35
|
+
llm: BaseChatModel,
|
|
36
|
+
tools: list[BaseTool],
|
|
37
|
+
callbacks: list[AsyncCallbackHandler] | None = None,
|
|
38
|
+
detailed_logs: bool = False,
|
|
39
|
+
log_response_max_chars: int = 1000):
|
|
40
|
+
super().__init__(llm=llm,
|
|
41
|
+
tools=tools,
|
|
42
|
+
callbacks=callbacks,
|
|
43
|
+
detailed_logs=detailed_logs,
|
|
44
|
+
log_response_max_chars=log_response_max_chars)
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
async def agent_node(self, state: BaseModel) -> BaseModel:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
@abstractmethod
|
|
51
|
+
async def tool_node(self, state: BaseModel) -> BaseModel:
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
async def conditional_edge(self, state: BaseModel) -> str:
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
async def _build_graph(self, state_schema: type) -> CompiledStateGraph:
|
|
59
|
+
log.debug("Building and compiling the Agent Graph")
|
|
60
|
+
|
|
61
|
+
graph = StateGraph(state_schema)
|
|
62
|
+
graph.add_node("agent", self.agent_node)
|
|
63
|
+
graph.add_node("tool", self.tool_node)
|
|
64
|
+
graph.add_edge("tool", "agent")
|
|
65
|
+
|
|
66
|
+
conditional_edge_possible_outputs = {AgentDecision.TOOL: "tool", AgentDecision.END: "__end__"}
|
|
67
|
+
graph.add_conditional_edges("agent", self.conditional_edge, conditional_edge_possible_outputs)
|
|
68
|
+
|
|
69
|
+
graph.set_entry_point("agent")
|
|
70
|
+
self.graph = graph.compile()
|
|
71
|
+
|
|
72
|
+
return self.graph
|
|
File without changes
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
# flake8: noqa W291
|
|
16
|
+
|
|
17
|
+
mutator_prompt = """
|
|
18
|
+
|
|
19
|
+
## CORE DIRECTIVES
|
|
20
|
+
- **Preserve the original objective and task.** Do not change what the prompt is meant to accomplish.
|
|
21
|
+
- **Keep the intent intact.** The improved prompt must solve the same problem as the original.
|
|
22
|
+
- **Do not invent new goals.** Only improve clarity, structure, constraints, and usability.
|
|
23
|
+
- **Do not drop critical instructions.** Everything essential from the original prompt must remain.
|
|
24
|
+
- **Return only the mutated prompt text.** No rationale, no diffs, no explanations.
|
|
25
|
+
- **Be Creative within bounds.** You may rephrase, reorganize, and enhance, but not alter meaning.
|
|
26
|
+
- **DO NOT use curly braces in your prompt** for anything other than existing variables in the prompt as the string
|
|
27
|
+
will be treated as an f-string.
|
|
28
|
+
- **Examples are a good idea** if the original prompt lacks them. They help clarify expected output.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## IMPROVEMENT HINTS
|
|
33
|
+
When modifying, apply these principles:
|
|
34
|
+
1. **Clarity & Precision** – remove vague language, strengthen directives.
|
|
35
|
+
2. **Structure & Flow** – order sections as: *Objective → Constraints → Tools → Steps → Output Schema → Examples*.
|
|
36
|
+
3. **Schema Adherence** – enforce a single canonical output schema (JSON/XML) with `schema_version`.
|
|
37
|
+
4. **Tool Governance** – clarify when/how tools are used, their inputs/outputs, and fallback behavior.
|
|
38
|
+
5. **Error Handling** – specify behavior if tools fail or inputs are insufficient.
|
|
39
|
+
6. **Budget Awareness** – minimize verbosity, respect token/latency limits.
|
|
40
|
+
7. **Safety** – include refusals for unsafe requests, enforce compliance with rules.
|
|
41
|
+
8. **Consistency** – avoid format drift; always maintain the same schema.
|
|
42
|
+
9. **Integrity** – confirm the task, objective, and intent are preserved.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## MUTATION OPERATORS
|
|
47
|
+
You may:
|
|
48
|
+
- **Tighten** (remove fluff, redundancies)
|
|
49
|
+
- **Reorder** (improve logical flow)
|
|
50
|
+
- **Constrain** (add explicit rules/limits)
|
|
51
|
+
- **Harden** (improve error handling/fallbacks)
|
|
52
|
+
- **Defuse** (replace ambiguous verbs with measurable actions)
|
|
53
|
+
- **Format-lock** (wrap outputs in JSON/XML fenced blocks)
|
|
54
|
+
- **Example-ify** (add examples if missing or weak)
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## INPUT
|
|
59
|
+
Here is the prompt to mutate:
|
|
60
|
+
{original_prompt}
|
|
61
|
+
|
|
62
|
+
## OBJECTIVE
|
|
63
|
+
The prompt must acheive the following objective:
|
|
64
|
+
{objective}
|
|
65
|
+
|
|
66
|
+
The modified prompt is: \n
|
|
67
|
+
|
|
68
|
+
"""
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2021-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 pydantic import Field
|
|
17
|
+
|
|
18
|
+
from nat.builder.builder import Builder
|
|
19
|
+
from nat.builder.framework_enum import LLMFrameworkEnum
|
|
20
|
+
from nat.builder.function_info import FunctionInfo
|
|
21
|
+
from nat.cli.register_workflow import register_function
|
|
22
|
+
from nat.data_models.component_ref import LLMRef
|
|
23
|
+
from nat.data_models.function import FunctionBaseConfig
|
|
24
|
+
from nat.profiler.parameter_optimization.prompt_optimizer import PromptOptimizerInputSchema
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PromptOptimizerConfig(FunctionBaseConfig, name="prompt_init"):
|
|
28
|
+
|
|
29
|
+
optimizer_llm: LLMRef = Field(description="LLM to use for prompt optimization")
|
|
30
|
+
optimizer_prompt: str = Field(
|
|
31
|
+
description="Prompt template for the optimizer",
|
|
32
|
+
default=(
|
|
33
|
+
"You are an expert at optimizing prompts for LLMs. "
|
|
34
|
+
"Your task is to take a given prompt and suggest an optimized version of it. "
|
|
35
|
+
"Note that the prompt might be a template with variables and curly braces. Remember to always keep the "
|
|
36
|
+
"variables and curly braces in the prompt the same. Only modify the instructions in the prompt that are"
|
|
37
|
+
"not variables. The system is meant to achieve the following objective\n"
|
|
38
|
+
"{system_objective}\n Of which, the prompt is one part. The details of the prompt and context as below.\n"))
|
|
39
|
+
system_objective: str = Field(description="Objective of the workflow")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@register_function(config_type=PromptOptimizerConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN])
|
|
43
|
+
async def prompt_optimizer_function(config: PromptOptimizerConfig, builder: Builder):
|
|
44
|
+
"""
|
|
45
|
+
Function to optimize prompts for LLMs.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
from langchain_core.prompts import PromptTemplate
|
|
50
|
+
|
|
51
|
+
from .prompt import mutator_prompt
|
|
52
|
+
except ImportError as exc:
|
|
53
|
+
raise ImportError("langchain-core is not installed. Please install it to use MultiLLMPlanner.\n"
|
|
54
|
+
"This error can be resolve by installing \"nvidia-nat[langchain]\".") from exc
|
|
55
|
+
|
|
56
|
+
llm = await builder.get_llm(config.optimizer_llm, wrapper_type=LLMFrameworkEnum.LANGCHAIN)
|
|
57
|
+
|
|
58
|
+
template = PromptTemplate(template=config.optimizer_prompt,
|
|
59
|
+
input_variables=["system_objective"],
|
|
60
|
+
validate_template=True)
|
|
61
|
+
|
|
62
|
+
base_prompt: str = (await template.ainvoke(input={"system_objective": config.system_objective})).to_string()
|
|
63
|
+
prompt_extension_template = PromptTemplate(template=mutator_prompt,
|
|
64
|
+
input_variables=["original_prompt", "objective"],
|
|
65
|
+
validate_template=True)
|
|
66
|
+
|
|
67
|
+
async def _inner(input_message: PromptOptimizerInputSchema) -> str:
|
|
68
|
+
"""
|
|
69
|
+
Optimize the prompt using the provided LLM.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
original_prompt = input_message.original_prompt
|
|
73
|
+
prompt_objective = input_message.objective
|
|
74
|
+
|
|
75
|
+
prompt_extension = (await prompt_extension_template.ainvoke(input={
|
|
76
|
+
"original_prompt": original_prompt,
|
|
77
|
+
"objective": prompt_objective,
|
|
78
|
+
})).to_string()
|
|
79
|
+
|
|
80
|
+
prompt = f"{base_prompt}\n\n{prompt_extension}"
|
|
81
|
+
|
|
82
|
+
optimized_prompt = await llm.ainvoke(prompt)
|
|
83
|
+
return optimized_prompt.content
|
|
84
|
+
|
|
85
|
+
yield FunctionInfo.from_fn(
|
|
86
|
+
fn=_inner,
|
|
87
|
+
description="Optimize prompts for LLMs using a feedback LLM.",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class PromptRecombinerConfig(FunctionBaseConfig, name="prompt_recombiner"):
|
|
92
|
+
|
|
93
|
+
optimizer_llm: LLMRef = Field(description="LLM to use for prompt recombination")
|
|
94
|
+
optimizer_prompt: str = Field(
|
|
95
|
+
description="Prompt template for the recombiner",
|
|
96
|
+
default=("You are an expert at combining prompt instructions for LLMs. "
|
|
97
|
+
"Your task is to merge two prompts for the same objective into a single, stronger prompt. "
|
|
98
|
+
"Do not introduce new variables or modify existing placeholders."),
|
|
99
|
+
)
|
|
100
|
+
system_objective: str = Field(description="Objective of the workflow")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@register_function(config_type=PromptRecombinerConfig, framework_wrappers=[LLMFrameworkEnum.LANGCHAIN])
|
|
104
|
+
async def prompt_recombiner_function(config: PromptRecombinerConfig, builder: Builder):
|
|
105
|
+
"""
|
|
106
|
+
Function to recombine two parent prompts into a child prompt using the optimizer LLM.
|
|
107
|
+
Uses the same base template and objective instructions.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
from langchain_core.prompts import PromptTemplate
|
|
112
|
+
except ImportError as exc:
|
|
113
|
+
raise ImportError("langchain-core is not installed. Please install it to use MultiLLMPlanner.\n"
|
|
114
|
+
"This error can be resolve by installing \"nvidia-nat[langchain]\".") from exc
|
|
115
|
+
|
|
116
|
+
llm = await builder.get_llm(config.optimizer_llm, wrapper_type=LLMFrameworkEnum.LANGCHAIN)
|
|
117
|
+
|
|
118
|
+
template = PromptTemplate(template=config.optimizer_prompt,
|
|
119
|
+
input_variables=["system_objective"],
|
|
120
|
+
validate_template=True)
|
|
121
|
+
|
|
122
|
+
base_prompt: str = (await template.ainvoke(input={"system_objective": config.system_objective})).to_string()
|
|
123
|
+
|
|
124
|
+
class RecombineSchema(PromptOptimizerInputSchema):
|
|
125
|
+
parent_b: str | None = None
|
|
126
|
+
|
|
127
|
+
async def _inner(input_message: RecombineSchema) -> str:
|
|
128
|
+
parent_a = input_message.original_prompt
|
|
129
|
+
parent_b = input_message.parent_b or ""
|
|
130
|
+
prompt_objective = input_message.objective
|
|
131
|
+
|
|
132
|
+
prompt = (
|
|
133
|
+
f"{base_prompt}\n\n"
|
|
134
|
+
"We are performing genetic recombination between two prompts that satisfy the same objective.\n"
|
|
135
|
+
f"Objective: {prompt_objective}\n\n"
|
|
136
|
+
f"Parent A:\n{parent_a}\n\n"
|
|
137
|
+
f"Parent B:\n{parent_b}\n\n"
|
|
138
|
+
"Combine the strongest instructions and phrasing from both parents to produce a single, coherent child "
|
|
139
|
+
"prompt.\n"
|
|
140
|
+
"Maintain variables and placeholders unchanged.\n"
|
|
141
|
+
"Return only the child prompt text, with no additional commentary.")
|
|
142
|
+
|
|
143
|
+
child_prompt = await llm.ainvoke(prompt)
|
|
144
|
+
return child_prompt.content
|
|
145
|
+
|
|
146
|
+
yield FunctionInfo.from_fn(
|
|
147
|
+
fn=_inner,
|
|
148
|
+
description="Recombine two prompts into a stronger child prompt.",
|
|
149
|
+
)
|
|
File without changes
|