nvidia-nat 1.2.1rc1__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiq/__init__.py +2 -2
- nat/agent/base.py +27 -18
- nat/agent/dual_node.py +9 -4
- nat/agent/prompt_optimizer/prompt.py +68 -0
- nat/agent/prompt_optimizer/register.py +149 -0
- nat/agent/react_agent/agent.py +81 -50
- nat/agent/react_agent/register.py +59 -40
- nat/agent/reasoning_agent/reasoning_agent.py +17 -15
- nat/agent/register.py +1 -1
- nat/agent/rewoo_agent/agent.py +327 -149
- nat/agent/rewoo_agent/prompt.py +19 -22
- nat/agent/rewoo_agent/register.py +64 -46
- nat/agent/tool_calling_agent/agent.py +152 -29
- nat/agent/tool_calling_agent/register.py +61 -38
- nat/authentication/api_key/api_key_auth_provider.py +2 -2
- nat/authentication/credential_validator/bearer_token_validator.py +557 -0
- nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
- nat/authentication/interfaces.py +5 -2
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +69 -36
- nat/authentication/oauth2/oauth2_resource_server_config.py +124 -0
- nat/authentication/register.py +0 -1
- nat/builder/builder.py +56 -24
- nat/builder/component_utils.py +10 -6
- nat/builder/context.py +70 -18
- nat/builder/eval_builder.py +16 -11
- nat/builder/framework_enum.py +1 -0
- nat/builder/front_end.py +1 -1
- nat/builder/function.py +378 -8
- nat/builder/function_base.py +3 -3
- nat/builder/function_info.py +6 -8
- nat/builder/intermediate_step_manager.py +6 -2
- nat/builder/user_interaction_manager.py +2 -2
- nat/builder/workflow.py +13 -1
- nat/builder/workflow_builder.py +327 -79
- nat/cli/cli_utils/config_override.py +2 -2
- nat/cli/commands/evaluate.py +1 -1
- nat/cli/commands/info/info.py +16 -6
- nat/cli/commands/info/list_channels.py +1 -1
- nat/cli/commands/info/list_components.py +7 -8
- nat/cli/commands/mcp/__init__.py +14 -0
- nat/cli/commands/mcp/mcp.py +986 -0
- nat/cli/commands/object_store/__init__.py +14 -0
- nat/cli/commands/object_store/object_store.py +227 -0
- nat/cli/commands/optimize.py +90 -0
- nat/cli/commands/registry/publish.py +2 -2
- nat/cli/commands/registry/pull.py +2 -2
- nat/cli/commands/registry/remove.py +2 -2
- nat/cli/commands/registry/search.py +15 -17
- nat/cli/commands/start.py +16 -5
- nat/cli/commands/uninstall.py +1 -1
- nat/cli/commands/workflow/templates/config.yml.j2 +14 -13
- nat/cli/commands/workflow/templates/pyproject.toml.j2 +5 -2
- nat/cli/commands/workflow/templates/register.py.j2 +2 -3
- nat/cli/commands/workflow/templates/workflow.py.j2 +35 -21
- nat/cli/commands/workflow/workflow_commands.py +105 -19
- nat/cli/entrypoint.py +17 -11
- nat/cli/main.py +3 -0
- nat/cli/register_workflow.py +38 -4
- nat/cli/type_registry.py +79 -10
- nat/control_flow/__init__.py +0 -0
- nat/control_flow/register.py +20 -0
- nat/control_flow/router_agent/__init__.py +0 -0
- nat/control_flow/router_agent/agent.py +329 -0
- nat/control_flow/router_agent/prompt.py +48 -0
- nat/control_flow/router_agent/register.py +91 -0
- nat/control_flow/sequential_executor.py +166 -0
- nat/data_models/agent.py +34 -0
- nat/data_models/api_server.py +196 -67
- nat/data_models/authentication.py +23 -9
- nat/data_models/common.py +1 -1
- nat/data_models/component.py +2 -0
- nat/data_models/component_ref.py +11 -0
- nat/data_models/config.py +42 -18
- nat/data_models/dataset_handler.py +1 -1
- nat/data_models/discovery_metadata.py +4 -4
- nat/data_models/evaluate.py +4 -1
- nat/data_models/function.py +34 -0
- nat/data_models/function_dependencies.py +14 -6
- nat/data_models/gated_field_mixin.py +242 -0
- nat/data_models/intermediate_step.py +3 -3
- nat/data_models/optimizable.py +119 -0
- nat/data_models/optimizer.py +149 -0
- nat/data_models/span.py +41 -3
- nat/data_models/swe_bench_model.py +1 -1
- nat/data_models/temperature_mixin.py +44 -0
- nat/data_models/thinking_mixin.py +86 -0
- nat/data_models/top_p_mixin.py +44 -0
- nat/embedder/azure_openai_embedder.py +46 -0
- nat/embedder/nim_embedder.py +1 -1
- nat/embedder/openai_embedder.py +2 -3
- nat/embedder/register.py +1 -1
- nat/eval/config.py +3 -1
- nat/eval/dataset_handler/dataset_handler.py +71 -7
- nat/eval/evaluate.py +86 -31
- nat/eval/evaluator/base_evaluator.py +1 -1
- nat/eval/evaluator/evaluator_model.py +13 -0
- nat/eval/intermediate_step_adapter.py +1 -1
- nat/eval/rag_evaluator/evaluate.py +9 -6
- nat/eval/rag_evaluator/register.py +3 -3
- nat/eval/register.py +4 -1
- nat/eval/remote_workflow.py +3 -3
- nat/eval/runtime_evaluator/__init__.py +14 -0
- nat/eval/runtime_evaluator/evaluate.py +123 -0
- nat/eval/runtime_evaluator/register.py +100 -0
- nat/eval/swe_bench_evaluator/evaluate.py +6 -6
- nat/eval/trajectory_evaluator/evaluate.py +1 -1
- nat/eval/trajectory_evaluator/register.py +1 -1
- nat/eval/tunable_rag_evaluator/evaluate.py +4 -7
- nat/eval/utils/eval_trace_ctx.py +89 -0
- nat/eval/utils/weave_eval.py +18 -9
- nat/experimental/decorators/experimental_warning_decorator.py +27 -7
- nat/experimental/test_time_compute/functions/execute_score_select_function.py +1 -1
- nat/experimental/test_time_compute/functions/plan_select_execute_function.py +7 -3
- nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +3 -3
- nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +3 -3
- nat/experimental/test_time_compute/models/strategy_base.py +5 -4
- nat/experimental/test_time_compute/register.py +0 -1
- nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -3
- nat/front_ends/console/authentication_flow_handler.py +82 -30
- nat/front_ends/console/console_front_end_plugin.py +19 -7
- nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +1 -1
- nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +52 -17
- nat/front_ends/fastapi/dask_client_mixin.py +65 -0
- nat/front_ends/fastapi/fastapi_front_end_config.py +36 -5
- nat/front_ends/fastapi/fastapi_front_end_controller.py +4 -4
- nat/front_ends/fastapi/fastapi_front_end_plugin.py +135 -4
- nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +455 -282
- nat/front_ends/fastapi/job_store.py +518 -99
- nat/front_ends/fastapi/main.py +11 -19
- nat/front_ends/fastapi/message_handler.py +74 -50
- nat/front_ends/fastapi/message_validator.py +20 -21
- nat/front_ends/fastapi/response_helpers.py +4 -4
- nat/front_ends/fastapi/step_adaptor.py +2 -2
- nat/front_ends/fastapi/utils.py +57 -0
- nat/front_ends/mcp/introspection_token_verifier.py +73 -0
- nat/front_ends/mcp/mcp_front_end_config.py +47 -3
- nat/front_ends/mcp/mcp_front_end_plugin.py +48 -13
- nat/front_ends/mcp/mcp_front_end_plugin_worker.py +120 -8
- nat/front_ends/mcp/tool_converter.py +44 -14
- nat/front_ends/register.py +0 -1
- nat/front_ends/simple_base/simple_front_end_plugin_base.py +3 -1
- nat/llm/aws_bedrock_llm.py +24 -12
- nat/llm/azure_openai_llm.py +57 -0
- nat/llm/litellm_llm.py +69 -0
- nat/llm/nim_llm.py +20 -8
- nat/llm/openai_llm.py +14 -6
- nat/llm/register.py +5 -1
- nat/llm/utils/env_config_value.py +2 -3
- nat/llm/utils/thinking.py +215 -0
- nat/meta/pypi.md +9 -9
- nat/object_store/register.py +0 -1
- nat/observability/exporter/base_exporter.py +3 -3
- nat/observability/exporter/file_exporter.py +1 -1
- nat/observability/exporter/processing_exporter.py +309 -81
- nat/observability/exporter/span_exporter.py +35 -15
- nat/observability/exporter_manager.py +7 -7
- nat/observability/mixin/file_mixin.py +7 -7
- nat/observability/mixin/redaction_config_mixin.py +42 -0
- nat/observability/mixin/tagging_config_mixin.py +62 -0
- nat/observability/mixin/type_introspection_mixin.py +420 -107
- nat/observability/processor/batching_processor.py +5 -7
- nat/observability/processor/falsy_batch_filter_processor.py +55 -0
- nat/observability/processor/processor.py +3 -0
- nat/observability/processor/processor_factory.py +70 -0
- nat/observability/processor/redaction/__init__.py +24 -0
- nat/observability/processor/redaction/contextual_redaction_processor.py +125 -0
- nat/observability/processor/redaction/contextual_span_redaction_processor.py +66 -0
- nat/observability/processor/redaction/redaction_processor.py +177 -0
- nat/observability/processor/redaction/span_header_redaction_processor.py +92 -0
- nat/observability/processor/span_tagging_processor.py +68 -0
- nat/observability/register.py +22 -4
- nat/profiler/calc/calc_runner.py +3 -4
- nat/profiler/callbacks/agno_callback_handler.py +1 -1
- nat/profiler/callbacks/langchain_callback_handler.py +14 -7
- nat/profiler/callbacks/llama_index_callback_handler.py +3 -3
- nat/profiler/callbacks/semantic_kernel_callback_handler.py +3 -3
- nat/profiler/data_frame_row.py +1 -1
- nat/profiler/decorators/framework_wrapper.py +62 -13
- nat/profiler/decorators/function_tracking.py +160 -3
- nat/profiler/forecasting/models/forecasting_base_model.py +3 -1
- nat/profiler/forecasting/models/linear_model.py +1 -1
- nat/profiler/forecasting/models/random_forest_regressor.py +1 -1
- nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
- nat/profiler/inference_optimization/data_models.py +3 -3
- nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +8 -9
- nat/profiler/inference_optimization/token_uniqueness.py +1 -1
- nat/profiler/parameter_optimization/__init__.py +0 -0
- nat/profiler/parameter_optimization/optimizable_utils.py +93 -0
- nat/profiler/parameter_optimization/optimizer_runtime.py +67 -0
- nat/profiler/parameter_optimization/parameter_optimizer.py +164 -0
- nat/profiler/parameter_optimization/parameter_selection.py +107 -0
- nat/profiler/parameter_optimization/pareto_visualizer.py +395 -0
- nat/profiler/parameter_optimization/prompt_optimizer.py +384 -0
- nat/profiler/parameter_optimization/update_helpers.py +66 -0
- nat/profiler/profile_runner.py +14 -9
- nat/profiler/utils.py +4 -2
- nat/registry_handlers/local/local_handler.py +2 -2
- nat/registry_handlers/package_utils.py +1 -2
- nat/registry_handlers/pypi/pypi_handler.py +23 -26
- nat/registry_handlers/register.py +3 -4
- nat/registry_handlers/rest/rest_handler.py +12 -13
- nat/retriever/milvus/retriever.py +2 -2
- nat/retriever/nemo_retriever/retriever.py +1 -1
- nat/retriever/register.py +0 -1
- nat/runtime/loader.py +2 -2
- nat/runtime/runner.py +105 -8
- nat/runtime/session.py +69 -8
- nat/settings/global_settings.py +16 -5
- nat/tool/chat_completion.py +5 -2
- nat/tool/code_execution/local_sandbox/local_sandbox_server.py +3 -3
- nat/tool/datetime_tools.py +49 -9
- nat/tool/document_search.py +2 -2
- nat/tool/github_tools.py +450 -0
- nat/tool/memory_tools/add_memory_tool.py +3 -3
- nat/tool/memory_tools/delete_memory_tool.py +3 -4
- nat/tool/memory_tools/get_memory_tool.py +4 -4
- nat/tool/nvidia_rag.py +1 -1
- nat/tool/register.py +2 -9
- nat/tool/retriever.py +3 -2
- nat/utils/callable_utils.py +70 -0
- nat/utils/data_models/schema_validator.py +3 -3
- nat/utils/decorators.py +210 -0
- nat/utils/exception_handlers/automatic_retries.py +104 -51
- nat/utils/exception_handlers/schemas.py +1 -1
- nat/utils/io/yaml_tools.py +2 -2
- nat/utils/log_levels.py +25 -0
- nat/utils/reactive/base/observable_base.py +2 -2
- nat/utils/reactive/base/observer_base.py +1 -1
- nat/utils/reactive/observable.py +2 -2
- nat/utils/reactive/observer.py +4 -4
- nat/utils/reactive/subscription.py +1 -1
- nat/utils/settings/global_settings.py +6 -8
- nat/utils/type_converter.py +12 -3
- nat/utils/type_utils.py +9 -5
- nvidia_nat-1.3.0.dist-info/METADATA +195 -0
- {nvidia_nat-1.2.1rc1.dist-info → nvidia_nat-1.3.0.dist-info}/RECORD +244 -200
- {nvidia_nat-1.2.1rc1.dist-info → nvidia_nat-1.3.0.dist-info}/entry_points.txt +1 -0
- nat/cli/commands/info/list_mcp.py +0 -304
- nat/tool/github_tools/create_github_commit.py +0 -133
- nat/tool/github_tools/create_github_issue.py +0 -87
- nat/tool/github_tools/create_github_pr.py +0 -106
- nat/tool/github_tools/get_github_file.py +0 -106
- nat/tool/github_tools/get_github_issue.py +0 -166
- nat/tool/github_tools/get_github_pr.py +0 -256
- nat/tool/github_tools/update_github_issue.py +0 -100
- nat/tool/mcp/exceptions.py +0 -142
- nat/tool/mcp/mcp_client.py +0 -255
- nat/tool/mcp/mcp_tool.py +0 -96
- nat/utils/exception_handlers/mcp.py +0 -211
- nvidia_nat-1.2.1rc1.dist-info/METADATA +0 -365
- /nat/{tool/github_tools → agent/prompt_optimizer}/__init__.py +0 -0
- /nat/{tool/mcp → authentication/credential_validator}/__init__.py +0 -0
- {nvidia_nat-1.2.1rc1.dist-info → nvidia_nat-1.3.0.dist-info}/WHEEL +0 -0
- {nvidia_nat-1.2.1rc1.dist-info → nvidia_nat-1.3.0.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
- {nvidia_nat-1.2.1rc1.dist-info → nvidia_nat-1.3.0.dist-info}/licenses/LICENSE.md +0 -0
- {nvidia_nat-1.2.1rc1.dist-info → nvidia_nat-1.3.0.dist-info}/top_level.txt +0 -0
nat/data_models/api_server.py
CHANGED
|
@@ -28,6 +28,7 @@ from pydantic import HttpUrl
|
|
|
28
28
|
from pydantic import conlist
|
|
29
29
|
from pydantic import field_serializer
|
|
30
30
|
from pydantic import field_validator
|
|
31
|
+
from pydantic import model_validator
|
|
31
32
|
from pydantic_core.core_schema import ValidationInfo
|
|
32
33
|
|
|
33
34
|
from nat.data_models.interactive import HumanPrompt
|
|
@@ -36,6 +37,15 @@ from nat.utils.type_converter import GlobalTypeConverter
|
|
|
36
37
|
FINISH_REASONS = frozenset({'stop', 'length', 'tool_calls', 'content_filter', 'function_call'})
|
|
37
38
|
|
|
38
39
|
|
|
40
|
+
class UserMessageContentRoleType(str, Enum):
|
|
41
|
+
"""
|
|
42
|
+
Enum representing chat message roles in API requests and responses.
|
|
43
|
+
"""
|
|
44
|
+
USER = "user"
|
|
45
|
+
ASSISTANT = "assistant"
|
|
46
|
+
SYSTEM = "system"
|
|
47
|
+
|
|
48
|
+
|
|
39
49
|
class Request(BaseModel):
|
|
40
50
|
"""
|
|
41
51
|
Request is a data model that represents HTTP request attributes.
|
|
@@ -108,7 +118,7 @@ UserContent = typing.Annotated[TextContent | ImageContent | AudioContent, Discri
|
|
|
108
118
|
|
|
109
119
|
class Message(BaseModel):
|
|
110
120
|
content: str | list[UserContent]
|
|
111
|
-
role:
|
|
121
|
+
role: UserMessageContentRoleType
|
|
112
122
|
|
|
113
123
|
|
|
114
124
|
class ChatRequest(BaseModel):
|
|
@@ -143,7 +153,6 @@ class ChatRequest(BaseModel):
|
|
|
143
153
|
tool_choice: str | dict[str, typing.Any] | None = Field(default=None, description="Controls which tool is called")
|
|
144
154
|
parallel_tool_calls: bool | None = Field(default=True, description="Whether to enable parallel function calling")
|
|
145
155
|
user: str | None = Field(default=None, description="Unique identifier representing end-user")
|
|
146
|
-
|
|
147
156
|
model_config = ConfigDict(extra="allow",
|
|
148
157
|
json_schema_extra={
|
|
149
158
|
"example": {
|
|
@@ -164,7 +173,7 @@ class ChatRequest(BaseModel):
|
|
|
164
173
|
max_tokens: int | None = None,
|
|
165
174
|
top_p: float | None = None) -> "ChatRequest":
|
|
166
175
|
|
|
167
|
-
return ChatRequest(messages=[Message(content=data, role=
|
|
176
|
+
return ChatRequest(messages=[Message(content=data, role=UserMessageContentRoleType.USER)],
|
|
168
177
|
model=model,
|
|
169
178
|
temperature=temperature,
|
|
170
179
|
max_tokens=max_tokens,
|
|
@@ -178,38 +187,128 @@ class ChatRequest(BaseModel):
|
|
|
178
187
|
max_tokens: int | None = None,
|
|
179
188
|
top_p: float | None = None) -> "ChatRequest":
|
|
180
189
|
|
|
181
|
-
return ChatRequest(messages=[Message(content=content, role=
|
|
190
|
+
return ChatRequest(messages=[Message(content=content, role=UserMessageContentRoleType.USER)],
|
|
182
191
|
model=model,
|
|
183
192
|
temperature=temperature,
|
|
184
193
|
max_tokens=max_tokens,
|
|
185
194
|
top_p=top_p)
|
|
186
195
|
|
|
187
196
|
|
|
197
|
+
class ChatRequestOrMessage(BaseModel):
|
|
198
|
+
"""
|
|
199
|
+
`ChatRequestOrMessage` is a data model that represents either a conversation or a string input.
|
|
200
|
+
This is useful for functions that can handle either type of input.
|
|
201
|
+
|
|
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
|
+
)
|
|
247
|
+
|
|
248
|
+
messages: typing.Annotated[list[Message] | None, conlist(Message, min_length=1)] = Field(
|
|
249
|
+
default=None, description="A non-empty conversation of messages to process.")
|
|
250
|
+
|
|
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")
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def is_string(self) -> bool:
|
|
257
|
+
return self.input_message is not None
|
|
258
|
+
|
|
259
|
+
@property
|
|
260
|
+
def is_conversation(self) -> bool:
|
|
261
|
+
return self.messages is not None
|
|
262
|
+
|
|
263
|
+
@model_validator(mode="after")
|
|
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)
|
|
271
|
+
if len(extra_fields) > 0:
|
|
272
|
+
raise ValueError("no extra fields are permitted when input_message is provided")
|
|
273
|
+
return self
|
|
274
|
+
|
|
275
|
+
|
|
188
276
|
class ChoiceMessage(BaseModel):
|
|
189
277
|
content: str | None = None
|
|
190
|
-
role:
|
|
278
|
+
role: UserMessageContentRoleType | None = None
|
|
191
279
|
|
|
192
280
|
|
|
193
281
|
class ChoiceDelta(BaseModel):
|
|
194
282
|
"""Delta object for streaming responses (OpenAI-compatible)"""
|
|
195
283
|
content: str | None = None
|
|
196
|
-
role:
|
|
284
|
+
role: UserMessageContentRoleType | None = None
|
|
197
285
|
|
|
198
286
|
|
|
199
|
-
class
|
|
287
|
+
class ChoiceBase(BaseModel):
|
|
288
|
+
"""Base choice model with common fields for both streaming and non-streaming responses"""
|
|
200
289
|
model_config = ConfigDict(extra="allow")
|
|
201
|
-
|
|
202
|
-
message: ChoiceMessage | None = None
|
|
203
|
-
delta: ChoiceDelta | None = None
|
|
204
290
|
finish_reason: typing.Literal['stop', 'length', 'tool_calls', 'content_filter', 'function_call'] | None = None
|
|
205
291
|
index: int
|
|
206
|
-
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class ChatResponseChoice(ChoiceBase):
|
|
295
|
+
"""Choice model for non-streaming responses - contains message field"""
|
|
296
|
+
message: ChoiceMessage
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class ChatResponseChunkChoice(ChoiceBase):
|
|
300
|
+
"""Choice model for streaming responses - contains delta field"""
|
|
301
|
+
delta: ChoiceDelta
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# Backward compatibility alias
|
|
305
|
+
Choice = ChatResponseChoice
|
|
207
306
|
|
|
208
307
|
|
|
209
308
|
class Usage(BaseModel):
|
|
210
|
-
prompt_tokens: int
|
|
211
|
-
completion_tokens: int
|
|
212
|
-
total_tokens: int
|
|
309
|
+
prompt_tokens: int | None = None
|
|
310
|
+
completion_tokens: int | None = None
|
|
311
|
+
total_tokens: int | None = None
|
|
213
312
|
|
|
214
313
|
|
|
215
314
|
class ResponseSerializable(abc.ABC):
|
|
@@ -245,10 +344,10 @@ class ChatResponse(ResponseBaseModelOutput):
|
|
|
245
344
|
model_config = ConfigDict(extra="allow")
|
|
246
345
|
id: str
|
|
247
346
|
object: str = "chat.completion"
|
|
248
|
-
model: str = ""
|
|
347
|
+
model: str = "unknown-model"
|
|
249
348
|
created: datetime.datetime
|
|
250
|
-
choices: list[
|
|
251
|
-
usage: Usage
|
|
349
|
+
choices: list[ChatResponseChoice]
|
|
350
|
+
usage: Usage
|
|
252
351
|
system_fingerprint: str | None = None
|
|
253
352
|
service_tier: typing.Literal["scale", "default"] | None = None
|
|
254
353
|
|
|
@@ -264,22 +363,27 @@ class ChatResponse(ResponseBaseModelOutput):
|
|
|
264
363
|
object_: str | None = None,
|
|
265
364
|
model: str | None = None,
|
|
266
365
|
created: datetime.datetime | None = None,
|
|
267
|
-
usage: Usage
|
|
366
|
+
usage: Usage) -> "ChatResponse":
|
|
268
367
|
|
|
269
368
|
if id_ is None:
|
|
270
369
|
id_ = str(uuid.uuid4())
|
|
271
370
|
if object_ is None:
|
|
272
371
|
object_ = "chat.completion"
|
|
273
372
|
if model is None:
|
|
274
|
-
model = ""
|
|
373
|
+
model = "unknown-model"
|
|
275
374
|
if created is None:
|
|
276
|
-
created = datetime.datetime.now(datetime.
|
|
375
|
+
created = datetime.datetime.now(datetime.UTC)
|
|
277
376
|
|
|
278
377
|
return ChatResponse(id=id_,
|
|
279
378
|
object=object_,
|
|
280
379
|
model=model,
|
|
281
380
|
created=created,
|
|
282
|
-
choices=[
|
|
381
|
+
choices=[
|
|
382
|
+
ChatResponseChoice(index=0,
|
|
383
|
+
message=ChoiceMessage(content=data,
|
|
384
|
+
role=UserMessageContentRoleType.ASSISTANT),
|
|
385
|
+
finish_reason="stop")
|
|
386
|
+
],
|
|
283
387
|
usage=usage)
|
|
284
388
|
|
|
285
389
|
|
|
@@ -293,9 +397,9 @@ class ChatResponseChunk(ResponseBaseModelOutput):
|
|
|
293
397
|
model_config = ConfigDict(extra="allow")
|
|
294
398
|
|
|
295
399
|
id: str
|
|
296
|
-
choices: list[
|
|
400
|
+
choices: list[ChatResponseChunkChoice]
|
|
297
401
|
created: datetime.datetime
|
|
298
|
-
model: str = ""
|
|
402
|
+
model: str = "unknown-model"
|
|
299
403
|
object: str = "chat.completion.chunk"
|
|
300
404
|
system_fingerprint: str | None = None
|
|
301
405
|
service_tier: typing.Literal["scale", "default"] | None = None
|
|
@@ -317,14 +421,20 @@ class ChatResponseChunk(ResponseBaseModelOutput):
|
|
|
317
421
|
if id_ is None:
|
|
318
422
|
id_ = str(uuid.uuid4())
|
|
319
423
|
if created is None:
|
|
320
|
-
created = datetime.datetime.now(datetime.
|
|
424
|
+
created = datetime.datetime.now(datetime.UTC)
|
|
321
425
|
if model is None:
|
|
322
|
-
model = ""
|
|
426
|
+
model = "unknown-model"
|
|
323
427
|
if object_ is None:
|
|
324
428
|
object_ = "chat.completion.chunk"
|
|
325
429
|
|
|
326
430
|
return ChatResponseChunk(id=id_,
|
|
327
|
-
choices=[
|
|
431
|
+
choices=[
|
|
432
|
+
ChatResponseChunkChoice(index=0,
|
|
433
|
+
delta=ChoiceDelta(
|
|
434
|
+
content=data,
|
|
435
|
+
role=UserMessageContentRoleType.ASSISTANT),
|
|
436
|
+
finish_reason="stop")
|
|
437
|
+
],
|
|
328
438
|
created=created,
|
|
329
439
|
model=model,
|
|
330
440
|
object=object_)
|
|
@@ -335,7 +445,7 @@ class ChatResponseChunk(ResponseBaseModelOutput):
|
|
|
335
445
|
id_: str | None = None,
|
|
336
446
|
created: datetime.datetime | None = None,
|
|
337
447
|
model: str | None = None,
|
|
338
|
-
role:
|
|
448
|
+
role: UserMessageContentRoleType | None = None,
|
|
339
449
|
finish_reason: str | None = None,
|
|
340
450
|
usage: Usage | None = None,
|
|
341
451
|
system_fingerprint: str | None = None) -> "ChatResponseChunk":
|
|
@@ -343,9 +453,9 @@ class ChatResponseChunk(ResponseBaseModelOutput):
|
|
|
343
453
|
if id_ is None:
|
|
344
454
|
id_ = str(uuid.uuid4())
|
|
345
455
|
if created is None:
|
|
346
|
-
created = datetime.datetime.now(datetime.
|
|
456
|
+
created = datetime.datetime.now(datetime.UTC)
|
|
347
457
|
if model is None:
|
|
348
|
-
model = ""
|
|
458
|
+
model = "unknown-model"
|
|
349
459
|
|
|
350
460
|
delta = ChoiceDelta(content=content, role=role) if content is not None or role is not None else ChoiceDelta()
|
|
351
461
|
|
|
@@ -353,7 +463,14 @@ class ChatResponseChunk(ResponseBaseModelOutput):
|
|
|
353
463
|
|
|
354
464
|
return ChatResponseChunk(
|
|
355
465
|
id=id_,
|
|
356
|
-
choices=[
|
|
466
|
+
choices=[
|
|
467
|
+
ChatResponseChunkChoice(
|
|
468
|
+
index=0,
|
|
469
|
+
delta=delta,
|
|
470
|
+
finish_reason=typing.cast(
|
|
471
|
+
typing.Literal['stop', 'length', 'tool_calls', 'content_filter', 'function_call'] | None,
|
|
472
|
+
final_finish_reason))
|
|
473
|
+
],
|
|
357
474
|
created=created,
|
|
358
475
|
model=model,
|
|
359
476
|
object="chat.completion.chunk",
|
|
@@ -398,11 +515,6 @@ class GenerateResponse(BaseModel):
|
|
|
398
515
|
value: str | None = "default"
|
|
399
516
|
|
|
400
517
|
|
|
401
|
-
class UserMessageContentRoleType(str, Enum):
|
|
402
|
-
USER = "user"
|
|
403
|
-
ASSISTANT = "assistant"
|
|
404
|
-
|
|
405
|
-
|
|
406
518
|
class WebSocketMessageType(str, Enum):
|
|
407
519
|
"""
|
|
408
520
|
WebSocketMessageType is an Enum that represents WebSocket Message types.
|
|
@@ -485,7 +597,7 @@ class WebSocketUserMessage(BaseModel):
|
|
|
485
597
|
security: Security = Security()
|
|
486
598
|
error: Error = Error()
|
|
487
599
|
schema_version: str = "1.0.0"
|
|
488
|
-
timestamp: str = str(datetime.datetime.now(datetime.
|
|
600
|
+
timestamp: str = str(datetime.datetime.now(datetime.UTC))
|
|
489
601
|
|
|
490
602
|
|
|
491
603
|
class WebSocketUserInteractionResponseMessage(BaseModel):
|
|
@@ -496,12 +608,14 @@ class WebSocketUserInteractionResponseMessage(BaseModel):
|
|
|
496
608
|
type: typing.Literal[WebSocketMessageType.USER_INTERACTION_MESSAGE]
|
|
497
609
|
id: str = "default"
|
|
498
610
|
thread_id: str = "default"
|
|
611
|
+
parent_id: str = "default"
|
|
612
|
+
conversation_id: str | None = None
|
|
499
613
|
content: UserMessageContent
|
|
500
614
|
user: User = User()
|
|
501
615
|
security: Security = Security()
|
|
502
616
|
error: Error = Error()
|
|
503
617
|
schema_version: str = "1.0.0"
|
|
504
|
-
timestamp: str = str(datetime.datetime.now(datetime.
|
|
618
|
+
timestamp: str = str(datetime.datetime.now(datetime.UTC))
|
|
505
619
|
|
|
506
620
|
|
|
507
621
|
class SystemIntermediateStepContent(BaseModel):
|
|
@@ -527,7 +641,7 @@ class WebSocketSystemIntermediateStepMessage(BaseModel):
|
|
|
527
641
|
conversation_id: str | None = None
|
|
528
642
|
content: SystemIntermediateStepContent
|
|
529
643
|
status: WebSocketMessageStatus
|
|
530
|
-
timestamp: str = str(datetime.datetime.now(datetime.
|
|
644
|
+
timestamp: str = str(datetime.datetime.now(datetime.UTC))
|
|
531
645
|
|
|
532
646
|
|
|
533
647
|
class SystemResponseContent(BaseModel):
|
|
@@ -551,7 +665,7 @@ class WebSocketSystemResponseTokenMessage(BaseModel):
|
|
|
551
665
|
conversation_id: str | None = None
|
|
552
666
|
content: SystemResponseContent | Error | GenerateResponse
|
|
553
667
|
status: WebSocketMessageStatus
|
|
554
|
-
timestamp: str = str(datetime.datetime.now(datetime.
|
|
668
|
+
timestamp: str = str(datetime.datetime.now(datetime.UTC))
|
|
555
669
|
|
|
556
670
|
@field_validator("content")
|
|
557
671
|
@classmethod
|
|
@@ -560,7 +674,7 @@ class WebSocketSystemResponseTokenMessage(BaseModel):
|
|
|
560
674
|
raise ValueError(f"Field: content must be 'Error' when type is {WebSocketMessageType.ERROR_MESSAGE}")
|
|
561
675
|
|
|
562
676
|
if info.data.get("type") == WebSocketMessageType.RESPONSE_MESSAGE and not isinstance(
|
|
563
|
-
value,
|
|
677
|
+
value, SystemResponseContent | GenerateResponse):
|
|
564
678
|
raise ValueError(
|
|
565
679
|
f"Field: content must be 'SystemResponseContent' when type is {WebSocketMessageType.RESPONSE_MESSAGE}")
|
|
566
680
|
return value
|
|
@@ -582,7 +696,7 @@ class WebSocketSystemInteractionMessage(BaseModel):
|
|
|
582
696
|
conversation_id: str | None = None
|
|
583
697
|
content: HumanPrompt
|
|
584
698
|
status: WebSocketMessageStatus
|
|
585
|
-
timestamp: str = str(datetime.datetime.now(datetime.
|
|
699
|
+
timestamp: str = str(datetime.datetime.now(datetime.UTC))
|
|
586
700
|
|
|
587
701
|
|
|
588
702
|
# ======== GenerateResponse Converters ========
|
|
@@ -622,12 +736,52 @@ GlobalTypeConverter.register_converter(_nat_chat_request_to_string)
|
|
|
622
736
|
|
|
623
737
|
|
|
624
738
|
def _string_to_nat_chat_request(data: str) -> ChatRequest:
|
|
625
|
-
return ChatRequest.from_string(data, model="")
|
|
739
|
+
return ChatRequest.from_string(data, model="unknown-model")
|
|
626
740
|
|
|
627
741
|
|
|
628
742
|
GlobalTypeConverter.register_converter(_string_to_nat_chat_request)
|
|
629
743
|
|
|
630
744
|
|
|
745
|
+
def _chat_request_or_message_to_chat_request(data: ChatRequestOrMessage) -> ChatRequest:
|
|
746
|
+
if data.input_message is not None:
|
|
747
|
+
return _string_to_nat_chat_request(data.input_message)
|
|
748
|
+
return ChatRequest(**data.model_dump(exclude={"input_message"}))
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
GlobalTypeConverter.register_converter(_chat_request_or_message_to_chat_request)
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
def _chat_request_to_chat_request_or_message(data: ChatRequest) -> ChatRequestOrMessage:
|
|
755
|
+
return ChatRequestOrMessage(**data.model_dump(by_alias=True))
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
GlobalTypeConverter.register_converter(_chat_request_to_chat_request_or_message)
|
|
759
|
+
|
|
760
|
+
|
|
761
|
+
def _chat_request_or_message_to_string(data: ChatRequestOrMessage) -> str:
|
|
762
|
+
if data.input_message is not None:
|
|
763
|
+
return data.input_message
|
|
764
|
+
# Extract content from last message in conversation
|
|
765
|
+
if data.messages is None:
|
|
766
|
+
return ""
|
|
767
|
+
content = data.messages[-1].content
|
|
768
|
+
if content is None:
|
|
769
|
+
return ""
|
|
770
|
+
if isinstance(content, str):
|
|
771
|
+
return content
|
|
772
|
+
return str(content)
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
GlobalTypeConverter.register_converter(_chat_request_or_message_to_string)
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
def _string_to_chat_request_or_message(data: str) -> ChatRequestOrMessage:
|
|
779
|
+
return ChatRequestOrMessage(input_message=data)
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
GlobalTypeConverter.register_converter(_string_to_chat_request_or_message)
|
|
783
|
+
|
|
784
|
+
|
|
631
785
|
# ======== ChatResponse Converters ========
|
|
632
786
|
def _nat_chat_response_to_string(data: ChatResponse) -> str:
|
|
633
787
|
if data.choices and data.choices[0].message:
|
|
@@ -654,22 +808,12 @@ def _string_to_nat_chat_response(data: str) -> ChatResponse:
|
|
|
654
808
|
GlobalTypeConverter.register_converter(_string_to_nat_chat_response)
|
|
655
809
|
|
|
656
810
|
|
|
657
|
-
def _chat_response_to_chat_response_chunk(data: ChatResponse) -> ChatResponseChunk:
|
|
658
|
-
# Preserve original message structure for backward compatibility
|
|
659
|
-
return ChatResponseChunk(id=data.id, choices=data.choices, created=data.created, model=data.model)
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
GlobalTypeConverter.register_converter(_chat_response_to_chat_response_chunk)
|
|
663
|
-
|
|
664
|
-
|
|
665
811
|
# ======== ChatResponseChunk Converters ========
|
|
666
812
|
def _chat_response_chunk_to_string(data: ChatResponseChunk) -> str:
|
|
667
813
|
if data.choices and len(data.choices) > 0:
|
|
668
814
|
choice = data.choices[0]
|
|
669
815
|
if choice.delta and choice.delta.content:
|
|
670
816
|
return choice.delta.content
|
|
671
|
-
if choice.message and choice.message.content:
|
|
672
|
-
return choice.message.content
|
|
673
817
|
return ""
|
|
674
818
|
|
|
675
819
|
|
|
@@ -685,21 +829,6 @@ def _string_to_nat_chat_response_chunk(data: str) -> ChatResponseChunk:
|
|
|
685
829
|
|
|
686
830
|
GlobalTypeConverter.register_converter(_string_to_nat_chat_response_chunk)
|
|
687
831
|
|
|
688
|
-
|
|
689
|
-
# ======== AINodeMessageChunk Converters ========
|
|
690
|
-
def _ai_message_chunk_to_nat_chat_response_chunk(data) -> ChatResponseChunk:
|
|
691
|
-
'''Converts LangChain AINodeMessageChunk to ChatResponseChunk'''
|
|
692
|
-
content = ""
|
|
693
|
-
if hasattr(data, 'content') and data.content is not None:
|
|
694
|
-
content = str(data.content)
|
|
695
|
-
elif hasattr(data, 'text') and data.text is not None:
|
|
696
|
-
content = str(data.text)
|
|
697
|
-
elif hasattr(data, 'message') and data.message is not None:
|
|
698
|
-
content = str(data.message)
|
|
699
|
-
|
|
700
|
-
return ChatResponseChunk.create_streaming_chunk(content=content, role="assistant", finish_reason=None)
|
|
701
|
-
|
|
702
|
-
|
|
703
832
|
# Compatibility aliases with previous releases
|
|
704
833
|
AIQChatRequest = ChatRequest
|
|
705
834
|
AIQChoiceMessage = ChoiceMessage
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
16
|
import typing
|
|
17
|
+
from datetime import UTC
|
|
17
18
|
from datetime import datetime
|
|
18
|
-
from datetime import timezone
|
|
19
19
|
from enum import Enum
|
|
20
20
|
|
|
21
21
|
import httpx
|
|
@@ -166,17 +166,31 @@ class BearerTokenCred(_CredBase):
|
|
|
166
166
|
|
|
167
167
|
|
|
168
168
|
Credential = typing.Annotated[
|
|
169
|
-
|
|
170
|
-
HeaderCred,
|
|
171
|
-
QueryCred,
|
|
172
|
-
CookieCred,
|
|
173
|
-
BasicAuthCred,
|
|
174
|
-
BearerTokenCred,
|
|
175
|
-
],
|
|
169
|
+
HeaderCred | QueryCred | CookieCred | BasicAuthCred | BearerTokenCred,
|
|
176
170
|
Field(discriminator="kind"),
|
|
177
171
|
]
|
|
178
172
|
|
|
179
173
|
|
|
174
|
+
class TokenValidationResult(BaseModel):
|
|
175
|
+
"""
|
|
176
|
+
Standard result for Bearer Token Validation.
|
|
177
|
+
"""
|
|
178
|
+
model_config = ConfigDict(extra="forbid")
|
|
179
|
+
|
|
180
|
+
client_id: str | None = Field(description="OAuth2 client identifier")
|
|
181
|
+
scopes: list[str] | None = Field(default=None, description="List of granted scopes (introspection only)")
|
|
182
|
+
expires_at: int | None = Field(default=None, description="Token expiration time (Unix timestamp)")
|
|
183
|
+
audience: list[str] | None = Field(default=None, description="Token audiences (aud claim)")
|
|
184
|
+
subject: str | None = Field(default=None, description="Token subject (sub claim)")
|
|
185
|
+
issuer: str | None = Field(default=None, description="Token issuer (iss claim)")
|
|
186
|
+
token_type: str = Field(description="Token type")
|
|
187
|
+
active: bool | None = Field(default=True, description="Token active status")
|
|
188
|
+
nbf: int | None = Field(default=None, description="Not before time (Unix timestamp)")
|
|
189
|
+
iat: int | None = Field(default=None, description="Issued at time (Unix timestamp)")
|
|
190
|
+
jti: str | None = Field(default=None, description="JWT ID")
|
|
191
|
+
username: str | None = Field(default=None, description="Username (introspection only)")
|
|
192
|
+
|
|
193
|
+
|
|
180
194
|
class AuthResult(BaseModel):
|
|
181
195
|
"""
|
|
182
196
|
Represents the result of an authentication process.
|
|
@@ -193,7 +207,7 @@ class AuthResult(BaseModel):
|
|
|
193
207
|
"""
|
|
194
208
|
Checks if the authentication token has expired.
|
|
195
209
|
"""
|
|
196
|
-
return bool(self.token_expires_at and datetime.now(
|
|
210
|
+
return bool(self.token_expires_at and datetime.now(UTC) >= self.token_expires_at)
|
|
197
211
|
|
|
198
212
|
def as_requests_kwargs(self) -> dict[str, typing.Any]:
|
|
199
213
|
"""
|
nat/data_models/common.py
CHANGED
|
@@ -160,7 +160,7 @@ class TypedBaseModel(BaseModel):
|
|
|
160
160
|
|
|
161
161
|
@staticmethod
|
|
162
162
|
def discriminator(v: typing.Any) -> str | None:
|
|
163
|
-
# If
|
|
163
|
+
# If it's serialized, then we use the alias
|
|
164
164
|
if isinstance(v, dict):
|
|
165
165
|
return v.get("_type", v.get("type"))
|
|
166
166
|
|
nat/data_models/component.py
CHANGED
|
@@ -27,6 +27,7 @@ class ComponentEnum(StrEnum):
|
|
|
27
27
|
EVALUATOR = "evaluator"
|
|
28
28
|
FRONT_END = "front_end"
|
|
29
29
|
FUNCTION = "function"
|
|
30
|
+
FUNCTION_GROUP = "function_group"
|
|
30
31
|
TTC_STRATEGY = "ttc_strategy"
|
|
31
32
|
LLM_CLIENT = "llm_client"
|
|
32
33
|
LLM_PROVIDER = "llm_provider"
|
|
@@ -47,6 +48,7 @@ class ComponentGroup(StrEnum):
|
|
|
47
48
|
AUTHENTICATION = "authentication"
|
|
48
49
|
EMBEDDERS = "embedders"
|
|
49
50
|
FUNCTIONS = "functions"
|
|
51
|
+
FUNCTION_GROUPS = "function_groups"
|
|
50
52
|
TTC_STRATEGIES = "ttc_strategies"
|
|
51
53
|
LLMS = "llms"
|
|
52
54
|
MEMORY = "memory"
|
nat/data_models/component_ref.py
CHANGED
|
@@ -102,6 +102,17 @@ class FunctionRef(ComponentRef):
|
|
|
102
102
|
return ComponentGroup.FUNCTIONS
|
|
103
103
|
|
|
104
104
|
|
|
105
|
+
class FunctionGroupRef(ComponentRef):
|
|
106
|
+
"""
|
|
107
|
+
A reference to a function group in a NAT configuration object.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
@override
|
|
112
|
+
def component_group(self):
|
|
113
|
+
return ComponentGroup.FUNCTION_GROUPS
|
|
114
|
+
|
|
115
|
+
|
|
105
116
|
class LLMRef(ComponentRef):
|
|
106
117
|
"""
|
|
107
118
|
A reference to an LLM in a NAT configuration object.
|