From d395e9abc27d08671a823ab1d1e597b939003420 Mon Sep 17 00:00:00 2001 From: "wenmeng.zwm" Date: Tue, 7 Jun 2022 14:49:57 +0800 Subject: [PATCH 01/13] [to #42281043] support kwargs in pipeline Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8949062 * support kwargs in pipeline * update develop doc with CR instruction --- docs/source/develop.md | 113 +++++++++++++++++++++++----------- maas_lib/pipelines/builder.py | 4 +- 2 files changed, 80 insertions(+), 37 deletions(-) diff --git a/docs/source/develop.md b/docs/source/develop.md index 4d0812ae..0d4f7f26 100644 --- a/docs/source/develop.md +++ b/docs/source/develop.md @@ -10,39 +10,80 @@ We use the following toolsseed isortseed isortseed isort for linting and formatt Style configurations of yapf and isort can be found in [setup.cfg](../../setup.cfg). We use [pre-commit hook](https://pre-commit.com/) that checks and formats for `flake8`, `yapf`, `seed-isort-config`, `isort`, `trailing whitespaces`, - fixes `end-of-files`, sorts `requirments.txt` automatically on every commit. - The config for a pre-commit hook is stored in [.pre-commit-config](../../.pre-commit-config.yaml). - After you clone the repository, you will need to install initialize pre-commit hook. - ```bash - pip install -r requirements/tests.txt - ``` - From the repository folder - ```bash - pre-commit install - ``` - - After this on every commit check code linters and formatter will be enforced. - - If you want to use pre-commit to check all the files, you can run - ```bash - pre-commit run --all-files - ``` - - If you only want to format and lint your code, you can run - ```bash - make linter - ``` - - ## 2. Test - ### 2.1 Unit test - ```bash - make test - ``` - - ### 2.2 Test data - TODO - - ## 3. Build pip package - ```bash - make whl - ``` +fixes `end-of-files`, sorts `requirments.txt` automatically on every commit. +The config for a pre-commit hook is stored in [.pre-commit-config](../../.pre-commit-config.yaml). +After you clone the repository, you will need to install initialize pre-commit hook. +```bash +pip install -r requirements/tests.txt +``` +From the repository folder +```bash +pre-commit install +``` + +After this on every commit check code linters and formatter will be enforced. + +If you want to use pre-commit to check all the files, you can run +```bash +pre-commit run --all-files +``` + +If you only want to format and lint your code, you can run +```bash +make linter +``` + +## 2. Test +### 2.1 Unit test +```bash +make test +``` + +### 2.2 Test data +TODO + +## Code Review + +1. Run following command to create an aone CR, replace `TARGET_BRANCH` and `CR_NAME` with the one you want. + ```shell + git push origin HEAD:refs/for/TARGET_BRANCH/CR_NAME + ``` + + Please refer to [https://yuque.antfin.com/aone/platform/lcg8yr](https://yuque.antfin.com/aone/platform/lcg8yr) for more details. + + The following output is expected. + ```shell + Counting objects: 5, done. + Delta compression using up to 96 threads. + Compressing objects: 100% (5/5), done. + Writing objects: 100% (5/5), 543 bytes | 0 bytes/s, done. + Total 5 (delta 4), reused 0 (delta 0) + remote: +------------------------------------------------------------------------+ + remote: | Merge Request #8949062 was created or updated. | + remote: | View merge request at URL: | + remote: | https://code.aone.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8949062 | + remote: +------------------------------------------------------------------------+ + To git@gitlab.alibaba-inc.com:Ali-MaaS/MaaS-lib.git + * [new branch] HEAD -> refs/for/master/support_kwargs_pipeline + ``` + +2. Open the remote url `https://code.aone.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/ID` and edit the title of CR with following format before merging your code: + * Feature + ```shell + [to #AONE_ID] feat: commit title + * commit msg1 + * commit msg2 + ``` + * Bugfix + ```shell + [to #AONE_ID] fix: commit title + * commit msg1 + * commit msg2 + ``` + + + +## Build pip package +```bash +make whl +``` diff --git a/maas_lib/pipelines/builder.py b/maas_lib/pipelines/builder.py index 703dd33f..acaccf05 100644 --- a/maas_lib/pipelines/builder.py +++ b/maas_lib/pipelines/builder.py @@ -67,10 +67,12 @@ def pipeline(task: str = None, if pipeline_name is None: # get default pipeline for this task - assert task in PIPELINES.modules, f'No pipeline is registerd for Task {task}' + assert task in PIPELINES.modules, f'No pipeline is registered for Task {task}' pipeline_name = get_default_pipeline(task) cfg = ConfigDict(type=pipeline_name) + if kwargs: + cfg.update(kwargs) if model: assert isinstance(model, (str, Model)), \ From e075ad2245c335aec93c6852d0f89cb88dab8c38 Mon Sep 17 00:00:00 2001 From: "yingda.chen" Date: Wed, 8 Jun 2022 11:29:25 +0800 Subject: [PATCH 02/13] [to #42322515]support plain pipeline for bert Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8945177 * support plain pipeline for bert --- .../nlp/sequence_classification_model.py | 2 +- .../nlp/sequence_classification_pipeline.py | 23 ++++++++++++++----- tests/pipelines/test_text_classification.py | 20 ++++++++++++---- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/maas_lib/models/nlp/sequence_classification_model.py b/maas_lib/models/nlp/sequence_classification_model.py index d29587a0..f77b0fbc 100644 --- a/maas_lib/models/nlp/sequence_classification_model.py +++ b/maas_lib/models/nlp/sequence_classification_model.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Dict import numpy as np diff --git a/maas_lib/pipelines/nlp/sequence_classification_pipeline.py b/maas_lib/pipelines/nlp/sequence_classification_pipeline.py index f3b20f95..9300035d 100644 --- a/maas_lib/pipelines/nlp/sequence_classification_pipeline.py +++ b/maas_lib/pipelines/nlp/sequence_classification_pipeline.py @@ -1,6 +1,6 @@ import os import uuid -from typing import Any, Dict +from typing import Any, Dict, Union import json import numpy as np @@ -8,6 +8,7 @@ import numpy as np from maas_lib.models.nlp import SequenceClassificationModel from maas_lib.preprocessors import SequenceClassificationPreprocessor from maas_lib.utils.constant import Tasks +from ...models import Model from ..base import Input, Pipeline from ..builder import PIPELINES @@ -18,19 +19,29 @@ __all__ = ['SequenceClassificationPipeline'] Tasks.text_classification, module_name=r'bert-sentiment-analysis') class SequenceClassificationPipeline(Pipeline): - def __init__(self, model: SequenceClassificationModel, - preprocessor: SequenceClassificationPreprocessor, **kwargs): + def __init__(self, + model: Union[SequenceClassificationModel, str], + preprocessor: SequenceClassificationPreprocessor = None, + **kwargs): """use `model` and `preprocessor` to create a nlp text classification pipeline for prediction Args: model (SequenceClassificationModel): a model instance preprocessor (SequenceClassificationPreprocessor): a preprocessor instance """ - - super().__init__(model=model, preprocessor=preprocessor, **kwargs) + sc_model = model if isinstance( + model, + SequenceClassificationModel) else Model.from_pretrained(model) + if preprocessor is None: + preprocessor = SequenceClassificationPreprocessor( + sc_model.model_dir, + first_sequence='sentence', + second_sequence=None) + super().__init__(model=sc_model, preprocessor=preprocessor, **kwargs) from easynlp.utils import io - self.label_path = os.path.join(model.model_dir, 'label_mapping.json') + self.label_path = os.path.join(sc_model.model_dir, + 'label_mapping.json') with io.open(self.label_path) as f: self.label_mapping = json.load(f) self.label_id_to_name = { diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index 45b584af..080622d3 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -29,6 +29,12 @@ class SequenceClassificationTest(unittest.TestCase): print(data) + def printDataset(self, dataset: PyDataset): + for i, r in enumerate(dataset): + if i > 10: + break + print(r) + def test_run(self): model_url = 'https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com' \ '/release/easynlp_modelzoo/alibaba-pai/bert-base-sst2.zip' @@ -53,7 +59,7 @@ class SequenceClassificationTest(unittest.TestCase): Tasks.text_classification, model=model, preprocessor=preprocessor) print(pipeline2('Hello world!')) - def test_run_modelhub(self): + def test_run_with_model_from_modelhub(self): model = Model.from_pretrained('damo/bert-base-sst2') preprocessor = SequenceClassificationPreprocessor( model.model_dir, first_sequence='sentence', second_sequence=None) @@ -63,6 +69,13 @@ class SequenceClassificationTest(unittest.TestCase): preprocessor=preprocessor) self.predict(pipeline_ins) + def test_run_with_model_name(self): + text_classification = pipeline( + task=Tasks.text_classification, model='damo/bert-base-sst2') + result = text_classification( + PyDataset.load('glue', name='sst2', target='sentence')) + self.printDataset(result) + def test_run_with_dataset(self): model = Model.from_pretrained('damo/bert-base-sst2') preprocessor = SequenceClassificationPreprocessor( @@ -74,10 +87,7 @@ class SequenceClassificationTest(unittest.TestCase): # TODO: rename parameter as dataset_name and subset_name dataset = PyDataset.load('glue', name='sst2', target='sentence') result = text_classification(dataset) - for i, r in enumerate(result): - if i > 10: - break - print(r) + self.printDataset(result) if __name__ == '__main__': From d6868ddffe32c373c08cc781f4c37e3eea9a99ca Mon Sep 17 00:00:00 2001 From: "yingda.chen" Date: Wed, 8 Jun 2022 14:22:23 +0800 Subject: [PATCH 03/13] [to #42323743] retain local cached model files by default Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8963687 --- maas_lib/models/base.py | 6 ++++-- maas_lib/pipelines/base.py | 13 ++++++++----- maas_lib/pipelines/util.py | 11 +++++++++++ tests/pipelines/test_image_matting.py | 19 +++++++++++++------ tests/pipelines/test_text_classification.py | 19 ++++++++++++++----- 5 files changed, 50 insertions(+), 18 deletions(-) diff --git a/maas_lib/models/base.py b/maas_lib/models/base.py index cc6c4ec8..677a136a 100644 --- a/maas_lib/models/base.py +++ b/maas_lib/models/base.py @@ -8,6 +8,7 @@ from maas_hub.file_download import model_file_download from maas_hub.snapshot_download import snapshot_download from maas_lib.models.builder import build_model +from maas_lib.pipelines import util from maas_lib.utils.config import Config from maas_lib.utils.constant import CONFIGFILE @@ -39,8 +40,9 @@ class Model(ABC): if osp.exists(model_name_or_path): local_model_dir = model_name_or_path else: - - local_model_dir = snapshot_download(model_name_or_path) + cache_path = util.get_model_cache_dir(model_name_or_path) + local_model_dir = cache_path if osp.exists( + cache_path) else snapshot_download(model_name_or_path) # else: # raise ValueError( # 'Remote model repo {model_name_or_path} does not exists') diff --git a/maas_lib/pipelines/base.py b/maas_lib/pipelines/base.py index 240dc140..3b1103f6 100644 --- a/maas_lib/pipelines/base.py +++ b/maas_lib/pipelines/base.py @@ -2,16 +2,15 @@ import os.path as osp from abc import ABC, abstractmethod -from multiprocessing.sharedctypes import Value from typing import Any, Dict, Generator, List, Tuple, Union from ali_maas_datasets import PyDataset from maas_hub.snapshot_download import snapshot_download from maas_lib.models import Model +from maas_lib.pipelines import util from maas_lib.preprocessors import Preprocessor from maas_lib.utils.config import Config -from maas_lib.utils.constant import CONFIGFILE from .util import is_model_name Tensor = Union['torch.Tensor', 'tf.Tensor'] @@ -31,7 +30,7 @@ class Pipeline(ABC): """ Base class for pipeline. If config_file is provided, model and preprocessor will be - instantiated from corresponding config. Otherwise model + instantiated from corresponding config. Otherwise, model and preprocessor will be constructed separately. Args: @@ -44,7 +43,11 @@ class Pipeline(ABC): if isinstance(model, str): if not osp.exists(model): - model = snapshot_download(model) + cache_path = util.get_model_cache_dir(model) + if osp.exists(cache_path): + model = cache_path + else: + model = snapshot_download(model) if is_model_name(model): self.model = Model.from_pretrained(model) @@ -61,7 +64,7 @@ class Pipeline(ABC): def __call__(self, input: Union[Input, List[Input]], *args, **post_kwargs) -> Union[Dict[str, Any], Generator]: - # moodel provider should leave it as it is + # model provider should leave it as it is # maas library developer will handle this function # simple showcase, need to support iterator type for both tensorflow and pytorch diff --git a/maas_lib/pipelines/util.py b/maas_lib/pipelines/util.py index 3e907359..4a0a28ec 100644 --- a/maas_lib/pipelines/util.py +++ b/maas_lib/pipelines/util.py @@ -1,12 +1,23 @@ # Copyright (c) Alibaba, Inc. and its affiliates. +import os import os.path as osp import json +from maas_hub.constants import MODEL_ID_SEPARATOR from maas_hub.file_download import model_file_download from maas_lib.utils.constant import CONFIGFILE +# temp solution before the hub-cache is in place +def get_model_cache_dir(model_id: str, branch: str = 'master'): + model_id_expanded = model_id.replace('/', + MODEL_ID_SEPARATOR) + '.' + branch + default_cache_dir = os.path.expanduser(os.path.join('~/.cache', 'maas')) + return os.getenv('MAAS_CACHE', + os.path.join(default_cache_dir, 'hub', model_id_expanded)) + + def is_model_name(model): if osp.exists(model): if osp.exists(osp.join(model, CONFIGFILE)): diff --git a/tests/pipelines/test_image_matting.py b/tests/pipelines/test_image_matting.py index 26847389..1713b34e 100644 --- a/tests/pipelines/test_image_matting.py +++ b/tests/pipelines/test_image_matting.py @@ -1,6 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. - +import os import os.path as osp +import shutil import tempfile import unittest @@ -8,12 +9,20 @@ import cv2 from ali_maas_datasets import PyDataset from maas_lib.fileio import File -from maas_lib.pipelines import pipeline +from maas_lib.pipelines import pipeline, util from maas_lib.utils.constant import Tasks class ImageMattingTest(unittest.TestCase): + def setUp(self) -> None: + self.model_id = 'damo/image-matting-person' + # switch to False if downloading everytime is not desired + purge_cache = True + if purge_cache: + shutil.rmtree( + util.get_model_cache_dir(self.model_id), ignore_errors=True) + def test_run(self): model_path = 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs' \ '.com/data/test/maas/image_matting/matting_person.pb' @@ -36,16 +45,14 @@ class ImageMattingTest(unittest.TestCase): # input_location = '/dir/to/images' dataset = PyDataset.load(input_location, target='image') - img_matting = pipeline( - Tasks.image_matting, model='damo/image-matting-person') + img_matting = pipeline(Tasks.image_matting, model=self.model_id) # note that for dataset output, the inference-output is a Generator that can be iterated. result = img_matting(dataset) cv2.imwrite('result.png', next(result)['output_png']) print(f'Output written to {osp.abspath("result.png")}') def test_run_modelhub(self): - img_matting = pipeline( - Tasks.image_matting, model='damo/image-matting-person') + img_matting = pipeline(Tasks.image_matting, model=self.model_id) result = img_matting( 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png' diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index 080622d3..cbdd8964 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -1,5 +1,6 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -import tempfile +import os +import shutil import unittest import zipfile from pathlib import Path @@ -9,13 +10,21 @@ from ali_maas_datasets import PyDataset from maas_lib.fileio import File from maas_lib.models import Model from maas_lib.models.nlp import SequenceClassificationModel -from maas_lib.pipelines import SequenceClassificationPipeline, pipeline +from maas_lib.pipelines import SequenceClassificationPipeline, pipeline, util from maas_lib.preprocessors import SequenceClassificationPreprocessor from maas_lib.utils.constant import Tasks class SequenceClassificationTest(unittest.TestCase): + def setUp(self) -> None: + self.model_id = 'damo/bert-base-sst2' + # switch to False if downloading everytime is not desired + purge_cache = True + if purge_cache: + shutil.rmtree( + util.get_model_cache_dir(self.model_id), ignore_errors=True) + def predict(self, pipeline_ins: SequenceClassificationPipeline): from easynlp.appzoo import load_dataset @@ -60,7 +69,7 @@ class SequenceClassificationTest(unittest.TestCase): print(pipeline2('Hello world!')) def test_run_with_model_from_modelhub(self): - model = Model.from_pretrained('damo/bert-base-sst2') + model = Model.from_pretrained(self.model_id) preprocessor = SequenceClassificationPreprocessor( model.model_dir, first_sequence='sentence', second_sequence=None) pipeline_ins = pipeline( @@ -71,13 +80,13 @@ class SequenceClassificationTest(unittest.TestCase): def test_run_with_model_name(self): text_classification = pipeline( - task=Tasks.text_classification, model='damo/bert-base-sst2') + task=Tasks.text_classification, model=self.model_id) result = text_classification( PyDataset.load('glue', name='sst2', target='sentence')) self.printDataset(result) def test_run_with_dataset(self): - model = Model.from_pretrained('damo/bert-base-sst2') + model = Model.from_pretrained(self.model_id) preprocessor = SequenceClassificationPreprocessor( model.model_dir, first_sequence='sentence', second_sequence=None) text_classification = pipeline( From 8a76f407546f635483417c1047742d44e36ff676 Mon Sep 17 00:00:00 2001 From: "hemu.zp" Date: Wed, 8 Jun 2022 17:11:04 +0800 Subject: [PATCH 04/13] [to #42322933]Add text-generation-pipeline with Palm model. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 Palm 中文模型接入 MaaS,添加了文本生成 pipeline Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8934393 * add text_generation model and pipeline * fix bug * fix bug * add TextGenerator in pipeline * fix bug * update checkpoint and test inputs * remove magic number.. * fix bug * adjust code with AutoModel * clear comments and tidy up the code * move model.eval() into generator * update master interface and lint code * replace 'palm-text-generation' with 'palm' * add text_generation model and pipeline * fix bug * fix bug * add TextGenerator in pipeline * fix bug * fix conflict of pipeline.txt * remove magic number.. * fix bug * adjust code with AutoModel * clear comments and tidy up the code * move model.eval() into generator * fix conflict * replace 'palm-text-generation' with 'palm' * fix conflict * add test_run_modelhub * update sofa version * modify sofa version * add test_run_with_model_name * fix bug --- maas_lib/models/nlp/__init__.py | 1 + maas_lib/models/nlp/text_generation_model.py | 52 ++++++++++++++++ maas_lib/pipelines/nlp/__init__.py | 1 + .../pipelines/nlp/text_generation_pipeline.py | 59 +++++++++++++++++++ maas_lib/preprocessors/__init__.py | 1 + maas_lib/preprocessors/nlp.py | 58 ++++++++++++++++++ requirements.txt | 1 + requirements/nlp.txt | 1 + tests/pipelines/test_text_generation.py | 46 +++++++++++++++ 9 files changed, 220 insertions(+) create mode 100644 maas_lib/models/nlp/text_generation_model.py create mode 100644 maas_lib/pipelines/nlp/text_generation_pipeline.py create mode 100644 requirements/nlp.txt create mode 100644 tests/pipelines/test_text_generation.py diff --git a/maas_lib/models/nlp/__init__.py b/maas_lib/models/nlp/__init__.py index d85c0ba7..b2a1d43b 100644 --- a/maas_lib/models/nlp/__init__.py +++ b/maas_lib/models/nlp/__init__.py @@ -1 +1,2 @@ from .sequence_classification_model import * # noqa F403 +from .text_generation_model import * # noqa F403 diff --git a/maas_lib/models/nlp/text_generation_model.py b/maas_lib/models/nlp/text_generation_model.py new file mode 100644 index 00000000..04345d22 --- /dev/null +++ b/maas_lib/models/nlp/text_generation_model.py @@ -0,0 +1,52 @@ +from typing import Any, Dict + +from maas_lib.utils.constant import Tasks +from ..base import Model, Tensor +from ..builder import MODELS + +__all__ = ['PalmForTextGenerationModel'] + + +@MODELS.register_module(Tasks.text_generation, module_name=r'palm') +class PalmForTextGenerationModel(Model): + + def __init__(self, model_dir: str, *args, **kwargs): + """initialize the text generation model from the `model_dir` path. + + Args: + model_dir (str): the model path. + model_cls (Optional[Any], optional): model loader, if None, use the + default loader to load model weights, by default None. + """ + from sofa import PalmTokenizer + + super().__init__(model_dir, *args, **kwargs) + self.model_dir = model_dir + + from sofa.models.palm import PalmForConditionalGeneration, TextGenerator + tokenizer = kwargs.pop('tokenizer', + PalmTokenizer.from_pretrained(model_dir)) + model = PalmForConditionalGeneration.from_pretrained(model_dir) + self.generator = TextGenerator(model, tokenizer) + + def forward(self, input: Dict[str, Tensor]) -> Dict[str, Tensor]: + """return the result by the model + + Args: + input (Dict[str, Any]): the preprocessed data + + Returns: + Dict[str, np.ndarray]: results + Example: + { + 'predictions': array([1]), # lable 0-negative 1-positive + 'probabilities': array([[0.11491239, 0.8850876 ]], dtype=float32), + 'logits': array([[-0.53860897, 1.5029076 ]], dtype=float32) # true value + } + """ + + encoder_inputs = [ + input['input_ids'], input['token_type_ids'], + input['attention_mask'] + ] + return self.generator(encoder_inputs) diff --git a/maas_lib/pipelines/nlp/__init__.py b/maas_lib/pipelines/nlp/__init__.py index f9d874e7..3dbbc1bb 100644 --- a/maas_lib/pipelines/nlp/__init__.py +++ b/maas_lib/pipelines/nlp/__init__.py @@ -1 +1,2 @@ from .sequence_classification_pipeline import * # noqa F403 +from .text_generation_pipeline import * # noqa F403 diff --git a/maas_lib/pipelines/nlp/text_generation_pipeline.py b/maas_lib/pipelines/nlp/text_generation_pipeline.py new file mode 100644 index 00000000..865557b5 --- /dev/null +++ b/maas_lib/pipelines/nlp/text_generation_pipeline.py @@ -0,0 +1,59 @@ +from typing import Dict, Optional, Union + +from maas_lib.models import Model +from maas_lib.models.nlp import PalmForTextGenerationModel +from maas_lib.preprocessors import TextGenerationPreprocessor +from maas_lib.utils.constant import Tasks +from ..base import Pipeline, Tensor +from ..builder import PIPELINES + +__all__ = ['TextGenerationPipeline'] + + +@PIPELINES.register_module(Tasks.text_generation, module_name=r'palm') +class TextGenerationPipeline(Pipeline): + + def __init__(self, + model: Union[PalmForTextGenerationModel, str], + preprocessor: Optional[TextGenerationPreprocessor] = None, + **kwargs): + """use `model` and `preprocessor` to create a nlp text classification pipeline for prediction + + Args: + model (SequenceClassificationModel): a model instance + preprocessor (SequenceClassificationPreprocessor): a preprocessor instance + """ + sc_model = model if isinstance( + model, + PalmForTextGenerationModel) else Model.from_pretrained(model) + if preprocessor is None: + preprocessor = TextGenerationPreprocessor( + sc_model.model_dir, + first_sequence='sentence', + second_sequence=None) + super().__init__(model=sc_model, preprocessor=preprocessor, **kwargs) + self.tokenizer = preprocessor.tokenizer + + def postprocess(self, inputs: Dict[str, Tensor]) -> Dict[str, str]: + """process the prediction results + + Args: + inputs (Dict[str, Any]): _description_ + + Returns: + Dict[str, str]: the prediction results + """ + + vocab_size = len(self.tokenizer.vocab) + pred_list = inputs['predictions'] + pred_ids = pred_list[0][0].cpu().numpy().tolist() + for j in range(len(pred_ids)): + if pred_ids[j] >= vocab_size: + pred_ids[j] = 100 + pred = self.tokenizer.convert_ids_to_tokens(pred_ids) + pred_string = ''.join(pred).replace( + '##', + '').split('[SEP]')[0].replace('[CLS]', + '').replace('[SEP]', + '').replace('[UNK]', '') + return {'pred_string': pred_string} diff --git a/maas_lib/preprocessors/__init__.py b/maas_lib/preprocessors/__init__.py index 81ca1007..518ea977 100644 --- a/maas_lib/preprocessors/__init__.py +++ b/maas_lib/preprocessors/__init__.py @@ -5,3 +5,4 @@ from .builder import PREPROCESSORS, build_preprocessor from .common import Compose from .image import LoadImage, load_image from .nlp import * # noqa F403 +from .nlp import TextGenerationPreprocessor diff --git a/maas_lib/preprocessors/nlp.py b/maas_lib/preprocessors/nlp.py index bde401c2..176322d4 100644 --- a/maas_lib/preprocessors/nlp.py +++ b/maas_lib/preprocessors/nlp.py @@ -89,3 +89,61 @@ class SequenceClassificationPreprocessor(Preprocessor): rst['token_type_ids'].append(feature['token_type_ids']) return rst + + +@PREPROCESSORS.register_module(Fields.nlp, module_name=r'palm') +class TextGenerationPreprocessor(Preprocessor): + + def __init__(self, model_dir: str, *args, **kwargs): + """preprocess the data using the vocab.txt from the `model_dir` path + + Args: + model_dir (str): model path + """ + from sofa import PalmTokenizer + + super().__init__(*args, **kwargs) + + self.model_dir: str = model_dir + self.first_sequence: str = kwargs.pop('first_sequence', + 'first_sequence') + self.second_sequence: str = kwargs.pop('second_sequence', + 'second_sequence') + self.sequence_length: int = kwargs.pop('sequence_length', 128) + self.tokenizer = PalmTokenizer.from_pretrained(model_dir) + + @type_assert(object, str) + def __call__(self, data: str) -> Dict[str, Any]: + """process the raw input data + + Args: + data (str): a sentence + Example: + 'you are so handsome.' + + Returns: + Dict[str, Any]: the preprocessed data + """ + import torch + + new_data = {self.first_sequence: data} + # preprocess the data for the model input + + rst = {'input_ids': [], 'attention_mask': [], 'token_type_ids': []} + + max_seq_length = self.sequence_length + + text_a = new_data.get(self.first_sequence, None) + text_b = new_data.get(self.second_sequence, None) + feature = self.tokenizer( + text_a, + text_b, + padding='max_length', + truncation=True, + max_length=max_seq_length) + + rst['input_ids'].append(feature['input_ids']) + rst['attention_mask'].append(feature['attention_mask']) + rst['token_type_ids'].append(feature['token_type_ids']) + + return {k: torch.tensor(v) for k, v in rst.items()} diff --git a/requirements.txt b/requirements.txt index 999c567e..3cc6857e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -r requirements/runtime.txt -r requirements/pipeline.txt +-r requirements/nlp.txt diff --git a/requirements/nlp.txt b/requirements/nlp.txt new file mode 100644 index 00000000..8de83798 --- /dev/null +++ b/requirements/nlp.txt @@ -0,0 +1 @@ +https://alinlp.alibaba-inc.com/pypi/sofa-1.0.1.3-py3-none-any.whl diff --git a/tests/pipelines/test_text_generation.py b/tests/pipelines/test_text_generation.py new file mode 100644 index 00000000..d59fdabb --- /dev/null +++ b/tests/pipelines/test_text_generation.py @@ -0,0 +1,46 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +import unittest + +from maas_hub.snapshot_download import snapshot_download + +from maas_lib.models import Model +from maas_lib.models.nlp import PalmForTextGenerationModel +from maas_lib.pipelines import TextGenerationPipeline, pipeline +from maas_lib.preprocessors import TextGenerationPreprocessor +from maas_lib.utils.constant import Tasks + + +class TextGenerationTest(unittest.TestCase): + model_id = 'damo/nlp_palm_text-generation_chinese' + input1 = "今日天气类型='晴'&温度变化趋势='大幅上升'&最低气温='28℃'&最高气温='31℃'&体感='湿热'" + input2 = "今日天气类型='多云'&体感='舒适'&最低气温='26℃'&最高气温='30℃'" + + def test_run(self): + cache_path = snapshot_download(self.model_id) + preprocessor = TextGenerationPreprocessor( + cache_path, first_sequence='sentence', second_sequence=None) + model = PalmForTextGenerationModel( + cache_path, tokenizer=preprocessor.tokenizer) + pipeline1 = TextGenerationPipeline(model, preprocessor) + pipeline2 = pipeline( + Tasks.text_generation, model=model, preprocessor=preprocessor) + print(f'input: {self.input1}\npipeline1: {pipeline1(self.input1)}') + print() + print(f'input: {self.input2}\npipeline2: {pipeline2(self.input2)}') + + def test_run_with_model_from_modelhub(self): + model = Model.from_pretrained(self.model_id) + preprocessor = TextGenerationPreprocessor( + model.model_dir, first_sequence='sentence', second_sequence=None) + pipeline_ins = pipeline( + task=Tasks.text_generation, model=model, preprocessor=preprocessor) + print(pipeline_ins(self.input1)) + + def test_run_with_model_name(self): + pipeline_ins = pipeline( + task=Tasks.text_generation, model=self.model_id) + print(pipeline_ins(self.input2)) + + +if __name__ == '__main__': + unittest.main() From 235880f300dada0fc4596ee36214caba47e2aa11 Mon Sep 17 00:00:00 2001 From: "feiwu.yfw" Date: Wed, 8 Jun 2022 18:29:39 +0800 Subject: [PATCH 05/13] [to #42339763] merge pydataset into maas-lib * merge pydataset to the repo Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8955999 --- docs/source/quick_start.md | 3 +- maas_lib/pipelines/base.py | 2 +- pydatasets/__init__.py | 1 + pydatasets/py_dataset.py | 126 ++++++++++++++++++++ requirements/maas.txt | 1 - requirements/runtime.txt | 2 +- tests/pipelines/test_image_matting.py | 2 +- tests/pipelines/test_text_classification.py | 2 +- tests/pydataset/__init__.py | 0 tests/pydataset/test_py_dataset.py | 43 +++++++ 10 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 pydatasets/__init__.py create mode 100644 pydatasets/py_dataset.py create mode 100644 tests/pydataset/__init__.py create mode 100644 tests/pydataset/test_py_dataset.py diff --git a/docs/source/quick_start.md b/docs/source/quick_start.md index 3c961097..4a76f690 100644 --- a/docs/source/quick_start.md +++ b/docs/source/quick_start.md @@ -95,12 +95,13 @@ print(f'Output written to {osp.abspath("result.png")}') ``` 此外,pipeline接口也能接收Dataset作为输入,上面的代码同样可以实现为 + ```python import cv2 import os.path as osp from maas_lib.pipelines import pipeline from maas_lib.utils.constant import Tasks -from ali_maas_datasets import PyDataset +from pydatasets import PyDataset # 使用图像url构建PyDataset,此处也可通过 input_location = '/dir/to/images' 来使用本地文件夹 input_location = [ diff --git a/maas_lib/pipelines/base.py b/maas_lib/pipelines/base.py index 3b1103f6..5e387c62 100644 --- a/maas_lib/pipelines/base.py +++ b/maas_lib/pipelines/base.py @@ -4,8 +4,8 @@ import os.path as osp from abc import ABC, abstractmethod from typing import Any, Dict, Generator, List, Tuple, Union -from ali_maas_datasets import PyDataset from maas_hub.snapshot_download import snapshot_download +from pydatasets import PyDataset from maas_lib.models import Model from maas_lib.pipelines import util diff --git a/pydatasets/__init__.py b/pydatasets/__init__.py new file mode 100644 index 00000000..a1ed1d93 --- /dev/null +++ b/pydatasets/__init__.py @@ -0,0 +1 @@ +from .py_dataset import PyDataset diff --git a/pydatasets/py_dataset.py b/pydatasets/py_dataset.py new file mode 100644 index 00000000..2e9a378f --- /dev/null +++ b/pydatasets/py_dataset.py @@ -0,0 +1,126 @@ +import logging +from typing import (Any, Callable, Dict, List, Mapping, Optional, Sequence, + Union) + +from datasets import Dataset, load_dataset + +from maas_lib.utils.logger import get_logger + +logger = get_logger() + + +class PyDataset: + _hf_ds = None # holds the underlying HuggingFace Dataset + """A PyDataset backed by hugging face datasets.""" + + def __init__(self, hf_ds: Dataset): + self._hf_ds = hf_ds + self.target = None + + def __iter__(self): + if isinstance(self._hf_ds, Dataset): + for item in self._hf_ds: + if self.target is not None: + yield item[self.target] + else: + yield item + else: + for ds in self._hf_ds.values(): + for item in ds: + if self.target is not None: + yield item[self.target] + else: + yield item + + @classmethod + def from_hf_dataset(cls, + hf_ds: Dataset, + target: str = None) -> 'PyDataset': + dataset = cls(hf_ds) + dataset.target = target + return dataset + + @staticmethod + def load( + path: Union[str, list], + target: Optional[str] = None, + version: Optional[str] = None, + name: Optional[str] = None, + split: Optional[str] = None, + data_dir: Optional[str] = None, + data_files: Optional[Union[str, Sequence[str], + Mapping[str, Union[str, + Sequence[str]]]]] = None + ) -> 'PyDataset': + """Load a pydataset from the MaaS Hub, Hugging Face Hub, urls, or a local dataset. + Args: + + path (str): Path or name of the dataset. + target (str, optional): Name of the column to output. + version (str, optional): Version of the dataset script to load: + name (str, optional): Defining the subset_name of the dataset. + data_dir (str, optional): Defining the data_dir of the dataset configuration. I + data_files (str or Sequence or Mapping, optional): Path(s) to source data file(s). + split (str, optional): Which split of the data to load. + + Returns: + pydataset (obj:`PyDataset`): PyDataset object for a certain dataset. + """ + if isinstance(path, str): + dataset = load_dataset( + path, + name=name, + revision=version, + split=split, + data_dir=data_dir, + data_files=data_files) + elif isinstance(path, list): + if target is None: + target = 'target' + dataset = Dataset.from_dict({target: [p] for p in path}) + else: + raise TypeError('path must be a str or a list, but got' + f' {type(path)}') + return PyDataset.from_hf_dataset(dataset, target=target) + + def to_torch_dataset( + self, + columns: Union[str, List[str]] = None, + output_all_columns: bool = False, + **format_kwargs, + ): + self._hf_ds.reset_format() + self._hf_ds.set_format( + type='torch', + columns=columns, + output_all_columns=output_all_columns, + format_kwargs=format_kwargs) + return self._hf_ds + + def to_tf_dataset( + self, + columns: Union[str, List[str]], + batch_size: int, + shuffle: bool, + collate_fn: Callable, + drop_remainder: bool = None, + collate_fn_args: Dict[str, Any] = None, + label_cols: Union[str, List[str]] = None, + dummy_labels: bool = False, + prefetch: bool = True, + ): + self._hf_ds.reset_format() + return self._hf_ds.to_tf_dataset( + columns, + batch_size, + shuffle, + collate_fn, + drop_remainder=drop_remainder, + collate_fn_args=collate_fn_args, + label_cols=label_cols, + dummy_labels=dummy_labels, + prefetch=prefetch) + + def to_hf_dataset(self) -> Dataset: + self._hf_ds.reset_format() + return self._hf_ds diff --git a/requirements/maas.txt b/requirements/maas.txt index 66b9aeca..3b64c375 100644 --- a/requirements/maas.txt +++ b/requirements/maas.txt @@ -1,3 +1,2 @@ http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release/maas/maas_lib-0.1.1-py3-none-any.whl https://maashub.oss-cn-hangzhou.aliyuncs.com/releases/maas_hub-0.1.0.dev0-py2.py3-none-any.whl -https://mit-dataset.oss-cn-beijing.aliyuncs.com/release/ali_maas_datasets-0.0.1.dev0-py3-none-any.whl diff --git a/requirements/runtime.txt b/requirements/runtime.txt index 5d24e660..b57358fc 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -1,6 +1,6 @@ addict +datasets https://maashub.oss-cn-hangzhou.aliyuncs.com/releases/maas_hub-0.1.0.dev0-py2.py3-none-any.whl -https://mit-dataset.oss-cn-beijing.aliyuncs.com/release/ali_maas_datasets-0.0.1.dev0-py3-none-any.whl numpy opencv-python-headless Pillow diff --git a/tests/pipelines/test_image_matting.py b/tests/pipelines/test_image_matting.py index 1713b34e..4fb475bb 100644 --- a/tests/pipelines/test_image_matting.py +++ b/tests/pipelines/test_image_matting.py @@ -6,7 +6,7 @@ import tempfile import unittest import cv2 -from ali_maas_datasets import PyDataset +from pydatasets import PyDataset from maas_lib.fileio import File from maas_lib.pipelines import pipeline, util diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index cbdd8964..2db7e67f 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -5,7 +5,7 @@ import unittest import zipfile from pathlib import Path -from ali_maas_datasets import PyDataset +from pydatasets import PyDataset from maas_lib.fileio import File from maas_lib.models import Model diff --git a/tests/pydataset/__init__.py b/tests/pydataset/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/pydataset/test_py_dataset.py b/tests/pydataset/test_py_dataset.py new file mode 100644 index 00000000..f6bdb8e9 --- /dev/null +++ b/tests/pydataset/test_py_dataset.py @@ -0,0 +1,43 @@ +import unittest + +import datasets as hfdata +from pydatasets import PyDataset + + +class PyDatasetTest(unittest.TestCase): + + def setUp(self): + # ds1 initiazed from in memory json + self.json_data = { + 'dummy': [{ + 'a': i, + 'x': i * 10, + 'c': i * 100 + } for i in range(1, 11)] + } + hfds1 = hfdata.Dataset.from_dict(self.json_data) + self.ds1 = PyDataset.from_hf_dataset(hfds1) + + # ds2 initialized from hg hub + hfds2 = hfdata.load_dataset( + 'glue', 'mrpc', revision='2.0.0', split='train') + self.ds2 = PyDataset.from_hf_dataset(hfds2) + + def tearDown(self): + pass + + def test_to_hf_dataset(self): + hfds = self.ds1.to_hf_dataset() + hfds1 = hfdata.Dataset.from_dict(self.json_data) + self.assertEqual(hfds.data, hfds1.data) + + # simple map function + hfds = hfds.map(lambda e: {'new_feature': e['dummy']['a']}) + self.assertEqual(len(hfds['new_feature']), 10) + + hfds2 = self.ds2.to_hf_dataset() + self.assertTrue(hfds2[0]['sentence1'].startswith('Amrozi')) + + +if __name__ == '__main__': + unittest.main() From 68e64a90d404359db32d3787832de401eecbe148 Mon Sep 17 00:00:00 2001 From: "menrui.mr" Date: Wed, 8 Jun 2022 18:38:19 +0800 Subject: [PATCH 06/13] [to #42322933] add image_caption_pipeline with OFA 1. add OFA whl for image caption pipeline 2. fix a bug in pipelines/builder.py Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8930942 * [to #41669377] docs and tools refinement and release 1. add build_doc linter script 2. add sphinx-docs support 3. add development doc and api doc 4. change version to 0.1.0 for the first internal release version Link: https://code.aone.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8775307 * [to #41669377] add pipeline tutorial and fix bugs 1. add pipleine tutorial 2. fix bugs when using pipeline with certain model and preprocessor Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8814301 * refine doc * refine doc * upload ofa for caption(with source code but not whl) * remove data in gitignore * append uncommitted data dir in ofa * remove ofa_dir , use ofa.whl instead. * update BPE * rollback changes used in debugging. * Merge branch 'master' into ofa/image_caption # Conflicts: # docs/README.md # docs/source/conf.py # docs/source/index.rst # docs/source/tutorials/pipeline.md # maas_lib/models/nlp/sequence_classification_model.py # maas_lib/pipelines/builder.py # maas_lib/version.py # setup.py # tests/pipelines/test_text_classification.py * 1. fix a bug in pipelines/builder.py. 2. modify model_path to model in image_captioning.py. * 1. rename test_image_captioning.py. * format all files using pre-commit. * add fairseq in requirements.txt * add fairseq in requirements.txt * change fairseq path to git repo to a whl on oss in ofa.txt. * change module_name to 'ofa' * Merge remote-tracking branch 'origin/master' into ofa/image_caption # Conflicts: # maas_lib/pipelines/builder.py * optim requirements for ofa / refine image_captioning.py * uncommited change. * feat: Fix confilct, auto commit by WebIDE --- maas_lib/pipelines/multi_modal/__init__.py | 1 + .../pipelines/multi_modal/image_captioning.py | 118 ++++++++++++++++++ requirements.txt | 1 + requirements/multi-modal.txt | 9 ++ tests/pipelines/test_image_captioning.py | 35 ++++++ 5 files changed, 164 insertions(+) create mode 100644 maas_lib/pipelines/multi_modal/image_captioning.py create mode 100644 requirements/multi-modal.txt create mode 100644 tests/pipelines/test_image_captioning.py diff --git a/maas_lib/pipelines/multi_modal/__init__.py b/maas_lib/pipelines/multi_modal/__init__.py index e69de29b..7d9a2c59 100644 --- a/maas_lib/pipelines/multi_modal/__init__.py +++ b/maas_lib/pipelines/multi_modal/__init__.py @@ -0,0 +1 @@ +from .image_captioning import ImageCaptionPipeline diff --git a/maas_lib/pipelines/multi_modal/image_captioning.py b/maas_lib/pipelines/multi_modal/image_captioning.py new file mode 100644 index 00000000..778354b7 --- /dev/null +++ b/maas_lib/pipelines/multi_modal/image_captioning.py @@ -0,0 +1,118 @@ +from typing import Any, Dict + +import numpy as np +import torch +from fairseq import checkpoint_utils, tasks, utils +from ofa.models.ofa import OFAModel +from ofa.tasks.mm_tasks import CaptionTask +from ofa.utils.eval_utils import eval_caption +from PIL import Image + +from maas_lib.pipelines.base import Input +from maas_lib.preprocessors import load_image +from maas_lib.utils.constant import Tasks +from maas_lib.utils.logger import get_logger +from ..base import Pipeline +from ..builder import PIPELINES + +logger = get_logger() + + +@PIPELINES.register_module(Tasks.image_captioning, module_name='ofa') +class ImageCaptionPipeline(Pipeline): + # TODO: refine using modelhub + def __init__(self, model: str, bpe_dir: str): + super().__init__() + # turn on cuda if GPU is available + + tasks.register_task('caption', CaptionTask) + use_cuda = False + # use fp16 only when GPU is available + use_fp16 = False + overrides = { + 'bpe_dir': bpe_dir, + 'eval_cider': False, + 'beam': 5, + 'max_len_b': 16, + 'no_repeat_ngram_size': 3, + 'seed': 7 + } + models, cfg, task = checkpoint_utils.load_model_ensemble_and_task( + utils.split_paths(model), arg_overrides=overrides) + + # Move models to GPU + for model in models: + model.eval() + if use_cuda: + model.cuda() + if use_fp16: + model.half() + model.prepare_for_inference_(cfg) + self.models = models + # Initialize generator + self.generator = task.build_generator(models, cfg.generation) + + # Initialize transform + from torchvision import transforms + mean = [0.5, 0.5, 0.5] + std = [0.5, 0.5, 0.5] + + self.patch_resize_transform = transforms.Compose([ + lambda image: image.convert('RGB'), + transforms.Resize( + (cfg.task.patch_image_size, cfg.task.patch_image_size), + interpolation=Image.BICUBIC), + transforms.ToTensor(), + transforms.Normalize(mean=mean, std=std), + ]) + + self.task = task + self.bos_item = torch.LongTensor([task.src_dict.bos()]) + self.eos_item = torch.LongTensor([task.src_dict.eos()]) + self.pad_idx = task.src_dict.pad() + + def preprocess(self, input: Input) -> Dict[str, Any]: + + def encode_text(text, length=None, append_bos=False, append_eos=False): + s = self.task.tgt_dict.encode_line( + line=self.task.bpe.encode(text), + add_if_not_exist=False, + append_eos=False).long() + if length is not None: + s = s[:length] + if append_bos: + s = torch.cat([self.bos_item, s]) + if append_eos: + s = torch.cat([s, self.eos_item]) + return s + + patch_image = self.patch_resize_transform( + load_image(input)).unsqueeze(0) + patch_mask = torch.tensor([True]) + text = 'what does the image describe?' + src_text = encode_text( + text, append_bos=True, append_eos=True).unsqueeze(0) + src_length = torch.LongTensor( + [s.ne(self.pad_idx).long().sum() for s in src_text]) + sample = { + 'id': np.array(['42']), + 'net_input': { + 'src_tokens': src_text, + 'src_lengths': src_length, + 'patch_images': patch_image, + 'patch_masks': patch_mask, + } + } + return sample + + def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: + results, _ = eval_caption(self.task, self.generator, self.models, + input) + return { + 'image_id': results[0]['image_id'], + 'caption': results[0]['caption'] + } + + def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: + # What should we do here ? + return inputs diff --git a/requirements.txt b/requirements.txt index 3cc6857e..1944b476 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -r requirements/runtime.txt -r requirements/pipeline.txt +-r requirements/multi-modal.txt -r requirements/nlp.txt diff --git a/requirements/multi-modal.txt b/requirements/multi-modal.txt new file mode 100644 index 00000000..ad641b63 --- /dev/null +++ b/requirements/multi-modal.txt @@ -0,0 +1,9 @@ +datasets +einops +ftfy>=6.0.3 +https://jirenmr.oss-cn-zhangjiakou.aliyuncs.com/ofa/fairseq-maas-py3-none-any.whl +https://jirenmr.oss-cn-zhangjiakou.aliyuncs.com/ofa/ofa-0.0.2-py3-none-any.whl +pycocoevalcap>=1.2 +pycocotools>=2.0.4 +rouge_score +timm diff --git a/tests/pipelines/test_image_captioning.py b/tests/pipelines/test_image_captioning.py new file mode 100644 index 00000000..f951f0a8 --- /dev/null +++ b/tests/pipelines/test_image_captioning.py @@ -0,0 +1,35 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. + +import os +import tempfile +import unittest + +from maas_lib.fileio import File +from maas_lib.pipelines import pipeline +from maas_lib.utils.constant import Tasks + + +class ImageCaptionTest(unittest.TestCase): + + def test_run(self): + model = 'https://ofa-beijing.oss-cn-beijing.aliyuncs.com/checkpoints/caption_large_best_clean.pt' + + os.system( + 'wget https://jirenmr.oss-cn-zhangjiakou.aliyuncs.com/ofa/BPE.zip' + ) + os.system('unzip BPE.zip') + bpe_dir = './BPE' + + with tempfile.NamedTemporaryFile('wb', suffix='.pb') as ofile: + ofile.write(File.read(model)) + img_captioning = pipeline( + Tasks.image_captioning, model=ofile.name, bpe_dir=bpe_dir) + + result = img_captioning( + 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png' + ) + print(result['caption']) + + +if __name__ == '__main__': + unittest.main() From e3b8ec3bf1ce3f1c43aa4a842dc569b7c4675897 Mon Sep 17 00:00:00 2001 From: "yingda.chen" Date: Wed, 8 Jun 2022 21:27:14 +0800 Subject: [PATCH 07/13] [to #42339559] support multiple models Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8972440 * [to #42339559] support multiple models --- maas_lib/models/__init__.py | 2 +- maas_lib/models/base.py | 2 +- .../nlp/sequence_classification_model.py | 4 +- maas_lib/pipelines/base.py | 60 +++++++++++-------- maas_lib/pipelines/builder.py | 10 ++-- maas_lib/pipelines/cv/__init__.py | 2 +- ...e_matting.py => image_matting_pipeline.py} | 3 +- .../nlp/sequence_classification_pipeline.py | 10 ++-- tests/pipelines/test_image_matting.py | 1 - tests/pipelines/test_text_classification.py | 4 +- 10 files changed, 55 insertions(+), 43 deletions(-) rename maas_lib/pipelines/cv/{image_matting.py => image_matting_pipeline.py} (97%) diff --git a/maas_lib/models/__init__.py b/maas_lib/models/__init__.py index aa1b3f14..170e525e 100644 --- a/maas_lib/models/__init__.py +++ b/maas_lib/models/__init__.py @@ -2,4 +2,4 @@ from .base import Model from .builder import MODELS, build_model -from .nlp import SequenceClassificationModel +from .nlp import BertForSequenceClassification diff --git a/maas_lib/models/base.py b/maas_lib/models/base.py index 677a136a..10425f6c 100644 --- a/maas_lib/models/base.py +++ b/maas_lib/models/base.py @@ -50,7 +50,7 @@ class Model(ABC): cfg = Config.from_file(osp.join(local_model_dir, CONFIGFILE)) task_name = cfg.task model_cfg = cfg.model - # TODO @wenmeng.zwm may should mannually initialize model after model building + # TODO @wenmeng.zwm may should manually initialize model after model building if hasattr(model_cfg, 'model_type') and not hasattr(model_cfg, 'type'): model_cfg.type = model_cfg.model_type model_cfg.model_dir = local_model_dir diff --git a/maas_lib/models/nlp/sequence_classification_model.py b/maas_lib/models/nlp/sequence_classification_model.py index f77b0fbc..0afdf26e 100644 --- a/maas_lib/models/nlp/sequence_classification_model.py +++ b/maas_lib/models/nlp/sequence_classification_model.py @@ -6,12 +6,12 @@ from maas_lib.utils.constant import Tasks from ..base import Model from ..builder import MODELS -__all__ = ['SequenceClassificationModel'] +__all__ = ['BertForSequenceClassification'] @MODELS.register_module( Tasks.text_classification, module_name=r'bert-sentiment-analysis') -class SequenceClassificationModel(Model): +class BertForSequenceClassification(Model): def __init__(self, model_dir: str, *args, **kwargs): # Model.__init__(self, model_dir, model_cls, first_sequence, *args, **kwargs) diff --git a/maas_lib/pipelines/base.py b/maas_lib/pipelines/base.py index 5e387c62..47c6d90b 100644 --- a/maas_lib/pipelines/base.py +++ b/maas_lib/pipelines/base.py @@ -15,6 +15,7 @@ from .util import is_model_name Tensor = Union['torch.Tensor', 'tf.Tensor'] Input = Union[str, PyDataset, 'PIL.Image.Image', 'numpy.ndarray'] +InputModel = Union[str, Model] output_keys = [ ] # 对于不同task的pipeline,规定标准化的输出key,用以对接postprocess,同时也用来标准化postprocess后输出的key @@ -22,10 +23,32 @@ output_keys = [ class Pipeline(ABC): + def initiate_single_model(self, model): + if isinstance(model, str): + if not osp.exists(model): + cache_path = util.get_model_cache_dir(model) + model = cache_path if osp.exists( + cache_path) else snapshot_download(model) + return Model.from_pretrained(model) if is_model_name( + model) else model + elif isinstance(model, Model): + return model + else: + if model: + raise ValueError( + f'model type for single model is either str or Model, but got type {type(model)}' + ) + + def initiate_multiple_models(self, input_models: List[InputModel]): + models = [] + for model in input_models: + models.append(self.initiate_single_model(model)) + return models + def __init__(self, config_file: str = None, - model: Union[Model, str] = None, - preprocessor: Preprocessor = None, + model: Union[InputModel, List[InputModel]] = None, + preprocessor: Union[Preprocessor, List[Preprocessor]] = None, **kwargs): """ Base class for pipeline. @@ -35,31 +58,18 @@ class Pipeline(ABC): Args: config_file(str, optional): Filepath to configuration file. - model: Model name or model object - preprocessor: Preprocessor object + model: (list of) Model name or model object + preprocessor: (list of) Preprocessor object """ if config_file is not None: self.cfg = Config.from_file(config_file) - - if isinstance(model, str): - if not osp.exists(model): - cache_path = util.get_model_cache_dir(model) - if osp.exists(cache_path): - model = cache_path - else: - model = snapshot_download(model) - - if is_model_name(model): - self.model = Model.from_pretrained(model) - else: - self.model = model - elif isinstance(model, Model): - self.model = model + if not isinstance(model, List): + self.model = self.initiate_single_model(model) + self.models = [self.model] else: - if model: - raise ValueError( - f'model type is either str or Model, but got type {type(model)}' - ) + self.models = self.initiate_multiple_models(model) + + self.has_multiple_models = len(self.models) > 1 self.preprocessor = preprocessor def __call__(self, input: Union[Input, List[Input]], *args, @@ -94,15 +104,17 @@ class Pipeline(ABC): def preprocess(self, inputs: Input) -> Dict[str, Any]: """ Provide default implementation based on preprocess_cfg and user can reimplement it - """ assert self.preprocessor is not None, 'preprocess method should be implemented' + assert not isinstance(self.preprocessor, List),\ + 'default implementation does not support using multiple preprocessors.' return self.preprocessor(inputs) def forward(self, inputs: Dict[str, Any]) -> Dict[str, Any]: """ Provide default implementation using self.model and user can reimplement it """ assert self.model is not None, 'forward method should be implemented' + assert not self.has_multiple_models, 'default implementation does not support multiple models in a pipeline.' return self.model(inputs) @abstractmethod diff --git a/maas_lib/pipelines/builder.py b/maas_lib/pipelines/builder.py index acaccf05..dd146cca 100644 --- a/maas_lib/pipelines/builder.py +++ b/maas_lib/pipelines/builder.py @@ -1,7 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import os.path as osp -from typing import Union +from typing import List, Union import json from maas_hub.file_download import model_file_download @@ -10,7 +10,7 @@ from maas_lib.models.base import Model from maas_lib.utils.config import Config, ConfigDict from maas_lib.utils.constant import CONFIGFILE, Tasks from maas_lib.utils.registry import Registry, build_from_cfg -from .base import Pipeline +from .base import InputModel, Pipeline from .util import is_model_name PIPELINES = Registry('pipelines') @@ -32,7 +32,7 @@ def build_pipeline(cfg: ConfigDict, def pipeline(task: str = None, - model: Union[str, Model] = None, + model: Union[InputModel, List[InputModel]] = None, preprocessor=None, config_file: str = None, pipeline_name: str = None, @@ -75,8 +75,8 @@ def pipeline(task: str = None, cfg.update(kwargs) if model: - assert isinstance(model, (str, Model)), \ - f'model should be either str or Model, but got {type(model)}' + assert isinstance(model, (str, Model, List)), \ + f'model should be either (list of) str or Model, but got {type(model)}' cfg.model = model if preprocessor is not None: diff --git a/maas_lib/pipelines/cv/__init__.py b/maas_lib/pipelines/cv/__init__.py index 79548682..6f877a26 100644 --- a/maas_lib/pipelines/cv/__init__.py +++ b/maas_lib/pipelines/cv/__init__.py @@ -1 +1 @@ -from .image_matting import ImageMatting +from .image_matting_pipeline import ImageMattingPipeline diff --git a/maas_lib/pipelines/cv/image_matting.py b/maas_lib/pipelines/cv/image_matting_pipeline.py similarity index 97% rename from maas_lib/pipelines/cv/image_matting.py rename to maas_lib/pipelines/cv/image_matting_pipeline.py index fdb443f9..0317b4bd 100644 --- a/maas_lib/pipelines/cv/image_matting.py +++ b/maas_lib/pipelines/cv/image_matting_pipeline.py @@ -4,7 +4,6 @@ from typing import Any, Dict, List, Tuple, Union import cv2 import numpy as np import PIL -from cv2 import COLOR_GRAY2RGB from maas_lib.pipelines.base import Input from maas_lib.preprocessors import load_image @@ -18,7 +17,7 @@ logger = get_logger() @PIPELINES.register_module( Tasks.image_matting, module_name=Tasks.image_matting) -class ImageMatting(Pipeline): +class ImageMattingPipeline(Pipeline): def __init__(self, model: str): super().__init__(model=model) diff --git a/maas_lib/pipelines/nlp/sequence_classification_pipeline.py b/maas_lib/pipelines/nlp/sequence_classification_pipeline.py index 9300035d..014eb4a3 100644 --- a/maas_lib/pipelines/nlp/sequence_classification_pipeline.py +++ b/maas_lib/pipelines/nlp/sequence_classification_pipeline.py @@ -5,7 +5,7 @@ from typing import Any, Dict, Union import json import numpy as np -from maas_lib.models.nlp import SequenceClassificationModel +from maas_lib.models.nlp import BertForSequenceClassification from maas_lib.preprocessors import SequenceClassificationPreprocessor from maas_lib.utils.constant import Tasks from ...models import Model @@ -20,18 +20,20 @@ __all__ = ['SequenceClassificationPipeline'] class SequenceClassificationPipeline(Pipeline): def __init__(self, - model: Union[SequenceClassificationModel, str], + model: Union[BertForSequenceClassification, str], preprocessor: SequenceClassificationPreprocessor = None, **kwargs): """use `model` and `preprocessor` to create a nlp text classification pipeline for prediction Args: - model (SequenceClassificationModel): a model instance + model (BertForSequenceClassification): a model instance preprocessor (SequenceClassificationPreprocessor): a preprocessor instance """ + assert isinstance(model, str) or isinstance(model, BertForSequenceClassification), \ + 'model must be a single str or BertForSequenceClassification' sc_model = model if isinstance( model, - SequenceClassificationModel) else Model.from_pretrained(model) + BertForSequenceClassification) else Model.from_pretrained(model) if preprocessor is None: preprocessor = SequenceClassificationPreprocessor( sc_model.model_dir, diff --git a/tests/pipelines/test_image_matting.py b/tests/pipelines/test_image_matting.py index 4fb475bb..33e8c28c 100644 --- a/tests/pipelines/test_image_matting.py +++ b/tests/pipelines/test_image_matting.py @@ -1,5 +1,4 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -import os import os.path as osp import shutil import tempfile diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index 2db7e67f..f599b205 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -9,7 +9,7 @@ from pydatasets import PyDataset from maas_lib.fileio import File from maas_lib.models import Model -from maas_lib.models.nlp import SequenceClassificationModel +from maas_lib.models.nlp import BertForSequenceClassification from maas_lib.pipelines import SequenceClassificationPipeline, pipeline, util from maas_lib.preprocessors import SequenceClassificationPreprocessor from maas_lib.utils.constant import Tasks @@ -59,7 +59,7 @@ class SequenceClassificationTest(unittest.TestCase): with zipfile.ZipFile(cache_path_str, 'r') as zipf: zipf.extractall(cache_path.parent) path = r'.cache/easynlp/' - model = SequenceClassificationModel(path) + model = BertForSequenceClassification(path) preprocessor = SequenceClassificationPreprocessor( path, first_sequence='sentence', second_sequence=None) pipeline1 = SequenceClassificationPipeline(model, preprocessor) From 0d840d519cdb421f047eb2adaa6056eded854e21 Mon Sep 17 00:00:00 2001 From: "yingda.chen" Date: Thu, 9 Jun 2022 10:14:48 +0800 Subject: [PATCH 08/13] [to #42339763] move pydataset into maas_lib Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8974892 --- docs/source/quick_start.md | 2 +- maas_lib/pipelines/base.py | 4 ++-- {pydatasets => maas_lib/pydatasets}/__init__.py | 0 {pydatasets => maas_lib/pydatasets}/py_dataset.py | 6 +++--- tests/pipelines/test_image_matting.py | 2 +- tests/pipelines/test_text_classification.py | 4 +--- tests/{pydataset => pydatasets}/__init__.py | 0 tests/{pydataset => pydatasets}/test_py_dataset.py | 5 +++-- 8 files changed, 11 insertions(+), 12 deletions(-) rename {pydatasets => maas_lib/pydatasets}/__init__.py (100%) rename {pydatasets => maas_lib/pydatasets}/py_dataset.py (95%) rename tests/{pydataset => pydatasets}/__init__.py (100%) rename tests/{pydataset => pydatasets}/test_py_dataset.py (92%) diff --git a/docs/source/quick_start.md b/docs/source/quick_start.md index 4a76f690..4d145e79 100644 --- a/docs/source/quick_start.md +++ b/docs/source/quick_start.md @@ -101,7 +101,7 @@ import cv2 import os.path as osp from maas_lib.pipelines import pipeline from maas_lib.utils.constant import Tasks -from pydatasets import PyDataset +from maas_lib.pydatasets import PyDataset # 使用图像url构建PyDataset,此处也可通过 input_location = '/dir/to/images' 来使用本地文件夹 input_location = [ diff --git a/maas_lib/pipelines/base.py b/maas_lib/pipelines/base.py index 47c6d90b..76747b05 100644 --- a/maas_lib/pipelines/base.py +++ b/maas_lib/pipelines/base.py @@ -2,14 +2,14 @@ import os.path as osp from abc import ABC, abstractmethod -from typing import Any, Dict, Generator, List, Tuple, Union +from typing import Any, Dict, Generator, List, Union from maas_hub.snapshot_download import snapshot_download -from pydatasets import PyDataset from maas_lib.models import Model from maas_lib.pipelines import util from maas_lib.preprocessors import Preprocessor +from maas_lib.pydatasets import PyDataset from maas_lib.utils.config import Config from .util import is_model_name diff --git a/pydatasets/__init__.py b/maas_lib/pydatasets/__init__.py similarity index 100% rename from pydatasets/__init__.py rename to maas_lib/pydatasets/__init__.py diff --git a/pydatasets/py_dataset.py b/maas_lib/pydatasets/py_dataset.py similarity index 95% rename from pydatasets/py_dataset.py rename to maas_lib/pydatasets/py_dataset.py index 2e9a378f..58f83830 100644 --- a/pydatasets/py_dataset.py +++ b/maas_lib/pydatasets/py_dataset.py @@ -11,7 +11,7 @@ logger = get_logger() class PyDataset: _hf_ds = None # holds the underlying HuggingFace Dataset - """A PyDataset backed by hugging face datasets.""" + """A PyDataset backed by hugging face Dataset.""" def __init__(self, hf_ds: Dataset): self._hf_ds = hf_ds @@ -52,7 +52,7 @@ class PyDataset: Mapping[str, Union[str, Sequence[str]]]]] = None ) -> 'PyDataset': - """Load a pydataset from the MaaS Hub, Hugging Face Hub, urls, or a local dataset. + """Load a PyDataset from the MaaS Hub, Hugging Face Hub, urls, or a local dataset. Args: path (str): Path or name of the dataset. @@ -64,7 +64,7 @@ class PyDataset: split (str, optional): Which split of the data to load. Returns: - pydataset (obj:`PyDataset`): PyDataset object for a certain dataset. + PyDataset (obj:`PyDataset`): PyDataset object for a certain dataset. """ if isinstance(path, str): dataset = load_dataset( diff --git a/tests/pipelines/test_image_matting.py b/tests/pipelines/test_image_matting.py index 33e8c28c..8153b70d 100644 --- a/tests/pipelines/test_image_matting.py +++ b/tests/pipelines/test_image_matting.py @@ -5,10 +5,10 @@ import tempfile import unittest import cv2 -from pydatasets import PyDataset from maas_lib.fileio import File from maas_lib.pipelines import pipeline, util +from maas_lib.pydatasets import PyDataset from maas_lib.utils.constant import Tasks diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index f599b205..b6528319 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -1,17 +1,15 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -import os import shutil import unittest import zipfile from pathlib import Path -from pydatasets import PyDataset - from maas_lib.fileio import File from maas_lib.models import Model from maas_lib.models.nlp import BertForSequenceClassification from maas_lib.pipelines import SequenceClassificationPipeline, pipeline, util from maas_lib.preprocessors import SequenceClassificationPreprocessor +from maas_lib.pydatasets import PyDataset from maas_lib.utils.constant import Tasks diff --git a/tests/pydataset/__init__.py b/tests/pydatasets/__init__.py similarity index 100% rename from tests/pydataset/__init__.py rename to tests/pydatasets/__init__.py diff --git a/tests/pydataset/test_py_dataset.py b/tests/pydatasets/test_py_dataset.py similarity index 92% rename from tests/pydataset/test_py_dataset.py rename to tests/pydatasets/test_py_dataset.py index f6bdb8e9..a32dcb0e 100644 --- a/tests/pydataset/test_py_dataset.py +++ b/tests/pydatasets/test_py_dataset.py @@ -1,13 +1,14 @@ import unittest import datasets as hfdata -from pydatasets import PyDataset + +from maas_lib.pydatasets import PyDataset class PyDatasetTest(unittest.TestCase): def setUp(self): - # ds1 initiazed from in memory json + # ds1 initialized from in memory json self.json_data = { 'dummy': [{ 'a': i, From 0f5b214ce0fd0972234a0bb196597aef90e12da6 Mon Sep 17 00:00:00 2001 From: myf272609 Date: Thu, 9 Jun 2022 15:18:38 +0800 Subject: [PATCH 09/13] [to #42322933] Add cv-person-image-cartoon-pipeline to maas lib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mass lib 接入人像卡通化算法 Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8925552 * update * fix style issues * fix style issues * fix style issues * fix style issues * add requirements * fix bug * adapt class init * fix * fix tf2 issue * feat: Fix confilct, auto commit by WebIDE * fix commit issues * fix --- maas_lib/models/cv/__init__.py | 0 maas_lib/models/cv/cartoon/__init__.py | 0 maas_lib/models/cv/cartoon/facelib/LICENSE | 4 + .../models/cv/cartoon/facelib/LK/__init__.py | 0 maas_lib/models/cv/cartoon/facelib/LK/lk.py | 97 +++++ .../models/cv/cartoon/facelib/__init__.py | 0 maas_lib/models/cv/cartoon/facelib/config.py | 23 ++ .../cv/cartoon/facelib/face_detector.py | 116 ++++++ .../cv/cartoon/facelib/face_landmark.py | 154 ++++++++ maas_lib/models/cv/cartoon/facelib/facer.py | 150 ++++++++ .../models/cv/cartoon/mtcnn_pytorch/LICENSE | 21 ++ .../models/cv/cartoon/mtcnn_pytorch/README.md | 26 ++ .../cv/cartoon/mtcnn_pytorch/__init__.py | 0 .../cv/cartoon/mtcnn_pytorch/src/__init__.py | 0 .../cartoon/mtcnn_pytorch/src/align_trans.py | 187 ++++++++++ .../mtcnn_pytorch/src/matlab_cp2tform.py | 339 ++++++++++++++++++ maas_lib/models/cv/cartoon/utils.py | 91 +++++ maas_lib/pipelines/cv/__init__.py | 1 + .../pipelines/cv/image_cartoon_pipeline.py | 149 ++++++++ requirements.txt | 1 + requirements/cv.txt | 1 + tests/pipelines/test_person_image_cartoon.py | 38 ++ 22 files changed, 1398 insertions(+) create mode 100644 maas_lib/models/cv/__init__.py create mode 100644 maas_lib/models/cv/cartoon/__init__.py create mode 100644 maas_lib/models/cv/cartoon/facelib/LICENSE create mode 100644 maas_lib/models/cv/cartoon/facelib/LK/__init__.py create mode 100644 maas_lib/models/cv/cartoon/facelib/LK/lk.py create mode 100644 maas_lib/models/cv/cartoon/facelib/__init__.py create mode 100644 maas_lib/models/cv/cartoon/facelib/config.py create mode 100644 maas_lib/models/cv/cartoon/facelib/face_detector.py create mode 100644 maas_lib/models/cv/cartoon/facelib/face_landmark.py create mode 100644 maas_lib/models/cv/cartoon/facelib/facer.py create mode 100644 maas_lib/models/cv/cartoon/mtcnn_pytorch/LICENSE create mode 100644 maas_lib/models/cv/cartoon/mtcnn_pytorch/README.md create mode 100644 maas_lib/models/cv/cartoon/mtcnn_pytorch/__init__.py create mode 100644 maas_lib/models/cv/cartoon/mtcnn_pytorch/src/__init__.py create mode 100644 maas_lib/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py create mode 100644 maas_lib/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py create mode 100644 maas_lib/models/cv/cartoon/utils.py create mode 100644 maas_lib/pipelines/cv/image_cartoon_pipeline.py create mode 100644 requirements/cv.txt create mode 100644 tests/pipelines/test_person_image_cartoon.py diff --git a/maas_lib/models/cv/__init__.py b/maas_lib/models/cv/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maas_lib/models/cv/cartoon/__init__.py b/maas_lib/models/cv/cartoon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maas_lib/models/cv/cartoon/facelib/LICENSE b/maas_lib/models/cv/cartoon/facelib/LICENSE new file mode 100644 index 00000000..8e497ab8 --- /dev/null +++ b/maas_lib/models/cv/cartoon/facelib/LICENSE @@ -0,0 +1,4 @@ + +Copyright (c) Peppa_Pig_Face_Engine + +https://github.com/610265158/Peppa_Pig_Face_Engine diff --git a/maas_lib/models/cv/cartoon/facelib/LK/__init__.py b/maas_lib/models/cv/cartoon/facelib/LK/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maas_lib/models/cv/cartoon/facelib/LK/lk.py b/maas_lib/models/cv/cartoon/facelib/LK/lk.py new file mode 100644 index 00000000..de7c6ced --- /dev/null +++ b/maas_lib/models/cv/cartoon/facelib/LK/lk.py @@ -0,0 +1,97 @@ +import numpy as np + +from ..config import config as cfg + + +class GroupTrack(): + + def __init__(self): + self.old_frame = None + self.previous_landmarks_set = None + self.with_landmark = True + self.thres = cfg.TRACE.pixel_thres + self.alpha = cfg.TRACE.smooth_landmark + self.iou_thres = cfg.TRACE.iou_thres + + def calculate(self, img, current_landmarks_set): + if self.previous_landmarks_set is None: + self.previous_landmarks_set = current_landmarks_set + result = current_landmarks_set + else: + previous_lm_num = self.previous_landmarks_set.shape[0] + if previous_lm_num == 0: + self.previous_landmarks_set = current_landmarks_set + result = current_landmarks_set + return result + else: + result = [] + for i in range(current_landmarks_set.shape[0]): + not_in_flag = True + for j in range(previous_lm_num): + if self.iou(current_landmarks_set[i], + self.previous_landmarks_set[j] + ) > self.iou_thres: + result.append( + self.smooth(current_landmarks_set[i], + self.previous_landmarks_set[j])) + not_in_flag = False + break + if not_in_flag: + result.append(current_landmarks_set[i]) + + result = np.array(result) + self.previous_landmarks_set = result + + return result + + def iou(self, p_set0, p_set1): + rec1 = [ + np.min(p_set0[:, 0]), + np.min(p_set0[:, 1]), + np.max(p_set0[:, 0]), + np.max(p_set0[:, 1]) + ] + rec2 = [ + np.min(p_set1[:, 0]), + np.min(p_set1[:, 1]), + np.max(p_set1[:, 0]), + np.max(p_set1[:, 1]) + ] + + # computing area of each rectangles + S_rec1 = (rec1[2] - rec1[0]) * (rec1[3] - rec1[1]) + S_rec2 = (rec2[2] - rec2[0]) * (rec2[3] - rec2[1]) + + # computing the sum_area + sum_area = S_rec1 + S_rec2 + + # find the each edge of intersect rectangle + x1 = max(rec1[0], rec2[0]) + y1 = max(rec1[1], rec2[1]) + x2 = min(rec1[2], rec2[2]) + y2 = min(rec1[3], rec2[3]) + + # judge if there is an intersect + intersect = max(0, x2 - x1) * max(0, y2 - y1) + + iou = intersect / (sum_area - intersect) + return iou + + def smooth(self, now_landmarks, previous_landmarks): + result = [] + for i in range(now_landmarks.shape[0]): + x = now_landmarks[i][0] - previous_landmarks[i][0] + y = now_landmarks[i][1] - previous_landmarks[i][1] + dis = np.sqrt(np.square(x) + np.square(y)) + if dis < self.thres: + result.append(previous_landmarks[i]) + else: + result.append( + self.do_moving_average(now_landmarks[i], + previous_landmarks[i])) + + return np.array(result) + + def do_moving_average(self, p_now, p_previous): + p = self.alpha * p_now + (1 - self.alpha) * p_previous + return p diff --git a/maas_lib/models/cv/cartoon/facelib/__init__.py b/maas_lib/models/cv/cartoon/facelib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maas_lib/models/cv/cartoon/facelib/config.py b/maas_lib/models/cv/cartoon/facelib/config.py new file mode 100644 index 00000000..d795fdde --- /dev/null +++ b/maas_lib/models/cv/cartoon/facelib/config.py @@ -0,0 +1,23 @@ +import os + +import numpy as np +from easydict import EasyDict as edict + +config = edict() +os.environ['CUDA_VISIBLE_DEVICES'] = '0' + +config.DETECT = edict() +config.DETECT.topk = 10 +config.DETECT.thres = 0.8 +config.DETECT.input_shape = (512, 512, 3) +config.KEYPOINTS = edict() +config.KEYPOINTS.p_num = 68 +config.KEYPOINTS.base_extend_range = [0.2, 0.3] +config.KEYPOINTS.input_shape = (160, 160, 3) +config.TRACE = edict() +config.TRACE.pixel_thres = 1 +config.TRACE.smooth_box = 0.3 +config.TRACE.smooth_landmark = 0.95 +config.TRACE.iou_thres = 0.5 +config.DATA = edict() +config.DATA.pixel_means = np.array([123., 116., 103.]) # RGB diff --git a/maas_lib/models/cv/cartoon/facelib/face_detector.py b/maas_lib/models/cv/cartoon/facelib/face_detector.py new file mode 100644 index 00000000..e5589719 --- /dev/null +++ b/maas_lib/models/cv/cartoon/facelib/face_detector.py @@ -0,0 +1,116 @@ +import time + +import cv2 +import numpy as np +import tensorflow as tf + +from .config import config as cfg + +if tf.__version__ >= '2.0': + tf = tf.compat.v1 + + +class FaceDetector: + + def __init__(self, dir): + + self.model_path = dir + '/detector.pb' + self.thres = cfg.DETECT.thres + self.input_shape = cfg.DETECT.input_shape + + self._graph = tf.Graph() + + with self._graph.as_default(): + self._graph, self._sess = self.init_model(self.model_path) + + self.input_image = tf.get_default_graph().get_tensor_by_name( + 'tower_0/images:0') + self.training = tf.get_default_graph().get_tensor_by_name( + 'training_flag:0') + self.output_ops = [ + tf.get_default_graph().get_tensor_by_name('tower_0/boxes:0'), + tf.get_default_graph().get_tensor_by_name('tower_0/scores:0'), + tf.get_default_graph().get_tensor_by_name( + 'tower_0/num_detections:0'), + ] + + def __call__(self, image): + + image, scale_x, scale_y = self.preprocess( + image, + target_width=self.input_shape[1], + target_height=self.input_shape[0]) + + image = np.expand_dims(image, 0) + + boxes, scores, num_boxes = self._sess.run( + self.output_ops, + feed_dict={ + self.input_image: image, + self.training: False + }) + + num_boxes = num_boxes[0] + boxes = boxes[0][:num_boxes] + + scores = scores[0][:num_boxes] + + to_keep = scores > self.thres + boxes = boxes[to_keep] + scores = scores[to_keep] + + y1 = self.input_shape[0] / scale_y + x1 = self.input_shape[1] / scale_x + y2 = self.input_shape[0] / scale_y + x2 = self.input_shape[1] / scale_x + scaler = np.array([y1, x1, y2, x2], dtype='float32') + boxes = boxes * scaler + + scores = np.expand_dims(scores, 0).reshape([-1, 1]) + + for i in range(boxes.shape[0]): + boxes[i] = np.array( + [boxes[i][1], boxes[i][0], boxes[i][3], boxes[i][2]]) + return np.concatenate([boxes, scores], axis=1) + + def preprocess(self, image, target_height, target_width, label=None): + + h, w, c = image.shape + + bimage = np.zeros( + shape=[target_height, target_width, c], + dtype=image.dtype) + np.array( + cfg.DATA.pixel_means, dtype=image.dtype) + long_side = max(h, w) + + scale_x = scale_y = target_height / long_side + + image = cv2.resize(image, None, fx=scale_x, fy=scale_y) + + h_, w_, _ = image.shape + bimage[:h_, :w_, :] = image + + return bimage, scale_x, scale_y + + def init_model(self, *args): + pb_path = args[0] + + def init_pb(model_path): + config = tf.ConfigProto() + config.gpu_options.per_process_gpu_memory_fraction = 0.2 + compute_graph = tf.Graph() + compute_graph.as_default() + sess = tf.Session(config=config) + with tf.gfile.GFile(model_path, 'rb') as fid: + graph_def = tf.GraphDef() + graph_def.ParseFromString(fid.read()) + tf.import_graph_def(graph_def, name='') + + return (compute_graph, sess) + + model = init_pb(pb_path) + + graph = model[0] + sess = model[1] + + return graph, sess diff --git a/maas_lib/models/cv/cartoon/facelib/face_landmark.py b/maas_lib/models/cv/cartoon/facelib/face_landmark.py new file mode 100644 index 00000000..063d40c3 --- /dev/null +++ b/maas_lib/models/cv/cartoon/facelib/face_landmark.py @@ -0,0 +1,154 @@ +import cv2 +import numpy as np +import tensorflow as tf + +from .config import config as cfg + +if tf.__version__ >= '2.0': + tf = tf.compat.v1 + + +class FaceLandmark: + + def __init__(self, dir): + self.model_path = dir + '/keypoints.pb' + self.min_face = 60 + self.keypoint_num = cfg.KEYPOINTS.p_num * 2 + + self._graph = tf.Graph() + + with self._graph.as_default(): + + self._graph, self._sess = self.init_model(self.model_path) + self.img_input = tf.get_default_graph().get_tensor_by_name( + 'tower_0/images:0') + self.embeddings = tf.get_default_graph().get_tensor_by_name( + 'tower_0/prediction:0') + self.training = tf.get_default_graph().get_tensor_by_name( + 'training_flag:0') + + self.landmark = self.embeddings[:, :self.keypoint_num] + self.headpose = self.embeddings[:, -7:-4] * 90. + self.state = tf.nn.sigmoid(self.embeddings[:, -4:]) + + def __call__(self, img, bboxes): + landmark_result = [] + state_result = [] + for i, bbox in enumerate(bboxes): + landmark, state = self._one_shot_run(img, bbox, i) + if landmark is not None: + landmark_result.append(landmark) + state_result.append(state) + return np.array(landmark_result), np.array(state_result) + + def simple_run(self, cropped_img): + with self._graph.as_default(): + + cropped_img = np.expand_dims(cropped_img, axis=0) + landmark, p, states = self._sess.run( + [self.landmark, self.headpose, self.state], + feed_dict={ + self.img_input: cropped_img, + self.training: False + }) + + return landmark, states + + def _one_shot_run(self, image, bbox, i): + + bbox_width = bbox[2] - bbox[0] + bbox_height = bbox[3] - bbox[1] + if (bbox_width <= self.min_face and bbox_height <= self.min_face): + return None, None + add = int(max(bbox_width, bbox_height)) + bimg = cv2.copyMakeBorder( + image, + add, + add, + add, + add, + borderType=cv2.BORDER_CONSTANT, + value=cfg.DATA.pixel_means) + bbox += add + + one_edge = (1 + 2 * cfg.KEYPOINTS.base_extend_range[0]) * bbox_width + center = [(bbox[0] + bbox[2]) // 2, (bbox[1] + bbox[3]) // 2] + + bbox[0] = center[0] - one_edge // 2 + bbox[1] = center[1] - one_edge // 2 + bbox[2] = center[0] + one_edge // 2 + bbox[3] = center[1] + one_edge // 2 + + bbox = bbox.astype(np.int) + crop_image = bimg[bbox[1]:bbox[3], bbox[0]:bbox[2], :] + h, w, _ = crop_image.shape + crop_image = cv2.resize( + crop_image, + (cfg.KEYPOINTS.input_shape[1], cfg.KEYPOINTS.input_shape[0])) + crop_image = crop_image.astype(np.float32) + + keypoints, state = self.simple_run(crop_image) + + res = keypoints[0][:self.keypoint_num].reshape((-1, 2)) + res[:, 0] = res[:, 0] * w / cfg.KEYPOINTS.input_shape[1] + res[:, 1] = res[:, 1] * h / cfg.KEYPOINTS.input_shape[0] + + landmark = [] + for _index in range(res.shape[0]): + x_y = res[_index] + landmark.append([ + int(x_y[0] * cfg.KEYPOINTS.input_shape[0] + bbox[0] - add), + int(x_y[1] * cfg.KEYPOINTS.input_shape[1] + bbox[1] - add) + ]) + + landmark = np.array(landmark, np.float32) + + return landmark, state + + def init_model(self, *args): + + if len(args) == 1: + use_pb = True + pb_path = args[0] + else: + use_pb = False + meta_path = args[0] + restore_model_path = args[1] + + def ini_ckpt(): + graph = tf.Graph() + graph.as_default() + configProto = tf.ConfigProto() + configProto.gpu_options.allow_growth = True + sess = tf.Session(config=configProto) + # load_model(model_path, sess) + saver = tf.train.import_meta_graph(meta_path) + saver.restore(sess, restore_model_path) + + print('Model restred!') + return (graph, sess) + + def init_pb(model_path): + config = tf.ConfigProto() + config.gpu_options.per_process_gpu_memory_fraction = 0.2 + compute_graph = tf.Graph() + compute_graph.as_default() + sess = tf.Session(config=config) + with tf.gfile.GFile(model_path, 'rb') as fid: + graph_def = tf.GraphDef() + graph_def.ParseFromString(fid.read()) + tf.import_graph_def(graph_def, name='') + + # saver = tf.train.Saver(tf.global_variables()) + # saver.save(sess, save_path='./tmp.ckpt') + return (compute_graph, sess) + + if use_pb: + model = init_pb(pb_path) + else: + model = ini_ckpt() + + graph = model[0] + sess = model[1] + + return graph, sess diff --git a/maas_lib/models/cv/cartoon/facelib/facer.py b/maas_lib/models/cv/cartoon/facelib/facer.py new file mode 100644 index 00000000..62388ab9 --- /dev/null +++ b/maas_lib/models/cv/cartoon/facelib/facer.py @@ -0,0 +1,150 @@ +import time + +import cv2 +import numpy as np + +from .config import config as cfg +from .face_detector import FaceDetector +from .face_landmark import FaceLandmark +from .LK.lk import GroupTrack + + +class FaceAna(): + ''' + by default the top3 facea sorted by area will be calculated for time reason + ''' + + def __init__(self, model_dir): + self.face_detector = FaceDetector(model_dir) + self.face_landmark = FaceLandmark(model_dir) + self.trace = GroupTrack() + + self.track_box = None + self.previous_image = None + self.previous_box = None + + self.diff_thres = 5 + self.top_k = cfg.DETECT.topk + self.iou_thres = cfg.TRACE.iou_thres + self.alpha = cfg.TRACE.smooth_box + + def run(self, image): + + boxes = self.face_detector(image) + + if boxes.shape[0] > self.top_k: + boxes = self.sort(boxes) + + boxes_return = np.array(boxes) + landmarks, states = self.face_landmark(image, boxes) + + if 1: + track = [] + for i in range(landmarks.shape[0]): + track.append([ + np.min(landmarks[i][:, 0]), + np.min(landmarks[i][:, 1]), + np.max(landmarks[i][:, 0]), + np.max(landmarks[i][:, 1]) + ]) + tmp_box = np.array(track) + + self.track_box = self.judge_boxs(boxes_return, tmp_box) + + self.track_box, landmarks = self.sort_res(self.track_box, landmarks) + return self.track_box, landmarks, states + + def sort_res(self, bboxes, points): + area = [] + for bbox in bboxes: + bbox_width = bbox[2] - bbox[0] + bbox_height = bbox[3] - bbox[1] + area.append(bbox_height * bbox_width) + + area = np.array(area) + picked = area.argsort()[::-1] + sorted_bboxes = [bboxes[x] for x in picked] + sorted_points = [points[x] for x in picked] + return np.array(sorted_bboxes), np.array(sorted_points) + + def diff_frames(self, previous_frame, image): + if previous_frame is None: + return True + else: + _diff = cv2.absdiff(previous_frame, image) + diff = np.sum( + _diff) / previous_frame.shape[0] / previous_frame.shape[1] / 3. + return diff > self.diff_thres + + def sort(self, bboxes): + if self.top_k > 100: + return bboxes + area = [] + for bbox in bboxes: + + bbox_width = bbox[2] - bbox[0] + bbox_height = bbox[3] - bbox[1] + area.append(bbox_height * bbox_width) + + area = np.array(area) + + picked = area.argsort()[-self.top_k:][::-1] + sorted_bboxes = [bboxes[x] for x in picked] + return np.array(sorted_bboxes) + + def judge_boxs(self, previuous_bboxs, now_bboxs): + + def iou(rec1, rec2): + + # computing area of each rectangles + S_rec1 = (rec1[2] - rec1[0]) * (rec1[3] - rec1[1]) + S_rec2 = (rec2[2] - rec2[0]) * (rec2[3] - rec2[1]) + + # computing the sum_area + sum_area = S_rec1 + S_rec2 + + # find the each edge of intersect rectangle + x1 = max(rec1[0], rec2[0]) + y1 = max(rec1[1], rec2[1]) + x2 = min(rec1[2], rec2[2]) + y2 = min(rec1[3], rec2[3]) + + # judge if there is an intersect + intersect = max(0, x2 - x1) * max(0, y2 - y1) + + return intersect / (sum_area - intersect) + + if previuous_bboxs is None: + return now_bboxs + + result = [] + + for i in range(now_bboxs.shape[0]): + contain = False + for j in range(previuous_bboxs.shape[0]): + if iou(now_bboxs[i], previuous_bboxs[j]) > self.iou_thres: + result.append( + self.smooth(now_bboxs[i], previuous_bboxs[j])) + contain = True + break + if not contain: + result.append(now_bboxs[i]) + + return np.array(result) + + def smooth(self, now_box, previous_box): + + return self.do_moving_average(now_box[:4], previous_box[:4]) + + def do_moving_average(self, p_now, p_previous): + p = self.alpha * p_now + (1 - self.alpha) * p_previous + return p + + def reset(self): + ''' + reset the previous info used foe tracking, + :return: + ''' + self.track_box = None + self.previous_image = None + self.previous_box = None diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/LICENSE b/maas_lib/models/cv/cartoon/mtcnn_pytorch/LICENSE new file mode 100644 index 00000000..9210f5b8 --- /dev/null +++ b/maas_lib/models/cv/cartoon/mtcnn_pytorch/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Dan Antoshchenko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/README.md b/maas_lib/models/cv/cartoon/mtcnn_pytorch/README.md new file mode 100644 index 00000000..b748cf58 --- /dev/null +++ b/maas_lib/models/cv/cartoon/mtcnn_pytorch/README.md @@ -0,0 +1,26 @@ +# MTCNN + +`pytorch` implementation of **inference stage** of face detection algorithm described in +[Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks](https://arxiv.org/abs/1604.02878). + +## Example +![example of a face detection](images/example.png) + +## How to use it +Just download the repository and then do this +```python +from src import detect_faces +from PIL import Image + +image = Image.open('image.jpg') +bounding_boxes, landmarks = detect_faces(image) +``` +For examples see `test_on_images.ipynb`. + +## Requirements +* pytorch 0.2 +* Pillow, numpy + +## Credit +This implementation is heavily inspired by: +* [pangyupo/mxnet_mtcnn_face_detection](https://github.com/pangyupo/mxnet_mtcnn_face_detection) diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/__init__.py b/maas_lib/models/cv/cartoon/mtcnn_pytorch/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/__init__.py b/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py b/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py new file mode 100644 index 00000000..baa3ba73 --- /dev/null +++ b/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py @@ -0,0 +1,187 @@ +""" +Created on Mon Apr 24 15:43:29 2017 +@author: zhaoy +""" +import cv2 +import numpy as np + +from .matlab_cp2tform import get_similarity_transform_for_cv2 + +# reference facial points, a list of coordinates (x,y) +dx = 1 +dy = 1 +REFERENCE_FACIAL_POINTS = [ + [30.29459953 + dx, 51.69630051 + dy], # left eye + [65.53179932 + dx, 51.50139999 + dy], # right eye + [48.02519989 + dx, 71.73660278 + dy], # nose + [33.54930115 + dx, 92.3655014 + dy], # left mouth + [62.72990036 + dx, 92.20410156 + dy] # right mouth +] + +DEFAULT_CROP_SIZE = (96, 112) + +global FACIAL_POINTS + + +class FaceWarpException(Exception): + + def __str__(self): + return 'In File {}:{}'.format(__file__, super.__str__(self)) + + +def get_reference_facial_points(output_size=None, + inner_padding_factor=0.0, + outer_padding=(0, 0), + default_square=False): + + tmp_5pts = np.array(REFERENCE_FACIAL_POINTS) + tmp_crop_size = np.array(DEFAULT_CROP_SIZE) + + # 0) make the inner region a square + if default_square: + size_diff = max(tmp_crop_size) - tmp_crop_size + tmp_5pts += size_diff / 2 + tmp_crop_size += size_diff + + h_crop = tmp_crop_size[0] + w_crop = tmp_crop_size[1] + if (output_size): + if (output_size[0] == h_crop and output_size[1] == w_crop): + return tmp_5pts + + if (inner_padding_factor == 0 and outer_padding == (0, 0)): + if output_size is None: + return tmp_5pts + else: + raise FaceWarpException( + 'No paddings to do, output_size must be None or {}'.format( + tmp_crop_size)) + + # check output size + if not (0 <= inner_padding_factor <= 1.0): + raise FaceWarpException('Not (0 <= inner_padding_factor <= 1.0)') + + factor = inner_padding_factor > 0 or outer_padding[0] > 0 + factor = factor or outer_padding[1] > 0 + if (factor and output_size is None): + output_size = tmp_crop_size * \ + (1 + inner_padding_factor * 2).astype(np.int32) + output_size += np.array(outer_padding) + + cond1 = outer_padding[0] < output_size[0] + cond2 = outer_padding[1] < output_size[1] + if not (cond1 and cond2): + raise FaceWarpException('Not (outer_padding[0] < output_size[0]' + 'and outer_padding[1] < output_size[1])') + + # 1) pad the inner region according inner_padding_factor + if inner_padding_factor > 0: + size_diff = tmp_crop_size * inner_padding_factor * 2 + tmp_5pts += size_diff / 2 + tmp_crop_size += np.round(size_diff).astype(np.int32) + + # 2) resize the padded inner region + size_bf_outer_pad = np.array(output_size) - np.array(outer_padding) * 2 + + if size_bf_outer_pad[0] * tmp_crop_size[1] != size_bf_outer_pad[ + 1] * tmp_crop_size[0]: + raise FaceWarpException( + 'Must have (output_size - outer_padding)' + '= some_scale * (crop_size * (1.0 + inner_padding_factor)') + + scale_factor = size_bf_outer_pad[0].astype(np.float32) / tmp_crop_size[0] + tmp_5pts = tmp_5pts * scale_factor + + # 3) add outer_padding to make output_size + reference_5point = tmp_5pts + np.array(outer_padding) + + return reference_5point + + +def get_affine_transform_matrix(src_pts, dst_pts): + + tfm = np.float32([[1, 0, 0], [0, 1, 0]]) + n_pts = src_pts.shape[0] + ones = np.ones((n_pts, 1), src_pts.dtype) + src_pts_ = np.hstack([src_pts, ones]) + dst_pts_ = np.hstack([dst_pts, ones]) + + A, res, rank, s = np.linalg.lstsq(src_pts_, dst_pts_) + + if rank == 3: + tfm = np.float32([[A[0, 0], A[1, 0], A[2, 0]], + [A[0, 1], A[1, 1], A[2, 1]]]) + elif rank == 2: + tfm = np.float32([[A[0, 0], A[1, 0], 0], [A[0, 1], A[1, 1], 0]]) + + return tfm + + +def warp_and_crop_face(src_img, + facial_pts, + ratio=0.84, + reference_pts=None, + crop_size=(96, 112), + align_type='similarity' + '', + return_trans_inv=False): + + if reference_pts is None: + if crop_size[0] == 96 and crop_size[1] == 112: + reference_pts = REFERENCE_FACIAL_POINTS + else: + default_square = False + inner_padding_factor = 0 + outer_padding = (0, 0) + output_size = crop_size + + reference_pts = get_reference_facial_points( + output_size, inner_padding_factor, outer_padding, + default_square) + + ref_pts = np.float32(reference_pts) + + factor = ratio + ref_pts = (ref_pts - 112 / 2) * factor + 112 / 2 + ref_pts *= crop_size[0] / 112. + + ref_pts_shp = ref_pts.shape + if max(ref_pts_shp) < 3 or min(ref_pts_shp) != 2: + raise FaceWarpException( + 'reference_pts.shape must be (K,2) or (2,K) and K>2') + + if ref_pts_shp[0] == 2: + ref_pts = ref_pts.T + + src_pts = np.float32(facial_pts) + src_pts_shp = src_pts.shape + if max(src_pts_shp) < 3 or min(src_pts_shp) != 2: + raise FaceWarpException( + 'facial_pts.shape must be (K,2) or (2,K) and K>2') + + if src_pts_shp[0] == 2: + src_pts = src_pts.T + + if src_pts.shape != ref_pts.shape: + raise FaceWarpException( + 'facial_pts and reference_pts must have the same shape') + + if align_type == 'cv2_affine': + tfm = cv2.getAffineTransform(src_pts, ref_pts) + tfm_inv = cv2.getAffineTransform(ref_pts, src_pts) + + elif align_type == 'affine': + tfm = get_affine_transform_matrix(src_pts, ref_pts) + tfm_inv = get_affine_transform_matrix(ref_pts, src_pts) + else: + tfm, tfm_inv = get_similarity_transform_for_cv2(src_pts, ref_pts) + + face_img = cv2.warpAffine( + src_img, + tfm, (crop_size[0], crop_size[1]), + borderValue=(255, 255, 255)) + + if return_trans_inv: + return face_img, tfm_inv + else: + return face_img diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py b/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py new file mode 100644 index 00000000..96a5f965 --- /dev/null +++ b/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py @@ -0,0 +1,339 @@ +""" +Created on Tue Jul 11 06:54:28 2017 + +@author: zhaoyafei +""" + +import numpy as np +from numpy.linalg import inv, lstsq +from numpy.linalg import matrix_rank as rank +from numpy.linalg import norm + + +class MatlabCp2tormException(Exception): + + def __str__(self): + return 'In File {}:{}'.format(__file__, super.__str__(self)) + + +def tformfwd(trans, uv): + """ + Function: + ---------- + apply affine transform 'trans' to uv + + Parameters: + ---------- + @trans: 3x3 np.array + transform matrix + @uv: Kx2 np.array + each row is a pair of coordinates (x, y) + + Returns: + ---------- + @xy: Kx2 np.array + each row is a pair of transformed coordinates (x, y) + """ + uv = np.hstack((uv, np.ones((uv.shape[0], 1)))) + xy = np.dot(uv, trans) + xy = xy[:, 0:-1] + return xy + + +def tforminv(trans, uv): + """ + Function: + ---------- + apply the inverse of affine transform 'trans' to uv + + Parameters: + ---------- + @trans: 3x3 np.array + transform matrix + @uv: Kx2 np.array + each row is a pair of coordinates (x, y) + + Returns: + ---------- + @xy: Kx2 np.array + each row is a pair of inverse-transformed coordinates (x, y) + """ + Tinv = inv(trans) + xy = tformfwd(Tinv, uv) + return xy + + +def findNonreflectiveSimilarity(uv, xy, options=None): + + options = {'K': 2} + + K = options['K'] + M = xy.shape[0] + x = xy[:, 0].reshape((-1, 1)) # use reshape to keep a column vector + y = xy[:, 1].reshape((-1, 1)) # use reshape to keep a column vector + # print('--->x, y:\n', x, y + + tmp1 = np.hstack((x, y, np.ones((M, 1)), np.zeros((M, 1)))) + tmp2 = np.hstack((y, -x, np.zeros((M, 1)), np.ones((M, 1)))) + X = np.vstack((tmp1, tmp2)) + # print('--->X.shape: ', X.shape + # print('X:\n', X + + u = uv[:, 0].reshape((-1, 1)) # use reshape to keep a column vector + v = uv[:, 1].reshape((-1, 1)) # use reshape to keep a column vector + U = np.vstack((u, v)) + # print('--->U.shape: ', U.shape + # print('U:\n', U + + # We know that X * r = U + if rank(X) >= 2 * K: + r, _, _, _ = lstsq(X, U) + r = np.squeeze(r) + else: + raise Exception('cp2tform:twoUniquePointsReq') + + # print('--->r:\n', r + + sc = r[0] + ss = r[1] + tx = r[2] + ty = r[3] + + Tinv = np.array([[sc, -ss, 0], [ss, sc, 0], [tx, ty, 1]]) + + # print('--->Tinv:\n', Tinv + + T = inv(Tinv) + # print('--->T:\n', T + + T[:, 2] = np.array([0, 0, 1]) + + return T, Tinv + + +def findSimilarity(uv, xy, options=None): + + options = {'K': 2} + + # uv = np.array(uv) + # xy = np.array(xy) + + # Solve for trans1 + trans1, trans1_inv = findNonreflectiveSimilarity(uv, xy, options) + + # Solve for trans2 + + # manually reflect the xy data across the Y-axis + xyR = xy + xyR[:, 0] = -1 * xyR[:, 0] + + trans2r, trans2r_inv = findNonreflectiveSimilarity(uv, xyR, options) + + # manually reflect the tform to undo the reflection done on xyR + TreflectY = np.array([[-1, 0, 0], [0, 1, 0], [0, 0, 1]]) + + trans2 = np.dot(trans2r, TreflectY) + + # Figure out if trans1 or trans2 is better + xy1 = tformfwd(trans1, uv) + norm1 = norm(xy1 - xy) + + xy2 = tformfwd(trans2, uv) + norm2 = norm(xy2 - xy) + + if norm1 <= norm2: + return trans1, trans1_inv + else: + trans2_inv = inv(trans2) + return trans2, trans2_inv + + +def get_similarity_transform(src_pts, dst_pts, reflective=True): + """ + Function: + ---------- + Find Similarity Transform Matrix 'trans': + u = src_pts[:, 0] + v = src_pts[:, 1] + x = dst_pts[:, 0] + y = dst_pts[:, 1] + [x, y, 1] = [u, v, 1] * trans + + Parameters: + ---------- + @src_pts: Kx2 np.array + source points, each row is a pair of coordinates (x, y) + @dst_pts: Kx2 np.array + destination points, each row is a pair of transformed + coordinates (x, y) + @reflective: True or False + if True: + use reflective similarity transform + else: + use non-reflective similarity transform + + Returns: + ---------- + @trans: 3x3 np.array + transform matrix from uv to xy + trans_inv: 3x3 np.array + inverse of trans, transform matrix from xy to uv + """ + + if reflective: + trans, trans_inv = findSimilarity(src_pts, dst_pts) + else: + trans, trans_inv = findNonreflectiveSimilarity(src_pts, dst_pts) + + return trans, trans_inv + + +def cvt_tform_mat_for_cv2(trans): + """ + Function: + ---------- + Convert Transform Matrix 'trans' into 'cv2_trans' which could be + directly used by cv2.warpAffine(): + u = src_pts[:, 0] + v = src_pts[:, 1] + x = dst_pts[:, 0] + y = dst_pts[:, 1] + [x, y].T = cv_trans * [u, v, 1].T + + Parameters: + ---------- + @trans: 3x3 np.array + transform matrix from uv to xy + + Returns: + ---------- + @cv2_trans: 2x3 np.array + transform matrix from src_pts to dst_pts, could be directly used + for cv2.warpAffine() + """ + cv2_trans = trans[:, 0:2].T + + return cv2_trans + + +def get_similarity_transform_for_cv2(src_pts, dst_pts, reflective=True): + """ + Function: + ---------- + Find Similarity Transform Matrix 'cv2_trans' which could be + directly used by cv2.warpAffine(): + u = src_pts[:, 0] + v = src_pts[:, 1] + x = dst_pts[:, 0] + y = dst_pts[:, 1] + [x, y].T = cv_trans * [u, v, 1].T + + Parameters: + ---------- + @src_pts: Kx2 np.array + source points, each row is a pair of coordinates (x, y) + @dst_pts: Kx2 np.array + destination points, each row is a pair of transformed + coordinates (x, y) + reflective: True or False + if True: + use reflective similarity transform + else: + use non-reflective similarity transform + + Returns: + ---------- + @cv2_trans: 2x3 np.array + transform matrix from src_pts to dst_pts, could be directly used + for cv2.warpAffine() + """ + trans, trans_inv = get_similarity_transform(src_pts, dst_pts, reflective) + cv2_trans = cvt_tform_mat_for_cv2(trans) + cv2_trans_inv = cvt_tform_mat_for_cv2(trans_inv) + + return cv2_trans, cv2_trans_inv + + +if __name__ == '__main__': + """ + u = [0, 6, -2] + v = [0, 3, 5] + x = [-1, 0, 4] + y = [-1, -10, 4] + + # In Matlab, run: + # + # uv = [u'; v']; + # xy = [x'; y']; + # tform_sim=cp2tform(uv,xy,'similarity'); + # + # trans = tform_sim.tdata.T + # ans = + # -0.0764 -1.6190 0 + # 1.6190 -0.0764 0 + # -3.2156 0.0290 1.0000 + # trans_inv = tform_sim.tdata.Tinv + # ans = + # + # -0.0291 0.6163 0 + # -0.6163 -0.0291 0 + # -0.0756 1.9826 1.0000 + # xy_m=tformfwd(tform_sim, u,v) + # + # xy_m = + # + # -3.2156 0.0290 + # 1.1833 -9.9143 + # 5.0323 2.8853 + # uv_m=tforminv(tform_sim, x,y) + # + # uv_m = + # + # 0.5698 1.3953 + # 6.0872 2.2733 + # -2.6570 4.3314 + """ + u = [0, 6, -2] + v = [0, 3, 5] + x = [-1, 0, 4] + y = [-1, -10, 4] + + uv = np.array((u, v)).T + xy = np.array((x, y)).T + + print('\n--->uv:') + print(uv) + print('\n--->xy:') + print(xy) + + trans, trans_inv = get_similarity_transform(uv, xy) + + print('\n--->trans matrix:') + print(trans) + + print('\n--->trans_inv matrix:') + print(trans_inv) + + print('\n---> apply transform to uv') + print('\nxy_m = uv_augmented * trans') + uv_aug = np.hstack((uv, np.ones((uv.shape[0], 1)))) + xy_m = np.dot(uv_aug, trans) + print(xy_m) + + print('\nxy_m = tformfwd(trans, uv)') + xy_m = tformfwd(trans, uv) + print(xy_m) + + print('\n---> apply inverse transform to xy') + print('\nuv_m = xy_augmented * trans_inv') + xy_aug = np.hstack((xy, np.ones((xy.shape[0], 1)))) + uv_m = np.dot(xy_aug, trans_inv) + print(uv_m) + + print('\nuv_m = tformfwd(trans_inv, xy)') + uv_m = tformfwd(trans_inv, xy) + print(uv_m) + + uv_m = tforminv(trans, xy) + print('\nuv_m = tforminv(trans, xy)') + print(uv_m) diff --git a/maas_lib/models/cv/cartoon/utils.py b/maas_lib/models/cv/cartoon/utils.py new file mode 100644 index 00000000..39712653 --- /dev/null +++ b/maas_lib/models/cv/cartoon/utils.py @@ -0,0 +1,91 @@ +import os + +import cv2 +import numpy as np + + +def resize_size(image, size=720): + h, w, c = np.shape(image) + if min(h, w) > size: + if h > w: + h, w = int(size * h / w), size + else: + h, w = size, int(size * w / h) + image = cv2.resize(image, (w, h), interpolation=cv2.INTER_AREA) + return image + + +def padTo16x(image): + h, w, c = np.shape(image) + if h % 16 == 0 and w % 16 == 0: + return image, h, w + nh, nw = (h // 16 + 1) * 16, (w // 16 + 1) * 16 + img_new = np.ones((nh, nw, 3), np.uint8) * 255 + img_new[:h, :w, :] = image + + return img_new, h, w + + +def get_f5p(landmarks, np_img): + eye_left = find_pupil(landmarks[36:41], np_img) + eye_right = find_pupil(landmarks[42:47], np_img) + if eye_left is None or eye_right is None: + print('cannot find 5 points with find_puil, used mean instead.!') + eye_left = landmarks[36:41].mean(axis=0) + eye_right = landmarks[42:47].mean(axis=0) + nose = landmarks[30] + mouth_left = landmarks[48] + mouth_right = landmarks[54] + f5p = [[eye_left[0], eye_left[1]], [eye_right[0], eye_right[1]], + [nose[0], nose[1]], [mouth_left[0], mouth_left[1]], + [mouth_right[0], mouth_right[1]]] + return f5p + + +def find_pupil(landmarks, np_img): + h, w, _ = np_img.shape + xmax = int(landmarks[:, 0].max()) + xmin = int(landmarks[:, 0].min()) + ymax = int(landmarks[:, 1].max()) + ymin = int(landmarks[:, 1].min()) + + if ymin >= ymax or xmin >= xmax or ymin < 0 or xmin < 0 or ymax > h or xmax > w: + return None + eye_img_bgr = np_img[ymin:ymax, xmin:xmax, :] + eye_img = cv2.cvtColor(eye_img_bgr, cv2.COLOR_BGR2GRAY) + eye_img = cv2.equalizeHist(eye_img) + n_marks = landmarks - np.array([xmin, ymin]).reshape([1, 2]) + eye_mask = cv2.fillConvexPoly( + np.zeros_like(eye_img), n_marks.astype(np.int32), 1) + ret, thresh = cv2.threshold(eye_img, 100, 255, + cv2.THRESH_BINARY | cv2.THRESH_OTSU) + thresh = (1 - thresh / 255.) * eye_mask + cnt = 0 + xm = [] + ym = [] + for i in range(thresh.shape[0]): + for j in range(thresh.shape[1]): + if thresh[i, j] > 0.5: + xm.append(j) + ym.append(i) + cnt += 1 + if cnt != 0: + xm.sort() + ym.sort() + xm = xm[cnt // 2] + ym = ym[cnt // 2] + else: + xm = thresh.shape[1] / 2 + ym = thresh.shape[0] / 2 + + return xm + xmin, ym + ymin + + +def all_file(file_dir): + L = [] + for root, dirs, files in os.walk(file_dir): + for file in files: + extend = os.path.splitext(file)[1] + if extend == '.png' or extend == '.jpg' or extend == '.jpeg': + L.append(os.path.join(root, file)) + return L diff --git a/maas_lib/pipelines/cv/__init__.py b/maas_lib/pipelines/cv/__init__.py index 6f877a26..79c85c19 100644 --- a/maas_lib/pipelines/cv/__init__.py +++ b/maas_lib/pipelines/cv/__init__.py @@ -1 +1,2 @@ +from .image_cartoon_pipeline import ImageCartoonPipeline from .image_matting_pipeline import ImageMattingPipeline diff --git a/maas_lib/pipelines/cv/image_cartoon_pipeline.py b/maas_lib/pipelines/cv/image_cartoon_pipeline.py new file mode 100644 index 00000000..88c2eb15 --- /dev/null +++ b/maas_lib/pipelines/cv/image_cartoon_pipeline.py @@ -0,0 +1,149 @@ +import os +from typing import Any, Dict + +import cv2 +import numpy as np +import PIL +import tensorflow as tf + +from maas_lib.models.cv.cartoon.facelib.facer import FaceAna +from maas_lib.models.cv.cartoon.mtcnn_pytorch.src.align_trans import ( + get_reference_facial_points, warp_and_crop_face) +from maas_lib.models.cv.cartoon.utils import get_f5p, padTo16x, resize_size +from maas_lib.pipelines.base import Input +from maas_lib.preprocessors import load_image +from maas_lib.utils.constant import Tasks +from maas_lib.utils.logger import get_logger +from ..base import Pipeline +from ..builder import PIPELINES + +if tf.__version__ >= '2.0': + tf = tf.compat.v1 + tf.disable_eager_execution() + +logger = get_logger() + + +@PIPELINES.register_module( + Tasks.image_generation, module_name='cv_unet_person-image-cartoon') +class ImageCartoonPipeline(Pipeline): + + def __init__(self, model: str): + super().__init__(model=model) + + self.facer = FaceAna(model) + self.sess_anime_head = self.load_sess( + os.path.join(model, 'cartoon_anime_h.pb'), 'model_anime_head') + self.sess_anime_bg = self.load_sess( + os.path.join(model, 'cartoon_anime_bg.pb'), 'model_anime_bg') + + self.box_width = 288 + global_mask = cv2.imread(os.path.join(model, 'alpha.jpg')) + global_mask = cv2.resize( + global_mask, (self.box_width, self.box_width), + interpolation=cv2.INTER_AREA) + self.global_mask = cv2.cvtColor( + global_mask, cv2.COLOR_BGR2GRAY).astype(np.float32) / 255.0 + + def load_sess(self, model_path, name): + config = tf.ConfigProto(allow_soft_placement=True) + config.gpu_options.allow_growth = True + sess = tf.Session(config=config) + logger.info(f'loading model from {model_path}') + with tf.gfile.FastGFile(model_path, 'rb') as f: + graph_def = tf.GraphDef() + graph_def.ParseFromString(f.read()) + sess.graph.as_default() + tf.import_graph_def(graph_def, name=name) + sess.run(tf.global_variables_initializer()) + logger.info(f'load model {model_path} done.') + return sess + + def preprocess(self, input: Input) -> Dict[str, Any]: + if isinstance(input, str): + img = np.array(load_image(input)) + elif isinstance(input, PIL.Image.Image): + img = np.array(input.convert('RGB')) + elif isinstance(input, np.ndarray): + if len(input.shape) == 2: + input = cv2.cvtColor(input, cv2.COLOR_GRAY2BGR) + img = input[:, :, ::-1] + else: + raise TypeError(f'input should be either str, PIL.Image,' + f' np.array, but got {type(input)}') + img = img.astype(np.float) + result = {'img': img} + return result + + def detect_face(self, img): + src_h, src_w, _ = img.shape + boxes, landmarks, _ = self.facer.run(img) + if boxes.shape[0] == 0: + return None + else: + return landmarks + + def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: + + img = input['img'].astype(np.uint8) + ori_h, ori_w, _ = img.shape + img = resize_size(img, size=720) + + img_brg = img[:, :, ::-1] + + landmarks = self.detect_face(img) + if landmarks is None: + print('No face detected!') + return {'output_png': None} + + # background process + pad_bg, pad_h, pad_w = padTo16x(img_brg) + + bg_res = self.sess_anime_bg.run( + self.sess_anime_bg.graph.get_tensor_by_name( + 'model_anime_bg/output_image:0'), + feed_dict={'model_anime_bg/input_image:0': pad_bg}) + res = bg_res[:pad_h, :pad_w, :] + + for landmark in landmarks: + # get facial 5 points + f5p = get_f5p(landmark, img_brg) + + # face alignment + head_img, trans_inv = warp_and_crop_face( + img, + f5p, + ratio=0.75, + reference_pts=get_reference_facial_points(default_square=True), + crop_size=(self.box_width, self.box_width), + return_trans_inv=True) + + # head process + head_res = self.sess_anime_head.run( + self.sess_anime_head.graph.get_tensor_by_name( + 'model_anime_head/output_image:0'), + feed_dict={ + 'model_anime_head/input_image:0': head_img[:, :, ::-1] + }) + + # merge head and background + head_trans_inv = cv2.warpAffine( + head_res, + trans_inv, (np.size(img, 1), np.size(img, 0)), + borderValue=(0, 0, 0)) + + mask = self.global_mask + mask_trans_inv = cv2.warpAffine( + mask, + trans_inv, (np.size(img, 1), np.size(img, 0)), + borderValue=(0, 0, 0)) + mask_trans_inv = np.expand_dims(mask_trans_inv, 2) + + res = mask_trans_inv * head_trans_inv + (1 - mask_trans_inv) * res + + res = cv2.resize(res, (ori_w, ori_h), interpolation=cv2.INTER_AREA) + + return {'output_png': res} + + def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: + return inputs diff --git a/requirements.txt b/requirements.txt index 1944b476..39eb5e23 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ -r requirements/pipeline.txt -r requirements/multi-modal.txt -r requirements/nlp.txt +-r requirements/cv.txt diff --git a/requirements/cv.txt b/requirements/cv.txt new file mode 100644 index 00000000..66799b76 --- /dev/null +++ b/requirements/cv.txt @@ -0,0 +1 @@ +easydict diff --git a/tests/pipelines/test_person_image_cartoon.py b/tests/pipelines/test_person_image_cartoon.py new file mode 100644 index 00000000..dae853d7 --- /dev/null +++ b/tests/pipelines/test_person_image_cartoon.py @@ -0,0 +1,38 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +import os +import unittest + +import cv2 + +from maas_lib.pipelines import pipeline +from maas_lib.utils.constant import Tasks + + +def all_file(file_dir): + L = [] + for root, dirs, files in os.walk(file_dir): + for file in files: + extend = os.path.splitext(file)[1] + if extend == '.png' or extend == '.jpg' or extend == '.jpeg' or extend == '.JPG' or extend == '.HEIC': + L.append(os.path.join(root, file)) + return L + + +class ImageCartoonTest(unittest.TestCase): + + def test_run(self): + model_dir = './assets' + if not os.path.exists(model_dir): + os.system( + 'wget https://invi-label.oss-cn-shanghai.aliyuncs.com/label/model/cartoon/assets.zip' + ) + os.system('unzip assets.zip') + + img_cartoon = pipeline(Tasks.image_generation, model=model_dir) + result = img_cartoon(os.path.join(model_dir, 'test.png')) + if result is not None: + cv2.imwrite('result.png', result['output_png']) + + +if __name__ == '__main__': + unittest.main() From dd0019581414200f068ded2438ef8f1d97780a86 Mon Sep 17 00:00:00 2001 From: "wenmeng.zwm" Date: Thu, 9 Jun 2022 16:57:33 +0800 Subject: [PATCH 10/13] [to #42362853] add default model support and fix circular import 1. add default model support 2. fix circular import 3. temporarily skip ofa and palm test which costs too much time Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8981076 --- docs/source/develop.md | 6 +++ maas_lib/models/base.py | 4 +- maas_lib/pipelines/base.py | 6 +-- maas_lib/pipelines/builder.py | 27 +++++------ maas_lib/pipelines/default.py | 48 +++++++++++++++++++ .../pipelines/multi_modal/image_captioning.py | 8 ++-- maas_lib/pipelines/util.py | 10 ---- maas_lib/utils/hub.py | 14 ++++++ maas_lib/utils/registry.py | 6 +++ tests/pipelines/test_base.py | 2 + tests/pipelines/test_image_captioning.py | 1 + tests/pipelines/test_image_matting.py | 14 +++++- tests/pipelines/test_text_classification.py | 11 ++++- tests/pipelines/test_text_generation.py | 5 ++ 14 files changed, 124 insertions(+), 38 deletions(-) create mode 100644 maas_lib/pipelines/default.py create mode 100644 maas_lib/utils/hub.py diff --git a/docs/source/develop.md b/docs/source/develop.md index 0d4f7f26..c048bef7 100644 --- a/docs/source/develop.md +++ b/docs/source/develop.md @@ -71,12 +71,18 @@ TODO * Feature ```shell [to #AONE_ID] feat: commit title + + Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8949062 + * commit msg1 * commit msg2 ``` * Bugfix ```shell [to #AONE_ID] fix: commit title + + Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8949062 + * commit msg1 * commit msg2 ``` diff --git a/maas_lib/models/base.py b/maas_lib/models/base.py index 10425f6c..efda1b3e 100644 --- a/maas_lib/models/base.py +++ b/maas_lib/models/base.py @@ -8,9 +8,9 @@ from maas_hub.file_download import model_file_download from maas_hub.snapshot_download import snapshot_download from maas_lib.models.builder import build_model -from maas_lib.pipelines import util from maas_lib.utils.config import Config from maas_lib.utils.constant import CONFIGFILE +from maas_lib.utils.hub import get_model_cache_dir Tensor = Union['torch.Tensor', 'tf.Tensor'] @@ -40,7 +40,7 @@ class Model(ABC): if osp.exists(model_name_or_path): local_model_dir = model_name_or_path else: - cache_path = util.get_model_cache_dir(model_name_or_path) + cache_path = get_model_cache_dir(model_name_or_path) local_model_dir = cache_path if osp.exists( cache_path) else snapshot_download(model_name_or_path) # else: diff --git a/maas_lib/pipelines/base.py b/maas_lib/pipelines/base.py index 76747b05..1ba8c36a 100644 --- a/maas_lib/pipelines/base.py +++ b/maas_lib/pipelines/base.py @@ -6,11 +6,11 @@ from typing import Any, Dict, Generator, List, Union from maas_hub.snapshot_download import snapshot_download -from maas_lib.models import Model -from maas_lib.pipelines import util +from maas_lib.models.base import Model from maas_lib.preprocessors import Preprocessor from maas_lib.pydatasets import PyDataset from maas_lib.utils.config import Config +from maas_lib.utils.hub import get_model_cache_dir from .util import is_model_name Tensor = Union['torch.Tensor', 'tf.Tensor'] @@ -26,7 +26,7 @@ class Pipeline(ABC): def initiate_single_model(self, model): if isinstance(model, str): if not osp.exists(model): - cache_path = util.get_model_cache_dir(model) + cache_path = get_model_cache_dir(model) model = cache_path if osp.exists( cache_path) else snapshot_download(model) return Model.from_pretrained(model) if is_model_name( diff --git a/maas_lib/pipelines/builder.py b/maas_lib/pipelines/builder.py index dd146cca..cd1eb32f 100644 --- a/maas_lib/pipelines/builder.py +++ b/maas_lib/pipelines/builder.py @@ -1,7 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import os.path as osp -from typing import List, Union +from typing import Union import json from maas_hub.file_download import model_file_download @@ -10,7 +10,8 @@ from maas_lib.models.base import Model from maas_lib.utils.config import Config, ConfigDict from maas_lib.utils.constant import CONFIGFILE, Tasks from maas_lib.utils.registry import Registry, build_from_cfg -from .base import InputModel, Pipeline +from .base import Pipeline +from .default import DEFAULT_MODEL_FOR_PIPELINE, get_default_pipeline_info from .util import is_model_name PIPELINES = Registry('pipelines') @@ -32,7 +33,7 @@ def build_pipeline(cfg: ConfigDict, def pipeline(task: str = None, - model: Union[InputModel, List[InputModel]] = None, + model: Union[str, Model] = None, preprocessor=None, config_file: str = None, pipeline_name: str = None, @@ -67,23 +68,19 @@ def pipeline(task: str = None, if pipeline_name is None: # get default pipeline for this task - assert task in PIPELINES.modules, f'No pipeline is registered for Task {task}' - pipeline_name = get_default_pipeline(task) + pipeline_name, default_model_repo = get_default_pipeline_info(task) + if model is None: + model = default_model_repo + + assert isinstance(model, (type(None), str, Model)), \ + f'model should be either None, str or Model, but got {type(model)}' + + cfg = ConfigDict(type=pipeline_name, model=model) - cfg = ConfigDict(type=pipeline_name) if kwargs: cfg.update(kwargs) - if model: - assert isinstance(model, (str, Model, List)), \ - f'model should be either (list of) str or Model, but got {type(model)}' - cfg.model = model - if preprocessor is not None: cfg.preprocessor = preprocessor return build_pipeline(cfg, task_name=task) - - -def get_default_pipeline(task): - return list(PIPELINES.modules[task].keys())[0] diff --git a/maas_lib/pipelines/default.py b/maas_lib/pipelines/default.py new file mode 100644 index 00000000..5d364288 --- /dev/null +++ b/maas_lib/pipelines/default.py @@ -0,0 +1,48 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. + +from maas_lib.utils.constant import Tasks + +DEFAULT_MODEL_FOR_PIPELINE = { + # TaskName: (pipeline_module_name, model_repo) + Tasks.image_matting: ('image-matting', 'damo/image-matting-person'), + Tasks.text_classification: + ('bert-sentiment-analysis', 'damo/bert-base-sst2'), + Tasks.text_generation: ('palm', 'damo/nlp_palm_text-generation_chinese'), + Tasks.image_captioning: ('ofa', None), +} + + +def add_default_pipeline_info(task: str, + model_name: str, + modelhub_name: str = None, + overwrite: bool = False): + """ Add default model for a task. + + Args: + task (str): task name. + model_name (str): model_name. + modelhub_name (str): name for default modelhub. + overwrite (bool): overwrite default info. + """ + if not overwrite: + assert task not in DEFAULT_MODEL_FOR_PIPELINE, \ + f'task {task} already has default model.' + + DEFAULT_MODEL_FOR_PIPELINE[task] = (model_name, modelhub_name) + + +def get_default_pipeline_info(task): + """ Get default info for certain task. + + Args: + task (str): task name. + + Return: + A tuple: first element is pipeline name(model_name), second element + is modelhub name. + """ + assert task in DEFAULT_MODEL_FOR_PIPELINE, \ + f'No default pipeline is registered for Task {task}' + + pipeline_name, default_model = DEFAULT_MODEL_FOR_PIPELINE[task] + return pipeline_name, default_model diff --git a/maas_lib/pipelines/multi_modal/image_captioning.py b/maas_lib/pipelines/multi_modal/image_captioning.py index 778354b7..2d8cc618 100644 --- a/maas_lib/pipelines/multi_modal/image_captioning.py +++ b/maas_lib/pipelines/multi_modal/image_captioning.py @@ -2,10 +2,6 @@ from typing import Any, Dict import numpy as np import torch -from fairseq import checkpoint_utils, tasks, utils -from ofa.models.ofa import OFAModel -from ofa.tasks.mm_tasks import CaptionTask -from ofa.utils.eval_utils import eval_caption from PIL import Image from maas_lib.pipelines.base import Input @@ -24,6 +20,8 @@ class ImageCaptionPipeline(Pipeline): def __init__(self, model: str, bpe_dir: str): super().__init__() # turn on cuda if GPU is available + from fairseq import checkpoint_utils, tasks, utils + from ofa.tasks.mm_tasks import CaptionTask tasks.register_task('caption', CaptionTask) use_cuda = False @@ -106,6 +104,8 @@ class ImageCaptionPipeline(Pipeline): return sample def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: + from ofa.utils.eval_utils import eval_caption + results, _ = eval_caption(self.task, self.generator, self.models, input) return { diff --git a/maas_lib/pipelines/util.py b/maas_lib/pipelines/util.py index 4a0a28ec..771e0d2b 100644 --- a/maas_lib/pipelines/util.py +++ b/maas_lib/pipelines/util.py @@ -3,21 +3,11 @@ import os import os.path as osp import json -from maas_hub.constants import MODEL_ID_SEPARATOR from maas_hub.file_download import model_file_download from maas_lib.utils.constant import CONFIGFILE -# temp solution before the hub-cache is in place -def get_model_cache_dir(model_id: str, branch: str = 'master'): - model_id_expanded = model_id.replace('/', - MODEL_ID_SEPARATOR) + '.' + branch - default_cache_dir = os.path.expanduser(os.path.join('~/.cache', 'maas')) - return os.getenv('MAAS_CACHE', - os.path.join(default_cache_dir, 'hub', model_id_expanded)) - - def is_model_name(model): if osp.exists(model): if osp.exists(osp.join(model, CONFIGFILE)): diff --git a/maas_lib/utils/hub.py b/maas_lib/utils/hub.py new file mode 100644 index 00000000..2f61b148 --- /dev/null +++ b/maas_lib/utils/hub.py @@ -0,0 +1,14 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. + +import os + +from maas_hub.constants import MODEL_ID_SEPARATOR + + +# temp solution before the hub-cache is in place +def get_model_cache_dir(model_id: str, branch: str = 'master'): + model_id_expanded = model_id.replace('/', + MODEL_ID_SEPARATOR) + '.' + branch + default_cache_dir = os.path.expanduser(os.path.join('~/.cache', 'maas')) + return os.getenv('MAAS_CACHE', + os.path.join(default_cache_dir, 'hub', model_id_expanded)) diff --git a/maas_lib/utils/registry.py b/maas_lib/utils/registry.py index 838e6f83..bac3d616 100644 --- a/maas_lib/utils/registry.py +++ b/maas_lib/utils/registry.py @@ -100,6 +100,12 @@ class Registry(object): >>> class SwinTransformerDefaultGroup: >>> pass + >>> class SwinTransformer2: + >>> pass + >>> MODELS.register_module('image-classification', + module_name='SwinT2', + module_cls=SwinTransformer2) + Args: group_key: Group name of which module will be registered, default group name is 'default' diff --git a/tests/pipelines/test_base.py b/tests/pipelines/test_base.py index d523e7c4..5994ddde 100644 --- a/tests/pipelines/test_base.py +++ b/tests/pipelines/test_base.py @@ -8,6 +8,7 @@ import PIL from maas_lib.pipelines import Pipeline, pipeline from maas_lib.pipelines.builder import PIPELINES +from maas_lib.pipelines.default import add_default_pipeline_info from maas_lib.utils.constant import Tasks from maas_lib.utils.logger import get_logger from maas_lib.utils.registry import default_group @@ -75,6 +76,7 @@ class CustomPipelineTest(unittest.TestCase): return inputs self.assertTrue('custom-image' in PIPELINES.modules[default_group]) + add_default_pipeline_info(Tasks.image_tagging, 'custom-image') pipe = pipeline(pipeline_name='custom-image') pipe2 = pipeline(Tasks.image_tagging) self.assertTrue(type(pipe) is type(pipe2)) diff --git a/tests/pipelines/test_image_captioning.py b/tests/pipelines/test_image_captioning.py index f951f0a8..afcab01d 100644 --- a/tests/pipelines/test_image_captioning.py +++ b/tests/pipelines/test_image_captioning.py @@ -11,6 +11,7 @@ from maas_lib.utils.constant import Tasks class ImageCaptionTest(unittest.TestCase): + @unittest.skip('skip long test') def test_run(self): model = 'https://ofa-beijing.oss-cn-beijing.aliyuncs.com/checkpoints/caption_large_best_clean.pt' diff --git a/tests/pipelines/test_image_matting.py b/tests/pipelines/test_image_matting.py index 8153b70d..25f19102 100644 --- a/tests/pipelines/test_image_matting.py +++ b/tests/pipelines/test_image_matting.py @@ -7,9 +7,10 @@ import unittest import cv2 from maas_lib.fileio import File -from maas_lib.pipelines import pipeline, util +from maas_lib.pipelines import pipeline from maas_lib.pydatasets import PyDataset from maas_lib.utils.constant import Tasks +from maas_lib.utils.hub import get_model_cache_dir class ImageMattingTest(unittest.TestCase): @@ -20,7 +21,7 @@ class ImageMattingTest(unittest.TestCase): purge_cache = True if purge_cache: shutil.rmtree( - util.get_model_cache_dir(self.model_id), ignore_errors=True) + get_model_cache_dir(self.model_id), ignore_errors=True) def test_run(self): model_path = 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs' \ @@ -59,6 +60,15 @@ class ImageMattingTest(unittest.TestCase): cv2.imwrite('result.png', result['output_png']) print(f'Output written to {osp.abspath("result.png")}') + def test_run_modelhub_default_model(self): + img_matting = pipeline(Tasks.image_matting) + + result = img_matting( + 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png' + ) + cv2.imwrite('result.png', result['output_png']) + print(f'Output written to {osp.abspath("result.png")}') + if __name__ == '__main__': unittest.main() diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index b6528319..36285f80 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -7,10 +7,11 @@ from pathlib import Path from maas_lib.fileio import File from maas_lib.models import Model from maas_lib.models.nlp import BertForSequenceClassification -from maas_lib.pipelines import SequenceClassificationPipeline, pipeline, util +from maas_lib.pipelines import SequenceClassificationPipeline, pipeline from maas_lib.preprocessors import SequenceClassificationPreprocessor from maas_lib.pydatasets import PyDataset from maas_lib.utils.constant import Tasks +from maas_lib.utils.hub import get_model_cache_dir class SequenceClassificationTest(unittest.TestCase): @@ -21,7 +22,7 @@ class SequenceClassificationTest(unittest.TestCase): purge_cache = True if purge_cache: shutil.rmtree( - util.get_model_cache_dir(self.model_id), ignore_errors=True) + get_model_cache_dir(self.model_id), ignore_errors=True) def predict(self, pipeline_ins: SequenceClassificationPipeline): from easynlp.appzoo import load_dataset @@ -83,6 +84,12 @@ class SequenceClassificationTest(unittest.TestCase): PyDataset.load('glue', name='sst2', target='sentence')) self.printDataset(result) + def test_run_with_default_model(self): + text_classification = pipeline(task=Tasks.text_classification) + result = text_classification( + PyDataset.load('glue', name='sst2', target='sentence')) + self.printDataset(result) + def test_run_with_dataset(self): model = Model.from_pretrained(self.model_id) preprocessor = SequenceClassificationPreprocessor( diff --git a/tests/pipelines/test_text_generation.py b/tests/pipelines/test_text_generation.py index d59fdabb..235279c2 100644 --- a/tests/pipelines/test_text_generation.py +++ b/tests/pipelines/test_text_generation.py @@ -15,6 +15,7 @@ class TextGenerationTest(unittest.TestCase): input1 = "今日天气类型='晴'&温度变化趋势='大幅上升'&最低气温='28℃'&最高气温='31℃'&体感='湿热'" input2 = "今日天气类型='多云'&体感='舒适'&最低气温='26℃'&最高气温='30℃'" + @unittest.skip('skip temporarily to save test time') def test_run(self): cache_path = snapshot_download(self.model_id) preprocessor = TextGenerationPreprocessor( @@ -41,6 +42,10 @@ class TextGenerationTest(unittest.TestCase): task=Tasks.text_generation, model=self.model_id) print(pipeline_ins(self.input2)) + def test_run_with_default_model(self): + pipeline_ins = pipeline(task=Tasks.text_generation) + print(pipeline_ins(self.input2)) + if __name__ == '__main__': unittest.main() From 1f6b37659933898dccfbe73f4308d08ee9b09323 Mon Sep 17 00:00:00 2001 From: "wenmeng.zwm" Date: Thu, 9 Jun 2022 20:16:26 +0800 Subject: [PATCH 11/13] [to #42373878] refactor maaslib to modelscope 1. refactor maaslib to modelscope 2. fix UT error 3. support pipeline which does not register default model Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8988388 --- .dev_scripts/build_docs.sh | 2 +- .dev_scripts/linter.sh | 6 +- LICENSE | 4 +- MANIFEST.in | 2 +- README.md | 2 +- configs/README.md | 2 +- docs/source/api/maas_lib.fileio.format.rst | 34 ---------- docs/source/api/maas_lib.fileio.rst | 34 ---------- docs/source/api/maas_lib.models.nlp.rst | 18 ----- docs/source/api/maas_lib.models.rst | 34 ---------- docs/source/api/maas_lib.pipelines.audio.rst | 7 -- docs/source/api/maas_lib.pipelines.cv.rst | 18 ----- .../api/maas_lib.pipelines.multi_modal.rst | 7 -- docs/source/api/maas_lib.preprocessors.rst | 50 -------------- docs/source/api/maas_lib.rst | 30 --------- docs/source/api/maas_lib.trainers.nlp.rst | 18 ----- docs/source/api/maas_lib.trainers.rst | 34 ---------- docs/source/api/maas_lib.utils.rst | 58 ---------------- docs/source/api/modelscope.fileio.format.rst | 34 ++++++++++ docs/source/api/modelscope.fileio.rst | 34 ++++++++++ ...odelscope.models.cv.cartoon.facelib.LK.rst | 18 +++++ .../modelscope.models.cv.cartoon.facelib.rst | 50 ++++++++++++++ ...lscope.models.cv.cartoon.mtcnn_pytorch.rst | 15 +++++ ...pe.models.cv.cartoon.mtcnn_pytorch.src.rst | 26 ++++++++ .../api/modelscope.models.cv.cartoon.rst | 27 ++++++++ docs/source/api/modelscope.models.cv.rst | 15 +++++ docs/source/api/modelscope.models.nlp.rst | 26 ++++++++ docs/source/api/modelscope.models.rst | 35 ++++++++++ .../source/api/modelscope.pipelines.audio.rst | 7 ++ docs/source/api/modelscope.pipelines.cv.rst | 26 ++++++++ .../api/modelscope.pipelines.multi_modal.rst | 18 +++++ docs/source/api/modelscope.pipelines.nlp.rst | 26 ++++++++ docs/source/api/modelscope.pipelines.rst | 53 +++++++++++++++ docs/source/api/modelscope.preprocessors.rst | 50 ++++++++++++++ docs/source/api/modelscope.pydatasets.rst | 18 +++++ docs/source/api/modelscope.rst | 32 +++++++++ ...es.nlp.rst => modelscope.trainers.nlp.rst} | 10 +-- ....pipelines.rst => modelscope.trainers.rst} | 16 ++--- docs/source/api/modelscope.utils.rst | 66 +++++++++++++++++++ docs/source/api/modules.rst | 6 +- docs/source/conf.py | 10 +-- docs/source/index.rst | 16 ++--- docs/source/quick_start.md | 32 ++++----- docs/source/tutorials/pipeline.md | 8 +-- maas_lib/pipelines/default.py | 48 -------------- {maas_lib => modelscope}/__init__.py | 0 {maas_lib => modelscope}/fileio/__init__.py | 0 {maas_lib => modelscope}/fileio/file.py | 0 .../fileio/format/__init__.py | 0 .../fileio/format/base.py | 0 .../fileio/format/json.py | 0 .../fileio/format/yaml.py | 0 {maas_lib => modelscope}/fileio/io.py | 0 {maas_lib => modelscope}/models/__init__.py | 0 {maas_lib => modelscope}/models/base.py | 8 +-- {maas_lib => modelscope}/models/builder.py | 4 +- .../models/cv/__init__.py | 0 .../models/cv/cartoon/__init__.py | 0 .../models/cv/cartoon/facelib/LICENSE | 0 .../models/cv/cartoon/facelib/LK/__init__.py | 0 .../models/cv/cartoon/facelib/LK/lk.py | 0 .../models/cv/cartoon/facelib/__init__.py | 0 .../models/cv/cartoon/facelib/config.py | 0 .../cv/cartoon/facelib/face_detector.py | 0 .../cv/cartoon/facelib/face_landmark.py | 0 .../models/cv/cartoon/facelib/facer.py | 0 .../models/cv/cartoon/mtcnn_pytorch/LICENSE | 0 .../models/cv/cartoon/mtcnn_pytorch/README.md | 0 .../cv/cartoon/mtcnn_pytorch/__init__.py | 0 .../cv/cartoon/mtcnn_pytorch/src/__init__.py | 0 .../cartoon/mtcnn_pytorch/src/align_trans.py | 0 .../mtcnn_pytorch/src/matlab_cp2tform.py | 0 .../models/cv/cartoon/utils.py | 0 .../models/nlp/__init__.py | 0 .../nlp/sequence_classification_model.py | 2 +- .../models/nlp/text_generation_model.py | 2 +- .../pipelines/__init__.py | 0 .../pipelines/audio/__init__.py | 0 {maas_lib => modelscope}/pipelines/base.py | 12 ++-- {maas_lib => modelscope}/pipelines/builder.py | 59 +++++++++++++++-- .../pipelines/cv/__init__.py | 0 .../pipelines/cv/image_cartoon_pipeline.py | 14 ++-- .../pipelines/cv/image_matting_pipeline.py | 8 +-- .../pipelines/multi_modal/__init__.py | 0 .../pipelines/multi_modal/image_captioning.py | 8 +-- .../pipelines/nlp/__init__.py | 0 .../nlp/sequence_classification_pipeline.py | 6 +- .../pipelines/nlp/text_generation_pipeline.py | 8 +-- {maas_lib => modelscope}/pipelines/util.py | 2 +- .../preprocessors/__init__.py | 0 .../preprocessors/base.py | 0 .../preprocessors/builder.py | 6 +- .../preprocessors/common.py | 0 .../preprocessors/image.py | 4 +- {maas_lib => modelscope}/preprocessors/nlp.py | 4 +- .../pydatasets/__init__.py | 0 .../pydatasets/py_dataset.py | 4 +- {maas_lib => modelscope}/tools/eval.py | 2 +- {maas_lib => modelscope}/tools/train.py | 2 +- {maas_lib => modelscope}/trainers/__init__.py | 0 {maas_lib => modelscope}/trainers/base.py | 4 +- {maas_lib => modelscope}/trainers/builder.py | 6 +- .../trainers/nlp/__init__.py | 0 .../nlp/sequence_classification_trainer.py | 4 +- {maas_lib => modelscope}/utils/__init__.py | 0 {maas_lib => modelscope}/utils/config.py | 10 +-- {maas_lib => modelscope}/utils/constant.py | 2 +- {maas_lib => modelscope}/utils/hub.py | 0 {maas_lib => modelscope}/utils/logger.py | 0 {maas_lib => modelscope}/utils/pymod.py | 2 +- {maas_lib => modelscope}/utils/registry.py | 4 +- {maas_lib => modelscope}/utils/type_assert.py | 0 {maas_lib => modelscope}/version.py | 0 requirements/maas.txt | 2 - requirements/runtime.txt | 1 + setup.cfg | 2 +- setup.py | 12 ++-- tests/fileio/test_file.py | 2 +- tests/fileio/test_io.py | 2 +- tests/pipelines/test_base.py | 13 ++-- tests/pipelines/test_image_captioning.py | 6 +- tests/pipelines/test_image_matting.py | 10 +-- tests/pipelines/test_person_image_cartoon.py | 4 +- tests/pipelines/test_text_classification.py | 16 ++--- tests/pipelines/test_text_generation.py | 10 +-- tests/preprocessors/test_common.py | 2 +- tests/preprocessors/test_nlp.py | 6 +- tests/pydatasets/test_py_dataset.py | 2 +- .../test_sequence_classification_trainer.py | 6 +- tests/trainers/test_trainer_base.py | 2 +- tests/utils/test_config.py | 4 +- tests/utils/test_registry.py | 4 +- tests/utils/test_type_assert.py | 2 +- 133 files changed, 804 insertions(+), 573 deletions(-) delete mode 100644 docs/source/api/maas_lib.fileio.format.rst delete mode 100644 docs/source/api/maas_lib.fileio.rst delete mode 100644 docs/source/api/maas_lib.models.nlp.rst delete mode 100644 docs/source/api/maas_lib.models.rst delete mode 100644 docs/source/api/maas_lib.pipelines.audio.rst delete mode 100644 docs/source/api/maas_lib.pipelines.cv.rst delete mode 100644 docs/source/api/maas_lib.pipelines.multi_modal.rst delete mode 100644 docs/source/api/maas_lib.preprocessors.rst delete mode 100644 docs/source/api/maas_lib.rst delete mode 100644 docs/source/api/maas_lib.trainers.nlp.rst delete mode 100644 docs/source/api/maas_lib.trainers.rst delete mode 100644 docs/source/api/maas_lib.utils.rst create mode 100644 docs/source/api/modelscope.fileio.format.rst create mode 100644 docs/source/api/modelscope.fileio.rst create mode 100644 docs/source/api/modelscope.models.cv.cartoon.facelib.LK.rst create mode 100644 docs/source/api/modelscope.models.cv.cartoon.facelib.rst create mode 100644 docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.rst create mode 100644 docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.src.rst create mode 100644 docs/source/api/modelscope.models.cv.cartoon.rst create mode 100644 docs/source/api/modelscope.models.cv.rst create mode 100644 docs/source/api/modelscope.models.nlp.rst create mode 100644 docs/source/api/modelscope.models.rst create mode 100644 docs/source/api/modelscope.pipelines.audio.rst create mode 100644 docs/source/api/modelscope.pipelines.cv.rst create mode 100644 docs/source/api/modelscope.pipelines.multi_modal.rst create mode 100644 docs/source/api/modelscope.pipelines.nlp.rst create mode 100644 docs/source/api/modelscope.pipelines.rst create mode 100644 docs/source/api/modelscope.preprocessors.rst create mode 100644 docs/source/api/modelscope.pydatasets.rst create mode 100644 docs/source/api/modelscope.rst rename docs/source/api/{maas_lib.pipelines.nlp.rst => modelscope.trainers.nlp.rst} (52%) rename docs/source/api/{maas_lib.pipelines.rst => modelscope.trainers.rst} (53%) create mode 100644 docs/source/api/modelscope.utils.rst delete mode 100644 maas_lib/pipelines/default.py rename {maas_lib => modelscope}/__init__.py (100%) rename {maas_lib => modelscope}/fileio/__init__.py (100%) rename {maas_lib => modelscope}/fileio/file.py (100%) rename {maas_lib => modelscope}/fileio/format/__init__.py (100%) rename {maas_lib => modelscope}/fileio/format/base.py (100%) rename {maas_lib => modelscope}/fileio/format/json.py (100%) rename {maas_lib => modelscope}/fileio/format/yaml.py (100%) rename {maas_lib => modelscope}/fileio/io.py (100%) rename {maas_lib => modelscope}/models/__init__.py (100%) rename {maas_lib => modelscope}/models/base.py (91%) rename {maas_lib => modelscope}/models/builder.py (84%) rename {maas_lib => modelscope}/models/cv/__init__.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/__init__.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/LICENSE (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/LK/__init__.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/LK/lk.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/__init__.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/config.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/face_detector.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/face_landmark.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/facelib/facer.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/mtcnn_pytorch/LICENSE (100%) rename {maas_lib => modelscope}/models/cv/cartoon/mtcnn_pytorch/README.md (100%) rename {maas_lib => modelscope}/models/cv/cartoon/mtcnn_pytorch/__init__.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/mtcnn_pytorch/src/__init__.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py (100%) rename {maas_lib => modelscope}/models/cv/cartoon/utils.py (100%) rename {maas_lib => modelscope}/models/nlp/__init__.py (100%) rename {maas_lib => modelscope}/models/nlp/sequence_classification_model.py (97%) rename {maas_lib => modelscope}/models/nlp/text_generation_model.py (97%) rename {maas_lib => modelscope}/pipelines/__init__.py (100%) rename {maas_lib => modelscope}/pipelines/audio/__init__.py (100%) rename {maas_lib => modelscope}/pipelines/base.py (93%) rename {maas_lib => modelscope}/pipelines/builder.py (58%) rename {maas_lib => modelscope}/pipelines/cv/__init__.py (100%) rename {maas_lib => modelscope}/pipelines/cv/image_cartoon_pipeline.py (92%) rename {maas_lib => modelscope}/pipelines/cv/image_matting_pipeline.py (92%) rename {maas_lib => modelscope}/pipelines/multi_modal/__init__.py (100%) rename {maas_lib => modelscope}/pipelines/multi_modal/image_captioning.py (95%) rename {maas_lib => modelscope}/pipelines/nlp/__init__.py (100%) rename {maas_lib => modelscope}/pipelines/nlp/sequence_classification_pipeline.py (94%) rename {maas_lib => modelscope}/pipelines/nlp/text_generation_pipeline.py (91%) rename {maas_lib => modelscope}/pipelines/util.py (94%) rename {maas_lib => modelscope}/preprocessors/__init__.py (100%) rename {maas_lib => modelscope}/preprocessors/base.py (100%) rename {maas_lib => modelscope}/preprocessors/builder.py (80%) rename {maas_lib => modelscope}/preprocessors/common.py (100%) rename {maas_lib => modelscope}/preprocessors/image.py (96%) rename {maas_lib => modelscope}/preprocessors/nlp.py (97%) rename {maas_lib => modelscope}/pydatasets/__init__.py (100%) rename {maas_lib => modelscope}/pydatasets/py_dataset.py (96%) rename {maas_lib => modelscope}/tools/eval.py (94%) rename {maas_lib => modelscope}/tools/train.py (92%) rename {maas_lib => modelscope}/trainers/__init__.py (100%) rename {maas_lib => modelscope}/trainers/base.py (96%) rename {maas_lib => modelscope}/trainers/builder.py (77%) rename {maas_lib => modelscope}/trainers/nlp/__init__.py (100%) rename {maas_lib => modelscope}/trainers/nlp/sequence_classification_trainer.py (98%) rename {maas_lib => modelscope}/utils/__init__.py (100%) rename {maas_lib => modelscope}/utils/config.py (98%) rename {maas_lib => modelscope}/utils/constant.py (97%) rename {maas_lib => modelscope}/utils/hub.py (100%) rename {maas_lib => modelscope}/utils/logger.py (100%) rename {maas_lib => modelscope}/utils/pymod.py (98%) rename {maas_lib => modelscope}/utils/registry.py (98%) rename {maas_lib => modelscope}/utils/type_assert.py (100%) rename {maas_lib => modelscope}/version.py (100%) delete mode 100644 requirements/maas.txt diff --git a/.dev_scripts/build_docs.sh b/.dev_scripts/build_docs.sh index 9c8acdf1..dc76e6f4 100644 --- a/.dev_scripts/build_docs.sh +++ b/.dev_scripts/build_docs.sh @@ -4,5 +4,5 @@ rm -rf build # update api rst #rm -rf source/api/ -#sphinx-apidoc --module-first -o source/api/ ../maas_lib/ +#sphinx-apidoc --module-first -o source/api/ ../modelscope/ make html diff --git a/.dev_scripts/linter.sh b/.dev_scripts/linter.sh index fb8ab19d..6468e42b 100644 --- a/.dev_scripts/linter.sh +++ b/.dev_scripts/linter.sh @@ -1,3 +1,3 @@ -yapf -r -i maas_lib/ configs/ tests/ setup.py -isort -rc maas_lib/ configs/ tests/ setup.py -flake8 maas_lib/ configs/ tests/ setup.py +yapf -r -i modelscope/ configs/ tests/ setup.py +isort -rc modelscope/ configs/ tests/ setup.py +flake8 modelscope/ configs/ tests/ setup.py diff --git a/LICENSE b/LICENSE index 85ed3d3a..14cec7de 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2022-2023 Alibaba MaaS. All rights reserved. +Copyright 2022-2023 Alibaba ModelScope. All rights reserved. Apache License Version 2.0, January 2004 @@ -188,7 +188,7 @@ Copyright 2022-2023 Alibaba MaaS. All rights reserved. same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2020-2022 Alibaba MaaS. + Copyright 2020-2022 Alibaba ModelScope. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/MANIFEST.in b/MANIFEST.in index 0a153dba..665d7e90 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -recursive-include maas_lib/configs *.py +recursive-include modelscope/configs *.py diff --git a/README.md b/README.md index dabe8726..944c1f07 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Introduction -MaaS library is targeted to support training, evaluation and inference for the state of the art models provided by Mind and further support third-party models provided by users outside alibaba. +ModelScope library is targeted to support training, evaluation and inference for the state of the art models provided by Mind and further support third-party models provided by users outside alibaba. # Design doc diff --git a/configs/README.md b/configs/README.md index 94499da7..3c3b6963 100644 --- a/configs/README.md +++ b/configs/README.md @@ -1 +1 @@ -This folder will host example configs for each model supported by maas_lib. +This folder will host example configs for each model supported by modelscope. diff --git a/docs/source/api/maas_lib.fileio.format.rst b/docs/source/api/maas_lib.fileio.format.rst deleted file mode 100644 index 7c2c649d..00000000 --- a/docs/source/api/maas_lib.fileio.format.rst +++ /dev/null @@ -1,34 +0,0 @@ -maas\_lib.fileio.format package -=============================== - -.. automodule:: maas_lib.fileio.format - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -maas\_lib.fileio.format.base module ------------------------------------ - -.. automodule:: maas_lib.fileio.format.base - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.fileio.format.json module ------------------------------------ - -.. automodule:: maas_lib.fileio.format.json - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.fileio.format.yaml module ------------------------------------ - -.. automodule:: maas_lib.fileio.format.yaml - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.fileio.rst b/docs/source/api/maas_lib.fileio.rst deleted file mode 100644 index e9540208..00000000 --- a/docs/source/api/maas_lib.fileio.rst +++ /dev/null @@ -1,34 +0,0 @@ -maas\_lib.fileio package -======================== - -.. automodule:: maas_lib.fileio - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - maas_lib.fileio.format - -Submodules ----------- - -maas\_lib.fileio.file module ----------------------------- - -.. automodule:: maas_lib.fileio.file - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.fileio.io module --------------------------- - -.. automodule:: maas_lib.fileio.io - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.models.nlp.rst b/docs/source/api/maas_lib.models.nlp.rst deleted file mode 100644 index bd782ea8..00000000 --- a/docs/source/api/maas_lib.models.nlp.rst +++ /dev/null @@ -1,18 +0,0 @@ -maas\_lib.models.nlp package -============================ - -.. automodule:: maas_lib.models.nlp - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -maas\_lib.models.nlp.sequence\_classification\_model module ------------------------------------------------------------ - -.. automodule:: maas_lib.models.nlp.sequence_classification_model - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.models.rst b/docs/source/api/maas_lib.models.rst deleted file mode 100644 index 9e1874a3..00000000 --- a/docs/source/api/maas_lib.models.rst +++ /dev/null @@ -1,34 +0,0 @@ -maas\_lib.models package -======================== - -.. automodule:: maas_lib.models - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - maas_lib.models.nlp - -Submodules ----------- - -maas\_lib.models.base module ----------------------------- - -.. automodule:: maas_lib.models.base - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.models.builder module -------------------------------- - -.. automodule:: maas_lib.models.builder - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.pipelines.audio.rst b/docs/source/api/maas_lib.pipelines.audio.rst deleted file mode 100644 index 71e29b42..00000000 --- a/docs/source/api/maas_lib.pipelines.audio.rst +++ /dev/null @@ -1,7 +0,0 @@ -maas\_lib.pipelines.audio package -================================= - -.. automodule:: maas_lib.pipelines.audio - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.pipelines.cv.rst b/docs/source/api/maas_lib.pipelines.cv.rst deleted file mode 100644 index 938ebb5a..00000000 --- a/docs/source/api/maas_lib.pipelines.cv.rst +++ /dev/null @@ -1,18 +0,0 @@ -maas\_lib.pipelines.cv package -============================== - -.. automodule:: maas_lib.pipelines.cv - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -maas\_lib.pipelines.cv.image\_matting module --------------------------------------------- - -.. automodule:: maas_lib.pipelines.cv.image_matting - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.pipelines.multi_modal.rst b/docs/source/api/maas_lib.pipelines.multi_modal.rst deleted file mode 100644 index 74a7bf43..00000000 --- a/docs/source/api/maas_lib.pipelines.multi_modal.rst +++ /dev/null @@ -1,7 +0,0 @@ -maas\_lib.pipelines.multi\_modal package -======================================== - -.. automodule:: maas_lib.pipelines.multi_modal - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.preprocessors.rst b/docs/source/api/maas_lib.preprocessors.rst deleted file mode 100644 index 5f70e808..00000000 --- a/docs/source/api/maas_lib.preprocessors.rst +++ /dev/null @@ -1,50 +0,0 @@ -maas\_lib.preprocessors package -=============================== - -.. automodule:: maas_lib.preprocessors - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -maas\_lib.preprocessors.base module ------------------------------------ - -.. automodule:: maas_lib.preprocessors.base - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.preprocessors.builder module --------------------------------------- - -.. automodule:: maas_lib.preprocessors.builder - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.preprocessors.common module -------------------------------------- - -.. automodule:: maas_lib.preprocessors.common - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.preprocessors.image module ------------------------------------- - -.. automodule:: maas_lib.preprocessors.image - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.preprocessors.nlp module ----------------------------------- - -.. automodule:: maas_lib.preprocessors.nlp - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.rst b/docs/source/api/maas_lib.rst deleted file mode 100644 index 727b7986..00000000 --- a/docs/source/api/maas_lib.rst +++ /dev/null @@ -1,30 +0,0 @@ -maas\_lib package -================= - -.. automodule:: maas_lib - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - maas_lib.fileio - maas_lib.models - maas_lib.pipelines - maas_lib.preprocessors - maas_lib.utils - -Submodules ----------- - -maas\_lib.version module ------------------------- - -.. automodule:: maas_lib.version - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.trainers.nlp.rst b/docs/source/api/maas_lib.trainers.nlp.rst deleted file mode 100644 index 71f484ca..00000000 --- a/docs/source/api/maas_lib.trainers.nlp.rst +++ /dev/null @@ -1,18 +0,0 @@ -maas\_lib.trainers.nlp package -============================== - -.. automodule:: maas_lib.trainers.nlp - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -maas\_lib.trainers.nlp.sequence\_classification\_trainer module ---------------------------------------------------------------- - -.. automodule:: maas_lib.trainers.nlp.sequence_classification_trainer - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.trainers.rst b/docs/source/api/maas_lib.trainers.rst deleted file mode 100644 index eb90ee4f..00000000 --- a/docs/source/api/maas_lib.trainers.rst +++ /dev/null @@ -1,34 +0,0 @@ -maas\_lib.trainers package -========================== - -.. automodule:: maas_lib.trainers - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - maas_lib.trainers.nlp - -Submodules ----------- - -maas\_lib.trainers.base module ------------------------------- - -.. automodule:: maas_lib.trainers.base - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.trainers.builder module ---------------------------------- - -.. automodule:: maas_lib.trainers.builder - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/maas_lib.utils.rst b/docs/source/api/maas_lib.utils.rst deleted file mode 100644 index 17ead3eb..00000000 --- a/docs/source/api/maas_lib.utils.rst +++ /dev/null @@ -1,58 +0,0 @@ -maas\_lib.utils package -======================= - -.. automodule:: maas_lib.utils - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -maas\_lib.utils.config module ------------------------------ - -.. automodule:: maas_lib.utils.config - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.utils.constant module -------------------------------- - -.. automodule:: maas_lib.utils.constant - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.utils.logger module ------------------------------ - -.. automodule:: maas_lib.utils.logger - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.utils.pymod module ----------------------------- - -.. automodule:: maas_lib.utils.pymod - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.utils.registry module -------------------------------- - -.. automodule:: maas_lib.utils.registry - :members: - :undoc-members: - :show-inheritance: - -maas\_lib.utils.type\_assert module ------------------------------------ - -.. automodule:: maas_lib.utils.type_assert - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/api/modelscope.fileio.format.rst b/docs/source/api/modelscope.fileio.format.rst new file mode 100644 index 00000000..2c7b11de --- /dev/null +++ b/docs/source/api/modelscope.fileio.format.rst @@ -0,0 +1,34 @@ +modelscope.fileio.format package +================================ + +.. automodule:: modelscope.fileio.format + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.fileio.format.base module +------------------------------------ + +.. automodule:: modelscope.fileio.format.base + :members: + :undoc-members: + :show-inheritance: + +modelscope.fileio.format.json module +------------------------------------ + +.. automodule:: modelscope.fileio.format.json + :members: + :undoc-members: + :show-inheritance: + +modelscope.fileio.format.yaml module +------------------------------------ + +.. automodule:: modelscope.fileio.format.yaml + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.fileio.rst b/docs/source/api/modelscope.fileio.rst new file mode 100644 index 00000000..3f4ae1ca --- /dev/null +++ b/docs/source/api/modelscope.fileio.rst @@ -0,0 +1,34 @@ +modelscope.fileio package +========================= + +.. automodule:: modelscope.fileio + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.fileio.format + +Submodules +---------- + +modelscope.fileio.file module +----------------------------- + +.. automodule:: modelscope.fileio.file + :members: + :undoc-members: + :show-inheritance: + +modelscope.fileio.io module +--------------------------- + +.. automodule:: modelscope.fileio.io + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.models.cv.cartoon.facelib.LK.rst b/docs/source/api/modelscope.models.cv.cartoon.facelib.LK.rst new file mode 100644 index 00000000..848c7d67 --- /dev/null +++ b/docs/source/api/modelscope.models.cv.cartoon.facelib.LK.rst @@ -0,0 +1,18 @@ +modelscope.models.cv.cartoon.facelib.LK package +=============================================== + +.. automodule:: modelscope.models.cv.cartoon.facelib.LK + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.models.cv.cartoon.facelib.LK.lk module +------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.facelib.LK.lk + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.models.cv.cartoon.facelib.rst b/docs/source/api/modelscope.models.cv.cartoon.facelib.rst new file mode 100644 index 00000000..a81536b0 --- /dev/null +++ b/docs/source/api/modelscope.models.cv.cartoon.facelib.rst @@ -0,0 +1,50 @@ +modelscope.models.cv.cartoon.facelib package +============================================ + +.. automodule:: modelscope.models.cv.cartoon.facelib + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.models.cv.cartoon.facelib.LK + +Submodules +---------- + +modelscope.models.cv.cartoon.facelib.config module +-------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.facelib.config + :members: + :undoc-members: + :show-inheritance: + +modelscope.models.cv.cartoon.facelib.face\_detector module +---------------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.facelib.face_detector + :members: + :undoc-members: + :show-inheritance: + +modelscope.models.cv.cartoon.facelib.face\_landmark module +---------------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.facelib.face_landmark + :members: + :undoc-members: + :show-inheritance: + +modelscope.models.cv.cartoon.facelib.facer module +------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.facelib.facer + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.rst b/docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.rst new file mode 100644 index 00000000..b5845af7 --- /dev/null +++ b/docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.rst @@ -0,0 +1,15 @@ +modelscope.models.cv.cartoon.mtcnn\_pytorch package +=================================================== + +.. automodule:: modelscope.models.cv.cartoon.mtcnn_pytorch + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.models.cv.cartoon.mtcnn_pytorch.src diff --git a/docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.src.rst b/docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.src.rst new file mode 100644 index 00000000..715cc292 --- /dev/null +++ b/docs/source/api/modelscope.models.cv.cartoon.mtcnn_pytorch.src.rst @@ -0,0 +1,26 @@ +modelscope.models.cv.cartoon.mtcnn\_pytorch.src package +======================================================= + +.. automodule:: modelscope.models.cv.cartoon.mtcnn_pytorch.src + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.models.cv.cartoon.mtcnn\_pytorch.src.align\_trans module +------------------------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.mtcnn_pytorch.src.align_trans + :members: + :undoc-members: + :show-inheritance: + +modelscope.models.cv.cartoon.mtcnn\_pytorch.src.matlab\_cp2tform module +----------------------------------------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.mtcnn_pytorch.src.matlab_cp2tform + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.models.cv.cartoon.rst b/docs/source/api/modelscope.models.cv.cartoon.rst new file mode 100644 index 00000000..5a262e03 --- /dev/null +++ b/docs/source/api/modelscope.models.cv.cartoon.rst @@ -0,0 +1,27 @@ +modelscope.models.cv.cartoon package +==================================== + +.. automodule:: modelscope.models.cv.cartoon + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.models.cv.cartoon.facelib + modelscope.models.cv.cartoon.mtcnn_pytorch + +Submodules +---------- + +modelscope.models.cv.cartoon.utils module +----------------------------------------- + +.. automodule:: modelscope.models.cv.cartoon.utils + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.models.cv.rst b/docs/source/api/modelscope.models.cv.rst new file mode 100644 index 00000000..47ce3916 --- /dev/null +++ b/docs/source/api/modelscope.models.cv.rst @@ -0,0 +1,15 @@ +modelscope.models.cv package +============================ + +.. automodule:: modelscope.models.cv + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.models.cv.cartoon diff --git a/docs/source/api/modelscope.models.nlp.rst b/docs/source/api/modelscope.models.nlp.rst new file mode 100644 index 00000000..f332aca8 --- /dev/null +++ b/docs/source/api/modelscope.models.nlp.rst @@ -0,0 +1,26 @@ +modelscope.models.nlp package +============================= + +.. automodule:: modelscope.models.nlp + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.models.nlp.sequence\_classification\_model module +------------------------------------------------------------ + +.. automodule:: modelscope.models.nlp.sequence_classification_model + :members: + :undoc-members: + :show-inheritance: + +modelscope.models.nlp.text\_generation\_model module +---------------------------------------------------- + +.. automodule:: modelscope.models.nlp.text_generation_model + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.models.rst b/docs/source/api/modelscope.models.rst new file mode 100644 index 00000000..8f2870b3 --- /dev/null +++ b/docs/source/api/modelscope.models.rst @@ -0,0 +1,35 @@ +modelscope.models package +========================= + +.. automodule:: modelscope.models + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.models.cv + modelscope.models.nlp + +Submodules +---------- + +modelscope.models.base module +----------------------------- + +.. automodule:: modelscope.models.base + :members: + :undoc-members: + :show-inheritance: + +modelscope.models.builder module +-------------------------------- + +.. automodule:: modelscope.models.builder + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.pipelines.audio.rst b/docs/source/api/modelscope.pipelines.audio.rst new file mode 100644 index 00000000..f162893f --- /dev/null +++ b/docs/source/api/modelscope.pipelines.audio.rst @@ -0,0 +1,7 @@ +modelscope.pipelines.audio package +================================== + +.. automodule:: modelscope.pipelines.audio + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.pipelines.cv.rst b/docs/source/api/modelscope.pipelines.cv.rst new file mode 100644 index 00000000..3f2da3f4 --- /dev/null +++ b/docs/source/api/modelscope.pipelines.cv.rst @@ -0,0 +1,26 @@ +modelscope.pipelines.cv package +=============================== + +.. automodule:: modelscope.pipelines.cv + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.pipelines.cv.image\_cartoon\_pipeline module +------------------------------------------------------- + +.. automodule:: modelscope.pipelines.cv.image_cartoon_pipeline + :members: + :undoc-members: + :show-inheritance: + +modelscope.pipelines.cv.image\_matting\_pipeline module +------------------------------------------------------- + +.. automodule:: modelscope.pipelines.cv.image_matting_pipeline + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.pipelines.multi_modal.rst b/docs/source/api/modelscope.pipelines.multi_modal.rst new file mode 100644 index 00000000..36df1c7c --- /dev/null +++ b/docs/source/api/modelscope.pipelines.multi_modal.rst @@ -0,0 +1,18 @@ +modelscope.pipelines.multi\_modal package +========================================= + +.. automodule:: modelscope.pipelines.multi_modal + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.pipelines.multi\_modal.image\_captioning module +---------------------------------------------------------- + +.. automodule:: modelscope.pipelines.multi_modal.image_captioning + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.pipelines.nlp.rst b/docs/source/api/modelscope.pipelines.nlp.rst new file mode 100644 index 00000000..836d914f --- /dev/null +++ b/docs/source/api/modelscope.pipelines.nlp.rst @@ -0,0 +1,26 @@ +modelscope.pipelines.nlp package +================================ + +.. automodule:: modelscope.pipelines.nlp + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.pipelines.nlp.sequence\_classification\_pipeline module +------------------------------------------------------------------ + +.. automodule:: modelscope.pipelines.nlp.sequence_classification_pipeline + :members: + :undoc-members: + :show-inheritance: + +modelscope.pipelines.nlp.text\_generation\_pipeline module +---------------------------------------------------------- + +.. automodule:: modelscope.pipelines.nlp.text_generation_pipeline + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.pipelines.rst b/docs/source/api/modelscope.pipelines.rst new file mode 100644 index 00000000..167b5cd3 --- /dev/null +++ b/docs/source/api/modelscope.pipelines.rst @@ -0,0 +1,53 @@ +modelscope.pipelines package +============================ + +.. automodule:: modelscope.pipelines + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.pipelines.audio + modelscope.pipelines.cv + modelscope.pipelines.multi_modal + modelscope.pipelines.nlp + +Submodules +---------- + +modelscope.pipelines.base module +-------------------------------- + +.. automodule:: modelscope.pipelines.base + :members: + :undoc-members: + :show-inheritance: + +modelscope.pipelines.builder module +----------------------------------- + +.. automodule:: modelscope.pipelines.builder + :members: + :undoc-members: + :show-inheritance: + +modelscope.pipelines.default module +----------------------------------- + +.. automodule:: modelscope.pipelines.default + :members: + :undoc-members: + :show-inheritance: + +modelscope.pipelines.util module +-------------------------------- + +.. automodule:: modelscope.pipelines.util + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.preprocessors.rst b/docs/source/api/modelscope.preprocessors.rst new file mode 100644 index 00000000..b555198d --- /dev/null +++ b/docs/source/api/modelscope.preprocessors.rst @@ -0,0 +1,50 @@ +modelscope.preprocessors package +================================ + +.. automodule:: modelscope.preprocessors + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.preprocessors.base module +------------------------------------ + +.. automodule:: modelscope.preprocessors.base + :members: + :undoc-members: + :show-inheritance: + +modelscope.preprocessors.builder module +--------------------------------------- + +.. automodule:: modelscope.preprocessors.builder + :members: + :undoc-members: + :show-inheritance: + +modelscope.preprocessors.common module +-------------------------------------- + +.. automodule:: modelscope.preprocessors.common + :members: + :undoc-members: + :show-inheritance: + +modelscope.preprocessors.image module +------------------------------------- + +.. automodule:: modelscope.preprocessors.image + :members: + :undoc-members: + :show-inheritance: + +modelscope.preprocessors.nlp module +----------------------------------- + +.. automodule:: modelscope.preprocessors.nlp + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.pydatasets.rst b/docs/source/api/modelscope.pydatasets.rst new file mode 100644 index 00000000..2508a91f --- /dev/null +++ b/docs/source/api/modelscope.pydatasets.rst @@ -0,0 +1,18 @@ +modelscope.pydatasets package +============================= + +.. automodule:: modelscope.pydatasets + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.pydatasets.py\_dataset module +---------------------------------------- + +.. automodule:: modelscope.pydatasets.py_dataset + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modelscope.rst b/docs/source/api/modelscope.rst new file mode 100644 index 00000000..efab568b --- /dev/null +++ b/docs/source/api/modelscope.rst @@ -0,0 +1,32 @@ +modelscope package +================== + +.. automodule:: modelscope + :members: + :undoc-members: + :show-inheritance: + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + modelscope.fileio + modelscope.models + modelscope.pipelines + modelscope.preprocessors + modelscope.pydatasets + modelscope.trainers + modelscope.utils + +Submodules +---------- + +modelscope.version module +------------------------- + +.. automodule:: modelscope.version + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/maas_lib.pipelines.nlp.rst b/docs/source/api/modelscope.trainers.nlp.rst similarity index 52% rename from docs/source/api/maas_lib.pipelines.nlp.rst rename to docs/source/api/modelscope.trainers.nlp.rst index d41c09ad..4bc2f875 100644 --- a/docs/source/api/maas_lib.pipelines.nlp.rst +++ b/docs/source/api/modelscope.trainers.nlp.rst @@ -1,7 +1,7 @@ -maas\_lib.pipelines.nlp package +modelscope.trainers.nlp package =============================== -.. automodule:: maas_lib.pipelines.nlp +.. automodule:: modelscope.trainers.nlp :members: :undoc-members: :show-inheritance: @@ -9,10 +9,10 @@ maas\_lib.pipelines.nlp package Submodules ---------- -maas\_lib.pipelines.nlp.sequence\_classification\_pipeline module ------------------------------------------------------------------ +modelscope.trainers.nlp.sequence\_classification\_trainer module +---------------------------------------------------------------- -.. automodule:: maas_lib.pipelines.nlp.sequence_classification_pipeline +.. automodule:: modelscope.trainers.nlp.sequence_classification_trainer :members: :undoc-members: :show-inheritance: diff --git a/docs/source/api/maas_lib.pipelines.rst b/docs/source/api/modelscope.trainers.rst similarity index 53% rename from docs/source/api/maas_lib.pipelines.rst rename to docs/source/api/modelscope.trainers.rst index 40b82adc..aac4fb99 100644 --- a/docs/source/api/maas_lib.pipelines.rst +++ b/docs/source/api/modelscope.trainers.rst @@ -1,7 +1,7 @@ -maas\_lib.pipelines package +modelscope.trainers package =========================== -.. automodule:: maas_lib.pipelines +.. automodule:: modelscope.trainers :members: :undoc-members: :show-inheritance: @@ -12,25 +12,23 @@ Subpackages .. toctree:: :maxdepth: 4 - maas_lib.pipelines.cv - maas_lib.pipelines.multi_modal - maas_lib.pipelines.nlp + modelscope.trainers.nlp Submodules ---------- -maas\_lib.pipelines.base module +modelscope.trainers.base module ------------------------------- -.. automodule:: maas_lib.pipelines.base +.. automodule:: modelscope.trainers.base :members: :undoc-members: :show-inheritance: -maas\_lib.pipelines.builder module +modelscope.trainers.builder module ---------------------------------- -.. automodule:: maas_lib.pipelines.builder +.. automodule:: modelscope.trainers.builder :members: :undoc-members: :show-inheritance: diff --git a/docs/source/api/modelscope.utils.rst b/docs/source/api/modelscope.utils.rst new file mode 100644 index 00000000..0a78d4f4 --- /dev/null +++ b/docs/source/api/modelscope.utils.rst @@ -0,0 +1,66 @@ +modelscope.utils package +======================== + +.. automodule:: modelscope.utils + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +modelscope.utils.config module +------------------------------ + +.. automodule:: modelscope.utils.config + :members: + :undoc-members: + :show-inheritance: + +modelscope.utils.constant module +-------------------------------- + +.. automodule:: modelscope.utils.constant + :members: + :undoc-members: + :show-inheritance: + +modelscope.utils.hub module +--------------------------- + +.. automodule:: modelscope.utils.hub + :members: + :undoc-members: + :show-inheritance: + +modelscope.utils.logger module +------------------------------ + +.. automodule:: modelscope.utils.logger + :members: + :undoc-members: + :show-inheritance: + +modelscope.utils.pymod module +----------------------------- + +.. automodule:: modelscope.utils.pymod + :members: + :undoc-members: + :show-inheritance: + +modelscope.utils.registry module +-------------------------------- + +.. automodule:: modelscope.utils.registry + :members: + :undoc-members: + :show-inheritance: + +modelscope.utils.type\_assert module +------------------------------------ + +.. automodule:: modelscope.utils.type_assert + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/api/modules.rst b/docs/source/api/modules.rst index 84eecc70..0f83e90c 100644 --- a/docs/source/api/modules.rst +++ b/docs/source/api/modules.rst @@ -1,7 +1,7 @@ -maas_lib -======== +modelscope +========== .. toctree:: :maxdepth: 4 - maas_lib + modelscope diff --git a/docs/source/conf.py b/docs/source/conf.py index 4cdcd956..2c2a0017 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -18,10 +18,10 @@ import sphinx_rtd_theme sys.path.insert(0, os.path.abspath('../../')) # -- Project information ----------------------------------------------------- -project = 'maas_lib' -copyright = '2022-2023, Alibaba MaaS' -author = 'maas_lib Authors' -version_file = '../../maas_lib/version.py' +project = 'modelscope' +copyright = '2022-2023, Alibaba ModelScope' +author = 'modelscope Authors' +version_file = '../../modelscope/version.py' def get_version(): @@ -88,7 +88,7 @@ html_static_path = ['_static'] # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'maas_lib_doc' +htmlhelp_basename = 'modelscope_doc' # -- Extension configuration ------------------------------------------------- # Ignore >>> when copying code diff --git a/docs/source/index.rst b/docs/source/index.rst index 0ca63b41..3b223531 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,11 +1,11 @@ -.. maas_lib documentation file, +.. modelscope documentation file, You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -MaasLib DOCUMENTATION +ModelScope DOCUMENTATION ======================================= -MaasLib doc +ModelScope doc .. toctree:: :maxdepth: 2 @@ -30,11 +30,11 @@ MaasLib doc :maxdepth: 10 :caption: API Doc - api/maas_lib.preprocessors - api/maas_lib.models - api/maas_lib.pipelines - api/maas_lib.fileio - api/maas_lib.utils + api/modelscope.preprocessors + api/modelscope.models + api/modelscope.pipelines + api/modelscope.fileio + api/modelscope.utils Indices and tables diff --git a/docs/source/quick_start.md b/docs/source/quick_start.md index 4d145e79..0f4cbbc3 100644 --- a/docs/source/quick_start.md +++ b/docs/source/quick_start.md @@ -5,39 +5,39 @@ 安装完成后,执行如下命令为maas library创建对应的python环境。 ```shell -conda create -n maas python=3.6 -conda activate maas +conda create -n modelscope python=3.6 +conda activate modelscope ``` 检查python和pip命令是否切换到conda环境下。 ```shell which python -# ~/workspace/anaconda3/envs/maas/bin/python +# ~/workspace/anaconda3/envs/modelscope/bin/python which pip -# ~/workspace/anaconda3/envs/maas/bin/pip +# ~/workspace/anaconda3/envs/modelscope/bin/pip ``` 注: 本项目只支持`python3`环境,请勿使用python2环境。 ## 第三方依赖安装 -MaaS Library目前支持tensorflow,pytorch两大深度学习框架进行模型训练、推理, 在Python 3.6+, Pytorch 1.8+, Tensorflow 2.6上测试可运行,用户可以根据所选模型对应的计算框架进行安装,可以参考如下链接进行安装所需框架: +ModelScope Library目前支持tensorflow,pytorch两大深度学习框架进行模型训练、推理, 在Python 3.6+, Pytorch 1.8+, Tensorflow 2.6上测试可运行,用户可以根据所选模型对应的计算框架进行安装,可以参考如下链接进行安装所需框架: * [Pytorch安装指导](https://pytorch.org/get-started/locally/) * [Tensorflow安装指导](https://www.tensorflow.org/install/pip) -## MaaS library 安装 +## ModelScope library 安装 注: 如果在安装过程中遇到错误,请前往[常见问题](faq.md)查找解决方案。 ### pip安装 ```shell -pip install -r http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release/maas/maas.txt +pip install -r http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release/maas/modelscope.txt ``` 安装成功后,可以执行如下命令进行验证安装是否正确 ```shell -python -c "from maas_lib.pipelines import pipeline;print(pipeline('image-matting',model='damo/image-matting-person')('http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png'))" +python -c "from modelscope.pipelines import pipeline;print(pipeline('image-matting',model='damo/image-matting-person')('http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png'))" ``` @@ -45,11 +45,11 @@ python -c "from maas_lib.pipelines import pipeline;print(pipeline('image-matting 适合本地开发调试使用,修改源码后可以直接执行 ```shell -git clone git@gitlab.alibaba-inc.com:Ali-MaaS/MaaS-lib.git maaslib +git clone git@gitlab.alibaba-inc.com:Ali-MaaS/MaaS-lib.git modelscope git fetch origin master git checkout master -cd maaslib +cd modelscope #安装依赖 pip install -r requirements.txt @@ -60,7 +60,7 @@ export PYTHONPATH=`pwd` 安装成功后,可以执行如下命令进行验证安装是否正确 ```shell -python -c "from maas_lib.pipelines import pipeline;print(pipeline('image-matting',model='damo/image-matting-person')('http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png'))" +python -c "from modelscope.pipelines import pipeline;print(pipeline('image-matting',model='damo/image-matting-person')('http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png'))" ``` @@ -79,8 +79,8 @@ pipeline函数提供了简洁的推理接口,示例如下, 更多pipeline介 ```python import cv2 import os.path as osp -from maas_lib.pipelines import pipeline -from maas_lib.utils.constant import Tasks +from modelscope.pipelines import pipeline +from modelscope.utils.constant import Tasks # 根据任务名创建pipeline img_matting = pipeline(Tasks.image_matting, model='damo/image-matting-person') @@ -99,9 +99,9 @@ print(f'Output written to {osp.abspath("result.png")}') ```python import cv2 import os.path as osp -from maas_lib.pipelines import pipeline -from maas_lib.utils.constant import Tasks -from maas_lib.pydatasets import PyDataset +from modelscope.pipelines import pipeline +from modelscope.utils.constant import Tasks +from modelscope.pydatasets import PyDataset # 使用图像url构建PyDataset,此处也可通过 input_location = '/dir/to/images' 来使用本地文件夹 input_location = [ diff --git a/docs/source/tutorials/pipeline.md b/docs/source/tutorials/pipeline.md index 512e64ee..cc851278 100644 --- a/docs/source/tutorials/pipeline.md +++ b/docs/source/tutorials/pipeline.md @@ -19,7 +19,7 @@ 1. pipeline函数支持指定特定任务名称,加载任务默认模型,创建对应Pipeline对象 执行如下python代码 ```python - >>> from maas_lib.pipelines import pipeline + >>> from modelscope.pipelines import pipeline >>> img_matting = pipeline(task='image-matting', model='damo/image-matting-person') ``` @@ -65,8 +65,8 @@ wget https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/easynlp_modelz 创建tokenizer和模型 ```python ->>> from maas_lib.models import Model ->>> from maas_lib.preprocessors import SequenceClassificationPreprocessor +>>> from modelscope.models import Model +>>> from modelscope.preprocessors import SequenceClassificationPreprocessor >>> model = Model.from_pretrained('damo/bert-base-sst2') >>> tokenizer = SequenceClassificationPreprocessor( model.model_dir, first_sequence='sentence', second_sequence=None) @@ -74,7 +74,7 @@ wget https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/easynlp_modelz 使用tokenizer和模型对象创建pipeline ```python ->>> from maas_lib.pipelines import pipeline +>>> from modelscope.pipelines import pipeline >>> semantic_cls = pipeline('text-classification', model=model, preprocessor=tokenizer) >>> semantic_cls("Hello world!") ``` diff --git a/maas_lib/pipelines/default.py b/maas_lib/pipelines/default.py deleted file mode 100644 index 5d364288..00000000 --- a/maas_lib/pipelines/default.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) Alibaba, Inc. and its affiliates. - -from maas_lib.utils.constant import Tasks - -DEFAULT_MODEL_FOR_PIPELINE = { - # TaskName: (pipeline_module_name, model_repo) - Tasks.image_matting: ('image-matting', 'damo/image-matting-person'), - Tasks.text_classification: - ('bert-sentiment-analysis', 'damo/bert-base-sst2'), - Tasks.text_generation: ('palm', 'damo/nlp_palm_text-generation_chinese'), - Tasks.image_captioning: ('ofa', None), -} - - -def add_default_pipeline_info(task: str, - model_name: str, - modelhub_name: str = None, - overwrite: bool = False): - """ Add default model for a task. - - Args: - task (str): task name. - model_name (str): model_name. - modelhub_name (str): name for default modelhub. - overwrite (bool): overwrite default info. - """ - if not overwrite: - assert task not in DEFAULT_MODEL_FOR_PIPELINE, \ - f'task {task} already has default model.' - - DEFAULT_MODEL_FOR_PIPELINE[task] = (model_name, modelhub_name) - - -def get_default_pipeline_info(task): - """ Get default info for certain task. - - Args: - task (str): task name. - - Return: - A tuple: first element is pipeline name(model_name), second element - is modelhub name. - """ - assert task in DEFAULT_MODEL_FOR_PIPELINE, \ - f'No default pipeline is registered for Task {task}' - - pipeline_name, default_model = DEFAULT_MODEL_FOR_PIPELINE[task] - return pipeline_name, default_model diff --git a/maas_lib/__init__.py b/modelscope/__init__.py similarity index 100% rename from maas_lib/__init__.py rename to modelscope/__init__.py diff --git a/maas_lib/fileio/__init__.py b/modelscope/fileio/__init__.py similarity index 100% rename from maas_lib/fileio/__init__.py rename to modelscope/fileio/__init__.py diff --git a/maas_lib/fileio/file.py b/modelscope/fileio/file.py similarity index 100% rename from maas_lib/fileio/file.py rename to modelscope/fileio/file.py diff --git a/maas_lib/fileio/format/__init__.py b/modelscope/fileio/format/__init__.py similarity index 100% rename from maas_lib/fileio/format/__init__.py rename to modelscope/fileio/format/__init__.py diff --git a/maas_lib/fileio/format/base.py b/modelscope/fileio/format/base.py similarity index 100% rename from maas_lib/fileio/format/base.py rename to modelscope/fileio/format/base.py diff --git a/maas_lib/fileio/format/json.py b/modelscope/fileio/format/json.py similarity index 100% rename from maas_lib/fileio/format/json.py rename to modelscope/fileio/format/json.py diff --git a/maas_lib/fileio/format/yaml.py b/modelscope/fileio/format/yaml.py similarity index 100% rename from maas_lib/fileio/format/yaml.py rename to modelscope/fileio/format/yaml.py diff --git a/maas_lib/fileio/io.py b/modelscope/fileio/io.py similarity index 100% rename from maas_lib/fileio/io.py rename to modelscope/fileio/io.py diff --git a/maas_lib/models/__init__.py b/modelscope/models/__init__.py similarity index 100% rename from maas_lib/models/__init__.py rename to modelscope/models/__init__.py diff --git a/maas_lib/models/base.py b/modelscope/models/base.py similarity index 91% rename from maas_lib/models/base.py rename to modelscope/models/base.py index efda1b3e..e641236d 100644 --- a/maas_lib/models/base.py +++ b/modelscope/models/base.py @@ -7,10 +7,10 @@ from typing import Dict, List, Tuple, Union from maas_hub.file_download import model_file_download from maas_hub.snapshot_download import snapshot_download -from maas_lib.models.builder import build_model -from maas_lib.utils.config import Config -from maas_lib.utils.constant import CONFIGFILE -from maas_lib.utils.hub import get_model_cache_dir +from modelscope.models.builder import build_model +from modelscope.utils.config import Config +from modelscope.utils.constant import CONFIGFILE +from modelscope.utils.hub import get_model_cache_dir Tensor = Union['torch.Tensor', 'tf.Tensor'] diff --git a/maas_lib/models/builder.py b/modelscope/models/builder.py similarity index 84% rename from maas_lib/models/builder.py rename to modelscope/models/builder.py index 1e52d271..b6df8c90 100644 --- a/maas_lib/models/builder.py +++ b/modelscope/models/builder.py @@ -1,7 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -from maas_lib.utils.config import ConfigDict -from maas_lib.utils.registry import Registry, build_from_cfg +from modelscope.utils.config import ConfigDict +from modelscope.utils.registry import Registry, build_from_cfg MODELS = Registry('models') diff --git a/maas_lib/models/cv/__init__.py b/modelscope/models/cv/__init__.py similarity index 100% rename from maas_lib/models/cv/__init__.py rename to modelscope/models/cv/__init__.py diff --git a/maas_lib/models/cv/cartoon/__init__.py b/modelscope/models/cv/cartoon/__init__.py similarity index 100% rename from maas_lib/models/cv/cartoon/__init__.py rename to modelscope/models/cv/cartoon/__init__.py diff --git a/maas_lib/models/cv/cartoon/facelib/LICENSE b/modelscope/models/cv/cartoon/facelib/LICENSE similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/LICENSE rename to modelscope/models/cv/cartoon/facelib/LICENSE diff --git a/maas_lib/models/cv/cartoon/facelib/LK/__init__.py b/modelscope/models/cv/cartoon/facelib/LK/__init__.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/LK/__init__.py rename to modelscope/models/cv/cartoon/facelib/LK/__init__.py diff --git a/maas_lib/models/cv/cartoon/facelib/LK/lk.py b/modelscope/models/cv/cartoon/facelib/LK/lk.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/LK/lk.py rename to modelscope/models/cv/cartoon/facelib/LK/lk.py diff --git a/maas_lib/models/cv/cartoon/facelib/__init__.py b/modelscope/models/cv/cartoon/facelib/__init__.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/__init__.py rename to modelscope/models/cv/cartoon/facelib/__init__.py diff --git a/maas_lib/models/cv/cartoon/facelib/config.py b/modelscope/models/cv/cartoon/facelib/config.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/config.py rename to modelscope/models/cv/cartoon/facelib/config.py diff --git a/maas_lib/models/cv/cartoon/facelib/face_detector.py b/modelscope/models/cv/cartoon/facelib/face_detector.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/face_detector.py rename to modelscope/models/cv/cartoon/facelib/face_detector.py diff --git a/maas_lib/models/cv/cartoon/facelib/face_landmark.py b/modelscope/models/cv/cartoon/facelib/face_landmark.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/face_landmark.py rename to modelscope/models/cv/cartoon/facelib/face_landmark.py diff --git a/maas_lib/models/cv/cartoon/facelib/facer.py b/modelscope/models/cv/cartoon/facelib/facer.py similarity index 100% rename from maas_lib/models/cv/cartoon/facelib/facer.py rename to modelscope/models/cv/cartoon/facelib/facer.py diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/LICENSE b/modelscope/models/cv/cartoon/mtcnn_pytorch/LICENSE similarity index 100% rename from maas_lib/models/cv/cartoon/mtcnn_pytorch/LICENSE rename to modelscope/models/cv/cartoon/mtcnn_pytorch/LICENSE diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/README.md b/modelscope/models/cv/cartoon/mtcnn_pytorch/README.md similarity index 100% rename from maas_lib/models/cv/cartoon/mtcnn_pytorch/README.md rename to modelscope/models/cv/cartoon/mtcnn_pytorch/README.md diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/__init__.py b/modelscope/models/cv/cartoon/mtcnn_pytorch/__init__.py similarity index 100% rename from maas_lib/models/cv/cartoon/mtcnn_pytorch/__init__.py rename to modelscope/models/cv/cartoon/mtcnn_pytorch/__init__.py diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/__init__.py b/modelscope/models/cv/cartoon/mtcnn_pytorch/src/__init__.py similarity index 100% rename from maas_lib/models/cv/cartoon/mtcnn_pytorch/src/__init__.py rename to modelscope/models/cv/cartoon/mtcnn_pytorch/src/__init__.py diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py b/modelscope/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py similarity index 100% rename from maas_lib/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py rename to modelscope/models/cv/cartoon/mtcnn_pytorch/src/align_trans.py diff --git a/maas_lib/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py b/modelscope/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py similarity index 100% rename from maas_lib/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py rename to modelscope/models/cv/cartoon/mtcnn_pytorch/src/matlab_cp2tform.py diff --git a/maas_lib/models/cv/cartoon/utils.py b/modelscope/models/cv/cartoon/utils.py similarity index 100% rename from maas_lib/models/cv/cartoon/utils.py rename to modelscope/models/cv/cartoon/utils.py diff --git a/maas_lib/models/nlp/__init__.py b/modelscope/models/nlp/__init__.py similarity index 100% rename from maas_lib/models/nlp/__init__.py rename to modelscope/models/nlp/__init__.py diff --git a/maas_lib/models/nlp/sequence_classification_model.py b/modelscope/models/nlp/sequence_classification_model.py similarity index 97% rename from maas_lib/models/nlp/sequence_classification_model.py rename to modelscope/models/nlp/sequence_classification_model.py index 0afdf26e..6ced7a4e 100644 --- a/maas_lib/models/nlp/sequence_classification_model.py +++ b/modelscope/models/nlp/sequence_classification_model.py @@ -2,7 +2,7 @@ from typing import Any, Dict import numpy as np -from maas_lib.utils.constant import Tasks +from modelscope.utils.constant import Tasks from ..base import Model from ..builder import MODELS diff --git a/maas_lib/models/nlp/text_generation_model.py b/modelscope/models/nlp/text_generation_model.py similarity index 97% rename from maas_lib/models/nlp/text_generation_model.py rename to modelscope/models/nlp/text_generation_model.py index 04345d22..ebefc8d1 100644 --- a/maas_lib/models/nlp/text_generation_model.py +++ b/modelscope/models/nlp/text_generation_model.py @@ -1,6 +1,6 @@ from typing import Any, Dict -from maas_lib.utils.constant import Tasks +from modelscope.utils.constant import Tasks from ..base import Model, Tensor from ..builder import MODELS diff --git a/maas_lib/pipelines/__init__.py b/modelscope/pipelines/__init__.py similarity index 100% rename from maas_lib/pipelines/__init__.py rename to modelscope/pipelines/__init__.py diff --git a/maas_lib/pipelines/audio/__init__.py b/modelscope/pipelines/audio/__init__.py similarity index 100% rename from maas_lib/pipelines/audio/__init__.py rename to modelscope/pipelines/audio/__init__.py diff --git a/maas_lib/pipelines/base.py b/modelscope/pipelines/base.py similarity index 93% rename from maas_lib/pipelines/base.py rename to modelscope/pipelines/base.py index 1ba8c36a..2e88801a 100644 --- a/maas_lib/pipelines/base.py +++ b/modelscope/pipelines/base.py @@ -6,11 +6,11 @@ from typing import Any, Dict, Generator, List, Union from maas_hub.snapshot_download import snapshot_download -from maas_lib.models.base import Model -from maas_lib.preprocessors import Preprocessor -from maas_lib.pydatasets import PyDataset -from maas_lib.utils.config import Config -from maas_lib.utils.hub import get_model_cache_dir +from modelscope.models.base import Model +from modelscope.preprocessors import Preprocessor +from modelscope.pydatasets import PyDataset +from modelscope.utils.config import Config +from modelscope.utils.hub import get_model_cache_dir from .util import is_model_name Tensor = Union['torch.Tensor', 'tf.Tensor'] @@ -75,7 +75,7 @@ class Pipeline(ABC): def __call__(self, input: Union[Input, List[Input]], *args, **post_kwargs) -> Union[Dict[str, Any], Generator]: # model provider should leave it as it is - # maas library developer will handle this function + # modelscope library developer will handle this function # simple showcase, need to support iterator type for both tensorflow and pytorch # input_dict = self._handle_input(input) diff --git a/maas_lib/pipelines/builder.py b/modelscope/pipelines/builder.py similarity index 58% rename from maas_lib/pipelines/builder.py rename to modelscope/pipelines/builder.py index cd1eb32f..06e614e6 100644 --- a/maas_lib/pipelines/builder.py +++ b/modelscope/pipelines/builder.py @@ -6,16 +6,26 @@ from typing import Union import json from maas_hub.file_download import model_file_download -from maas_lib.models.base import Model -from maas_lib.utils.config import Config, ConfigDict -from maas_lib.utils.constant import CONFIGFILE, Tasks -from maas_lib.utils.registry import Registry, build_from_cfg +from modelscope.models.base import Model +from modelscope.utils.config import Config, ConfigDict +from modelscope.utils.constant import CONFIGFILE, Tasks +from modelscope.utils.registry import Registry, build_from_cfg from .base import Pipeline -from .default import DEFAULT_MODEL_FOR_PIPELINE, get_default_pipeline_info from .util import is_model_name PIPELINES = Registry('pipelines') +DEFAULT_MODEL_FOR_PIPELINE = { + # TaskName: (pipeline_module_name, model_repo) + Tasks.image_matting: ('image-matting', 'damo/image-matting-person'), + Tasks.text_classification: + ('bert-sentiment-analysis', 'damo/bert-base-sst2'), + Tasks.text_generation: ('palm', 'damo/nlp_palm_text-generation_chinese'), + Tasks.image_captioning: ('ofa', None), + Tasks.image_generation: + ('cv_unet_person-image-cartoon', 'damo/cv_unet_image-matting_damo'), +} + def build_pipeline(cfg: ConfigDict, task_name: str = None, @@ -84,3 +94,42 @@ def pipeline(task: str = None, cfg.preprocessor = preprocessor return build_pipeline(cfg, task_name=task) + + +def add_default_pipeline_info(task: str, + model_name: str, + modelhub_name: str = None, + overwrite: bool = False): + """ Add default model for a task. + + Args: + task (str): task name. + model_name (str): model_name. + modelhub_name (str): name for default modelhub. + overwrite (bool): overwrite default info. + """ + if not overwrite: + assert task not in DEFAULT_MODEL_FOR_PIPELINE, \ + f'task {task} already has default model.' + + DEFAULT_MODEL_FOR_PIPELINE[task] = (model_name, modelhub_name) + + +def get_default_pipeline_info(task): + """ Get default info for certain task. + + Args: + task (str): task name. + + Return: + A tuple: first element is pipeline name(model_name), second element + is modelhub name. + """ + + if task not in DEFAULT_MODEL_FOR_PIPELINE: + # support pipeline which does not register default model + pipeline_name = list(PIPELINES.modules[task].keys())[0] + default_model = None + else: + pipeline_name, default_model = DEFAULT_MODEL_FOR_PIPELINE[task] + return pipeline_name, default_model diff --git a/maas_lib/pipelines/cv/__init__.py b/modelscope/pipelines/cv/__init__.py similarity index 100% rename from maas_lib/pipelines/cv/__init__.py rename to modelscope/pipelines/cv/__init__.py diff --git a/maas_lib/pipelines/cv/image_cartoon_pipeline.py b/modelscope/pipelines/cv/image_cartoon_pipeline.py similarity index 92% rename from maas_lib/pipelines/cv/image_cartoon_pipeline.py rename to modelscope/pipelines/cv/image_cartoon_pipeline.py index 88c2eb15..6a6c10e0 100644 --- a/maas_lib/pipelines/cv/image_cartoon_pipeline.py +++ b/modelscope/pipelines/cv/image_cartoon_pipeline.py @@ -6,14 +6,14 @@ import numpy as np import PIL import tensorflow as tf -from maas_lib.models.cv.cartoon.facelib.facer import FaceAna -from maas_lib.models.cv.cartoon.mtcnn_pytorch.src.align_trans import ( +from modelscope.models.cv.cartoon.facelib.facer import FaceAna +from modelscope.models.cv.cartoon.mtcnn_pytorch.src.align_trans import ( get_reference_facial_points, warp_and_crop_face) -from maas_lib.models.cv.cartoon.utils import get_f5p, padTo16x, resize_size -from maas_lib.pipelines.base import Input -from maas_lib.preprocessors import load_image -from maas_lib.utils.constant import Tasks -from maas_lib.utils.logger import get_logger +from modelscope.models.cv.cartoon.utils import get_f5p, padTo16x, resize_size +from modelscope.pipelines.base import Input +from modelscope.preprocessors import load_image +from modelscope.utils.constant import Tasks +from modelscope.utils.logger import get_logger from ..base import Pipeline from ..builder import PIPELINES diff --git a/maas_lib/pipelines/cv/image_matting_pipeline.py b/modelscope/pipelines/cv/image_matting_pipeline.py similarity index 92% rename from maas_lib/pipelines/cv/image_matting_pipeline.py rename to modelscope/pipelines/cv/image_matting_pipeline.py index 0317b4bd..6f3ff5f5 100644 --- a/maas_lib/pipelines/cv/image_matting_pipeline.py +++ b/modelscope/pipelines/cv/image_matting_pipeline.py @@ -5,10 +5,10 @@ import cv2 import numpy as np import PIL -from maas_lib.pipelines.base import Input -from maas_lib.preprocessors import load_image -from maas_lib.utils.constant import Tasks -from maas_lib.utils.logger import get_logger +from modelscope.pipelines.base import Input +from modelscope.preprocessors import load_image +from modelscope.utils.constant import Tasks +from modelscope.utils.logger import get_logger from ..base import Pipeline from ..builder import PIPELINES diff --git a/maas_lib/pipelines/multi_modal/__init__.py b/modelscope/pipelines/multi_modal/__init__.py similarity index 100% rename from maas_lib/pipelines/multi_modal/__init__.py rename to modelscope/pipelines/multi_modal/__init__.py diff --git a/maas_lib/pipelines/multi_modal/image_captioning.py b/modelscope/pipelines/multi_modal/image_captioning.py similarity index 95% rename from maas_lib/pipelines/multi_modal/image_captioning.py rename to modelscope/pipelines/multi_modal/image_captioning.py index 2d8cc618..91180e23 100644 --- a/maas_lib/pipelines/multi_modal/image_captioning.py +++ b/modelscope/pipelines/multi_modal/image_captioning.py @@ -4,10 +4,10 @@ import numpy as np import torch from PIL import Image -from maas_lib.pipelines.base import Input -from maas_lib.preprocessors import load_image -from maas_lib.utils.constant import Tasks -from maas_lib.utils.logger import get_logger +from modelscope.pipelines.base import Input +from modelscope.preprocessors import load_image +from modelscope.utils.constant import Tasks +from modelscope.utils.logger import get_logger from ..base import Pipeline from ..builder import PIPELINES diff --git a/maas_lib/pipelines/nlp/__init__.py b/modelscope/pipelines/nlp/__init__.py similarity index 100% rename from maas_lib/pipelines/nlp/__init__.py rename to modelscope/pipelines/nlp/__init__.py diff --git a/maas_lib/pipelines/nlp/sequence_classification_pipeline.py b/modelscope/pipelines/nlp/sequence_classification_pipeline.py similarity index 94% rename from maas_lib/pipelines/nlp/sequence_classification_pipeline.py rename to modelscope/pipelines/nlp/sequence_classification_pipeline.py index 014eb4a3..5a14f136 100644 --- a/maas_lib/pipelines/nlp/sequence_classification_pipeline.py +++ b/modelscope/pipelines/nlp/sequence_classification_pipeline.py @@ -5,9 +5,9 @@ from typing import Any, Dict, Union import json import numpy as np -from maas_lib.models.nlp import BertForSequenceClassification -from maas_lib.preprocessors import SequenceClassificationPreprocessor -from maas_lib.utils.constant import Tasks +from modelscope.models.nlp import BertForSequenceClassification +from modelscope.preprocessors import SequenceClassificationPreprocessor +from modelscope.utils.constant import Tasks from ...models import Model from ..base import Input, Pipeline from ..builder import PIPELINES diff --git a/maas_lib/pipelines/nlp/text_generation_pipeline.py b/modelscope/pipelines/nlp/text_generation_pipeline.py similarity index 91% rename from maas_lib/pipelines/nlp/text_generation_pipeline.py rename to modelscope/pipelines/nlp/text_generation_pipeline.py index 865557b5..7ad2b67f 100644 --- a/maas_lib/pipelines/nlp/text_generation_pipeline.py +++ b/modelscope/pipelines/nlp/text_generation_pipeline.py @@ -1,9 +1,9 @@ from typing import Dict, Optional, Union -from maas_lib.models import Model -from maas_lib.models.nlp import PalmForTextGenerationModel -from maas_lib.preprocessors import TextGenerationPreprocessor -from maas_lib.utils.constant import Tasks +from modelscope.models import Model +from modelscope.models.nlp import PalmForTextGenerationModel +from modelscope.preprocessors import TextGenerationPreprocessor +from modelscope.utils.constant import Tasks from ..base import Pipeline, Tensor from ..builder import PIPELINES diff --git a/maas_lib/pipelines/util.py b/modelscope/pipelines/util.py similarity index 94% rename from maas_lib/pipelines/util.py rename to modelscope/pipelines/util.py index 771e0d2b..92ad6af4 100644 --- a/maas_lib/pipelines/util.py +++ b/modelscope/pipelines/util.py @@ -5,7 +5,7 @@ import os.path as osp import json from maas_hub.file_download import model_file_download -from maas_lib.utils.constant import CONFIGFILE +from modelscope.utils.constant import CONFIGFILE def is_model_name(model): diff --git a/maas_lib/preprocessors/__init__.py b/modelscope/preprocessors/__init__.py similarity index 100% rename from maas_lib/preprocessors/__init__.py rename to modelscope/preprocessors/__init__.py diff --git a/maas_lib/preprocessors/base.py b/modelscope/preprocessors/base.py similarity index 100% rename from maas_lib/preprocessors/base.py rename to modelscope/preprocessors/base.py diff --git a/maas_lib/preprocessors/builder.py b/modelscope/preprocessors/builder.py similarity index 80% rename from maas_lib/preprocessors/builder.py rename to modelscope/preprocessors/builder.py index 69421b5f..918f8d17 100644 --- a/maas_lib/preprocessors/builder.py +++ b/modelscope/preprocessors/builder.py @@ -1,8 +1,8 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -from maas_lib.utils.config import ConfigDict -from maas_lib.utils.constant import Fields -from maas_lib.utils.registry import Registry, build_from_cfg +from modelscope.utils.config import ConfigDict +from modelscope.utils.constant import Fields +from modelscope.utils.registry import Registry, build_from_cfg PREPROCESSORS = Registry('preprocessors') diff --git a/maas_lib/preprocessors/common.py b/modelscope/preprocessors/common.py similarity index 100% rename from maas_lib/preprocessors/common.py rename to modelscope/preprocessors/common.py diff --git a/maas_lib/preprocessors/image.py b/modelscope/preprocessors/image.py similarity index 96% rename from maas_lib/preprocessors/image.py rename to modelscope/preprocessors/image.py index 8db9f5bb..142f9484 100644 --- a/maas_lib/preprocessors/image.py +++ b/modelscope/preprocessors/image.py @@ -4,8 +4,8 @@ from typing import Dict, Union from PIL import Image, ImageOps -from maas_lib.fileio import File -from maas_lib.utils.constant import Fields +from modelscope.fileio import File +from modelscope.utils.constant import Fields from .builder import PREPROCESSORS diff --git a/maas_lib/preprocessors/nlp.py b/modelscope/preprocessors/nlp.py similarity index 97% rename from maas_lib/preprocessors/nlp.py rename to modelscope/preprocessors/nlp.py index 176322d4..0de41bfc 100644 --- a/maas_lib/preprocessors/nlp.py +++ b/modelscope/preprocessors/nlp.py @@ -5,8 +5,8 @@ from typing import Any, Dict, Union from transformers import AutoTokenizer -from maas_lib.utils.constant import Fields, InputFields -from maas_lib.utils.type_assert import type_assert +from modelscope.utils.constant import Fields, InputFields +from modelscope.utils.type_assert import type_assert from .base import Preprocessor from .builder import PREPROCESSORS diff --git a/maas_lib/pydatasets/__init__.py b/modelscope/pydatasets/__init__.py similarity index 100% rename from maas_lib/pydatasets/__init__.py rename to modelscope/pydatasets/__init__.py diff --git a/maas_lib/pydatasets/py_dataset.py b/modelscope/pydatasets/py_dataset.py similarity index 96% rename from maas_lib/pydatasets/py_dataset.py rename to modelscope/pydatasets/py_dataset.py index 58f83830..7d0edadb 100644 --- a/maas_lib/pydatasets/py_dataset.py +++ b/modelscope/pydatasets/py_dataset.py @@ -4,7 +4,7 @@ from typing import (Any, Callable, Dict, List, Mapping, Optional, Sequence, from datasets import Dataset, load_dataset -from maas_lib.utils.logger import get_logger +from modelscope.utils.logger import get_logger logger = get_logger() @@ -52,7 +52,7 @@ class PyDataset: Mapping[str, Union[str, Sequence[str]]]]] = None ) -> 'PyDataset': - """Load a PyDataset from the MaaS Hub, Hugging Face Hub, urls, or a local dataset. + """Load a PyDataset from the ModelScope Hub, Hugging Face Hub, urls, or a local dataset. Args: path (str): Path or name of the dataset. diff --git a/maas_lib/tools/eval.py b/modelscope/tools/eval.py similarity index 94% rename from maas_lib/tools/eval.py rename to modelscope/tools/eval.py index 95bf7054..ca39932d 100644 --- a/maas_lib/tools/eval.py +++ b/modelscope/tools/eval.py @@ -2,7 +2,7 @@ import argparse -from maas_lib.trainers import build_trainer +from modelscope.trainers import build_trainer def parse_args(): diff --git a/maas_lib/tools/train.py b/modelscope/tools/train.py similarity index 92% rename from maas_lib/tools/train.py rename to modelscope/tools/train.py index f7c2b54b..c6f1ef5f 100644 --- a/maas_lib/tools/train.py +++ b/modelscope/tools/train.py @@ -2,7 +2,7 @@ import argparse -from maas_lib.trainers import build_trainer +from modelscope.trainers import build_trainer def parse_args(): diff --git a/maas_lib/trainers/__init__.py b/modelscope/trainers/__init__.py similarity index 100% rename from maas_lib/trainers/__init__.py rename to modelscope/trainers/__init__.py diff --git a/maas_lib/trainers/base.py b/modelscope/trainers/base.py similarity index 96% rename from maas_lib/trainers/base.py rename to modelscope/trainers/base.py index 2c11779e..372938b4 100644 --- a/maas_lib/trainers/base.py +++ b/modelscope/trainers/base.py @@ -3,8 +3,8 @@ from abc import ABC, abstractmethod from typing import Callable, Dict, List, Optional, Tuple, Union -from maas_lib.trainers.builder import TRAINERS -from maas_lib.utils.config import Config +from modelscope.trainers.builder import TRAINERS +from modelscope.utils.config import Config class BaseTrainer(ABC): diff --git a/maas_lib/trainers/builder.py b/modelscope/trainers/builder.py similarity index 77% rename from maas_lib/trainers/builder.py rename to modelscope/trainers/builder.py index 2165fe58..2192d46c 100644 --- a/maas_lib/trainers/builder.py +++ b/modelscope/trainers/builder.py @@ -1,8 +1,8 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -from maas_lib.utils.config import ConfigDict -from maas_lib.utils.constant import Tasks -from maas_lib.utils.registry import Registry, build_from_cfg +from modelscope.utils.config import ConfigDict +from modelscope.utils.constant import Tasks +from modelscope.utils.registry import Registry, build_from_cfg TRAINERS = Registry('trainers') diff --git a/maas_lib/trainers/nlp/__init__.py b/modelscope/trainers/nlp/__init__.py similarity index 100% rename from maas_lib/trainers/nlp/__init__.py rename to modelscope/trainers/nlp/__init__.py diff --git a/maas_lib/trainers/nlp/sequence_classification_trainer.py b/modelscope/trainers/nlp/sequence_classification_trainer.py similarity index 98% rename from maas_lib/trainers/nlp/sequence_classification_trainer.py rename to modelscope/trainers/nlp/sequence_classification_trainer.py index f2264c0d..b2b759fa 100644 --- a/maas_lib/trainers/nlp/sequence_classification_trainer.py +++ b/modelscope/trainers/nlp/sequence_classification_trainer.py @@ -3,8 +3,8 @@ from typing import Callable, Dict, List, Optional, Tuple, Union import numpy as np -from maas_lib.utils.constant import Tasks -from maas_lib.utils.logger import get_logger +from modelscope.utils.constant import Tasks +from modelscope.utils.logger import get_logger from ..base import BaseTrainer from ..builder import TRAINERS diff --git a/maas_lib/utils/__init__.py b/modelscope/utils/__init__.py similarity index 100% rename from maas_lib/utils/__init__.py rename to modelscope/utils/__init__.py diff --git a/maas_lib/utils/config.py b/modelscope/utils/config.py similarity index 98% rename from maas_lib/utils/config.py rename to modelscope/utils/config.py index 7d67d248..d0f3f657 100644 --- a/maas_lib/utils/config.py +++ b/modelscope/utils/config.py @@ -17,9 +17,9 @@ from typing import Dict import addict from yapf.yapflib.yapf_api import FormatCode -from maas_lib.utils.logger import get_logger -from maas_lib.utils.pymod import (import_modules, import_modules_from_file, - validate_py_syntax) +from modelscope.utils.logger import get_logger +from modelscope.utils.pymod import (import_modules, import_modules_from_file, + validate_py_syntax) if platform.system() == 'Windows': import regex as re # type: ignore @@ -117,7 +117,7 @@ class Config: # delete imported module del sys.modules[module_nanme] elif filename.endswith(('.yml', '.yaml', '.json')): - from maas_lib.fileio import load + from modelscope.fileio import load cfg_dict = load(tmp_cfg_file.name) # close temp file tmp_cfg_file.close() @@ -364,7 +364,7 @@ class Config: file (str, optional): Path of the output file where the config will be dumped. Defaults to None. """ - from maas_lib.fileio import dump + from modelscope.fileio import dump cfg_dict = super(Config, self).__getattribute__('_cfg_dict').to_dict() if file is None: if self.filename is None or self.filename.endswith('.py'): diff --git a/maas_lib/utils/constant.py b/modelscope/utils/constant.py similarity index 97% rename from maas_lib/utils/constant.py rename to modelscope/utils/constant.py index 8f808a6f..eae719a3 100644 --- a/maas_lib/utils/constant.py +++ b/modelscope/utils/constant.py @@ -13,7 +13,7 @@ class Fields(object): class Tasks(object): - """ Names for tasks supported by maas lib. + """ Names for tasks supported by modelscope. Holds the standard task name to use for identifying different tasks. This should be used to register models, pipelines, trainers. diff --git a/maas_lib/utils/hub.py b/modelscope/utils/hub.py similarity index 100% rename from maas_lib/utils/hub.py rename to modelscope/utils/hub.py diff --git a/maas_lib/utils/logger.py b/modelscope/utils/logger.py similarity index 100% rename from maas_lib/utils/logger.py rename to modelscope/utils/logger.py diff --git a/maas_lib/utils/pymod.py b/modelscope/utils/pymod.py similarity index 98% rename from maas_lib/utils/pymod.py rename to modelscope/utils/pymod.py index 4f717480..6db6798d 100644 --- a/maas_lib/utils/pymod.py +++ b/modelscope/utils/pymod.py @@ -7,7 +7,7 @@ import sys import types from importlib import import_module -from maas_lib.utils.logger import get_logger +from modelscope.utils.logger import get_logger logger = get_logger() diff --git a/maas_lib/utils/registry.py b/modelscope/utils/registry.py similarity index 98% rename from maas_lib/utils/registry.py rename to modelscope/utils/registry.py index bac3d616..73a938ea 100644 --- a/maas_lib/utils/registry.py +++ b/modelscope/utils/registry.py @@ -3,7 +3,7 @@ import inspect from email.policy import default -from maas_lib.utils.logger import get_logger +from modelscope.utils.logger import get_logger default_group = 'default' logger = get_logger() @@ -174,7 +174,7 @@ def build_from_cfg(cfg, '`cfg` or `default_args` must contain the key "type", ' f'but got {cfg}\n{default_args}') if not isinstance(registry, Registry): - raise TypeError('registry must be an maas_lib.Registry object, ' + raise TypeError('registry must be an modelscope.Registry object, ' f'but got {type(registry)}') if not (isinstance(default_args, dict) or default_args is None): raise TypeError('default_args must be a dict or None, ' diff --git a/maas_lib/utils/type_assert.py b/modelscope/utils/type_assert.py similarity index 100% rename from maas_lib/utils/type_assert.py rename to modelscope/utils/type_assert.py diff --git a/maas_lib/version.py b/modelscope/version.py similarity index 100% rename from maas_lib/version.py rename to modelscope/version.py diff --git a/requirements/maas.txt b/requirements/maas.txt deleted file mode 100644 index 3b64c375..00000000 --- a/requirements/maas.txt +++ /dev/null @@ -1,2 +0,0 @@ -http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release/maas/maas_lib-0.1.1-py3-none-any.whl -https://maashub.oss-cn-hangzhou.aliyuncs.com/releases/maas_hub-0.1.0.dev0-py2.py3-none-any.whl diff --git a/requirements/runtime.txt b/requirements/runtime.txt index b57358fc..47a11cbc 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -1,5 +1,6 @@ addict datasets +easydict https://maashub.oss-cn-hangzhou.aliyuncs.com/releases/maas_hub-0.1.0.dev0-py2.py3-none-any.whl numpy opencv-python-headless diff --git a/setup.cfg b/setup.cfg index 8feaa182..0b929b04 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,7 @@ line_length = 79 multi_line_output = 0 known_standard_library = setuptools -known_first_party = maas_lib +known_first_party = modelscope known_third_party = json,yaml no_lines_before = STDLIB,LOCALFOLDER default_section = THIRDPARTY diff --git a/setup.py b/setup.py index b9044bff..b027c4cb 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ def readme(): return content -version_file = 'maas_lib/version.py' +version_file = 'modelscope/version.py' def get_git_hash(): @@ -155,8 +155,8 @@ def pack_resource(): shutil.rmtree(root_dir) os.makedirs(root_dir) - proj_dir = root_dir + 'maas_lib/' - shutil.copytree('./maas_lib', proj_dir) + proj_dir = root_dir + 'modelscope/' + shutil.copytree('./modelscope', proj_dir) shutil.copytree('./configs', proj_dir + 'configs') shutil.copytree('./requirements', 'package/requirements') shutil.copy('./requirements.txt', 'package/requirements.txt') @@ -170,13 +170,13 @@ if __name__ == '__main__': os.chdir('package') install_requires, deps_link = parse_requirements('requirements.txt') setup( - name='maas-lib', + name='model-scope', version=get_version(), description='', long_description=readme(), long_description_content_type='text/markdown', - author='Alibaba MaaS team', - author_email='maas_lib@list.alibaba-inc.com', + author='Alibaba ModelScope team', + author_email='modelscope@list.alibaba-inc.com', keywords='', url='TBD', packages=find_packages(exclude=('configs', 'tools', 'demo')), diff --git a/tests/fileio/test_file.py b/tests/fileio/test_file.py index 9f83f02c..0be41b42 100644 --- a/tests/fileio/test_file.py +++ b/tests/fileio/test_file.py @@ -5,7 +5,7 @@ import unittest from requests import HTTPError -from maas_lib.fileio.file import File, HTTPStorage, LocalStorage +from modelscope.fileio.file import File, HTTPStorage, LocalStorage class FileTest(unittest.TestCase): diff --git a/tests/fileio/test_io.py b/tests/fileio/test_io.py index 1e202e5b..0a80d3f7 100644 --- a/tests/fileio/test_io.py +++ b/tests/fileio/test_io.py @@ -2,7 +2,7 @@ import tempfile import unittest -from maas_lib.fileio.io import dump, dumps, load +from modelscope.fileio.io import dump, dumps, load class FileIOTest(unittest.TestCase): diff --git a/tests/pipelines/test_base.py b/tests/pipelines/test_base.py index 5994ddde..14f646a9 100644 --- a/tests/pipelines/test_base.py +++ b/tests/pipelines/test_base.py @@ -6,12 +6,11 @@ from typing import Any, Dict, List, Tuple, Union import numpy as np import PIL -from maas_lib.pipelines import Pipeline, pipeline -from maas_lib.pipelines.builder import PIPELINES -from maas_lib.pipelines.default import add_default_pipeline_info -from maas_lib.utils.constant import Tasks -from maas_lib.utils.logger import get_logger -from maas_lib.utils.registry import default_group +from modelscope.pipelines import Pipeline, pipeline +from modelscope.pipelines.builder import PIPELINES, add_default_pipeline_info +from modelscope.utils.constant import Tasks +from modelscope.utils.logger import get_logger +from modelscope.utils.registry import default_group logger = get_logger() @@ -54,7 +53,7 @@ class CustomPipelineTest(unittest.TestCase): """ if not isinstance(input, PIL.Image.Image): - from maas_lib.preprocessors import load_image + from modelscope.preprocessors import load_image data_dict = {'img': load_image(input), 'url': input} else: data_dict = {'img': input} diff --git a/tests/pipelines/test_image_captioning.py b/tests/pipelines/test_image_captioning.py index afcab01d..5584d0e2 100644 --- a/tests/pipelines/test_image_captioning.py +++ b/tests/pipelines/test_image_captioning.py @@ -4,9 +4,9 @@ import os import tempfile import unittest -from maas_lib.fileio import File -from maas_lib.pipelines import pipeline -from maas_lib.utils.constant import Tasks +from modelscope.fileio import File +from modelscope.pipelines import pipeline +from modelscope.utils.constant import Tasks class ImageCaptionTest(unittest.TestCase): diff --git a/tests/pipelines/test_image_matting.py b/tests/pipelines/test_image_matting.py index 25f19102..53006317 100644 --- a/tests/pipelines/test_image_matting.py +++ b/tests/pipelines/test_image_matting.py @@ -6,11 +6,11 @@ import unittest import cv2 -from maas_lib.fileio import File -from maas_lib.pipelines import pipeline -from maas_lib.pydatasets import PyDataset -from maas_lib.utils.constant import Tasks -from maas_lib.utils.hub import get_model_cache_dir +from modelscope.fileio import File +from modelscope.pipelines import pipeline +from modelscope.pydatasets import PyDataset +from modelscope.utils.constant import Tasks +from modelscope.utils.hub import get_model_cache_dir class ImageMattingTest(unittest.TestCase): diff --git a/tests/pipelines/test_person_image_cartoon.py b/tests/pipelines/test_person_image_cartoon.py index dae853d7..817593f1 100644 --- a/tests/pipelines/test_person_image_cartoon.py +++ b/tests/pipelines/test_person_image_cartoon.py @@ -4,8 +4,8 @@ import unittest import cv2 -from maas_lib.pipelines import pipeline -from maas_lib.utils.constant import Tasks +from modelscope.pipelines import pipeline +from modelscope.utils.constant import Tasks def all_file(file_dir): diff --git a/tests/pipelines/test_text_classification.py b/tests/pipelines/test_text_classification.py index 36285f80..3e3faa1d 100644 --- a/tests/pipelines/test_text_classification.py +++ b/tests/pipelines/test_text_classification.py @@ -4,14 +4,14 @@ import unittest import zipfile from pathlib import Path -from maas_lib.fileio import File -from maas_lib.models import Model -from maas_lib.models.nlp import BertForSequenceClassification -from maas_lib.pipelines import SequenceClassificationPipeline, pipeline -from maas_lib.preprocessors import SequenceClassificationPreprocessor -from maas_lib.pydatasets import PyDataset -from maas_lib.utils.constant import Tasks -from maas_lib.utils.hub import get_model_cache_dir +from modelscope.fileio import File +from modelscope.models import Model +from modelscope.models.nlp import BertForSequenceClassification +from modelscope.pipelines import SequenceClassificationPipeline, pipeline +from modelscope.preprocessors import SequenceClassificationPreprocessor +from modelscope.pydatasets import PyDataset +from modelscope.utils.constant import Tasks +from modelscope.utils.hub import get_model_cache_dir class SequenceClassificationTest(unittest.TestCase): diff --git a/tests/pipelines/test_text_generation.py b/tests/pipelines/test_text_generation.py index 235279c2..d8f1b495 100644 --- a/tests/pipelines/test_text_generation.py +++ b/tests/pipelines/test_text_generation.py @@ -3,11 +3,11 @@ import unittest from maas_hub.snapshot_download import snapshot_download -from maas_lib.models import Model -from maas_lib.models.nlp import PalmForTextGenerationModel -from maas_lib.pipelines import TextGenerationPipeline, pipeline -from maas_lib.preprocessors import TextGenerationPreprocessor -from maas_lib.utils.constant import Tasks +from modelscope.models import Model +from modelscope.models.nlp import PalmForTextGenerationModel +from modelscope.pipelines import TextGenerationPipeline, pipeline +from modelscope.preprocessors import TextGenerationPreprocessor +from modelscope.utils.constant import Tasks class TextGenerationTest(unittest.TestCase): diff --git a/tests/preprocessors/test_common.py b/tests/preprocessors/test_common.py index d9b0f74f..1ee13589 100644 --- a/tests/preprocessors/test_common.py +++ b/tests/preprocessors/test_common.py @@ -2,7 +2,7 @@ import unittest -from maas_lib.preprocessors import PREPROCESSORS, Compose, Preprocessor +from modelscope.preprocessors import PREPROCESSORS, Compose, Preprocessor class ComposeTest(unittest.TestCase): diff --git a/tests/preprocessors/test_nlp.py b/tests/preprocessors/test_nlp.py index 740bf938..fca01597 100644 --- a/tests/preprocessors/test_nlp.py +++ b/tests/preprocessors/test_nlp.py @@ -2,9 +2,9 @@ import unittest -from maas_lib.preprocessors import build_preprocessor -from maas_lib.utils.constant import Fields, InputFields -from maas_lib.utils.logger import get_logger +from modelscope.preprocessors import build_preprocessor +from modelscope.utils.constant import Fields, InputFields +from modelscope.utils.logger import get_logger logger = get_logger() diff --git a/tests/pydatasets/test_py_dataset.py b/tests/pydatasets/test_py_dataset.py index a32dcb0e..7accd814 100644 --- a/tests/pydatasets/test_py_dataset.py +++ b/tests/pydatasets/test_py_dataset.py @@ -2,7 +2,7 @@ import unittest import datasets as hfdata -from maas_lib.pydatasets import PyDataset +from modelscope.pydatasets import PyDataset class PyDatasetTest(unittest.TestCase): diff --git a/tests/trainers/test_sequence_classification_trainer.py b/tests/trainers/test_sequence_classification_trainer.py index 9846db4f..c0b2d109 100644 --- a/tests/trainers/test_sequence_classification_trainer.py +++ b/tests/trainers/test_sequence_classification_trainer.py @@ -2,9 +2,9 @@ import unittest import zipfile from pathlib import Path -from maas_lib.fileio import File -from maas_lib.trainers import build_trainer -from maas_lib.utils.logger import get_logger +from modelscope.fileio import File +from modelscope.trainers import build_trainer +from modelscope.utils.logger import get_logger logger = get_logger() diff --git a/tests/trainers/test_trainer_base.py b/tests/trainers/test_trainer_base.py index e764d6c9..c5fc1303 100644 --- a/tests/trainers/test_trainer_base.py +++ b/tests/trainers/test_trainer_base.py @@ -2,7 +2,7 @@ import unittest -from maas_lib.trainers import build_trainer +from modelscope.trainers import build_trainer class DummyTrainerTest(unittest.TestCase): diff --git a/tests/utils/test_config.py b/tests/utils/test_config.py index 31d51311..48f1d4a8 100644 --- a/tests/utils/test_config.py +++ b/tests/utils/test_config.py @@ -5,8 +5,8 @@ import tempfile import unittest from pathlib import Path -from maas_lib.fileio import dump, load -from maas_lib.utils.config import Config +from modelscope.fileio import dump, load +from modelscope.utils.config import Config obj = {'a': 1, 'b': {'c': [1, 2, 3], 'd': 'dd'}} diff --git a/tests/utils/test_registry.py b/tests/utils/test_registry.py index 982b9f21..67e44f4e 100644 --- a/tests/utils/test_registry.py +++ b/tests/utils/test_registry.py @@ -1,8 +1,8 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import unittest -from maas_lib.utils.constant import Tasks -from maas_lib.utils.registry import Registry, build_from_cfg, default_group +from modelscope.utils.constant import Tasks +from modelscope.utils.registry import Registry, build_from_cfg, default_group class RegistryTest(unittest.TestCase): diff --git a/tests/utils/test_type_assert.py b/tests/utils/test_type_assert.py index 4ec9f2e5..5b62a269 100644 --- a/tests/utils/test_type_assert.py +++ b/tests/utils/test_type_assert.py @@ -3,7 +3,7 @@ import unittest from typing import List, Union -from maas_lib.utils.type_assert import type_assert +from modelscope.utils.type_assert import type_assert class type_assertTest(unittest.TestCase): From 3c1ec035fd3140c4b4745ed817d65d030fb49a40 Mon Sep 17 00:00:00 2001 From: "yingda.chen" Date: Fri, 10 Jun 2022 12:56:44 +0800 Subject: [PATCH 12/13] [to #42322933] refine cartoon model and add model op utitlity Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8993758 --- modelscope/pipelines/builder.py | 3 +- .../pipelines/cv/image_cartoon_pipeline.py | 11 ++-- tests/pipelines/test_person_image_cartoon.py | 37 +++++++++----- tests/utils/test_hub_operation.py | 50 +++++++++++++++++++ 4 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 tests/utils/test_hub_operation.py diff --git a/modelscope/pipelines/builder.py b/modelscope/pipelines/builder.py index 06e614e6..6d0ec729 100644 --- a/modelscope/pipelines/builder.py +++ b/modelscope/pipelines/builder.py @@ -23,7 +23,8 @@ DEFAULT_MODEL_FOR_PIPELINE = { Tasks.text_generation: ('palm', 'damo/nlp_palm_text-generation_chinese'), Tasks.image_captioning: ('ofa', None), Tasks.image_generation: - ('cv_unet_person-image-cartoon', 'damo/cv_unet_image-matting_damo'), + ('person-image-cartoon', + 'damo/cv_unet_person-image-cartoon_compound-models'), } diff --git a/modelscope/pipelines/cv/image_cartoon_pipeline.py b/modelscope/pipelines/cv/image_cartoon_pipeline.py index 6a6c10e0..d253eaf5 100644 --- a/modelscope/pipelines/cv/image_cartoon_pipeline.py +++ b/modelscope/pipelines/cv/image_cartoon_pipeline.py @@ -25,20 +25,19 @@ logger = get_logger() @PIPELINES.register_module( - Tasks.image_generation, module_name='cv_unet_person-image-cartoon') + Tasks.image_generation, module_name='person-image-cartoon') class ImageCartoonPipeline(Pipeline): def __init__(self, model: str): super().__init__(model=model) - - self.facer = FaceAna(model) + self.facer = FaceAna(self.model) self.sess_anime_head = self.load_sess( - os.path.join(model, 'cartoon_anime_h.pb'), 'model_anime_head') + os.path.join(self.model, 'cartoon_anime_h.pb'), 'model_anime_head') self.sess_anime_bg = self.load_sess( - os.path.join(model, 'cartoon_anime_bg.pb'), 'model_anime_bg') + os.path.join(self.model, 'cartoon_anime_bg.pb'), 'model_anime_bg') self.box_width = 288 - global_mask = cv2.imread(os.path.join(model, 'alpha.jpg')) + global_mask = cv2.imread(os.path.join(self.model, 'alpha.jpg')) global_mask = cv2.resize( global_mask, (self.box_width, self.box_width), interpolation=cv2.INTER_AREA) diff --git a/tests/pipelines/test_person_image_cartoon.py b/tests/pipelines/test_person_image_cartoon.py index 817593f1..6f352e42 100644 --- a/tests/pipelines/test_person_image_cartoon.py +++ b/tests/pipelines/test_person_image_cartoon.py @@ -1,26 +1,31 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import os +import os.path as osp import unittest import cv2 from modelscope.pipelines import pipeline +from modelscope.pipelines.base import Pipeline from modelscope.utils.constant import Tasks -def all_file(file_dir): - L = [] - for root, dirs, files in os.walk(file_dir): - for file in files: - extend = os.path.splitext(file)[1] - if extend == '.png' or extend == '.jpg' or extend == '.jpeg' or extend == '.JPG' or extend == '.HEIC': - L.append(os.path.join(root, file)) - return L +class ImageCartoonTest(unittest.TestCase): + def setUp(self) -> None: + self.model_id = 'damo/cv_unet_person-image-cartoon_compound-models' + self.test_image = \ + 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com' \ + '/data/test/maas/image_carton/test.png' -class ImageCartoonTest(unittest.TestCase): + def pipeline_inference(self, pipeline: Pipeline, input_location: str): + result = pipeline(input_location) + if result is not None: + cv2.imwrite('result.png', result['output_png']) + print(f'Output written to {osp.abspath("result.png")}') - def test_run(self): + @unittest.skip('deprecated, download model from model hub instead') + def test_run_by_direct_model_download(self): model_dir = './assets' if not os.path.exists(model_dir): os.system( @@ -29,9 +34,15 @@ class ImageCartoonTest(unittest.TestCase): os.system('unzip assets.zip') img_cartoon = pipeline(Tasks.image_generation, model=model_dir) - result = img_cartoon(os.path.join(model_dir, 'test.png')) - if result is not None: - cv2.imwrite('result.png', result['output_png']) + self.pipeline_inference(img_cartoon, self.test_image) + + def test_run_modelhub(self): + img_cartoon = pipeline(Tasks.image_generation, model=self.model_id) + self.pipeline_inference(img_cartoon, self.test_image) + + def test_run_modelhub_default_model(self): + img_cartoon = pipeline(Tasks.image_generation) + self.pipeline_inference(img_cartoon, self.test_image) if __name__ == '__main__': diff --git a/tests/utils/test_hub_operation.py b/tests/utils/test_hub_operation.py new file mode 100644 index 00000000..f432a60c --- /dev/null +++ b/tests/utils/test_hub_operation.py @@ -0,0 +1,50 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +import os.path as osp +import unittest + +from maas_hub.maas_api import MaasApi +from maas_hub.repository import Repository + +USER_NAME = 'maasadmin' +PASSWORD = '12345678' + + +class HubOperationTest(unittest.TestCase): + + def setUp(self): + self.api = MaasApi() + # note this is temporary before official account management is ready + self.api.login(USER_NAME, PASSWORD) + + @unittest.skip('to be used for local test only') + def test_model_repo_creation(self): + # change to proper model names before use + model_name = 'cv_unet_person-image-cartoon_compound-models' + model_chinese_name = '达摩卡通化模型' + model_org = 'damo' + try: + self.api.create_model( + owner=model_org, + name=model_name, + chinese_name=model_chinese_name, + visibility=5, # 1-private, 5-public + license='apache-2.0') + # TODO: support proper name duplication checking + except KeyError as ke: + if ke.args[0] == 'name': + print(f'model {self.model_name} already exists, ignore') + else: + raise + + # Note that this can be done via git operation once model repo + # has been created. Git-Op is the RECOMMENDED model upload approach + @unittest.skip('to be used for local test only') + def test_model_upload(self): + local_path = '/path/to/local/model/directory' + assert osp.exists(local_path), 'Local model directory not exist.' + repo = Repository(local_dir=local_path) + repo.push_to_hub(commit_message='Upload model files') + + +if __name__ == '__main__': + unittest.main() From 76bc51eadd7d3e257f2e439c836c2c48155271d8 Mon Sep 17 00:00:00 2001 From: "wenmeng.zwm" Date: Fri, 10 Jun 2022 16:22:28 +0800 Subject: [PATCH 13/13] [to #42362853] support multimodel in pipeline Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/8997599 --- modelscope/pipelines/base.py | 10 ++++- modelscope/pipelines/builder.py | 51 +++++++++++++++++++++---- modelscope/pipelines/util.py | 52 ++++++++++++++++--------- tests/pipelines/test_builder.py | 68 +++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 28 deletions(-) create mode 100644 tests/pipelines/test_builder.py diff --git a/modelscope/pipelines/base.py b/modelscope/pipelines/base.py index 2e88801a..f4d4d1b7 100644 --- a/modelscope/pipelines/base.py +++ b/modelscope/pipelines/base.py @@ -11,6 +11,7 @@ from modelscope.preprocessors import Preprocessor from modelscope.pydatasets import PyDataset from modelscope.utils.config import Config from modelscope.utils.hub import get_model_cache_dir +from modelscope.utils.logger import get_logger from .util import is_model_name Tensor = Union['torch.Tensor', 'tf.Tensor'] @@ -20,11 +21,15 @@ InputModel = Union[str, Model] output_keys = [ ] # 对于不同task的pipeline,规定标准化的输出key,用以对接postprocess,同时也用来标准化postprocess后输出的key +logger = get_logger() + class Pipeline(ABC): def initiate_single_model(self, model): - if isinstance(model, str): + logger.info(f'initiate model from {model}') + # TODO @wenmeng.zwm replace model.startswith('damo/') with get_model + if isinstance(model, str) and model.startswith('damo/'): if not osp.exists(model): cache_path = get_model_cache_dir(model) model = cache_path if osp.exists( @@ -34,10 +39,11 @@ class Pipeline(ABC): elif isinstance(model, Model): return model else: - if model: + if model and not isinstance(model, str): raise ValueError( f'model type for single model is either str or Model, but got type {type(model)}' ) + return model def initiate_multiple_models(self, input_models: List[InputModel]): models = [] diff --git a/modelscope/pipelines/builder.py b/modelscope/pipelines/builder.py index 6d0ec729..6495a5db 100644 --- a/modelscope/pipelines/builder.py +++ b/modelscope/pipelines/builder.py @@ -1,7 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import os.path as osp -from typing import Union +from typing import List, Union import json from maas_hub.file_download import model_file_download @@ -44,7 +44,7 @@ def build_pipeline(cfg: ConfigDict, def pipeline(task: str = None, - model: Union[str, Model] = None, + model: Union[str, List[str], Model, List[Model]] = None, preprocessor=None, config_file: str = None, pipeline_name: str = None, @@ -56,7 +56,7 @@ def pipeline(task: str = None, Args: task (str): Task name defining which pipeline will be returned. - model (str or obj:`Model`): model name or model object. + model (str or List[str] or obj:`Model` or obj:list[`Model`]): (list of) model name or model object. preprocessor: preprocessor object. config_file (str, optional): path to config file. pipeline_name (str, optional): pipeline class name or alias name. @@ -68,23 +68,42 @@ def pipeline(task: str = None, Examples: ```python + >>> # Using default model for a task >>> p = pipeline('image-classification') - >>> p = pipeline('text-classification', model='distilbert-base-uncased') - >>> # Using model object + >>> # Using pipeline with a model name + >>> p = pipeline('text-classification', model='damo/distilbert-base-uncased') + >>> # Using pipeline with a model object >>> resnet = Model.from_pretrained('Resnet') >>> p = pipeline('image-classification', model=resnet) + >>> # Using pipeline with a list of model names + >>> p = pipeline('audio-kws', model=['damo/audio-tts', 'damo/auto-tts2']) """ if task is None and pipeline_name is None: raise ValueError('task or pipeline_name is required') if pipeline_name is None: # get default pipeline for this task - pipeline_name, default_model_repo = get_default_pipeline_info(task) + if isinstance(model, str) \ + or (isinstance(model, list) and isinstance(model[0], str)): + + # if is_model_name(model): + if (isinstance(model, str) and model.startswith('damo/')) \ + or (isinstance(model, list) and model[0].startswith('damo/')) \ + or (isinstance(model, str) and osp.exists(model)): + # TODO @wenmeng.zwm add support when model is a str of modelhub address + # read pipeline info from modelhub configuration file. + pipeline_name, default_model_repo = get_default_pipeline_info( + task) + else: + pipeline_name = get_pipeline_by_model_name(task, model) + else: + pipeline_name, default_model_repo = get_default_pipeline_info(task) + if model is None: model = default_model_repo - assert isinstance(model, (type(None), str, Model)), \ - f'model should be either None, str or Model, but got {type(model)}' + assert isinstance(model, (type(None), str, Model, list)), \ + f'model should be either None, str, List[str], Model, or List[Model], but got {type(model)}' cfg = ConfigDict(type=pipeline_name, model=model) @@ -134,3 +153,19 @@ def get_default_pipeline_info(task): else: pipeline_name, default_model = DEFAULT_MODEL_FOR_PIPELINE[task] return pipeline_name, default_model + + +def get_pipeline_by_model_name(task: str, model: Union[str, List[str]]): + """ Get pipeline name by task name and model name + + Args: + task (str): task name. + model (str| list[str]): model names + """ + if isinstance(model, str): + model_key = model + else: + model_key = '_'.join(model) + assert model_key in PIPELINES.modules[task], \ + f'pipeline for task {task} model {model_key} not found.' + return model_key diff --git a/modelscope/pipelines/util.py b/modelscope/pipelines/util.py index 92ad6af4..caef6b22 100644 --- a/modelscope/pipelines/util.py +++ b/modelscope/pipelines/util.py @@ -1,6 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. import os import os.path as osp +from typing import List, Union import json from maas_hub.file_download import model_file_download @@ -8,23 +9,38 @@ from maas_hub.file_download import model_file_download from modelscope.utils.constant import CONFIGFILE -def is_model_name(model): - if osp.exists(model): - if osp.exists(osp.join(model, CONFIGFILE)): - return True +def is_model_name(model: Union[str, List]): + """ whether model is a valid modelhub path + """ + + def is_model_name_impl(model): + if osp.exists(model): + if osp.exists(osp.join(model, CONFIGFILE)): + return True + else: + return False else: - return False + # try: + # cfg_file = model_file_download(model, CONFIGFILE) + # except Exception: + # cfg_file = None + # TODO @wenmeng.zwm use exception instead of + # following tricky logic + cfg_file = model_file_download(model, CONFIGFILE) + with open(cfg_file, 'r') as infile: + cfg = json.load(infile) + if 'Code' in cfg: + return False + else: + return True + + if isinstance(model, str): + return is_model_name_impl(model) else: - # try: - # cfg_file = model_file_download(model, CONFIGFILE) - # except Exception: - # cfg_file = None - # TODO @wenmeng.zwm use exception instead of - # following tricky logic - cfg_file = model_file_download(model, CONFIGFILE) - with open(cfg_file, 'r') as infile: - cfg = json.load(infile) - if 'Code' in cfg: - return False - else: - return True + results = [is_model_name_impl(m) for m in model] + all_true = all(results) + any_true = any(results) + if any_true and not all_true: + raise ValueError('some model are hub address, some are not') + + return all_true diff --git a/tests/pipelines/test_builder.py b/tests/pipelines/test_builder.py new file mode 100644 index 00000000..a0b15a32 --- /dev/null +++ b/tests/pipelines/test_builder.py @@ -0,0 +1,68 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. + +import unittest +from asyncio import Task +from typing import Any, Dict, List, Tuple, Union + +import numpy as np +import PIL + +from modelscope.models.base import Model +from modelscope.pipelines import Pipeline, pipeline +from modelscope.pipelines.builder import PIPELINES, add_default_pipeline_info +from modelscope.utils.constant import Tasks +from modelscope.utils.logger import get_logger +from modelscope.utils.registry import default_group + +logger = get_logger() + + +@PIPELINES.register_module( + group_key=Tasks.image_tagging, module_name='custom_single_model') +class CustomSingleModelPipeline(Pipeline): + + def __init__(self, + config_file: str = None, + model: List[Union[str, Model]] = None, + preprocessor=None, + **kwargs): + super().__init__(config_file, model, preprocessor, **kwargs) + assert isinstance(model, str), 'model is not str' + print(model) + + def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: + return super().postprocess(inputs) + + +@PIPELINES.register_module( + group_key=Tasks.image_tagging, module_name='model1_model2') +class CustomMultiModelPipeline(Pipeline): + + def __init__(self, + config_file: str = None, + model: List[Union[str, Model]] = None, + preprocessor=None, + **kwargs): + super().__init__(config_file, model, preprocessor, **kwargs) + assert isinstance(model, list), 'model is not list' + for m in model: + assert isinstance(m, str), 'submodel is not str' + print(m) + + def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: + return super().postprocess(inputs) + + +class PipelineInterfaceTest(unittest.TestCase): + + def test_single_model(self): + pipe = pipeline(Tasks.image_tagging, model='custom_single_model') + assert isinstance(pipe, CustomSingleModelPipeline) + + def test_multi_model(self): + pipe = pipeline(Tasks.image_tagging, model=['model1', 'model2']) + assert isinstance(pipe, CustomMultiModelPipeline) + + +if __name__ == '__main__': + unittest.main()