nvidia-nat-adk 1.3.0a20250925__py3-none-any.whl → 1.3.0a20250928__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.
@@ -12,9 +12,3 @@
12
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
-
16
- # pylint: disable=unused-import
17
- # flake8: noqa
18
- # isort:skip_file
19
-
20
- # Import any providers which need to be automatically registered here
@@ -20,8 +20,6 @@ import time
20
20
  from collections.abc import Callable
21
21
  from typing import Any
22
22
 
23
- import litellm
24
-
25
23
  from nat.builder.context import Context
26
24
  from nat.builder.framework_enum import LLMFrameworkEnum
27
25
  from nat.data_models.intermediate_step import IntermediateStepPayload
@@ -60,6 +58,7 @@ class ADKProfilerHandler(BaseProfilerCallback):
60
58
  Monkey-patch the relevant Google ADK methods with usage-stat collection logic.
61
59
  Assumes the 'google-adk' library is installed.
62
60
  """
61
+ import litellm
63
62
 
64
63
  if getattr(self, "_instrumented", False):
65
64
  logger.debug("ADKProfilerHandler already instrumented; skipping.")
@@ -89,6 +88,7 @@ class ADKProfilerHandler(BaseProfilerCallback):
89
88
  Add an explicit unpatch to avoid side-effects across tests/process lifetime.
90
89
  """
91
90
  try:
91
+ import litellm
92
92
  from google.adk.tools.function_tool import FunctionTool
93
93
  if self._original_tool_call:
94
94
  FunctionTool.run_async = self._original_tool_call
@@ -140,12 +140,17 @@ class ADKProfilerHandler(BaseProfilerCallback):
140
140
  usage_info=UsageInfo(token_usage=TokenUsageBaseModel()),
141
141
  )
142
142
 
143
+ # Store the UUID to ensure the END event uses the same ID
144
+ step_uuid = stats.UUID
143
145
  self.step_manager.push_intermediate_step(stats)
144
146
 
145
147
  with self._lock:
146
148
  self.last_call_ts = now
147
149
 
148
150
  # Call the original _use(...)
151
+ if original_func is None:
152
+ raise RuntimeError(
153
+ "Original tool function is None - instrumentation may not have been set up correctly")
149
154
  result = await original_func(base_tool_instance, *args, **kwargs)
150
155
  now = time.time()
151
156
  # Post-call usage stats - safely extract kwargs args if present
@@ -163,6 +168,7 @@ class ADKProfilerHandler(BaseProfilerCallback):
163
168
  ),
164
169
  metadata=TraceMetadata(tool_outputs={"result": str(result)}),
165
170
  usage_info=UsageInfo(token_usage=TokenUsageBaseModel()),
171
+ UUID=step_uuid, # Use the same UUID as the START event
166
172
  )
167
173
 
168
174
  self.step_manager.push_intermediate_step(usage_stat)
@@ -236,9 +242,13 @@ class ADKProfilerHandler(BaseProfilerCallback):
236
242
  ),
237
243
  )
238
244
 
245
+ # Store the UUID to ensure the END event uses the same ID
246
+ step_uuid = input_stats.UUID
239
247
  self.step_manager.push_intermediate_step(input_stats)
240
248
 
241
249
  # Call the original litellm.acompletion(...)
250
+ if original_func is None:
251
+ raise RuntimeError("Original LLM function is None - instrumentation may not have been set up correctly")
242
252
  output = await original_func(*args, **kwargs)
243
253
 
244
254
  model_output = ""
@@ -284,6 +294,7 @@ class ADKProfilerHandler(BaseProfilerCallback):
284
294
  num_llm_calls=1,
285
295
  seconds_between_calls=seconds_between_calls,
286
296
  ),
297
+ UUID=step_uuid, # Use the same UUID as the START event
287
298
  )
288
299
 
289
300
  self.step_manager.push_intermediate_step(output_stats)
@@ -0,0 +1,113 @@
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
+
18
+ from pydantic import Field
19
+
20
+ from nat.builder.builder import Builder
21
+ from nat.builder.framework_enum import LLMFrameworkEnum
22
+ from nat.builder.function_info import FunctionInfo
23
+ from nat.cli.register_workflow import register_function
24
+ from nat.data_models.component_ref import LLMRef
25
+ from nat.data_models.function import FunctionBaseConfig
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ class ADKFunctionConfig(FunctionBaseConfig, name="adk"):
31
+ """Configuration for ADK demo function."""
32
+ name: str = Field(default="nat-adk-agent")
33
+ description: str
34
+ prompt: str
35
+ llm: LLMRef
36
+ tool_names: list[str] = Field(default_factory=list)
37
+ workflow_alias: str = Field(default="adk_agent")
38
+ user_id: str = Field(default="nat")
39
+
40
+
41
+ @register_function(config_type=ADKFunctionConfig, framework_wrappers=[LLMFrameworkEnum.ADK])
42
+ async def adk_agent(config: ADKFunctionConfig, builder: Builder):
43
+ """An example function that demonstrates how to use the Google ADK framework with NAT.
44
+
45
+ Args:
46
+ config (ADKFunctionConfig): The configuration for the ADK agent function.
47
+ builder (Builder): The NAT builder instance.
48
+ """
49
+ import logging
50
+
51
+ from google.adk import Runner
52
+ from google.adk.agents import Agent
53
+ from google.adk.artifacts import InMemoryArtifactService
54
+ from google.adk.sessions import InMemorySessionService
55
+ from google.genai import types
56
+
57
+ logging.getLogger("LiteLLM").setLevel(logging.WARNING)
58
+
59
+ model = await builder.get_llm(config.llm, wrapper_type=LLMFrameworkEnum.ADK)
60
+ tools = await builder.get_tools(config.tool_names, wrapper_type=LLMFrameworkEnum.ADK)
61
+
62
+ agent = Agent(
63
+ name=config.name,
64
+ model=model,
65
+ description=config.description,
66
+ instruction=config.prompt,
67
+ tools=tools,
68
+ )
69
+
70
+ # Initialize the Runner with the agent and services
71
+ session_service = InMemorySessionService()
72
+ artifact_service = InMemoryArtifactService()
73
+ runner = Runner(app_name=config.name,
74
+ agent=agent,
75
+ artifact_service=artifact_service,
76
+ session_service=session_service)
77
+ session = await session_service.create_session(app_name=config.name, user_id=config.user_id)
78
+
79
+ async def _response_fn(input_message: str) -> str:
80
+ """Wrapper for response fn
81
+
82
+ Args:
83
+ input_message (str): The input message from the user.
84
+ Returns:
85
+ str : The response from the agent.
86
+ """
87
+
88
+ async def run_prompt(new_message: str) -> str:
89
+ """Run prompt through the agent.
90
+
91
+ Args:
92
+ new_message (str): The input message from the user.
93
+ Returns:
94
+ str: The response from the agent.
95
+ """
96
+ content = types.Content(role="user", parts=[types.Part.from_text(text=new_message)])
97
+ text_buf: list[str] = []
98
+ async for event in runner.run_async(user_id=config.user_id, session_id=session.id, new_message=content):
99
+ if event.content is None:
100
+ continue
101
+ if event.content.parts is None:
102
+ continue
103
+ text_buf.extend(part.text for part in event.content.parts if part.text is not None)
104
+ return "".join(text_buf) if text_buf else ""
105
+
106
+ return await run_prompt(input_message)
107
+
108
+ try:
109
+ yield FunctionInfo.create(single_fn=_response_fn, description=config.description)
110
+ except GeneratorExit:
111
+ logger.debug("Exited early!", exc_info=True)
112
+ finally:
113
+ logger.debug("Cleaning up")
nat/plugins/adk/llm.py CHANGED
@@ -13,38 +13,96 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from collections.abc import AsyncIterator
16
+ import logging
17
+ import os
17
18
 
18
19
  from nat.builder.builder import Builder
19
20
  from nat.builder.framework_enum import LLMFrameworkEnum
20
21
  from nat.cli.register_workflow import register_llm_client
22
+ from nat.llm.azure_openai_llm import AzureOpenAIModelConfig
21
23
  from nat.llm.litellm_llm import LiteLlmModelConfig
24
+ from nat.llm.nim_llm import NIMModelConfig
25
+ from nat.llm.openai_llm import OpenAIModelConfig
22
26
 
27
+ logger = logging.getLogger(__name__)
23
28
 
24
- @register_llm_client(config_type=LiteLlmModelConfig, wrapper_type=LLMFrameworkEnum.ADK)
25
- async def litellm_adk(
26
- litellm_config: LiteLlmModelConfig,
27
- _builder: Builder, # pylint: disable=W0613 (_builder not used)
28
- ) -> AsyncIterator["LiteLlm"]: # type: ignore # noqa: F821 (forward reference of LiteLlm)
29
- """Create and yield a Google ADK `LiteLlm` client from a NAT `LiteLlmModelConfig`.
29
+
30
+ @register_llm_client(config_type=AzureOpenAIModelConfig, wrapper_type=LLMFrameworkEnum.ADK)
31
+ async def azure_openai_adk(config: AzureOpenAIModelConfig, _builder: Builder):
32
+ """Create and yield a Google ADK `AzureOpenAI` client from a NAT `AzureOpenAIModelConfig`.
30
33
 
31
34
  Args:
32
- litellm_config (LiteLlmModelConfig): The configuration for the LiteLlm model.
35
+ config (AzureOpenAIModelConfig): The configuration for the AzureOpenAI model.
33
36
  _builder (Builder): The NAT builder instance.
34
-
35
- Yields:
36
- AsyncIterator[LiteLlm]: An async iterator that yields a LiteLlm client.
37
37
  """
38
+ from google.adk.models.lite_llm import LiteLlm
39
+
40
+ config_dict = config.model_dump(
41
+ exclude={"type", "max_retries", "thinking", "azure_endpoint", "azure_deployment", "model_name", "model"},
42
+ by_alias=True,
43
+ exclude_none=True,
44
+ )
45
+ if config.azure_endpoint:
46
+ config_dict["api_base"] = config.azure_endpoint
38
47
 
39
- try:
40
- from google.adk.models.lite_llm import LiteLlm
41
- except ModuleNotFoundError as e:
42
- raise ModuleNotFoundError("Google ADK not installed; pip install google-adk") from e
48
+ yield LiteLlm(f"azure/{config.azure_deployment}", **config_dict)
43
49
 
44
- llm = LiteLlm(**litellm_config.model_dump(
45
- exclude={"type", "max_retries"},
50
+
51
+ @register_llm_client(config_type=LiteLlmModelConfig, wrapper_type=LLMFrameworkEnum.ADK)
52
+ async def litellm_adk(litellm_config: LiteLlmModelConfig, _builder: Builder):
53
+ from google.adk.models.lite_llm import LiteLlm
54
+ yield LiteLlm(**litellm_config.model_dump(
55
+ exclude={"type", "max_retries", "thinking"},
46
56
  by_alias=True,
47
57
  exclude_none=True,
48
58
  ))
49
59
 
50
- yield llm
60
+
61
+ @register_llm_client(config_type=NIMModelConfig, wrapper_type=LLMFrameworkEnum.ADK)
62
+ async def nim_adk(config: NIMModelConfig, _builder: Builder):
63
+ """Create and yield a Google ADK `NIM` client from a NAT `NIMModelConfig`.
64
+
65
+ Args:
66
+ config (NIMModelConfig): The configuration for the NIM model.
67
+ _builder (Builder): The NAT builder instance.
68
+ """
69
+ import litellm
70
+ from google.adk.models.lite_llm import LiteLlm
71
+
72
+ logger.warning("NIMs do not currently support tools with ADK. Tools will be ignored.")
73
+ litellm.add_function_to_prompt = True
74
+ litellm.drop_params = True
75
+
76
+ if (api_key := os.getenv("NVIDIA_API_KEY", None)) is not None:
77
+ os.environ["NVIDIA_NIM_API_KEY"] = api_key
78
+
79
+ config_dict = config.model_dump(
80
+ exclude={"type", "max_retries", "thinking", "model_name", "model", "base_url"},
81
+ by_alias=True,
82
+ exclude_none=True,
83
+ )
84
+ if config.base_url:
85
+ config_dict["api_base"] = config.base_url
86
+
87
+ yield LiteLlm(f"nvidia_nim/{config.model_name}", **config_dict)
88
+
89
+
90
+ @register_llm_client(config_type=OpenAIModelConfig, wrapper_type=LLMFrameworkEnum.ADK)
91
+ async def openai_adk(config: OpenAIModelConfig, _builder: Builder):
92
+ """Create and yield a Google ADK `OpenAI` client from a NAT `OpenAIModelConfig`.
93
+
94
+ Args:
95
+ config (OpenAIModelConfig): The configuration for the OpenAI model.
96
+ _builder (Builder): The NAT builder instance.
97
+ """
98
+ from google.adk.models.lite_llm import LiteLlm
99
+
100
+ config_dict = config.model_dump(
101
+ exclude={"type", "max_retries", "thinking", "model_name", "model", "base_url"},
102
+ by_alias=True,
103
+ exclude_none=True,
104
+ )
105
+ if config.base_url:
106
+ config_dict["api_base"] = config.base_url
107
+
108
+ yield LiteLlm(config.model_name, **config_dict)
@@ -15,11 +15,8 @@
15
15
 
16
16
  # pylint: disable=unused-import
17
17
  # flake8: noqa
18
- # isort:skip_file
19
- # Auto-registration module: importing submodules triggers provider registration via side effects.
20
- """Register ADK providers via import side-effects (loaded from the `nat_adk` entry point)."""
21
18
 
22
- # Import any providers which need to be automatically registered here
23
-
24
- from . import llm # pylint: disable=unused-import # imported for side effects (registration)
25
- from . import tool_wrapper # pylint: disable=unused-import # imported for side effects (registration)
19
+ from . import adk_callback_handler
20
+ from . import agent
21
+ from . import llm
22
+ from . import tool_wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvidia-nat-adk
3
- Version: 1.3.0a20250925
3
+ Version: 1.3.0a20250928
4
4
  Summary: Subpackage for Google ADK integration in NeMo Agent Toolkit
5
5
  Keywords: ai,rag,agents
6
6
  Classifier: Programming Language :: Python
@@ -9,9 +9,8 @@ Classifier: Programming Language :: Python :: 3.12
9
9
  Classifier: Programming Language :: Python :: 3.13
10
10
  Requires-Python: <3.14,>=3.11
11
11
  Description-Content-Type: text/markdown
12
- Requires-Dist: nvidia-nat==v1.3.0a20250925
13
- Requires-Dist: google-adk~=1.6
14
- Requires-Dist: litellm<1.74,>=1.63
12
+ Requires-Dist: nvidia-nat[litellm]==v1.3.0a20250928
13
+ Requires-Dist: google-adk~=1.14.1
15
14
 
16
15
  <!--
17
16
  SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
@@ -0,0 +1,12 @@
1
+ nat/meta/pypi.md,sha256=AOSYTEk4JQQeaQQ1fA7v__j9-5rchBPvvSAICORgttE,953
2
+ nat/plugins/adk/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
3
+ nat/plugins/adk/adk_callback_handler.py,sha256=mJIeyREdqlDCwIuvudT5FaEyMqioISqjBRPFUGJoLGA,12561
4
+ nat/plugins/adk/agent.py,sha256=9EpPSocb9OdPX9p5I7nrfe11L1ldhdOk7v09NMVcHNw,4270
5
+ nat/plugins/adk/llm.py,sha256=glwlO9UQhfGagVDNbtw-bNQ7FVdJfs31v6rqd-MBJLY,4120
6
+ nat/plugins/adk/register.py,sha256=9EEYSA9CFkPiEwVX-FB5Ho16wzaFsyO0hiiOUJFmaiM,829
7
+ nat/plugins/adk/tool_wrapper.py,sha256=TroOo7tM6I3gOqMxOL7fQmPsyVKlntPPRNbYQMk6JHs,5779
8
+ nvidia_nat_adk-1.3.0a20250928.dist-info/METADATA,sha256=oCtgyABZx7WyXDap2J04RZ4c6-RRYJ4Q1P02KezLVlQ,1466
9
+ nvidia_nat_adk-1.3.0a20250928.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
+ nvidia_nat_adk-1.3.0a20250928.dist-info/entry_points.txt,sha256=K1K0clA1uqXk1Q0dh8ZaWNQyveaFx_XvgBWzCyGMYts,52
11
+ nvidia_nat_adk-1.3.0a20250928.dist-info/top_level.txt,sha256=8-CJ2cP6-f0ZReXe5Hzqp-5pvzzHz-5Ds5H2bGqh1-U,4
12
+ nvidia_nat_adk-1.3.0a20250928.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- nat/meta/pypi.md,sha256=AOSYTEk4JQQeaQQ1fA7v__j9-5rchBPvvSAICORgttE,953
2
- nat/plugins/adk/__init__.py,sha256=bcb2ATld-lJ85wuXZWznP79-jfVZQp6SLwvSrt_vExU,817
3
- nat/plugins/adk/adk_callback_handler.py,sha256=cZb2-CRKGKX9RMtveG5oYFQCDPMj43jxIdi3LgXEPYw,11803
4
- nat/plugins/adk/llm.py,sha256=91zMW14t80tl-tMAmq-zzirPYBMnXaiv3dtCOLjMXr4,1936
5
- nat/plugins/adk/register.py,sha256=-H9gEfqRRBUINJx1zvZiLc06oY2aXu-y1lcKxrF67Ts,1209
6
- nat/plugins/adk/tool_wrapper.py,sha256=TroOo7tM6I3gOqMxOL7fQmPsyVKlntPPRNbYQMk6JHs,5779
7
- nvidia_nat_adk-1.3.0a20250925.dist-info/METADATA,sha256=fBPVYAuCRt_iJLFdfaZdEvrSrA-AbhnzZamvjv5FvZk,1489
8
- nvidia_nat_adk-1.3.0a20250925.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
- nvidia_nat_adk-1.3.0a20250925.dist-info/entry_points.txt,sha256=K1K0clA1uqXk1Q0dh8ZaWNQyveaFx_XvgBWzCyGMYts,52
10
- nvidia_nat_adk-1.3.0a20250925.dist-info/top_level.txt,sha256=8-CJ2cP6-f0ZReXe5Hzqp-5pvzzHz-5Ds5H2bGqh1-U,4
11
- nvidia_nat_adk-1.3.0a20250925.dist-info/RECORD,,