Add v2 trainings + train-recipe support (describe, non-blocking start_training, CLI)#510
Draft
leeclemnet wants to merge 3 commits into
Draft
Add v2 trainings + train-recipe support (describe, non-blocking start_training, CLI)#510leeclemnet wants to merge 3 commits into
leeclemnet wants to merge 3 commits into
Conversation
Wraps the new v2 trainings API surface:
GET /{ws}/{proj}/{ver}/v2/trainings/recipe?modelType=...
POST /{ws}/{proj}/{ver}/v2/trainings
GET /{ws}/{proj}/{ver}/v2/trainings
GET /{ws}/{proj}/{ver}/v2/trainings/get?trainingId=...
Adapters (roboflow/adapters/rfapi.py): get_train_recipe,
create_training (camelCase modelType/trainRecipe, only non-None body
keys), list_version_trainings, get_version_training — same URL/error
conventions as start_version_training.
SDK (roboflow/core/version.py): Version.describe_train_recipe,
Version.start_training (non-blocking; builds a full trainRecipe from
the server template when hyperparameters/online_augmentation are
given — the backend dense-fills defaults server-side; mirrors
train()'s generation-wait + export-ensuring when model_type is set),
Version.list_trainings, Version.get_training. train() unchanged.
Shared merge logic lives in roboflow/util/train_recipe.py
(build_train_recipe) so the CLI and SDK submit identical recipes;
online_augmentation defaults splits to ["train"].
CLI (roboflow/cli/handlers/train.py):
roboflow train recipe -p <project> -v <N> -m <model_type>
roboflow train start ... --hyperparameters '<json>'
roboflow train start ... --train-recipe '<json>'
Recipe flags route through the v2 create_training path and print the
new trainingId; invalid JSON and recipe-vs-hyperparameters conflicts
fail with structured errors, not tracebacks.
Tests: +34 (9 rfapi via responses, 13 Version via patched rfapi,
12 CLI via CliRunner + patched adapters). Full suite 897 passing;
ruff format/check and mypy clean. CLI-COMMANDS.md documents the new
command and flags (roboflow-product-docs follow-up out of scope).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Server behavior: normalizeRecipeHyperparameters dense-fills a submitted
recipe's hyperparameters (adding a manifest-default epochs, e.g. 100 for
rf-detr) and trainJobConfig resolves
trainRecipe.hyperparameters.epochs ?? body.epochs, so any recipe built
from the template silently swallowed the top-level epochs argument:
start_training(model_type=..., epochs=50, hyperparameters={"lr": 2e-4})
trained 100 epochs, not 50 — likewise CLI --epochs + --hyperparameters,
and even epochs + online_augmentation with no hyperparameters at all.
Client-side fix (POST path unchanged): build_train_recipe gains an
epochs kwarg that folds a non-None value into the recipe's
hyperparameters unless the caller already set "epochs" there; threaded
from both template-building call sites (Version.start_training override
path, CLI --hyperparameters path). Override dicts are copied so caller
input is never mutated.
Explicit --train-recipe / train_recipe= stays authoritative; the
start_training docstring and the --train-recipe flag help now state
that a recipe's (dense-filled) epochs takes precedence over the
top-level epochs argument.
Tests: +12 (new tests/util/test_train_recipe.py covering fold /
no-clobber / no-mutation; 3 Version cases incl. augmentation-only +
epochs and body epochs still sent; 1 CLI case asserting the merged
create_training body). Full suite 909 passing; ruff + mypy clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…explicit recipes Addresses two Jarbas review warnings on #510 plus trivia: Non-object JSON flag values (e.g. --hyperparameters '5', --train-recipe '[1]') previously passed the syntax-only parse and either crashed with a raw TypeError in build_train_recipe (after a wasted recipe fetch) or shipped a malformed trainRecipe to the server. _parse_json_flag now requires a JSON object and exits with a structured error before any network call. epochs was still silently ignored when combined with an explicit train_recipe: the server dense-fills recipe hyperparameters, so recipe epochs always beats body epochs, and a template-derived recipe + --epochs 5 smoke run would train the full default epochs at GPU cost. Explicit recipes are now run through the same build_train_recipe fold (setdefault semantics: an epochs set inside the recipe still wins; the fold creates the hyperparameters key when a hand-written recipe omits it). Docstrings and --train-recipe help updated from "recipe epochs takes precedence" to the fold semantics. Trivia: sweep docstring example now imports time (it calls time.sleep); CHANGELOG.md gains the Unreleased entry for the v2 trainings SDK methods, CLI command, and flags (#510). Tests: +7 (util fold-creates-missing-key; Version explicit-recipe fold / recipe-epochs-wins / missing-hyperparameters-key; CLI non-object --hyperparameters and --train-recipe assert structured error with no adapter call, --train-recipe + --epochs asserts merged body). Full suite 916 passing; ruff + mypy clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What does this PR do?
Adds SDK + CLI support for training with a custom
trainRecipe(hyperparameter/augmentation sweeps) against the v2 trainings API.roboflow/adapters/rfapi.py):get_train_recipe(GET.../v2/trainings/recipe?modelType=),create_training(POST.../v2/trainings, returns{"trainingId", ...}),list_version_trainings,get_version_training— same URL/auth/error conventions as the existing train adapters.roboflow/core/version.py):Version.describe_train_recipe(model_type)(schema + ready-to-submit template), non-blockingVersion.start_training(...)(builds a full recipe from the server template whenhyperparameters/online_augmentationare given; mirrorstrain()'s generation-wait + export-ensuring; docstring includes a sweep-loop example),Version.list_trainings(),Version.get_training(). The blockingVersion.train()is untouched.roboflow/util/train_recipe.py):build_train_recipe— shared by SDK and CLI so both submit identical recipes; folds a top-levelepochsinto the recipe's hyperparameters unless explicitly set there (the server prefers the dense-filled recipe epochs over body epochs, so without the fold a caller'sepochs=would be silently ignored).roboflow train recipe -p <project> -v <N> -m <model_type>(prints schema+template JSON) and--hyperparameters '<json>'/--train-recipe '<json>'onroboflow train start(v2 path, prints the new trainingId; clean errors on invalid JSON / conflicting flags).Related Issue(s): Companion to roboflow/roboflow#13699 (the backend describe endpoint — this PR's
describe_train_recipe/--hyperparameterspaths require it; deploy order: platform first, then release this). MCP companion: roboflow/roboflow-mcp#120.Type of Change
Testing
Test details:
+46 tests:
responses-based adapter tests (URLs, query params, conditional camelCase body keys, error raise),Versiontests with patched adapters (template merge, epochs fold incl. no-clobber and aug-only cases, export-ensuring), CLI tests via CliRunner + patched adapters (recipe command happy/error paths,--hyperparametersmerge,--epochsfold, conflicting-flags error). Full suite:python -m unittest→ 909 tests OK.ruff format --check,ruff check,mypy roboflowall clean. CLI smoke-tested via the installed entry point.Checklist
CLI-COMMANDS.mdupdated; docs.roboflow.com CLI reference is a tracked follow-upAdditional Context
Sweep usage the PR enables:
Recipe-based training requires the workspace's online-augmentation training entitlement (403 otherwise). Against a backend without the describe endpoint,
describe_train_recipe/knob kwargs fail with the upstream 404; passing a fulltrain_recipeworks today.🤖 Generated with Claude Code