nvidia-nat-data-flywheel 1.3.0a20250828__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/meta/pypi.md +23 -0
- nat/plugins/data_flywheel/observability/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/exporter/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/exporter/dfw_elasticsearch_exporter.py +74 -0
- nat/plugins/data_flywheel/observability/exporter/dfw_exporter.py +99 -0
- nat/plugins/data_flywheel/observability/mixin/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/mixin/elasticsearch_mixin.py +75 -0
- nat/plugins/data_flywheel/observability/processor/__init__.py +27 -0
- nat/plugins/data_flywheel/observability/processor/dfw_record_processor.py +86 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/__init__.py +30 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/elasticsearch/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/elasticsearch/nim_converter.py +44 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/elasticsearch/openai_converter.py +368 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/register.py +24 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/span_extractor.py +79 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/span_to_dfw_record.py +119 -0
- nat/plugins/data_flywheel/observability/processor/trace_conversion/trace_adapter_registry.py +255 -0
- nat/plugins/data_flywheel/observability/register.py +61 -0
- nat/plugins/data_flywheel/observability/schema/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/schema/provider/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/schema/provider/nim_trace_source.py +24 -0
- nat/plugins/data_flywheel/observability/schema/provider/openai_message.py +31 -0
- nat/plugins/data_flywheel/observability/schema/provider/openai_trace_source.py +95 -0
- nat/plugins/data_flywheel/observability/schema/register.py +21 -0
- nat/plugins/data_flywheel/observability/schema/schema_registry.py +144 -0
- nat/plugins/data_flywheel/observability/schema/sink/__init__.py +14 -0
- nat/plugins/data_flywheel/observability/schema/sink/elasticsearch/__init__.py +20 -0
- nat/plugins/data_flywheel/observability/schema/sink/elasticsearch/contract_version.py +31 -0
- nat/plugins/data_flywheel/observability/schema/sink/elasticsearch/dfw_es_record.py +222 -0
- nat/plugins/data_flywheel/observability/schema/trace_container.py +79 -0
- nat/plugins/data_flywheel/observability/schema/trace_source_base.py +22 -0
- nat/plugins/data_flywheel/observability/utils/deserialize.py +42 -0
- nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/METADATA +34 -0
- nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/RECORD +38 -0
- nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/WHEEL +5 -0
- nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/entry_points.txt +4 -0
- nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/top_level.txt +1 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
# schemas are auto-discovered by the discovery system - no manual imports needed
|
17
|
+
from .contract_version import ContractVersion
|
18
|
+
from .dfw_es_record import DFWESRecord
|
19
|
+
|
20
|
+
__all__ = ["DFWESRecord", "ContractVersion"]
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
from enum import Enum
|
17
|
+
|
18
|
+
from pydantic import BaseModel
|
19
|
+
|
20
|
+
from nat.plugins.data_flywheel.observability.schema.schema_registry import SchemaRegistry
|
21
|
+
|
22
|
+
|
23
|
+
class ContractVersion(str, Enum):
|
24
|
+
"""The contract version for Elasticsearch schema."""
|
25
|
+
|
26
|
+
V1_0 = "1.0"
|
27
|
+
V1_1 = "1.1"
|
28
|
+
|
29
|
+
def get_contract_class(self) -> type[BaseModel]:
|
30
|
+
"""Get the Pydantic model class for this contract version."""
|
31
|
+
return SchemaRegistry.get_schema("elasticsearch", self.value)
|
@@ -0,0 +1,222 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
import logging
|
17
|
+
from enum import Enum
|
18
|
+
from typing import Any
|
19
|
+
from typing import Literal
|
20
|
+
from typing import Self
|
21
|
+
from typing import TypeAlias
|
22
|
+
|
23
|
+
from pydantic import BaseModel
|
24
|
+
from pydantic import ConfigDict
|
25
|
+
from pydantic import Field
|
26
|
+
from pydantic import field_validator
|
27
|
+
from pydantic import model_validator
|
28
|
+
|
29
|
+
from nat.plugins.data_flywheel.observability.schema.schema_registry import register_schema
|
30
|
+
from nat.plugins.data_flywheel.observability.schema.sink.elasticsearch.contract_version import ContractVersion
|
31
|
+
|
32
|
+
logger = logging.getLogger(__name__)
|
33
|
+
|
34
|
+
|
35
|
+
class FinishReason(str, Enum):
|
36
|
+
"""Finish reason for chat completion responses."""
|
37
|
+
|
38
|
+
STOP = "stop"
|
39
|
+
LENGTH = "length"
|
40
|
+
TOOL_CALLS = "tool_calls"
|
41
|
+
|
42
|
+
|
43
|
+
class Function(BaseModel):
|
44
|
+
"""Function call structure used in both requests and responses."""
|
45
|
+
|
46
|
+
name: str = Field(..., description="The name of the function to call.")
|
47
|
+
arguments: dict = Field(
|
48
|
+
...,
|
49
|
+
description="The arguments to call the function with, as generated by the model in JSON format.",
|
50
|
+
)
|
51
|
+
|
52
|
+
|
53
|
+
class ToolCall(BaseModel):
|
54
|
+
"""Tool call structure used in responses."""
|
55
|
+
|
56
|
+
function: Function = Field(..., description="The function that the model called.")
|
57
|
+
type_: Literal["function"] = Field(
|
58
|
+
default="function",
|
59
|
+
description="The type of the tool. Currently, only `function` is supported.",
|
60
|
+
alias="type",
|
61
|
+
)
|
62
|
+
|
63
|
+
|
64
|
+
class AssistantMessage(BaseModel):
|
65
|
+
"""Assistant message structure used in responses."""
|
66
|
+
|
67
|
+
role: Literal["assistant", "ai"] = Field(...,
|
68
|
+
description="The role of the messages author, in this case `assistant`.")
|
69
|
+
content: str | None = Field(default=None, description="The contents of the assistant message.")
|
70
|
+
tool_calls: list[ToolCall] | None = Field(
|
71
|
+
default=None, description="The tool calls generated by the model, such as function calls.")
|
72
|
+
|
73
|
+
|
74
|
+
class SystemMessage(BaseModel):
|
75
|
+
"""System message structure used in requests."""
|
76
|
+
|
77
|
+
content: str = Field(..., description="The contents of the system message.")
|
78
|
+
role: Literal["system"] = Field(..., description="The role of the messages author, in this case `system`.")
|
79
|
+
|
80
|
+
|
81
|
+
class UserMessage(BaseModel):
|
82
|
+
"""User message structure used in requests."""
|
83
|
+
|
84
|
+
content: str = Field(..., description="The contents of the user message.")
|
85
|
+
role: Literal["user", "human"] = Field(..., description="The role of the messages author, in this case `user`.")
|
86
|
+
|
87
|
+
|
88
|
+
class ToolMessage(BaseModel):
|
89
|
+
"""Tool message structure used in responses."""
|
90
|
+
|
91
|
+
content: str = Field(..., description="The contents of the tool message.")
|
92
|
+
role: Literal["tool"] = Field(..., description="The role of the messages author, in this case `tool`.")
|
93
|
+
tool_call_id: str = Field(..., description="Tool call that this message is responding to.")
|
94
|
+
|
95
|
+
|
96
|
+
class FunctionMessage(BaseModel):
|
97
|
+
"""Function message structure used in responses."""
|
98
|
+
|
99
|
+
content: str | None = Field(default=None, description="The contents of the function message.")
|
100
|
+
role: Literal["function", "chain"] = Field(...,
|
101
|
+
description="The role of the messages author, in this case `function`.")
|
102
|
+
|
103
|
+
|
104
|
+
Message: TypeAlias = SystemMessage | UserMessage | AssistantMessage | ToolMessage | FunctionMessage
|
105
|
+
|
106
|
+
|
107
|
+
class FunctionParameters(BaseModel):
|
108
|
+
"""Function parameters structure used in responses."""
|
109
|
+
|
110
|
+
properties: dict = Field(..., description="The properties of the function parameters.")
|
111
|
+
required: list[str] = Field(..., description="The required properties of the function parameters.")
|
112
|
+
type_: Literal["object"] = Field(default="object", description="The type of the function parameters.", alias="type")
|
113
|
+
|
114
|
+
@field_validator("properties")
|
115
|
+
@classmethod
|
116
|
+
def validate_property_limit(cls, v: dict) -> dict:
|
117
|
+
"""Enforce 8-property limit for tool parameters (WAR for NIM bug)."""
|
118
|
+
if len(v) > 8:
|
119
|
+
raise ValueError(f"Tool properties cannot exceed 8 properties. Found {len(v)} properties.")
|
120
|
+
return v
|
121
|
+
|
122
|
+
|
123
|
+
class FunctionDetails(BaseModel):
|
124
|
+
"""Function details structure used in requests."""
|
125
|
+
|
126
|
+
name: str = Field(..., description="The name of the function.")
|
127
|
+
description: str = Field(..., description="The description of the function.")
|
128
|
+
parameters: FunctionParameters = Field(..., description="The parameters of the function.")
|
129
|
+
|
130
|
+
|
131
|
+
class RequestTool(BaseModel):
|
132
|
+
"""Request tool structure used in requests."""
|
133
|
+
|
134
|
+
type: Literal["function"] = Field(..., description="The type of the tool.")
|
135
|
+
function: FunctionDetails = Field(..., description="The function details.")
|
136
|
+
|
137
|
+
|
138
|
+
class Request(BaseModel):
|
139
|
+
"""Request structure used in requests."""
|
140
|
+
|
141
|
+
model_config = ConfigDict(extra="allow") # Allow extra fields
|
142
|
+
|
143
|
+
tools: list[RequestTool] | None = Field(default=None, description="The tool choice.")
|
144
|
+
messages: list[Message] | None = Field(default=None, description="The messages.")
|
145
|
+
model: str = Field(default="", description="The model to use.")
|
146
|
+
|
147
|
+
# Enhanced fields for better tracking
|
148
|
+
temperature: float | None = Field(None, description="Sampling temperature", ge=0.0, le=2.0)
|
149
|
+
|
150
|
+
max_tokens: int | None = Field(None, description="Maximum tokens in response", ge=1)
|
151
|
+
|
152
|
+
|
153
|
+
class ResponseMessage(BaseModel):
|
154
|
+
"""Response message structure used in responses."""
|
155
|
+
|
156
|
+
role: Literal["assistant"] | None = Field(default=None,
|
157
|
+
description="The role of the messages author, in this case `assistant`.")
|
158
|
+
content: str | None = Field(default=None, description="The contents of the assistant message.")
|
159
|
+
tool_calls: list[ToolCall] | None = Field(
|
160
|
+
default=None, description="The tool calls generated by the model, such as function calls.")
|
161
|
+
|
162
|
+
|
163
|
+
class ResponseChoice(BaseModel):
|
164
|
+
"""Response choice structure used in responses."""
|
165
|
+
|
166
|
+
message: ResponseMessage = Field(..., description="A chat completion message generated by the model.")
|
167
|
+
finish_reason: FinishReason | None = Field(None, description="Reason for completion finish")
|
168
|
+
index: int | None = Field(None, description="Choice index", ge=0)
|
169
|
+
|
170
|
+
|
171
|
+
class Response(BaseModel):
|
172
|
+
"""Response structure used in responses."""
|
173
|
+
|
174
|
+
model_config = ConfigDict(extra="allow") # Allow extra fields
|
175
|
+
|
176
|
+
choices: list[ResponseChoice] | None = Field(default=None, description="The choices.")
|
177
|
+
|
178
|
+
# Enhanced fields for better tracking
|
179
|
+
id: str | None = Field(None, description="Response ID")
|
180
|
+
|
181
|
+
object: str | None = Field(None, description="Object type")
|
182
|
+
|
183
|
+
created: int | None = Field(None, description="Creation timestamp")
|
184
|
+
|
185
|
+
model: str | None = Field(None, description="Model used for response")
|
186
|
+
|
187
|
+
usage: dict[str, Any] | None = Field(None, description="Token usage information")
|
188
|
+
|
189
|
+
|
190
|
+
@register_schema(name="elasticsearch", version="1.0")
|
191
|
+
@register_schema(name="elasticsearch", version="1.1")
|
192
|
+
class DFWESRecord(BaseModel):
|
193
|
+
"""Data Flywheel Elasticsearch record."""
|
194
|
+
|
195
|
+
model_config = ConfigDict(extra="forbid", validate_assignment=True)
|
196
|
+
|
197
|
+
# Contract versioning
|
198
|
+
contract_version: ContractVersion = Field(default=ContractVersion.V1_0,
|
199
|
+
description="Contract version for compatibility tracking")
|
200
|
+
|
201
|
+
# Core fields (backward compatible)
|
202
|
+
request: Request = Field(..., description="The OpenAI ChatCompletion request.")
|
203
|
+
response: Response = Field(..., description="The OpenAI ChatCompletion response.")
|
204
|
+
client_id: str = Field(..., description="Identifier of the application or deployment that generated traffic.")
|
205
|
+
workload_id: str = Field(..., description="Stable identifier for the logical task / route / agent node.")
|
206
|
+
timestamp: int = Field(..., description="The timestamp of the payload in seconds since epoch.")
|
207
|
+
|
208
|
+
# Enhanced tracking fields
|
209
|
+
error_details: str | None = Field(None, description="Error details if processing failed", max_length=5000)
|
210
|
+
|
211
|
+
@model_validator(mode="after")
|
212
|
+
def validate_data_consistency(self) -> Self:
|
213
|
+
# Validate tool calling format if tools are
|
214
|
+
request_tools = getattr(self.request, "tools", None)
|
215
|
+
if request_tools:
|
216
|
+
# Check if response has tool calls
|
217
|
+
response_choices = getattr(self.response, "choices", [])
|
218
|
+
has_tool_calls = any(choice.message and choice.message.tool_calls for choice in response_choices)
|
219
|
+
if not has_tool_calls:
|
220
|
+
logger.warning("Request has tools but response has no tool calls")
|
221
|
+
|
222
|
+
return self
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
from typing import Any
|
17
|
+
|
18
|
+
from pydantic import BaseModel
|
19
|
+
from pydantic import Field
|
20
|
+
from pydantic import TypeAdapter
|
21
|
+
from pydantic import field_validator
|
22
|
+
from pydantic import model_validator
|
23
|
+
|
24
|
+
from nat.data_models.span import Span
|
25
|
+
|
26
|
+
|
27
|
+
class TraceContainer(BaseModel):
|
28
|
+
"""Base TraceContainer model with dynamic union support.
|
29
|
+
|
30
|
+
The source field uses a dynamic union that automatically includes
|
31
|
+
all types registered via TraceAdapterRegistry.register_adapter().
|
32
|
+
"""
|
33
|
+
source: Any = Field(..., description="The matched source of the trace")
|
34
|
+
span: Span = Field(..., description="The span of the trace")
|
35
|
+
|
36
|
+
@field_validator('source', mode='before')
|
37
|
+
@classmethod
|
38
|
+
def validate_source_via_union(cls, v):
|
39
|
+
"""Validate source field using dynamic union."""
|
40
|
+
if isinstance(v, dict):
|
41
|
+
# Use the dynamic union to validate and select the correct schema
|
42
|
+
try:
|
43
|
+
from nat.plugins.data_flywheel.observability.processor.trace_conversion.trace_adapter_registry import (
|
44
|
+
TraceAdapterRegistry, # yapf: disable
|
45
|
+
)
|
46
|
+
|
47
|
+
current_union = TraceAdapterRegistry.get_current_union()
|
48
|
+
if current_union != Any: # Only validate if union is available
|
49
|
+
adapter = TypeAdapter(current_union)
|
50
|
+
return adapter.validate_python(v)
|
51
|
+
except ImportError:
|
52
|
+
# Registry not available - return original value
|
53
|
+
pass
|
54
|
+
except Exception as e:
|
55
|
+
# Union validation failed - this should trigger fail-fast in get_trace_source
|
56
|
+
raise ValueError(
|
57
|
+
f"Union validation failed: none of the registered schemas match this data structure. {e}") from e
|
58
|
+
return v
|
59
|
+
|
60
|
+
@model_validator(mode='before')
|
61
|
+
@classmethod
|
62
|
+
def ensure_union_built(cls, data):
|
63
|
+
"""Ensure union is built before validation."""
|
64
|
+
# Trigger union building on first instantiation if needed
|
65
|
+
try:
|
66
|
+
from nat.plugins.data_flywheel.observability.processor.trace_conversion.trace_adapter_registry import (
|
67
|
+
TraceAdapterRegistry, # yapf: disable
|
68
|
+
)
|
69
|
+
TraceAdapterRegistry.get_current_union() # This ensures union is built and model updated
|
70
|
+
except ImportError:
|
71
|
+
pass # Registry not available
|
72
|
+
return data
|
73
|
+
|
74
|
+
@classmethod
|
75
|
+
def __init_subclass__(cls, **kwargs):
|
76
|
+
"""Update source annotation with current dynamic union when subclassed."""
|
77
|
+
super().__init_subclass__(**kwargs)
|
78
|
+
# This ensures subclasses get the latest union
|
79
|
+
cls.model_rebuild()
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
from pydantic import BaseModel
|
17
|
+
from pydantic import Field
|
18
|
+
|
19
|
+
|
20
|
+
class TraceSourceBase(BaseModel):
|
21
|
+
"""Base class for trace sources with generic framework and provider types."""
|
22
|
+
client_id: str = Field(..., description="The client ID of the trace source")
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
import json
|
17
|
+
from typing import Any
|
18
|
+
|
19
|
+
# Type alias for all possible JSON values
|
20
|
+
JSONValue = dict[str, Any] | list[Any] | str | int | float | bool | None
|
21
|
+
|
22
|
+
|
23
|
+
def deserialize_span_attribute(value: dict[str, Any] | list[Any] | str) -> JSONValue:
|
24
|
+
"""Deserialize a string input value to any valid JSON value.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
value (str): The input value to deserialize
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
JSONValue: The deserialized input value, which can be a dictionary, list,
|
31
|
+
string, number (int/float), boolean, or None
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
ValueError: If parsing fails
|
35
|
+
"""
|
36
|
+
try:
|
37
|
+
if isinstance(value, (dict, list)):
|
38
|
+
return value
|
39
|
+
deserialized_attribute = json.loads(value)
|
40
|
+
return deserialized_attribute
|
41
|
+
except (json.JSONDecodeError, TypeError) as e:
|
42
|
+
raise ValueError(f"Failed to parse input_value: {value}, error: {e}") from e
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: nvidia-nat-data-flywheel
|
3
|
+
Version: 1.3.0a20250828
|
4
|
+
Summary: Subpackage for NVIDIA Data Flywheel Blueprint integration in NeMo Agent Toolkit
|
5
|
+
Keywords: ai,observability,nemo,data flywheel
|
6
|
+
Classifier: Programming Language :: Python
|
7
|
+
Requires-Python: <3.13,>=3.11
|
8
|
+
Description-Content-Type: text/markdown
|
9
|
+
Requires-Dist: elasticsearch~=8.1
|
10
|
+
Requires-Dist: nvidia-nat==v1.3.0a20250828
|
11
|
+
|
12
|
+
<!--
|
13
|
+
SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
14
|
+
SPDX-License-Identifier: Apache-2.0
|
15
|
+
|
16
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
17
|
+
you may not use this file except in compliance with the License.
|
18
|
+
You may obtain a copy of the License at
|
19
|
+
|
20
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
21
|
+
|
22
|
+
Unless required by applicable law or agreed to in writing, software
|
23
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
24
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
25
|
+
See the License for the specific language governing permissions and
|
26
|
+
limitations under the License.
|
27
|
+
-->
|
28
|
+
|
29
|
+

|
30
|
+
|
31
|
+
# NVIDIA Agent Toolkit Subpackage
|
32
|
+
This is a subpackage for NVIDIA Data Flywheel Blueprint integration for continuous model improvement.
|
33
|
+
|
34
|
+
For more information about the NVIDIA NeMo Agent toolkit, please visit the [NeMo Agent toolkit GitHub Repo](https://github.com/NVIDIA/NeMo-Agent-Toolkit).
|
@@ -0,0 +1,38 @@
|
|
1
|
+
nat/meta/pypi.md,sha256=kqTY91XBsWVIQNt63BVOjEj02f8YYNG0WVoFn7HfWsc,1137
|
2
|
+
nat/plugins/data_flywheel/observability/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
3
|
+
nat/plugins/data_flywheel/observability/register.py,sha256=2D1UvjTtz3fwhqadXbV-flz4EsBBrTHpr8vCPMgQTiI,3310
|
4
|
+
nat/plugins/data_flywheel/observability/exporter/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
5
|
+
nat/plugins/data_flywheel/observability/exporter/dfw_elasticsearch_exporter.py,sha256=CREldRXPJAs4LVFipHPQks8qXX5V--cwVAyACRHNrCM,3722
|
6
|
+
nat/plugins/data_flywheel/observability/exporter/dfw_exporter.py,sha256=ZCxvB0HgSpnKN8lwYe6AfoPbMe7Un9T9C2FaVRFuGAQ,4336
|
7
|
+
nat/plugins/data_flywheel/observability/mixin/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
8
|
+
nat/plugins/data_flywheel/observability/mixin/elasticsearch_mixin.py,sha256=Taf4OypW6goBLHQ7TTzVqBCpYJdSFt9jQHQOygXO9dQ,3058
|
9
|
+
nat/plugins/data_flywheel/observability/processor/__init__.py,sha256=Lj0nT8rGFxd3ITrrW5ZMRYsVwkwtTWzmJYGRsW-r_VA,1072
|
10
|
+
nat/plugins/data_flywheel/observability/processor/dfw_record_processor.py,sha256=aRRhEokFKNNlWoeQizBbFvjaY2CgqEN2CI5wNJjfins,3074
|
11
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/__init__.py,sha256=1ZME9GRzJCti2ExzNHRqYK9fhhnRAkrep7Db4AH-Sbg,1159
|
12
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/span_extractor.py,sha256=nX2uKR0DUMaxC5jpeZc741cJR1PiakQPMGDrrwPbjJY,2750
|
13
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/span_to_dfw_record.py,sha256=bqS4BJ0iJ-v_Mh-jnSOHq_Dh4eKyMmnpDS0T4kv8rlQ,4929
|
14
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/trace_adapter_registry.py,sha256=qrNdSuYjqbTTtbu7mN3cPfBs7r5sn_MpBUPw2RWbabM,9911
|
15
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
16
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/register.py,sha256=Xm05kMVRJ8h65QCKTh3UsmIZ8dOMZhKHBDjklGZ9m_E,1061
|
17
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/elasticsearch/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
18
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/elasticsearch/nim_converter.py,sha256=tch_uZZGxhyyXEe3B2U3m3pL3zUL5NffsOb4yUfGDzk,1753
|
19
|
+
nat/plugins/data_flywheel/observability/processor/trace_conversion/adapter/elasticsearch/openai_converter.py,sha256=Ml9WxVXBCO37FLnHMQHo8KTB2713MM2zms9eEAXPZXo,14757
|
20
|
+
nat/plugins/data_flywheel/observability/schema/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
21
|
+
nat/plugins/data_flywheel/observability/schema/register.py,sha256=P7WfvItuvYn22rYSPrZgydZPe-a9JkfUN7UUyiqsMRo,929
|
22
|
+
nat/plugins/data_flywheel/observability/schema/schema_registry.py,sha256=tYwkFDhCJauNWlNATd2YpVgydp6HWXZCAZyN0f6ECbg,4971
|
23
|
+
nat/plugins/data_flywheel/observability/schema/trace_container.py,sha256=bD9hYjFQzEMw0BS1Og4y_-437E7N4Y_7tKjCzVw3TGA,3339
|
24
|
+
nat/plugins/data_flywheel/observability/schema/trace_source_base.py,sha256=vwIzRqsPPLpBAjVY9AmkxgK0jdds-ZCz9TcYmCIqwrw,938
|
25
|
+
nat/plugins/data_flywheel/observability/schema/provider/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
|
26
|
+
nat/plugins/data_flywheel/observability/schema/provider/nim_trace_source.py,sha256=SzP5yoZFQR2F5ueTfEcObrbDjk7_m0Kjd2ny9Ncwqho,901
|
27
|
+
nat/plugins/data_flywheel/observability/schema/provider/openai_message.py,sha256=qQRwSNBsIJgm2dj9WIQhwBGmn-x7NreSBhFYFAeagnA,1526
|
28
|
+
nat/plugins/data_flywheel/observability/schema/provider/openai_trace_source.py,sha256=2le9cRyeeR8Se9rMwtlS3uuZjXKIYhrajQhvM0ImyFs,3523
|
29
|
+
nat/plugins/data_flywheel/observability/schema/sink/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
|
30
|
+
nat/plugins/data_flywheel/observability/schema/sink/elasticsearch/__init__.py,sha256=zij8aeeVtQqZODJwrJ9xg-CY61yythnUMeJzbUJfjO8,899
|
31
|
+
nat/plugins/data_flywheel/observability/schema/sink/elasticsearch/contract_version.py,sha256=eAxkIZG2uYl0e8QNzcLiDhqzYbaibx0XBV6jsfNm5UM,1153
|
32
|
+
nat/plugins/data_flywheel/observability/schema/sink/elasticsearch/dfw_es_record.py,sha256=104nkmI2ZbiiP_qrdVUZkn4i4N_OBYCyUM-q-a4Orjc,9176
|
33
|
+
nat/plugins/data_flywheel/observability/utils/deserialize.py,sha256=WTRaxnNy034X1_qaHVDI0CWgvrZ7F1Oq0QnFL9_STYs,1569
|
34
|
+
nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/METADATA,sha256=fqGIyXXwFHTdPIItHLZf7TY5HYAHHERK6JkioDIKkj0,1540
|
35
|
+
nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
36
|
+
nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/entry_points.txt,sha256=ElemL8x3DrrcLB-NsVsrUWKbHMD6rapsvs8qoIGVWrY,295
|
37
|
+
nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/top_level.txt,sha256=8-CJ2cP6-f0ZReXe5Hzqp-5pvzzHz-5Ds5H2bGqh1-U,4
|
38
|
+
nvidia_nat_data_flywheel-1.3.0a20250828.dist-info/RECORD,,
|
@@ -0,0 +1,4 @@
|
|
1
|
+
[nat.components]
|
2
|
+
nat_data_flywheel_adapter = nat.plugins.data_flywheel.observability.processor.trace_conversion.adapter.register
|
3
|
+
nat_data_flywheel_observability = nat.plugins.data_flywheel.observability.register
|
4
|
+
nat_data_flywheel_schema = nat.plugins.data_flywheel.observability.schema.register
|
@@ -0,0 +1 @@
|
|
1
|
+
nat
|