nvidia-nat 1.3a20250819__py3-none-any.whl → 1.3.0a20250823__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.
Files changed (108) hide show
  1. aiq/__init__.py +66 -0
  2. nat/agent/base.py +16 -0
  3. nat/agent/react_agent/agent.py +38 -13
  4. nat/agent/react_agent/prompt.py +4 -1
  5. nat/agent/react_agent/register.py +1 -1
  6. nat/agent/register.py +0 -1
  7. nat/agent/rewoo_agent/agent.py +6 -3
  8. nat/agent/rewoo_agent/prompt.py +3 -0
  9. nat/agent/rewoo_agent/register.py +4 -3
  10. nat/agent/tool_calling_agent/agent.py +92 -22
  11. nat/agent/tool_calling_agent/register.py +9 -13
  12. nat/authentication/api_key/api_key_auth_provider.py +1 -1
  13. nat/authentication/register.py +0 -1
  14. nat/builder/builder.py +1 -1
  15. nat/builder/context.py +9 -1
  16. nat/builder/function_base.py +3 -3
  17. nat/builder/function_info.py +5 -7
  18. nat/builder/user_interaction_manager.py +2 -2
  19. nat/builder/workflow.py +3 -0
  20. nat/builder/workflow_builder.py +0 -1
  21. nat/cli/commands/evaluate.py +1 -1
  22. nat/cli/commands/info/list_components.py +7 -8
  23. nat/cli/commands/info/list_mcp.py +3 -4
  24. nat/cli/commands/registry/search.py +14 -16
  25. nat/cli/commands/start.py +0 -1
  26. nat/cli/commands/workflow/templates/pyproject.toml.j2 +3 -0
  27. nat/cli/commands/workflow/templates/register.py.j2 +0 -1
  28. nat/cli/commands/workflow/workflow_commands.py +0 -1
  29. nat/cli/type_registry.py +7 -9
  30. nat/data_models/config.py +1 -1
  31. nat/data_models/evaluate.py +1 -1
  32. nat/data_models/function_dependencies.py +6 -6
  33. nat/data_models/intermediate_step.py +3 -3
  34. nat/data_models/model_gated_field_mixin.py +125 -0
  35. nat/data_models/swe_bench_model.py +1 -1
  36. nat/data_models/temperature_mixin.py +36 -0
  37. nat/data_models/top_p_mixin.py +36 -0
  38. nat/embedder/azure_openai_embedder.py +46 -0
  39. nat/embedder/openai_embedder.py +1 -2
  40. nat/embedder/register.py +1 -1
  41. nat/eval/config.py +2 -0
  42. nat/eval/dataset_handler/dataset_handler.py +5 -6
  43. nat/eval/evaluate.py +64 -20
  44. nat/eval/rag_evaluator/register.py +2 -2
  45. nat/eval/register.py +0 -1
  46. nat/eval/tunable_rag_evaluator/evaluate.py +0 -3
  47. nat/eval/utils/eval_trace_ctx.py +89 -0
  48. nat/eval/utils/weave_eval.py +14 -7
  49. nat/experimental/test_time_compute/models/strategy_base.py +3 -2
  50. nat/experimental/test_time_compute/register.py +0 -1
  51. nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +0 -2
  52. nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +48 -49
  53. nat/front_ends/fastapi/message_handler.py +13 -14
  54. nat/front_ends/fastapi/message_validator.py +4 -4
  55. nat/front_ends/fastapi/step_adaptor.py +1 -1
  56. nat/front_ends/register.py +0 -1
  57. nat/llm/aws_bedrock_llm.py +3 -3
  58. nat/llm/azure_openai_llm.py +49 -0
  59. nat/llm/nim_llm.py +4 -4
  60. nat/llm/openai_llm.py +4 -4
  61. nat/llm/register.py +1 -1
  62. nat/llm/utils/env_config_value.py +2 -3
  63. nat/meta/pypi.md +9 -9
  64. nat/object_store/models.py +2 -0
  65. nat/object_store/register.py +0 -1
  66. nat/observability/exporter/base_exporter.py +1 -1
  67. nat/observability/exporter/file_exporter.py +1 -1
  68. nat/observability/register.py +3 -3
  69. nat/profiler/callbacks/langchain_callback_handler.py +9 -2
  70. nat/profiler/callbacks/semantic_kernel_callback_handler.py +1 -1
  71. nat/profiler/data_frame_row.py +1 -1
  72. nat/profiler/decorators/framework_wrapper.py +1 -4
  73. nat/profiler/forecasting/models/forecasting_base_model.py +3 -1
  74. nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
  75. nat/profiler/inference_optimization/data_models.py +3 -3
  76. nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +7 -8
  77. nat/profiler/inference_optimization/token_uniqueness.py +1 -1
  78. nat/profiler/profile_runner.py +13 -8
  79. nat/registry_handlers/package_utils.py +0 -1
  80. nat/registry_handlers/pypi/pypi_handler.py +20 -23
  81. nat/registry_handlers/register.py +3 -4
  82. nat/registry_handlers/rest/rest_handler.py +8 -9
  83. nat/retriever/register.py +0 -1
  84. nat/runtime/session.py +23 -8
  85. nat/settings/global_settings.py +13 -2
  86. nat/tool/code_execution/local_sandbox/local_sandbox_server.py +1 -1
  87. nat/tool/datetime_tools.py +49 -9
  88. nat/tool/document_search.py +1 -1
  89. nat/tool/mcp/mcp_tool.py +1 -1
  90. nat/tool/register.py +0 -1
  91. nat/utils/data_models/schema_validator.py +2 -2
  92. nat/utils/exception_handlers/automatic_retries.py +0 -2
  93. nat/utils/exception_handlers/schemas.py +1 -1
  94. nat/utils/reactive/base/observable_base.py +2 -2
  95. nat/utils/reactive/base/observer_base.py +1 -1
  96. nat/utils/reactive/observable.py +2 -2
  97. nat/utils/reactive/observer.py +2 -2
  98. nat/utils/reactive/subscription.py +1 -1
  99. nat/utils/settings/global_settings.py +4 -6
  100. nat/utils/type_utils.py +4 -4
  101. {nvidia_nat-1.3a20250819.dist-info → nvidia_nat-1.3.0a20250823.dist-info}/METADATA +17 -15
  102. {nvidia_nat-1.3a20250819.dist-info → nvidia_nat-1.3.0a20250823.dist-info}/RECORD +107 -100
  103. nvidia_nat-1.3.0a20250823.dist-info/licenses/LICENSE-3rd-party.txt +5478 -0
  104. {nvidia_nat-1.3a20250819.dist-info → nvidia_nat-1.3.0a20250823.dist-info}/top_level.txt +1 -0
  105. nvidia_nat-1.3a20250819.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
  106. {nvidia_nat-1.3a20250819.dist-info → nvidia_nat-1.3.0a20250823.dist-info}/WHEEL +0 -0
  107. {nvidia_nat-1.3a20250819.dist-info → nvidia_nat-1.3.0a20250823.dist-info}/entry_points.txt +0 -0
  108. {nvidia_nat-1.3a20250819.dist-info → nvidia_nat-1.3.0a20250823.dist-info}/licenses/LICENSE.md +0 -0
@@ -232,7 +232,7 @@ class MessageValidator:
232
232
  """
233
233
  return data_model.parent_id or "root"
234
234
 
235
- async def create_system_response_token_message( # pylint: disable=R0917:too-many-positional-arguments
235
+ async def create_system_response_token_message(
236
236
  self,
237
237
  message_type: Literal[WebSocketMessageType.RESPONSE_MESSAGE,
238
238
  WebSocketMessageType.ERROR_MESSAGE] = WebSocketMessageType.RESPONSE_MESSAGE,
@@ -272,7 +272,7 @@ class MessageValidator:
272
272
  logger.error("Error creating system response token message: %s", str(e), exc_info=True)
273
273
  return None
274
274
 
275
- async def create_system_intermediate_step_message( # pylint: disable=R0917:too-many-positional-arguments
275
+ async def create_system_intermediate_step_message(
276
276
  self,
277
277
  message_type: Literal[WebSocketMessageType.INTERMEDIATE_STEP_MESSAGE] = (
278
278
  WebSocketMessageType.INTERMEDIATE_STEP_MESSAGE),
@@ -311,7 +311,7 @@ class MessageValidator:
311
311
  logger.error("Error creating system intermediate step message: %s", str(e), exc_info=True)
312
312
  return None
313
313
 
314
- async def create_system_interaction_message( # pylint: disable=R0917:too-many-positional-arguments
314
+ async def create_system_interaction_message(
315
315
  self,
316
316
  *,
317
317
  message_type: Literal[WebSocketMessageType.SYSTEM_INTERACTION_MESSAGE] = (
@@ -323,7 +323,7 @@ class MessageValidator:
323
323
  content: HumanPrompt,
324
324
  status: WebSocketMessageStatus = WebSocketMessageStatus.IN_PROGRESS,
325
325
  timestamp: str = str(datetime.datetime.now(datetime.timezone.utc))
326
- ) -> WebSocketSystemInteractionMessage | None: # noqa: E125 continuation line with same indent as next logical line
326
+ ) -> WebSocketSystemInteractionMessage | None:
327
327
  """
328
328
  Creates a system interaction message with default values.
329
329
 
@@ -289,7 +289,7 @@ class StepAdaptor:
289
289
 
290
290
  return event
291
291
 
292
- def process(self, step: IntermediateStep) -> ResponseSerializable | None: # pylint: disable=R1710
292
+ def process(self, step: IntermediateStep) -> ResponseSerializable | None:
293
293
 
294
294
  # Track the chunk
295
295
  self._history.append(step)
@@ -13,7 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # pylint: disable=unused-import
17
16
  # flake8: noqa
18
17
  # isort:skip_file
19
18
 
@@ -22,9 +22,10 @@ from nat.builder.llm import LLMProviderInfo
22
22
  from nat.cli.register_workflow import register_llm_provider
23
23
  from nat.data_models.llm import LLMBaseConfig
24
24
  from nat.data_models.retry_mixin import RetryMixin
25
+ from nat.data_models.temperature_mixin import TemperatureMixin
25
26
 
26
27
 
27
- class AWSBedrockModelConfig(LLMBaseConfig, RetryMixin, name="aws_bedrock"):
28
+ class AWSBedrockModelConfig(LLMBaseConfig, RetryMixin, TemperatureMixin, name="aws_bedrock"):
28
29
  """An AWS Bedrock llm provider to be used with an LLM client."""
29
30
 
30
31
  model_config = ConfigDict(protected_namespaces=())
@@ -33,7 +34,6 @@ class AWSBedrockModelConfig(LLMBaseConfig, RetryMixin, name="aws_bedrock"):
33
34
  model_name: str = Field(validation_alias=AliasChoices("model_name", "model"),
34
35
  serialization_alias="model",
35
36
  description="The model name for the hosted AWS Bedrock.")
36
- temperature: float = Field(default=0.0, ge=0.0, le=1.0, description="Sampling temperature in [0, 1].")
37
37
  max_tokens: int | None = Field(default=1024,
38
38
  gt=0,
39
39
  description="Maximum number of tokens to generate."
@@ -52,6 +52,6 @@ class AWSBedrockModelConfig(LLMBaseConfig, RetryMixin, name="aws_bedrock"):
52
52
 
53
53
 
54
54
  @register_llm_provider(config_type=AWSBedrockModelConfig)
55
- async def aws_bedrock_model(llm_config: AWSBedrockModelConfig, builder: Builder):
55
+ async def aws_bedrock_model(llm_config: AWSBedrockModelConfig, _builder: Builder):
56
56
 
57
57
  yield LLMProviderInfo(config=llm_config, description="A AWS Bedrock model for use with an LLM client.")
@@ -0,0 +1,49 @@
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 pydantic import AliasChoices
17
+ from pydantic import ConfigDict
18
+ from pydantic import Field
19
+
20
+ from nat.builder.builder import Builder
21
+ from nat.builder.llm import LLMProviderInfo
22
+ from nat.cli.register_workflow import register_llm_provider
23
+ from nat.data_models.llm import LLMBaseConfig
24
+ from nat.data_models.retry_mixin import RetryMixin
25
+ from nat.data_models.temperature_mixin import TemperatureMixin
26
+ from nat.data_models.top_p_mixin import TopPMixin
27
+
28
+
29
+ class AzureOpenAIModelConfig(LLMBaseConfig, RetryMixin, TemperatureMixin, TopPMixin, name="azure_openai"):
30
+ """An Azure OpenAI LLM provider to be used with an LLM client."""
31
+
32
+ model_config = ConfigDict(protected_namespaces=(), extra="allow")
33
+
34
+ api_key: str | None = Field(default=None, description="Azure OpenAI API key to interact with hosted model.")
35
+ api_version: str = Field(default="2025-04-01-preview", description="Azure OpenAI API version.")
36
+ azure_endpoint: str | None = Field(validation_alias=AliasChoices("azure_endpoint", "base_url"),
37
+ serialization_alias="azure_endpoint",
38
+ default=None,
39
+ description="Base URL for the hosted model.")
40
+ azure_deployment: str = Field(validation_alias=AliasChoices("azure_deployment", "model_name", "model"),
41
+ serialization_alias="azure_deployment",
42
+ description="The Azure OpenAI hosted model/deployment name.")
43
+ seed: int | None = Field(default=None, description="Random seed to set for generation.")
44
+
45
+
46
+ @register_llm_provider(config_type=AzureOpenAIModelConfig)
47
+ async def azure_openai_llm(config: AzureOpenAIModelConfig, _builder: Builder):
48
+
49
+ yield LLMProviderInfo(config=config, description="An Azure OpenAI model for use with an LLM client.")
nat/llm/nim_llm.py CHANGED
@@ -23,9 +23,11 @@ from nat.builder.llm import LLMProviderInfo
23
23
  from nat.cli.register_workflow import register_llm_provider
24
24
  from nat.data_models.llm import LLMBaseConfig
25
25
  from nat.data_models.retry_mixin import RetryMixin
26
+ from nat.data_models.temperature_mixin import TemperatureMixin
27
+ from nat.data_models.top_p_mixin import TopPMixin
26
28
 
27
29
 
28
- class NIMModelConfig(LLMBaseConfig, RetryMixin, name="nim"):
30
+ class NIMModelConfig(LLMBaseConfig, RetryMixin, TemperatureMixin, TopPMixin, name="nim"):
29
31
  """An NVIDIA Inference Microservice (NIM) llm provider to be used with an LLM client."""
30
32
 
31
33
  model_config = ConfigDict(protected_namespaces=())
@@ -35,12 +37,10 @@ class NIMModelConfig(LLMBaseConfig, RetryMixin, name="nim"):
35
37
  model_name: str = Field(validation_alias=AliasChoices("model_name", "model"),
36
38
  serialization_alias="model",
37
39
  description="The model name for the hosted NIM.")
38
- temperature: float = Field(default=0.0, description="Sampling temperature in [0, 1].")
39
- top_p: float = Field(default=1.0, description="Top-p for distribution sampling.")
40
40
  max_tokens: PositiveInt = Field(default=300, description="Maximum number of tokens to generate.")
41
41
 
42
42
 
43
43
  @register_llm_provider(config_type=NIMModelConfig)
44
- async def nim_model(llm_config: NIMModelConfig, builder: Builder):
44
+ async def nim_model(llm_config: NIMModelConfig, _builder: Builder):
45
45
 
46
46
  yield LLMProviderInfo(config=llm_config, description="A NIM model for use with an LLM client.")
nat/llm/openai_llm.py CHANGED
@@ -22,9 +22,11 @@ from nat.builder.llm import LLMProviderInfo
22
22
  from nat.cli.register_workflow import register_llm_provider
23
23
  from nat.data_models.llm import LLMBaseConfig
24
24
  from nat.data_models.retry_mixin import RetryMixin
25
+ from nat.data_models.temperature_mixin import TemperatureMixin
26
+ from nat.data_models.top_p_mixin import TopPMixin
25
27
 
26
28
 
27
- class OpenAIModelConfig(LLMBaseConfig, RetryMixin, name="openai"):
29
+ class OpenAIModelConfig(LLMBaseConfig, RetryMixin, TemperatureMixin, TopPMixin, name="openai"):
28
30
  """An OpenAI LLM provider to be used with an LLM client."""
29
31
 
30
32
  model_config = ConfigDict(protected_namespaces=(), extra="allow")
@@ -34,13 +36,11 @@ class OpenAIModelConfig(LLMBaseConfig, RetryMixin, name="openai"):
34
36
  model_name: str = Field(validation_alias=AliasChoices("model_name", "model"),
35
37
  serialization_alias="model",
36
38
  description="The OpenAI hosted model name.")
37
- temperature: float = Field(default=0.0, description="Sampling temperature in [0, 1].")
38
- top_p: float = Field(default=1.0, description="Top-p for distribution sampling.")
39
39
  seed: int | None = Field(default=None, description="Random seed to set for generation.")
40
40
  max_retries: int = Field(default=10, description="The max number of retries for the request.")
41
41
 
42
42
 
43
43
  @register_llm_provider(config_type=OpenAIModelConfig)
44
- async def openai_llm(config: OpenAIModelConfig, builder: Builder):
44
+ async def openai_llm(config: OpenAIModelConfig, _builder: Builder):
45
45
 
46
46
  yield LLMProviderInfo(config=config, description="An OpenAI model for use with an LLM client.")
nat/llm/register.py CHANGED
@@ -13,11 +13,11 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # pylint: disable=unused-import
17
16
  # flake8: noqa
18
17
  # isort:skip_file
19
18
 
20
19
  # Import any providers which need to be automatically registered here
21
20
  from . import aws_bedrock_llm
21
+ from . import azure_openai_llm
22
22
  from . import nim_llm
23
23
  from . import openai_llm
@@ -72,9 +72,8 @@ class EnvConfigValue(ABC):
72
72
  f"{message} Try passing a value to the constructor, or setting the `{self.__class__._ENV_KEY}` "
73
73
  "environment variable.")
74
74
 
75
- else:
76
- if not self.__class__._ALLOW_NONE and value is None:
77
- raise ValueError("value must not be none")
75
+ elif not self.__class__._ALLOW_NONE and value is None:
76
+ raise ValueError("value must not be none")
78
77
 
79
78
  assert isinstance(value, str) or value is None
80
79
 
nat/meta/pypi.md CHANGED
@@ -23,19 +23,19 @@ NeMo Agent toolkit is a flexible library designed to seamlessly integrate your e
23
23
 
24
24
  ## Key Features
25
25
 
26
- - [**Framework Agnostic:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/extend/plugins.html) Works with any agentic framework, so you can use your current technology stack without replatforming.
27
- - [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/extend/sharing-components.html) Every agent, tool, or workflow can be combined and repurposed, allowing developers to leverage existing work in new scenarios.
28
- - [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/tutorials/index.html) Start with a pre-built agent, tool, or workflow, and customize it to your needs.
29
- - [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/workflows/profiler.html) Profile entire workflows down to the tool and agent level, track input/output tokens and timings, and identify bottlenecks.
30
- - [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/workflows/observe/observe-workflow-with-phoenix.html) Monitor and debug your workflows with any OpenTelemetry-compatible observability tool, with examples using [Phoenix](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/workflows/observe/observe-workflow-with-phoenix.html) and [W&B Weave](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/workflows/observe/observe-workflow-with-weave.html).
31
- - [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/workflows/evaluate.html) Validate and maintain accuracy of agentic workflows with built-in evaluation tools.
32
- - [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/quick-start/launching-ui.html) Use the NeMo Agent toolkit UI chat interface to interact with your agents, visualize output, and debug workflows.
33
- - [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/workflows/mcp/mcp-client.html) Compatible with Model Context Protocol (MCP), allowing tools served by MCP Servers to be used as NeMo Agent toolkit functions.
26
+ - [**Framework Agnostic:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/extend/plugins.html) Works with any agentic framework, so you can use your current technology stack without replatforming.
27
+ - [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/extend/sharing-components.html) Every agent, tool, or workflow can be combined and repurposed, allowing developers to leverage existing work in new scenarios.
28
+ - [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/tutorials/index.html) Start with a pre-built agent, tool, or workflow, and customize it to your needs.
29
+ - [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/profiler.html) Profile entire workflows down to the tool and agent level, track input/output tokens and timings, and identify bottlenecks.
30
+ - [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/observe/observe-workflow-with-phoenix.html) Monitor and debug your workflows with any OpenTelemetry-compatible observability tool, with examples using [Phoenix](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/observe/observe-workflow-with-phoenix.html) and [W&B Weave](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/observe/observe-workflow-with-weave.html).
31
+ - [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/evaluate.html) Validate and maintain accuracy of agentic workflows with built-in evaluation tools.
32
+ - [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/quick-start/launching-ui.html) Use the NeMo Agent toolkit UI chat interface to interact with your agents, visualize output, and debug workflows.
33
+ - [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.3/workflows/mcp/mcp-client.html) Compatible with Model Context Protocol (MCP), allowing tools served by MCP Servers to be used as NeMo Agent toolkit functions.
34
34
 
35
35
  With NeMo Agent toolkit, you can move quickly, experiment freely, and ensure reliability across all your agent-driven projects.
36
36
 
37
37
  ## Links
38
- * [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.2.0/index.html): Explore the full documentation for NeMo Agent toolkit.
38
+ * [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.3/index.html): Explore the full documentation for NeMo Agent toolkit.
39
39
 
40
40
  ## First time user?
41
41
  If this is your first time using NeMo Agent toolkit, it is recommended to install the latest version from the [source repository](https://github.com/NVIDIA/NeMo-Agent-Toolkit?tab=readme-ov-file#quick-start) on GitHub. This package is intended for users who are familiar with NeMo Agent toolkit applications and need to add NeMo Agent toolkit as a dependency to their project.
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  from pydantic import BaseModel
17
+ from pydantic import ConfigDict
17
18
  from pydantic import Field
18
19
 
19
20
 
@@ -30,6 +31,7 @@ class ObjectStoreItem(BaseModel):
30
31
  metadata : dict[str, str] | None
31
32
  Metadata providing context and utility for management operations.
32
33
  """
34
+ model_config = ConfigDict(ser_json_bytes="base64", val_json_bytes="base64")
33
35
 
34
36
  data: bytes = Field(description="The data to store in the object store.")
35
37
  content_type: str | None = Field(description="The content type of the data.", default=None)
@@ -13,7 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # pylint: disable=unused-import
17
16
  # flake8: noqa
18
17
  # isort:skip_file
19
18
 
@@ -357,7 +357,7 @@ class BaseExporter(Exporter):
357
357
  except Exception as e:
358
358
  logger.warning("Error while canceling task %s: %s", task.get_name(), e)
359
359
 
360
- async def _wait_for_tasks(self, timeout: float = 5.0):
360
+ async def wait_for_tasks(self, timeout: float = 5.0):
361
361
  """Wait for all tracked tasks to complete with a timeout.
362
362
 
363
363
  Note: This method is NOT called during normal stop() operation for performance.
@@ -24,7 +24,7 @@ from nat.observability.processor.intermediate_step_serializer import Intermediat
24
24
  logger = logging.getLogger(__name__)
25
25
 
26
26
 
27
- class FileExporter(FileExportMixin, RawExporter[IntermediateStep, str]): # pylint: disable=R0901
27
+ class FileExporter(FileExportMixin, RawExporter[IntermediateStep, str]):
28
28
  """A File exporter that exports telemetry traces to a local file."""
29
29
 
30
30
  def __init__(self, context_state: ContextState | None = None, **file_kwargs):
@@ -45,7 +45,7 @@ class FileTelemetryExporterConfig(TelemetryExporterBaseConfig, name="file"):
45
45
 
46
46
 
47
47
  @register_telemetry_exporter(config_type=FileTelemetryExporterConfig)
48
- async def file_telemetry_exporter(config: FileTelemetryExporterConfig, builder: Builder): # pylint: disable=W0613
48
+ async def file_telemetry_exporter(config: FileTelemetryExporterConfig, builder: Builder):
49
49
  """
50
50
  Build and return a FileExporter for file-based telemetry export with optional rolling.
51
51
  """
@@ -68,7 +68,7 @@ class ConsoleLoggingMethodConfig(LoggingBaseConfig, name="console"):
68
68
 
69
69
 
70
70
  @register_logging_method(config_type=ConsoleLoggingMethodConfig)
71
- async def console_logging_method(config: ConsoleLoggingMethodConfig, builder: Builder): # pylint: disable=W0613
71
+ async def console_logging_method(config: ConsoleLoggingMethodConfig, builder: Builder):
72
72
  """
73
73
  Build and return a StreamHandler for console-based logging.
74
74
  """
@@ -86,7 +86,7 @@ class FileLoggingMethod(LoggingBaseConfig, name="file"):
86
86
 
87
87
 
88
88
  @register_logging_method(config_type=FileLoggingMethod)
89
- async def file_logging_method(config: FileLoggingMethod, builder: Builder): # pylint: disable=W0613
89
+ async def file_logging_method(config: FileLoggingMethod, builder: Builder):
90
90
  """
91
91
  Build and return a FileHandler for file-based logging.
92
92
  """
@@ -53,7 +53,7 @@ def _extract_tools_schema(invocation_params: dict) -> list:
53
53
  return tools_schema
54
54
 
55
55
 
56
- class LangchainProfilerHandler(AsyncCallbackHandler, BaseProfilerCallback): # pylint: disable=R0901
56
+ class LangchainProfilerHandler(AsyncCallbackHandler, BaseProfilerCallback):
57
57
  """Callback Handler that tracks NIM info."""
58
58
 
59
59
  total_tokens: int = 0
@@ -223,7 +223,14 @@ class LangchainProfilerHandler(AsyncCallbackHandler, BaseProfilerCallback): # p
223
223
  except AttributeError:
224
224
  usage_metadata = {}
225
225
 
226
- llm_text_output = generation.message.content if generation else ""
226
+ if generation:
227
+ llm_text_output = generation.message.content
228
+ if "tool_calls" in generation.message.additional_kwargs:
229
+ # add tool calls if included in the output
230
+ tool_calls = generation.message.additional_kwargs['tool_calls']
231
+ llm_text_output = f"{llm_text_output}\n\nTool calls: {tool_calls}"
232
+ else:
233
+ llm_text_output = ""
227
234
 
228
235
  # update shared state behind lock
229
236
  with self._lock:
@@ -86,7 +86,7 @@ class SemanticKernelProfilerHandler(BaseProfilerCallback):
86
86
 
87
87
  # Gather the appropriate modules/functions based on your builder config
88
88
  for llm in self._builder_llms:
89
- if self._builder_llms[llm].provider_type == 'openai': # pylint: disable=consider-using-in
89
+ if self._builder_llms[llm].provider_type == 'openai':
90
90
  functions_to_patch.extend(["openai_non_streaming", "openai_streaming"])
91
91
 
92
92
  # Grab original reference for the tool call
@@ -42,7 +42,7 @@ class DataFrameRow(BaseModel):
42
42
  framework: str | None
43
43
 
44
44
  @field_validator('llm_text_input', 'llm_text_output', 'llm_new_token', mode='before')
45
- def cast_to_str(cls, v): # pylint: disable=no-self-argument
45
+ def cast_to_str(cls, v):
46
46
  if v is None:
47
47
  return v
48
48
  try:
@@ -13,8 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # pylint disable=ungrouped-imports
17
-
18
16
  from __future__ import annotations
19
17
 
20
18
  import functools
@@ -75,8 +73,7 @@ def set_framework_profiler_handler(
75
73
  logger.debug("LlamaIndex callback handler registered")
76
74
 
77
75
  if LLMFrameworkEnum.CREWAI in frameworks and not _library_instrumented["crewai"]:
78
- from nat.plugins.crewai.crewai_callback_handler import \
79
- CrewAIProfilerHandler # pylint: disable=ungrouped-imports,line-too-long # noqa E501
76
+ from nat.plugins.crewai.crewai_callback_handler import CrewAIProfilerHandler
80
77
 
81
78
  handler = CrewAIProfilerHandler()
82
79
  handler.instrument()
@@ -15,7 +15,9 @@
15
15
 
16
16
  # forecasting/models/base_model.py
17
17
 
18
- from abc import ABC, abstractmethod
18
+ from abc import ABC
19
+ from abc import abstractmethod
20
+
19
21
  import numpy as np
20
22
 
21
23
 
@@ -195,7 +195,7 @@ def profile_workflow_bottlenecks(all_steps: list[list[IntermediateStep]]) -> Sim
195
195
  c_max = 0
196
196
  for ts, delta in events_sub:
197
197
  c_curr += delta
198
- if c_curr > c_max: # pylint: disable=consider-using-max-builtin
198
+ if c_curr > c_max: # noqa: PLR1730 - don't use max built-in
199
199
  c_max = c_curr
200
200
  max_concurrency_by_name[op_name] = c_max
201
201
 
@@ -172,7 +172,7 @@ class CallNode(BaseModel):
172
172
  if not self.children:
173
173
  return self.duration
174
174
 
175
- intervals = [(c.start_time, c.end_time) for c in self.children] # pylint: disable=not-an-iterable
175
+ intervals = [(c.start_time, c.end_time) for c in self.children]
176
176
  # Sort by start time
177
177
  intervals.sort(key=lambda x: x[0])
178
178
 
@@ -204,7 +204,7 @@ class CallNode(BaseModel):
204
204
  This ensures no overlap double-counting among children.
205
205
  """
206
206
  total = self.compute_self_time()
207
- for c in self.children: # pylint: disable=not-an-iterable
207
+ for c in self.children:
208
208
  total += c.compute_subtree_time()
209
209
  return total
210
210
 
@@ -216,7 +216,7 @@ class CallNode(BaseModel):
216
216
  info = (f"{indent}- {self.operation_type} '{self.operation_name}' "
217
217
  f"(uuid={self.uuid}, start={self.start_time:.2f}, "
218
218
  f"end={self.end_time:.2f}, dur={self.duration:.2f})")
219
- child_strs = [child._repr(level + 1) for child in self.children] # pylint: disable=not-an-iterable
219
+ child_strs = [child._repr(level + 1) for child in self.children]
220
220
  return "\n".join([info] + child_strs)
221
221
 
222
222
 
@@ -228,7 +228,7 @@ def run_prefixspan(sequences_map: dict[int, list[PrefixCallNode]],
228
228
  else:
229
229
  abs_min_support = min_support
230
230
 
231
- freq_patterns = ps.frequent(abs_min_support) # pylint: disable=not-callable
231
+ freq_patterns = ps.frequent(abs_min_support)
232
232
  # freq_patterns => [(count, [item1, item2, ...])]
233
233
 
234
234
  results = []
@@ -321,13 +321,12 @@ def compute_coverage_and_duration(sequences_map: dict[int, list[PrefixCallNode]]
321
321
  # --------------------------------------------------------------------------------
322
322
 
323
323
 
324
- def prefixspan_subworkflow_with_text( # pylint: disable=too-many-positional-arguments
325
- all_steps: list[list[IntermediateStep]],
326
- min_support: int | float = 2,
327
- top_k: int = 10,
328
- min_coverage: float = 0.0,
329
- max_text_len: int = 700,
330
- prefix_list: list[str] = None) -> PrefixSpanSubworkflowResult:
324
+ def prefixspan_subworkflow_with_text(all_steps: list[list[IntermediateStep]],
325
+ min_support: int | float = 2,
326
+ top_k: int = 10,
327
+ min_coverage: float = 0.0,
328
+ max_text_len: int = 700,
329
+ prefix_list: list[str] = None) -> PrefixSpanSubworkflowResult:
331
330
  """
332
331
  1) Build sequences of calls for each example (with llm_text_input).
333
332
  2) Convert to token lists, run PrefixSpan with min_support.
@@ -66,7 +66,7 @@ def compute_inter_query_token_uniqueness_by_llm(all_steps: list[list[Intermediat
66
66
  # 2) Group by (llm_name, example_number), then sort each group
67
67
  grouped = cdf.groupby(['llm_name', 'example_number'], as_index=False, group_keys=True)
68
68
 
69
- for (llm, ex_num), group_df in grouped: # pylint: disable=unused-variable
69
+ for (llm, ex_num), group_df in grouped:
70
70
  # Sort by event_timestamp
71
71
  group_df = group_df.sort_values('event_timestamp', ascending=True)
72
72
 
@@ -88,14 +88,19 @@ class ProfilerRunner:
88
88
  writes out combined requests JSON, then computes and saves additional metrics,
89
89
  and optionally fits a forecasting model.
90
90
  """
91
- from nat.profiler.inference_optimization.bottleneck_analysis.nested_stack_analysis import \
92
- multi_example_call_profiling
93
- from nat.profiler.inference_optimization.bottleneck_analysis.simple_stack_analysis import \
94
- profile_workflow_bottlenecks
95
- from nat.profiler.inference_optimization.experimental.concurrency_spike_analysis import \
96
- concurrency_spike_analysis
97
- from nat.profiler.inference_optimization.experimental.prefix_span_analysis import \
98
- prefixspan_subworkflow_with_text
91
+ # Yapf and ruff disagree on how to format long imports, disable yapf go with ruff
92
+ from nat.profiler.inference_optimization.bottleneck_analysis.nested_stack_analysis import (
93
+ multi_example_call_profiling,
94
+ ) # yapf: disable
95
+ from nat.profiler.inference_optimization.bottleneck_analysis.simple_stack_analysis import (
96
+ profile_workflow_bottlenecks,
97
+ ) # yapf: disable
98
+ from nat.profiler.inference_optimization.experimental.concurrency_spike_analysis import (
99
+ concurrency_spike_analysis,
100
+ ) # yapf: disable
101
+ from nat.profiler.inference_optimization.experimental.prefix_span_analysis import (
102
+ prefixspan_subworkflow_with_text,
103
+ ) # yapf: disable
99
104
  from nat.profiler.inference_optimization.llm_metrics import LLMMetrics
100
105
  from nat.profiler.inference_optimization.prompt_caching import get_common_prefixes
101
106
  from nat.profiler.inference_optimization.token_uniqueness import compute_inter_query_token_uniqueness_by_llm
@@ -29,7 +29,6 @@ from nat.registry_handlers.schemas.publish import Artifact
29
29
  from nat.runtime.loader import PluginTypes
30
30
  from nat.runtime.loader import discover_entrypoints
31
31
 
32
- # pylint: disable=redefined-outer-name
33
32
  logger = logging.getLogger(__name__)
34
33
 
35
34
 
@@ -44,13 +44,12 @@ class PypiRegistryHandler(AbstractRegistryHandler):
44
44
  https://github.com/pypiserver/pypiserver
45
45
  """
46
46
 
47
- def __init__( # pylint: disable=R0917
48
- self,
49
- endpoint: str,
50
- token: str | None = None,
51
- publish_route: str = "",
52
- pull_route: str = "",
53
- search_route: str = ""):
47
+ def __init__(self,
48
+ endpoint: str,
49
+ token: str | None = None,
50
+ publish_route: str = "",
51
+ pull_route: str = "",
52
+ search_route: str = ""):
54
53
  super().__init__()
55
54
  self._endpoint = endpoint.rstrip("/")
56
55
  self._token = token
@@ -126,17 +125,16 @@ class PypiRegistryHandler(AbstractRegistryHandler):
126
125
 
127
126
  versioned_packages_str = " ".join(versioned_packages)
128
127
 
129
- result = subprocess.run(
130
- [
131
- "uv",
132
- "pip",
133
- "install",
134
- "--prerelease=allow",
135
- "--index-url",
136
- f"{self._endpoint}/{self._pull_route}/",
137
- versioned_packages_str
138
- ], # pylint: disable=W0631
139
- check=True)
128
+ result = subprocess.run([
129
+ "uv",
130
+ "pip",
131
+ "install",
132
+ "--prerelease=allow",
133
+ "--index-url",
134
+ f"{self._endpoint}/{self._pull_route}/",
135
+ versioned_packages_str
136
+ ],
137
+ check=True)
140
138
 
141
139
  result.check_returncode()
142
140
 
@@ -171,11 +169,10 @@ class PypiRegistryHandler(AbstractRegistryHandler):
171
169
  """
172
170
 
173
171
  try:
174
- completed_process = subprocess.run(
175
- ["pip", "search", "--index", f"{self._endpoint}", query.query], # pylint: disable=W0631
176
- text=True,
177
- capture_output=True,
178
- check=True)
172
+ completed_process = subprocess.run(["pip", "search", "--index", f"{self._endpoint}", query.query],
173
+ text=True,
174
+ capture_output=True,
175
+ check=True)
179
176
  search_response_list = []
180
177
  search_results = completed_process.stdout
181
178
  package_results = search_results.split("\n")
@@ -13,9 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # pylint: disable=unused-import
17
16
  # flake8: noqa
18
17
 
19
- from .local import register_local # pylint: disable=E0611
20
- from .pypi import register_pypi # pylint: disable=E0611
21
- from .rest import register_rest # pylint: disable=E0611
18
+ from .local import register_local
19
+ from .pypi import register_pypi
20
+ from .rest import register_rest
@@ -42,15 +42,14 @@ logger = logging.getLogger(__name__)
42
42
  class RestRegistryHandler(AbstractRegistryHandler):
43
43
  """A registry handler for interactions with a remote REST registry."""
44
44
 
45
- def __init__( # pylint: disable=R0917
46
- self,
47
- endpoint: str,
48
- token: str,
49
- timeout: int = 30,
50
- publish_route: str = "",
51
- pull_route: str = "",
52
- search_route: str = "",
53
- remove_route: str = ""):
45
+ def __init__(self,
46
+ endpoint: str,
47
+ token: str,
48
+ timeout: int = 30,
49
+ publish_route: str = "",
50
+ pull_route: str = "",
51
+ search_route: str = "",
52
+ remove_route: str = ""):
54
53
  super().__init__()
55
54
  self._endpoint = endpoint.rstrip("/")
56
55
  self._timeout = timeout
nat/retriever/register.py CHANGED
@@ -13,7 +13,6 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- # pylint: disable=unused-import
17
16
  # flake8: noqa
18
17
  # isort:skip_file
19
18