nvidia-nat 1.3a20250818__py3-none-any.whl → 1.3.0a20250822__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiq/__init__.py +66 -0
- nat/agent/base.py +17 -0
- nat/agent/react_agent/agent.py +17 -10
- nat/agent/react_agent/prompt.py +4 -1
- nat/agent/rewoo_agent/agent.py +6 -2
- nat/agent/rewoo_agent/prompt.py +3 -0
- nat/agent/rewoo_agent/register.py +3 -2
- nat/agent/tool_calling_agent/agent.py +92 -21
- nat/agent/tool_calling_agent/register.py +8 -12
- nat/builder/user_interaction_manager.py +2 -2
- nat/builder/workflow.py +3 -0
- nat/cli/commands/workflow/templates/pyproject.toml.j2 +3 -0
- nat/cli/type_registry.py +4 -4
- nat/embedder/azure_openai_embedder.py +46 -0
- nat/embedder/openai_embedder.py +1 -2
- nat/embedder/register.py +1 -0
- nat/eval/config.py +2 -0
- nat/eval/evaluate.py +68 -23
- nat/eval/utils/eval_trace_ctx.py +89 -0
- nat/eval/utils/weave_eval.py +13 -6
- nat/llm/azure_openai_llm.py +50 -0
- nat/llm/register.py +1 -0
- nat/meta/pypi.md +9 -9
- nat/object_store/models.py +2 -0
- nat/observability/exporter/base_exporter.py +1 -1
- nat/profiler/callbacks/langchain_callback_handler.py +8 -1
- nat/settings/global_settings.py +13 -1
- nat/tool/datetime_tools.py +49 -9
- {nvidia_nat-1.3a20250818.dist-info → nvidia_nat-1.3.0a20250822.dist-info}/METADATA +17 -15
- {nvidia_nat-1.3a20250818.dist-info → nvidia_nat-1.3.0a20250822.dist-info}/RECORD +35 -31
- nvidia_nat-1.3.0a20250822.dist-info/licenses/LICENSE-3rd-party.txt +5478 -0
- {nvidia_nat-1.3a20250818.dist-info → nvidia_nat-1.3.0a20250822.dist-info}/top_level.txt +1 -0
- nvidia_nat-1.3a20250818.dist-info/licenses/LICENSE-3rd-party.txt +0 -3686
- {nvidia_nat-1.3a20250818.dist-info → nvidia_nat-1.3.0a20250822.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.3a20250818.dist-info → nvidia_nat-1.3.0a20250822.dist-info}/entry_points.txt +0 -0
- {nvidia_nat-1.3a20250818.dist-info → nvidia_nat-1.3.0a20250822.dist-info}/licenses/LICENSE.md +0 -0
nat/eval/evaluate.py
CHANGED
|
@@ -63,7 +63,16 @@ class EvaluationRun: # pylint: disable=too-many-public-methods
|
|
|
63
63
|
|
|
64
64
|
# Helpers
|
|
65
65
|
self.intermediate_step_adapter: IntermediateStepAdapter = IntermediateStepAdapter()
|
|
66
|
-
|
|
66
|
+
|
|
67
|
+
# Create evaluation trace context
|
|
68
|
+
try:
|
|
69
|
+
from nat.eval.utils.eval_trace_ctx import WeaveEvalTraceContext
|
|
70
|
+
self.eval_trace_context = WeaveEvalTraceContext()
|
|
71
|
+
except Exception:
|
|
72
|
+
from nat.eval.utils.eval_trace_ctx import EvalTraceContext
|
|
73
|
+
self.eval_trace_context = EvalTraceContext()
|
|
74
|
+
|
|
75
|
+
self.weave_eval: WeaveEvaluationIntegration = WeaveEvaluationIntegration(self.eval_trace_context)
|
|
67
76
|
# Metadata
|
|
68
77
|
self.eval_input: EvalInput | None = None
|
|
69
78
|
self.workflow_interrupted: bool = False
|
|
@@ -401,6 +410,33 @@ class EvaluationRun: # pylint: disable=too-many-public-methods
|
|
|
401
410
|
|
|
402
411
|
return workflow_type
|
|
403
412
|
|
|
413
|
+
async def wait_for_all_export_tasks_local(self, session_manager: SessionManager, timeout: float) -> None:
|
|
414
|
+
"""Wait for all trace export tasks to complete for local workflows.
|
|
415
|
+
|
|
416
|
+
This only works for local workflows where we have direct access to the
|
|
417
|
+
SessionManager and its underlying workflow with exporter manager.
|
|
418
|
+
"""
|
|
419
|
+
try:
|
|
420
|
+
workflow = session_manager.workflow
|
|
421
|
+
all_exporters = await workflow.get_all_exporters()
|
|
422
|
+
if not all_exporters:
|
|
423
|
+
logger.debug("No exporters to wait for")
|
|
424
|
+
return
|
|
425
|
+
|
|
426
|
+
logger.info("Waiting for export tasks from %d local exporters (timeout: %ds)", len(all_exporters), timeout)
|
|
427
|
+
|
|
428
|
+
for name, exporter in all_exporters.items():
|
|
429
|
+
try:
|
|
430
|
+
await exporter.wait_for_tasks(timeout=timeout)
|
|
431
|
+
logger.info("Export tasks completed for exporter: %s", name)
|
|
432
|
+
except Exception as e:
|
|
433
|
+
logger.warning("Error waiting for export tasks from %s: %s", name, e)
|
|
434
|
+
|
|
435
|
+
logger.info("All local export task waiting completed")
|
|
436
|
+
|
|
437
|
+
except Exception as e:
|
|
438
|
+
logger.warning("Failed to wait for local export tasks: %s", e)
|
|
439
|
+
|
|
404
440
|
async def run_and_evaluate(self,
|
|
405
441
|
session_manager: SessionManager | None = None,
|
|
406
442
|
job_id: str | None = None) -> EvaluationRunOutput:
|
|
@@ -442,11 +478,13 @@ class EvaluationRun: # pylint: disable=too-many-public-methods
|
|
|
442
478
|
dataset_config = self.eval_config.general.dataset # Currently only one dataset is supported
|
|
443
479
|
if not dataset_config:
|
|
444
480
|
logger.info("No dataset found, nothing to evaluate")
|
|
445
|
-
return EvaluationRunOutput(
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
481
|
+
return EvaluationRunOutput(workflow_output_file=self.workflow_output_file,
|
|
482
|
+
evaluator_output_files=self.evaluator_output_files,
|
|
483
|
+
workflow_interrupted=self.workflow_interrupted,
|
|
484
|
+
eval_input=EvalInput(eval_input_items=[]),
|
|
485
|
+
evaluation_results=[],
|
|
486
|
+
usage_stats=UsageStats(),
|
|
487
|
+
profiler_results=ProfilerResults())
|
|
450
488
|
|
|
451
489
|
dataset_handler = DatasetHandler(dataset_config=dataset_config,
|
|
452
490
|
reps=self.config.reps,
|
|
@@ -456,11 +494,13 @@ class EvaluationRun: # pylint: disable=too-many-public-methods
|
|
|
456
494
|
self.eval_input = dataset_handler.get_eval_input_from_dataset(self.config.dataset)
|
|
457
495
|
if not self.eval_input.eval_input_items:
|
|
458
496
|
logger.info("Dataset is empty. Nothing to evaluate.")
|
|
459
|
-
return EvaluationRunOutput(
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
497
|
+
return EvaluationRunOutput(workflow_output_file=self.workflow_output_file,
|
|
498
|
+
evaluator_output_files=self.evaluator_output_files,
|
|
499
|
+
workflow_interrupted=self.workflow_interrupted,
|
|
500
|
+
eval_input=self.eval_input,
|
|
501
|
+
evaluation_results=self.evaluation_results,
|
|
502
|
+
usage_stats=self.usage_stats,
|
|
503
|
+
profiler_results=ProfilerResults())
|
|
464
504
|
|
|
465
505
|
# Run workflow and evaluate
|
|
466
506
|
async with WorkflowEvalBuilder.from_config(config=config) as eval_workflow:
|
|
@@ -468,18 +508,23 @@ class EvaluationRun: # pylint: disable=too-many-public-methods
|
|
|
468
508
|
self.weave_eval.initialize_logger(workflow_alias, self.eval_input, config)
|
|
469
509
|
|
|
470
510
|
# Run workflow
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if
|
|
476
|
-
session_manager
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
511
|
+
with self.eval_trace_context.evaluation_context():
|
|
512
|
+
if self.config.endpoint:
|
|
513
|
+
await self.run_workflow_remote()
|
|
514
|
+
else:
|
|
515
|
+
if not self.config.skip_workflow:
|
|
516
|
+
if session_manager is None:
|
|
517
|
+
session_manager = SessionManager(eval_workflow.build(),
|
|
518
|
+
max_concurrency=self.eval_config.general.max_concurrency)
|
|
519
|
+
await self.run_workflow_local(session_manager)
|
|
520
|
+
|
|
521
|
+
# Evaluate
|
|
522
|
+
evaluators = {name: eval_workflow.get_evaluator(name) for name in self.eval_config.evaluators}
|
|
523
|
+
await self.run_evaluators(evaluators)
|
|
524
|
+
|
|
525
|
+
# Wait for all trace export tasks to complete (local workflows only)
|
|
526
|
+
if session_manager and not self.config.endpoint:
|
|
527
|
+
await self.wait_for_all_export_tasks_local(session_manager, timeout=self.config.export_timeout)
|
|
483
528
|
|
|
484
529
|
# Profile the workflow
|
|
485
530
|
profiler_results = await self.profile_workflow()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from collections.abc import Callable
|
|
18
|
+
from contextlib import contextmanager
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
# Type alias for evaluation call objects that have an optional 'id' attribute
|
|
24
|
+
EvalCallType = Any # Could be Weave Call object or other tracing framework objects
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class EvalTraceContext:
|
|
28
|
+
"""
|
|
29
|
+
Evaluation trace context manager for coordinating traces.
|
|
30
|
+
|
|
31
|
+
This class provides a framework-agnostic way to:
|
|
32
|
+
1. Track evaluation calls/contexts
|
|
33
|
+
2. Ensure proper parent-child relationships in traces
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
self.eval_call: EvalCallType | None = None # Store the evaluation call/context for propagation
|
|
38
|
+
|
|
39
|
+
def set_eval_call(self, eval_call: EvalCallType | None) -> None:
|
|
40
|
+
"""Set the evaluation call/context for propagation to traces."""
|
|
41
|
+
self.eval_call = eval_call
|
|
42
|
+
if eval_call:
|
|
43
|
+
logger.debug("Set evaluation call context: %s", getattr(eval_call, 'id', str(eval_call)))
|
|
44
|
+
|
|
45
|
+
def get_eval_call(self) -> EvalCallType | None:
|
|
46
|
+
"""Get the current evaluation call/context."""
|
|
47
|
+
return self.eval_call
|
|
48
|
+
|
|
49
|
+
@contextmanager
|
|
50
|
+
def evaluation_context(self):
|
|
51
|
+
"""
|
|
52
|
+
Context manager that can be overridden by framework-specific implementations.
|
|
53
|
+
Default implementation is a no-op.
|
|
54
|
+
"""
|
|
55
|
+
yield
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class WeaveEvalTraceContext(EvalTraceContext):
|
|
59
|
+
"""
|
|
60
|
+
Weave-specific implementation of evaluation trace context.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def __init__(self):
|
|
64
|
+
super().__init__()
|
|
65
|
+
self.available = False
|
|
66
|
+
self.set_call_stack: Callable[[list[EvalCallType]], Any] | None = None
|
|
67
|
+
|
|
68
|
+
try:
|
|
69
|
+
from weave.trace.context.call_context import set_call_stack
|
|
70
|
+
self.set_call_stack = set_call_stack
|
|
71
|
+
self.available = True
|
|
72
|
+
except ImportError:
|
|
73
|
+
self.available = False
|
|
74
|
+
logger.debug("Weave not available for trace context")
|
|
75
|
+
|
|
76
|
+
@contextmanager
|
|
77
|
+
def evaluation_context(self):
|
|
78
|
+
"""Set the evaluation call as active context for Weave traces."""
|
|
79
|
+
if self.available and self.eval_call and self.set_call_stack:
|
|
80
|
+
try:
|
|
81
|
+
with self.set_call_stack([self.eval_call]):
|
|
82
|
+
logger.debug("Set Weave evaluation call context: %s",
|
|
83
|
+
getattr(self.eval_call, 'id', str(self.eval_call)))
|
|
84
|
+
yield
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logger.warning("Failed to set Weave evaluation call context: %s", e)
|
|
87
|
+
yield
|
|
88
|
+
else:
|
|
89
|
+
yield
|
nat/eval/utils/weave_eval.py
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import asyncio
|
|
17
17
|
import logging
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
18
19
|
from typing import Any
|
|
19
20
|
|
|
20
21
|
from nat.eval.evaluator.evaluator_model import EvalInput
|
|
@@ -24,6 +25,9 @@ from nat.eval.usage_stats import UsageStats
|
|
|
24
25
|
from nat.eval.usage_stats import UsageStatsItem
|
|
25
26
|
from nat.profiler.data_models import ProfilerResults
|
|
26
27
|
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from nat.eval.utils.eval_trace_ctx import EvalTraceContext
|
|
30
|
+
|
|
27
31
|
logger = logging.getLogger(__name__)
|
|
28
32
|
|
|
29
33
|
|
|
@@ -32,18 +36,19 @@ class WeaveEvaluationIntegration: # pylint: disable=too-many-public-methods
|
|
|
32
36
|
Class to handle all Weave integration functionality.
|
|
33
37
|
"""
|
|
34
38
|
|
|
35
|
-
def __init__(self):
|
|
39
|
+
def __init__(self, eval_trace_context: "EvalTraceContext"):
|
|
36
40
|
self.available = False
|
|
37
41
|
self.client = None
|
|
38
42
|
self.eval_logger = None
|
|
39
43
|
self.pred_loggers = {}
|
|
44
|
+
self.eval_trace_context = eval_trace_context
|
|
40
45
|
|
|
41
46
|
try:
|
|
42
47
|
from weave.flow.eval_imperative import EvaluationLogger
|
|
43
48
|
from weave.flow.eval_imperative import ScoreLogger
|
|
44
49
|
from weave.trace.context import weave_client_context
|
|
45
|
-
self.
|
|
46
|
-
self.
|
|
50
|
+
self.evaluation_logger_cls = EvaluationLogger # pylint: disable=invalid-name
|
|
51
|
+
self.score_logger_cls = ScoreLogger # pylint: disable=invalid-name
|
|
47
52
|
self.weave_client_context = weave_client_context
|
|
48
53
|
self.available = True
|
|
49
54
|
except ImportError:
|
|
@@ -89,9 +94,12 @@ class WeaveEvaluationIntegration: # pylint: disable=too-many-public-methods
|
|
|
89
94
|
weave_dataset = self._get_weave_dataset(eval_input)
|
|
90
95
|
config_dict = config.model_dump(mode="json")
|
|
91
96
|
config_dict["name"] = workflow_alias
|
|
92
|
-
self.eval_logger = self.
|
|
97
|
+
self.eval_logger = self.evaluation_logger_cls(model=config_dict, dataset=weave_dataset)
|
|
93
98
|
self.pred_loggers = {}
|
|
94
99
|
|
|
100
|
+
# Capture the current evaluation call for context propagation
|
|
101
|
+
self.eval_trace_context.set_eval_call(self.eval_logger._evaluate_call)
|
|
102
|
+
|
|
95
103
|
return True
|
|
96
104
|
except Exception as e:
|
|
97
105
|
self.eval_logger = None
|
|
@@ -137,7 +145,7 @@ class WeaveEvaluationIntegration: # pylint: disable=too-many-public-methods
|
|
|
137
145
|
await asyncio.gather(*coros)
|
|
138
146
|
|
|
139
147
|
async def afinish_loggers(self):
|
|
140
|
-
"""Finish all prediction loggers."""
|
|
148
|
+
"""Finish all prediction loggers and wait for exports."""
|
|
141
149
|
if not self.eval_logger:
|
|
142
150
|
return
|
|
143
151
|
|
|
@@ -157,7 +165,6 @@ class WeaveEvaluationIntegration: # pylint: disable=too-many-public-methods
|
|
|
157
165
|
if profiler_results.workflow_runtime_metrics:
|
|
158
166
|
profile_metrics["wf_runtime_p95"] = profiler_results.workflow_runtime_metrics.p95
|
|
159
167
|
|
|
160
|
-
# TODO:get the LLM tokens from the usage stats and log them
|
|
161
168
|
profile_metrics["total_runtime"] = usage_stats.total_runtime
|
|
162
169
|
|
|
163
170
|
return profile_metrics
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
|
|
26
|
+
|
|
27
|
+
class AzureOpenAIModelConfig(LLMBaseConfig, RetryMixin, name="azure_openai"):
|
|
28
|
+
"""An Azure OpenAI LLM provider to be used with an LLM client."""
|
|
29
|
+
|
|
30
|
+
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
31
|
+
|
|
32
|
+
api_key: str | None = Field(default=None, description="Azure OpenAI API key to interact with hosted model.")
|
|
33
|
+
api_version: str = Field(default="2025-04-01-preview", description="Azure OpenAI API version.")
|
|
34
|
+
azure_endpoint: str | None = Field(validation_alias=AliasChoices("azure_endpoint", "base_url"),
|
|
35
|
+
serialization_alias="azure_endpoint",
|
|
36
|
+
default=None,
|
|
37
|
+
description="Base URL for the hosted model.")
|
|
38
|
+
azure_deployment: str = Field(validation_alias=AliasChoices("azure_deployment", "model_name", "model"),
|
|
39
|
+
serialization_alias="azure_deployment",
|
|
40
|
+
description="The Azure OpenAI hosted model/deployment name.")
|
|
41
|
+
temperature: float = Field(default=0.0, description="Sampling temperature in [0, 1].")
|
|
42
|
+
top_p: float = Field(default=1.0, description="Top-p for distribution sampling.")
|
|
43
|
+
seed: int | None = Field(default=None, description="Random seed to set for generation.")
|
|
44
|
+
max_retries: int = Field(default=10, description="The max number of retries for the request.")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@register_llm_provider(config_type=AzureOpenAIModelConfig)
|
|
48
|
+
async def azure_openai_llm(config: AzureOpenAIModelConfig, _builder: Builder):
|
|
49
|
+
|
|
50
|
+
yield LLMProviderInfo(config=config, description="An Azure OpenAI model for use with an LLM client.")
|
nat/llm/register.py
CHANGED
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.
|
|
27
|
-
- [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
28
|
-
- [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
29
|
-
- [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
30
|
-
- [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
31
|
-
- [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
32
|
-
- [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
33
|
-
- [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
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.
|
|
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.
|
nat/object_store/models.py
CHANGED
|
@@ -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)
|
|
@@ -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
|
|
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.
|
|
@@ -223,7 +223,14 @@ class LangchainProfilerHandler(AsyncCallbackHandler, BaseProfilerCallback): # p
|
|
|
223
223
|
except AttributeError:
|
|
224
224
|
usage_metadata = {}
|
|
225
225
|
|
|
226
|
-
|
|
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:
|
nat/settings/global_settings.py
CHANGED
|
@@ -47,6 +47,12 @@ class Settings(HashableBaseModel):
|
|
|
47
47
|
# Registry Handeler Configuration
|
|
48
48
|
channels: dict[str, RegistryHandlerBaseConfig] = {}
|
|
49
49
|
|
|
50
|
+
# Timezone fallback behavior
|
|
51
|
+
# Options:
|
|
52
|
+
# - "utc": default to UTC
|
|
53
|
+
# - "system": use the system's local timezone
|
|
54
|
+
fallback_timezone: typing.Literal["system", "utc"] = "utc"
|
|
55
|
+
|
|
50
56
|
_configuration_directory: typing.ClassVar[str]
|
|
51
57
|
_settings_changed_hooks: typing.ClassVar[list[Callable[[], None]]] = []
|
|
52
58
|
_settings_changed_hooks_active: bool = True
|
|
@@ -165,7 +171,11 @@ class Settings(HashableBaseModel):
|
|
|
165
171
|
loaded_config = {}
|
|
166
172
|
else:
|
|
167
173
|
with open(file_path, mode="r", encoding="utf-8") as f:
|
|
168
|
-
|
|
174
|
+
try:
|
|
175
|
+
loaded_config = json.load(f)
|
|
176
|
+
except Exception as e:
|
|
177
|
+
logger.exception("Error loading configuration file %s: %s", file_path, e)
|
|
178
|
+
loaded_config = {}
|
|
169
179
|
|
|
170
180
|
settings = Settings(**loaded_config)
|
|
171
181
|
settings.set_configuration_directory(configuration_directory)
|
|
@@ -214,6 +224,8 @@ class Settings(HashableBaseModel):
|
|
|
214
224
|
match field:
|
|
215
225
|
case "channels":
|
|
216
226
|
self.channels = validated_data.channels
|
|
227
|
+
case "fallback_timezone":
|
|
228
|
+
self.fallback_timezone = validated_data.fallback_timezone
|
|
217
229
|
case _:
|
|
218
230
|
raise ValueError(f"Encountered invalid model field: {field}")
|
|
219
231
|
|
nat/tool/datetime_tools.py
CHANGED
|
@@ -13,30 +13,70 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
import datetime
|
|
17
|
+
import zoneinfo
|
|
18
|
+
|
|
19
|
+
from starlette.datastructures import Headers
|
|
20
|
+
|
|
16
21
|
from nat.builder.builder import Builder
|
|
17
22
|
from nat.builder.function_info import FunctionInfo
|
|
18
23
|
from nat.cli.register_workflow import register_function
|
|
19
24
|
from nat.data_models.function import FunctionBaseConfig
|
|
25
|
+
from nat.settings.global_settings import GlobalSettings
|
|
20
26
|
|
|
21
27
|
|
|
22
28
|
class CurrentTimeToolConfig(FunctionBaseConfig, name="current_datetime"):
|
|
23
29
|
"""
|
|
24
|
-
Simple tool which returns the current date and time in human readable format.
|
|
30
|
+
Simple tool which returns the current date and time in human readable format with timezone information. By default,
|
|
31
|
+
the timezone is in Etc/UTC. If the user provides a timezone in the header, we will use it. Timezone will be
|
|
32
|
+
provided in IANA zone name format. For example, "America/New_York" or "Etc/UTC".
|
|
25
33
|
"""
|
|
26
34
|
pass
|
|
27
35
|
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
def _get_timezone_obj(headers: Headers | None) -> zoneinfo.ZoneInfo | datetime.tzinfo:
|
|
38
|
+
# Default to UTC
|
|
39
|
+
timezone_obj = zoneinfo.ZoneInfo("Etc/UTC")
|
|
40
|
+
|
|
41
|
+
if headers:
|
|
42
|
+
# If user has provided a timezone in the header, we will prioritize on using it
|
|
43
|
+
timezone_header = headers.get("x-timezone")
|
|
44
|
+
if timezone_header:
|
|
45
|
+
try:
|
|
46
|
+
timezone_obj = zoneinfo.ZoneInfo(timezone_header)
|
|
47
|
+
except Exception:
|
|
48
|
+
pass
|
|
49
|
+
else:
|
|
50
|
+
# Only if a timezone is not in the header, we will determine default timezone based on global settings
|
|
51
|
+
fallback_tz = GlobalSettings.get().fallback_timezone
|
|
52
|
+
|
|
53
|
+
if fallback_tz == "system":
|
|
54
|
+
# Use the system's local timezone. Avoid requiring external deps.
|
|
55
|
+
timezone_obj = datetime.datetime.now().astimezone().tzinfo or zoneinfo.ZoneInfo("Etc/UTC")
|
|
56
|
+
|
|
57
|
+
return timezone_obj
|
|
31
58
|
|
|
32
|
-
|
|
59
|
+
|
|
60
|
+
@register_function(config_type=CurrentTimeToolConfig)
|
|
61
|
+
async def current_datetime(_config: CurrentTimeToolConfig, _builder: Builder):
|
|
33
62
|
|
|
34
63
|
async def _get_current_time(unused: str) -> str:
|
|
35
64
|
|
|
36
|
-
|
|
37
|
-
|
|
65
|
+
del unused # Unused parameter to avoid linting error
|
|
66
|
+
|
|
67
|
+
from nat.builder.context import Context
|
|
68
|
+
nat_context = Context.get()
|
|
69
|
+
|
|
70
|
+
headers: Headers | None = nat_context.metadata.headers
|
|
71
|
+
|
|
72
|
+
timezone_obj = _get_timezone_obj(headers)
|
|
73
|
+
|
|
74
|
+
now = datetime.datetime.now(timezone_obj)
|
|
75
|
+
now_machine_readable = now.strftime(("%Y-%m-%d %H:%M:%S %z"))
|
|
38
76
|
|
|
39
|
-
|
|
77
|
+
# Returns the current time in machine readable format with timezone offset.
|
|
78
|
+
return f"The current time of day is {now_machine_readable}"
|
|
40
79
|
|
|
41
|
-
yield FunctionInfo.from_fn(
|
|
42
|
-
|
|
80
|
+
yield FunctionInfo.from_fn(
|
|
81
|
+
_get_current_time,
|
|
82
|
+
description="Returns the current date and time in human readable format with timezone information.")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nvidia-nat
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0a20250822
|
|
4
4
|
Summary: NVIDIA NeMo Agent toolkit
|
|
5
5
|
Author: NVIDIA Corporation
|
|
6
6
|
Maintainer: NVIDIA Corporation
|
|
@@ -237,12 +237,14 @@ Requires-Dist: rich~=13.9
|
|
|
237
237
|
Requires-Dist: tabulate~=0.9
|
|
238
238
|
Requires-Dist: uvicorn[standard]~=0.32.0
|
|
239
239
|
Requires-Dist: wikipedia~=1.4
|
|
240
|
+
Provides-Extra: all
|
|
241
|
+
Requires-Dist: nvidia-nat-all; extra == "all"
|
|
240
242
|
Provides-Extra: agno
|
|
241
243
|
Requires-Dist: nvidia-nat-agno; extra == "agno"
|
|
242
244
|
Provides-Extra: crewai
|
|
243
245
|
Requires-Dist: nvidia-nat-crewai; extra == "crewai"
|
|
244
246
|
Provides-Extra: ingestion
|
|
245
|
-
Requires-Dist:
|
|
247
|
+
Requires-Dist: nvidia-nat-ingestion; extra == "ingestion"
|
|
246
248
|
Provides-Extra: langchain
|
|
247
249
|
Requires-Dist: nvidia-nat-langchain; extra == "langchain"
|
|
248
250
|
Provides-Extra: llama-index
|
|
@@ -253,6 +255,8 @@ Provides-Extra: opentelemetry
|
|
|
253
255
|
Requires-Dist: nvidia-nat-opentelemetry; extra == "opentelemetry"
|
|
254
256
|
Provides-Extra: phoenix
|
|
255
257
|
Requires-Dist: nvidia-nat-phoenix; extra == "phoenix"
|
|
258
|
+
Provides-Extra: profiling
|
|
259
|
+
Requires-Dist: nvidia-nat-profiling; extra == "profiling"
|
|
256
260
|
Provides-Extra: ragaai
|
|
257
261
|
Requires-Dist: nvidia-nat-ragaai; extra == "ragaai"
|
|
258
262
|
Provides-Extra: mysql
|
|
@@ -278,10 +282,12 @@ Requires-Dist: nat_alert_triage_agent; extra == "examples"
|
|
|
278
282
|
Requires-Dist: nat_automated_description_generation; extra == "examples"
|
|
279
283
|
Requires-Dist: nat_email_phishing_analyzer; extra == "examples"
|
|
280
284
|
Requires-Dist: nat_multi_frameworks; extra == "examples"
|
|
285
|
+
Requires-Dist: nat_first_search_agent; extra == "examples"
|
|
281
286
|
Requires-Dist: nat_plot_charts; extra == "examples"
|
|
282
287
|
Requires-Dist: nat_por_to_jiratickets; extra == "examples"
|
|
283
288
|
Requires-Dist: nat_profiler_agent; extra == "examples"
|
|
284
289
|
Requires-Dist: nat_redact_pii; extra == "examples"
|
|
290
|
+
Requires-Dist: nat_retail_sales_agent; extra == "examples"
|
|
285
291
|
Requires-Dist: nat_semantic_kernel_demo; extra == "examples"
|
|
286
292
|
Requires-Dist: nat_simple_auth; extra == "examples"
|
|
287
293
|
Requires-Dist: nat_simple_web_query; extra == "examples"
|
|
@@ -295,10 +301,6 @@ Requires-Dist: nat_simple_calculator_hitl; extra == "examples"
|
|
|
295
301
|
Requires-Dist: nat_simple_rag; extra == "examples"
|
|
296
302
|
Requires-Dist: nat_swe_bench; extra == "examples"
|
|
297
303
|
Requires-Dist: nat_user_report; extra == "examples"
|
|
298
|
-
Provides-Extra: profiling
|
|
299
|
-
Requires-Dist: matplotlib~=3.9; extra == "profiling"
|
|
300
|
-
Requires-Dist: prefixspan~=0.5.2; extra == "profiling"
|
|
301
|
-
Requires-Dist: scikit-learn~=1.6; extra == "profiling"
|
|
302
304
|
Provides-Extra: gunicorn
|
|
303
305
|
Requires-Dist: gunicorn~=23.0; extra == "gunicorn"
|
|
304
306
|
Dynamic: license-file
|
|
@@ -328,19 +330,19 @@ NeMo Agent toolkit is a flexible library designed to seamlessly integrate your e
|
|
|
328
330
|
|
|
329
331
|
## Key Features
|
|
330
332
|
|
|
331
|
-
- [**Framework Agnostic:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
332
|
-
- [**Reusability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
333
|
-
- [**Rapid Development:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
334
|
-
- [**Profiling:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
335
|
-
- [**Observability:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
336
|
-
- [**Evaluation System:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
337
|
-
- [**User Interface:**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
338
|
-
- [**MCP Compatibility**](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
333
|
+
- [**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.
|
|
334
|
+
- [**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.
|
|
335
|
+
- [**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.
|
|
336
|
+
- [**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.
|
|
337
|
+
- [**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).
|
|
338
|
+
- [**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.
|
|
339
|
+
- [**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.
|
|
340
|
+
- [**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.
|
|
339
341
|
|
|
340
342
|
With NeMo Agent toolkit, you can move quickly, experiment freely, and ensure reliability across all your agent-driven projects.
|
|
341
343
|
|
|
342
344
|
## Links
|
|
343
|
-
* [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.
|
|
345
|
+
* [Documentation](https://docs.nvidia.com/nemo/agent-toolkit/1.3/index.html): Explore the full documentation for NeMo Agent toolkit.
|
|
344
346
|
|
|
345
347
|
## First time user?
|
|
346
348
|
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.
|