nvidia-nat 1.3.0.dev2__py3-none-any.whl → 1.3.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiq/__init__.py +2 -2
- nat/agent/base.py +24 -15
- nat/agent/dual_node.py +9 -4
- nat/agent/prompt_optimizer/prompt.py +68 -0
- nat/agent/prompt_optimizer/register.py +149 -0
- nat/agent/react_agent/agent.py +79 -47
- nat/agent/react_agent/register.py +41 -21
- nat/agent/reasoning_agent/reasoning_agent.py +11 -9
- nat/agent/register.py +1 -1
- nat/agent/rewoo_agent/agent.py +326 -148
- nat/agent/rewoo_agent/prompt.py +19 -22
- nat/agent/rewoo_agent/register.py +46 -26
- nat/agent/tool_calling_agent/agent.py +84 -28
- nat/agent/tool_calling_agent/register.py +51 -28
- nat/authentication/api_key/api_key_auth_provider.py +2 -2
- nat/authentication/credential_validator/bearer_token_validator.py +557 -0
- nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
- nat/authentication/interfaces.py +5 -2
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +40 -20
- nat/authentication/oauth2/oauth2_resource_server_config.py +124 -0
- nat/authentication/register.py +0 -1
- nat/builder/builder.py +56 -24
- nat/builder/component_utils.py +9 -5
- nat/builder/context.py +46 -11
- nat/builder/eval_builder.py +16 -11
- nat/builder/framework_enum.py +1 -0
- nat/builder/front_end.py +1 -1
- nat/builder/function.py +378 -8
- nat/builder/function_base.py +3 -3
- nat/builder/function_info.py +6 -8
- nat/builder/user_interaction_manager.py +2 -2
- nat/builder/workflow.py +13 -1
- nat/builder/workflow_builder.py +281 -76
- nat/cli/cli_utils/config_override.py +2 -2
- nat/cli/commands/evaluate.py +1 -1
- nat/cli/commands/info/info.py +16 -6
- nat/cli/commands/info/list_channels.py +1 -1
- nat/cli/commands/info/list_components.py +7 -8
- nat/cli/commands/mcp/__init__.py +14 -0
- nat/cli/commands/mcp/mcp.py +986 -0
- nat/cli/commands/object_store/__init__.py +14 -0
- nat/cli/commands/object_store/object_store.py +227 -0
- nat/cli/commands/optimize.py +90 -0
- nat/cli/commands/registry/publish.py +2 -2
- nat/cli/commands/registry/pull.py +2 -2
- nat/cli/commands/registry/remove.py +2 -2
- nat/cli/commands/registry/search.py +15 -17
- nat/cli/commands/start.py +16 -5
- nat/cli/commands/uninstall.py +1 -1
- nat/cli/commands/workflow/templates/config.yml.j2 +0 -1
- nat/cli/commands/workflow/templates/pyproject.toml.j2 +4 -1
- nat/cli/commands/workflow/templates/register.py.j2 +0 -1
- nat/cli/commands/workflow/workflow_commands.py +9 -13
- nat/cli/entrypoint.py +8 -10
- nat/cli/register_workflow.py +38 -4
- nat/cli/type_registry.py +75 -6
- nat/control_flow/__init__.py +0 -0
- nat/control_flow/register.py +20 -0
- nat/control_flow/router_agent/__init__.py +0 -0
- nat/control_flow/router_agent/agent.py +329 -0
- nat/control_flow/router_agent/prompt.py +48 -0
- nat/control_flow/router_agent/register.py +91 -0
- nat/control_flow/sequential_executor.py +166 -0
- nat/data_models/agent.py +34 -0
- nat/data_models/api_server.py +10 -10
- nat/data_models/authentication.py +23 -9
- nat/data_models/common.py +1 -1
- nat/data_models/component.py +2 -0
- nat/data_models/component_ref.py +11 -0
- nat/data_models/config.py +41 -17
- nat/data_models/dataset_handler.py +1 -1
- nat/data_models/discovery_metadata.py +4 -4
- nat/data_models/evaluate.py +4 -1
- nat/data_models/function.py +34 -0
- nat/data_models/function_dependencies.py +14 -6
- nat/data_models/gated_field_mixin.py +242 -0
- nat/data_models/intermediate_step.py +3 -3
- nat/data_models/optimizable.py +119 -0
- nat/data_models/optimizer.py +149 -0
- nat/data_models/swe_bench_model.py +1 -1
- nat/data_models/temperature_mixin.py +44 -0
- nat/data_models/thinking_mixin.py +86 -0
- nat/data_models/top_p_mixin.py +44 -0
- nat/embedder/nim_embedder.py +1 -1
- nat/embedder/openai_embedder.py +1 -1
- nat/embedder/register.py +0 -1
- nat/eval/config.py +3 -1
- nat/eval/dataset_handler/dataset_handler.py +71 -7
- nat/eval/evaluate.py +86 -31
- nat/eval/evaluator/base_evaluator.py +1 -1
- nat/eval/evaluator/evaluator_model.py +13 -0
- nat/eval/intermediate_step_adapter.py +1 -1
- nat/eval/rag_evaluator/evaluate.py +2 -2
- nat/eval/rag_evaluator/register.py +3 -3
- nat/eval/register.py +4 -1
- nat/eval/remote_workflow.py +3 -3
- nat/eval/runtime_evaluator/__init__.py +14 -0
- nat/eval/runtime_evaluator/evaluate.py +123 -0
- nat/eval/runtime_evaluator/register.py +100 -0
- nat/eval/swe_bench_evaluator/evaluate.py +6 -6
- nat/eval/trajectory_evaluator/evaluate.py +1 -1
- nat/eval/trajectory_evaluator/register.py +1 -1
- nat/eval/tunable_rag_evaluator/evaluate.py +4 -7
- nat/eval/utils/eval_trace_ctx.py +89 -0
- nat/eval/utils/weave_eval.py +18 -9
- nat/experimental/decorators/experimental_warning_decorator.py +27 -7
- nat/experimental/test_time_compute/functions/plan_select_execute_function.py +7 -3
- nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +3 -3
- nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
- nat/experimental/test_time_compute/models/strategy_base.py +5 -4
- nat/experimental/test_time_compute/register.py +0 -1
- nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -3
- nat/front_ends/console/authentication_flow_handler.py +82 -30
- nat/front_ends/console/console_front_end_plugin.py +8 -5
- nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +52 -17
- nat/front_ends/fastapi/dask_client_mixin.py +65 -0
- nat/front_ends/fastapi/fastapi_front_end_config.py +36 -5
- nat/front_ends/fastapi/fastapi_front_end_controller.py +4 -4
- nat/front_ends/fastapi/fastapi_front_end_plugin.py +135 -4
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +481 -281
- nat/front_ends/fastapi/job_store.py +518 -99
- nat/front_ends/fastapi/main.py +11 -19
- nat/front_ends/fastapi/message_handler.py +13 -14
- nat/front_ends/fastapi/message_validator.py +17 -19
- nat/front_ends/fastapi/response_helpers.py +4 -4
- nat/front_ends/fastapi/step_adaptor.py +2 -2
- nat/front_ends/fastapi/utils.py +57 -0
- nat/front_ends/mcp/introspection_token_verifier.py +73 -0
- nat/front_ends/mcp/mcp_front_end_config.py +10 -1
- nat/front_ends/mcp/mcp_front_end_plugin.py +45 -13
- nat/front_ends/mcp/mcp_front_end_plugin_worker.py +116 -8
- nat/front_ends/mcp/tool_converter.py +44 -14
- nat/front_ends/register.py +0 -1
- nat/front_ends/simple_base/simple_front_end_plugin_base.py +3 -1
- nat/llm/aws_bedrock_llm.py +24 -12
- nat/llm/azure_openai_llm.py +13 -6
- nat/llm/litellm_llm.py +69 -0
- nat/llm/nim_llm.py +20 -8
- nat/llm/openai_llm.py +14 -6
- nat/llm/register.py +4 -1
- nat/llm/utils/env_config_value.py +2 -3
- nat/llm/utils/thinking.py +215 -0
- nat/meta/pypi.md +9 -9
- nat/object_store/register.py +0 -1
- nat/observability/exporter/base_exporter.py +3 -3
- nat/observability/exporter/file_exporter.py +1 -1
- nat/observability/exporter/processing_exporter.py +309 -81
- nat/observability/exporter/span_exporter.py +1 -1
- nat/observability/exporter_manager.py +7 -7
- nat/observability/mixin/file_mixin.py +7 -7
- nat/observability/mixin/redaction_config_mixin.py +42 -0
- nat/observability/mixin/tagging_config_mixin.py +62 -0
- nat/observability/mixin/type_introspection_mixin.py +420 -107
- nat/observability/processor/batching_processor.py +5 -7
- nat/observability/processor/falsy_batch_filter_processor.py +55 -0
- nat/observability/processor/processor.py +3 -0
- nat/observability/processor/processor_factory.py +70 -0
- nat/observability/processor/redaction/__init__.py +24 -0
- nat/observability/processor/redaction/contextual_redaction_processor.py +125 -0
- nat/observability/processor/redaction/contextual_span_redaction_processor.py +66 -0
- nat/observability/processor/redaction/redaction_processor.py +177 -0
- nat/observability/processor/redaction/span_header_redaction_processor.py +92 -0
- nat/observability/processor/span_tagging_processor.py +68 -0
- nat/observability/register.py +6 -4
- nat/profiler/calc/calc_runner.py +3 -4
- nat/profiler/callbacks/agno_callback_handler.py +1 -1
- nat/profiler/callbacks/langchain_callback_handler.py +6 -6
- nat/profiler/callbacks/llama_index_callback_handler.py +3 -3
- nat/profiler/callbacks/semantic_kernel_callback_handler.py +3 -3
- nat/profiler/data_frame_row.py +1 -1
- nat/profiler/decorators/framework_wrapper.py +62 -13
- nat/profiler/decorators/function_tracking.py +160 -3
- nat/profiler/forecasting/models/forecasting_base_model.py +3 -1
- nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/data_models.py +3 -3
- nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +7 -8
- nat/profiler/inference_optimization/token_uniqueness.py +1 -1
- nat/profiler/parameter_optimization/__init__.py +0 -0
- nat/profiler/parameter_optimization/optimizable_utils.py +93 -0
- nat/profiler/parameter_optimization/optimizer_runtime.py +67 -0
- nat/profiler/parameter_optimization/parameter_optimizer.py +153 -0
- nat/profiler/parameter_optimization/parameter_selection.py +107 -0
- nat/profiler/parameter_optimization/pareto_visualizer.py +380 -0
- nat/profiler/parameter_optimization/prompt_optimizer.py +384 -0
- nat/profiler/parameter_optimization/update_helpers.py +66 -0
- nat/profiler/profile_runner.py +14 -9
- nat/profiler/utils.py +4 -2
- nat/registry_handlers/local/local_handler.py +2 -2
- nat/registry_handlers/package_utils.py +1 -2
- nat/registry_handlers/pypi/pypi_handler.py +23 -26
- nat/registry_handlers/register.py +3 -4
- nat/registry_handlers/rest/rest_handler.py +12 -13
- nat/retriever/milvus/retriever.py +2 -2
- nat/retriever/nemo_retriever/retriever.py +1 -1
- nat/retriever/register.py +0 -1
- nat/runtime/loader.py +2 -2
- nat/runtime/runner.py +3 -2
- nat/runtime/session.py +43 -8
- nat/settings/global_settings.py +16 -5
- nat/tool/chat_completion.py +5 -2
- nat/tool/code_execution/local_sandbox/local_sandbox_server.py +3 -3
- nat/tool/datetime_tools.py +49 -9
- nat/tool/document_search.py +2 -2
- nat/tool/github_tools.py +450 -0
- nat/tool/nvidia_rag.py +1 -1
- nat/tool/register.py +2 -9
- nat/tool/retriever.py +3 -2
- nat/utils/callable_utils.py +70 -0
- nat/utils/data_models/schema_validator.py +3 -3
- nat/utils/exception_handlers/automatic_retries.py +104 -51
- nat/utils/exception_handlers/schemas.py +1 -1
- nat/utils/io/yaml_tools.py +2 -2
- nat/utils/log_levels.py +25 -0
- nat/utils/reactive/base/observable_base.py +2 -2
- nat/utils/reactive/base/observer_base.py +1 -1
- nat/utils/reactive/observable.py +2 -2
- nat/utils/reactive/observer.py +4 -4
- nat/utils/reactive/subscription.py +1 -1
- nat/utils/settings/global_settings.py +6 -8
- nat/utils/type_converter.py +4 -3
- nat/utils/type_utils.py +9 -5
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/METADATA +42 -16
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/RECORD +230 -189
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/entry_points.txt +1 -0
- nat/cli/commands/info/list_mcp.py +0 -304
- nat/tool/github_tools/create_github_commit.py +0 -133
- nat/tool/github_tools/create_github_issue.py +0 -87
- nat/tool/github_tools/create_github_pr.py +0 -106
- nat/tool/github_tools/get_github_file.py +0 -106
- nat/tool/github_tools/get_github_issue.py +0 -166
- nat/tool/github_tools/get_github_pr.py +0 -256
- nat/tool/github_tools/update_github_issue.py +0 -100
- nat/tool/mcp/exceptions.py +0 -142
- nat/tool/mcp/mcp_client.py +0 -255
- nat/tool/mcp/mcp_tool.py +0 -96
- nat/utils/exception_handlers/mcp.py +0 -211
- /nat/{tool/github_tools → agent/prompt_optimizer}/__init__.py +0 -0
- /nat/{tool/mcp → authentication/credential_validator}/__init__.py +0 -0
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/licenses/LICENSE.md +0 -0
- {nvidia_nat-1.3.0.dev2.dist-info → nvidia_nat-1.3.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -26,8 +26,6 @@ from collections.abc import Sequence
|
|
|
26
26
|
from typing import Any
|
|
27
27
|
from typing import TypeVar
|
|
28
28
|
|
|
29
|
-
# pylint: disable=inconsistent-return-statements
|
|
30
|
-
|
|
31
29
|
T = TypeVar("T")
|
|
32
30
|
Exc = tuple[type[BaseException], ...] # exception classes
|
|
33
31
|
CodePattern = int | str | range # for retry_codes argument
|
|
@@ -120,6 +118,7 @@ def _retry_decorator(
|
|
|
120
118
|
retry_codes: Sequence[CodePattern] | None = None,
|
|
121
119
|
retry_on_messages: Sequence[str] | None = None,
|
|
122
120
|
deepcopy: bool = False,
|
|
121
|
+
instance_context_aware: bool = False,
|
|
123
122
|
) -> Callable[[Callable[..., T]], Callable[..., T]]:
|
|
124
123
|
"""
|
|
125
124
|
Build a decorator that retries with exponential back-off *iff*:
|
|
@@ -132,69 +131,122 @@ def _retry_decorator(
|
|
|
132
131
|
deepcopy:
|
|
133
132
|
If True, each retry receives deep‑copied *args and **kwargs* to avoid
|
|
134
133
|
mutating shared state between attempts.
|
|
134
|
+
|
|
135
|
+
instance_context_aware:
|
|
136
|
+
If True, the decorator will check for a retry context flag on the first
|
|
137
|
+
argument (assumed to be 'self'). If the flag is set, retries are skipped
|
|
138
|
+
to prevent retry storms in nested method calls.
|
|
135
139
|
"""
|
|
136
140
|
|
|
137
141
|
def decorate(fn: Callable[..., T]) -> Callable[..., T]:
|
|
138
142
|
use_deepcopy = deepcopy
|
|
143
|
+
use_context_aware = instance_context_aware
|
|
139
144
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
+
class _RetryContext:
|
|
146
|
+
"""Context manager for instance-level retry gating."""
|
|
147
|
+
|
|
148
|
+
__slots__ = ("_obj", "_enabled", "_active")
|
|
149
|
+
|
|
150
|
+
def __init__(self, args: tuple[Any, ...]):
|
|
151
|
+
self._obj = args[0] if (use_context_aware and args) else None
|
|
152
|
+
self._enabled = bool(self._obj)
|
|
153
|
+
self._active = False
|
|
154
|
+
|
|
155
|
+
def __enter__(self):
|
|
156
|
+
if not self._enabled:
|
|
157
|
+
return False
|
|
145
158
|
try:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
# If already in retry context, signal caller to skip retries
|
|
160
|
+
if getattr(self._obj, "_in_retry_context", False):
|
|
161
|
+
return True
|
|
162
|
+
object.__setattr__(self._obj, "_in_retry_context", True)
|
|
163
|
+
self._active = True
|
|
164
|
+
return False
|
|
165
|
+
except Exception:
|
|
166
|
+
# If we cannot set the attribute, behave as if context isn't enabled
|
|
167
|
+
self._enabled = False
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
def __exit__(self, _exc_type, _exc, _tb):
|
|
171
|
+
if self._enabled and self._active:
|
|
172
|
+
try:
|
|
173
|
+
object.__setattr__(self._obj, "_in_retry_context", False)
|
|
174
|
+
except Exception:
|
|
175
|
+
pass
|
|
176
|
+
|
|
177
|
+
async def _call_with_retry_async(*args, **kw) -> T:
|
|
178
|
+
with _RetryContext(args) as already_in_context:
|
|
179
|
+
if already_in_context:
|
|
180
|
+
return await fn(*args, **kw)
|
|
181
|
+
delay = base_delay
|
|
182
|
+
for attempt in range(retries):
|
|
183
|
+
call_args = copy.deepcopy(args) if use_deepcopy else args
|
|
184
|
+
call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
|
|
185
|
+
try:
|
|
186
|
+
return await fn(*call_args, **call_kwargs)
|
|
187
|
+
except retry_on as exc:
|
|
188
|
+
if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
|
|
189
|
+
or attempt == retries - 1):
|
|
190
|
+
raise
|
|
191
|
+
await asyncio.sleep(delay)
|
|
192
|
+
delay *= backoff
|
|
153
193
|
|
|
154
194
|
async def _agen_with_retry(*args, **kw):
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
|
|
159
|
-
try:
|
|
160
|
-
async for item in fn(*call_args, **call_kwargs):
|
|
195
|
+
with _RetryContext(args) as already_in_context:
|
|
196
|
+
if already_in_context:
|
|
197
|
+
async for item in fn(*args, **kw):
|
|
161
198
|
yield item
|
|
162
199
|
return
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
200
|
+
delay = base_delay
|
|
201
|
+
for attempt in range(retries):
|
|
202
|
+
call_args = copy.deepcopy(args) if use_deepcopy else args
|
|
203
|
+
call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
|
|
204
|
+
try:
|
|
205
|
+
async for item in fn(*call_args, **call_kwargs):
|
|
206
|
+
yield item
|
|
207
|
+
return
|
|
208
|
+
except retry_on as exc:
|
|
209
|
+
if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
|
|
210
|
+
or attempt == retries - 1):
|
|
211
|
+
raise
|
|
212
|
+
await asyncio.sleep(delay)
|
|
213
|
+
delay *= backoff
|
|
169
214
|
|
|
170
215
|
def _gen_with_retry(*args, **kw) -> Iterable[Any]:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
|
|
175
|
-
try:
|
|
176
|
-
yield from fn(*call_args, **call_kwargs)
|
|
216
|
+
with _RetryContext(args) as already_in_context:
|
|
217
|
+
if already_in_context:
|
|
218
|
+
yield from fn(*args, **kw)
|
|
177
219
|
return
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
220
|
+
delay = base_delay
|
|
221
|
+
for attempt in range(retries):
|
|
222
|
+
call_args = copy.deepcopy(args) if use_deepcopy else args
|
|
223
|
+
call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
|
|
224
|
+
try:
|
|
225
|
+
yield from fn(*call_args, **call_kwargs)
|
|
226
|
+
return
|
|
227
|
+
except retry_on as exc:
|
|
228
|
+
if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
|
|
229
|
+
or attempt == retries - 1):
|
|
230
|
+
raise
|
|
231
|
+
time.sleep(delay)
|
|
232
|
+
delay *= backoff
|
|
184
233
|
|
|
185
234
|
def _sync_with_retry(*args, **kw) -> T:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
235
|
+
with _RetryContext(args) as already_in_context:
|
|
236
|
+
if already_in_context:
|
|
237
|
+
return fn(*args, **kw)
|
|
238
|
+
delay = base_delay
|
|
239
|
+
for attempt in range(retries):
|
|
240
|
+
call_args = copy.deepcopy(args) if use_deepcopy else args
|
|
241
|
+
call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
|
|
242
|
+
try:
|
|
243
|
+
return fn(*call_args, **call_kwargs)
|
|
244
|
+
except retry_on as exc:
|
|
245
|
+
if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
|
|
246
|
+
or attempt == retries - 1):
|
|
247
|
+
raise
|
|
248
|
+
time.sleep(delay)
|
|
249
|
+
delay *= backoff
|
|
198
250
|
|
|
199
251
|
# Decide which wrapper to return
|
|
200
252
|
if inspect.iscoroutinefunction(fn):
|
|
@@ -247,6 +299,7 @@ def patch_with_retry(
|
|
|
247
299
|
retry_codes=retry_codes,
|
|
248
300
|
retry_on_messages=retry_on_messages,
|
|
249
301
|
deepcopy=deepcopy,
|
|
302
|
+
instance_context_aware=True, # Prevent retry storms
|
|
250
303
|
)
|
|
251
304
|
|
|
252
305
|
# Choose attribute source: the *class* to avoid triggering __getattr__
|
|
@@ -257,7 +310,7 @@ def patch_with_retry(
|
|
|
257
310
|
descriptor = inspect.getattr_static(cls, name)
|
|
258
311
|
|
|
259
312
|
# Skip dunders, privates and all descriptors we must not wrap
|
|
260
|
-
if (name.startswith("_") or isinstance(descriptor,
|
|
313
|
+
if (name.startswith("_") or isinstance(descriptor, property | staticmethod | classmethod)):
|
|
261
314
|
continue
|
|
262
315
|
|
|
263
316
|
original = descriptor.__func__ if isinstance(descriptor, types.MethodType) else descriptor
|
|
@@ -21,7 +21,7 @@ from pydantic import ValidationError
|
|
|
21
21
|
logger = logging.getLogger(__name__)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def schema_exception_handler(func, **kwargs):
|
|
24
|
+
def schema_exception_handler(func, **kwargs):
|
|
25
25
|
"""
|
|
26
26
|
A decorator that handles `ValidationError` exceptions for schema validation functions.
|
|
27
27
|
|
nat/utils/io/yaml_tools.py
CHANGED
|
@@ -57,7 +57,7 @@ def yaml_load(config_path: StrPath) -> dict:
|
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
59
|
# Read YAML file
|
|
60
|
-
with open(config_path,
|
|
60
|
+
with open(config_path, encoding="utf-8") as stream:
|
|
61
61
|
config_str = stream.read()
|
|
62
62
|
|
|
63
63
|
return yaml_loads(config_str)
|
|
@@ -85,7 +85,7 @@ def yaml_loads(config: str) -> dict:
|
|
|
85
85
|
try:
|
|
86
86
|
config_data = yaml.safe_load(stream)
|
|
87
87
|
except yaml.YAMLError as e:
|
|
88
|
-
logger.error("Error loading YAML: %s", interpolated_config_str
|
|
88
|
+
logger.error("Error loading YAML: %s", interpolated_config_str)
|
|
89
89
|
raise ValueError(f"Error loading YAML: {e}") from e
|
|
90
90
|
|
|
91
91
|
assert isinstance(config_data, dict)
|
nat/utils/log_levels.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
# Define log level choices
|
|
19
|
+
LOG_LEVELS = {
|
|
20
|
+
'DEBUG': logging.DEBUG,
|
|
21
|
+
'INFO': logging.INFO,
|
|
22
|
+
'WARNING': logging.WARNING,
|
|
23
|
+
'ERROR': logging.ERROR,
|
|
24
|
+
'CRITICAL': logging.CRITICAL
|
|
25
|
+
}
|
|
@@ -25,8 +25,8 @@ from nat.utils.reactive.subscription import Subscription
|
|
|
25
25
|
|
|
26
26
|
# Covariant type param: An Observable producing type X can also produce
|
|
27
27
|
# a subtype of X.
|
|
28
|
-
_T_out_co = TypeVar("_T_out_co", covariant=True)
|
|
29
|
-
_T = TypeVar("_T")
|
|
28
|
+
_T_out_co = TypeVar("_T_out_co", covariant=True)
|
|
29
|
+
_T = TypeVar("_T")
|
|
30
30
|
|
|
31
31
|
OnNext = Callable[[_T], None]
|
|
32
32
|
OnError = Callable[[Exception], None]
|
|
@@ -20,7 +20,7 @@ from typing import TypeVar
|
|
|
20
20
|
|
|
21
21
|
# Contravariant type param: An Observer that can accept type X can also
|
|
22
22
|
# accept any supertype of X.
|
|
23
|
-
_T_in_contra = TypeVar("_T_in_contra", contravariant=True)
|
|
23
|
+
_T_in_contra = TypeVar("_T_in_contra", contravariant=True)
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class ObserverBase(Generic[_T_in_contra], ABC):
|
nat/utils/reactive/observable.py
CHANGED
|
@@ -24,8 +24,8 @@ from nat.utils.type_utils import override
|
|
|
24
24
|
|
|
25
25
|
# Covariant type param: An Observable producing type X can also produce
|
|
26
26
|
# a subtype of X.
|
|
27
|
-
_T_out_co = TypeVar("_T_out_co", covariant=True)
|
|
28
|
-
_T = TypeVar("_T")
|
|
27
|
+
_T_out_co = TypeVar("_T_out_co", covariant=True)
|
|
28
|
+
_T = TypeVar("_T")
|
|
29
29
|
|
|
30
30
|
OnNext = Callable[[_T], None]
|
|
31
31
|
OnError = Callable[[Exception], None]
|
nat/utils/reactive/observer.py
CHANGED
|
@@ -23,8 +23,8 @@ logger = logging.getLogger(__name__)
|
|
|
23
23
|
|
|
24
24
|
# Contravariant type param: An Observer that can accept type X can also
|
|
25
25
|
# accept any supertype of X.
|
|
26
|
-
_T_in_contra = TypeVar("_T_in_contra", contravariant=True)
|
|
27
|
-
_T = TypeVar("_T")
|
|
26
|
+
_T_in_contra = TypeVar("_T_in_contra", contravariant=True)
|
|
27
|
+
_T = TypeVar("_T")
|
|
28
28
|
|
|
29
29
|
OnNext = Callable[[_T], None]
|
|
30
30
|
OnError = Callable[[Exception], None]
|
|
@@ -64,7 +64,7 @@ class Observer(ObserverBase[_T_in_contra]):
|
|
|
64
64
|
try:
|
|
65
65
|
self._on_error(exc)
|
|
66
66
|
except Exception as e:
|
|
67
|
-
logger.exception("Error in on_error callback: %s", e
|
|
67
|
+
logger.exception("Error in on_error callback: %s", e)
|
|
68
68
|
|
|
69
69
|
def on_complete(self) -> None:
|
|
70
70
|
if not self._stopped:
|
|
@@ -73,4 +73,4 @@ class Observer(ObserverBase[_T_in_contra]):
|
|
|
73
73
|
try:
|
|
74
74
|
self._on_complete()
|
|
75
75
|
except Exception as e:
|
|
76
|
-
logger.exception("Error in on_complete callback: %s", e
|
|
76
|
+
logger.exception("Error in on_complete callback: %s", e)
|
|
@@ -21,7 +21,7 @@ from typing import TypeVar
|
|
|
21
21
|
if typing.TYPE_CHECKING:
|
|
22
22
|
from nat.utils.reactive.base.subject_base import SubjectBase
|
|
23
23
|
|
|
24
|
-
_T = TypeVar("_T")
|
|
24
|
+
_T = TypeVar("_T")
|
|
25
25
|
|
|
26
26
|
OnNext = Callable[[_T], None]
|
|
27
27
|
OnError = Callable[[Exception], None]
|
|
@@ -47,7 +47,7 @@ def configure_registry_channel(config_type: RegistryHandlerBaseConfig, channel_n
|
|
|
47
47
|
user_input = input(f"{human_prompt}: ")
|
|
48
48
|
model_fields = {}
|
|
49
49
|
model_fields[field] = (info.annotation, ...)
|
|
50
|
-
DynamicFieldModel = create_model("DynamicFieldModel", **model_fields)
|
|
50
|
+
DynamicFieldModel = create_model("DynamicFieldModel", **model_fields)
|
|
51
51
|
dynamic_inputs = {field: user_input}
|
|
52
52
|
|
|
53
53
|
try:
|
|
@@ -55,7 +55,7 @@ def configure_registry_channel(config_type: RegistryHandlerBaseConfig, channel_n
|
|
|
55
55
|
channel_registry_pre[field] = getattr(validated_field_model, field)
|
|
56
56
|
break
|
|
57
57
|
except Exception as e:
|
|
58
|
-
logger.exception(e
|
|
58
|
+
logger.exception(e)
|
|
59
59
|
logger.warning("Invalid '%s' input, input must be of type %s.", field, info.annotation)
|
|
60
60
|
|
|
61
61
|
validated_model = config_type(**channel_registry_pre)
|
|
@@ -76,10 +76,9 @@ def add_channel_interative(channel_type: str) -> None:
|
|
|
76
76
|
registry = GlobalTypeRegistry.get()
|
|
77
77
|
|
|
78
78
|
try:
|
|
79
|
-
ChannelConfigType = registry.get_registered_channel_info_by_channel_type(
|
|
80
|
-
channel_type=channel_type).config_type
|
|
79
|
+
ChannelConfigType = registry.get_registered_channel_info_by_channel_type(channel_type=channel_type).config_type
|
|
81
80
|
except Exception as e:
|
|
82
|
-
logger.exception("Invalid channel type: %s", e
|
|
81
|
+
logger.exception("Invalid channel type: %s", e)
|
|
83
82
|
return
|
|
84
83
|
|
|
85
84
|
while (True):
|
|
@@ -92,8 +91,7 @@ def add_channel_interative(channel_type: str) -> None:
|
|
|
92
91
|
settings.channels[channel_name] = {}
|
|
93
92
|
break
|
|
94
93
|
|
|
95
|
-
ChannelConfigType = registry.get_registered_channel_info_by_channel_type(
|
|
96
|
-
channel_type=channel_type).config_type
|
|
94
|
+
ChannelConfigType = registry.get_registered_channel_info_by_channel_type(channel_type=channel_type).config_type
|
|
97
95
|
|
|
98
96
|
configure_registry_channel(config_type=ChannelConfigType, channel_name=channel_name)
|
|
99
97
|
|
|
@@ -181,7 +179,7 @@ def match_valid_channel(channel_name: str) -> None:
|
|
|
181
179
|
|
|
182
180
|
channals_settings = settings.channels
|
|
183
181
|
channel_settings = channals_settings.get(channel_name)
|
|
184
|
-
ChannelConfigType = registry.get_registered_channel_info_by_channel_type(
|
|
182
|
+
ChannelConfigType = registry.get_registered_channel_info_by_channel_type(
|
|
185
183
|
channel_type=channel_settings.static_type()).config_type
|
|
186
184
|
|
|
187
185
|
configure_registry_channel(config_type=ChannelConfigType, channel_name=channel_name)
|
nat/utils/type_converter.py
CHANGED
|
@@ -90,7 +90,7 @@ class TypeConverter:
|
|
|
90
90
|
decomposed = DecomposedType(to_type)
|
|
91
91
|
|
|
92
92
|
# 1) If data is already correct type, return it
|
|
93
|
-
if to_type is None or decomposed.is_instance(
|
|
93
|
+
if to_type is None or decomposed.is_instance(data):
|
|
94
94
|
return data
|
|
95
95
|
|
|
96
96
|
root = decomposed.root
|
|
@@ -198,16 +198,17 @@ class TypeConverter:
|
|
|
198
198
|
"""
|
|
199
199
|
visited = set()
|
|
200
200
|
final = self._try_indirect_conversion(data, to_type, visited)
|
|
201
|
+
src_type = type(data)
|
|
201
202
|
if final is not None:
|
|
202
203
|
# Warn once if found a chain
|
|
203
|
-
self._maybe_warn_indirect(
|
|
204
|
+
self._maybe_warn_indirect(src_type, to_type)
|
|
204
205
|
return final
|
|
205
206
|
|
|
206
207
|
# If no success, try parent's indirect
|
|
207
208
|
if self._parent is not None:
|
|
208
209
|
parent_final = self._parent._try_indirect_convert(data, to_type)
|
|
209
210
|
if parent_final is not None:
|
|
210
|
-
self._maybe_warn_indirect(
|
|
211
|
+
self._maybe_warn_indirect(src_type, to_type)
|
|
211
212
|
return parent_final
|
|
212
213
|
|
|
213
214
|
return None
|
nat/utils/type_utils.py
CHANGED
|
@@ -50,7 +50,7 @@ def is_valid_json(string):
|
|
|
50
50
|
# In Python >= 3.12, it uses the built-in typing.override decorator
|
|
51
51
|
# In Python < 3.12, it acts as a no-op decorator
|
|
52
52
|
if sys.version_info >= (3, 12):
|
|
53
|
-
from typing import override
|
|
53
|
+
from typing import override
|
|
54
54
|
else:
|
|
55
55
|
|
|
56
56
|
def override(func):
|
|
@@ -181,7 +181,7 @@ class DecomposedType:
|
|
|
181
181
|
True if the current type is a union type, False otherwise.
|
|
182
182
|
"""
|
|
183
183
|
|
|
184
|
-
return self.origin in (typing.Union, types.UnionType)
|
|
184
|
+
return self.origin in (typing.Union, types.UnionType)
|
|
185
185
|
|
|
186
186
|
@property
|
|
187
187
|
@lru_cache
|
|
@@ -197,7 +197,7 @@ class DecomposedType:
|
|
|
197
197
|
"""
|
|
198
198
|
|
|
199
199
|
return self.origin in (
|
|
200
|
-
typing.AsyncGenerator,
|
|
200
|
+
typing.AsyncGenerator,
|
|
201
201
|
collections.abc.AsyncGenerator,
|
|
202
202
|
types.AsyncGeneratorType,
|
|
203
203
|
)
|
|
@@ -250,7 +250,7 @@ class DecomposedType:
|
|
|
250
250
|
remaining_args = tuple(arg for arg in self.args if arg is not types.NoneType)
|
|
251
251
|
|
|
252
252
|
if (len(remaining_args) > 1):
|
|
253
|
-
return DecomposedType(typing.Union[remaining_args])
|
|
253
|
+
return DecomposedType(typing.Union[*remaining_args])
|
|
254
254
|
if (len(remaining_args) == 1):
|
|
255
255
|
return DecomposedType(remaining_args[0])
|
|
256
256
|
|
|
@@ -353,7 +353,7 @@ class DecomposedType:
|
|
|
353
353
|
True if the current type is an instance of the specified instance, False otherwise
|
|
354
354
|
"""
|
|
355
355
|
|
|
356
|
-
return isinstance(instance, self.root)
|
|
356
|
+
return isinstance(instance, self.get_base_type().root)
|
|
357
357
|
|
|
358
358
|
def get_pydantic_schema(self,
|
|
359
359
|
converters: list[collections.abc.Callable] | None = None) -> type[BaseModel] | type[None]:
|
|
@@ -469,6 +469,10 @@ class DecomposedType:
|
|
|
469
469
|
# Handle generic types that can't use issubclass
|
|
470
470
|
pass
|
|
471
471
|
|
|
472
|
+
# Check direct equality (works for both regular and generic types)
|
|
473
|
+
if source_type == target_type:
|
|
474
|
+
return True
|
|
475
|
+
|
|
472
476
|
# Check if source outputs list[T] and target expects T
|
|
473
477
|
source_decomposed = DecomposedType(source_type)
|
|
474
478
|
if source_decomposed.origin is list and source_decomposed.args:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nvidia-nat
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.0rc1
|
|
4
4
|
Summary: NVIDIA NeMo Agent toolkit
|
|
5
5
|
Author: NVIDIA Corporation
|
|
6
6
|
Maintainer: NVIDIA Corporation
|
|
@@ -207,12 +207,15 @@ License: Apache License
|
|
|
207
207
|
limitations under the License.
|
|
208
208
|
Keywords: ai,rag,agents
|
|
209
209
|
Classifier: Programming Language :: Python
|
|
210
|
-
|
|
210
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
211
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
212
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
213
|
+
Requires-Python: <3.14,>=3.11
|
|
211
214
|
Description-Content-Type: text/markdown
|
|
212
215
|
License-File: LICENSE-3rd-party.txt
|
|
213
216
|
License-File: LICENSE.md
|
|
214
217
|
Requires-Dist: aioboto3>=11.0.0
|
|
215
|
-
Requires-Dist: authlib~=1.
|
|
218
|
+
Requires-Dist: authlib~=1.5
|
|
216
219
|
Requires-Dist: click~=8.1
|
|
217
220
|
Requires-Dist: colorama~=0.4.6
|
|
218
221
|
Requires-Dist: datasets~=4.0
|
|
@@ -221,34 +224,44 @@ Requires-Dist: fastapi~=0.115.5
|
|
|
221
224
|
Requires-Dist: httpx~=0.27
|
|
222
225
|
Requires-Dist: jinja2~=3.1
|
|
223
226
|
Requires-Dist: jsonpath-ng~=1.7
|
|
224
|
-
Requires-Dist: mcp~=1.
|
|
227
|
+
Requires-Dist: mcp~=1.13
|
|
228
|
+
Requires-Dist: nest-asyncio~=1.6
|
|
225
229
|
Requires-Dist: networkx~=3.4
|
|
226
|
-
Requires-Dist: numpy~=1.26
|
|
230
|
+
Requires-Dist: numpy~=1.26; python_version < "3.12"
|
|
231
|
+
Requires-Dist: numpy~=2.3; python_version >= "3.12"
|
|
227
232
|
Requires-Dist: openinference-semantic-conventions~=0.1.14
|
|
228
233
|
Requires-Dist: openpyxl~=3.1
|
|
234
|
+
Requires-Dist: optuna~=4.4.0
|
|
235
|
+
Requires-Dist: pip>=24.3.1
|
|
229
236
|
Requires-Dist: pkce==1.0.3
|
|
230
237
|
Requires-Dist: pkginfo~=1.12
|
|
231
238
|
Requires-Dist: platformdirs~=4.3
|
|
232
|
-
Requires-Dist: pydantic
|
|
239
|
+
Requires-Dist: pydantic~=2.11
|
|
233
240
|
Requires-Dist: pymilvus~=2.4
|
|
234
241
|
Requires-Dist: PyYAML~=6.0
|
|
235
242
|
Requires-Dist: ragas~=0.2.14
|
|
236
243
|
Requires-Dist: rich~=13.9
|
|
237
244
|
Requires-Dist: tabulate~=0.9
|
|
238
|
-
Requires-Dist: uvicorn[standard]~=0.
|
|
245
|
+
Requires-Dist: uvicorn[standard]~=0.34
|
|
239
246
|
Requires-Dist: wikipedia~=1.4
|
|
240
247
|
Provides-Extra: all
|
|
241
248
|
Requires-Dist: nvidia-nat-all; extra == "all"
|
|
249
|
+
Provides-Extra: adk
|
|
250
|
+
Requires-Dist: nvidia-nat-adk; extra == "adk"
|
|
242
251
|
Provides-Extra: agno
|
|
243
252
|
Requires-Dist: nvidia-nat-agno; extra == "agno"
|
|
244
253
|
Provides-Extra: crewai
|
|
245
254
|
Requires-Dist: nvidia-nat-crewai; extra == "crewai"
|
|
255
|
+
Provides-Extra: data-flywheel
|
|
256
|
+
Requires-Dist: nvidia-nat-data-flywheel; extra == "data-flywheel"
|
|
246
257
|
Provides-Extra: ingestion
|
|
247
258
|
Requires-Dist: nvidia-nat-ingestion; extra == "ingestion"
|
|
248
259
|
Provides-Extra: langchain
|
|
249
260
|
Requires-Dist: nvidia-nat-langchain; extra == "langchain"
|
|
250
261
|
Provides-Extra: llama-index
|
|
251
262
|
Requires-Dist: nvidia-nat-llama-index; extra == "llama-index"
|
|
263
|
+
Provides-Extra: mcp
|
|
264
|
+
Requires-Dist: nvidia-nat-mcp; extra == "mcp"
|
|
252
265
|
Provides-Extra: mem0ai
|
|
253
266
|
Requires-Dist: nvidia-nat-mem0ai; extra == "mem0ai"
|
|
254
267
|
Provides-Extra: opentelemetry
|
|
@@ -277,6 +290,7 @@ Requires-Dist: nvidia-nat-weave; extra == "weave"
|
|
|
277
290
|
Provides-Extra: zep-cloud
|
|
278
291
|
Requires-Dist: nvidia-nat-zep-cloud; extra == "zep-cloud"
|
|
279
292
|
Provides-Extra: examples
|
|
293
|
+
Requires-Dist: nat_adk_demo; extra == "examples"
|
|
280
294
|
Requires-Dist: nat_agno_personal_finance; extra == "examples"
|
|
281
295
|
Requires-Dist: nat_alert_triage_agent; extra == "examples"
|
|
282
296
|
Requires-Dist: nat_automated_description_generation; extra == "examples"
|
|
@@ -288,8 +302,11 @@ Requires-Dist: nat_por_to_jiratickets; extra == "examples"
|
|
|
288
302
|
Requires-Dist: nat_profiler_agent; extra == "examples"
|
|
289
303
|
Requires-Dist: nat_redact_pii; extra == "examples"
|
|
290
304
|
Requires-Dist: nat_retail_sales_agent; extra == "examples"
|
|
305
|
+
Requires-Dist: nat_router_agent; extra == "examples"
|
|
291
306
|
Requires-Dist: nat_semantic_kernel_demo; extra == "examples"
|
|
307
|
+
Requires-Dist: nat_sequential_executor; extra == "examples"
|
|
292
308
|
Requires-Dist: nat_simple_auth; extra == "examples"
|
|
309
|
+
Requires-Dist: nat_simple_auth_mcp; extra == "examples"
|
|
293
310
|
Requires-Dist: nat_simple_web_query; extra == "examples"
|
|
294
311
|
Requires-Dist: nat_simple_web_query_eval; extra == "examples"
|
|
295
312
|
Requires-Dist: nat_simple_calculator; extra == "examples"
|
|
@@ -303,6 +320,15 @@ Requires-Dist: nat_swe_bench; extra == "examples"
|
|
|
303
320
|
Requires-Dist: nat_user_report; extra == "examples"
|
|
304
321
|
Provides-Extra: gunicorn
|
|
305
322
|
Requires-Dist: gunicorn~=23.0; extra == "gunicorn"
|
|
323
|
+
Provides-Extra: async-endpoints
|
|
324
|
+
Requires-Dist: aiosqlite~=0.21; extra == "async-endpoints"
|
|
325
|
+
Requires-Dist: dask==2023.6; extra == "async-endpoints"
|
|
326
|
+
Requires-Dist: distributed==2023.6; extra == "async-endpoints"
|
|
327
|
+
Requires-Dist: sqlalchemy[asyncio]~=2.0; extra == "async-endpoints"
|
|
328
|
+
Provides-Extra: litellm
|
|
329
|
+
Requires-Dist: litellm==1.74.9; extra == "litellm"
|
|
330
|
+
Provides-Extra: openai
|
|
331
|
+
Requires-Dist: openai~=1.106; extra == "openai"
|
|
306
332
|
Dynamic: license-file
|
|
307
333
|
|
|
308
334
|
<!--
|
|
@@ -330,19 +356,19 @@ NeMo Agent toolkit is a flexible library designed to seamlessly integrate your e
|
|
|
330
356
|
|
|
331
357
|
## Key Features
|
|
332
358
|
|
|
333
|
-
- [**Framework Agnostic:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
334
|
-
- [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
335
|
-
- [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
336
|
-
- [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
337
|
-
- [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
338
|
-
- [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
339
|
-
- [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
340
|
-
- [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
359
|
+
- [**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.
|
|
360
|
+
- [**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.
|
|
361
|
+
- [**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.
|
|
362
|
+
- [**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.
|
|
363
|
+
- [**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).
|
|
364
|
+
- [**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.
|
|
365
|
+
- [**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.
|
|
366
|
+
- [**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.
|
|
341
367
|
|
|
342
368
|
With NeMo Agent toolkit, you can move quickly, experiment freely, and ensure reliability across all your agent-driven projects.
|
|
343
369
|
|
|
344
370
|
## Links
|
|
345
|
-
* [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
371
|
+
* [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.3/index.html): Explore the full documentation for NeMo Agent toolkit.
|
|
346
372
|
|
|
347
373
|
## First time user?
|
|
348
374
|
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.
|