nvidia-nat 1.3.0a20251013__py3-none-any.whl → 1.3.0a20251022__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/agent/base.py +3 -3
- nat/agent/reasoning_agent/reasoning_agent.py +6 -6
- nat/agent/tool_calling_agent/agent.py +6 -10
- nat/builder/context.py +2 -1
- nat/builder/intermediate_step_manager.py +6 -2
- nat/data_models/api_server.py +83 -33
- nat/data_models/thinking_mixin.py +2 -2
- nat/eval/rag_evaluator/evaluate.py +7 -4
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +3 -0
- nat/front_ends/fastapi/message_handler.py +65 -40
- nat/front_ends/fastapi/message_validator.py +1 -2
- nat/front_ends/mcp/mcp_front_end_plugin.py +9 -6
- nat/profiler/parameter_optimization/parameter_optimizer.py +11 -0
- nat/profiler/parameter_optimization/pareto_visualizer.py +31 -16
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/METADATA +4 -4
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/RECORD +21 -21
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/entry_points.txt +0 -0
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/licenses/LICENSE.md +0 -0
- {nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/top_level.txt +0 -0
nat/agent/base.py
CHANGED
|
@@ -102,11 +102,11 @@ class BaseAgent(ABC):
|
|
|
102
102
|
AIMessage
|
|
103
103
|
The LLM response
|
|
104
104
|
"""
|
|
105
|
-
output_message =
|
|
105
|
+
output_message = []
|
|
106
106
|
async for event in runnable.astream(inputs, config=config):
|
|
107
|
-
output_message
|
|
107
|
+
output_message.append(event.content)
|
|
108
108
|
|
|
109
|
-
return AIMessage(content=output_message)
|
|
109
|
+
return AIMessage(content="".join(output_message))
|
|
110
110
|
|
|
111
111
|
async def _call_llm(self, llm: Runnable, inputs: dict[str, Any], config: RunnableConfig | None = None) -> AIMessage:
|
|
112
112
|
"""
|
|
@@ -157,12 +157,12 @@ async def build_reasoning_function(config: ReasoningFunctionConfig, builder: Bui
|
|
|
157
157
|
prompt = prompt.to_string()
|
|
158
158
|
|
|
159
159
|
# Get the reasoning output from the LLM
|
|
160
|
-
reasoning_output =
|
|
160
|
+
reasoning_output = []
|
|
161
161
|
|
|
162
162
|
async for chunk in llm.astream(prompt):
|
|
163
|
-
reasoning_output
|
|
163
|
+
reasoning_output.append(chunk.content)
|
|
164
164
|
|
|
165
|
-
reasoning_output = remove_r1_think_tags(reasoning_output)
|
|
165
|
+
reasoning_output = remove_r1_think_tags("".join(reasoning_output))
|
|
166
166
|
|
|
167
167
|
output = await downstream_template.ainvoke(input={
|
|
168
168
|
"input_text": input_text, "reasoning_output": reasoning_output
|
|
@@ -200,12 +200,12 @@ async def build_reasoning_function(config: ReasoningFunctionConfig, builder: Bui
|
|
|
200
200
|
prompt = prompt.to_string()
|
|
201
201
|
|
|
202
202
|
# Get the reasoning output from the LLM
|
|
203
|
-
reasoning_output =
|
|
203
|
+
reasoning_output = []
|
|
204
204
|
|
|
205
205
|
async for chunk in llm.astream(prompt):
|
|
206
|
-
reasoning_output
|
|
206
|
+
reasoning_output.append(chunk.content)
|
|
207
207
|
|
|
208
|
-
reasoning_output = remove_r1_think_tags(reasoning_output)
|
|
208
|
+
reasoning_output = remove_r1_think_tags("".join(reasoning_output))
|
|
209
209
|
|
|
210
210
|
output = await downstream_template.ainvoke(input={
|
|
211
211
|
"input_text": input_text, "reasoning_output": reasoning_output
|
|
@@ -233,14 +233,10 @@ def create_tool_calling_agent_prompt(config: "ToolCallAgentWorkflowConfig") -> s
|
|
|
233
233
|
"""
|
|
234
234
|
# the Tool Calling Agent prompt can be customized via config option system_prompt and additional_instructions.
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
prompt_str += f" {config.additional_instructions}"
|
|
243
|
-
|
|
244
|
-
if len(prompt_str) > 0:
|
|
245
|
-
return prompt_str
|
|
236
|
+
prompt_strs = []
|
|
237
|
+
for msg in [config.system_prompt, config.additional_instructions]:
|
|
238
|
+
if msg is not None:
|
|
239
|
+
prompt_strs.append(msg)
|
|
240
|
+
if prompt_strs:
|
|
241
|
+
return " ".join(prompt_strs)
|
|
246
242
|
return None
|
nat/builder/context.py
CHANGED
|
@@ -19,6 +19,7 @@ from collections.abc import Awaitable
|
|
|
19
19
|
from collections.abc import Callable
|
|
20
20
|
from contextlib import contextmanager
|
|
21
21
|
from contextvars import ContextVar
|
|
22
|
+
from functools import cached_property
|
|
22
23
|
|
|
23
24
|
from nat.builder.intermediate_step_manager import IntermediateStepManager
|
|
24
25
|
from nat.builder.user_interaction_manager import UserInteractionManager
|
|
@@ -167,7 +168,7 @@ class Context:
|
|
|
167
168
|
"""
|
|
168
169
|
return UserInteractionManager(self._context_state)
|
|
169
170
|
|
|
170
|
-
@
|
|
171
|
+
@cached_property
|
|
171
172
|
def intermediate_step_manager(self) -> IntermediateStepManager:
|
|
172
173
|
"""
|
|
173
174
|
Retrieves the intermediate step manager instance from the current context state.
|
|
@@ -91,7 +91,10 @@ class IntermediateStepManager:
|
|
|
91
91
|
open_step = self._outstanding_start_steps.pop(payload.UUID, None)
|
|
92
92
|
|
|
93
93
|
if (open_step is None):
|
|
94
|
-
logger.warning(
|
|
94
|
+
logger.warning(
|
|
95
|
+
"Step id %s not found in outstanding start steps. "
|
|
96
|
+
"This may occur if the step was started in a different context or already completed.",
|
|
97
|
+
payload.UUID)
|
|
95
98
|
return
|
|
96
99
|
|
|
97
100
|
parent_step_id = open_step.step_parent_id
|
|
@@ -147,7 +150,8 @@ class IntermediateStepManager:
|
|
|
147
150
|
if (open_step is None):
|
|
148
151
|
logger.warning(
|
|
149
152
|
"Created a chunk for step %s, but no matching start step was found. "
|
|
150
|
-
"Chunks must be created with the same ID as the start step."
|
|
153
|
+
"Chunks must be created with the same ID as the start step. "
|
|
154
|
+
"This may occur if the step was started in a different context.",
|
|
151
155
|
payload.UUID)
|
|
152
156
|
return
|
|
153
157
|
|
nat/data_models/api_server.py
CHANGED
|
@@ -121,7 +121,15 @@ class Message(BaseModel):
|
|
|
121
121
|
role: UserMessageContentRoleType
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
class
|
|
124
|
+
class ChatRequest(BaseModel):
|
|
125
|
+
"""
|
|
126
|
+
ChatRequest is a data model that represents a request to the NAT chat API.
|
|
127
|
+
Fully compatible with OpenAI Chat Completions API specification.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
# Required fields
|
|
131
|
+
messages: typing.Annotated[list[Message], conlist(Message, min_length=1)]
|
|
132
|
+
|
|
125
133
|
# Optional fields (OpenAI Chat Completions API compatible)
|
|
126
134
|
model: str | None = Field(default=None, description="name of the model to use")
|
|
127
135
|
frequency_penalty: float | None = Field(default=0.0,
|
|
@@ -145,17 +153,6 @@ class ChatRequestOptionals(BaseModel):
|
|
|
145
153
|
tool_choice: str | dict[str, typing.Any] | None = Field(default=None, description="Controls which tool is called")
|
|
146
154
|
parallel_tool_calls: bool | None = Field(default=True, description="Whether to enable parallel function calling")
|
|
147
155
|
user: str | None = Field(default=None, description="Unique identifier representing end-user")
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
class ChatRequest(ChatRequestOptionals):
|
|
151
|
-
"""
|
|
152
|
-
ChatRequest is a data model that represents a request to the NAT chat API.
|
|
153
|
-
Fully compatible with OpenAI Chat Completions API specification.
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
# Required fields
|
|
157
|
-
messages: typing.Annotated[list[Message], conlist(Message, min_length=1)]
|
|
158
|
-
|
|
159
156
|
model_config = ConfigDict(extra="allow",
|
|
160
157
|
json_schema_extra={
|
|
161
158
|
"example": {
|
|
@@ -197,39 +194,82 @@ class ChatRequest(ChatRequestOptionals):
|
|
|
197
194
|
top_p=top_p)
|
|
198
195
|
|
|
199
196
|
|
|
200
|
-
class ChatRequestOrMessage(
|
|
197
|
+
class ChatRequestOrMessage(BaseModel):
|
|
201
198
|
"""
|
|
202
|
-
ChatRequestOrMessage is a data model that represents either a conversation or a string input.
|
|
199
|
+
`ChatRequestOrMessage` is a data model that represents either a conversation or a string input.
|
|
203
200
|
This is useful for functions that can handle either type of input.
|
|
204
201
|
|
|
205
|
-
`messages` is compatible with the OpenAI Chat Completions API specification.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
- `messages` is compatible with the OpenAI Chat Completions API specification.
|
|
203
|
+
- `input_message` is a string input that can be used for functions that do not require a conversation.
|
|
204
|
+
|
|
205
|
+
Note: When `messages` is provided, extra fields are allowed to enable lossless round-trip
|
|
206
|
+
conversion with ChatRequest. When `input_message` is provided, no extra fields are permitted.
|
|
207
|
+
"""
|
|
208
|
+
model_config = ConfigDict(
|
|
209
|
+
extra="allow",
|
|
210
|
+
json_schema_extra={
|
|
211
|
+
"examples": [
|
|
212
|
+
{
|
|
213
|
+
"input_message": "What can you do?"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"messages": [{
|
|
217
|
+
"role": "user", "content": "What can you do?"
|
|
218
|
+
}],
|
|
219
|
+
"model": "nvidia/nemotron",
|
|
220
|
+
"temperature": 0.7
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
"oneOf": [
|
|
224
|
+
{
|
|
225
|
+
"required": ["input_message"],
|
|
226
|
+
"properties": {
|
|
227
|
+
"input_message": {
|
|
228
|
+
"type": "string"
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
"additionalProperties": {
|
|
232
|
+
"not": True, "errorMessage": 'remove additional property ${0#}'
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"required": ["messages"],
|
|
237
|
+
"properties": {
|
|
238
|
+
"messages": {
|
|
239
|
+
"type": "array"
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
"additionalProperties": True
|
|
243
|
+
},
|
|
244
|
+
]
|
|
245
|
+
},
|
|
246
|
+
)
|
|
209
247
|
|
|
210
248
|
messages: typing.Annotated[list[Message] | None, conlist(Message, min_length=1)] = Field(
|
|
211
|
-
default=None, description="
|
|
249
|
+
default=None, description="A non-empty conversation of messages to process.")
|
|
212
250
|
|
|
213
|
-
|
|
251
|
+
input_message: str | None = Field(
|
|
252
|
+
default=None,
|
|
253
|
+
description="A single input message to process. Useful for functions that do not require a conversation")
|
|
214
254
|
|
|
215
255
|
@property
|
|
216
256
|
def is_string(self) -> bool:
|
|
217
|
-
return self.
|
|
257
|
+
return self.input_message is not None
|
|
218
258
|
|
|
219
259
|
@property
|
|
220
260
|
def is_conversation(self) -> bool:
|
|
221
261
|
return self.messages is not None
|
|
222
262
|
|
|
223
263
|
@model_validator(mode="after")
|
|
224
|
-
def
|
|
225
|
-
if self.messages is not None and self.
|
|
226
|
-
raise ValueError("Either messages or input_message
|
|
227
|
-
if self.messages is None and self.
|
|
228
|
-
raise ValueError("Either messages or input_message
|
|
229
|
-
if self.
|
|
230
|
-
extra_fields = self.model_dump(exclude={"
|
|
264
|
+
def validate_model(self):
|
|
265
|
+
if self.messages is not None and self.input_message is not None:
|
|
266
|
+
raise ValueError("Either messages or input_message must be provided, not both")
|
|
267
|
+
if self.messages is None and self.input_message is None:
|
|
268
|
+
raise ValueError("Either messages or input_message must be provided")
|
|
269
|
+
if self.input_message is not None:
|
|
270
|
+
extra_fields = self.model_dump(exclude={"input_message"}, exclude_none=True, exclude_unset=True)
|
|
231
271
|
if len(extra_fields) > 0:
|
|
232
|
-
raise ValueError("no extra fields are permitted when input_message
|
|
272
|
+
raise ValueError("no extra fields are permitted when input_message is provided")
|
|
233
273
|
return self
|
|
234
274
|
|
|
235
275
|
|
|
@@ -701,9 +741,9 @@ GlobalTypeConverter.register_converter(_string_to_nat_chat_request)
|
|
|
701
741
|
|
|
702
742
|
|
|
703
743
|
def _chat_request_or_message_to_chat_request(data: ChatRequestOrMessage) -> ChatRequest:
|
|
704
|
-
if data.
|
|
705
|
-
return _string_to_nat_chat_request(data.
|
|
706
|
-
return ChatRequest(**data.model_dump(exclude={"
|
|
744
|
+
if data.input_message is not None:
|
|
745
|
+
return _string_to_nat_chat_request(data.input_message)
|
|
746
|
+
return ChatRequest(**data.model_dump(exclude={"input_message"}))
|
|
707
747
|
|
|
708
748
|
|
|
709
749
|
GlobalTypeConverter.register_converter(_chat_request_or_message_to_chat_request)
|
|
@@ -717,7 +757,17 @@ GlobalTypeConverter.register_converter(_chat_request_to_chat_request_or_message)
|
|
|
717
757
|
|
|
718
758
|
|
|
719
759
|
def _chat_request_or_message_to_string(data: ChatRequestOrMessage) -> str:
|
|
720
|
-
|
|
760
|
+
if data.input_message is not None:
|
|
761
|
+
return data.input_message
|
|
762
|
+
# Extract content from last message in conversation
|
|
763
|
+
if data.messages is None:
|
|
764
|
+
return ""
|
|
765
|
+
content = data.messages[-1].content
|
|
766
|
+
if content is None:
|
|
767
|
+
return ""
|
|
768
|
+
if isinstance(content, str):
|
|
769
|
+
return content
|
|
770
|
+
return str(content)
|
|
721
771
|
|
|
722
772
|
|
|
723
773
|
GlobalTypeConverter.register_converter(_chat_request_or_message_to_string)
|
|
@@ -51,7 +51,7 @@ class ThinkingMixin(
|
|
|
51
51
|
Returns the system prompt to use for thinking.
|
|
52
52
|
For NVIDIA Nemotron, returns "/think" if enabled, else "/no_think".
|
|
53
53
|
For Llama Nemotron v1.5, returns "/think" if enabled, else "/no_think".
|
|
54
|
-
For Llama Nemotron v1.0, returns "detailed thinking on" if enabled, else "detailed thinking off".
|
|
54
|
+
For Llama Nemotron v1.0 or v1.1, returns "detailed thinking on" if enabled, else "detailed thinking off".
|
|
55
55
|
If thinking is not supported on the model, returns None.
|
|
56
56
|
|
|
57
57
|
Returns:
|
|
@@ -72,7 +72,7 @@ class ThinkingMixin(
|
|
|
72
72
|
return "/think" if self.thinking else "/no_think"
|
|
73
73
|
|
|
74
74
|
if model.startswith("nvidia/llama"):
|
|
75
|
-
if "v1-0" in model or "v1-1" in model:
|
|
75
|
+
if "v1-0" in model or "v1-1" in model or model.endswith("v1"):
|
|
76
76
|
return f"detailed thinking {'on' if self.thinking else 'off'}"
|
|
77
77
|
|
|
78
78
|
if "v1-5" in model:
|
|
@@ -116,11 +116,14 @@ class RAGEvaluator:
|
|
|
116
116
|
"""Convert NaN or None to 0.0 for safe arithmetic/serialization."""
|
|
117
117
|
return 0.0 if v is None or (isinstance(v, float) and math.isnan(v)) else v
|
|
118
118
|
|
|
119
|
-
#
|
|
119
|
+
# Keep original scores (preserving NaN/None) for output
|
|
120
|
+
original_scores_dict = {metric: [score.get(metric) for score in scores] for metric in scores[0]}
|
|
121
|
+
|
|
122
|
+
# Convert from list of dicts to dict of lists, coercing NaN/None to 0.0 for average calculation
|
|
120
123
|
scores_dict = {metric: [_nan_to_zero(score.get(metric)) for score in scores] for metric in scores[0]}
|
|
121
124
|
first_metric_name = list(scores_dict.keys())[0] if scores_dict else None
|
|
122
125
|
|
|
123
|
-
# Compute the average of each metric
|
|
126
|
+
# Compute the average of each metric using cleaned scores (NaN/None -> 0.0)
|
|
124
127
|
average_scores = {
|
|
125
128
|
metric: (sum(values) / len(values) if values else 0.0)
|
|
126
129
|
for metric, values in scores_dict.items()
|
|
@@ -137,11 +140,11 @@ class RAGEvaluator:
|
|
|
137
140
|
else:
|
|
138
141
|
ids = df["user_input"].tolist() # Use "user_input" as ID fallback
|
|
139
142
|
|
|
140
|
-
# Construct EvalOutputItem list
|
|
143
|
+
# Construct EvalOutputItem list using original scores (preserving NaN/None)
|
|
141
144
|
eval_output_items = [
|
|
142
145
|
EvalOutputItem(
|
|
143
146
|
id=ids[i],
|
|
144
|
-
score=
|
|
147
|
+
score=original_scores_dict[first_metric_name][i] if first_metric_name else None,
|
|
145
148
|
reasoning={
|
|
146
149
|
key:
|
|
147
150
|
getattr(row, key, None) # Use getattr to safely access attributes
|
|
@@ -1184,6 +1184,7 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
|
|
|
1184
1184
|
"server": client.server_name,
|
|
1185
1185
|
"transport": config.server.transport,
|
|
1186
1186
|
"session_healthy": session_healthy,
|
|
1187
|
+
"protected": True if config.server.auth_provider is not None else False,
|
|
1187
1188
|
"tools": tools_info,
|
|
1188
1189
|
"total_tools": len(configured_short_names),
|
|
1189
1190
|
"available_tools": available_count
|
|
@@ -1196,6 +1197,7 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
|
|
|
1196
1197
|
"server": "unknown",
|
|
1197
1198
|
"transport": config.server.transport if config.server else "unknown",
|
|
1198
1199
|
"session_healthy": False,
|
|
1200
|
+
"protected": False,
|
|
1199
1201
|
"error": str(e),
|
|
1200
1202
|
"tools": [],
|
|
1201
1203
|
"total_tools": 0,
|
|
@@ -1226,6 +1228,7 @@ class FastApiFrontEndPluginWorker(FastApiFrontEndPluginWorkerBase):
|
|
|
1226
1228
|
"server": "streamable-http:http://localhost:9901/mcp",
|
|
1227
1229
|
"transport": "streamable-http",
|
|
1228
1230
|
"session_healthy": True,
|
|
1231
|
+
"protected": False,
|
|
1229
1232
|
"tools": [{
|
|
1230
1233
|
"name": "tool_a",
|
|
1231
1234
|
"description": "Tool A description",
|
|
@@ -25,6 +25,7 @@ from pydantic import ValidationError
|
|
|
25
25
|
from starlette.websockets import WebSocketDisconnect
|
|
26
26
|
|
|
27
27
|
from nat.authentication.interfaces import FlowHandlerBase
|
|
28
|
+
from nat.data_models.api_server import ChatRequest
|
|
28
29
|
from nat.data_models.api_server import ChatResponse
|
|
29
30
|
from nat.data_models.api_server import ChatResponseChunk
|
|
30
31
|
from nat.data_models.api_server import Error
|
|
@@ -33,6 +34,8 @@ from nat.data_models.api_server import ResponsePayloadOutput
|
|
|
33
34
|
from nat.data_models.api_server import ResponseSerializable
|
|
34
35
|
from nat.data_models.api_server import SystemResponseContent
|
|
35
36
|
from nat.data_models.api_server import TextContent
|
|
37
|
+
from nat.data_models.api_server import UserMessageContentRoleType
|
|
38
|
+
from nat.data_models.api_server import UserMessages
|
|
36
39
|
from nat.data_models.api_server import WebSocketMessageStatus
|
|
37
40
|
from nat.data_models.api_server import WebSocketMessageType
|
|
38
41
|
from nat.data_models.api_server import WebSocketSystemInteractionMessage
|
|
@@ -64,12 +67,12 @@ class WebSocketMessageHandler:
|
|
|
64
67
|
self._running_workflow_task: asyncio.Task | None = None
|
|
65
68
|
self._message_parent_id: str = "default_id"
|
|
66
69
|
self._conversation_id: str | None = None
|
|
67
|
-
self._workflow_schema_type: str = None
|
|
68
|
-
self._user_interaction_response: asyncio.Future[
|
|
70
|
+
self._workflow_schema_type: str | None = None
|
|
71
|
+
self._user_interaction_response: asyncio.Future[TextContent] | None = None
|
|
69
72
|
|
|
70
73
|
self._flow_handler: FlowHandlerBase | None = None
|
|
71
74
|
|
|
72
|
-
self._schema_output_mapping: dict[str, type[BaseModel] | None] = {
|
|
75
|
+
self._schema_output_mapping: dict[str, type[BaseModel] | type[None]] = {
|
|
73
76
|
WorkflowSchemaType.GENERATE: self._session_manager.workflow.single_output_schema,
|
|
74
77
|
WorkflowSchemaType.CHAT: ChatResponse,
|
|
75
78
|
WorkflowSchemaType.CHAT_STREAM: ChatResponseChunk,
|
|
@@ -114,36 +117,58 @@ class WebSocketMessageHandler:
|
|
|
114
117
|
pass
|
|
115
118
|
|
|
116
119
|
elif (isinstance(validated_message, WebSocketUserInteractionResponseMessage)):
|
|
117
|
-
user_content = await self.
|
|
120
|
+
user_content = await self._process_websocket_user_interaction_response_message(validated_message)
|
|
121
|
+
assert self._user_interaction_response is not None
|
|
118
122
|
self._user_interaction_response.set_result(user_content)
|
|
119
123
|
except (asyncio.CancelledError, WebSocketDisconnect):
|
|
120
124
|
# TODO: Handle the disconnect
|
|
121
125
|
break
|
|
122
126
|
|
|
123
|
-
|
|
124
|
-
self, user_content: WebSocketUserMessage | WebSocketUserInteractionResponseMessage) -> BaseModel | None:
|
|
127
|
+
def _extract_last_user_message_content(self, messages: list[UserMessages]) -> TextContent:
|
|
125
128
|
"""
|
|
126
|
-
|
|
129
|
+
Extracts the last user's TextContent from a list of messages.
|
|
127
130
|
|
|
128
|
-
:
|
|
129
|
-
|
|
130
|
-
"""
|
|
131
|
+
Args:
|
|
132
|
+
messages: List of UserMessages.
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
Returns:
|
|
135
|
+
TextContent object from the last user message.
|
|
134
136
|
|
|
137
|
+
Raises:
|
|
138
|
+
ValueError: If no user text content is found.
|
|
139
|
+
"""
|
|
140
|
+
for user_message in messages[::-1]:
|
|
141
|
+
if user_message.role == UserMessageContentRoleType.USER:
|
|
135
142
|
for attachment in user_message.content:
|
|
136
|
-
|
|
137
143
|
if isinstance(attachment, TextContent):
|
|
138
144
|
return attachment
|
|
145
|
+
raise ValueError("No user text content found in messages.")
|
|
146
|
+
|
|
147
|
+
async def _process_websocket_user_interaction_response_message(
|
|
148
|
+
self, user_content: WebSocketUserInteractionResponseMessage) -> TextContent:
|
|
149
|
+
"""
|
|
150
|
+
Processes a WebSocketUserInteractionResponseMessage.
|
|
151
|
+
"""
|
|
152
|
+
return self._extract_last_user_message_content(user_content.content.messages)
|
|
139
153
|
|
|
140
|
-
|
|
154
|
+
async def _process_websocket_user_message(self, user_content: WebSocketUserMessage) -> ChatRequest | str:
|
|
155
|
+
"""
|
|
156
|
+
Processes a WebSocketUserMessage based on schema type.
|
|
157
|
+
"""
|
|
158
|
+
if self._workflow_schema_type in [WorkflowSchemaType.CHAT, WorkflowSchemaType.CHAT_STREAM]:
|
|
159
|
+
return ChatRequest(**user_content.content.model_dump(include={"messages"}))
|
|
160
|
+
|
|
161
|
+
elif self._workflow_schema_type in [WorkflowSchemaType.GENERATE, WorkflowSchemaType.GENERATE_STREAM]:
|
|
162
|
+
return self._extract_last_user_message_content(user_content.content.messages).text
|
|
163
|
+
|
|
164
|
+
raise ValueError("Unsupported workflow schema type for WebSocketUserMessage")
|
|
141
165
|
|
|
142
166
|
async def process_workflow_request(self, user_message_as_validated_type: WebSocketUserMessage) -> None:
|
|
143
167
|
"""
|
|
144
168
|
Process user messages and routes them appropriately.
|
|
145
169
|
|
|
146
|
-
:
|
|
170
|
+
Args:
|
|
171
|
+
user_message_as_validated_type (WebSocketUserMessage): The validated user message to process.
|
|
147
172
|
"""
|
|
148
173
|
|
|
149
174
|
try:
|
|
@@ -151,18 +176,15 @@ class WebSocketMessageHandler:
|
|
|
151
176
|
self._workflow_schema_type = user_message_as_validated_type.schema_type
|
|
152
177
|
self._conversation_id = user_message_as_validated_type.conversation_id
|
|
153
178
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if content is None:
|
|
157
|
-
raise ValueError(f"User message content could not be found: {user_message_as_validated_type}")
|
|
179
|
+
message_content: typing.Any = await self._process_websocket_user_message(user_message_as_validated_type)
|
|
158
180
|
|
|
159
|
-
if
|
|
181
|
+
if (self._running_workflow_task is None):
|
|
160
182
|
|
|
161
|
-
def _done_callback(
|
|
183
|
+
def _done_callback(_task: asyncio.Task):
|
|
162
184
|
self._running_workflow_task = None
|
|
163
185
|
|
|
164
186
|
self._running_workflow_task = asyncio.create_task(
|
|
165
|
-
self._run_workflow(payload=
|
|
187
|
+
self._run_workflow(payload=message_content,
|
|
166
188
|
user_message_id=self._message_parent_id,
|
|
167
189
|
conversation_id=self._conversation_id,
|
|
168
190
|
result_type=self._schema_output_mapping[self._workflow_schema_type],
|
|
@@ -180,13 +202,14 @@ class WebSocketMessageHandler:
|
|
|
180
202
|
async def create_websocket_message(self,
|
|
181
203
|
data_model: BaseModel,
|
|
182
204
|
message_type: str | None = None,
|
|
183
|
-
status:
|
|
205
|
+
status: WebSocketMessageStatus = WebSocketMessageStatus.IN_PROGRESS) -> None:
|
|
184
206
|
"""
|
|
185
207
|
Creates a websocket message that will be ready for routing based on message type or data model.
|
|
186
208
|
|
|
187
|
-
:
|
|
188
|
-
|
|
189
|
-
|
|
209
|
+
Args:
|
|
210
|
+
data_model (BaseModel): Message content model.
|
|
211
|
+
message_type (str | None): Message content model.
|
|
212
|
+
status (WebSocketMessageStatus): Message content model.
|
|
190
213
|
"""
|
|
191
214
|
try:
|
|
192
215
|
message: BaseModel | None = None
|
|
@@ -196,8 +219,8 @@ class WebSocketMessageHandler:
|
|
|
196
219
|
|
|
197
220
|
message_schema: type[BaseModel] = await self._message_validator.get_message_schema_by_type(message_type)
|
|
198
221
|
|
|
199
|
-
if 'id'
|
|
200
|
-
message_id: str = data_model
|
|
222
|
+
if hasattr(data_model, 'id'):
|
|
223
|
+
message_id: str = str(getattr(data_model, 'id'))
|
|
201
224
|
else:
|
|
202
225
|
message_id = str(uuid.uuid4())
|
|
203
226
|
|
|
@@ -253,12 +276,15 @@ class WebSocketMessageHandler:
|
|
|
253
276
|
Registered human interaction callback that processes human interactions and returns
|
|
254
277
|
responses from websocket connection.
|
|
255
278
|
|
|
256
|
-
:
|
|
257
|
-
|
|
279
|
+
Args:
|
|
280
|
+
prompt: Incoming interaction content data model.
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
A Text Content Base Pydantic model.
|
|
258
284
|
"""
|
|
259
285
|
|
|
260
286
|
# First create a future from the loop for the human response
|
|
261
|
-
human_response_future: asyncio.Future[
|
|
287
|
+
human_response_future: asyncio.Future[TextContent] = asyncio.get_running_loop().create_future()
|
|
262
288
|
|
|
263
289
|
# Then add the future to the outstanding human prompts dictionary
|
|
264
290
|
self._user_interaction_response = human_response_future
|
|
@@ -274,10 +300,10 @@ class WebSocketMessageHandler:
|
|
|
274
300
|
return HumanResponseNotification()
|
|
275
301
|
|
|
276
302
|
# Wait for the human response future to complete
|
|
277
|
-
|
|
303
|
+
text_content: TextContent = await human_response_future
|
|
278
304
|
|
|
279
305
|
interaction_response: HumanResponse = await self._message_validator.convert_text_content_to_human_response(
|
|
280
|
-
|
|
306
|
+
text_content, prompt.content)
|
|
281
307
|
|
|
282
308
|
return interaction_response
|
|
283
309
|
|
|
@@ -293,13 +319,12 @@ class WebSocketMessageHandler:
|
|
|
293
319
|
output_type: type | None = None) -> None:
|
|
294
320
|
|
|
295
321
|
try:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if self._flow_handler else None)) as session:
|
|
322
|
+
auth_callback = self._flow_handler.authenticate if self._flow_handler else None
|
|
323
|
+
async with self._session_manager.session(user_message_id=user_message_id,
|
|
324
|
+
conversation_id=conversation_id,
|
|
325
|
+
http_connection=self._socket,
|
|
326
|
+
user_input_callback=self.human_interaction_callback,
|
|
327
|
+
user_authentication_callback=auth_callback) as session:
|
|
303
328
|
|
|
304
329
|
async for value in generate_streaming_response(payload,
|
|
305
330
|
session_manager=session,
|
|
@@ -240,8 +240,7 @@ class MessageValidator:
|
|
|
240
240
|
thread_id: str = "default",
|
|
241
241
|
parent_id: str = "default",
|
|
242
242
|
conversation_id: str | None = None,
|
|
243
|
-
content: SystemResponseContent
|
|
244
|
-
| Error = SystemResponseContent(),
|
|
243
|
+
content: SystemResponseContent | Error = SystemResponseContent(),
|
|
245
244
|
status: WebSocketMessageStatus = WebSocketMessageStatus.IN_PROGRESS,
|
|
246
245
|
timestamp: str = str(datetime.datetime.now(datetime.UTC))
|
|
247
246
|
) -> WebSocketSystemResponseTokenMessage | None:
|
|
@@ -105,9 +105,12 @@ class MCPFrontEndPlugin(FrontEndBase[MCPFrontEndConfig]):
|
|
|
105
105
|
|
|
106
106
|
# Start the MCP server with configurable transport
|
|
107
107
|
# streamable-http is the default, but users can choose sse if preferred
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
try:
|
|
109
|
+
if self.front_end_config.transport == "sse":
|
|
110
|
+
logger.info("Starting MCP server with SSE endpoint at /sse")
|
|
111
|
+
await mcp.run_sse_async()
|
|
112
|
+
else: # streamable-http
|
|
113
|
+
logger.info("Starting MCP server with streamable-http endpoint at /mcp/")
|
|
114
|
+
await mcp.run_streamable_http_async()
|
|
115
|
+
except KeyboardInterrupt:
|
|
116
|
+
logger.info("MCP server shutdown requested (Ctrl+C). Shutting down gracefully.")
|
|
@@ -121,6 +121,17 @@ def optimize_parameters(
|
|
|
121
121
|
with (out_dir / "trials_dataframe_params.csv").open("w") as fh:
|
|
122
122
|
# Export full trials DataFrame (values, params, timings, etc.).
|
|
123
123
|
df = study.trials_dataframe()
|
|
124
|
+
|
|
125
|
+
# Rename values_X columns to actual metric names
|
|
126
|
+
metric_names = list(metric_cfg.keys())
|
|
127
|
+
rename_mapping = {}
|
|
128
|
+
for i, metric_name in enumerate(metric_names):
|
|
129
|
+
old_col = f"values_{i}"
|
|
130
|
+
if old_col in df.columns:
|
|
131
|
+
rename_mapping[old_col] = f"values_{metric_name}"
|
|
132
|
+
if rename_mapping:
|
|
133
|
+
df = df.rename(columns=rename_mapping)
|
|
134
|
+
|
|
124
135
|
# Normalise rep_scores column naming for convenience.
|
|
125
136
|
if "user_attrs_rep_scores" in df.columns and "rep_scores" not in df.columns:
|
|
126
137
|
df = df.rename(columns={"user_attrs_rep_scores": "rep_scores"})
|
|
@@ -46,9 +46,13 @@ class ParetoVisualizer:
|
|
|
46
46
|
|
|
47
47
|
fig, ax = plt.subplots(figsize=figsize)
|
|
48
48
|
|
|
49
|
-
# Extract metric values
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
# Extract metric values - support both old (values_0) and new (values_metricname) formats
|
|
50
|
+
x_col = f"values_{self.metric_names[0]}" \
|
|
51
|
+
if f"values_{self.metric_names[0]}" in trials_df.columns else f"values_{0}"
|
|
52
|
+
y_col = f"values_{self.metric_names[1]}"\
|
|
53
|
+
if f"values_{self.metric_names[1]}" in trials_df.columns else f"values_{1}"
|
|
54
|
+
x_vals = trials_df[x_col].values
|
|
55
|
+
y_vals = trials_df[y_col].values
|
|
52
56
|
|
|
53
57
|
# Plot all trials
|
|
54
58
|
ax.scatter(x_vals,
|
|
@@ -62,8 +66,8 @@ class ParetoVisualizer:
|
|
|
62
66
|
|
|
63
67
|
# Plot Pareto optimal trials if provided
|
|
64
68
|
if pareto_trials_df is not None and not pareto_trials_df.empty:
|
|
65
|
-
pareto_x = pareto_trials_df[
|
|
66
|
-
pareto_y = pareto_trials_df[
|
|
69
|
+
pareto_x = pareto_trials_df[x_col].values
|
|
70
|
+
pareto_y = pareto_trials_df[y_col].values
|
|
67
71
|
|
|
68
72
|
ax.scatter(pareto_x,
|
|
69
73
|
pareto_y,
|
|
@@ -98,8 +102,8 @@ class ParetoVisualizer:
|
|
|
98
102
|
ax.grid(True, alpha=0.3)
|
|
99
103
|
|
|
100
104
|
# Add direction annotations
|
|
101
|
-
x_annotation = (f"Better {self.metric_names[0]}
|
|
102
|
-
if self.directions[0] == "minimize" else f"
|
|
105
|
+
x_annotation = (f"Better {self.metric_names[0]} ←"
|
|
106
|
+
if self.directions[0] == "minimize" else f"→ Better {self.metric_names[0]}")
|
|
103
107
|
ax.annotate(x_annotation,
|
|
104
108
|
xy=(0.02, 0.98),
|
|
105
109
|
xycoords='axes fraction',
|
|
@@ -109,8 +113,8 @@ class ParetoVisualizer:
|
|
|
109
113
|
style='italic',
|
|
110
114
|
bbox=dict(boxstyle="round,pad=0.3", facecolor="wheat", alpha=0.7))
|
|
111
115
|
|
|
112
|
-
y_annotation = (f"Better {self.metric_names[1]}
|
|
113
|
-
if self.directions[1] == "minimize" else f"Better {self.metric_names[1]}
|
|
116
|
+
y_annotation = (f"Better {self.metric_names[1]} ↓"
|
|
117
|
+
if self.directions[1] == "minimize" else f"Better {self.metric_names[1]} ↑")
|
|
114
118
|
ax.annotate(y_annotation,
|
|
115
119
|
xy=(0.02, 0.02),
|
|
116
120
|
xycoords='axes fraction',
|
|
@@ -145,7 +149,10 @@ class ParetoVisualizer:
|
|
|
145
149
|
# Normalize values for better visualization
|
|
146
150
|
all_values = []
|
|
147
151
|
for i in range(n_metrics):
|
|
148
|
-
|
|
152
|
+
# Support both old (values_0) and new (values_metricname) formats
|
|
153
|
+
col_name = f"values_{self.metric_names[i]}"\
|
|
154
|
+
if f"values_{self.metric_names[i]}" in trials_df.columns else f"values_{i}"
|
|
155
|
+
all_values.append(trials_df[col_name].values)
|
|
149
156
|
|
|
150
157
|
# Normalize each metric to [0, 1] for parallel coordinates
|
|
151
158
|
normalized_values = []
|
|
@@ -221,23 +228,31 @@ class ParetoVisualizer:
|
|
|
221
228
|
|
|
222
229
|
if i == j:
|
|
223
230
|
# Diagonal: histograms
|
|
224
|
-
|
|
231
|
+
# Support both old (values_0) and new (values_metricname) formats
|
|
232
|
+
col_name = f"values_{self.metric_names[i]}"\
|
|
233
|
+
if f"values_{self.metric_names[i]}" in trials_df.columns else f"values_{i}"
|
|
234
|
+
values = trials_df[col_name].values
|
|
225
235
|
ax.hist(values, bins=20, alpha=0.7, color='lightblue', edgecolor='navy')
|
|
226
236
|
if pareto_trials_df is not None and not pareto_trials_df.empty:
|
|
227
|
-
pareto_values = pareto_trials_df[
|
|
237
|
+
pareto_values = pareto_trials_df[col_name].values
|
|
228
238
|
ax.hist(pareto_values, bins=20, alpha=0.8, color='red', edgecolor='darkred')
|
|
229
239
|
ax.set_xlabel(f"{self.metric_names[i]}")
|
|
230
240
|
ax.set_ylabel("Frequency")
|
|
231
241
|
else:
|
|
232
242
|
# Off-diagonal: scatter plots
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
# Support both old (values_0) and new (values_metricname) formats
|
|
244
|
+
x_col = f"values_{self.metric_names[j]}"\
|
|
245
|
+
if f"values_{self.metric_names[j]}" in trials_df.columns else f"values_{j}"
|
|
246
|
+
y_col = f"values_{self.metric_names[i]}"\
|
|
247
|
+
if f"values_{self.metric_names[i]}" in trials_df.columns else f"values_{i}"
|
|
248
|
+
x_vals = trials_df[x_col].values
|
|
249
|
+
y_vals = trials_df[y_col].values
|
|
235
250
|
|
|
236
251
|
ax.scatter(x_vals, y_vals, alpha=0.6, s=30, c='lightblue', edgecolors='navy', linewidths=0.5)
|
|
237
252
|
|
|
238
253
|
if pareto_trials_df is not None and not pareto_trials_df.empty:
|
|
239
|
-
pareto_x = pareto_trials_df[
|
|
240
|
-
pareto_y = pareto_trials_df[
|
|
254
|
+
pareto_x = pareto_trials_df[x_col].values
|
|
255
|
+
pareto_y = pareto_trials_df[y_col].values
|
|
241
256
|
ax.scatter(pareto_x,
|
|
242
257
|
pareto_y,
|
|
243
258
|
alpha=0.9,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nvidia-nat
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.0a20251022
|
|
4
4
|
Summary: NVIDIA NeMo Agent toolkit
|
|
5
5
|
Author: NVIDIA Corporation
|
|
6
6
|
Maintainer: NVIDIA Corporation
|
|
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
License-File: LICENSE-3rd-party.txt
|
|
18
18
|
License-File: LICENSE.md
|
|
19
19
|
Requires-Dist: aioboto3>=11.0.0
|
|
20
|
-
Requires-Dist: authlib
|
|
20
|
+
Requires-Dist: authlib<2.0.0,>=1.6.5
|
|
21
21
|
Requires-Dist: click~=8.1
|
|
22
22
|
Requires-Dist: colorama~=0.4.6
|
|
23
23
|
Requires-Dist: datasets~=4.0
|
|
@@ -84,10 +84,11 @@ Requires-Dist: nvidia-nat-s3; extra == "s3"
|
|
|
84
84
|
Provides-Extra: semantic-kernel
|
|
85
85
|
Requires-Dist: nvidia-nat-semantic-kernel; extra == "semantic-kernel"
|
|
86
86
|
Provides-Extra: telemetry
|
|
87
|
+
Requires-Dist: nvidia-nat-data-flywheel; extra == "telemetry"
|
|
87
88
|
Requires-Dist: nvidia-nat-opentelemetry; extra == "telemetry"
|
|
88
89
|
Requires-Dist: nvidia-nat-phoenix; extra == "telemetry"
|
|
89
|
-
Requires-Dist: nvidia-nat-weave; extra == "telemetry"
|
|
90
90
|
Requires-Dist: nvidia-nat-ragaai; extra == "telemetry"
|
|
91
|
+
Requires-Dist: nvidia-nat-weave; extra == "telemetry"
|
|
91
92
|
Provides-Extra: weave
|
|
92
93
|
Requires-Dist: nvidia-nat-weave; extra == "weave"
|
|
93
94
|
Provides-Extra: zep-cloud
|
|
@@ -103,7 +104,6 @@ Requires-Dist: nat_multi_frameworks; extra == "examples"
|
|
|
103
104
|
Requires-Dist: nat_plot_charts; extra == "examples"
|
|
104
105
|
Requires-Dist: nat_por_to_jiratickets; extra == "examples"
|
|
105
106
|
Requires-Dist: nat_profiler_agent; extra == "examples"
|
|
106
|
-
Requires-Dist: nat_redact_pii; extra == "examples"
|
|
107
107
|
Requires-Dist: nat_router_agent; extra == "examples"
|
|
108
108
|
Requires-Dist: nat_semantic_kernel_demo; extra == "examples"
|
|
109
109
|
Requires-Dist: nat_sequential_executor; extra == "examples"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
aiq/__init__.py,sha256=qte-NlwgM990yEeyaRUxA4IBQq3PaEkQUCK3i95iwPw,2341
|
|
2
2
|
nat/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
nat/agent/base.py,sha256=
|
|
3
|
+
nat/agent/base.py,sha256=Q6byRPl4mrfVFD3boKt5yftnnJ3ucH9l39FTt3QOQbg,10169
|
|
4
4
|
nat/agent/dual_node.py,sha256=pfvXa1iLKtrNBHsh-tM5RWRmVe7QkyYhQNanOfWdJJs,2569
|
|
5
5
|
nat/agent/register.py,sha256=rPhHDyqRBIKyon3HqhOmpAjqPP18Or6wDQb0wRUBIjQ,1032
|
|
6
6
|
nat/agent/prompt_optimizer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -12,13 +12,13 @@ nat/agent/react_agent/output_parser.py,sha256=m7K6wRwtckBBpAHqOf3BZ9mqZLwrP13Kxz
|
|
|
12
12
|
nat/agent/react_agent/prompt.py,sha256=N47JJrT6xwYQCv1jedHhlul2AE7EfKsSYfAbgJwWRew,1758
|
|
13
13
|
nat/agent/react_agent/register.py,sha256=qkPaK6AvXjolL-q_Z3waVobXDz24GMfuqGqCn-2un2Q,8991
|
|
14
14
|
nat/agent/reasoning_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
nat/agent/reasoning_agent/reasoning_agent.py,sha256=
|
|
15
|
+
nat/agent/reasoning_agent/reasoning_agent.py,sha256=fFQtzvaBWtmr_B6S9KSkqAfyl1BdcOc9xkhnbO4O8Pk,9603
|
|
16
16
|
nat/agent/rewoo_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
nat/agent/rewoo_agent/agent.py,sha256=XXgVXY9xwkyxnr093KXUtfgyNxAQbyGAecoGqN5mMLY,26199
|
|
18
18
|
nat/agent/rewoo_agent/prompt.py,sha256=B0JeL1xDX4VKcShlkkviEcAsOKAwzSlX8NcAQdmUUPw,3645
|
|
19
19
|
nat/agent/rewoo_agent/register.py,sha256=XArlOR37QOBtAvsdKJUjRok5qTmx39S2mJHSteOwU58,9283
|
|
20
20
|
nat/agent/tool_calling_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
nat/agent/tool_calling_agent/agent.py,sha256=
|
|
21
|
+
nat/agent/tool_calling_agent/agent.py,sha256=9CRQbFlcJ02WvuRojaWcRS8ISl38JlS18BUflApuoAw,10960
|
|
22
22
|
nat/agent/tool_calling_agent/register.py,sha256=OucceyELA2xZL3KdANWK9w12fnVP75eVbZgzOnmXHys,7057
|
|
23
23
|
nat/authentication/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
24
24
|
nat/authentication/interfaces.py,sha256=1J2CWEJ_n6CLA3_HD3XV28CSbyfxrPAHzr7Q4kKDFdc,3511
|
|
@@ -42,7 +42,7 @@ nat/authentication/oauth2/register.py,sha256=7rXhf-ilgSS_bUJsd9pOOCotL1FM8dKUt3k
|
|
|
42
42
|
nat/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
nat/builder/builder.py,sha256=okI3Y101hwF63AwazzxiahQx-W9eFZ_SNdFXzDuoftU,11608
|
|
44
44
|
nat/builder/component_utils.py,sha256=gxDhm4NCLI1GU0XL9gFe_gife0oJLwgk_YuABJneFfs,13838
|
|
45
|
-
nat/builder/context.py,sha256=
|
|
45
|
+
nat/builder/context.py,sha256=YmgYHzXggPQCOIBj1Mirr7xKM7NvtVr3XrSfn979fDM,13138
|
|
46
46
|
nat/builder/embedder.py,sha256=NPkOEcxt_-wc53QRijCQQDLretRUYHRYaKoYmarmrBk,965
|
|
47
47
|
nat/builder/eval_builder.py,sha256=I-ScvupmorClYoVBIs_PhSsB7Xf9e2nGWe0rCZp3txo,6857
|
|
48
48
|
nat/builder/evaluator.py,sha256=xWHMND2vcAUkdFP7FU3jnVki1rUHeTa0-9saFh2hWKs,1162
|
|
@@ -51,7 +51,7 @@ nat/builder/front_end.py,sha256=FCJ87NSshVVuTg8zZrq3YAr_u0RaYVZVcibnqlRFy-M,2173
|
|
|
51
51
|
nat/builder/function.py,sha256=eZZWLwhphgQTnPvbga8sGleX7HCP46usZPIegE7zFzs,27725
|
|
52
52
|
nat/builder/function_base.py,sha256=0Eg8RtjWhEU3Yme0CVxcRutobA0Qo8-YHZLI6L2qAgM,13116
|
|
53
53
|
nat/builder/function_info.py,sha256=7Rmrn-gOFrT2TIJklJwA_O-ycx_oimwZ0-qMYpbuZrU,25161
|
|
54
|
-
nat/builder/intermediate_step_manager.py,sha256=
|
|
54
|
+
nat/builder/intermediate_step_manager.py,sha256=wTfCV47IKpYO7NvoHSD4BGwOiuZ8Db9ktzs14T38gBE,7834
|
|
55
55
|
nat/builder/llm.py,sha256=DW-2q64A06VChsXNEL5PfBjH3DcsnTKVoCEWDuP7MF4,951
|
|
56
56
|
nat/builder/retriever.py,sha256=ZyEqc7pFK31t_yr6Jaxa34c-tRas2edKqJZCNiVh9-0,970
|
|
57
57
|
nat/builder/user_interaction_manager.py,sha256=-Z2qbQes7a2cuXgT7KEbWeuok0HcCnRdw9WB8Ghyl9k,3081
|
|
@@ -112,7 +112,7 @@ nat/control_flow/router_agent/prompt.py,sha256=fIAiNsAs1zXRAatButR76zSpHJNxSkXXK
|
|
|
112
112
|
nat/control_flow/router_agent/register.py,sha256=4RGmS9sy-QtIMmvh8mfMcR1VqxFPLpG4RckWCIExh40,4144
|
|
113
113
|
nat/data_models/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
114
114
|
nat/data_models/agent.py,sha256=IwDyb9Zc3R4Zd5rFeqt7q0EQswczAl5focxV9KozIzs,1625
|
|
115
|
-
nat/data_models/api_server.py,sha256=
|
|
115
|
+
nat/data_models/api_server.py,sha256=IowzLwxJqnSkUehCbK0WJp98hBZFXUQDd1cq8lr9PVs,30582
|
|
116
116
|
nat/data_models/authentication.py,sha256=XPu9W8nh4XRSuxPv3HxO-FMQ_JtTEoK6Y02JwnzDwTg,8457
|
|
117
117
|
nat/data_models/common.py,sha256=nXXfGrjpxebzBUa55mLdmzePLt7VFHvTAc6Znj3yEv0,5875
|
|
118
118
|
nat/data_models/component.py,sha256=b_hXOA8Gm5UNvlFkAhsR6kEvf33ST50MKtr5kWf75Ao,1894
|
|
@@ -146,7 +146,7 @@ nat/data_models/streaming.py,sha256=sSqJqLqb70qyw69_4R9QC2RMbRw7UjTLPdo3FYBUGxE,
|
|
|
146
146
|
nat/data_models/swe_bench_model.py,sha256=uZs-hLFuT1B5CiPFwFg1PHinDW8PHne8TBzu7tHFv_k,1718
|
|
147
147
|
nat/data_models/telemetry_exporter.py,sha256=P7kqxIQnFVuvo_UFpH9QSB8fACy_0U2Uzkw_IfWXagE,998
|
|
148
148
|
nat/data_models/temperature_mixin.py,sha256=LlpfWrWtDrPJfSKfNx5E0P3p5SNGZli7ACRRpmO0QqA,1628
|
|
149
|
-
nat/data_models/thinking_mixin.py,sha256=
|
|
149
|
+
nat/data_models/thinking_mixin.py,sha256=VRDUJZ8XP_Vv0gW2FRZUf8O9-kVgNEdZCEZ8oEmHyMk,3335
|
|
150
150
|
nat/data_models/top_p_mixin.py,sha256=mu0DLnCAiwNzpSFR8FOW4kQBUpodSrvUR4MsLrNtbgA,1599
|
|
151
151
|
nat/data_models/ttc_strategy.py,sha256=tAkKWcyEBmBOOYtHMtQTgeCbHxFTk5SEkmFunNVnfyE,1114
|
|
152
152
|
nat/embedder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -170,7 +170,7 @@ nat/eval/evaluator/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQ
|
|
|
170
170
|
nat/eval/evaluator/base_evaluator.py,sha256=5WaVGhCGzkynCJyQdxRv7CtqLoUpr6B4O8tilP_gb3g,3232
|
|
171
171
|
nat/eval/evaluator/evaluator_model.py,sha256=riGCcDW8YwC3Kd1yoVmbMdJE1Yf2kVmO8uhsGsKKJA4,1878
|
|
172
172
|
nat/eval/rag_evaluator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
173
|
-
nat/eval/rag_evaluator/evaluate.py,sha256=
|
|
173
|
+
nat/eval/rag_evaluator/evaluate.py,sha256=IfCpfCKBTYhReRkPPbOqyr-9H6gsPGaeFWBIcGDUynw,8639
|
|
174
174
|
nat/eval/rag_evaluator/register.py,sha256=AzT5uICDU5dEo7scvStmOWC7ac-S0Tx4UY87idGtXIs,5835
|
|
175
175
|
nat/eval/runners/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
|
176
176
|
nat/eval/runners/config.py,sha256=bRPai_th02OJrFepbbY6w-t7A18TBXozQUnnnH9iWIU,1403
|
|
@@ -242,12 +242,12 @@ nat/front_ends/fastapi/dask_client_mixin.py,sha256=N_tw4yxA7EKIFTKp5_C2ZksIZucWx
|
|
|
242
242
|
nat/front_ends/fastapi/fastapi_front_end_config.py,sha256=BcuzrVlA5b7yYyQKNvQgEanDBtKEHdpC8TAd-O7lfF0,11992
|
|
243
243
|
nat/front_ends/fastapi/fastapi_front_end_controller.py,sha256=ei-34KCMpyaeAgeAN4gVvSGFjewjjRhHZPN0FqAfhDY,2548
|
|
244
244
|
nat/front_ends/fastapi/fastapi_front_end_plugin.py,sha256=e33YkMcLzvm4OUG34bhl-WYiBTqkR-_wJYKG4GODkGM,11169
|
|
245
|
-
nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py,sha256=
|
|
245
|
+
nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py,sha256=T6uslFdkHl_r0U54_7cRRKLnWYP2tTMcD7snx9Gv1xs,60547
|
|
246
246
|
nat/front_ends/fastapi/intermediate_steps_subscriber.py,sha256=kbyWlBVpyvyQQjeUnFG9nsR4RaqqNkx567ZSVwwl2RU,3104
|
|
247
247
|
nat/front_ends/fastapi/job_store.py,sha256=cWIBnIgRdkGL7qbBunEKzTYzdPp3l3QCDHMP-qTZJpc,22743
|
|
248
248
|
nat/front_ends/fastapi/main.py,sha256=s8gXCy61rJjK1aywMRpgPvzlkMGsCS-kI_0EIy4JjBM,2445
|
|
249
|
-
nat/front_ends/fastapi/message_handler.py,sha256=
|
|
250
|
-
nat/front_ends/fastapi/message_validator.py,sha256=
|
|
249
|
+
nat/front_ends/fastapi/message_handler.py,sha256=9CH42D-Ti5cczvRTLVuvlfCV9LaTqFGJCny46zrrEnk,16584
|
|
250
|
+
nat/front_ends/fastapi/message_validator.py,sha256=9n-DvUNfqlTtPgcBMC684quD619XYSzjgPfe6f23LPQ,17606
|
|
251
251
|
nat/front_ends/fastapi/register.py,sha256=rA12NPFgV9ZNHOEIgB7_SB6NytjRxgBTLo7fJ-73_HM,1153
|
|
252
252
|
nat/front_ends/fastapi/response_helpers.py,sha256=MGE9E73sQSCYjsR5YXRga2qbl44hrTAPW2N5Ui3vXX0,9028
|
|
253
253
|
nat/front_ends/fastapi/step_adaptor.py,sha256=J6UtoXL9De8bgAg93nE0ASLUHZbidWOfRiuFo-tyZgY,12412
|
|
@@ -260,7 +260,7 @@ nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py,sha256=BNpWwzmA5
|
|
|
260
260
|
nat/front_ends/mcp/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
|
261
261
|
nat/front_ends/mcp/introspection_token_verifier.py,sha256=s7Q4Q6rWZJ0ZVujSxxpvVI6Bnhkg1LJQ3RLkvhzFIGE,2836
|
|
262
262
|
nat/front_ends/mcp/mcp_front_end_config.py,sha256=m6z5qSz8YGnFnfu8hRID69suvO1YT_L6sxy1Ki64Ufw,4042
|
|
263
|
-
nat/front_ends/mcp/mcp_front_end_plugin.py,sha256=
|
|
263
|
+
nat/front_ends/mcp/mcp_front_end_plugin.py,sha256=4u_kpen_T-_Uh62V5M7dfW9KyzbqXI7tGBG4AxJXWm0,5231
|
|
264
264
|
nat/front_ends/mcp/mcp_front_end_plugin_worker.py,sha256=jMclC0qEd910oTGCqd1kQ8WjP3WPdQKTl854-2bU_KI,10200
|
|
265
265
|
nat/front_ends/mcp/register.py,sha256=3aJtgG5VaiqujoeU1-Eq7Hl5pWslIlIwGFU2ASLTXgM,1173
|
|
266
266
|
nat/front_ends/mcp/tool_converter.py,sha256=jyH6tFKUDXSfRBKkv8WjvJsQt05zk3FJBTCwnIuUh5M,11547
|
|
@@ -367,9 +367,9 @@ nat/profiler/inference_optimization/experimental/prefix_span_analysis.py,sha256=
|
|
|
367
367
|
nat/profiler/parameter_optimization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
368
368
|
nat/profiler/parameter_optimization/optimizable_utils.py,sha256=93Pl8A14Zq_f3XsxSH-yFnEJ6B7W5hp7doPnPoLlRB4,3714
|
|
369
369
|
nat/profiler/parameter_optimization/optimizer_runtime.py,sha256=rXmCOq81o7ZorQOUYociVjuO3NO9CIjFBbwql2u_4H4,2715
|
|
370
|
-
nat/profiler/parameter_optimization/parameter_optimizer.py,sha256=
|
|
370
|
+
nat/profiler/parameter_optimization/parameter_optimizer.py,sha256=LA2gTBTuezWg5tdqyPA2VjIPkXylgwU9EHpVyaQqBxM,6951
|
|
371
371
|
nat/profiler/parameter_optimization/parameter_selection.py,sha256=pfnNQIx1evNICgChsOJXIFQHoL1R_kmh_vNDsVMC9kg,3982
|
|
372
|
-
nat/profiler/parameter_optimization/pareto_visualizer.py,sha256=
|
|
372
|
+
nat/profiler/parameter_optimization/pareto_visualizer.py,sha256=QclLZmmsWINIAh4n0XAKmnIZOqGHTMr-iggZS0kxj-Y,17055
|
|
373
373
|
nat/profiler/parameter_optimization/prompt_optimizer.py,sha256=_AmdeB1jRamd93qR5UqRy5LweYR3bjnD7zoLxzXYE0k,17658
|
|
374
374
|
nat/profiler/parameter_optimization/update_helpers.py,sha256=NxWhrGVchbjws85pPd-jS-C14_l70QvVSvEfENndVcY,2339
|
|
375
375
|
nat/registry_handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -470,10 +470,10 @@ nat/utils/reactive/base/observer_base.py,sha256=6BiQfx26EMumotJ3KoVcdmFBYR_fnAss
|
|
|
470
470
|
nat/utils/reactive/base/subject_base.py,sha256=UQOxlkZTIeeyYmG5qLtDpNf_63Y7p-doEeUA08_R8ME,2521
|
|
471
471
|
nat/utils/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
472
472
|
nat/utils/settings/global_settings.py,sha256=9JaO6pxKT_Pjw6rxJRsRlFCXdVKCl_xUKU2QHZQWWNM,7294
|
|
473
|
-
nvidia_nat-1.3.
|
|
474
|
-
nvidia_nat-1.3.
|
|
475
|
-
nvidia_nat-1.3.
|
|
476
|
-
nvidia_nat-1.3.
|
|
477
|
-
nvidia_nat-1.3.
|
|
478
|
-
nvidia_nat-1.3.
|
|
479
|
-
nvidia_nat-1.3.
|
|
473
|
+
nvidia_nat-1.3.0a20251022.dist-info/licenses/LICENSE-3rd-party.txt,sha256=fOk5jMmCX9YoKWyYzTtfgl-SUy477audFC5hNY4oP7Q,284609
|
|
474
|
+
nvidia_nat-1.3.0a20251022.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
|
|
475
|
+
nvidia_nat-1.3.0a20251022.dist-info/METADATA,sha256=rw6YPLCZm_c9suL_Fh7q5ABrSwQCxdTQOi3m2o-BIz8,10248
|
|
476
|
+
nvidia_nat-1.3.0a20251022.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
477
|
+
nvidia_nat-1.3.0a20251022.dist-info/entry_points.txt,sha256=4jCqjyETMpyoWbCBf4GalZU8I_wbstpzwQNezdAVbbo,698
|
|
478
|
+
nvidia_nat-1.3.0a20251022.dist-info/top_level.txt,sha256=lgJWLkigiVZuZ_O1nxVnD_ziYBwgpE2OStdaCduMEGc,8
|
|
479
|
+
nvidia_nat-1.3.0a20251022.dist-info/RECORD,,
|
|
File without changes
|
{nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{nvidia_nat-1.3.0a20251013.dist-info → nvidia_nat-1.3.0a20251022.dist-info}/licenses/LICENSE.md
RENAMED
|
File without changes
|
|
File without changes
|