Skip to content
Merged
2 changes: 1 addition & 1 deletion roboflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from roboflow.models import CLIPModel, GazeModel # noqa: F401
from roboflow.util.general import write_line

__version__ = "1.1.56"
__version__ = "1.1.57"


def check_key(api_key, model, notebook, num_retries=0):
Expand Down
3 changes: 2 additions & 1 deletion roboflow/core/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from roboflow.util.annotations import amend_data_yaml
from roboflow.util.general import write_line
from roboflow.util.model_processor import process
from roboflow.util.versions import get_wrong_dependencies_versions
from roboflow.util.versions import get_wrong_dependencies_versions, normalize_yolo_model_type

if TYPE_CHECKING:
import numpy as np
Expand Down Expand Up @@ -477,6 +477,7 @@ def deploy(self, model_type: str, model_path: str, filename: str = "weights/best
model_path (str): File path to the model weights to be uploaded.
filename (str, optional): The name of the weights file. Defaults to "weights/best.pt".
"""
model_type = normalize_yolo_model_type(model_type)
zip_file_name = process(model_type, model_path, filename)

if zip_file_name is None:
Expand Down
2 changes: 2 additions & 0 deletions roboflow/core/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from roboflow.util.image_utils import load_labelmap
from roboflow.util.model_processor import process
from roboflow.util.two_stage_utils import ocr_infer
from roboflow.util.versions import normalize_yolo_model_type


class Workspace:
Expand Down Expand Up @@ -596,6 +597,7 @@ def deploy_model(
if project_id not in user_projects:
raise ValueError(f"Project {project_id} is not accessible in this workspace")

model_type = normalize_yolo_model_type(model_type)
zip_file_name = process(model_type, model_path, filename)

if zip_file_name is None:
Expand Down
3 changes: 2 additions & 1 deletion roboflow/roboflowpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ def upload_model(args):

if args.version_number is not None:
# Deploy to specific version
project = workspace.project(args.project)
project_id = args.project[0] if isinstance(args.project, list) else args.project
project = workspace.project(project_id)
version = project.version(args.version_number)
version.deploy(str(args.model_type), str(args.model_path), str(args.filename))
else:
Expand Down
51 changes: 46 additions & 5 deletions roboflow/util/model_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,18 @@ def process(model_type: str, model_path: str, filename: str) -> str:


def _get_processor_function(model_type: str) -> Callable:
if model_type.startswith("yolo11"):
model_type = model_type.replace("yolo11", "yolov11")

supported_models = [
"yolov5",
"yolov7-seg",
"yolov8",
"yolov9",
"yolov10",
"yolov11",
"yolov12",
"yolonas",
"paligemma",
"paligemma2",
"yolov10",
"florence-2",
"yolov11",
]

if not any(supported_model in model_type for supported_model in supported_models):
Expand Down Expand Up @@ -59,6 +57,9 @@ def _get_processor_function(model_type: str) -> Callable:
if "yolonas" in model_type:
return _process_yolonas

if "yolov12" in model_type:
return _process_yolov12

return _process_yolo


Expand Down Expand Up @@ -195,6 +196,46 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
return zip_file_name


def _process_yolov12(model_type: str, model_path: str, filename: str) -> str:
# For YOLOv12, since it uses a special Ultralytics version,
# state dict extraction and model artifacts are handled during model conversion

print(
"Note: Model must be trained using ultralytics from https://github.com/sunsmarterjie/yolov12 "
"or through the Roboflow platform"
)

# Check if model_path exists
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model path {model_path} does not exist.")

# Find any .pt file in model path
model_files = os.listdir(model_path)
pt_file = next((f for f in model_files if f.endswith(".pt")), None)

if pt_file is None:
raise RuntimeError("No .pt model file found in the provided path")

# Copy the .pt file to weights.pt if not already named weights.pt
if pt_file != "weights.pt":
shutil.copy(os.path.join(model_path, pt_file), os.path.join(model_path, "weights.pt"))

required_files = ["weights.pt"]

optional_files = ["results.csv", "results.png", "model_artifacts.json"]

zip_file_name = "roboflow_deploy.zip"
with zipfile.ZipFile(os.path.join(model_path, zip_file_name), "w") as zipMe:
for file in required_files:
zipMe.write(os.path.join(model_path, file), arcname=file, compress_type=zipfile.ZIP_DEFLATED)

for file in optional_files:
if os.path.exists(os.path.join(model_path, file)):
zipMe.write(os.path.join(model_path, file), arcname=file, compress_type=zipfile.ZIP_DEFLATED)

return zip_file_name


def _process_huggingface(
model_type: str, model_path: str, filename: str = "fine-tuned-paligemma-3b-pt-224.f16.npz"
) -> str:
Expand Down
6 changes: 6 additions & 0 deletions roboflow/util/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,9 @@ def _wrapper(*args, **kwargs):
return _wrapper

return _inner


def normalize_yolo_model_type(model_type: str) -> str:
model_type = model_type.replace("yolo11", "yolov11")
model_type = model_type.replace("yolo12", "yolov12")
return model_type