nvidia-nat 1.4.0a20251029__py3-none-any.whl → 1.4.0a20251031__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.
- nat/authentication/api_key/api_key_auth_provider.py +5 -10
- nat/authentication/api_key/api_key_auth_provider_config.py +8 -5
- nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +2 -1
- nat/authentication/oauth2/oauth2_resource_server_config.py +2 -1
- nat/data_models/api_server.py +3 -2
- nat/data_models/common.py +22 -0
- nat/data_models/dataset_handler.py +3 -2
- nat/embedder/azure_openai_embedder.py +2 -1
- nat/embedder/nim_embedder.py +2 -1
- nat/embedder/openai_embedder.py +2 -1
- nat/eval/dataset_handler/dataset_downloader.py +3 -2
- nat/eval/utils/output_uploader.py +3 -2
- nat/front_ends/console/authentication_flow_handler.py +1 -1
- nat/front_ends/mcp/tool_converter.py +53 -22
- nat/llm/azure_openai_llm.py +2 -1
- nat/llm/litellm_llm.py +2 -1
- nat/llm/nim_llm.py +2 -1
- nat/llm/openai_llm.py +2 -1
- nat/profiler/parameter_optimization/parameter_optimizer.py +12 -2
- nat/profiler/parameter_optimization/pareto_visualizer.py +67 -2
- nat/registry_handlers/pypi/register_pypi.py +5 -3
- nat/registry_handlers/rest/register_rest.py +5 -3
- nat/retriever/nemo_retriever/register.py +2 -1
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/METADATA +1 -1
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/RECORD +30 -30
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/entry_points.txt +0 -0
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/licenses/LICENSE.md +0 -0
- {nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/top_level.txt +0 -0
|
@@ -15,8 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
import logging
|
|
17
17
|
|
|
18
|
-
from pydantic import SecretStr
|
|
19
|
-
|
|
20
18
|
from nat.authentication.api_key.api_key_auth_provider_config import APIKeyAuthProviderConfig
|
|
21
19
|
from nat.authentication.interfaces import AuthProviderBase
|
|
22
20
|
from nat.data_models.authentication import AuthResult
|
|
@@ -29,11 +27,10 @@ logger = logging.getLogger(__name__)
|
|
|
29
27
|
class APIKeyAuthProvider(AuthProviderBase[APIKeyAuthProviderConfig]):
|
|
30
28
|
|
|
31
29
|
# fmt: off
|
|
32
|
-
def __init__(self,
|
|
33
|
-
config: APIKeyAuthProviderConfig,
|
|
34
|
-
config_name: str | None = None) -> None:
|
|
30
|
+
def __init__(self, config: APIKeyAuthProviderConfig, config_name: str | None = None) -> None:
|
|
35
31
|
assert isinstance(config, APIKeyAuthProviderConfig), ("Config is not APIKeyAuthProviderConfig")
|
|
36
32
|
super().__init__(config)
|
|
33
|
+
|
|
37
34
|
# fmt: on
|
|
38
35
|
|
|
39
36
|
async def _construct_authentication_header(self) -> BearerTokenCred:
|
|
@@ -58,14 +55,12 @@ class APIKeyAuthProvider(AuthProviderBase[APIKeyAuthProviderConfig]):
|
|
|
58
55
|
header_auth_scheme = config.auth_scheme
|
|
59
56
|
|
|
60
57
|
if header_auth_scheme == HeaderAuthScheme.BEARER:
|
|
61
|
-
return BearerTokenCred(token=
|
|
58
|
+
return BearerTokenCred(token=config.raw_key,
|
|
62
59
|
scheme=HeaderAuthScheme.BEARER.value,
|
|
63
60
|
header_name=AUTHORIZATION_HEADER)
|
|
64
61
|
|
|
65
62
|
if header_auth_scheme == HeaderAuthScheme.X_API_KEY:
|
|
66
|
-
return BearerTokenCred(token=
|
|
67
|
-
scheme=HeaderAuthScheme.X_API_KEY.value,
|
|
68
|
-
header_name='')
|
|
63
|
+
return BearerTokenCred(token=config.raw_key, scheme=HeaderAuthScheme.X_API_KEY.value, header_name='')
|
|
69
64
|
|
|
70
65
|
if header_auth_scheme == HeaderAuthScheme.CUSTOM:
|
|
71
66
|
if not config.custom_header_name:
|
|
@@ -74,7 +69,7 @@ class APIKeyAuthProvider(AuthProviderBase[APIKeyAuthProviderConfig]):
|
|
|
74
69
|
if not config.custom_header_prefix:
|
|
75
70
|
raise ValueError('custom_header_prefix required when using header_auth_scheme=CUSTOM')
|
|
76
71
|
|
|
77
|
-
return BearerTokenCred(token=
|
|
72
|
+
return BearerTokenCred(token=config.raw_key,
|
|
78
73
|
scheme=config.custom_header_prefix,
|
|
79
74
|
header_name=config.custom_header_name)
|
|
80
75
|
|
|
@@ -25,6 +25,7 @@ from nat.authentication.exceptions.api_key_exceptions import HeaderNameFieldErro
|
|
|
25
25
|
from nat.authentication.exceptions.api_key_exceptions import HeaderPrefixFieldError
|
|
26
26
|
from nat.data_models.authentication import AuthProviderBaseConfig
|
|
27
27
|
from nat.data_models.authentication import HeaderAuthScheme
|
|
28
|
+
from nat.data_models.common import SerializableSecretStr
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
30
31
|
|
|
@@ -37,8 +38,9 @@ class APIKeyAuthProviderConfig(AuthProviderBaseConfig, name="api_key"):
|
|
|
37
38
|
API Key authentication configuration model.
|
|
38
39
|
"""
|
|
39
40
|
|
|
40
|
-
raw_key:
|
|
41
|
-
|
|
41
|
+
raw_key: SerializableSecretStr = Field(
|
|
42
|
+
description=("Raw API token or credential to be injected into the request parameter. "
|
|
43
|
+
"Used for 'bearer','x-api-key','custom', and other schemes. "))
|
|
42
44
|
|
|
43
45
|
auth_scheme: HeaderAuthScheme = Field(default=HeaderAuthScheme.BEARER,
|
|
44
46
|
description=("The HTTP authentication scheme to use. "
|
|
@@ -53,7 +55,7 @@ class APIKeyAuthProviderConfig(AuthProviderBaseConfig, name="api_key"):
|
|
|
53
55
|
|
|
54
56
|
@field_validator('raw_key')
|
|
55
57
|
@classmethod
|
|
56
|
-
def validate_raw_key(cls, value:
|
|
58
|
+
def validate_raw_key(cls, value: SerializableSecretStr) -> SerializableSecretStr:
|
|
57
59
|
if not value:
|
|
58
60
|
raise APIKeyFieldError('value_missing', 'raw_key field value is required.')
|
|
59
61
|
|
|
@@ -63,11 +65,12 @@ class APIKeyAuthProviderConfig(AuthProviderBaseConfig, name="api_key"):
|
|
|
63
65
|
'raw_key field value must be at least 8 characters long for security. '
|
|
64
66
|
f'Got: {len(value)} characters.')
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
str_value = value.get_secret_value()
|
|
69
|
+
if len(str_value.strip()) != len(value):
|
|
67
70
|
raise APIKeyFieldError('whitespace_found',
|
|
68
71
|
'raw_key field value cannot have leading or trailing whitespace.')
|
|
69
72
|
|
|
70
|
-
if any(c in string.whitespace for c in
|
|
73
|
+
if any(c in string.whitespace for c in str_value):
|
|
71
74
|
raise APIKeyFieldError('contains_whitespace', 'raw_key must not contain any '
|
|
72
75
|
'whitespace characters.')
|
|
73
76
|
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
from pydantic import Field
|
|
17
17
|
|
|
18
18
|
from nat.data_models.authentication import AuthProviderBaseConfig
|
|
19
|
+
from nat.data_models.common import SerializableSecretStr
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
class OAuth2AuthCodeFlowProviderConfig(AuthProviderBaseConfig, name="oauth2_auth_code_flow"):
|
|
22
23
|
|
|
23
24
|
client_id: str = Field(description="The client ID for OAuth 2.0 authentication.")
|
|
24
|
-
client_secret:
|
|
25
|
+
client_secret: SerializableSecretStr = Field(description="The secret associated with the client_id.")
|
|
25
26
|
authorization_url: str = Field(description="The authorization URL for OAuth 2.0 authentication.")
|
|
26
27
|
token_url: str = Field(description="The token URL for OAuth 2.0 authentication.")
|
|
27
28
|
token_endpoint_auth_method: str | None = Field(
|
|
@@ -20,6 +20,7 @@ from pydantic import field_validator
|
|
|
20
20
|
from pydantic import model_validator
|
|
21
21
|
|
|
22
22
|
from nat.data_models.authentication import AuthProviderBaseConfig
|
|
23
|
+
from nat.data_models.common import OptionalSecretStr
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class OAuth2ResourceServerConfig(AuthProviderBaseConfig, name="oauth2_resource_server"):
|
|
@@ -66,7 +67,7 @@ class OAuth2ResourceServerConfig(AuthProviderBaseConfig, name="oauth2_resource_s
|
|
|
66
67
|
default=None,
|
|
67
68
|
description="OAuth2 client ID for authenticating to the introspection endpoint (opaque token validation).",
|
|
68
69
|
)
|
|
69
|
-
client_secret:
|
|
70
|
+
client_secret: OptionalSecretStr = Field(
|
|
70
71
|
default=None,
|
|
71
72
|
description="OAuth2 client secret for authenticating to the introspection endpoint (opaque token validation).",
|
|
72
73
|
)
|
nat/data_models/api_server.py
CHANGED
|
@@ -31,6 +31,7 @@ from pydantic import field_validator
|
|
|
31
31
|
from pydantic import model_validator
|
|
32
32
|
from pydantic_core.core_schema import ValidationInfo
|
|
33
33
|
|
|
34
|
+
from nat.data_models.common import SerializableSecretStr
|
|
34
35
|
from nat.data_models.interactive import HumanPrompt
|
|
35
36
|
from nat.utils.type_converter import GlobalTypeConverter
|
|
36
37
|
|
|
@@ -109,8 +110,8 @@ class TextContent(BaseModel):
|
|
|
109
110
|
class Security(BaseModel):
|
|
110
111
|
model_config = ConfigDict(extra="forbid")
|
|
111
112
|
|
|
112
|
-
api_key:
|
|
113
|
-
token:
|
|
113
|
+
api_key: SerializableSecretStr = Field(default="default")
|
|
114
|
+
token: SerializableSecretStr = Field(default="default")
|
|
114
115
|
|
|
115
116
|
|
|
116
117
|
UserContent = typing.Annotated[TextContent | ImageContent | AudioContent, Discriminator("type")]
|
nat/data_models/common.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
import inspect
|
|
17
|
+
import os
|
|
17
18
|
import sys
|
|
18
19
|
import typing
|
|
19
20
|
from hashlib import sha512
|
|
@@ -192,5 +193,26 @@ def get_secret_value(v: SecretStr | None) -> str | None:
|
|
|
192
193
|
return v.get_secret_value()
|
|
193
194
|
|
|
194
195
|
|
|
196
|
+
def set_secret_from_env(model: BaseModel, field_name: str, env_var: str):
|
|
197
|
+
"""
|
|
198
|
+
Set a SecretStr field in a Pydantic model from an environment variable, but only if the environment variable is set.
|
|
199
|
+
|
|
200
|
+
Parameters
|
|
201
|
+
----------
|
|
202
|
+
model: BaseModel
|
|
203
|
+
The Pydantic model instance containing the field to set.
|
|
204
|
+
field_name: str
|
|
205
|
+
The name of the field in the model to set.
|
|
206
|
+
env_var: str
|
|
207
|
+
The name of the environment variable to read the secret value from.
|
|
208
|
+
"""
|
|
209
|
+
env_value = os.getenv(env_var)
|
|
210
|
+
if env_value is not None:
|
|
211
|
+
setattr(model, field_name, SecretStr(env_value))
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# A SecretStr that serializes to plain string
|
|
215
|
+
SerializableSecretStr = typing.Annotated[SecretStr, PlainSerializer(get_secret_value)]
|
|
216
|
+
|
|
195
217
|
# A SecretStr or None that serializes to plain string
|
|
196
218
|
OptionalSecretStr = typing.Annotated[SecretStr | None, PlainSerializer(get_secret_value)]
|
|
@@ -26,6 +26,7 @@ from pydantic import FilePath
|
|
|
26
26
|
from pydantic import Tag
|
|
27
27
|
|
|
28
28
|
from nat.data_models.common import BaseModelRegistryTag
|
|
29
|
+
from nat.data_models.common import SerializableSecretStr
|
|
29
30
|
from nat.data_models.common import TypedBaseModel
|
|
30
31
|
|
|
31
32
|
|
|
@@ -34,8 +35,8 @@ class EvalS3Config(BaseModel):
|
|
|
34
35
|
endpoint_url: str | None = None
|
|
35
36
|
region_name: str | None = None
|
|
36
37
|
bucket: str
|
|
37
|
-
access_key:
|
|
38
|
-
secret_key:
|
|
38
|
+
access_key: SerializableSecretStr
|
|
39
|
+
secret_key: SerializableSecretStr
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
class EvalFilterEntryConfig(BaseModel):
|
|
@@ -20,6 +20,7 @@ from pydantic import Field
|
|
|
20
20
|
from nat.builder.builder import Builder
|
|
21
21
|
from nat.builder.embedder import EmbedderProviderInfo
|
|
22
22
|
from nat.cli.register_workflow import register_embedder_provider
|
|
23
|
+
from nat.data_models.common import OptionalSecretStr
|
|
23
24
|
from nat.data_models.embedder import EmbedderBaseConfig
|
|
24
25
|
from nat.data_models.retry_mixin import RetryMixin
|
|
25
26
|
|
|
@@ -29,7 +30,7 @@ class AzureOpenAIEmbedderModelConfig(EmbedderBaseConfig, RetryMixin, name="azure
|
|
|
29
30
|
|
|
30
31
|
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
31
32
|
|
|
32
|
-
api_key:
|
|
33
|
+
api_key: OptionalSecretStr = Field(default=None, description="Azure OpenAI API key to interact with hosted model.")
|
|
33
34
|
api_version: str = Field(default="2025-04-01-preview", description="Azure OpenAI API version.")
|
|
34
35
|
azure_endpoint: str | None = Field(validation_alias=AliasChoices("azure_endpoint", "base_url"),
|
|
35
36
|
serialization_alias="azure_endpoint",
|
nat/embedder/nim_embedder.py
CHANGED
|
@@ -23,6 +23,7 @@ from pydantic import Field
|
|
|
23
23
|
from nat.builder.builder import Builder
|
|
24
24
|
from nat.builder.embedder import EmbedderProviderInfo
|
|
25
25
|
from nat.cli.register_workflow import register_embedder_provider
|
|
26
|
+
from nat.data_models.common import OptionalSecretStr
|
|
26
27
|
from nat.data_models.embedder import EmbedderBaseConfig
|
|
27
28
|
from nat.data_models.retry_mixin import RetryMixin
|
|
28
29
|
|
|
@@ -41,7 +42,7 @@ TruncationOption = typing.Annotated[str, AfterValidator(option_in_allowed_values
|
|
|
41
42
|
class NIMEmbedderModelConfig(EmbedderBaseConfig, RetryMixin, name="nim"):
|
|
42
43
|
"""A NVIDIA Inference Microservice (NIM) embedder provider to be used with an embedder client."""
|
|
43
44
|
|
|
44
|
-
api_key:
|
|
45
|
+
api_key: OptionalSecretStr = Field(default=None, description="NVIDIA API key to interact with hosted NIM.")
|
|
45
46
|
base_url: str | None = Field(default=None, description="Base url to the hosted NIM.")
|
|
46
47
|
model_name: str = Field(validation_alias=AliasChoices("model_name", "model"),
|
|
47
48
|
serialization_alias="model",
|
nat/embedder/openai_embedder.py
CHANGED
|
@@ -20,6 +20,7 @@ from pydantic import Field
|
|
|
20
20
|
from nat.builder.builder import Builder
|
|
21
21
|
from nat.builder.embedder import EmbedderProviderInfo
|
|
22
22
|
from nat.cli.register_workflow import register_embedder_provider
|
|
23
|
+
from nat.data_models.common import OptionalSecretStr
|
|
23
24
|
from nat.data_models.embedder import EmbedderBaseConfig
|
|
24
25
|
from nat.data_models.retry_mixin import RetryMixin
|
|
25
26
|
|
|
@@ -29,7 +30,7 @@ class OpenAIEmbedderModelConfig(EmbedderBaseConfig, RetryMixin, name="openai"):
|
|
|
29
30
|
|
|
30
31
|
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
31
32
|
|
|
32
|
-
api_key:
|
|
33
|
+
api_key: OptionalSecretStr = Field(default=None, description="OpenAI API key to interact with hosted model.")
|
|
33
34
|
base_url: str | None = Field(default=None, description="Base url to the hosted model.")
|
|
34
35
|
model_name: str = Field(validation_alias=AliasChoices("model_name", "model"),
|
|
35
36
|
serialization_alias="model",
|
|
@@ -19,6 +19,7 @@ import boto3
|
|
|
19
19
|
import requests
|
|
20
20
|
from botocore.exceptions import NoCredentialsError
|
|
21
21
|
|
|
22
|
+
from nat.data_models.common import get_secret_value
|
|
22
23
|
from nat.data_models.dataset_handler import EvalDatasetConfig
|
|
23
24
|
|
|
24
25
|
logger = logging.getLogger(__name__)
|
|
@@ -46,8 +47,8 @@ class DatasetDownloader:
|
|
|
46
47
|
try:
|
|
47
48
|
self._s3_client = boto3.client("s3",
|
|
48
49
|
endpoint_url=self.s3_config.endpoint_url,
|
|
49
|
-
aws_access_key_id=self.s3_config.access_key,
|
|
50
|
-
aws_secret_access_key=self.s3_config.secret_key)
|
|
50
|
+
aws_access_key_id=get_secret_value(self.s3_config.access_key),
|
|
51
|
+
aws_secret_access_key=get_secret_value(self.s3_config.secret_key))
|
|
51
52
|
except NoCredentialsError as e:
|
|
52
53
|
logger.error("AWS credentials not available: %s", e)
|
|
53
54
|
raise
|
|
@@ -24,6 +24,7 @@ import aioboto3
|
|
|
24
24
|
from botocore.exceptions import NoCredentialsError
|
|
25
25
|
from tqdm import tqdm
|
|
26
26
|
|
|
27
|
+
from nat.data_models.common import get_secret_value
|
|
27
28
|
from nat.data_models.evaluate import EvalOutputConfig
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
@@ -90,8 +91,8 @@ class OutputUploader:
|
|
|
90
91
|
"s3",
|
|
91
92
|
endpoint_url=endpoint_url,
|
|
92
93
|
region_name=region_name,
|
|
93
|
-
aws_access_key_id=self.s3_config.access_key,
|
|
94
|
-
aws_secret_access_key=self.s3_config.secret_key,
|
|
94
|
+
aws_access_key_id=get_secret_value(self.s3_config.access_key),
|
|
95
|
+
aws_secret_access_key=get_secret_value(self.s3_config.secret_key),
|
|
95
96
|
) as s3_client:
|
|
96
97
|
with tqdm(total=len(file_entries), desc="Uploading files to S3") as pbar:
|
|
97
98
|
upload_tasks = [
|
|
@@ -95,7 +95,7 @@ class ConsoleAuthenticationFlowHandler(FlowHandlerBase):
|
|
|
95
95
|
try:
|
|
96
96
|
client = AsyncOAuth2Client(
|
|
97
97
|
client_id=cfg.client_id,
|
|
98
|
-
client_secret=cfg.client_secret,
|
|
98
|
+
client_secret=cfg.client_secret.get_secret_value(),
|
|
99
99
|
redirect_uri=cfg.redirect_uri,
|
|
100
100
|
scope=" ".join(cfg.scopes) if cfg.scopes else None,
|
|
101
101
|
token_endpoint=cfg.token_url,
|
|
@@ -18,9 +18,12 @@ import logging
|
|
|
18
18
|
from inspect import Parameter
|
|
19
19
|
from inspect import Signature
|
|
20
20
|
from typing import TYPE_CHECKING
|
|
21
|
+
from typing import Any
|
|
21
22
|
|
|
22
23
|
from mcp.server.fastmcp import FastMCP
|
|
23
24
|
from pydantic import BaseModel
|
|
25
|
+
from pydantic.fields import FieldInfo
|
|
26
|
+
from pydantic_core import PydanticUndefined
|
|
24
27
|
|
|
25
28
|
from nat.builder.context import ContextState
|
|
26
29
|
from nat.builder.function import Function
|
|
@@ -32,6 +35,41 @@ if TYPE_CHECKING:
|
|
|
32
35
|
|
|
33
36
|
logger = logging.getLogger(__name__)
|
|
34
37
|
|
|
38
|
+
# Sentinel: marks "optional; let Pydantic supply default/factory"
|
|
39
|
+
_USE_PYDANTIC_DEFAULT = object()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def is_field_optional(field: FieldInfo) -> tuple[bool, Any]:
|
|
43
|
+
"""Determine if a Pydantic field is optional and extract its default value for MCP signatures.
|
|
44
|
+
|
|
45
|
+
For MCP tool signatures, we need to distinguish:
|
|
46
|
+
- Required fields: marked with Parameter.empty
|
|
47
|
+
- Optional with concrete default: use that default
|
|
48
|
+
- Optional with factory: use sentinel so Pydantic can apply the factory later
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
field: The Pydantic FieldInfo to check
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
A tuple of (is_optional, default_value):
|
|
55
|
+
- (False, Parameter.empty) for required fields
|
|
56
|
+
- (True, actual_default) for optional fields with explicit defaults
|
|
57
|
+
- (True, _USE_PYDANTIC_DEFAULT) for optional fields with default_factory
|
|
58
|
+
"""
|
|
59
|
+
if field.is_required():
|
|
60
|
+
return False, Parameter.empty
|
|
61
|
+
|
|
62
|
+
# Field is optional - has either default or factory
|
|
63
|
+
if field.default is not PydanticUndefined:
|
|
64
|
+
return True, field.default
|
|
65
|
+
|
|
66
|
+
# Factory case: mark optional in signature but don't fabricate a value
|
|
67
|
+
if field.default_factory is not None:
|
|
68
|
+
return True, _USE_PYDANTIC_DEFAULT
|
|
69
|
+
|
|
70
|
+
# Rare corner case: non-required yet no default surfaced
|
|
71
|
+
return True, _USE_PYDANTIC_DEFAULT
|
|
72
|
+
|
|
35
73
|
|
|
36
74
|
def create_function_wrapper(
|
|
37
75
|
function_name: str,
|
|
@@ -79,12 +117,15 @@ def create_function_wrapper(
|
|
|
79
117
|
# Get the field type and convert to appropriate Python type
|
|
80
118
|
field_type = field.annotation
|
|
81
119
|
|
|
120
|
+
# Check if field is optional and get its default value
|
|
121
|
+
_is_optional, param_default = is_field_optional(field)
|
|
122
|
+
|
|
82
123
|
# Add the parameter to our list
|
|
83
124
|
parameters.append(
|
|
84
125
|
Parameter(
|
|
85
126
|
name=name,
|
|
86
127
|
kind=Parameter.KEYWORD_ONLY,
|
|
87
|
-
default=
|
|
128
|
+
default=param_default,
|
|
88
129
|
annotation=field_type,
|
|
89
130
|
))
|
|
90
131
|
|
|
@@ -143,33 +184,23 @@ def create_function_wrapper(
|
|
|
143
184
|
result = await call_with_observability(lambda: function.ainvoke(chat_request, to_type=str))
|
|
144
185
|
else:
|
|
145
186
|
# Regular handling
|
|
146
|
-
#
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
# If it's a pydantic model, we need to create an instance
|
|
154
|
-
if field_type and hasattr(field_type, "model_validate"):
|
|
155
|
-
# Create the nested object
|
|
156
|
-
nested_obj = field_type.model_validate(kwargs)
|
|
157
|
-
# Call with the nested object
|
|
158
|
-
kwargs = {field_name: nested_obj}
|
|
187
|
+
# Strip sentinel values so Pydantic can apply defaults/factories
|
|
188
|
+
cleaned_kwargs = {k: v for k, v in kwargs.items() if v is not _USE_PYDANTIC_DEFAULT}
|
|
189
|
+
|
|
190
|
+
# Always validate with the declared schema
|
|
191
|
+
# This handles defaults, factories, nested models, validators, etc.
|
|
192
|
+
model_input = schema.model_validate(cleaned_kwargs)
|
|
159
193
|
|
|
160
194
|
# Call the NAT function with the parameters - special handling for Workflow
|
|
161
195
|
if is_workflow:
|
|
162
|
-
#
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# Workflows have a run method that is an async context manager
|
|
166
|
-
# that returns a Runner
|
|
167
|
-
async with function.run(input_value) as runner:
|
|
196
|
+
# Workflows expect the model instance directly
|
|
197
|
+
async with function.run(model_input) as runner:
|
|
168
198
|
# Get the result from the runner
|
|
169
199
|
result = await runner.result(to_type=str)
|
|
170
200
|
else:
|
|
171
|
-
# Regular function call
|
|
172
|
-
result = await call_with_observability(lambda: function.acall_invoke(**
|
|
201
|
+
# Regular function call - unpack the validated model
|
|
202
|
+
result = await call_with_observability(lambda: function.acall_invoke(**model_input.model_dump())
|
|
203
|
+
)
|
|
173
204
|
|
|
174
205
|
# Report completion
|
|
175
206
|
if ctx:
|
nat/llm/azure_openai_llm.py
CHANGED
|
@@ -20,6 +20,7 @@ from pydantic import Field
|
|
|
20
20
|
from nat.builder.builder import Builder
|
|
21
21
|
from nat.builder.llm import LLMProviderInfo
|
|
22
22
|
from nat.cli.register_workflow import register_llm_provider
|
|
23
|
+
from nat.data_models.common import OptionalSecretStr
|
|
23
24
|
from nat.data_models.llm import LLMBaseConfig
|
|
24
25
|
from nat.data_models.retry_mixin import RetryMixin
|
|
25
26
|
from nat.data_models.temperature_mixin import TemperatureMixin
|
|
@@ -39,7 +40,7 @@ class AzureOpenAIModelConfig(
|
|
|
39
40
|
|
|
40
41
|
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
41
42
|
|
|
42
|
-
api_key:
|
|
43
|
+
api_key: OptionalSecretStr = Field(default=None, description="Azure OpenAI API key to interact with hosted model.")
|
|
43
44
|
api_version: str = Field(default="2025-04-01-preview", description="Azure OpenAI API version.")
|
|
44
45
|
azure_endpoint: str | None = Field(validation_alias=AliasChoices("azure_endpoint", "base_url"),
|
|
45
46
|
serialization_alias="azure_endpoint",
|
nat/llm/litellm_llm.py
CHANGED
|
@@ -22,6 +22,7 @@ from pydantic import Field
|
|
|
22
22
|
from nat.builder.builder import Builder
|
|
23
23
|
from nat.builder.llm import LLMProviderInfo
|
|
24
24
|
from nat.cli.register_workflow import register_llm_provider
|
|
25
|
+
from nat.data_models.common import OptionalSecretStr
|
|
25
26
|
from nat.data_models.llm import LLMBaseConfig
|
|
26
27
|
from nat.data_models.optimizable import OptimizableField
|
|
27
28
|
from nat.data_models.optimizable import OptimizableMixin
|
|
@@ -44,7 +45,7 @@ class LiteLlmModelConfig(
|
|
|
44
45
|
|
|
45
46
|
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
46
47
|
|
|
47
|
-
api_key:
|
|
48
|
+
api_key: OptionalSecretStr = Field(default=None, description="API key to interact with hosted model.")
|
|
48
49
|
base_url: str | None = Field(default=None,
|
|
49
50
|
description="Base url to the hosted model.",
|
|
50
51
|
validation_alias=AliasChoices("base_url", "api_base"),
|
nat/llm/nim_llm.py
CHANGED
|
@@ -21,6 +21,7 @@ from pydantic import PositiveInt
|
|
|
21
21
|
from nat.builder.builder import Builder
|
|
22
22
|
from nat.builder.llm import LLMProviderInfo
|
|
23
23
|
from nat.cli.register_workflow import register_llm_provider
|
|
24
|
+
from nat.data_models.common import OptionalSecretStr
|
|
24
25
|
from nat.data_models.llm import LLMBaseConfig
|
|
25
26
|
from nat.data_models.optimizable import OptimizableField
|
|
26
27
|
from nat.data_models.optimizable import OptimizableMixin
|
|
@@ -42,7 +43,7 @@ class NIMModelConfig(LLMBaseConfig,
|
|
|
42
43
|
|
|
43
44
|
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
44
45
|
|
|
45
|
-
api_key:
|
|
46
|
+
api_key: OptionalSecretStr = Field(default=None, description="NVIDIA API key to interact with hosted NIM.")
|
|
46
47
|
base_url: str | None = Field(default=None, description="Base url to the hosted NIM.")
|
|
47
48
|
model_name: str = OptimizableField(validation_alias=AliasChoices("model_name", "model"),
|
|
48
49
|
serialization_alias="model",
|
nat/llm/openai_llm.py
CHANGED
|
@@ -20,6 +20,7 @@ from pydantic import Field
|
|
|
20
20
|
from nat.builder.builder import Builder
|
|
21
21
|
from nat.builder.llm import LLMProviderInfo
|
|
22
22
|
from nat.cli.register_workflow import register_llm_provider
|
|
23
|
+
from nat.data_models.common import OptionalSecretStr
|
|
23
24
|
from nat.data_models.llm import LLMBaseConfig
|
|
24
25
|
from nat.data_models.optimizable import OptimizableField
|
|
25
26
|
from nat.data_models.optimizable import OptimizableMixin
|
|
@@ -40,7 +41,7 @@ class OpenAIModelConfig(LLMBaseConfig,
|
|
|
40
41
|
|
|
41
42
|
model_config = ConfigDict(protected_namespaces=(), extra="allow")
|
|
42
43
|
|
|
43
|
-
api_key:
|
|
44
|
+
api_key: OptionalSecretStr = Field(default=None, description="OpenAI API key to interact with hosted model.")
|
|
44
45
|
base_url: str | None = Field(default=None, description="Base url to the hosted model.")
|
|
45
46
|
model_name: str = OptimizableField(validation_alias=AliasChoices("model_name", "model"),
|
|
46
47
|
serialization_alias="model",
|
|
@@ -111,7 +111,10 @@ def optimize_parameters(
|
|
|
111
111
|
tasks = [_single_eval(i) for i in range(reps)]
|
|
112
112
|
return await asyncio.gather(*tasks)
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
# Calculate padding width based on total number of trials
|
|
115
|
+
trial_id_width = len(str(max(0, optimizer_config.numeric.n_trials - 1)))
|
|
116
|
+
trial_id_padded = f"{trial.number:0{trial_id_width}d}"
|
|
117
|
+
with (out_dir / f"config_numeric_trial_{trial_id_padded}.yml").open("w") as fh:
|
|
115
118
|
yaml.dump(cfg_trial.model_dump(), fh)
|
|
116
119
|
|
|
117
120
|
all_scores = asyncio.run(_run_all_evals())
|
|
@@ -132,7 +135,7 @@ def optimize_parameters(
|
|
|
132
135
|
|
|
133
136
|
# Save final results (out_dir already created and defined above)
|
|
134
137
|
with (out_dir / "optimized_config.yml").open("w") as fh:
|
|
135
|
-
yaml.dump(tuned_cfg.model_dump(), fh)
|
|
138
|
+
yaml.dump(tuned_cfg.model_dump(mode='json'), fh)
|
|
136
139
|
with (out_dir / "trials_dataframe_params.csv").open("w") as fh:
|
|
137
140
|
# Export full trials DataFrame (values, params, timings, etc.).
|
|
138
141
|
df = study.trials_dataframe()
|
|
@@ -154,6 +157,13 @@ def optimize_parameters(
|
|
|
154
157
|
# Some Optuna versions return a dict in a single user_attrs column.
|
|
155
158
|
df["rep_scores"] = df["user_attrs"].apply(lambda d: d.get("rep_scores") if isinstance(d, dict) else None)
|
|
156
159
|
df = df.drop(columns=["user_attrs"])
|
|
160
|
+
|
|
161
|
+
# Get Pareto optimal trial numbers from Optuna study
|
|
162
|
+
pareto_trials = study.best_trials
|
|
163
|
+
pareto_trial_numbers = {trial.number for trial in pareto_trials}
|
|
164
|
+
# Add boolean column indicating if trial is Pareto optimal
|
|
165
|
+
df["pareto_optimal"] = df["number"].isin(pareto_trial_numbers)
|
|
166
|
+
|
|
157
167
|
df.to_csv(fh, index=False)
|
|
158
168
|
|
|
159
169
|
# Generate Pareto front visualizations
|
|
@@ -21,6 +21,8 @@ import matplotlib.pyplot as plt
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
import optuna
|
|
23
23
|
import pandas as pd
|
|
24
|
+
from matplotlib.lines import Line2D
|
|
25
|
+
from matplotlib.patches import Patch
|
|
24
26
|
|
|
25
27
|
logger = logging.getLogger(__name__)
|
|
26
28
|
|
|
@@ -79,6 +81,19 @@ class ParetoVisualizer:
|
|
|
79
81
|
linewidths=1.5,
|
|
80
82
|
marker='*')
|
|
81
83
|
|
|
84
|
+
# Add trial number labels to Pareto optimal points
|
|
85
|
+
for idx in range(len(pareto_trials_df)):
|
|
86
|
+
trial_number = pareto_trials_df.iloc[idx]['number'] \
|
|
87
|
+
if 'number' in pareto_trials_df.columns else pareto_trials_df.index[idx]
|
|
88
|
+
ax.annotate(f'{int(trial_number)}',
|
|
89
|
+
xy=(pareto_x[idx], pareto_y[idx]),
|
|
90
|
+
xytext=(8, 8),
|
|
91
|
+
textcoords='offset points',
|
|
92
|
+
fontsize=9,
|
|
93
|
+
fontweight='bold',
|
|
94
|
+
color='darkred',
|
|
95
|
+
bbox=dict(boxstyle='round,pad=0.3', facecolor='white', edgecolor='red', alpha=0.9))
|
|
96
|
+
|
|
82
97
|
# Draw Pareto front line (only for 2D)
|
|
83
98
|
if len(pareto_x) > 1:
|
|
84
99
|
# Sort points for line drawing based on first objective
|
|
@@ -182,6 +197,18 @@ class ParetoVisualizer:
|
|
|
182
197
|
trial_values = [normalized_values[j][idx] for j in range(n_metrics)]
|
|
183
198
|
ax.plot(x_positions, trial_values, 'r-', alpha=0.8, linewidth=3)
|
|
184
199
|
|
|
200
|
+
# Add trial number label at the rightmost point
|
|
201
|
+
trial_number = trials_df.iloc[idx]['number'] if 'number' in trials_df.columns else idx
|
|
202
|
+
# Position label slightly to the right and above the last point
|
|
203
|
+
ax.annotate(f'{int(trial_number)}',
|
|
204
|
+
xy=(x_positions[-1], trial_values[-1]),
|
|
205
|
+
xytext=(5, 5),
|
|
206
|
+
textcoords='offset points',
|
|
207
|
+
fontsize=9,
|
|
208
|
+
fontweight='bold',
|
|
209
|
+
color='darkred',
|
|
210
|
+
bbox=dict(boxstyle='round,pad=0.3', facecolor='white', edgecolor='red', alpha=0.8))
|
|
211
|
+
|
|
185
212
|
# Customize plot
|
|
186
213
|
ax.set_xticks(x_positions)
|
|
187
214
|
ax.set_xticklabels([f"{name}\n({direction})" for name, direction in zip(self.metric_names, self.directions)])
|
|
@@ -191,10 +218,10 @@ class ParetoVisualizer:
|
|
|
191
218
|
ax.grid(True, alpha=0.3)
|
|
192
219
|
|
|
193
220
|
# Add legend
|
|
194
|
-
from matplotlib.lines import Line2D
|
|
195
221
|
legend_elements = [
|
|
196
222
|
Line2D([0], [0], color='blue', alpha=0.3, linewidth=2, label='All Trials'),
|
|
197
|
-
Line2D([0], [0], color='red', alpha=0.8, linewidth=3, label='Pareto Optimal')
|
|
223
|
+
Line2D([0], [0], color='red', alpha=0.8, linewidth=3, label='Pareto Optimal'),
|
|
224
|
+
Patch(facecolor='white', edgecolor='red', label='[n]: trial number')
|
|
198
225
|
]
|
|
199
226
|
ax.legend(handles=legend_elements, loc='best')
|
|
200
227
|
|
|
@@ -262,11 +289,49 @@ class ParetoVisualizer:
|
|
|
262
289
|
linewidths=1,
|
|
263
290
|
marker='*')
|
|
264
291
|
|
|
292
|
+
# Add trial number labels to Pareto optimal points
|
|
293
|
+
for idx in range(len(pareto_trials_df)):
|
|
294
|
+
trial_number = pareto_trials_df.iloc[idx]['number'] \
|
|
295
|
+
if 'number' in pareto_trials_df.columns else pareto_trials_df.index[idx]
|
|
296
|
+
ax.annotate(f'{int(trial_number)}',
|
|
297
|
+
xy=(pareto_x[idx], pareto_y[idx]),
|
|
298
|
+
xytext=(6, 6),
|
|
299
|
+
textcoords='offset points',
|
|
300
|
+
fontsize=8,
|
|
301
|
+
fontweight='bold',
|
|
302
|
+
color='darkred',
|
|
303
|
+
bbox=dict(boxstyle='round,pad=0.2',
|
|
304
|
+
facecolor='white',
|
|
305
|
+
edgecolor='red',
|
|
306
|
+
alpha=0.8))
|
|
307
|
+
|
|
265
308
|
ax.set_xlabel(f"{self.metric_names[j]} ({self.directions[j]})")
|
|
266
309
|
ax.set_ylabel(f"{self.metric_names[i]} ({self.directions[i]})")
|
|
267
310
|
|
|
268
311
|
ax.grid(True, alpha=0.3)
|
|
269
312
|
|
|
313
|
+
# Add legend to the figure
|
|
314
|
+
legend_elements = [
|
|
315
|
+
Line2D([0], [0],
|
|
316
|
+
marker='o',
|
|
317
|
+
color='w',
|
|
318
|
+
markerfacecolor='lightblue',
|
|
319
|
+
markeredgecolor='navy',
|
|
320
|
+
markersize=8,
|
|
321
|
+
alpha=0.6,
|
|
322
|
+
label='All Trials'),
|
|
323
|
+
Line2D([0], [0],
|
|
324
|
+
marker='*',
|
|
325
|
+
color='w',
|
|
326
|
+
markerfacecolor='red',
|
|
327
|
+
markeredgecolor='darkred',
|
|
328
|
+
markersize=10,
|
|
329
|
+
alpha=0.9,
|
|
330
|
+
label='Pareto Optimal'),
|
|
331
|
+
Patch(facecolor='white', edgecolor='red', label='[n]: trial number')
|
|
332
|
+
]
|
|
333
|
+
fig.legend(handles=legend_elements, loc='upper right', bbox_to_anchor=(0.98, 0.98), framealpha=0.9, fontsize=10)
|
|
334
|
+
|
|
270
335
|
plt.tight_layout()
|
|
271
336
|
|
|
272
337
|
if save_path:
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
from pydantic import Field
|
|
17
17
|
|
|
18
18
|
from nat.cli.register_workflow import register_registry_handler
|
|
19
|
+
from nat.data_models.common import OptionalSecretStr
|
|
20
|
+
from nat.data_models.common import get_secret_value
|
|
19
21
|
from nat.data_models.registry_handler import RegistryHandlerBaseConfig
|
|
20
22
|
|
|
21
23
|
|
|
@@ -23,8 +25,8 @@ class PypiRegistryHandlerConfig(RegistryHandlerBaseConfig, name="pypi"):
|
|
|
23
25
|
"""Registry handler for interacting with a remote PyPI registry index."""
|
|
24
26
|
|
|
25
27
|
endpoint: str = Field(description="A string representing the remote endpoint.")
|
|
26
|
-
token:
|
|
27
|
-
|
|
28
|
+
token: OptionalSecretStr = Field(default=None,
|
|
29
|
+
description="The authentication token to use when interacting with the registry.")
|
|
28
30
|
publish_route: str = Field(description="The route to the NAT publish service.")
|
|
29
31
|
pull_route: str = Field(description="The route to the NAT pull service.")
|
|
30
32
|
search_route: str = Field(default="simple", description="The route to the NAT search service.")
|
|
@@ -35,6 +37,6 @@ async def pypi_publish_registry_handler(config: PypiRegistryHandlerConfig):
|
|
|
35
37
|
|
|
36
38
|
from nat.registry_handlers.pypi.pypi_handler import PypiRegistryHandler
|
|
37
39
|
|
|
38
|
-
registry_handler = PypiRegistryHandler(endpoint=config.endpoint, token=config.token)
|
|
40
|
+
registry_handler = PypiRegistryHandler(endpoint=config.endpoint, token=get_secret_value(config.token))
|
|
39
41
|
|
|
40
42
|
yield registry_handler
|
|
@@ -18,6 +18,8 @@ import os
|
|
|
18
18
|
from pydantic import Field
|
|
19
19
|
|
|
20
20
|
from nat.cli.register_workflow import register_registry_handler
|
|
21
|
+
from nat.data_models.common import OptionalSecretStr
|
|
22
|
+
from nat.data_models.common import get_secret_value
|
|
21
23
|
from nat.data_models.registry_handler import RegistryHandlerBaseConfig
|
|
22
24
|
|
|
23
25
|
|
|
@@ -25,8 +27,8 @@ class RestRegistryHandlerConfig(RegistryHandlerBaseConfig, name="rest"):
|
|
|
25
27
|
"""Registry handler for interacting with a remote REST registry."""
|
|
26
28
|
|
|
27
29
|
endpoint: str = Field(description="A string representing the remote endpoint.")
|
|
28
|
-
token:
|
|
29
|
-
|
|
30
|
+
token: OptionalSecretStr = Field(default=None,
|
|
31
|
+
description="The authentication token to use when interacting with the registry.")
|
|
30
32
|
publish_route: str = Field(default="", description="The route to the NAT publish service.")
|
|
31
33
|
pull_route: str = Field(default="", description="The route to the NAT pull service.")
|
|
32
34
|
search_route: str = Field(default="", description="The route to the NAT search service")
|
|
@@ -44,7 +46,7 @@ async def rest_search_handler(config: RestRegistryHandlerConfig):
|
|
|
44
46
|
if (registry_token is None):
|
|
45
47
|
raise ValueError("Please supply registry token.")
|
|
46
48
|
else:
|
|
47
|
-
registry_token = config.token
|
|
49
|
+
registry_token = get_secret_value(config.token)
|
|
48
50
|
|
|
49
51
|
registry_handler = RestRegistryHandler(token=registry_token,
|
|
50
52
|
endpoint=config.endpoint,
|
|
@@ -20,6 +20,7 @@ from nat.builder.builder import Builder
|
|
|
20
20
|
from nat.builder.retriever import RetrieverProviderInfo
|
|
21
21
|
from nat.cli.register_workflow import register_retriever_client
|
|
22
22
|
from nat.cli.register_workflow import register_retriever_provider
|
|
23
|
+
from nat.data_models.common import OptionalSecretStr
|
|
23
24
|
from nat.data_models.retriever import RetrieverBaseConfig
|
|
24
25
|
|
|
25
26
|
|
|
@@ -34,7 +35,7 @@ class NemoRetrieverConfig(RetrieverBaseConfig, name="nemo_retriever"):
|
|
|
34
35
|
default=None,
|
|
35
36
|
description="A list of fields to return from the datastore. If 'None', all fields but the vector are returned.")
|
|
36
37
|
timeout: int = Field(default=60, description="Maximum time to wait for results to be returned from the service.")
|
|
37
|
-
nvidia_api_key:
|
|
38
|
+
nvidia_api_key: OptionalSecretStr = Field(
|
|
38
39
|
description="API key used to authenticate with the service. If 'None', will use ENV Variable 'NVIDIA_API_KEY'",
|
|
39
40
|
default=None,
|
|
40
41
|
)
|
|
@@ -26,8 +26,8 @@ nat/authentication/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7
|
|
|
26
26
|
nat/authentication/interfaces.py,sha256=1J2CWEJ_n6CLA3_HD3XV28CSbyfxrPAHzr7Q4kKDFdc,3511
|
|
27
27
|
nat/authentication/register.py,sha256=lFhswYUk9iZ53mq33fClR9UfjJPdjGIivGGNHQeWiYo,915
|
|
28
28
|
nat/authentication/api_key/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
|
29
|
-
nat/authentication/api_key/api_key_auth_provider.py,sha256=
|
|
30
|
-
nat/authentication/api_key/api_key_auth_provider_config.py,sha256=
|
|
29
|
+
nat/authentication/api_key/api_key_auth_provider.py,sha256=J6WNarzdLIT1dRLM0wbYlcgypddNNGhgo9ExfQodM1I,3849
|
|
30
|
+
nat/authentication/api_key/api_key_auth_provider_config.py,sha256=RLywkXGxfQlKnTW0Rz3a5qGgqyHV1B8ec8w2_nv3Dl8,5628
|
|
31
31
|
nat/authentication/api_key/register.py,sha256=Mhv3WyZ9H7C2JN8VuPvwlsJEZrwXJCLXCIokkN9RrP0,1147
|
|
32
32
|
nat/authentication/credential_validator/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
|
33
33
|
nat/authentication/credential_validator/bearer_token_validator.py,sha256=cwGENd_bp-u2Y_JCRbEPxFkulk_vREpLog5c83h1nRU,21250
|
|
@@ -38,8 +38,8 @@ nat/authentication/http_basic_auth/http_basic_auth_provider.py,sha256=OXr5TV87Si
|
|
|
38
38
|
nat/authentication/http_basic_auth/register.py,sha256=N2VD0vw7cYABsLxsGXl5yw0htc8adkrB0Y_EMxKwFfk,1235
|
|
39
39
|
nat/authentication/oauth2/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
40
40
|
nat/authentication/oauth2/oauth2_auth_code_flow_provider.py,sha256=NXsVATFxQ10Gg_nrW7Ljft2VXlAj460TeoXL-ww4WZc,5804
|
|
41
|
-
nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py,sha256=
|
|
42
|
-
nat/authentication/oauth2/oauth2_resource_server_config.py,sha256=
|
|
41
|
+
nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py,sha256=R261a2QU2ZUiyY2GjMc3xJpPYqPzydSKVSGhgyj7Do0,2279
|
|
42
|
+
nat/authentication/oauth2/oauth2_resource_server_config.py,sha256=WtqFMsJ-FzIjP7tjqs-tdYN4Pck0wxvdSyKIObNtU_8,5374
|
|
43
43
|
nat/authentication/oauth2/register.py,sha256=7rXhf-ilgSS_bUJsd9pOOCotL1FM8dKUt3ke1TllKkQ,1228
|
|
44
44
|
nat/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
45
|
nat/builder/builder.py,sha256=okI3Y101hwF63AwazzxiahQx-W9eFZ_SNdFXzDuoftU,11608
|
|
@@ -114,13 +114,13 @@ nat/control_flow/router_agent/prompt.py,sha256=fIAiNsAs1zXRAatButR76zSpHJNxSkXXK
|
|
|
114
114
|
nat/control_flow/router_agent/register.py,sha256=4RGmS9sy-QtIMmvh8mfMcR1VqxFPLpG4RckWCIExh40,4144
|
|
115
115
|
nat/data_models/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
116
116
|
nat/data_models/agent.py,sha256=IwDyb9Zc3R4Zd5rFeqt7q0EQswczAl5focxV9KozIzs,1625
|
|
117
|
-
nat/data_models/api_server.py,sha256=
|
|
117
|
+
nat/data_models/api_server.py,sha256=sX_faprmycij1Zy_PQqEMtAcbvGD8PG1kWKLAyNQx6M,30775
|
|
118
118
|
nat/data_models/authentication.py,sha256=XPu9W8nh4XRSuxPv3HxO-FMQ_JtTEoK6Y02JwnzDwTg,8457
|
|
119
|
-
nat/data_models/common.py,sha256=
|
|
119
|
+
nat/data_models/common.py,sha256=dOtZI6g9AvFplu40nTsUDnahafVa9c2VITq19V_cb50,7302
|
|
120
120
|
nat/data_models/component.py,sha256=b_hXOA8Gm5UNvlFkAhsR6kEvf33ST50MKtr5kWf75Ao,1894
|
|
121
121
|
nat/data_models/component_ref.py,sha256=KFDWFVCcvJCfBBcXTh9f3R802EVHBtHXh9OdbRqFmdM,4747
|
|
122
122
|
nat/data_models/config.py,sha256=P0JJmjqvUHUkpZ3Yc0IrMPoA2qP8HkmOjl7CwNq-nQQ,18833
|
|
123
|
-
nat/data_models/dataset_handler.py,sha256=
|
|
123
|
+
nat/data_models/dataset_handler.py,sha256=1zz0456WGcGdLA9bodbMd1EMtQC8pns8TpvjNkk27No,5611
|
|
124
124
|
nat/data_models/discovery_metadata.py,sha256=_l97iQsqp_ihba8CbMBQ73mH1sipTQ19GiJDdzQYQGY,13432
|
|
125
125
|
nat/data_models/embedder.py,sha256=nPhthEQDtzAMGd8gFRB1ZfJpN5M9DJvv0h28ohHnTmI,1002
|
|
126
126
|
nat/data_models/evaluate.py,sha256=L0GdNh_c8jii-MiK8oHW9sUUsGO3l1FMsprr-UazT5c,4836
|
|
@@ -153,9 +153,9 @@ nat/data_models/thinking_mixin.py,sha256=VRDUJZ8XP_Vv0gW2FRZUf8O9-kVgNEdZCEZ8oEm
|
|
|
153
153
|
nat/data_models/top_p_mixin.py,sha256=mu0DLnCAiwNzpSFR8FOW4kQBUpodSrvUR4MsLrNtbgA,1599
|
|
154
154
|
nat/data_models/ttc_strategy.py,sha256=tAkKWcyEBmBOOYtHMtQTgeCbHxFTk5SEkmFunNVnfyE,1114
|
|
155
155
|
nat/embedder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
156
|
-
nat/embedder/azure_openai_embedder.py,sha256=
|
|
157
|
-
nat/embedder/nim_embedder.py,sha256=
|
|
158
|
-
nat/embedder/openai_embedder.py,sha256=
|
|
156
|
+
nat/embedder/azure_openai_embedder.py,sha256=yMHOA6lWZl15Pvd9Gpp_rHy5q2qmBiRjbFesFBGuC_U,2441
|
|
157
|
+
nat/embedder/nim_embedder.py,sha256=BDwqixfzToXoOg4vkHcLAhoCGzwfJjixcDAGYGM8Sok,2592
|
|
158
|
+
nat/embedder/openai_embedder.py,sha256=To7aCg8UyWPwSoA0MAHanH_MAKFDi3EcZxgLU1xYE9M,1997
|
|
159
159
|
nat/embedder/register.py,sha256=TM_LKuSlJr3tEceNVuHfAx_yrCzf1sryD5Ycep5rNGo,883
|
|
160
160
|
nat/eval/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
161
161
|
nat/eval/config.py,sha256=G0LE4JpZaQy3PvERldVATFpQCiDQcVJGUFChgorqzNo,2377
|
|
@@ -166,7 +166,7 @@ nat/eval/remote_workflow.py,sha256=JAAbD0s753AOjo9baT4OqcB5dVEDmN34jPe0Uk13LcU,6
|
|
|
166
166
|
nat/eval/runtime_event_subscriber.py,sha256=9MVgZLKvpnThHINaPbszPYDWnJ61sntS09YZtDhIRE4,1900
|
|
167
167
|
nat/eval/usage_stats.py,sha256=r8Zr3bIy2qXU1BgVKXr_4mr7bG0hte3BPNQLSgZvg8M,1376
|
|
168
168
|
nat/eval/dataset_handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
169
|
-
nat/eval/dataset_handler/dataset_downloader.py,sha256=
|
|
169
|
+
nat/eval/dataset_handler/dataset_downloader.py,sha256=ZaNohbRSvoHPWIj0C_FqyJnhQKoTBk_uZF7ijjfk6vE,4641
|
|
170
170
|
nat/eval/dataset_handler/dataset_filter.py,sha256=HrK0m3SQnPX6zOcKwJwYMrD9O-f6aOw8Vo3j9RKszqE,2115
|
|
171
171
|
nat/eval/dataset_handler/dataset_handler.py,sha256=my28rKvQiiRN_h2TJz6fdKeMOjP3LC3_e2aJNnPPYhE,18159
|
|
172
172
|
nat/eval/evaluator/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
|
@@ -192,7 +192,7 @@ nat/eval/tunable_rag_evaluator/evaluate.py,sha256=SzZYwE0juuNv6o9Pbddxi4edxRXlo8
|
|
|
192
192
|
nat/eval/tunable_rag_evaluator/register.py,sha256=jYhPz8Xwsxyb7E0xpkAcQFT20xjSoYd_4qOJ7ltvUzU,2558
|
|
193
193
|
nat/eval/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
194
194
|
nat/eval/utils/eval_trace_ctx.py,sha256=hN0YZ0wMOPzh9I-iSav-cGdxY3RWQWoE_tk5BxUf1mc,3264
|
|
195
|
-
nat/eval/utils/output_uploader.py,sha256=
|
|
195
|
+
nat/eval/utils/output_uploader.py,sha256=wtAaxvrJrjQPFt8mTLSz31sWDs09KmLkmyelMQOLDws,5667
|
|
196
196
|
nat/eval/utils/tqdm_position_registry.py,sha256=9CtpCk1wtYCSyieHPaSp8nlZu6EcNUOaUz2RTqfekrA,1286
|
|
197
197
|
nat/eval/utils/weave_eval.py,sha256=fma5x9JbWpWrfQbfMHcjMovlRVR0v35yfNt1Avt6Vro,7719
|
|
198
198
|
nat/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -235,7 +235,7 @@ nat/experimental/test_time_compute/selection/threshold_selector.py,sha256=9E__TM
|
|
|
235
235
|
nat/front_ends/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
236
236
|
nat/front_ends/register.py,sha256=_C6AFpsQ8hUXavKHaBMy0g137fOcLfEjyU0EAuYqtao,857
|
|
237
237
|
nat/front_ends/console/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
238
|
-
nat/front_ends/console/authentication_flow_handler.py,sha256=
|
|
238
|
+
nat/front_ends/console/authentication_flow_handler.py,sha256=ikZdzQH4uLJ_eWLDHcCAcXhOk_2gmnjVTjykuISeVQE,12166
|
|
239
239
|
nat/front_ends/console/console_front_end_config.py,sha256=wkMXk-RCdlEj3303kB1gh47UKJnubX2R-vzBzhedpS4,1318
|
|
240
240
|
nat/front_ends/console/console_front_end_plugin.py,sha256=rlh8rL8iJCczVJngBFMckNFB7ERqJGtX1QJr-iNKGyA,4670
|
|
241
241
|
nat/front_ends/console/register.py,sha256=2Kf6Mthx6jzWzU8YdhYIR1iABmZDvs1UXM_20npXWXs,1153
|
|
@@ -267,15 +267,15 @@ nat/front_ends/mcp/mcp_front_end_plugin.py,sha256=MVYJBCOhZAzUPlnXest6CYP3Gf0Ef1
|
|
|
267
267
|
nat/front_ends/mcp/mcp_front_end_plugin_worker.py,sha256=qoRbYLC_HWqSH_jSNb-w7R_qwOmLyXaUA5JK0SX33GA,15362
|
|
268
268
|
nat/front_ends/mcp/memory_profiler.py,sha256=OpcpLBAGCdQwYSFZbtAqdfncrnGYVjDcMpWydB71hjY,12811
|
|
269
269
|
nat/front_ends/mcp/register.py,sha256=3aJtgG5VaiqujoeU1-Eq7Hl5pWslIlIwGFU2ASLTXgM,1173
|
|
270
|
-
nat/front_ends/mcp/tool_converter.py,sha256=
|
|
270
|
+
nat/front_ends/mcp/tool_converter.py,sha256=IOHb8UoW_TVvRoiML2yi6nlbx13KgcmUsuYOGS3xYe0,13349
|
|
271
271
|
nat/front_ends/simple_base/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
272
272
|
nat/front_ends/simple_base/simple_front_end_plugin_base.py,sha256=py_yA9XAw-yHfK5cQJLM8ElnubEEM2ac8M0bvz-ScWs,1801
|
|
273
273
|
nat/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
274
274
|
nat/llm/aws_bedrock_llm.py,sha256=Qo6-7MUrh4qGzUQMsEPTyKEBp5D7DwU6e8LHoHwzQIs,3252
|
|
275
|
-
nat/llm/azure_openai_llm.py,sha256=
|
|
276
|
-
nat/llm/litellm_llm.py,sha256=
|
|
277
|
-
nat/llm/nim_llm.py,sha256=
|
|
278
|
-
nat/llm/openai_llm.py,sha256=
|
|
275
|
+
nat/llm/azure_openai_llm.py,sha256=IJ_o6W_NtR2rzaCowznyJUA8-5F4CG0scy3Nw2egoPs,2709
|
|
276
|
+
nat/llm/litellm_llm.py,sha256=060odQkgTR087LmFrgnpy_yP0nvUoHI25DahS5VUbgA,3003
|
|
277
|
+
nat/llm/nim_llm.py,sha256=2v5QC16Fk-Nczx2p9OP7hfPM7CsylbAEZlkJrkvLgKI,2789
|
|
278
|
+
nat/llm/openai_llm.py,sha256=vg4K05IUamsRz9SVs1GUJrabr38cs8JNa_jd52048cw,2637
|
|
279
279
|
nat/llm/register.py,sha256=7xDYdK4w4opAwIjzDM5x7moJXT3QeEGaGGc_nDfY0i4,1090
|
|
280
280
|
nat/llm/utils/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
|
281
281
|
nat/llm/utils/env_config_value.py,sha256=kBVsv0pEokIAfDQx5omR7_FevFv_5fTPswcbnvhVT2c,3548
|
|
@@ -371,9 +371,9 @@ nat/profiler/inference_optimization/experimental/prefix_span_analysis.py,sha256=
|
|
|
371
371
|
nat/profiler/parameter_optimization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
372
372
|
nat/profiler/parameter_optimization/optimizable_utils.py,sha256=93Pl8A14Zq_f3XsxSH-yFnEJ6B7W5hp7doPnPoLlRB4,3714
|
|
373
373
|
nat/profiler/parameter_optimization/optimizer_runtime.py,sha256=rXmCOq81o7ZorQOUYociVjuO3NO9CIjFBbwql2u_4H4,2715
|
|
374
|
-
nat/profiler/parameter_optimization/parameter_optimizer.py,sha256=
|
|
374
|
+
nat/profiler/parameter_optimization/parameter_optimizer.py,sha256=xKqKLOJaOi3EVZjT95zwKwHdX3AyYmMfxDxyhwtHal4,8256
|
|
375
375
|
nat/profiler/parameter_optimization/parameter_selection.py,sha256=pfnNQIx1evNICgChsOJXIFQHoL1R_kmh_vNDsVMC9kg,3982
|
|
376
|
-
nat/profiler/parameter_optimization/pareto_visualizer.py,sha256=
|
|
376
|
+
nat/profiler/parameter_optimization/pareto_visualizer.py,sha256=mE4Az9G_hw4CsAP8jgNl9H5L9KQjq82bxmIPEr63nEg,20537
|
|
377
377
|
nat/profiler/parameter_optimization/prompt_optimizer.py,sha256=_AmdeB1jRamd93qR5UqRy5LweYR3bjnD7zoLxzXYE0k,17658
|
|
378
378
|
nat/profiler/parameter_optimization/update_helpers.py,sha256=NxWhrGVchbjws85pPd-jS-C14_l70QvVSvEfENndVcY,2339
|
|
379
379
|
nat/registry_handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -386,9 +386,9 @@ nat/registry_handlers/local/local_handler.py,sha256=Dz-jRccF3NbSM9ddEzI7qckD-Ngj
|
|
|
386
386
|
nat/registry_handlers/local/register_local.py,sha256=EMcQ3tvDDic4YeViz3jNIQyrUiD0foriP11CuuEmrr0,1341
|
|
387
387
|
nat/registry_handlers/pypi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
388
388
|
nat/registry_handlers/pypi/pypi_handler.py,sha256=ec6oJjMO4msWTqahpP0L72O-iVckOFvrgcnpZuUlrw4,10070
|
|
389
|
-
nat/registry_handlers/pypi/register_pypi.py,sha256=
|
|
389
|
+
nat/registry_handlers/pypi/register_pypi.py,sha256=4TY6RLab99yIeQvfysZKFdsCWzTU81Dkxyb0yMONys0,1977
|
|
390
390
|
nat/registry_handlers/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
391
|
-
nat/registry_handlers/rest/register_rest.py,sha256=
|
|
391
|
+
nat/registry_handlers/rest/register_rest.py,sha256=anIc20Tkupnm0T7wFfo5g_9tvJwBJjtaCo3nfhZUAmI,2666
|
|
392
392
|
nat/registry_handlers/rest/rest_handler.py,sha256=Ez-seJyUqVYrR_kLrDFrA1kuzWIKeiJYY0GTrV9-qnA,9371
|
|
393
393
|
nat/registry_handlers/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
394
394
|
nat/registry_handlers/schemas/headers.py,sha256=LnVfCMNc3vRr-lRdFB8Cuv9Db5Ct-ACTapjWLaRg2os,1549
|
|
@@ -406,7 +406,7 @@ nat/retriever/milvus/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aM
|
|
|
406
406
|
nat/retriever/milvus/register.py,sha256=FaWvUFj4rU6qcui-G459Z-bQV-QAVR3PNONT1qu7jxs,4027
|
|
407
407
|
nat/retriever/milvus/retriever.py,sha256=wfWi-Ck17ZXbrCJE3MiEVD4DuVeeAkgifdAkoISqNa0,9485
|
|
408
408
|
nat/retriever/nemo_retriever/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
|
409
|
-
nat/retriever/nemo_retriever/register.py,sha256=
|
|
409
|
+
nat/retriever/nemo_retriever/register.py,sha256=j0K5wz4jS9LbSXMknKUjkZ5bnqLGqrkcKGKTQNSg0ro,2953
|
|
410
410
|
nat/retriever/nemo_retriever/retriever.py,sha256=gi3_qJFqE-iqRh3of_cmJg-SwzaQ3z24zA9LwY_MSLY,6930
|
|
411
411
|
nat/runtime/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
412
412
|
nat/runtime/loader.py,sha256=obUdAgZVYCPGC0R8u3wcoKFJzzSPQgJvrbU4OWygtog,7953
|
|
@@ -475,10 +475,10 @@ nat/utils/reactive/base/observer_base.py,sha256=6BiQfx26EMumotJ3KoVcdmFBYR_fnAss
|
|
|
475
475
|
nat/utils/reactive/base/subject_base.py,sha256=UQOxlkZTIeeyYmG5qLtDpNf_63Y7p-doEeUA08_R8ME,2521
|
|
476
476
|
nat/utils/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
477
477
|
nat/utils/settings/global_settings.py,sha256=9JaO6pxKT_Pjw6rxJRsRlFCXdVKCl_xUKU2QHZQWWNM,7294
|
|
478
|
-
nvidia_nat-1.4.
|
|
479
|
-
nvidia_nat-1.4.
|
|
480
|
-
nvidia_nat-1.4.
|
|
481
|
-
nvidia_nat-1.4.
|
|
482
|
-
nvidia_nat-1.4.
|
|
483
|
-
nvidia_nat-1.4.
|
|
484
|
-
nvidia_nat-1.4.
|
|
478
|
+
nvidia_nat-1.4.0a20251031.dist-info/licenses/LICENSE-3rd-party.txt,sha256=fOk5jMmCX9YoKWyYzTtfgl-SUy477audFC5hNY4oP7Q,284609
|
|
479
|
+
nvidia_nat-1.4.0a20251031.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
480
|
+
nvidia_nat-1.4.0a20251031.dist-info/METADATA,sha256=qPR0zmgu2THcW57-42J5cZOLVmw059YSyZV5ngsk-Gw,10248
|
|
481
|
+
nvidia_nat-1.4.0a20251031.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
482
|
+
nvidia_nat-1.4.0a20251031.dist-info/entry_points.txt,sha256=4jCqjyETMpyoWbCBf4GalZU8I_wbstpzwQNezdAVbbo,698
|
|
483
|
+
nvidia_nat-1.4.0a20251031.dist-info/top_level.txt,sha256=lgJWLkigiVZuZ_O1nxVnD_ziYBwgpE2OStdaCduMEGc,8
|
|
484
|
+
nvidia_nat-1.4.0a20251031.dist-info/RECORD,,
|
|
File without changes
|
{nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{nvidia_nat-1.4.0a20251029.dist-info → nvidia_nat-1.4.0a20251031.dist-info}/licenses/LICENSE.md
RENAMED
|
File without changes
|
|
File without changes
|