data-designer 0.3.8rc2__py3-none-any.whl → 0.4.0rc1__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.
Files changed (166) hide show
  1. data_designer/cli/commands/__init__.py +1 -1
  2. data_designer/interface/__init__.py +21 -1
  3. data_designer/{_version.py → interface/_version.py} +2 -2
  4. data_designer/interface/data_designer.py +1 -7
  5. {data_designer-0.3.8rc2.dist-info → data_designer-0.4.0rc1.dist-info}/METADATA +10 -42
  6. data_designer-0.4.0rc1.dist-info/RECORD +39 -0
  7. data_designer/__init__.py +0 -17
  8. data_designer/config/__init__.py +0 -2
  9. data_designer/config/analysis/__init__.py +0 -2
  10. data_designer/config/analysis/column_profilers.py +0 -159
  11. data_designer/config/analysis/column_statistics.py +0 -421
  12. data_designer/config/analysis/dataset_profiler.py +0 -84
  13. data_designer/config/analysis/utils/errors.py +0 -10
  14. data_designer/config/analysis/utils/reporting.py +0 -192
  15. data_designer/config/base.py +0 -69
  16. data_designer/config/column_configs.py +0 -470
  17. data_designer/config/column_types.py +0 -141
  18. data_designer/config/config_builder.py +0 -595
  19. data_designer/config/data_designer_config.py +0 -40
  20. data_designer/config/dataset_builders.py +0 -13
  21. data_designer/config/dataset_metadata.py +0 -18
  22. data_designer/config/default_model_settings.py +0 -129
  23. data_designer/config/errors.py +0 -24
  24. data_designer/config/exports.py +0 -145
  25. data_designer/config/interface.py +0 -55
  26. data_designer/config/models.py +0 -455
  27. data_designer/config/preview_results.py +0 -41
  28. data_designer/config/processors.py +0 -148
  29. data_designer/config/run_config.py +0 -51
  30. data_designer/config/sampler_constraints.py +0 -52
  31. data_designer/config/sampler_params.py +0 -639
  32. data_designer/config/seed.py +0 -116
  33. data_designer/config/seed_source.py +0 -84
  34. data_designer/config/seed_source_types.py +0 -19
  35. data_designer/config/utils/code_lang.py +0 -82
  36. data_designer/config/utils/constants.py +0 -363
  37. data_designer/config/utils/errors.py +0 -21
  38. data_designer/config/utils/info.py +0 -94
  39. data_designer/config/utils/io_helpers.py +0 -258
  40. data_designer/config/utils/misc.py +0 -78
  41. data_designer/config/utils/numerical_helpers.py +0 -30
  42. data_designer/config/utils/type_helpers.py +0 -106
  43. data_designer/config/utils/visualization.py +0 -482
  44. data_designer/config/validator_params.py +0 -94
  45. data_designer/engine/__init__.py +0 -2
  46. data_designer/engine/analysis/column_profilers/base.py +0 -49
  47. data_designer/engine/analysis/column_profilers/judge_score_profiler.py +0 -153
  48. data_designer/engine/analysis/column_profilers/registry.py +0 -22
  49. data_designer/engine/analysis/column_statistics.py +0 -145
  50. data_designer/engine/analysis/dataset_profiler.py +0 -149
  51. data_designer/engine/analysis/errors.py +0 -9
  52. data_designer/engine/analysis/utils/column_statistics_calculations.py +0 -234
  53. data_designer/engine/analysis/utils/judge_score_processing.py +0 -132
  54. data_designer/engine/column_generators/__init__.py +0 -2
  55. data_designer/engine/column_generators/generators/__init__.py +0 -2
  56. data_designer/engine/column_generators/generators/base.py +0 -122
  57. data_designer/engine/column_generators/generators/embedding.py +0 -35
  58. data_designer/engine/column_generators/generators/expression.py +0 -55
  59. data_designer/engine/column_generators/generators/llm_completion.py +0 -113
  60. data_designer/engine/column_generators/generators/samplers.py +0 -69
  61. data_designer/engine/column_generators/generators/seed_dataset.py +0 -144
  62. data_designer/engine/column_generators/generators/validation.py +0 -140
  63. data_designer/engine/column_generators/registry.py +0 -60
  64. data_designer/engine/column_generators/utils/errors.py +0 -15
  65. data_designer/engine/column_generators/utils/generator_classification.py +0 -43
  66. data_designer/engine/column_generators/utils/judge_score_factory.py +0 -58
  67. data_designer/engine/column_generators/utils/prompt_renderer.py +0 -100
  68. data_designer/engine/compiler.py +0 -97
  69. data_designer/engine/configurable_task.py +0 -71
  70. data_designer/engine/dataset_builders/artifact_storage.py +0 -283
  71. data_designer/engine/dataset_builders/column_wise_builder.py +0 -335
  72. data_designer/engine/dataset_builders/errors.py +0 -15
  73. data_designer/engine/dataset_builders/multi_column_configs.py +0 -46
  74. data_designer/engine/dataset_builders/utils/__init__.py +0 -2
  75. data_designer/engine/dataset_builders/utils/concurrency.py +0 -212
  76. data_designer/engine/dataset_builders/utils/config_compiler.py +0 -62
  77. data_designer/engine/dataset_builders/utils/dag.py +0 -62
  78. data_designer/engine/dataset_builders/utils/dataset_batch_manager.py +0 -200
  79. data_designer/engine/dataset_builders/utils/errors.py +0 -15
  80. data_designer/engine/errors.py +0 -51
  81. data_designer/engine/model_provider.py +0 -77
  82. data_designer/engine/models/__init__.py +0 -2
  83. data_designer/engine/models/errors.py +0 -300
  84. data_designer/engine/models/facade.py +0 -287
  85. data_designer/engine/models/factory.py +0 -42
  86. data_designer/engine/models/litellm_overrides.py +0 -179
  87. data_designer/engine/models/parsers/__init__.py +0 -2
  88. data_designer/engine/models/parsers/errors.py +0 -34
  89. data_designer/engine/models/parsers/parser.py +0 -235
  90. data_designer/engine/models/parsers/postprocessors.py +0 -93
  91. data_designer/engine/models/parsers/tag_parsers.py +0 -62
  92. data_designer/engine/models/parsers/types.py +0 -84
  93. data_designer/engine/models/recipes/base.py +0 -81
  94. data_designer/engine/models/recipes/response_recipes.py +0 -293
  95. data_designer/engine/models/registry.py +0 -146
  96. data_designer/engine/models/telemetry.py +0 -359
  97. data_designer/engine/models/usage.py +0 -73
  98. data_designer/engine/models/utils.py +0 -38
  99. data_designer/engine/processing/ginja/__init__.py +0 -2
  100. data_designer/engine/processing/ginja/ast.py +0 -65
  101. data_designer/engine/processing/ginja/environment.py +0 -463
  102. data_designer/engine/processing/ginja/exceptions.py +0 -56
  103. data_designer/engine/processing/ginja/record.py +0 -32
  104. data_designer/engine/processing/gsonschema/__init__.py +0 -2
  105. data_designer/engine/processing/gsonschema/exceptions.py +0 -15
  106. data_designer/engine/processing/gsonschema/schema_transformers.py +0 -83
  107. data_designer/engine/processing/gsonschema/types.py +0 -10
  108. data_designer/engine/processing/gsonschema/validators.py +0 -202
  109. data_designer/engine/processing/processors/base.py +0 -13
  110. data_designer/engine/processing/processors/drop_columns.py +0 -42
  111. data_designer/engine/processing/processors/registry.py +0 -25
  112. data_designer/engine/processing/processors/schema_transform.py +0 -49
  113. data_designer/engine/processing/utils.py +0 -169
  114. data_designer/engine/registry/base.py +0 -99
  115. data_designer/engine/registry/data_designer_registry.py +0 -39
  116. data_designer/engine/registry/errors.py +0 -12
  117. data_designer/engine/resources/managed_dataset_generator.py +0 -39
  118. data_designer/engine/resources/managed_dataset_repository.py +0 -197
  119. data_designer/engine/resources/managed_storage.py +0 -65
  120. data_designer/engine/resources/resource_provider.py +0 -77
  121. data_designer/engine/resources/seed_reader.py +0 -154
  122. data_designer/engine/sampling_gen/column.py +0 -91
  123. data_designer/engine/sampling_gen/constraints.py +0 -100
  124. data_designer/engine/sampling_gen/data_sources/base.py +0 -217
  125. data_designer/engine/sampling_gen/data_sources/errors.py +0 -12
  126. data_designer/engine/sampling_gen/data_sources/sources.py +0 -347
  127. data_designer/engine/sampling_gen/entities/__init__.py +0 -2
  128. data_designer/engine/sampling_gen/entities/assets/zip_area_code_map.parquet +0 -0
  129. data_designer/engine/sampling_gen/entities/dataset_based_person_fields.py +0 -86
  130. data_designer/engine/sampling_gen/entities/email_address_utils.py +0 -171
  131. data_designer/engine/sampling_gen/entities/errors.py +0 -10
  132. data_designer/engine/sampling_gen/entities/national_id_utils.py +0 -102
  133. data_designer/engine/sampling_gen/entities/person.py +0 -144
  134. data_designer/engine/sampling_gen/entities/phone_number.py +0 -128
  135. data_designer/engine/sampling_gen/errors.py +0 -26
  136. data_designer/engine/sampling_gen/generator.py +0 -122
  137. data_designer/engine/sampling_gen/jinja_utils.py +0 -64
  138. data_designer/engine/sampling_gen/people_gen.py +0 -199
  139. data_designer/engine/sampling_gen/person_constants.py +0 -56
  140. data_designer/engine/sampling_gen/schema.py +0 -147
  141. data_designer/engine/sampling_gen/schema_builder.py +0 -61
  142. data_designer/engine/sampling_gen/utils.py +0 -46
  143. data_designer/engine/secret_resolver.py +0 -82
  144. data_designer/engine/validation.py +0 -367
  145. data_designer/engine/validators/__init__.py +0 -19
  146. data_designer/engine/validators/base.py +0 -38
  147. data_designer/engine/validators/local_callable.py +0 -39
  148. data_designer/engine/validators/python.py +0 -254
  149. data_designer/engine/validators/remote.py +0 -89
  150. data_designer/engine/validators/sql.py +0 -65
  151. data_designer/errors.py +0 -7
  152. data_designer/essentials/__init__.py +0 -33
  153. data_designer/lazy_heavy_imports.py +0 -54
  154. data_designer/logging.py +0 -163
  155. data_designer/plugin_manager.py +0 -78
  156. data_designer/plugins/__init__.py +0 -8
  157. data_designer/plugins/errors.py +0 -15
  158. data_designer/plugins/plugin.py +0 -141
  159. data_designer/plugins/registry.py +0 -88
  160. data_designer/plugins/testing/__init__.py +0 -10
  161. data_designer/plugins/testing/stubs.py +0 -116
  162. data_designer/plugins/testing/utils.py +0 -20
  163. data_designer-0.3.8rc2.dist-info/RECORD +0 -196
  164. data_designer-0.3.8rc2.dist-info/licenses/LICENSE +0 -201
  165. {data_designer-0.3.8rc2.dist-info → data_designer-0.4.0rc1.dist-info}/WHEEL +0 -0
  166. {data_designer-0.3.8rc2.dist-info → data_designer-0.4.0rc1.dist-info}/entry_points.txt +0 -0
@@ -1,359 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
-
4
- """
5
- Telemetry handler for NeMo products.
6
-
7
- Environment variables:
8
- - NEMO_TELEMETRY_ENABLED: Whether telemetry is enabled.
9
- - NEMO_DEPLOYMENT_TYPE: The deployment type the event came from.
10
- - NEMO_TELEMETRY_ENDPOINT: The endpoint to send the telemetry events to.
11
- """
12
-
13
- from __future__ import annotations
14
-
15
- import asyncio
16
- import os
17
- import platform
18
- from dataclasses import dataclass
19
- from datetime import datetime, timezone
20
- from enum import Enum
21
- from typing import TYPE_CHECKING, Any, ClassVar
22
-
23
- from pydantic import BaseModel, Field
24
-
25
- from data_designer.lazy_heavy_imports import httpx
26
-
27
- if TYPE_CHECKING:
28
- import httpx
29
-
30
- TELEMETRY_ENABLED = os.getenv("NEMO_TELEMETRY_ENABLED", "true").lower() in ("1", "true", "yes")
31
- CLIENT_ID = "184482118588404"
32
- NEMO_TELEMETRY_VERSION = "nemo-telemetry/1.0"
33
- MAX_RETRIES = 3
34
- NEMO_TELEMETRY_ENDPOINT = os.getenv(
35
- "NEMO_TELEMETRY_ENDPOINT", "https://events.telemetry.data.nvidia.com/v1.1/events/json"
36
- ).lower()
37
- CPU_ARCHITECTURE = platform.uname().machine
38
-
39
-
40
- class NemoSourceEnum(str, Enum):
41
- INFERENCE = "inference"
42
- AUDITOR = "auditor"
43
- DATADESIGNER = "datadesigner"
44
- EVALUATOR = "evaluator"
45
- GUARDRAILS = "guardrails"
46
- UNDEFINED = "undefined"
47
-
48
-
49
- class DeploymentTypeEnum(str, Enum):
50
- LIBRARY = "library"
51
- API = "api"
52
- UNDEFINED = "undefined"
53
-
54
-
55
- _deployment_type_raw = os.getenv("NEMO_DEPLOYMENT_TYPE", "library").lower()
56
- try:
57
- DEPLOYMENT_TYPE = DeploymentTypeEnum(_deployment_type_raw)
58
- except ValueError:
59
- valid_values = [e.value for e in DeploymentTypeEnum]
60
- raise ValueError(
61
- f"Invalid NEMO_DEPLOYMENT_TYPE: {_deployment_type_raw!r}. Must be one of: {valid_values}"
62
- ) from None
63
-
64
-
65
- class TaskStatusEnum(str, Enum):
66
- SUCCESS = "success"
67
- FAILURE = "failure"
68
- UNDEFINED = "undefined"
69
-
70
-
71
- class TelemetryEvent(BaseModel):
72
- _event_name: ClassVar[str] # Subclasses must define this
73
- _schema_version: ClassVar[str] = "1.3"
74
-
75
- def __init_subclass__(cls, **kwargs: Any) -> None:
76
- super().__init_subclass__(**kwargs)
77
- if "_event_name" not in cls.__dict__:
78
- raise TypeError(f"{cls.__name__} must define '_event_name' class variable")
79
-
80
-
81
- class InferenceEvent(TelemetryEvent):
82
- _event_name: ClassVar[str] = "inference_event"
83
-
84
- nemo_source: NemoSourceEnum = Field(
85
- ...,
86
- alias="nemoSource",
87
- description="The NeMo product that created the event (i.e. data-designer).",
88
- )
89
- task: str = Field(
90
- ...,
91
- description="The type of task that was performed that generated the inference event (i.e. preview-job, batch-job).",
92
- )
93
- task_status: TaskStatusEnum = Field(
94
- ...,
95
- alias="taskStatus",
96
- description="The status of the task.",
97
- )
98
- deployment_type: DeploymentTypeEnum = Field(
99
- default=DEPLOYMENT_TYPE,
100
- alias="deploymentType",
101
- description="The deployment type the event came from.",
102
- )
103
- model: str = Field(
104
- ...,
105
- description="The name of the model that was used.",
106
- )
107
- model_group: str = Field(
108
- default="undefined",
109
- alias="modelGroup",
110
- description="An optional identifier to group models together.",
111
- )
112
- input_bytes: int = Field(
113
- default=-1,
114
- alias="inputBytes",
115
- description="Number of bytes provided as input to the model. -1 if not available.",
116
- ge=-9223372036854775808,
117
- le=9223372036854775807,
118
- )
119
- input_tokens: int = Field(
120
- default=-1,
121
- alias="inputTokens",
122
- description="Number of tokens provided as input to the model. -1 if not available.",
123
- ge=-9223372036854775808,
124
- le=9223372036854775807,
125
- )
126
- output_bytes: int = Field(
127
- default=-1,
128
- alias="outputBytes",
129
- description="Number of bytes returned by the model. -1 if not available.",
130
- ge=-9223372036854775808,
131
- le=9223372036854775807,
132
- )
133
- output_tokens: int = Field(
134
- default=-1,
135
- alias="outputTokens",
136
- description="Number of tokens returned by the model. -1 if not available.",
137
- ge=-9223372036854775808,
138
- le=9223372036854775807,
139
- )
140
-
141
- model_config = {"populate_by_name": True}
142
-
143
-
144
- @dataclass
145
- class QueuedEvent:
146
- event: TelemetryEvent
147
- timestamp: datetime
148
- retry_count: int = 0
149
-
150
-
151
- def _get_iso_timestamp(dt: datetime | None = None) -> str:
152
- if dt is None:
153
- dt = datetime.now(timezone.utc)
154
- return dt.strftime("%Y-%m-%dT%H:%M:%S.") + f"{dt.microsecond // 1000:03d}Z"
155
-
156
-
157
- def build_payload(
158
- events: list[QueuedEvent], *, source_client_version: str, session_id: str = "undefined"
159
- ) -> dict[str, Any]:
160
- return {
161
- "browserType": "undefined", # do not change
162
- "clientId": CLIENT_ID,
163
- "clientType": "Native", # do not change
164
- "clientVariant": "Release", # do not change
165
- "clientVer": source_client_version,
166
- "cpuArchitecture": CPU_ARCHITECTURE,
167
- "deviceGdprBehOptIn": "None", # do not change
168
- "deviceGdprFuncOptIn": "None", # do not change
169
- "deviceGdprTechOptIn": "None", # do not change
170
- "deviceId": "undefined", # do not change
171
- "deviceMake": "undefined", # do not change
172
- "deviceModel": "undefined", # do not change
173
- "deviceOS": "undefined", # do not change
174
- "deviceOSVersion": "undefined", # do not change
175
- "deviceType": "undefined", # do not change
176
- "eventProtocol": "1.6", # do not change
177
- "eventSchemaVer": events[0].event._schema_version,
178
- "eventSysVer": NEMO_TELEMETRY_VERSION,
179
- "externalUserId": "undefined", # do not change
180
- "gdprBehOptIn": "None", # do not change
181
- "gdprFuncOptIn": "None", # do not change
182
- "gdprTechOptIn": "None", # do not change
183
- "idpId": "undefined", # do not change
184
- "integrationId": "undefined", # do not change
185
- "productName": "undefined", # do not change
186
- "productVersion": "undefined", # do not change
187
- "sentTs": _get_iso_timestamp(),
188
- "sessionId": session_id,
189
- "userId": "undefined", # do not change
190
- "events": [
191
- {
192
- "ts": _get_iso_timestamp(queued.timestamp),
193
- "parameters": queued.event.model_dump(by_alias=True),
194
- "name": queued.event._event_name,
195
- }
196
- for queued in events
197
- ],
198
- }
199
-
200
-
201
- class TelemetryHandler:
202
- """
203
- Handles telemetry event batching, flushing, and retry logic for NeMo products.
204
-
205
- Args:
206
- flush_interval_seconds (float): The interval in seconds to flush the events.
207
- max_queue_size (int): The maximum number of events to queue before flushing.
208
- max_retries (int): The maximum number of times to retry sending an event.
209
- source_client_version (str): The version of the source client. This should be the version of
210
- the actual NeMo product that is sending the events, typically the same as the version of
211
- a PyPi package that a user would install.
212
- session_id (str): An optional session ID to associate with the events.
213
- This should be a unique identifier for the session, such as a UUID.
214
- It is used to group events together.
215
- """
216
-
217
- def __init__(
218
- self,
219
- flush_interval_seconds: float = 120.0,
220
- max_queue_size: int = 50,
221
- max_retries: int = MAX_RETRIES,
222
- source_client_version: str = "undefined",
223
- session_id: str = "undefined",
224
- ):
225
- self._flush_interval = flush_interval_seconds
226
- self._max_queue_size = max_queue_size
227
- self._max_retries = max_retries
228
- self._events: list[QueuedEvent] = []
229
- self._dlq: list[QueuedEvent] = [] # Dead letter queue for retry
230
- self._flush_signal = asyncio.Event()
231
- self._timer_task: asyncio.Task | None = None
232
- self._running = False
233
- self._source_client_version = source_client_version
234
- self._session_id = session_id
235
-
236
- async def astart(self) -> None:
237
- if self._running:
238
- return
239
- self._running = True
240
- self._timer_task = asyncio.create_task(self._timer_loop())
241
-
242
- async def astop(self) -> None:
243
- self._running = False
244
- self._flush_signal.set()
245
- if self._timer_task:
246
- self._timer_task.cancel()
247
- try:
248
- await self._timer_task
249
- except asyncio.CancelledError:
250
- pass
251
- self._timer_task = None
252
- await self._flush_events()
253
-
254
- async def aflush(self) -> None:
255
- self._flush_signal.set()
256
-
257
- def start(self) -> None:
258
- self._run_sync(self.astart())
259
-
260
- def stop(self) -> None:
261
- self._run_sync(self.astop())
262
-
263
- def flush(self) -> None:
264
- self._flush_signal.set()
265
-
266
- def enqueue(self, event: TelemetryEvent) -> None:
267
- if not TELEMETRY_ENABLED:
268
- return
269
- if not isinstance(event, TelemetryEvent):
270
- # Silently fail as we prioritize not disrupting upstream call sites and telemetry is best effort
271
- return
272
- queued = QueuedEvent(event=event, timestamp=datetime.now(timezone.utc))
273
- self._events.append(queued)
274
- if len(self._events) >= self._max_queue_size:
275
- self._flush_signal.set()
276
-
277
- def _run_sync(self, coro: Any) -> Any:
278
- try:
279
- loop = asyncio.get_running_loop()
280
- except RuntimeError:
281
- loop = None
282
-
283
- if loop and loop.is_running():
284
- import concurrent.futures
285
-
286
- with concurrent.futures.ThreadPoolExecutor() as pool:
287
- future = pool.submit(asyncio.run, coro)
288
- return future.result()
289
- else:
290
- return asyncio.run(coro)
291
-
292
- def __enter__(self) -> TelemetryHandler:
293
- self.start()
294
- return self
295
-
296
- def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
297
- self.stop()
298
-
299
- async def __aenter__(self) -> TelemetryHandler:
300
- await self.astart()
301
- return self
302
-
303
- async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
304
- await self.astop()
305
-
306
- async def _timer_loop(self) -> None:
307
- while self._running:
308
- try:
309
- await asyncio.wait_for(
310
- self._flush_signal.wait(),
311
- timeout=self._flush_interval,
312
- )
313
- except asyncio.TimeoutError:
314
- pass
315
- self._flush_signal.clear()
316
- await self._flush_events()
317
-
318
- async def _flush_events(self) -> None:
319
- dlq_events, self._dlq = self._dlq, []
320
- new_events, self._events = self._events, []
321
- events_to_send = dlq_events + new_events
322
- if events_to_send:
323
- await self._send_events(events_to_send)
324
-
325
- async def _send_events(self, events: list[QueuedEvent]) -> None:
326
- async with httpx.AsyncClient() as client:
327
- await self._send_events_with_client(client, events)
328
-
329
- async def _send_events_with_client(self, client: httpx.AsyncClient, events: list[QueuedEvent]) -> None:
330
- if not events:
331
- return
332
-
333
- payload = build_payload(events, source_client_version=self._source_client_version, session_id=self._session_id)
334
- try:
335
- response = await client.post(NEMO_TELEMETRY_ENDPOINT, json=payload)
336
- # 2xx, 400, 422 are all considered complete (no retry)
337
- # 400/422 indicate bad payload which retrying won't fix
338
- if response.status_code in (400, 422) or response.is_success:
339
- return
340
- # 413 (payload too large) - split and retry
341
- if response.status_code == 413:
342
- if len(events) == 1:
343
- # Can't split further, drop the event
344
- return
345
- mid = len(events) // 2
346
- await self._send_events_with_client(client, events[:mid])
347
- await self._send_events_with_client(client, events[mid:])
348
- return
349
- if response.status_code == 408 or response.status_code >= 500:
350
- self._add_to_dlq(events)
351
- except httpx.HTTPError:
352
- self._add_to_dlq(events)
353
-
354
- def _add_to_dlq(self, events: list[QueuedEvent]) -> None:
355
- for queued in events:
356
- queued.retry_count += 1
357
- if queued.retry_count > self._max_retries:
358
- continue
359
- self._dlq.append(queued)
@@ -1,73 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
-
4
- from __future__ import annotations
5
-
6
- import logging
7
-
8
- from pydantic import BaseModel, computed_field
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- class TokenUsageStats(BaseModel):
14
- input_tokens: int = 0
15
- output_tokens: int = 0
16
-
17
- @computed_field
18
- def total_tokens(self) -> int:
19
- return self.input_tokens + self.output_tokens
20
-
21
- @property
22
- def has_usage(self) -> bool:
23
- return self.total_tokens > 0
24
-
25
- def extend(self, *, input_tokens: int, output_tokens: int) -> None:
26
- self.input_tokens += input_tokens
27
- self.output_tokens += output_tokens
28
-
29
-
30
- class RequestUsageStats(BaseModel):
31
- successful_requests: int = 0
32
- failed_requests: int = 0
33
-
34
- @computed_field
35
- def total_requests(self) -> int:
36
- return self.successful_requests + self.failed_requests
37
-
38
- @property
39
- def has_usage(self) -> bool:
40
- return self.total_requests > 0
41
-
42
- def extend(self, *, successful_requests: int, failed_requests: int) -> None:
43
- self.successful_requests += successful_requests
44
- self.failed_requests += failed_requests
45
-
46
-
47
- class ModelUsageStats(BaseModel):
48
- token_usage: TokenUsageStats = TokenUsageStats()
49
- request_usage: RequestUsageStats = RequestUsageStats()
50
-
51
- @property
52
- def has_usage(self) -> bool:
53
- return self.token_usage.has_usage and self.request_usage.has_usage
54
-
55
- def extend(
56
- self, *, token_usage: TokenUsageStats | None = None, request_usage: RequestUsageStats | None = None
57
- ) -> None:
58
- if token_usage is not None:
59
- self.token_usage.extend(input_tokens=token_usage.input_tokens, output_tokens=token_usage.output_tokens)
60
- if request_usage is not None:
61
- self.request_usage.extend(
62
- successful_requests=request_usage.successful_requests, failed_requests=request_usage.failed_requests
63
- )
64
-
65
- def get_usage_stats(self, *, total_time_elapsed: float) -> dict:
66
- return self.model_dump() | {
67
- "tokens_per_second": int(self.token_usage.total_tokens / total_time_elapsed)
68
- if total_time_elapsed > 0
69
- else 0,
70
- "requests_per_minute": int(self.request_usage.total_requests / total_time_elapsed * 60)
71
- if total_time_elapsed > 0
72
- else 0,
73
- }
@@ -1,38 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
-
4
- from __future__ import annotations
5
-
6
- from typing import Any
7
-
8
-
9
- def prompt_to_messages(
10
- *,
11
- user_prompt: str,
12
- system_prompt: str | None = None,
13
- multi_modal_context: list[dict[str, Any]] | None = None,
14
- ) -> list[dict[str, str | list[dict]]]:
15
- """Convert a user and system prompt into Messages format.
16
-
17
- Args:
18
- user_prompt (str): A user prompt.
19
- system_prompt (str, optional): An optional system prompt.
20
- """
21
- user_content = user_prompt
22
- if multi_modal_context and len(multi_modal_context) > 0:
23
- user_content = []
24
- user_content.append({"type": "text", "text": user_prompt})
25
- for context in multi_modal_context:
26
- user_content.append(context)
27
- return (
28
- [
29
- str_to_message(content=system_prompt, role="system"),
30
- str_to_message(content=user_content, role="user"),
31
- ]
32
- if system_prompt
33
- else [str_to_message(content=user_content, role="user")]
34
- )
35
-
36
-
37
- def str_to_message(content: str | list[dict], role: str = "user") -> dict[str, str | list[dict]]:
38
- return {"content": content, "role": role}
@@ -1,2 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
@@ -1,65 +0,0 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
- # SPDX-License-Identifier: Apache-2.0
3
-
4
- from __future__ import annotations
5
-
6
- from collections import deque
7
-
8
- from jinja2 import nodes as j_nodes
9
-
10
-
11
- def ast_max_depth(node: j_nodes.Node) -> int:
12
- """Calculate the depth of a Jinja AST from a given node.
13
-
14
- Args:
15
- node (jinja2.nodes.Node): The starting Jinja2 AST node
16
-
17
- Returns:
18
- int: The maximum depth of the tree
19
- """
20
- # Each entry is (node, depth)
21
- queue = deque([(node, 1)])
22
- max_depth = 0
23
-
24
- while queue:
25
- current_node, current_depth = queue.popleft()
26
-
27
- # Update maximum depth seen so far
28
- max_depth = max(max_depth, current_depth)
29
-
30
- # Add all children with incremented depth
31
- for child in current_node.iter_child_nodes():
32
- queue.append((child, current_depth + 1))
33
-
34
- return max_depth
35
-
36
-
37
- def ast_descendant_count(ast: j_nodes.Node, only_type: type[j_nodes.Node] | None = None) -> int:
38
- """Count the number of nodes which descend from the given node.
39
-
40
- Args:
41
- ast (jinja2.nodes.Node): The starting Jinja2 AST node
42
- only_type (Type[jinja2.nodes.Node]): If specified, then only
43
- nodes of this type will be counted.
44
-
45
- Returns:
46
- int: The number of nodes descended from the given node.
47
- """
48
- if only_type is None:
49
- only_type = j_nodes.Node
50
-
51
- return len(list(ast.find_all(only_type)))
52
-
53
-
54
- def ast_count_name_references(ast: j_nodes.Node, name: str) -> int:
55
- """Count the number of nodes descended from the current that refer to name.
56
-
57
- Args:
58
- ast (jinja2.nodes.Node): The starting Jinja2 AST node
59
-
60
- Returns:
61
- int: The number of nodes descended from the provided node whose
62
- name field matches the given name.
63
- """
64
- referenced_names = [node.name for node in ast.find_all(j_nodes.Name) if node.name == name]
65
- return len(referenced_names)