def register_model_from_yaml(file_path: Union[Path, str]): # check if file exist file_path = Path(file_path) assert file_path.exists( ), f'Model definition file at {str(file_path)} does not exist' # read yaml with open(file_path) as f: model_config = yaml.safe_load(f) model_yaml = MLModelFromYaml.parse_obj(model_config) # copy model weight to cache directory model_in_saved_path = model_yaml.saved_path if model_in_saved_path != model_yaml.weight: copy2(model_yaml.weight, model_in_saved_path) # zip weight folder if model_yaml.engine == Engine.TFS: weight_dir = model_yaml.weight make_archive(weight_dir.with_suffix('.zip'), 'zip', weight_dir) model_data = model_yaml.dict(exclude_none=True, exclude={'convert', 'profile'}) model = MLModel.parse_obj(model_data) register_model(model, convert=model_yaml.convert, profile=model_yaml.profile)
def publish( file_or_dir: Optional[Path] = typer.Argument(None, help='Model weight files', exists=True), architecture: Optional[str] = typer.Option(None, '-n', '--name', help='Architecture'), framework: Optional[Framework] = typer.Option(None, '-fw', '--framework', help='Framework'), engine: Optional[Engine] = typer.Option(None, '-e', '--engine', help='Engine'), version: Optional[int] = typer.Option(None, '-v', '--version', min=1, help='Version number'), task: Optional[Task] = typer.Option(None, '-t', '--task', help='Task'), dataset: Optional[str] = typer.Option(None, '-d', '--dataset', help='Dataset name'), metric: Dict[Metric, float] = typer.Option( '{}', help='Metrics in the form of mapping JSON string. The map type is ' '`Dict[types.models.mlmodel.Metric, float]`. An example is \'{"acc": 0.76}.\'', ), inputs: List[IOShape] = typer.Option( [], '-i', '--input', help= 'List of shape definitions for input tensors. An example of one shape definition is ' '\'{"name": "input", "shape": [-1, 3, 224, 224], "dtype": "TYPE_FP32", "format": "FORMAT_NCHW"}\'', ), outputs: List[IOShape] = typer.Option( [], '-o', '--output', help= 'List of shape definitions for output tensors. An example of one shape definition is ' '\'{"name": "output", "shape": [-1, 1000], "dtype": "TYPE_FP32"}\'', ), convert: Optional[bool] = typer.Option( True, '-c', '--convert', is_flag=True, help='Convert the model to other possible format.', ), profile: Optional[bool] = typer.Option( False, '-p', '--profile', is_flag=True, help='Profile the published model(s).', ), yaml_file: Optional[Path] = typer.Option( None, '-f', '--yaml-file', exists=True, file_okay=True, help= 'Path to configuration YAML file. You should either set the `yaml_file` field or fields ' '(`FILE_OR_DIR`, `--name`, `--framework`, `--engine`, `--version`, `--task`, `--dataset`,' '`--metric`, `--input`, `--output`).'), ): meta_info = (file_or_dir, architecture, framework, engine, version, task, dataset, metric, inputs, outputs) # check either using parameters, or using YAML if yaml_file and not any(meta_info): with open(yaml_file) as f: model_config = yaml.safe_load(f) try: model_yaml = MLModelFromYaml.parse_obj(model_config) except ValidationError as exc: typer.echo(exc, err=True, color=True) raise typer.Exit(422) elif not yaml_file and all(meta_info): model_yaml = MLModelFromYaml( weight=file_or_dir, architecture=architecture, framework=framework, engine=engine, version=version, # noqa dataset=dataset, metric=metric, task=task, inputs=inputs, outputs=outputs, convert=convert, profile=profile) else: typer.echo( 'Incorrect parameter, you should set either YAML_FILE, or all of the (FILE_OR_DIR, --name,' '--framework, --engine, --version, --task, --dataset, --metric, --input, --output)' ) raise typer.Exit(422) # build request parameters payload = {'convert': model_yaml.convert, 'profile': model_yaml.profile} data = model_yaml.dict(use_enum_values=True, exclude_none=True, exclude={'convert', 'profile', 'weight'}) form_data = {k: str(v) for k, v in data.items()} file_or_dir = model_yaml.weight # read weight files files = list() key = 'files' try: # read weight file if file_or_dir.is_dir(): for file in filter(Path.is_file, file_or_dir.rglob('*')): name = Path(file).relative_to(file_or_dir.parent) files.append( (key, (str(name), open(file, 'rb'), 'application/example'))) else: files.append( (key, (file_or_dir.name, open(file_or_dir, 'rb'), 'application/example'))) with requests.post( f'{app_settings.api_v1_prefix}/model/', params=payload, data=form_data, files=files, ) as r: typer.echo(r.json(), color=True) finally: for file in files: file[1][1].close()
def convert( id: str = typer.Option(None, '-i', '--id', help='ID of model.'), yaml_file: Optional[Path] = typer. Option( None, '-f', '--yaml-file', exists=True, file_okay=True, help= 'Path to configuration YAML file. You should either set the `yaml_file` field or fields ' '(`FILE_OR_DIR`, `--name`, `--framework`, `--engine`, `--version`, `--task`, `--dataset`,' '`--metric`, `--input`, `--output`).'), register: bool = typer.Option( False, '-r', '--register', is_flag=True, help='register the converted models to modelhub, default false')): model = None if id is None and yaml_file is None: typer.echo( "WARNING: Please assign a way to find the target model! details refer to --help" ) raise RuntimeError if id is not None and yaml_file is not None: typer.echo("WARNING: Do not use -id and -path at the same time!") raise RuntimeError elif id is not None and yaml_file is None: if ModelDB.exists_by_id(id): model = ModelDB.get_by_id(id) else: typer.echo(f"model id: {id} does not exist in modelhub") elif id is None and yaml_file is not None: # get MLModel from yaml file with open(yaml_file) as f: model_config = yaml.safe_load(f) model_yaml = MLModelFromYaml.parse_obj(model_config) model_in_saved_path = model_yaml.saved_path if model_in_saved_path != model_yaml.weight: copy2(model_yaml.weight, model_in_saved_path) if model_yaml.engine == Engine.TFS: weight_dir = model_yaml.weight make_archive(weight_dir.with_suffix('.zip'), 'zip', weight_dir) model_data = model_yaml.dict(exclude_none=True, exclude={'convert', 'profile'}) model = MLModel.parse_obj(model_data) # auto execute all possible convert and return a list of save paths of every converted model generated_dir_list = generate_model_family(model) typer.echo(f"Converted models are save in: {generated_dir_list}") if register: model_data = model.dict( exclude={'weight', 'id', 'model_status', 'engine'}) for model_dir in generated_dir_list: parse_result = parse_path_plain(model_dir) engine = parse_result['engine'] model_cvt = MLModel(**model_data, weight=model_dir, engine=engine, model_status=[ModelStatus.CONVERTED]) ModelDB.save(model_cvt) typer.echo( f"converted {engine} are successfully registered in Modelhub")