nvidia-nat 1.2.0rc5__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/agent/__init__.py +0 -0
- aiq/agent/base.py +239 -0
- aiq/agent/dual_node.py +67 -0
- aiq/agent/react_agent/__init__.py +0 -0
- aiq/agent/react_agent/agent.py +355 -0
- aiq/agent/react_agent/output_parser.py +104 -0
- aiq/agent/react_agent/prompt.py +41 -0
- aiq/agent/react_agent/register.py +149 -0
- aiq/agent/reasoning_agent/__init__.py +0 -0
- aiq/agent/reasoning_agent/reasoning_agent.py +225 -0
- aiq/agent/register.py +23 -0
- aiq/agent/rewoo_agent/__init__.py +0 -0
- aiq/agent/rewoo_agent/agent.py +411 -0
- aiq/agent/rewoo_agent/prompt.py +108 -0
- aiq/agent/rewoo_agent/register.py +158 -0
- aiq/agent/tool_calling_agent/__init__.py +0 -0
- aiq/agent/tool_calling_agent/agent.py +119 -0
- aiq/agent/tool_calling_agent/register.py +106 -0
- aiq/authentication/__init__.py +14 -0
- aiq/authentication/api_key/__init__.py +14 -0
- aiq/authentication/api_key/api_key_auth_provider.py +96 -0
- aiq/authentication/api_key/api_key_auth_provider_config.py +124 -0
- aiq/authentication/api_key/register.py +26 -0
- aiq/authentication/exceptions/__init__.py +14 -0
- aiq/authentication/exceptions/api_key_exceptions.py +38 -0
- aiq/authentication/http_basic_auth/__init__.py +0 -0
- aiq/authentication/http_basic_auth/http_basic_auth_provider.py +81 -0
- aiq/authentication/http_basic_auth/register.py +30 -0
- aiq/authentication/interfaces.py +93 -0
- aiq/authentication/oauth2/__init__.py +14 -0
- aiq/authentication/oauth2/oauth2_auth_code_flow_provider.py +107 -0
- aiq/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +39 -0
- aiq/authentication/oauth2/register.py +25 -0
- aiq/authentication/register.py +21 -0
- aiq/builder/__init__.py +0 -0
- aiq/builder/builder.py +285 -0
- aiq/builder/component_utils.py +316 -0
- aiq/builder/context.py +264 -0
- aiq/builder/embedder.py +24 -0
- aiq/builder/eval_builder.py +161 -0
- aiq/builder/evaluator.py +29 -0
- aiq/builder/framework_enum.py +24 -0
- aiq/builder/front_end.py +73 -0
- aiq/builder/function.py +344 -0
- aiq/builder/function_base.py +380 -0
- aiq/builder/function_info.py +627 -0
- aiq/builder/intermediate_step_manager.py +174 -0
- aiq/builder/llm.py +25 -0
- aiq/builder/retriever.py +25 -0
- aiq/builder/user_interaction_manager.py +74 -0
- aiq/builder/workflow.py +148 -0
- aiq/builder/workflow_builder.py +1117 -0
- aiq/cli/__init__.py +14 -0
- aiq/cli/cli_utils/__init__.py +0 -0
- aiq/cli/cli_utils/config_override.py +231 -0
- aiq/cli/cli_utils/validation.py +37 -0
- aiq/cli/commands/__init__.py +0 -0
- aiq/cli/commands/configure/__init__.py +0 -0
- aiq/cli/commands/configure/channel/__init__.py +0 -0
- aiq/cli/commands/configure/channel/add.py +28 -0
- aiq/cli/commands/configure/channel/channel.py +36 -0
- aiq/cli/commands/configure/channel/remove.py +30 -0
- aiq/cli/commands/configure/channel/update.py +30 -0
- aiq/cli/commands/configure/configure.py +33 -0
- aiq/cli/commands/evaluate.py +139 -0
- aiq/cli/commands/info/__init__.py +14 -0
- aiq/cli/commands/info/info.py +39 -0
- aiq/cli/commands/info/list_channels.py +32 -0
- aiq/cli/commands/info/list_components.py +129 -0
- aiq/cli/commands/info/list_mcp.py +213 -0
- aiq/cli/commands/registry/__init__.py +14 -0
- aiq/cli/commands/registry/publish.py +88 -0
- aiq/cli/commands/registry/pull.py +118 -0
- aiq/cli/commands/registry/registry.py +38 -0
- aiq/cli/commands/registry/remove.py +108 -0
- aiq/cli/commands/registry/search.py +155 -0
- aiq/cli/commands/sizing/__init__.py +14 -0
- aiq/cli/commands/sizing/calc.py +297 -0
- aiq/cli/commands/sizing/sizing.py +27 -0
- aiq/cli/commands/start.py +246 -0
- aiq/cli/commands/uninstall.py +81 -0
- aiq/cli/commands/validate.py +47 -0
- aiq/cli/commands/workflow/__init__.py +14 -0
- aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
- aiq/cli/commands/workflow/templates/config.yml.j2 +16 -0
- aiq/cli/commands/workflow/templates/pyproject.toml.j2 +22 -0
- aiq/cli/commands/workflow/templates/register.py.j2 +5 -0
- aiq/cli/commands/workflow/templates/workflow.py.j2 +36 -0
- aiq/cli/commands/workflow/workflow.py +37 -0
- aiq/cli/commands/workflow/workflow_commands.py +313 -0
- aiq/cli/entrypoint.py +135 -0
- aiq/cli/main.py +44 -0
- aiq/cli/register_workflow.py +488 -0
- aiq/cli/type_registry.py +1000 -0
- aiq/data_models/__init__.py +14 -0
- aiq/data_models/api_server.py +694 -0
- aiq/data_models/authentication.py +231 -0
- aiq/data_models/common.py +171 -0
- aiq/data_models/component.py +54 -0
- aiq/data_models/component_ref.py +168 -0
- aiq/data_models/config.py +406 -0
- aiq/data_models/dataset_handler.py +123 -0
- aiq/data_models/discovery_metadata.py +335 -0
- aiq/data_models/embedder.py +27 -0
- aiq/data_models/evaluate.py +127 -0
- aiq/data_models/evaluator.py +26 -0
- aiq/data_models/front_end.py +26 -0
- aiq/data_models/function.py +30 -0
- aiq/data_models/function_dependencies.py +72 -0
- aiq/data_models/interactive.py +246 -0
- aiq/data_models/intermediate_step.py +302 -0
- aiq/data_models/invocation_node.py +38 -0
- aiq/data_models/llm.py +27 -0
- aiq/data_models/logging.py +26 -0
- aiq/data_models/memory.py +27 -0
- aiq/data_models/object_store.py +44 -0
- aiq/data_models/profiler.py +54 -0
- aiq/data_models/registry_handler.py +26 -0
- aiq/data_models/retriever.py +30 -0
- aiq/data_models/retry_mixin.py +35 -0
- aiq/data_models/span.py +187 -0
- aiq/data_models/step_adaptor.py +64 -0
- aiq/data_models/streaming.py +33 -0
- aiq/data_models/swe_bench_model.py +54 -0
- aiq/data_models/telemetry_exporter.py +26 -0
- aiq/data_models/ttc_strategy.py +30 -0
- aiq/embedder/__init__.py +0 -0
- aiq/embedder/langchain_client.py +41 -0
- aiq/embedder/nim_embedder.py +59 -0
- aiq/embedder/openai_embedder.py +43 -0
- aiq/embedder/register.py +24 -0
- aiq/eval/__init__.py +14 -0
- aiq/eval/config.py +60 -0
- aiq/eval/dataset_handler/__init__.py +0 -0
- aiq/eval/dataset_handler/dataset_downloader.py +106 -0
- aiq/eval/dataset_handler/dataset_filter.py +52 -0
- aiq/eval/dataset_handler/dataset_handler.py +254 -0
- aiq/eval/evaluate.py +506 -0
- aiq/eval/evaluator/__init__.py +14 -0
- aiq/eval/evaluator/base_evaluator.py +73 -0
- aiq/eval/evaluator/evaluator_model.py +45 -0
- aiq/eval/intermediate_step_adapter.py +99 -0
- aiq/eval/rag_evaluator/__init__.py +0 -0
- aiq/eval/rag_evaluator/evaluate.py +178 -0
- aiq/eval/rag_evaluator/register.py +143 -0
- aiq/eval/register.py +23 -0
- aiq/eval/remote_workflow.py +133 -0
- aiq/eval/runners/__init__.py +14 -0
- aiq/eval/runners/config.py +39 -0
- aiq/eval/runners/multi_eval_runner.py +54 -0
- aiq/eval/runtime_event_subscriber.py +52 -0
- aiq/eval/swe_bench_evaluator/__init__.py +0 -0
- aiq/eval/swe_bench_evaluator/evaluate.py +215 -0
- aiq/eval/swe_bench_evaluator/register.py +36 -0
- aiq/eval/trajectory_evaluator/__init__.py +0 -0
- aiq/eval/trajectory_evaluator/evaluate.py +75 -0
- aiq/eval/trajectory_evaluator/register.py +40 -0
- aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
- aiq/eval/tunable_rag_evaluator/evaluate.py +245 -0
- aiq/eval/tunable_rag_evaluator/register.py +52 -0
- aiq/eval/usage_stats.py +41 -0
- aiq/eval/utils/__init__.py +0 -0
- aiq/eval/utils/output_uploader.py +140 -0
- aiq/eval/utils/tqdm_position_registry.py +40 -0
- aiq/eval/utils/weave_eval.py +184 -0
- aiq/experimental/__init__.py +0 -0
- aiq/experimental/decorators/__init__.py +0 -0
- aiq/experimental/decorators/experimental_warning_decorator.py +130 -0
- aiq/experimental/test_time_compute/__init__.py +0 -0
- aiq/experimental/test_time_compute/editing/__init__.py +0 -0
- aiq/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +147 -0
- aiq/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +204 -0
- aiq/experimental/test_time_compute/editing/motivation_aware_summarization.py +107 -0
- aiq/experimental/test_time_compute/functions/__init__.py +0 -0
- aiq/experimental/test_time_compute/functions/execute_score_select_function.py +105 -0
- aiq/experimental/test_time_compute/functions/its_tool_orchestration_function.py +205 -0
- aiq/experimental/test_time_compute/functions/its_tool_wrapper_function.py +146 -0
- aiq/experimental/test_time_compute/functions/plan_select_execute_function.py +224 -0
- aiq/experimental/test_time_compute/models/__init__.py +0 -0
- aiq/experimental/test_time_compute/models/editor_config.py +132 -0
- aiq/experimental/test_time_compute/models/scoring_config.py +112 -0
- aiq/experimental/test_time_compute/models/search_config.py +120 -0
- aiq/experimental/test_time_compute/models/selection_config.py +154 -0
- aiq/experimental/test_time_compute/models/stage_enums.py +43 -0
- aiq/experimental/test_time_compute/models/strategy_base.py +66 -0
- aiq/experimental/test_time_compute/models/tool_use_config.py +41 -0
- aiq/experimental/test_time_compute/models/ttc_item.py +48 -0
- aiq/experimental/test_time_compute/register.py +36 -0
- aiq/experimental/test_time_compute/scoring/__init__.py +0 -0
- aiq/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +168 -0
- aiq/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +168 -0
- aiq/experimental/test_time_compute/scoring/motivation_aware_scorer.py +111 -0
- aiq/experimental/test_time_compute/search/__init__.py +0 -0
- aiq/experimental/test_time_compute/search/multi_llm_planner.py +128 -0
- aiq/experimental/test_time_compute/search/multi_query_retrieval_search.py +122 -0
- aiq/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +128 -0
- aiq/experimental/test_time_compute/selection/__init__.py +0 -0
- aiq/experimental/test_time_compute/selection/best_of_n_selector.py +63 -0
- aiq/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +131 -0
- aiq/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +159 -0
- aiq/experimental/test_time_compute/selection/llm_based_plan_selector.py +128 -0
- aiq/experimental/test_time_compute/selection/threshold_selector.py +58 -0
- aiq/front_ends/__init__.py +14 -0
- aiq/front_ends/console/__init__.py +14 -0
- aiq/front_ends/console/authentication_flow_handler.py +233 -0
- aiq/front_ends/console/console_front_end_config.py +32 -0
- aiq/front_ends/console/console_front_end_plugin.py +96 -0
- aiq/front_ends/console/register.py +25 -0
- aiq/front_ends/cron/__init__.py +14 -0
- aiq/front_ends/fastapi/__init__.py +14 -0
- aiq/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
- aiq/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +27 -0
- aiq/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +107 -0
- aiq/front_ends/fastapi/fastapi_front_end_config.py +234 -0
- aiq/front_ends/fastapi/fastapi_front_end_controller.py +68 -0
- aiq/front_ends/fastapi/fastapi_front_end_plugin.py +116 -0
- aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +1092 -0
- aiq/front_ends/fastapi/html_snippets/__init__.py +14 -0
- aiq/front_ends/fastapi/html_snippets/auth_code_grant_success.py +35 -0
- aiq/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
- aiq/front_ends/fastapi/job_store.py +183 -0
- aiq/front_ends/fastapi/main.py +72 -0
- aiq/front_ends/fastapi/message_handler.py +298 -0
- aiq/front_ends/fastapi/message_validator.py +345 -0
- aiq/front_ends/fastapi/register.py +25 -0
- aiq/front_ends/fastapi/response_helpers.py +195 -0
- aiq/front_ends/fastapi/step_adaptor.py +321 -0
- aiq/front_ends/mcp/__init__.py +14 -0
- aiq/front_ends/mcp/mcp_front_end_config.py +32 -0
- aiq/front_ends/mcp/mcp_front_end_plugin.py +93 -0
- aiq/front_ends/mcp/register.py +27 -0
- aiq/front_ends/mcp/tool_converter.py +242 -0
- aiq/front_ends/register.py +22 -0
- aiq/front_ends/simple_base/__init__.py +14 -0
- aiq/front_ends/simple_base/simple_front_end_plugin_base.py +54 -0
- aiq/llm/__init__.py +0 -0
- aiq/llm/aws_bedrock_llm.py +57 -0
- aiq/llm/nim_llm.py +46 -0
- aiq/llm/openai_llm.py +46 -0
- aiq/llm/register.py +23 -0
- aiq/llm/utils/__init__.py +14 -0
- aiq/llm/utils/env_config_value.py +94 -0
- aiq/llm/utils/error.py +17 -0
- aiq/memory/__init__.py +20 -0
- aiq/memory/interfaces.py +183 -0
- aiq/memory/models.py +112 -0
- aiq/meta/module_to_distro.json +3 -0
- aiq/meta/pypi.md +58 -0
- aiq/object_store/__init__.py +20 -0
- aiq/object_store/in_memory_object_store.py +76 -0
- aiq/object_store/interfaces.py +84 -0
- aiq/object_store/models.py +36 -0
- aiq/object_store/register.py +20 -0
- aiq/observability/__init__.py +14 -0
- aiq/observability/exporter/__init__.py +14 -0
- aiq/observability/exporter/base_exporter.py +449 -0
- aiq/observability/exporter/exporter.py +78 -0
- aiq/observability/exporter/file_exporter.py +33 -0
- aiq/observability/exporter/processing_exporter.py +322 -0
- aiq/observability/exporter/raw_exporter.py +52 -0
- aiq/observability/exporter/span_exporter.py +265 -0
- aiq/observability/exporter_manager.py +335 -0
- aiq/observability/mixin/__init__.py +14 -0
- aiq/observability/mixin/batch_config_mixin.py +26 -0
- aiq/observability/mixin/collector_config_mixin.py +23 -0
- aiq/observability/mixin/file_mixin.py +288 -0
- aiq/observability/mixin/file_mode.py +23 -0
- aiq/observability/mixin/resource_conflict_mixin.py +134 -0
- aiq/observability/mixin/serialize_mixin.py +61 -0
- aiq/observability/mixin/type_introspection_mixin.py +183 -0
- aiq/observability/processor/__init__.py +14 -0
- aiq/observability/processor/batching_processor.py +310 -0
- aiq/observability/processor/callback_processor.py +42 -0
- aiq/observability/processor/intermediate_step_serializer.py +28 -0
- aiq/observability/processor/processor.py +71 -0
- aiq/observability/register.py +96 -0
- aiq/observability/utils/__init__.py +14 -0
- aiq/observability/utils/dict_utils.py +236 -0
- aiq/observability/utils/time_utils.py +31 -0
- aiq/plugins/.namespace +1 -0
- aiq/profiler/__init__.py +0 -0
- aiq/profiler/calc/__init__.py +14 -0
- aiq/profiler/calc/calc_runner.py +627 -0
- aiq/profiler/calc/calculations.py +288 -0
- aiq/profiler/calc/data_models.py +188 -0
- aiq/profiler/calc/plot.py +345 -0
- aiq/profiler/callbacks/__init__.py +0 -0
- aiq/profiler/callbacks/agno_callback_handler.py +295 -0
- aiq/profiler/callbacks/base_callback_class.py +20 -0
- aiq/profiler/callbacks/langchain_callback_handler.py +290 -0
- aiq/profiler/callbacks/llama_index_callback_handler.py +205 -0
- aiq/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
- aiq/profiler/callbacks/token_usage_base_model.py +27 -0
- aiq/profiler/data_frame_row.py +51 -0
- aiq/profiler/data_models.py +24 -0
- aiq/profiler/decorators/__init__.py +0 -0
- aiq/profiler/decorators/framework_wrapper.py +131 -0
- aiq/profiler/decorators/function_tracking.py +254 -0
- aiq/profiler/forecasting/__init__.py +0 -0
- aiq/profiler/forecasting/config.py +18 -0
- aiq/profiler/forecasting/model_trainer.py +75 -0
- aiq/profiler/forecasting/models/__init__.py +22 -0
- aiq/profiler/forecasting/models/forecasting_base_model.py +40 -0
- aiq/profiler/forecasting/models/linear_model.py +196 -0
- aiq/profiler/forecasting/models/random_forest_regressor.py +268 -0
- aiq/profiler/inference_metrics_model.py +28 -0
- aiq/profiler/inference_optimization/__init__.py +0 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +460 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
- aiq/profiler/inference_optimization/data_models.py +386 -0
- aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
- aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
- aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +405 -0
- aiq/profiler/inference_optimization/llm_metrics.py +212 -0
- aiq/profiler/inference_optimization/prompt_caching.py +163 -0
- aiq/profiler/inference_optimization/token_uniqueness.py +107 -0
- aiq/profiler/inference_optimization/workflow_runtimes.py +72 -0
- aiq/profiler/intermediate_property_adapter.py +102 -0
- aiq/profiler/profile_runner.py +473 -0
- aiq/profiler/utils.py +184 -0
- aiq/registry_handlers/__init__.py +0 -0
- aiq/registry_handlers/local/__init__.py +0 -0
- aiq/registry_handlers/local/local_handler.py +176 -0
- aiq/registry_handlers/local/register_local.py +37 -0
- aiq/registry_handlers/metadata_factory.py +60 -0
- aiq/registry_handlers/package_utils.py +567 -0
- aiq/registry_handlers/pypi/__init__.py +0 -0
- aiq/registry_handlers/pypi/pypi_handler.py +251 -0
- aiq/registry_handlers/pypi/register_pypi.py +40 -0
- aiq/registry_handlers/register.py +21 -0
- aiq/registry_handlers/registry_handler_base.py +157 -0
- aiq/registry_handlers/rest/__init__.py +0 -0
- aiq/registry_handlers/rest/register_rest.py +56 -0
- aiq/registry_handlers/rest/rest_handler.py +237 -0
- aiq/registry_handlers/schemas/__init__.py +0 -0
- aiq/registry_handlers/schemas/headers.py +42 -0
- aiq/registry_handlers/schemas/package.py +68 -0
- aiq/registry_handlers/schemas/publish.py +63 -0
- aiq/registry_handlers/schemas/pull.py +82 -0
- aiq/registry_handlers/schemas/remove.py +36 -0
- aiq/registry_handlers/schemas/search.py +91 -0
- aiq/registry_handlers/schemas/status.py +47 -0
- aiq/retriever/__init__.py +0 -0
- aiq/retriever/interface.py +37 -0
- aiq/retriever/milvus/__init__.py +14 -0
- aiq/retriever/milvus/register.py +81 -0
- aiq/retriever/milvus/retriever.py +228 -0
- aiq/retriever/models.py +74 -0
- aiq/retriever/nemo_retriever/__init__.py +14 -0
- aiq/retriever/nemo_retriever/register.py +60 -0
- aiq/retriever/nemo_retriever/retriever.py +190 -0
- aiq/retriever/register.py +22 -0
- aiq/runtime/__init__.py +14 -0
- aiq/runtime/loader.py +215 -0
- aiq/runtime/runner.py +190 -0
- aiq/runtime/session.py +158 -0
- aiq/runtime/user_metadata.py +130 -0
- aiq/settings/__init__.py +0 -0
- aiq/settings/global_settings.py +318 -0
- aiq/test/.namespace +1 -0
- aiq/tool/__init__.py +0 -0
- aiq/tool/chat_completion.py +74 -0
- aiq/tool/code_execution/README.md +151 -0
- aiq/tool/code_execution/__init__.py +0 -0
- aiq/tool/code_execution/code_sandbox.py +267 -0
- aiq/tool/code_execution/local_sandbox/.gitignore +1 -0
- aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
- aiq/tool/code_execution/local_sandbox/__init__.py +13 -0
- aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +198 -0
- aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +6 -0
- aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +50 -0
- aiq/tool/code_execution/register.py +74 -0
- aiq/tool/code_execution/test_code_execution_sandbox.py +414 -0
- aiq/tool/code_execution/utils.py +100 -0
- aiq/tool/datetime_tools.py +42 -0
- aiq/tool/document_search.py +141 -0
- aiq/tool/github_tools/__init__.py +0 -0
- aiq/tool/github_tools/create_github_commit.py +133 -0
- aiq/tool/github_tools/create_github_issue.py +87 -0
- aiq/tool/github_tools/create_github_pr.py +106 -0
- aiq/tool/github_tools/get_github_file.py +106 -0
- aiq/tool/github_tools/get_github_issue.py +166 -0
- aiq/tool/github_tools/get_github_pr.py +256 -0
- aiq/tool/github_tools/update_github_issue.py +100 -0
- aiq/tool/mcp/__init__.py +14 -0
- aiq/tool/mcp/exceptions.py +142 -0
- aiq/tool/mcp/mcp_client.py +255 -0
- aiq/tool/mcp/mcp_tool.py +96 -0
- aiq/tool/memory_tools/__init__.py +0 -0
- aiq/tool/memory_tools/add_memory_tool.py +79 -0
- aiq/tool/memory_tools/delete_memory_tool.py +67 -0
- aiq/tool/memory_tools/get_memory_tool.py +72 -0
- aiq/tool/nvidia_rag.py +95 -0
- aiq/tool/register.py +38 -0
- aiq/tool/retriever.py +89 -0
- aiq/tool/server_tools.py +66 -0
- aiq/utils/__init__.py +0 -0
- aiq/utils/data_models/__init__.py +0 -0
- aiq/utils/data_models/schema_validator.py +58 -0
- aiq/utils/debugging_utils.py +43 -0
- aiq/utils/dump_distro_mapping.py +32 -0
- aiq/utils/exception_handlers/__init__.py +0 -0
- aiq/utils/exception_handlers/automatic_retries.py +289 -0
- aiq/utils/exception_handlers/mcp.py +211 -0
- aiq/utils/exception_handlers/schemas.py +114 -0
- aiq/utils/io/__init__.py +0 -0
- aiq/utils/io/model_processing.py +28 -0
- aiq/utils/io/yaml_tools.py +119 -0
- aiq/utils/log_utils.py +37 -0
- aiq/utils/metadata_utils.py +74 -0
- aiq/utils/optional_imports.py +142 -0
- aiq/utils/producer_consumer_queue.py +178 -0
- aiq/utils/reactive/__init__.py +0 -0
- aiq/utils/reactive/base/__init__.py +0 -0
- aiq/utils/reactive/base/observable_base.py +65 -0
- aiq/utils/reactive/base/observer_base.py +55 -0
- aiq/utils/reactive/base/subject_base.py +79 -0
- aiq/utils/reactive/observable.py +59 -0
- aiq/utils/reactive/observer.py +76 -0
- aiq/utils/reactive/subject.py +131 -0
- aiq/utils/reactive/subscription.py +49 -0
- aiq/utils/settings/__init__.py +0 -0
- aiq/utils/settings/global_settings.py +197 -0
- aiq/utils/string_utils.py +38 -0
- aiq/utils/type_converter.py +290 -0
- aiq/utils/type_utils.py +484 -0
- aiq/utils/url_utils.py +27 -0
- nvidia_nat-1.2.0rc5.dist-info/METADATA +363 -0
- nvidia_nat-1.2.0rc5.dist-info/RECORD +435 -0
- nvidia_nat-1.2.0rc5.dist-info/WHEEL +5 -0
- nvidia_nat-1.2.0rc5.dist-info/entry_points.txt +20 -0
- nvidia_nat-1.2.0rc5.dist-info/licenses/LICENSE-3rd-party.txt +3686 -0
- nvidia_nat-1.2.0rc5.dist-info/licenses/LICENSE.md +201 -0
- nvidia_nat-1.2.0rc5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,161 @@
|
|
|
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 dataclasses
|
|
17
|
+
import logging
|
|
18
|
+
from contextlib import asynccontextmanager
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from aiq.builder.builder import EvalBuilder
|
|
22
|
+
from aiq.builder.evaluator import EvaluatorInfo
|
|
23
|
+
from aiq.builder.framework_enum import LLMFrameworkEnum
|
|
24
|
+
from aiq.builder.workflow_builder import WorkflowBuilder
|
|
25
|
+
from aiq.cli.type_registry import TypeRegistry
|
|
26
|
+
from aiq.data_models.config import AIQConfig
|
|
27
|
+
from aiq.data_models.config import GeneralConfig
|
|
28
|
+
from aiq.data_models.evaluate import EvalGeneralConfig
|
|
29
|
+
from aiq.data_models.evaluator import EvaluatorBaseConfig
|
|
30
|
+
from aiq.data_models.function import EmptyFunctionConfig
|
|
31
|
+
from aiq.utils.type_utils import override
|
|
32
|
+
|
|
33
|
+
logger = logging.getLogger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclasses.dataclass
|
|
37
|
+
class ConfiguredEvaluator:
|
|
38
|
+
config: EvaluatorBaseConfig
|
|
39
|
+
instance: EvaluatorInfo
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class WorkflowEvalBuilder(WorkflowBuilder, EvalBuilder):
|
|
43
|
+
|
|
44
|
+
def __init__(self,
|
|
45
|
+
general_config: GeneralConfig | None = None,
|
|
46
|
+
eval_general_config: EvalGeneralConfig | None = None,
|
|
47
|
+
registry: TypeRegistry | None = None):
|
|
48
|
+
super().__init__(general_config=general_config, registry=registry)
|
|
49
|
+
self.eval_general_config = eval_general_config
|
|
50
|
+
self._evaluators: dict[str, ConfiguredEvaluator] = {}
|
|
51
|
+
|
|
52
|
+
@override
|
|
53
|
+
async def add_evaluator(self, name: str, config: EvaluatorBaseConfig):
|
|
54
|
+
if name in self._evaluators:
|
|
55
|
+
raise ValueError(f"Evaluator `{name}` already exists in the list of evaluators")
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
evaluator_info = self._registry.get_evaluator(type(config))
|
|
59
|
+
info_obj = await self._get_exit_stack().enter_async_context(evaluator_info.build_fn(config, self))
|
|
60
|
+
|
|
61
|
+
# Store the evaluator
|
|
62
|
+
self._evaluators[name] = ConfiguredEvaluator(config=config, instance=info_obj)
|
|
63
|
+
except Exception as e:
|
|
64
|
+
logger.error("Error %s adding evaluator `%s` with config `%s`", e, name, config, exc_info=True)
|
|
65
|
+
raise
|
|
66
|
+
|
|
67
|
+
@override
|
|
68
|
+
def get_evaluator(self, evaluator_name: str) -> EvaluatorInfo:
|
|
69
|
+
|
|
70
|
+
if (evaluator_name not in self._evaluators):
|
|
71
|
+
raise ValueError(f"Evaluator `{evaluator_name}` not found")
|
|
72
|
+
|
|
73
|
+
return self._evaluators[evaluator_name].instance
|
|
74
|
+
|
|
75
|
+
@override
|
|
76
|
+
def get_evaluator_config(self, evaluator_name: str) -> EvaluatorBaseConfig:
|
|
77
|
+
|
|
78
|
+
if evaluator_name not in self._evaluators:
|
|
79
|
+
raise ValueError(f"Evaluator `{evaluator_name}` not found")
|
|
80
|
+
|
|
81
|
+
# Return the tool configuration object
|
|
82
|
+
return self._evaluators[evaluator_name].config
|
|
83
|
+
|
|
84
|
+
@override
|
|
85
|
+
def get_max_concurrency(self) -> int:
|
|
86
|
+
return self.eval_general_config.max_concurrency
|
|
87
|
+
|
|
88
|
+
@override
|
|
89
|
+
def get_output_dir(self) -> Path:
|
|
90
|
+
return self.eval_general_config.output_dir
|
|
91
|
+
|
|
92
|
+
@override
|
|
93
|
+
def get_all_tools(self, wrapper_type: LLMFrameworkEnum | str):
|
|
94
|
+
tools = []
|
|
95
|
+
tool_wrapper_reg = self._registry.get_tool_wrapper(llm_framework=wrapper_type)
|
|
96
|
+
for fn_name in self._functions:
|
|
97
|
+
fn = self.get_function(fn_name)
|
|
98
|
+
try:
|
|
99
|
+
tools.append(tool_wrapper_reg.build_fn(fn_name, fn, self))
|
|
100
|
+
except Exception:
|
|
101
|
+
logger.exception("Error fetching tool `%s`", fn_name, exc_info=True)
|
|
102
|
+
|
|
103
|
+
return tools
|
|
104
|
+
|
|
105
|
+
def _log_build_failure_evaluator(self,
|
|
106
|
+
failing_evaluator_name: str,
|
|
107
|
+
completed_evaluators: list[str],
|
|
108
|
+
remaining_evaluators: list[str],
|
|
109
|
+
original_error: Exception) -> None:
|
|
110
|
+
"""
|
|
111
|
+
Log comprehensive evaluator build failure information.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
failing_evaluator_name (str): The name of the evaluator that failed to build
|
|
115
|
+
completed_evaluators (list[str]): List of evaluator names that were successfully built
|
|
116
|
+
remaining_evaluators (list[str]): List of evaluator names still to be built
|
|
117
|
+
original_error (Exception): The original exception that caused the failure
|
|
118
|
+
"""
|
|
119
|
+
# Convert evaluator names to (name, type) tuples for consistent logging
|
|
120
|
+
completed_components = [(name, "evaluator") for name in completed_evaluators]
|
|
121
|
+
remaining_components = [(name, "evaluator") for name in remaining_evaluators]
|
|
122
|
+
|
|
123
|
+
# Use the inherited common logging method from WorkflowBuilder
|
|
124
|
+
self._log_build_failure(failing_evaluator_name,
|
|
125
|
+
"evaluator",
|
|
126
|
+
completed_components,
|
|
127
|
+
remaining_components,
|
|
128
|
+
original_error)
|
|
129
|
+
|
|
130
|
+
async def populate_builder(self, config: AIQConfig):
|
|
131
|
+
# Skip setting workflow if workflow config is EmptyFunctionConfig
|
|
132
|
+
skip_workflow = isinstance(config.workflow, EmptyFunctionConfig)
|
|
133
|
+
|
|
134
|
+
await super().populate_builder(config, skip_workflow)
|
|
135
|
+
|
|
136
|
+
# Initialize progress tracking for evaluators
|
|
137
|
+
completed_evaluators = []
|
|
138
|
+
remaining_evaluators = list(config.eval.evaluators.keys())
|
|
139
|
+
|
|
140
|
+
# Instantiate the evaluators with enhanced error logging
|
|
141
|
+
for name, evaluator_config in config.eval.evaluators.items():
|
|
142
|
+
try:
|
|
143
|
+
# Remove from remaining as we start building
|
|
144
|
+
remaining_evaluators.remove(name)
|
|
145
|
+
|
|
146
|
+
await self.add_evaluator(name, evaluator_config)
|
|
147
|
+
|
|
148
|
+
# Add to completed after successful build
|
|
149
|
+
completed_evaluators.append(name)
|
|
150
|
+
|
|
151
|
+
except Exception as e:
|
|
152
|
+
self._log_build_failure_evaluator(name, completed_evaluators, remaining_evaluators, e)
|
|
153
|
+
raise
|
|
154
|
+
|
|
155
|
+
@classmethod
|
|
156
|
+
@asynccontextmanager
|
|
157
|
+
async def from_config(cls, config: AIQConfig):
|
|
158
|
+
|
|
159
|
+
async with cls(config.general, config.eval.general, registry=None) as builder:
|
|
160
|
+
await builder.populate_builder(config)
|
|
161
|
+
yield builder
|
aiq/builder/evaluator.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
from collections.abc import Callable
|
|
17
|
+
|
|
18
|
+
from aiq.data_models.evaluator import EvaluatorBaseConfig
|
|
19
|
+
from aiq.eval.evaluator.evaluator_model import EvalInput
|
|
20
|
+
from aiq.eval.evaluator.evaluator_model import EvalOutput
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class EvaluatorInfo:
|
|
24
|
+
|
|
25
|
+
def __init__(self, *, config: EvaluatorBaseConfig, evaluate_fn: Callable[[EvalInput], EvalOutput],
|
|
26
|
+
description: str):
|
|
27
|
+
self.config = config
|
|
28
|
+
self.evaluate_fn = evaluate_fn
|
|
29
|
+
self.description = description
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from enum import Enum
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class LLMFrameworkEnum(str, Enum):
|
|
20
|
+
LANGCHAIN = "langchain"
|
|
21
|
+
LLAMA_INDEX = "llama_index"
|
|
22
|
+
CREWAI = "crewai"
|
|
23
|
+
SEMANTIC_KERNEL = "semantic_kernel"
|
|
24
|
+
AGNO = "agno"
|
aiq/builder/front_end.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import typing
|
|
17
|
+
from abc import ABC
|
|
18
|
+
from abc import abstractmethod
|
|
19
|
+
|
|
20
|
+
from aiq.data_models.front_end import FrontEndConfigT
|
|
21
|
+
|
|
22
|
+
if (typing.TYPE_CHECKING):
|
|
23
|
+
from aiq.data_models.config import AIQConfig
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class FrontEndBase(typing.Generic[FrontEndConfigT], ABC):
|
|
27
|
+
|
|
28
|
+
def __init__(self, full_config: "AIQConfig"):
|
|
29
|
+
"""
|
|
30
|
+
Initializes the FrontEndBase object with the specified AIQ Toolkit configuration.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
full_config : AIQConfig
|
|
35
|
+
The configuration object to use for the front end.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
super().__init__()
|
|
39
|
+
|
|
40
|
+
self._full_config: "AIQConfig" = full_config
|
|
41
|
+
self._front_end_config: FrontEndConfigT = typing.cast(FrontEndConfigT, full_config.general.front_end)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def front_end_config(self) -> FrontEndConfigT:
|
|
45
|
+
"""
|
|
46
|
+
Returns the front end configuration object extracted from the AIQ Toolkit configuration.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
FrontEndConfigT
|
|
51
|
+
The front end configuration object.
|
|
52
|
+
"""
|
|
53
|
+
return self._front_end_config
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def full_config(self) -> "AIQConfig":
|
|
57
|
+
"""
|
|
58
|
+
Returns the full AIQ Toolkit configuration object.
|
|
59
|
+
|
|
60
|
+
Returns
|
|
61
|
+
-------
|
|
62
|
+
AIQConfig
|
|
63
|
+
The full AIQ Toolkit configuration object.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
return self._full_config
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
async def run(self):
|
|
70
|
+
"""
|
|
71
|
+
Runs the specified configuration file, launching the workflow until the front end is complete.
|
|
72
|
+
"""
|
|
73
|
+
pass
|
aiq/builder/function.py
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import typing
|
|
18
|
+
from abc import ABC
|
|
19
|
+
from abc import abstractmethod
|
|
20
|
+
from collections.abc import AsyncGenerator
|
|
21
|
+
from collections.abc import Awaitable
|
|
22
|
+
from collections.abc import Callable
|
|
23
|
+
|
|
24
|
+
from pydantic import BaseModel
|
|
25
|
+
|
|
26
|
+
from aiq.builder.context import AIQContext
|
|
27
|
+
from aiq.builder.function_base import FunctionBase
|
|
28
|
+
from aiq.builder.function_base import InputT
|
|
29
|
+
from aiq.builder.function_base import SingleOutputT
|
|
30
|
+
from aiq.builder.function_base import StreamingOutputT
|
|
31
|
+
from aiq.builder.function_info import FunctionInfo
|
|
32
|
+
from aiq.data_models.function import FunctionBaseConfig
|
|
33
|
+
|
|
34
|
+
_InvokeFnT = Callable[[InputT], Awaitable[SingleOutputT]]
|
|
35
|
+
_StreamFnT = Callable[[InputT], AsyncGenerator[StreamingOutputT]]
|
|
36
|
+
|
|
37
|
+
_T = typing.TypeVar("_T")
|
|
38
|
+
|
|
39
|
+
logger = logging.getLogger(__name__)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Function(FunctionBase[InputT, StreamingOutputT, SingleOutputT], ABC):
|
|
43
|
+
|
|
44
|
+
def __init__(self,
|
|
45
|
+
*,
|
|
46
|
+
config: FunctionBaseConfig,
|
|
47
|
+
description: str | None,
|
|
48
|
+
input_schema: type[BaseModel] | None = None,
|
|
49
|
+
streaming_output_schema: type[BaseModel] | type[None] | None = None,
|
|
50
|
+
single_output_schema: type[BaseModel] | type[None] | None = None,
|
|
51
|
+
converters: list[Callable[[typing.Any], typing.Any]] | None = None,
|
|
52
|
+
instance_name: str | None = None):
|
|
53
|
+
|
|
54
|
+
super().__init__(input_schema=input_schema,
|
|
55
|
+
streaming_output_schema=streaming_output_schema,
|
|
56
|
+
single_output_schema=single_output_schema,
|
|
57
|
+
converters=converters)
|
|
58
|
+
|
|
59
|
+
self.config = config
|
|
60
|
+
self.description = description
|
|
61
|
+
self.instance_name = instance_name or config.type
|
|
62
|
+
self._context = AIQContext.get()
|
|
63
|
+
|
|
64
|
+
def convert(self, value: typing.Any, to_type: type[_T]) -> _T:
|
|
65
|
+
"""
|
|
66
|
+
Converts the given value to the specified type using the function's converter.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
value : typing.Any
|
|
71
|
+
The value to convert.
|
|
72
|
+
to_type : type
|
|
73
|
+
The type to convert the value to.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
_T
|
|
78
|
+
The converted value.
|
|
79
|
+
|
|
80
|
+
Raises
|
|
81
|
+
------
|
|
82
|
+
ValueError
|
|
83
|
+
If the value cannot be converted to the specified type (when `to_type` is specified).
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
return self._converter.convert(value, to_type=to_type)
|
|
87
|
+
|
|
88
|
+
def try_convert(self, value: typing.Any, to_type: type[_T]) -> _T | typing.Any:
|
|
89
|
+
"""
|
|
90
|
+
Converts the given value to the specified type using graceful error handling.
|
|
91
|
+
If conversion fails, returns the original value and continues processing.
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
value : typing.Any
|
|
96
|
+
The value to convert.
|
|
97
|
+
to_type : type
|
|
98
|
+
The type to convert the value to.
|
|
99
|
+
|
|
100
|
+
Returns
|
|
101
|
+
-------
|
|
102
|
+
_T | typing.Any
|
|
103
|
+
The converted value, or original value if conversion fails.
|
|
104
|
+
"""
|
|
105
|
+
return self._converter.try_convert(value, to_type=to_type)
|
|
106
|
+
|
|
107
|
+
@abstractmethod
|
|
108
|
+
async def _ainvoke(self, value: InputT) -> SingleOutputT:
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
@typing.overload
|
|
112
|
+
async def ainvoke(self, value: InputT | typing.Any) -> SingleOutputT:
|
|
113
|
+
...
|
|
114
|
+
|
|
115
|
+
@typing.overload
|
|
116
|
+
async def ainvoke(self, value: InputT | typing.Any, to_type: type[_T]) -> _T:
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
@typing.final
|
|
120
|
+
async def ainvoke(self, value: InputT | typing.Any, to_type: type | None = None):
|
|
121
|
+
"""
|
|
122
|
+
Runs the function with the given input and returns a single output from the function. This is the
|
|
123
|
+
main entry point for running a function.
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
value : InputT | typing.Any
|
|
128
|
+
The input to the function.
|
|
129
|
+
to_type : type | None, optional
|
|
130
|
+
The type to convert the output to using the function's converter. When not specified, the
|
|
131
|
+
output will match `single_output_type`.
|
|
132
|
+
|
|
133
|
+
Returns
|
|
134
|
+
-------
|
|
135
|
+
typing.Any
|
|
136
|
+
The output of the function optionally converted to the specified type.
|
|
137
|
+
|
|
138
|
+
Raises
|
|
139
|
+
------
|
|
140
|
+
ValueError
|
|
141
|
+
If the output of the function cannot be converted to the specified type.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
with self._context.push_active_function(self.instance_name,
|
|
145
|
+
input_data=value) as manager: # Set the current invocation context
|
|
146
|
+
try:
|
|
147
|
+
converted_input: InputT = self._convert_input(value)
|
|
148
|
+
|
|
149
|
+
result = await self._ainvoke(converted_input)
|
|
150
|
+
|
|
151
|
+
if to_type is not None and not isinstance(result, to_type):
|
|
152
|
+
result = self.convert(result, to_type)
|
|
153
|
+
|
|
154
|
+
manager.set_output(result)
|
|
155
|
+
|
|
156
|
+
return result
|
|
157
|
+
except Exception as e:
|
|
158
|
+
logger.error("Error with ainvoke in function with input: %s.", value, exc_info=True)
|
|
159
|
+
raise e
|
|
160
|
+
|
|
161
|
+
@typing.final
|
|
162
|
+
async def acall_invoke(self, *args, **kwargs):
|
|
163
|
+
"""
|
|
164
|
+
A wrapper around `ainvoke` that allows for calling the function with arbitrary arguments and keyword arguments.
|
|
165
|
+
This is useful in scenarios where the function might be called by an LLM or other system which gives varying
|
|
166
|
+
inputs to the function. The function will attempt to convert the args and kwargs to the input schema of the
|
|
167
|
+
function.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
SingleOutputT
|
|
172
|
+
The output of the function.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
if (len(args) == 1 and not kwargs):
|
|
176
|
+
# If only one argument is passed, assume it is the input just like ainvoke
|
|
177
|
+
return await self.ainvoke(value=args[0])
|
|
178
|
+
|
|
179
|
+
if (not args and kwargs):
|
|
180
|
+
# If only kwargs are passed, assume we are calling a function with named arguments in a dict
|
|
181
|
+
# This will rely on the processing in ainvoke to convert from dict to the correct input type
|
|
182
|
+
return await self.ainvoke(value=kwargs)
|
|
183
|
+
|
|
184
|
+
# Possibly have both args and kwargs, final attempt is to use the input schema object constructor.
|
|
185
|
+
try:
|
|
186
|
+
input_obj = self.input_schema(*args, **kwargs)
|
|
187
|
+
|
|
188
|
+
return await self.ainvoke(value=input_obj)
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logger.error(
|
|
191
|
+
"Error in acall_invoke() converting input to function schema. Both args and kwargs were "
|
|
192
|
+
"supplied which could not be converted to the input schema. args: %s\nkwargs: %s\nschema: %s",
|
|
193
|
+
args,
|
|
194
|
+
kwargs,
|
|
195
|
+
self.input_schema)
|
|
196
|
+
raise e
|
|
197
|
+
|
|
198
|
+
@abstractmethod
|
|
199
|
+
async def _astream(self, value: InputT) -> AsyncGenerator[StreamingOutputT]:
|
|
200
|
+
yield # type: ignore
|
|
201
|
+
|
|
202
|
+
@typing.overload
|
|
203
|
+
async def astream(self, value: InputT | typing.Any) -> AsyncGenerator[SingleOutputT]:
|
|
204
|
+
...
|
|
205
|
+
|
|
206
|
+
@typing.overload
|
|
207
|
+
async def astream(self, value: InputT | typing.Any, to_type: type[_T]) -> AsyncGenerator[_T]:
|
|
208
|
+
...
|
|
209
|
+
|
|
210
|
+
@typing.final
|
|
211
|
+
async def astream(self, value: InputT | typing.Any, to_type: type | None = None):
|
|
212
|
+
"""
|
|
213
|
+
Runs the function with the given input and returns a stream of outputs from the function. This is the main entry
|
|
214
|
+
point for running a function with streaming output.
|
|
215
|
+
|
|
216
|
+
Parameters
|
|
217
|
+
----------
|
|
218
|
+
value : InputT | typing.Any
|
|
219
|
+
The input to the function.
|
|
220
|
+
to_type : type | None, optional
|
|
221
|
+
The type to convert the output to using the function's converter. When not specified, the
|
|
222
|
+
output will match `streaming_output_type`.
|
|
223
|
+
|
|
224
|
+
Yields
|
|
225
|
+
------
|
|
226
|
+
typing.Any
|
|
227
|
+
The output of the function optionally converted to the specified type.
|
|
228
|
+
|
|
229
|
+
Raises
|
|
230
|
+
------
|
|
231
|
+
ValueError
|
|
232
|
+
If the output of the function cannot be converted to the specified type (when `to_type` is specified).
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
with self._context.push_active_function(self.instance_name, input_data=value) as manager:
|
|
236
|
+
try:
|
|
237
|
+
converted_input: InputT = self._convert_input(value)
|
|
238
|
+
|
|
239
|
+
# Collect streaming outputs to capture the final result
|
|
240
|
+
final_output: list[typing.Any] = []
|
|
241
|
+
|
|
242
|
+
async for data in self._astream(converted_input):
|
|
243
|
+
if to_type is not None and not isinstance(data, to_type):
|
|
244
|
+
converted_data = self.convert(data, to_type=to_type)
|
|
245
|
+
final_output.append(converted_data)
|
|
246
|
+
yield converted_data
|
|
247
|
+
else:
|
|
248
|
+
final_output.append(data)
|
|
249
|
+
yield data
|
|
250
|
+
|
|
251
|
+
# Set the final output for intermediate step tracking
|
|
252
|
+
manager.set_output(final_output)
|
|
253
|
+
|
|
254
|
+
except Exception as e:
|
|
255
|
+
logger.error("Error with astream in function with input: %s.", value, exc_info=True)
|
|
256
|
+
raise e
|
|
257
|
+
|
|
258
|
+
@typing.final
|
|
259
|
+
async def acall_stream(self, *args, **kwargs):
|
|
260
|
+
"""
|
|
261
|
+
A wrapper around `astream` that allows for calling the function with arbitrary arguments and keyword arguments.
|
|
262
|
+
This is useful in scenarios where the function might be called by an LLM or other system which gives varying
|
|
263
|
+
inputs to the function. The function will attempt to convert the args and kwargs to the input schema of the
|
|
264
|
+
function.
|
|
265
|
+
|
|
266
|
+
Yields
|
|
267
|
+
------
|
|
268
|
+
StreamingOutputT
|
|
269
|
+
The output of the function.
|
|
270
|
+
"""
|
|
271
|
+
|
|
272
|
+
if (len(args) == 1 and not kwargs):
|
|
273
|
+
# If only one argument is passed, assume it is the input just like ainvoke
|
|
274
|
+
async for x in self.astream(value=args[0]):
|
|
275
|
+
yield x
|
|
276
|
+
|
|
277
|
+
elif (not args and kwargs):
|
|
278
|
+
# If only kwargs are passed, assume we are calling a function with named arguments in a dict
|
|
279
|
+
# This will rely on the processing in ainvoke to convert from dict to the correct input type
|
|
280
|
+
async for x in self.astream(value=kwargs):
|
|
281
|
+
yield x
|
|
282
|
+
|
|
283
|
+
# Possibly have both args and kwargs, final attempt is to use the input schema object constructor.
|
|
284
|
+
else:
|
|
285
|
+
try:
|
|
286
|
+
input_obj = self.input_schema(*args, **kwargs)
|
|
287
|
+
|
|
288
|
+
async for x in self.astream(value=input_obj):
|
|
289
|
+
yield x
|
|
290
|
+
except Exception as e:
|
|
291
|
+
logger.error(
|
|
292
|
+
"Error in acall_stream() converting input to function schema. Both args and kwargs were "
|
|
293
|
+
"supplied which could not be converted to the input schema. args: %s\nkwargs: %s\nschema: %s",
|
|
294
|
+
args,
|
|
295
|
+
kwargs,
|
|
296
|
+
self.input_schema)
|
|
297
|
+
raise e
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class LambdaFunction(Function[InputT, StreamingOutputT, SingleOutputT]):
|
|
301
|
+
|
|
302
|
+
def __init__(self, *, config: FunctionBaseConfig, info: FunctionInfo, instance_name: str | None = None):
|
|
303
|
+
|
|
304
|
+
super().__init__(config=config,
|
|
305
|
+
description=info.description,
|
|
306
|
+
input_schema=info.input_schema,
|
|
307
|
+
streaming_output_schema=info.stream_output_schema,
|
|
308
|
+
single_output_schema=info.single_output_schema,
|
|
309
|
+
converters=info.converters,
|
|
310
|
+
instance_name=instance_name)
|
|
311
|
+
|
|
312
|
+
self._info = info
|
|
313
|
+
self._ainvoke_fn: _InvokeFnT = info.single_fn
|
|
314
|
+
self._astream_fn: _StreamFnT = info.stream_fn
|
|
315
|
+
|
|
316
|
+
@property
|
|
317
|
+
def has_streaming_output(self) -> bool:
|
|
318
|
+
return self._astream_fn is not None
|
|
319
|
+
|
|
320
|
+
@property
|
|
321
|
+
def has_single_output(self) -> bool:
|
|
322
|
+
return self._ainvoke_fn is not None
|
|
323
|
+
|
|
324
|
+
async def _ainvoke(self, value: InputT) -> SingleOutputT:
|
|
325
|
+
return await self._ainvoke_fn(value)
|
|
326
|
+
|
|
327
|
+
async def _astream(self, value: InputT) -> AsyncGenerator[StreamingOutputT]:
|
|
328
|
+
async for x in self._astream_fn(value):
|
|
329
|
+
yield x
|
|
330
|
+
|
|
331
|
+
@staticmethod
|
|
332
|
+
def from_info(*,
|
|
333
|
+
config: FunctionBaseConfig,
|
|
334
|
+
info: FunctionInfo,
|
|
335
|
+
instance_name: str | None = None) -> 'LambdaFunction[InputT, StreamingOutputT, SingleOutputT]':
|
|
336
|
+
|
|
337
|
+
input_type: type = info.input_type
|
|
338
|
+
streaming_output_type = info.stream_output_type
|
|
339
|
+
single_output_type = info.single_output_type
|
|
340
|
+
|
|
341
|
+
class FunctionImpl(LambdaFunction[input_type, streaming_output_type, single_output_type]):
|
|
342
|
+
pass
|
|
343
|
+
|
|
344
|
+
return FunctionImpl(config=config, info=info, instance_name=instance_name)
|