Skip to content

Commit fa9547a

Browse files
committed
Merge remote-tracking branch 'origin/main' into uploadrfdetr
2 parents 9a19ac2 + 7476e72 commit fa9547a

File tree

5 files changed

+140
-20
lines changed

5 files changed

+140
-20
lines changed

.github/workflows/publish.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,35 @@ jobs:
3030
PYPI_TEST_PASSWORD: ${{ secrets.PYPI_TEST_PASSWORD }}
3131
run: |
3232
make publish -e PYPI_USERNAME=$PYPI_USERNAME -e PYPI_PASSWORD=$PYPI_PASSWORD -e PYPI_TEST_PASSWORD=$PYPI_TEST_PASSWORD
33+
34+
deploy-docs:
35+
needs: build
36+
runs-on: ubuntu-latest
37+
permissions:
38+
contents: write
39+
steps:
40+
- name: 🛎️ Checkout
41+
uses: actions/checkout@v4
42+
with:
43+
fetch-depth: 0
44+
45+
- name: 🐍 Set up Python
46+
uses: actions/setup-python@v5
47+
with:
48+
python-version: '3.8'
49+
50+
- name: 📚 Install MkDocs and dependencies
51+
run: |
52+
python -m pip install --upgrade pip
53+
pip install mkdocs-material mkdocstrings mkdocstrings[python]
54+
pip install ".[dev]"
55+
56+
- name: 🏗️ Build documentation
57+
run: |
58+
mkdocs build
59+
60+
- name: 🚀 Deploy to GitHub Pages
61+
uses: peaceiris/actions-gh-pages@v3
62+
with:
63+
github_token: ${{ secrets.GITHUB_TOKEN }}
64+
publish_dir: ./site

roboflow/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from roboflow.models import CLIPModel, GazeModel # noqa: F401
1616
from roboflow.util.general import write_line
1717

18-
__version__ = "1.1.58"
18+
__version__ = "1.1.60"
1919

2020

2121
def check_key(api_key, model, notebook, num_retries=0):

roboflow/adapters/deploymentapi.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ class DeploymentApiError(Exception):
99
pass
1010

1111

12-
def add_deployment(api_key, machine_type, duration, delete_on_expiration, deployment_name, inference_version):
12+
def add_deployment(
13+
api_key, creator_email, machine_type, duration, delete_on_expiration, deployment_name, inference_version
14+
):
1315
url = f"{DEDICATED_DEPLOYMENT_URL}/add"
1416
params = {
1517
"api_key": api_key,
18+
"creator_email": creator_email,
1619
# "security_level": security_level,
1720
"duration": duration,
1821
"delete_on_expiration": delete_on_expiration,
@@ -69,6 +72,22 @@ def get_deployment_usage(api_key, deployment_name, from_timestamp, to_timestamp)
6972
return response.status_code, response.json()
7073

7174

75+
def pause_deployment(api_key, deployment_name):
76+
url = f"{DEDICATED_DEPLOYMENT_URL}/pause"
77+
response = requests.post(url, json={"api_key": api_key, "deployment_name": deployment_name})
78+
if response.status_code != 200:
79+
return response.status_code, response.text
80+
return response.status_code, response.json()
81+
82+
83+
def resume_deployment(api_key, deployment_name):
84+
url = f"{DEDICATED_DEPLOYMENT_URL}/resume"
85+
response = requests.post(url, json={"api_key": api_key, "deployment_name": deployment_name})
86+
if response.status_code != 200:
87+
return response.status_code, response.text
88+
return response.status_code, response.json()
89+
90+
7291
def delete_deployment(api_key, deployment_name):
7392
url = f"{DEDICATED_DEPLOYMENT_URL}/delete"
7493
response = requests.post(url, json={"api_key": api_key, "deployment_name": deployment_name})

roboflow/deployment.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def add_deployment_parser(subparsers):
6161
deployment_usage_deployment_parser = deployment_subparsers.add_parser(
6262
"usage_deployment", help="get usage of a specific dedicated deployments"
6363
)
64+
deployment_pause_parser = deployment_subparsers.add_parser("pause", help="pause a dedicated deployment")
65+
deployment_resume_parser = deployment_subparsers.add_parser("resume", help="resume a dedicated deployment")
6466
deployment_delete_parser = deployment_subparsers.add_parser("delete", help="delete a dedicated deployment")
6567
deployment_log_parser = deployment_subparsers.add_parser("log", help="show log info for a dedicated deployment")
6668

@@ -77,7 +79,13 @@ def add_deployment_parser(subparsers):
7779
# "-s", "--security_level", help="security level (protected)", default="protected"
7880
# )
7981
deployment_add_parser.add_argument(
80-
"-m", "--machine_type", help="machine type, run `roboflow deployment machine_type` to see available options"
82+
"-m",
83+
"--machine_type",
84+
help="machine type, run `roboflow deployment machine_type` to see available options",
85+
required=True,
86+
)
87+
deployment_add_parser.add_argument(
88+
"-e", "--creator_email", help="your email address (must be added to the workspace)", required=True
8189
)
8290
deployment_add_parser.add_argument(
8391
"-t",
@@ -87,7 +95,7 @@ def add_deployment_parser(subparsers):
8795
default=3,
8896
)
8997
deployment_add_parser.add_argument(
90-
"-e", "--no_delete_on_expiration", help="keep when expired (default: False)", action="store_true"
98+
"-nodel", "--no_delete_on_expiration", help="keep when expired (default: False)", action="store_true"
9199
)
92100
deployment_add_parser.add_argument(
93101
"-v",
@@ -128,6 +136,14 @@ def add_deployment_parser(subparsers):
128136
"-t", "--to_timestamp", help="end time stamp in ISO8601 format (YYYY-MM-DD HH:MM:SS)", default=None
129137
)
130138

139+
deployment_pause_parser.set_defaults(func=pause_deployment)
140+
deployment_pause_parser.add_argument("-a", "--api_key", help="api key")
141+
deployment_pause_parser.add_argument("deployment_name", help="deployment name")
142+
143+
deployment_resume_parser.set_defaults(func=resume_deployment)
144+
deployment_resume_parser.add_argument("-a", "--api_key", help="api key")
145+
deployment_resume_parser.add_argument("deployment_name", help="deployment name")
146+
131147
deployment_delete_parser.set_defaults(func=delete_deployment)
132148
deployment_delete_parser.add_argument("-a", "--api_key", help="api key")
133149
deployment_delete_parser.add_argument("deployment_name", help="deployment name")
@@ -163,6 +179,7 @@ def add_deployment(args):
163179
exit(1)
164180
status_code, msg = deploymentapi.add_deployment(
165181
api_key,
182+
args.creator_email,
166183
# args.security_level,
167184
args.machine_type,
168185
args.duration,
@@ -241,6 +258,30 @@ def get_deployment_usage(args):
241258
print(json.dumps(msg, indent=2))
242259

243260

261+
def pause_deployment(args):
262+
api_key = args.api_key or load_roboflow_api_key(None)
263+
if api_key is None:
264+
print("Please provide an api key")
265+
exit(1)
266+
status_code, msg = deploymentapi.pause_deployment(api_key, args.deployment_name)
267+
if status_code != 200:
268+
print(f"{status_code}: {msg}")
269+
exit(status_code)
270+
print(json.dumps(msg, indent=2))
271+
272+
273+
def resume_deployment(args):
274+
api_key = args.api_key or load_roboflow_api_key(None)
275+
if api_key is None:
276+
print("Please provide an api key")
277+
exit(1)
278+
status_code, msg = deploymentapi.resume_deployment(api_key, args.deployment_name)
279+
if status_code != 200:
280+
print(f"{status_code}: {msg}")
281+
exit(status_code)
282+
print(json.dumps(msg, indent=2))
283+
284+
244285
def delete_deployment(args):
245286
api_key = args.api_key or load_roboflow_api_key(None)
246287
if api_key is None:

roboflow/util/model_processor.py

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -114,29 +114,56 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
114114

115115
print_warn_for_wrong_dependencies_versions([("ultralytics", ">=", "8.3.0")], ask_to_continue=True)
116116

117-
model = torch.load(os.path.join(model_path, filename), map_location="cpu")
117+
elif "yolov12" in model_type:
118+
try:
119+
import torch
120+
import ultralytics
121+
122+
except ImportError:
123+
raise RuntimeError(
124+
"The ultralytics python package is required to deploy yolov12"
125+
" models. Please install it from `https://github.com/sunsmarterjie/yolov12`"
126+
)
127+
128+
print(
129+
"\n!!! ATTENTION !!!\n"
130+
"Model must be trained and uploaded using ultralytics from https://github.com/sunsmarterjie/yolov12\n"
131+
"or through the Roboflow platform\n"
132+
"!!! ATTENTION !!!\n"
133+
)
134+
135+
print_warn_for_wrong_dependencies_versions([("ultralytics", "==", "8.3.63")], ask_to_continue=True)
118136

119-
if isinstance(model["model"].names, list):
120-
class_names = model["model"].names
137+
model = torch.load(os.path.join(model_path, filename), weights_only=False)
138+
139+
model_instance = model["model"] if "model" in model and model["model"] is not None else model["ema"]
140+
141+
if isinstance(model_instance.names, list):
142+
class_names = model_instance.names
121143
else:
122144
class_names = []
123-
for i, val in enumerate(model["model"].names):
124-
class_names.append((val, model["model"].names[val]))
145+
for i, val in enumerate(model_instance.names):
146+
class_names.append((val, model_instance.names[val]))
125147
class_names.sort(key=lambda x: x[0])
126148
class_names = [x[1] for x in class_names]
127149

128-
if "yolov8" in model_type or "yolov10" in model_type or "yolov11" in model_type:
150+
if "yolov8" in model_type or "yolov10" in model_type or "yolov11" in model_type or "yolov12" in model_type:
129151
# try except for backwards compatibility with older versions of ultralytics
130-
if "-cls" in model_type or model_type.startswith("yolov10") or model_type.startswith("yolov11"):
131-
nc = model["model"].yaml["nc"]
152+
if (
153+
"-cls" in model_type
154+
or model_type.startswith("yolov10")
155+
or model_type.startswith("yolov11")
156+
or model_type.startswith("yolov12")
157+
):
158+
nc = model_instance.yaml["nc"]
132159
args = model["train_args"]
133160
else:
134-
nc = model["model"].nc
135-
args = model["model"].args
161+
nc = model_instance.nc
162+
args = model_instance.args
136163
try:
137164
model_artifacts = {
138165
"names": class_names,
139-
"yaml": model["model"].yaml,
166+
"yaml": model_instance.yaml,
140167
"nc": nc,
141168
"args": {k: val for k, val in args.items() if ((k == "model") or (k == "imgsz") or (k == "batch"))},
142169
"ultralytics_version": ultralytics.__version__,
@@ -145,7 +172,7 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
145172
except Exception:
146173
model_artifacts = {
147174
"names": class_names,
148-
"yaml": model["model"].yaml,
175+
"yaml": model_instance.yaml,
149176
"nc": nc,
150177
"args": {
151178
k: val for k, val in args.__dict__.items() if ((k == "model") or (k == "imgsz") or (k == "batch"))
@@ -161,20 +188,20 @@ def _process_yolo(model_type: str, model_path: str, filename: str) -> str:
161188

162189
model_artifacts = {
163190
"names": class_names,
164-
"nc": model["model"].nc,
191+
"nc": model_instance.nc,
165192
"args": {
166193
"imgsz": opts["imgsz"] if "imgsz" in opts else opts["img_size"],
167194
"batch": opts["batch_size"],
168195
},
169196
"model_type": model_type,
170197
}
171-
if hasattr(model["model"], "yaml"):
172-
model_artifacts["yaml"] = model["model"].yaml
198+
if hasattr(model_instance, "yaml"):
199+
model_artifacts["yaml"] = model_instance.yaml
173200

174201
with open(os.path.join(model_path, "model_artifacts.json"), "w") as fp:
175202
json.dump(model_artifacts, fp)
176203

177-
torch.save(model["model"].state_dict(), os.path.join(model_path, "state_dict.pt"))
204+
torch.save(model_instance.state_dict(), os.path.join(model_path, "state_dict.pt"))
178205

179206
list_files = [
180207
"results.csv",
@@ -300,6 +327,7 @@ def get_classnames_txt_for_rfdetr(model_path: str, pt_file: str):
300327
f"please create a class_names.txt file in the model path with the class names in new lines in the order of the classes in the model.\n"
301328
)
302329

330+
303331
def maybe_prepend_dummy_class(class_name_file: str):
304332
with open(class_name_file, "r") as f:
305333
class_names = f.readlines()

0 commit comments

Comments
 (0)