From f5c39838423e784791c2bb71916baa4909f1d084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20P=C4=99czek?= Date: Thu, 9 Oct 2025 21:20:57 +0200 Subject: [PATCH 1/4] Add ability to configure model training epochs --- roboflow/__init__.py | 2 +- roboflow/adapters/rfapi.py | 3 +++ roboflow/core/version.py | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/roboflow/__init__.py b/roboflow/__init__.py index a74398da..bde69972 100644 --- a/roboflow/__init__.py +++ b/roboflow/__init__.py @@ -15,7 +15,7 @@ from roboflow.models import CLIPModel, GazeModel # noqa: F401 from roboflow.util.general import write_line -__version__ = "1.2.10" +__version__ = "1.2.11" def check_key(api_key, model, notebook, num_retries=0): diff --git a/roboflow/adapters/rfapi.py b/roboflow/adapters/rfapi.py index 4021122a..ec3558ba 100644 --- a/roboflow/adapters/rfapi.py +++ b/roboflow/adapters/rfapi.py @@ -58,6 +58,7 @@ def start_version_training( speed: Optional[str] = None, checkpoint: Optional[str] = None, model_type: Optional[str] = None, + epochs: Optional[int] = None, ): """ Start a training job for a specific version. @@ -74,6 +75,8 @@ def start_version_training( if model_type is not None: # API expects camelCase data["modelType"] = model_type + if epochs is not None: + data["epochs"] = epochs response = requests.post(url, json=data) if not response.ok: diff --git a/roboflow/core/version.py b/roboflow/core/version.py index ad321074..cdf4543f 100644 --- a/roboflow/core/version.py +++ b/roboflow/core/version.py @@ -296,7 +296,7 @@ def export(self, model_format=None) -> bool | None: else: raise RuntimeError(f"Unexpected export {export_info}") - def train(self, speed=None, model_type=None, checkpoint=None, plot_in_notebook=False) -> InferenceModel: + def train(self, speed=None, model_type=None, checkpoint=None, plot_in_notebook=False, epochs=None) -> InferenceModel: """ Ask the Roboflow API to train a previously exported version's dataset. @@ -304,6 +304,7 @@ def train(self, speed=None, model_type=None, checkpoint=None, plot_in_notebook=F speed: Whether to train quickly or accurately. Note: accurate training is a paid feature. Default speed is `fast`. model_type: The type of model to train. Default depends on kind of project. It takes precedence over speed. You can check the list of model ids by sending an invalid parameter in this argument. checkpoint: A string representing the checkpoint to use while training + epochs: Number of epochs to train the model plot: Whether to plot the training results. Default is `False`. Returns: @@ -336,6 +337,7 @@ def train(self, speed=None, model_type=None, checkpoint=None, plot_in_notebook=F speed=payload_speed, checkpoint=payload_checkpoint, model_type=payload_model_type, + epochs=epochs, ) status = "training" From b8c00a720289dae973a775995b55dd0cfbfb607a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:21:54 +0000 Subject: [PATCH 2/4] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto=20?= =?UTF-8?q?format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roboflow/core/version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/roboflow/core/version.py b/roboflow/core/version.py index cdf4543f..35d42391 100644 --- a/roboflow/core/version.py +++ b/roboflow/core/version.py @@ -296,7 +296,9 @@ def export(self, model_format=None) -> bool | None: else: raise RuntimeError(f"Unexpected export {export_info}") - def train(self, speed=None, model_type=None, checkpoint=None, plot_in_notebook=False, epochs=None) -> InferenceModel: + def train( + self, speed=None, model_type=None, checkpoint=None, plot_in_notebook=False, epochs=None + ) -> InferenceModel: """ Ask the Roboflow API to train a previously exported version's dataset. From a344f689435c98941fa0ed8086c4166a06cfafb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20P=C4=99czek?= Date: Thu, 9 Oct 2025 21:27:29 +0200 Subject: [PATCH 3/4] Make linters happy --- roboflow/adapters/rfapi.py | 4 ++-- roboflow/core/version.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/roboflow/adapters/rfapi.py b/roboflow/adapters/rfapi.py index ec3558ba..eebfd92a 100644 --- a/roboflow/adapters/rfapi.py +++ b/roboflow/adapters/rfapi.py @@ -1,7 +1,7 @@ import json import os import urllib -from typing import List, Optional +from typing import List, Optional, Dict, Union import requests from requests.exceptions import RequestException @@ -67,7 +67,7 @@ def start_version_training( """ url = f"{API_URL}/{workspace_url}/{project_url}/{version}/train?api_key={api_key}&nocache=true" - data = {} + data: Dict[str, Union[str, int]] = {} if speed is not None: data["speed"] = speed if checkpoint is not None: diff --git a/roboflow/core/version.py b/roboflow/core/version.py index 35d42391..12d50320 100644 --- a/roboflow/core/version.py +++ b/roboflow/core/version.py @@ -307,7 +307,7 @@ def train( model_type: The type of model to train. Default depends on kind of project. It takes precedence over speed. You can check the list of model ids by sending an invalid parameter in this argument. checkpoint: A string representing the checkpoint to use while training epochs: Number of epochs to train the model - plot: Whether to plot the training results. Default is `False`. + plot_in_notebook: Whether to plot the training results. Default is `False`. Returns: An instance of the trained model class @@ -389,7 +389,7 @@ def live_plot(epochs, mAP, loss, title=""): write_line(line="Training failed") break - epochs: Union[np.ndarray, list] + epoch_ids: Union[np.ndarray, list] mAP: Union[np.ndarray, list] loss: Union[np.ndarray, list] @@ -397,7 +397,7 @@ def live_plot(epochs, mAP, loss, title=""): import numpy as np # training has started - epochs = np.array([int(epoch["epoch"]) for epoch in models["roboflow-train"]["epochs"]]) + epoch_ids = np.array([int(epoch["epoch"]) for epoch in models["roboflow-train"]["epochs"]]) mAP = np.array([float(epoch["mAP"]) for epoch in models["roboflow-train"]["epochs"]]) loss = np.array( [ @@ -414,23 +414,23 @@ def live_plot(epochs, mAP, loss, title=""): num_machine_spin_dots = ["."] title = "Training Machine Spinning Up" + "".join(num_machine_spin_dots) - epochs = [] + epoch_ids = [] mAP = [] loss = [] - if (len(epochs) > len(previous_epochs)) or (len(epochs) == 0): + if (len(epoch_ids) > len(previous_epochs)) or (len(epoch_ids) == 0): if plot_in_notebook: - live_plot(epochs, mAP, loss, title) + live_plot(epoch_ids, mAP, loss, title) else: - if len(epochs) > 0: + if len(epoch_ids) > 0: title = ( - title + ": Epoch: " + str(epochs[-1]) + " mAP: " + str(mAP[-1]) + " loss: " + str(loss[-1]) + title + ": Epoch: " + str(epoch_ids[-1]) + " mAP: " + str(mAP[-1]) + " loss: " + str(loss[-1]) ) if not first_graph_write: write_line(title) first_graph_write = True - previous_epochs = copy.deepcopy(epochs) + previous_epochs = copy.deepcopy(epoch_ids) time.sleep(5) From 2f8cd115ed56c5a784cd77a1f9329adaf2e3502d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:27:41 +0000 Subject: [PATCH 4/4] =?UTF-8?q?fix(pre=5Fcommit):=20=F0=9F=8E=A8=20auto=20?= =?UTF-8?q?format=20pre-commit=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roboflow/adapters/rfapi.py | 2 +- roboflow/core/version.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/roboflow/adapters/rfapi.py b/roboflow/adapters/rfapi.py index eebfd92a..a522429e 100644 --- a/roboflow/adapters/rfapi.py +++ b/roboflow/adapters/rfapi.py @@ -1,7 +1,7 @@ import json import os import urllib -from typing import List, Optional, Dict, Union +from typing import Dict, List, Optional, Union import requests from requests.exceptions import RequestException diff --git a/roboflow/core/version.py b/roboflow/core/version.py index 12d50320..bd6e035c 100644 --- a/roboflow/core/version.py +++ b/roboflow/core/version.py @@ -424,7 +424,13 @@ def live_plot(epochs, mAP, loss, title=""): else: if len(epoch_ids) > 0: title = ( - title + ": Epoch: " + str(epoch_ids[-1]) + " mAP: " + str(mAP[-1]) + " loss: " + str(loss[-1]) + title + + ": Epoch: " + + str(epoch_ids[-1]) + + " mAP: " + + str(mAP[-1]) + + " loss: " + + str(loss[-1]) ) if not first_graph_write: write_line(title)