Skip to content

Commit

Permalink
Add workflow and upgrade SDK to v6.73.178
Browse files Browse the repository at this point in the history
  • Loading branch information
GoldenAnpu committed Sep 5, 2024
1 parent d7fa7c8 commit be70593
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 37 deletions.
4 changes: 2 additions & 2 deletions serve/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"serve"
],
"description": "Deploy model as REST API service",
"docker_image": "supervisely/mmseg:1.3.12",
"instance_version": "6.9.22",
"docker_image": "supervisely/mmseg:1.3.13",
"instance_version": "6.11.10",
"entrypoint": "python -m uvicorn main:m.app --app-dir ./serve/src --host 0.0.0.0 --port 8000 --ws websockets",
"port": 8000,
"task_location": "application_sessions",
Expand Down
2 changes: 1 addition & 1 deletion serve/dev_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# git+https://github.com/supervisely/supervisely.git@some-test-branch

supervisely==6.73.119
supervisely==6.73.178

openmim
ffmpeg-python==0.2.0
Expand Down
3 changes: 3 additions & 0 deletions serve/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
Widget,
)
from supervisely.io.fs import silent_remove
import workflow as w

root_source_path = str(Path(__file__).parents[2])
app_source_path = str(Path(__file__).parents[1])
Expand Down Expand Up @@ -285,6 +286,8 @@ def load_on_device(
]
self._model_meta = sly.ProjectMeta(obj_classes=sly.ObjClassCollection(obj_classes))
print(f"✅ Model has been successfully loaded on {device.upper()} device")
if model_source == "Custom models":
w.workflow_input(self.api, custom_weights_link)

def get_info(self) -> dict:
info = super().get_info()
Expand Down
20 changes: 20 additions & 0 deletions serve/src/workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Description: This file contains functionality for workflow feature

import supervisely as sly


def workflow_input(api: sly.Api, checkpoint_url: str):
try:
node_settings = sly.WorkflowSettings(title="Serve Custom Model")
meta = sly.WorkflowMeta(node_settings=node_settings)
sly.logger.debug(f"Workflow Input: Checkpoint URL - {checkpoint_url}")
if checkpoint_url and api.file.exists(sly.env.team_id(), checkpoint_url):
api.app.workflow.add_input_file(checkpoint_url, model_weight=True, meta=meta)
else:
sly.logger.debug(f"Checkpoint {checkpoint_url} not found in Team Files. Cannot set workflow input")
except Exception as e:
sly.logger.debug(f"Failed to add input to the workflow: {repr(e)}")


def workflow_output(api: sly.Api):
raise NotImplementedError("Method is not implemented yet")
62 changes: 31 additions & 31 deletions train/config.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
{
"name": "Train MMSegmentation",
"type": "app",
"categories": [
"neural network",
"images",
"videos",
"semantic segmentation",
"segmentation & tracking",
"train"
],
"description": "Dashboard to configure, start and monitor training",
"docker_image": "supervisely/mmseg:1.3.12",
"min_instance_version": "6.9.22",
"main_script": "train/src/main.py",
"gui_template": "train/src/gui.html",
"task_location": "workspace_tasks",
"need_gpu": true,
"gpu": "required",
"isolate": true,
"icon": "https://i.imgur.com/GaEFmkH.png",
"icon_cover": true,
"context_menu": {
"target": ["images_project"],
"context_root": "Neural Networks",
"context_category": "MM Segmentation"
},
"poster": "https://user-images.githubusercontent.com/48245050/182847473-9a35f213-c27b-4abd-bd64-c73bf80fb056.jpg",
"community_agent": false,
"license": {
"type": "Apache-2.0"
}
"name": "Train MMSegmentation",
"type": "app",
"categories": [
"neural network",
"images",
"videos",
"semantic segmentation",
"segmentation & tracking",
"train"
],
"description": "Dashboard to configure, start and monitor training",
"docker_image": "supervisely/mmseg:1.3.13",
"min_instance_version": "6.11.10",
"main_script": "train/src/main.py",
"gui_template": "train/src/gui.html",
"task_location": "workspace_tasks",
"need_gpu": true,
"gpu": "required",
"isolate": true,
"icon": "https://i.imgur.com/GaEFmkH.png",
"icon_cover": true,
"context_menu": {
"target": ["images_project"],
"context_root": "Neural Networks",
"context_category": "MM Segmentation"
},
"poster": "https://user-images.githubusercontent.com/48245050/182847473-9a35f213-c27b-4abd-bd64-c73bf80fb056.jpg",
"community_agent": false,
"license": {
"type": "Apache-2.0"
}
}
2 changes: 1 addition & 1 deletion train/dev_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# git+https://github.com/supervisely/supervisely.git@some-test-branch

supervisely==6.73.119
supervisely==6.73.178

openmim
ffmpeg-python==0.2.0
Expand Down
2 changes: 2 additions & 0 deletions train/src/sly_globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,5 @@
shutil.copytree(f"/tmp/mmseg/mmsegmentation-{mmseg_ver}/configs", configs_dir)
models_cnt = len(os.listdir(configs_dir)) - 1
sly.logger.info(f"Found {models_cnt} folders in {configs_dir} directory.")

sly_mmseg_generated_metadata = None # for project Workflow purposes
8 changes: 6 additions & 2 deletions train/src/ui/monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from mmseg.datasets import build_dataset
from mmseg.models import build_segmentor
from init_cfg import init_cfg
import workflow as w

# ! required to be left here despite not being used
import sly_imgaugs
Expand Down Expand Up @@ -216,7 +217,7 @@ def upload_monitor(monitor, api: sly.Api, task_id, progress: sly.Progress):
)

# generate metadata file
g.sly_mmseg.generate_metadata(
g.sly_mmseg_generated_metadata = g.sly_mmseg.generate_metadata(
app_name=g.sly_mmseg.app_name,
task_id=g.task_id,
artifacts_folder=remote_artifacts_dir,
Expand Down Expand Up @@ -347,7 +348,10 @@ def train(api: sly.Api, task_id, context, state, app_logger):
]
g.api.app.set_fields(g.task_id, fields)

# stop application
w.workflow_input(api, g.project_info, state)
w.workflow_output(api, g.sly_mmseg_generated_metadata, state)

# stop application
g.my_app.stop()
except Exception as e:
g.api.app.set_field(task_id, "state.started", False)
Expand Down
81 changes: 81 additions & 0 deletions train/src/workflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Description: This file contains versioning and workflow features

import supervisely as sly

from supervisely.api.file_api import FileInfo

def workflow_input(api: sly.Api, project_info: sly.ProjectInfo, state: dict = None):
try:
if project_info.type != sly.ProjectType.IMAGES.__str__():
sly.logger.info(f"{project_info.type =} is not '{sly.ProjectType.IMAGES.__str__()}'. Project version will not be created.")
project_version_id = None
else:
project_version_id = api.project.version.create(
project_info, "Train MMSegmentation", f"This backup was created automatically by Supervisely before the Train MMSegmentation task with ID: {api.task_id}"
)
except Exception as e:
sly.logger.warning(f"Failed to create a project version: {repr(e)}")
project_version_id = None

try:
file_info = None
if project_version_id is None:
project_version_id = project_info.version.get("id", None) if project_info.version else None
api.app.workflow.add_input_project(project_info.id, version_id=project_version_id)
if state.get("weightsInitialization", None) == "custom":
file_path = state.get("weightsPath", None)
if file_path is None:
sly.logger.debug("Workflow Input: weights file path is not specified. Cannot add input file to the workflow.")
file_info = api.file.get_info_by_path(sly.env.team_id(), file_path)
if file_info is not None:
api.app.workflow.add_input_file(file_info, model_weight=True)
sly.logger.debug(f"Workflow Input: Project ID - {project_info.id}, Project Version ID - {project_version_id}, Input File - {True if file_info else False}")
except Exception as e:
sly.logger.debug(f"Failed to add input to the workflow: {repr(e)}")


def workflow_output(api: sly.Api, mmseg_generated_metadata: dict, state:dict):
try:
checkpoints_list = mmseg_generated_metadata.get("checkpoints", [])
if len(checkpoints_list) == 0:
sly.logger.debug("Workflow Output: No checkpoints found. Cannot set workflow output.")
best_filename_info = None
else:
best_checkpoints = []
new_infos = [FileInfo(*checkpoint) for checkpoint in checkpoints_list]
for info in new_infos:
best_checkpoints.append(info) if "best" in info.name else None
if len(best_checkpoints) > 1:
best_filename_info = sorted(best_checkpoints, key=lambda x: x.name, reverse=True)[0]
else:
best_filename_info = best_checkpoints[0]


module_id = api.task.get_info_by_id(api.task_id).get("meta", {}).get("app", {}).get("id")

if state.get("weightsInitialization", None) == "custom":
node_custom_title = "Train Custom Model"
else:
node_custom_title = None
if best_filename_info:
node_settings = sly.WorkflowSettings(
title=node_custom_title,
url = f"/apps/{module_id}/sessions/{api.task_id}" if module_id else f"apps/sessions/{api.task_id}",
url_title= "Show Results",
)
relation_settings = sly.WorkflowSettings(
title="Checkpoints",
icon="folder",
icon_color = "#FFA500",
icon_bg_color ="#FFE8BE",
url=f"/files/{best_filename_info.id}/true",
url_title = "Open Folder",
)
meta = sly.WorkflowMeta(relation_settings, node_settings)
api.app.workflow.add_output_file(best_filename_info, model_weight=True, meta=meta)
sly.logger.debug(f"Workflow Output: Node custom title - {node_custom_title}, Best filename - {best_filename_info}")
sly.logger.debug(f"Workflow Output: Meta \n {meta.as_dict}")
else:
sly.logger.debug(f"File {best_filename_info} not found in Team Files. Cannot set workflow output.")
except Exception as e:
sly.logger.debug(f"Failed to add output to the workflow: {repr(e)}")

0 comments on commit be70593

Please sign in to comment.