feat(formats): the yolo format becomes the ultralytics dialect, beside yolov5-yaml - #798
Merged
Conversation
…rrows the compatibility report validate_targets checks a target's geometries against what the exporter writes at all, supported and degraded together, and validate_installed applies it across every installed exporter while refusing a target name two of them declare. _compatibility takes an optional target: a geometry the format writes whole but the target does not carry is a reported drop, and a geometry no annotation can carry is never a row.
…e yolov5-yaml The ultralytics dialect derives its task from the release: segment when it holds a polygon, classify when it holds only classification tags, detect otherwise. Its data.yaml carries path: ., one key per fold present, and names as a mapping with no nc. yolov5-yaml writes the YOLOv5 descriptor grammar for YOLOv7 over the same layout, extracted into _yolo_writer. The registry accepts yolo as an alias of ultralytics and answers the alias beside the plugin, and validates every declaration at the scan. The nine Ultralytics targets and yolov7 are declared.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the export-targets epic (#784). The single
yoloformat becomes theultralyticsdialect, a second dialectyolov5-yamlwrites the older descriptor grammar for YOLOv7, and the ten trainer targets the epic names are declared on the two exporters.yolois accepted as an alias ofultralyticsfor one release and then removed.The dialect grammar
A dialect is the descriptor grammar;
format_namenames it. A target is the model a person will train, and it resolves to exactly one dialect.ultralyticswritesdata.yamlaspath: ., one key per fold present, andnamesas a mapping from index with nonc. The task is derived from the release, never chosen:segmentwhen it holds any polygon (every polygon as its vertices, every box as its four corners),classifywhen it holds classification tags and no box or polygon (the class tree<fold>/<class>/<image>, one copy per tag, a directory for every tag-capable class, no yaml),detectotherwise. Its geometry declaration is{bbox, polygon, classification_tag}supported and nothing degraded. It declaresyolo26,yolo12,yolo11,yolov10,yolov9,yolov8,yolov6,yolov5,yolov3, familyultralytics-yolo, with the task sets the Ultralytics models page lists and hints(640, 640), letterbox, trainer resizes, augmentation common.yolov5-yamlwritestrain: ./images/train,val: ./images/val,test: ./images/testwhen present,nc, andnamesas a list; detection only, so a polygon is written as its bounding box and reported degraded. It declaresyolov7, familycommunity-yolo. Both dialects share the layout and label arithmetic informats/_yolo_writer.py, which is not part of the port.The registry applies
ALIASES = {"yolo": "ultralytics"}inpick(), which now answers(plugin, deprecated_alias); the CLI turns the marker into a warning in the next slice.exporters()validates every declaration at the scan: a target promising a geometry its format never writes, or one name declared by two formats, is refused there.validate_targetsjudges a target againstsupported ∪ degraded, so TuSimple's{polyline}target validates._compatibilitytakes an optional target: a geometry the format writes whole but the target does not carry is a reported drop, consented throughallow_lossy; a geometry no annotation can carry is never a row.Class ids are positions in the frozen schema order;
LabelClasscarries no number of its own, so a gap is unrepresentable and no refusal exists for it.Recorded, for the reviewer
yoloexporter omittedpath:deliberately and wrotenc:, with a smoke test proving the export loads from any working directory. In ultralytics 8.4.124 a relativepaththat exists is kept as it is (data/utils.py, thecheck_det_datasetpath resolution), and.always exists, sopath: .resolves the splits against the working directory of the loading process. The round-trip test andexamples/thirty_minute_flow.pytherefore load from inside the export directory, and the docs say so. The descriptor is as the epic specifies; the portability the omitted key bought is gone.classificationexporter's layout isimages/<fold>/pluslabels.csv, not the class tree the trainer reads, so the classify layout is written by theultralyticsdialect itself.classification_tagsupported (a tags-only release is written as a class tree). The report misstates that one row for mixed releases; consent is still asked because the format is lossy.test_report_agreement.pypins the shape as what it is and compares the dialect per layout.Exporterport carries no target, so the written layout does not yet depend on which target was named; narrowing the output to a target's task set needs the export seam the next slice wires.Found, not fixed
formats/classification/__init__.py's docstring says the kernel enforces no(asset, class)uniqueness for a classification tag;AnnotationServicerefuses a duplicate withDuplicateClassificationTag.Stack
Position 2 of the export-targets stack (#784); based on
main, which now holds PR #788.Checks
Targeted:
uv run ruff check .,uv run ruff format --check .,uv run mypy src/visionset,uv run lint-imports,uv run pytest tests/formats tests/kernel tests/cli tests/mcp tests/server tests/jobs tests/examples tests/packaging tests/architecture -n 4(3903 passed, 9 skipped),uv sync --group yolo && VISIONSET_REQUIRE_ULTRALYTICS=1 uv run pytest tests/formats/test_ultralytics_roundtrip.py(3 passed),scripts/export_mcp_tools.py --check,scripts/export_openapi.py(no diff).Full gate (
bash scripts/check.sh) on the final tree: