dgenerate-ultralytics-headless 8.3.248__py3-none-any.whl → 8.4.7__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 (97) hide show
  1. {dgenerate_ultralytics_headless-8.3.248.dist-info → dgenerate_ultralytics_headless-8.4.7.dist-info}/METADATA +52 -61
  2. {dgenerate_ultralytics_headless-8.3.248.dist-info → dgenerate_ultralytics_headless-8.4.7.dist-info}/RECORD +97 -84
  3. {dgenerate_ultralytics_headless-8.3.248.dist-info → dgenerate_ultralytics_headless-8.4.7.dist-info}/WHEEL +1 -1
  4. tests/__init__.py +2 -2
  5. tests/conftest.py +1 -1
  6. tests/test_cuda.py +8 -2
  7. tests/test_engine.py +8 -8
  8. tests/test_exports.py +11 -4
  9. tests/test_integrations.py +9 -9
  10. tests/test_python.py +41 -16
  11. tests/test_solutions.py +3 -3
  12. ultralytics/__init__.py +1 -1
  13. ultralytics/cfg/__init__.py +31 -31
  14. ultralytics/cfg/datasets/TT100K.yaml +346 -0
  15. ultralytics/cfg/datasets/coco12-formats.yaml +101 -0
  16. ultralytics/cfg/default.yaml +3 -1
  17. ultralytics/cfg/models/26/yolo26-cls.yaml +33 -0
  18. ultralytics/cfg/models/26/yolo26-obb.yaml +52 -0
  19. ultralytics/cfg/models/26/yolo26-p2.yaml +60 -0
  20. ultralytics/cfg/models/26/yolo26-p6.yaml +62 -0
  21. ultralytics/cfg/models/26/yolo26-pose.yaml +53 -0
  22. ultralytics/cfg/models/26/yolo26-seg.yaml +52 -0
  23. ultralytics/cfg/models/26/yolo26.yaml +52 -0
  24. ultralytics/cfg/models/26/yoloe-26-seg.yaml +53 -0
  25. ultralytics/cfg/models/26/yoloe-26.yaml +53 -0
  26. ultralytics/data/annotator.py +2 -2
  27. ultralytics/data/augment.py +15 -0
  28. ultralytics/data/converter.py +76 -45
  29. ultralytics/data/dataset.py +1 -1
  30. ultralytics/data/utils.py +2 -2
  31. ultralytics/engine/exporter.py +34 -28
  32. ultralytics/engine/model.py +38 -37
  33. ultralytics/engine/predictor.py +17 -17
  34. ultralytics/engine/results.py +22 -15
  35. ultralytics/engine/trainer.py +83 -48
  36. ultralytics/engine/tuner.py +20 -11
  37. ultralytics/engine/validator.py +16 -16
  38. ultralytics/models/fastsam/predict.py +1 -1
  39. ultralytics/models/yolo/classify/predict.py +1 -1
  40. ultralytics/models/yolo/classify/train.py +1 -1
  41. ultralytics/models/yolo/classify/val.py +1 -1
  42. ultralytics/models/yolo/detect/predict.py +2 -2
  43. ultralytics/models/yolo/detect/train.py +6 -3
  44. ultralytics/models/yolo/detect/val.py +7 -1
  45. ultralytics/models/yolo/model.py +8 -8
  46. ultralytics/models/yolo/obb/predict.py +2 -2
  47. ultralytics/models/yolo/obb/train.py +3 -3
  48. ultralytics/models/yolo/obb/val.py +1 -1
  49. ultralytics/models/yolo/pose/predict.py +1 -1
  50. ultralytics/models/yolo/pose/train.py +3 -1
  51. ultralytics/models/yolo/pose/val.py +1 -1
  52. ultralytics/models/yolo/segment/predict.py +3 -3
  53. ultralytics/models/yolo/segment/train.py +4 -4
  54. ultralytics/models/yolo/segment/val.py +2 -2
  55. ultralytics/models/yolo/yoloe/train.py +6 -1
  56. ultralytics/models/yolo/yoloe/train_seg.py +6 -1
  57. ultralytics/nn/autobackend.py +14 -8
  58. ultralytics/nn/modules/__init__.py +8 -0
  59. ultralytics/nn/modules/block.py +128 -8
  60. ultralytics/nn/modules/head.py +788 -203
  61. ultralytics/nn/tasks.py +86 -41
  62. ultralytics/nn/text_model.py +5 -2
  63. ultralytics/optim/__init__.py +5 -0
  64. ultralytics/optim/muon.py +338 -0
  65. ultralytics/solutions/ai_gym.py +3 -3
  66. ultralytics/solutions/config.py +1 -1
  67. ultralytics/solutions/heatmap.py +1 -1
  68. ultralytics/solutions/instance_segmentation.py +2 -2
  69. ultralytics/solutions/object_counter.py +1 -1
  70. ultralytics/solutions/parking_management.py +1 -1
  71. ultralytics/solutions/solutions.py +2 -2
  72. ultralytics/trackers/byte_tracker.py +7 -7
  73. ultralytics/trackers/track.py +1 -1
  74. ultralytics/utils/__init__.py +8 -8
  75. ultralytics/utils/benchmarks.py +26 -26
  76. ultralytics/utils/callbacks/platform.py +173 -64
  77. ultralytics/utils/callbacks/tensorboard.py +2 -0
  78. ultralytics/utils/callbacks/wb.py +6 -1
  79. ultralytics/utils/checks.py +28 -9
  80. ultralytics/utils/dist.py +1 -0
  81. ultralytics/utils/downloads.py +5 -3
  82. ultralytics/utils/export/engine.py +19 -10
  83. ultralytics/utils/export/imx.py +38 -20
  84. ultralytics/utils/export/tensorflow.py +21 -21
  85. ultralytics/utils/files.py +2 -2
  86. ultralytics/utils/loss.py +597 -203
  87. ultralytics/utils/metrics.py +2 -1
  88. ultralytics/utils/ops.py +11 -2
  89. ultralytics/utils/patches.py +42 -0
  90. ultralytics/utils/plotting.py +3 -0
  91. ultralytics/utils/tal.py +100 -20
  92. ultralytics/utils/torch_utils.py +1 -1
  93. ultralytics/utils/tqdm.py +4 -1
  94. ultralytics/utils/tuner.py +2 -5
  95. {dgenerate_ultralytics_headless-8.3.248.dist-info → dgenerate_ultralytics_headless-8.4.7.dist-info}/entry_points.txt +0 -0
  96. {dgenerate_ultralytics_headless-8.3.248.dist-info → dgenerate_ultralytics_headless-8.4.7.dist-info}/licenses/LICENSE +0 -0
  97. {dgenerate_ultralytics_headless-8.3.248.dist-info → dgenerate_ultralytics_headless-8.4.7.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  import os
4
4
  import platform
5
+ import re
5
6
  import socket
6
7
  import sys
7
8
  from concurrent.futures import ThreadPoolExecutor
@@ -11,9 +12,18 @@ from time import time
11
12
  from ultralytics.utils import ENVIRONMENT, GIT, LOGGER, PYTHON_VERSION, RANK, SETTINGS, TESTS_RUNNING, colorstr
12
13
 
13
14
  PREFIX = colorstr("Platform: ")
14
- _last_upload = 0 # Rate limit model uploads
15
- _console_logger = None # Global console logger instance
16
- _system_logger = None # Cached system logger instance
15
+
16
+ # Configurable platform URL for debugging (e.g. ULTRALYTICS_PLATFORM_URL=http://localhost:3000)
17
+ PLATFORM_URL = os.getenv("ULTRALYTICS_PLATFORM_URL", "https://platform.ultralytics.com").rstrip("/")
18
+ PLATFORM_API_URL = f"{PLATFORM_URL}/api/webhooks"
19
+
20
+
21
+ def slugify(text):
22
+ """Convert text to URL-safe slug (e.g., 'My Project 1' -> 'my-project-1')."""
23
+ if not text:
24
+ return text
25
+ return re.sub(r"-+", "-", re.sub(r"[^a-z0-9\s-]", "", str(text).lower()).replace(" ", "-")).strip("-")[:128]
26
+
17
27
 
18
28
  try:
19
29
  assert not TESTS_RUNNING # do not log pytest
@@ -32,6 +42,84 @@ except (AssertionError, ImportError):
32
42
  _api_key = None
33
43
 
34
44
 
45
+ def resolve_platform_uri(uri, hard=True):
46
+ """Resolve ul:// URIs to signed URLs by authenticating with Ultralytics Platform.
47
+
48
+ Formats:
49
+ ul://username/datasets/slug -> Returns signed URL to NDJSON file
50
+ ul://username/project/model -> Returns signed URL to .pt file
51
+
52
+ Args:
53
+ uri (str): Platform URI starting with "ul://".
54
+ hard (bool): Whether to raise an error if resolution fails (FileNotFoundError only).
55
+
56
+ Returns:
57
+ (str | None): Signed URL on success, None if not found and hard=False.
58
+
59
+ Raises:
60
+ ValueError: If API key is missing/invalid or URI format is wrong.
61
+ PermissionError: If access is denied.
62
+ RuntimeError: If resource is not ready (e.g., dataset still processing).
63
+ FileNotFoundError: If resource not found and hard=True.
64
+ ConnectionError: If network request fails and hard=True.
65
+ """
66
+ import requests
67
+
68
+ path = uri[5:] # Remove "ul://"
69
+ parts = path.split("/")
70
+
71
+ api_key = os.getenv("ULTRALYTICS_API_KEY") or SETTINGS.get("api_key")
72
+ if not api_key:
73
+ raise ValueError(f"ULTRALYTICS_API_KEY required for '{uri}'. Get key at {PLATFORM_URL}/settings")
74
+
75
+ base = PLATFORM_API_URL
76
+ headers = {"Authorization": f"Bearer {api_key}"}
77
+
78
+ # ul://username/datasets/slug
79
+ if len(parts) == 3 and parts[1] == "datasets":
80
+ username, _, slug = parts
81
+ url = f"{base}/datasets/{username}/{slug}/export"
82
+
83
+ # ul://username/project/model
84
+ elif len(parts) == 3:
85
+ username, project, model = parts
86
+ url = f"{base}/models/{username}/{project}/{model}/download"
87
+
88
+ else:
89
+ raise ValueError(f"Invalid platform URI: {uri}. Use ul://user/datasets/name or ul://user/project/model")
90
+
91
+ try:
92
+ timeout = 3600 if "/datasets/" in url else 90 # NDJSON generation can be slow for large datasets
93
+ r = requests.head(url, headers=headers, allow_redirects=False, timeout=timeout)
94
+
95
+ # Handle redirect responses (301, 302, 303, 307, 308)
96
+ if 300 <= r.status_code < 400 and "location" in r.headers:
97
+ return r.headers["location"] # Return signed URL
98
+
99
+ # Handle error responses
100
+ if r.status_code == 401:
101
+ raise ValueError(f"Invalid ULTRALYTICS_API_KEY for '{uri}'")
102
+ if r.status_code == 403:
103
+ raise PermissionError(f"Access denied for '{uri}'. Check dataset/model visibility settings.")
104
+ if r.status_code == 404:
105
+ if hard:
106
+ raise FileNotFoundError(f"Not found on platform: {uri}")
107
+ LOGGER.warning(f"Not found on platform: {uri}")
108
+ return None
109
+ if r.status_code == 409:
110
+ raise RuntimeError(f"Resource not ready: {uri}. Dataset may still be processing.")
111
+
112
+ # Unexpected response
113
+ r.raise_for_status()
114
+ raise RuntimeError(f"Unexpected response from platform for '{uri}': {r.status_code}")
115
+
116
+ except requests.exceptions.RequestException as e:
117
+ if hard:
118
+ raise ConnectionError(f"Failed to resolve {uri}: {e}") from e
119
+ LOGGER.warning(f"Failed to resolve {uri}: {e}")
120
+ return None
121
+
122
+
35
123
  def _interp_plot(plot, n=101):
36
124
  """Interpolate plot curve data from 1000 to n points to reduce storage size."""
37
125
  import numpy as np
@@ -60,22 +148,28 @@ def _interp_plot(plot, n=101):
60
148
  return result
61
149
 
62
150
 
63
- def _send(event, data, project, name):
64
- """Send event to Platform endpoint."""
151
+ def _send(event, data, project, name, model_id=None):
152
+ """Send event to Platform endpoint. Returns response JSON on success."""
65
153
  try:
66
- requests.post(
67
- "https://alpha.ultralytics.com/api/webhooks/training/metrics",
68
- json={"event": event, "project": project, "name": name, "data": data},
154
+ payload = {"event": event, "project": project, "name": name, "data": data}
155
+ if model_id:
156
+ payload["modelId"] = model_id
157
+ r = requests.post(
158
+ f"{PLATFORM_API_URL}/training/metrics",
159
+ json=payload,
69
160
  headers={"Authorization": f"Bearer {_api_key}"},
70
161
  timeout=10,
71
- ).raise_for_status()
162
+ )
163
+ r.raise_for_status()
164
+ return r.json()
72
165
  except Exception as e:
73
166
  LOGGER.debug(f"Platform: Failed to send {event}: {e}")
167
+ return None
74
168
 
75
169
 
76
- def _send_async(event, data, project, name):
170
+ def _send_async(event, data, project, name, model_id=None):
77
171
  """Send event asynchronously using bounded thread pool."""
78
- _executor.submit(_send, event, data, project, name)
172
+ _executor.submit(_send, event, data, project, name, model_id)
79
173
 
80
174
 
81
175
  def _upload_model(model_path, project, name):
@@ -87,7 +181,7 @@ def _upload_model(model_path, project, name):
87
181
 
88
182
  # Get signed upload URL
89
183
  response = requests.post(
90
- "https://alpha.ultralytics.com/api/webhooks/models/upload",
184
+ f"{PLATFORM_API_URL}/models/upload",
91
185
  json={"project": project, "name": name, "filename": model_path.name},
92
186
  headers={"Authorization": f"Bearer {_api_key}"},
93
187
  timeout=10,
@@ -104,7 +198,7 @@ def _upload_model(model_path, project, name):
104
198
  timeout=600, # 10 min timeout for large models
105
199
  ).raise_for_status()
106
200
 
107
- # url = f"https://alpha.ultralytics.com/{project}/{name}"
201
+ # url = f"{PLATFORM_URL}/{project}/{name}"
108
202
  # LOGGER.info(f"{PREFIX}Model uploaded to {url}")
109
203
  return data.get("gcsPath")
110
204
 
@@ -169,132 +263,146 @@ def _get_environment_info():
169
263
  return env
170
264
 
171
265
 
266
+ def _get_project_name(trainer):
267
+ """Get slugified project and name from trainer args."""
268
+ raw = str(trainer.args.project)
269
+ parts = raw.split("/", 1)
270
+ project = f"{parts[0]}/{slugify(parts[1])}" if len(parts) == 2 else slugify(raw)
271
+ return project, slugify(str(trainer.args.name or "train"))
272
+
273
+
172
274
  def on_pretrain_routine_start(trainer):
173
275
  """Initialize Platform logging at training start."""
174
- global _console_logger, _last_upload
175
-
176
276
  if RANK not in {-1, 0} or not trainer.args.project:
177
277
  return
178
278
 
179
- # Initialize upload timer to now so first checkpoint waits 15 min from training start
180
- _last_upload = time()
279
+ # Per-trainer state to isolate concurrent training runs
280
+ trainer._platform_model_id = None
281
+ trainer._platform_last_upload = time()
181
282
 
182
- project, name = str(trainer.args.project), str(trainer.args.name or "train")
183
- url = f"https://alpha.ultralytics.com/{project}/{name}"
283
+ project, name = _get_project_name(trainer)
284
+ url = f"{PLATFORM_URL}/{project}/{name}"
184
285
  LOGGER.info(f"{PREFIX}Streaming to {url}")
185
286
 
186
287
  # Create callback to send console output to Platform
187
288
  def send_console_output(content, line_count, chunk_id):
188
289
  """Send batched console output to Platform webhook."""
189
- _send_async("console_output", {"chunkId": chunk_id, "content": content, "lineCount": line_count}, project, name)
290
+ _send_async(
291
+ "console_output",
292
+ {"chunkId": chunk_id, "content": content, "lineCount": line_count},
293
+ project,
294
+ name,
295
+ getattr(trainer, "_platform_model_id", None),
296
+ )
190
297
 
191
298
  # Start console capture with batching (5 lines or 5 seconds)
192
- _console_logger = ConsoleLogger(batch_size=5, flush_interval=5.0, on_flush=send_console_output)
193
- _console_logger.start_capture()
194
-
195
- # Gather model info for richer metadata
196
- model_info = {}
197
- try:
198
- info = model_info_for_loggers(trainer)
199
- model_info = {
200
- "parameters": info.get("model/parameters", 0),
201
- "gflops": info.get("model/GFLOPs", 0),
202
- "classes": getattr(trainer.model, "yaml", {}).get("nc", 0), # number of classes
203
- }
204
- except Exception:
205
- pass
299
+ trainer._platform_console_logger = ConsoleLogger(batch_size=5, flush_interval=5.0, on_flush=send_console_output)
300
+ trainer._platform_console_logger.start_capture()
206
301
 
207
302
  # Collect environment info (W&B-style metadata)
208
303
  environment = _get_environment_info()
209
304
 
210
- _send_async(
305
+ # Build trainArgs - callback runs before get_dataset() so args.data is still original (e.g., ul:// URIs)
306
+ # Note: model_info is sent later in on_fit_epoch_end (epoch 0) when the model is actually loaded
307
+ train_args = {k: str(v) for k, v in vars(trainer.args).items()}
308
+
309
+ # Send synchronously to get modelId for subsequent webhooks
310
+ response = _send(
211
311
  "training_started",
212
312
  {
213
- "trainArgs": {k: str(v) for k, v in vars(trainer.args).items()},
313
+ "trainArgs": train_args,
214
314
  "epochs": trainer.epochs,
215
315
  "device": str(trainer.device),
216
- "modelInfo": model_info,
217
316
  "environment": environment,
218
317
  },
219
318
  project,
220
319
  name,
221
320
  )
321
+ if response and response.get("modelId"):
322
+ trainer._platform_model_id = response["modelId"]
222
323
 
223
324
 
224
325
  def on_fit_epoch_end(trainer):
225
326
  """Log training and system metrics at epoch end."""
226
- global _system_logger
227
-
228
327
  if RANK not in {-1, 0} or not trainer.args.project:
229
328
  return
230
329
 
231
- project, name = str(trainer.args.project), str(trainer.args.name or "train")
330
+ project, name = _get_project_name(trainer)
232
331
  metrics = {**trainer.label_loss_items(trainer.tloss, prefix="train"), **trainer.metrics}
233
332
 
234
333
  if trainer.optimizer and trainer.optimizer.param_groups:
235
334
  metrics["lr"] = trainer.optimizer.param_groups[0]["lr"]
335
+
336
+ # Extract model info at epoch 0 (sent as separate field, not in metrics)
337
+ model_info = None
236
338
  if trainer.epoch == 0:
237
339
  try:
238
- metrics.update(model_info_for_loggers(trainer))
340
+ info = model_info_for_loggers(trainer)
341
+ model_info = {
342
+ "parameters": info.get("model/parameters", 0),
343
+ "gflops": info.get("model/GFLOPs", 0),
344
+ "speedMs": info.get("model/speed_PyTorch(ms)", 0),
345
+ }
239
346
  except Exception:
240
347
  pass
241
348
 
242
- # Get system metrics (cache SystemLogger for efficiency)
349
+ # Get system metrics (cache SystemLogger on trainer for efficiency)
243
350
  system = {}
244
351
  try:
245
- if _system_logger is None:
246
- _system_logger = SystemLogger()
247
- system = _system_logger.get_metrics(rates=True)
352
+ if not hasattr(trainer, "_platform_system_logger"):
353
+ trainer._platform_system_logger = SystemLogger()
354
+ system = trainer._platform_system_logger.get_metrics(rates=True)
248
355
  except Exception:
249
356
  pass
250
357
 
358
+ payload = {
359
+ "epoch": trainer.epoch,
360
+ "metrics": metrics,
361
+ "system": system,
362
+ "fitness": trainer.fitness,
363
+ "best_fitness": trainer.best_fitness,
364
+ }
365
+ if model_info:
366
+ payload["modelInfo"] = model_info
367
+
251
368
  _send_async(
252
369
  "epoch_end",
253
- {
254
- "epoch": trainer.epoch,
255
- "metrics": metrics,
256
- "system": system,
257
- "fitness": trainer.fitness,
258
- "best_fitness": trainer.best_fitness,
259
- },
370
+ payload,
260
371
  project,
261
372
  name,
373
+ getattr(trainer, "_platform_model_id", None),
262
374
  )
263
375
 
264
376
 
265
377
  def on_model_save(trainer):
266
378
  """Upload model checkpoint (rate limited to every 15 min)."""
267
- global _last_upload
268
-
269
379
  if RANK not in {-1, 0} or not trainer.args.project:
270
380
  return
271
381
 
272
382
  # Rate limit to every 15 minutes (900 seconds)
273
- if time() - _last_upload < 900:
383
+ if time() - getattr(trainer, "_platform_last_upload", 0) < 900:
274
384
  return
275
385
 
276
386
  model_path = trainer.best if trainer.best and Path(trainer.best).exists() else trainer.last
277
387
  if not model_path:
278
388
  return
279
389
 
280
- project, name = str(trainer.args.project), str(trainer.args.name or "train")
390
+ project, name = _get_project_name(trainer)
281
391
  _upload_model_async(model_path, project, name)
282
- _last_upload = time()
392
+ trainer._platform_last_upload = time()
283
393
 
284
394
 
285
395
  def on_train_end(trainer):
286
396
  """Log final results, upload best model, and send validation plot data."""
287
- global _console_logger
288
-
289
397
  if RANK not in {-1, 0} or not trainer.args.project:
290
398
  return
291
399
 
292
- project, name = str(trainer.args.project), str(trainer.args.name or "train")
400
+ project, name = _get_project_name(trainer)
293
401
 
294
402
  # Stop console capture
295
- if _console_logger:
296
- _console_logger.stop_capture()
297
- _console_logger = None
403
+ if hasattr(trainer, "_platform_console_logger") and trainer._platform_console_logger:
404
+ trainer._platform_console_logger.stop_capture()
405
+ trainer._platform_console_logger = None
298
406
 
299
407
  # Upload best model (blocking to ensure it completes)
300
408
  model_path = None
@@ -332,8 +440,9 @@ def on_train_end(trainer):
332
440
  },
333
441
  project,
334
442
  name,
443
+ getattr(trainer, "_platform_model_id", None),
335
444
  )
336
- url = f"https://alpha.ultralytics.com/{project}/{name}"
445
+ url = f"{PLATFORM_URL}/{project}/{name}"
337
446
  LOGGER.info(f"{PREFIX}View results at {url}")
338
447
 
339
448
 
@@ -1,6 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
3
  from ultralytics.utils import LOGGER, SETTINGS, TESTS_RUNNING, colorstr, torch_utils
4
+ from ultralytics.utils.torch_utils import smart_inference_mode
4
5
 
5
6
  try:
6
7
  assert not TESTS_RUNNING # do not log pytest
@@ -38,6 +39,7 @@ def _log_scalars(scalars: dict, step: int = 0) -> None:
38
39
  WRITER.add_scalar(k, v, step)
39
40
 
40
41
 
42
+ @smart_inference_mode()
41
43
  def _log_tensorboard_graph(trainer) -> None:
42
44
  """Log model graph to TensorBoard.
43
45
 
@@ -128,10 +128,15 @@ def _log_plots(plots, step):
128
128
  def on_pretrain_routine_start(trainer):
129
129
  """Initialize and start wandb project if module is present."""
130
130
  if not wb.run:
131
+ from datetime import datetime
132
+
133
+ name = str(trainer.args.name).replace("/", "-").replace(" ", "_")
131
134
  wb.init(
132
135
  project=str(trainer.args.project).replace("/", "-") if trainer.args.project else "Ultralytics",
133
- name=str(trainer.args.name).replace("/", "-"),
136
+ name=name,
134
137
  config=vars(trainer.args),
138
+ id=f"{name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}", # add unique id
139
+ dir=str(trainer.save_dir),
135
140
  )
136
141
 
137
142
 
@@ -530,7 +530,7 @@ def check_torchvision():
530
530
  )
531
531
 
532
532
 
533
- def check_suffix(file="yolo11n.pt", suffix=".pt", msg=""):
533
+ def check_suffix(file="yolo26n.pt", suffix=".pt", msg=""):
534
534
  """Check file(s) for acceptable suffix.
535
535
 
536
536
  Args:
@@ -584,7 +584,7 @@ def check_model_file_from_stem(model="yolo11n"):
584
584
  """
585
585
  path = Path(model)
586
586
  if not path.suffix and path.stem in downloads.GITHUB_ASSETS_STEMS:
587
- return path.with_suffix(".pt") # add suffix, i.e. yolo11n -> yolo11n.pt
587
+ return path.with_suffix(".pt") # add suffix, i.e. yolo26n -> yolo26n.pt
588
588
  return model
589
589
 
590
590
 
@@ -592,7 +592,7 @@ def check_file(file, suffix="", download=True, download_dir=".", hard=True):
592
592
  """Search/download file (if necessary), check suffix (if provided), and return path.
593
593
 
594
594
  Args:
595
- file (str): File name or path.
595
+ file (str): File name or path, URL, platform URI (ul://), or GCS path (gs://).
596
596
  suffix (str | tuple): Acceptable suffix or tuple of suffixes to validate against the file.
597
597
  download (bool): Whether to download the file if it doesn't exist locally.
598
598
  download_dir (str): Directory to download the file to.
@@ -610,7 +610,26 @@ def check_file(file, suffix="", download=True, download_dir=".", hard=True):
610
610
  or file.lower().startswith("grpc://")
611
611
  ): # file exists or gRPC Triton images
612
612
  return file
613
- elif download and file.lower().startswith(("https://", "http://", "rtsp://", "rtmp://", "tcp://")): # download
613
+ elif download and file.lower().startswith("ul://"): # Ultralytics Platform URI
614
+ from ultralytics.utils.callbacks.platform import resolve_platform_uri
615
+
616
+ url = resolve_platform_uri(file, hard=hard) # Convert to signed HTTPS URL
617
+ if url is None:
618
+ return [] # Not found, soft fail (consistent with file search behavior)
619
+ # Use URI path for unique directory structure: ul://user/project/model -> user/project/model/filename.pt
620
+ uri_path = file[5:] # Remove "ul://"
621
+ local_file = Path(download_dir) / uri_path / url2file(url)
622
+ if local_file.exists():
623
+ LOGGER.info(f"Found {clean_url(url)} locally at {local_file}")
624
+ else:
625
+ local_file.parent.mkdir(parents=True, exist_ok=True)
626
+ downloads.safe_download(url=url, file=local_file, unzip=False)
627
+ return str(local_file)
628
+ elif download and file.lower().startswith(
629
+ ("https://", "http://", "rtsp://", "rtmp://", "tcp://", "gs://")
630
+ ): # download
631
+ if file.startswith("gs://"):
632
+ file = "https://storage.googleapis.com/" + file[5:] # convert gs:// to public HTTPS URL
614
633
  url = file # warning: Pathlib turns :// -> :/
615
634
  file = Path(download_dir) / url2file(file) # '%2F' to '/', split https://url.com/file.txt?auth
616
635
  if file.exists():
@@ -793,7 +812,7 @@ def check_amp(model):
793
812
  Examples:
794
813
  >>> from ultralytics import YOLO
795
814
  >>> from ultralytics.utils.checks import check_amp
796
- >>> model = YOLO("yolo11n.pt").model.cuda()
815
+ >>> model = YOLO("yolo26n.pt").model.cuda()
797
816
  >>> check_amp(model)
798
817
  """
799
818
  from ultralytics.utils.torch_utils import autocast
@@ -832,14 +851,14 @@ def check_amp(model):
832
851
  try:
833
852
  from ultralytics import YOLO
834
853
 
835
- assert amp_allclose(YOLO("yolo11n.pt"), im)
854
+ assert amp_allclose(YOLO("yolo26n.pt"), im)
836
855
  LOGGER.info(f"{prefix}checks passed ✅")
837
856
  except ConnectionError:
838
- LOGGER.warning(f"{prefix}checks skipped. Offline and unable to download YOLO11n for AMP checks. {warning_msg}")
857
+ LOGGER.warning(f"{prefix}checks skipped. Offline and unable to download YOLO26n for AMP checks. {warning_msg}")
839
858
  except (AttributeError, ModuleNotFoundError):
840
859
  LOGGER.warning(
841
860
  f"{prefix}checks skipped. "
842
- f"Unable to load YOLO11n for AMP checks due to possible Ultralytics package modifications. {warning_msg}"
861
+ f"Unable to load YOLO26n for AMP checks due to possible Ultralytics package modifications. {warning_msg}"
843
862
  )
844
863
  except AssertionError:
845
864
  LOGGER.error(
@@ -945,7 +964,7 @@ def is_rockchip():
945
964
  with open("/proc/device-tree/compatible") as f:
946
965
  dev_str = f.read()
947
966
  *_, soc = dev_str.split(",")
948
- if soc.replace("\x00", "") in RKNN_CHIPS:
967
+ if soc.replace("\x00", "").split("-", 1)[0] in RKNN_CHIPS:
949
968
  return True
950
969
  except OSError:
951
970
  return False
ultralytics/utils/dist.py CHANGED
@@ -49,6 +49,7 @@ def generate_ddp_file(trainer):
49
49
 
50
50
  content = f"""
51
51
  # Ultralytics Multi-GPU training temp file (should be automatically deleted after use)
52
+ from pathlib import Path, PosixPath # For model arguments stored as Path instead of str
52
53
  overrides = {vars(trainer.args)}
53
54
 
54
55
  if __name__ == "__main__":
@@ -18,12 +18,14 @@ GITHUB_ASSETS_NAMES = frozenset(
18
18
  [f"yolov8{k}{suffix}.pt" for k in "nsmlx" for suffix in ("", "-cls", "-seg", "-pose", "-obb", "-oiv7")]
19
19
  + [f"yolo11{k}{suffix}.pt" for k in "nsmlx" for suffix in ("", "-cls", "-seg", "-pose", "-obb")]
20
20
  + [f"yolo12{k}{suffix}.pt" for k in "nsmlx" for suffix in ("",)] # detect models only currently
21
+ + [f"yolo26{k}{suffix}.pt" for k in "nsmlx" for suffix in ("", "-cls", "-seg", "-pose", "-obb")]
21
22
  + [f"yolov5{k}{resolution}u.pt" for k in "nsmlx" for resolution in ("", "6")]
22
23
  + [f"yolov3{k}u.pt" for k in ("", "-spp", "-tiny")]
23
24
  + [f"yolov8{k}-world.pt" for k in "smlx"]
24
25
  + [f"yolov8{k}-worldv2.pt" for k in "smlx"]
25
26
  + [f"yoloe-v8{k}{suffix}.pt" for k in "sml" for suffix in ("-seg", "-seg-pf")]
26
27
  + [f"yoloe-11{k}{suffix}.pt" for k in "sml" for suffix in ("-seg", "-seg-pf")]
28
+ + [f"yoloe-26{k}{suffix}.pt" for k in "nsmlx" for suffix in ("-seg", "-seg-pf")]
27
29
  + [f"yolov9{k}.pt" for k in "tsmce"]
28
30
  + [f"yolov10{k}.pt" for k in "nsmblx"]
29
31
  + [f"yolo_nas_{k}.pt" for k in "sml"]
@@ -418,13 +420,13 @@ def get_github_assets(
418
420
  LOGGER.warning(f"GitHub assets check failure for {url}: {r.status_code} {r.reason}")
419
421
  return "", []
420
422
  data = r.json()
421
- return data["tag_name"], [x["name"] for x in data["assets"]] # tag, assets i.e. ['yolo11n.pt', 'yolov8s.pt', ...]
423
+ return data["tag_name"], [x["name"] for x in data["assets"]] # tag, assets i.e. ['yolo26n.pt', 'yolo11s.pt', ...]
422
424
 
423
425
 
424
426
  def attempt_download_asset(
425
427
  file: str | Path,
426
428
  repo: str = "ultralytics/assets",
427
- release: str = "v8.3.0",
429
+ release: str = "v8.4.0",
428
430
  **kwargs,
429
431
  ) -> str:
430
432
  """Attempt to download a file from GitHub release assets if it is not found locally.
@@ -439,7 +441,7 @@ def attempt_download_asset(
439
441
  (str): The path to the downloaded file.
440
442
 
441
443
  Examples:
442
- >>> file_path = attempt_download_asset("yolo11n.pt", repo="ultralytics/assets", release="latest")
444
+ >>> file_path = attempt_download_asset("yolo26n.pt", repo="ultralytics/assets", release="latest")
443
445
  """
444
446
  from ultralytics.utils import SETTINGS # scoped for circular import
445
447
 
@@ -143,7 +143,7 @@ def onnx2engine(
143
143
  for inp in inputs:
144
144
  profile.set_shape(inp.name, min=min_shape, opt=shape, max=max_shape)
145
145
  config.add_optimization_profile(profile)
146
- if int8:
146
+ if int8 and not is_trt10: # deprecated in TensorRT 10, causes internal errors
147
147
  config.set_calibration_profile(profile)
148
148
 
149
149
  LOGGER.info(f"{prefix} building {'INT8' if int8 else 'FP' + ('16' if half else '32')} engine as {engine_file}")
@@ -226,12 +226,21 @@ def onnx2engine(
226
226
  config.set_flag(trt.BuilderFlag.FP16)
227
227
 
228
228
  # Write file
229
- build = builder.build_serialized_network if is_trt10 else builder.build_engine
230
- with build(network, config) as engine, open(engine_file, "wb") as t:
231
- # Metadata
232
- if metadata is not None:
233
- meta = json.dumps(metadata)
234
- t.write(len(meta).to_bytes(4, byteorder="little", signed=True))
235
- t.write(meta.encode())
236
- # Model
237
- t.write(engine if is_trt10 else engine.serialize())
229
+ if is_trt10:
230
+ # TensorRT 10+ returns bytes directly, not a context manager
231
+ engine = builder.build_serialized_network(network, config)
232
+ if engine is None:
233
+ raise RuntimeError("TensorRT engine build failed, check logs for errors")
234
+ with open(engine_file, "wb") as t:
235
+ if metadata is not None:
236
+ meta = json.dumps(metadata)
237
+ t.write(len(meta).to_bytes(4, byteorder="little", signed=True))
238
+ t.write(meta.encode())
239
+ t.write(engine)
240
+ else:
241
+ with builder.build_engine(network, config) as engine, open(engine_file, "wb") as t:
242
+ if metadata is not None:
243
+ meta = json.dumps(metadata)
244
+ t.write(len(meta).to_bytes(4, byteorder="little", signed=True))
245
+ t.write(meta.encode())
246
+ t.write(engine.serialize())