| @@ -0,0 +1,7 @@ | |||||
| #sudo docker run --name zwm_maas -v /home/wenmeng.zwm/workspace:/home/wenmeng.zwm/workspace --net host -ti reg.docker.alibaba-inc.com/pai-dlc/tensorflow-training:2.3-gpu-py36-cu101-ubuntu18.04 bash | |||||
| #sudo docker run --name zwm_maas_pytorch -v /home/wenmeng.zwm/workspace:/home/wenmeng.zwm/workspace --net host -ti reg.docker.alibaba-inc.com/pai-dlc/pytorch-training:1.10PAI-gpu-py36-cu113-ubuntu18.04 bash | |||||
| CONTAINER_NAME=modelscope-dev | |||||
| IMAGE_NAME=registry.cn-shanghai.aliyuncs.com/modelscope/modelscope | |||||
| IMAGE_VERSION=v0.1.1-16-g62856fa-devel | |||||
| MOUNT_DIR=/home/wenmeng.zwm/workspace | |||||
| sudo docker run --name $CONTAINER_NAME -v $MOUNT_DIR:$MOUNT_DIR --net host -ti ${IMAGE_NAME}:${IMAGE_VERSION} bash | |||||
| @@ -1,3 +1,4 @@ | |||||
| *.png filter=lfs diff=lfs merge=lfs -text | *.png filter=lfs diff=lfs merge=lfs -text | ||||
| *.jpg filter=lfs diff=lfs merge=lfs -text | *.jpg filter=lfs diff=lfs merge=lfs -text | ||||
| *.mp4 filter=lfs diff=lfs merge=lfs -text | *.mp4 filter=lfs diff=lfs merge=lfs -text | ||||
| *.wav filter=lfs diff=lfs merge=lfs -text | |||||
| @@ -124,7 +124,3 @@ replace.sh | |||||
| # Pytorch | # Pytorch | ||||
| *.pth | *.pth | ||||
| # audio | |||||
| *.wav | |||||
| @@ -0,0 +1,3 @@ | |||||
| version https://git-lfs.github.com/spec/v1 | |||||
| oid sha256:a72a7b8d1e8be6ebaa09aeee0d71472569bc62cc4872ecfdbd1651bb3d03eaba | |||||
| size 69110 | |||||
| @@ -0,0 +1,3 @@ | |||||
| version https://git-lfs.github.com/spec/v1 | |||||
| oid sha256:c6b1671bcfa872278c99490cd1acb08297b8df4dc78f268e4b6a582b4364e4a1 | |||||
| size 297684 | |||||
| @@ -30,7 +30,8 @@ RUN apt-get update &&\ | |||||
| zip \ | zip \ | ||||
| zlib1g-dev \ | zlib1g-dev \ | ||||
| unzip \ | unzip \ | ||||
| pkg-config | |||||
| pkg-config \ | |||||
| libsndfile1 | |||||
| # install modelscope and its python env | # install modelscope and its python env | ||||
| WORKDIR /opt/modelscope | WORKDIR /opt/modelscope | ||||
| @@ -13,6 +13,7 @@ ModelScope doc | |||||
| quick_start.md | quick_start.md | ||||
| develop.md | develop.md | ||||
| faq.md | |||||
| .. toctree:: | .. toctree:: | ||||
| :maxdepth: 2 | :maxdepth: 2 | ||||
| @@ -20,6 +21,8 @@ ModelScope doc | |||||
| tutorials/index | tutorials/index | ||||
| .. toctree:: | .. toctree:: | ||||
| :maxdepth: 2 | :maxdepth: 2 | ||||
| :caption: Changelog | :caption: Changelog | ||||
| @@ -1,72 +1,55 @@ | |||||
| # 快速开始 | # 快速开始 | ||||
| ModelScope Library目前支持tensorflow,pytorch深度学习框架进行模型训练、推理, 在Python 3.7+, Pytorch 1.8+, Tensorflow1.15+,Tensorflow 2.6上测试可运行。 | |||||
| 注: 当前(630)版本仅支持python3.7 以及linux环境,其他环境(mac,windows等)支持预计730完成。 | |||||
| ## python环境配置 | ## python环境配置 | ||||
| 首先,参考[文档](https://docs.anaconda.com/anaconda/install/) 安装配置Anaconda环境 | 首先,参考[文档](https://docs.anaconda.com/anaconda/install/) 安装配置Anaconda环境 | ||||
| 安装完成后,执行如下命令为modelscope library创建对应的python环境。 | 安装完成后,执行如下命令为modelscope library创建对应的python环境。 | ||||
| ```shell | ```shell | ||||
| conda create -n modelscope python=3.6 | |||||
| conda create -n modelscope python=3.7 | |||||
| conda activate modelscope | conda activate modelscope | ||||
| ``` | ``` | ||||
| 检查python和pip命令是否切换到conda环境下。 | |||||
| ## 安装深度学习框架 | |||||
| * 安装pytorch[参考链接](https://pytorch.org/get-started/locally/) | |||||
| ```shell | ```shell | ||||
| which python | |||||
| # ~/workspace/anaconda3/envs/modelscope/bin/python | |||||
| which pip | |||||
| # ~/workspace/anaconda3/envs/modelscope/bin/pip | |||||
| pip install torch torchvision | |||||
| ``` | ``` | ||||
| 注: 本项目只支持`python3`环境,请勿使用python2环境。 | |||||
| ## 第三方依赖安装 | |||||
| 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) | |||||
| 部分第三方依赖库需要提前安装numpy | |||||
| ``` | |||||
| pip install numpy | |||||
| * 安装Tensorflow[参考链接](https://www.tensorflow.org/install/pip) | |||||
| ```shell | |||||
| pip install --upgrade tensorflow | |||||
| ``` | ``` | ||||
| ## ModelScope library 安装 | ## ModelScope library 安装 | ||||
| 注: 如果在安装过程中遇到错误,请前往[常见问题](faq.md)查找解决方案。 | 注: 如果在安装过程中遇到错误,请前往[常见问题](faq.md)查找解决方案。 | ||||
| ### pip安装 | ### pip安装 | ||||
| 执行如下命令: | |||||
| ```shell | ```shell | ||||
| pip install -r http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release/maas/modelscope.txt | |||||
| pip install model_scope[all] -f https://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/release/maas/repo.html | |||||
| ``` | ``` | ||||
| 安装成功后,可以执行如下命令进行验证安装是否正确 | |||||
| ```shell | |||||
| 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'))" | |||||
| ``` | |||||
| ### 使用源码安装 | ### 使用源码安装 | ||||
| 适合本地开发调试使用,修改源码后可以直接执行 | 适合本地开发调试使用,修改源码后可以直接执行 | ||||
| 下载源码可以直接clone代码到本地 | |||||
| ```shell | ```shell | ||||
| git clone git@gitlab.alibaba-inc.com:Ali-MaaS/MaaS-lib.git modelscope | git clone git@gitlab.alibaba-inc.com:Ali-MaaS/MaaS-lib.git modelscope | ||||
| git fetch origin master | git fetch origin master | ||||
| git checkout master | git checkout master | ||||
| cd modelscope | cd modelscope | ||||
| #安装依赖 | |||||
| ``` | |||||
| 安装依赖并设置PYTHONPATH | |||||
| ```shell | |||||
| pip install -r requirements.txt | pip install -r requirements.txt | ||||
| # 设置PYTHONPATH | |||||
| export PYTHONPATH=`pwd` | export PYTHONPATH=`pwd` | ||||
| ``` | ``` | ||||
| ### 安装验证 | |||||
| 安装成功后,可以执行如下命令进行验证安装是否正确 | 安装成功后,可以执行如下命令进行验证安装是否正确 | ||||
| ```shell | ```shell | ||||
| 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'))" | |||||
| python -c "from modelscope.pipelines import pipeline;print(pipeline('word-segmentation')('今天天气不错,适合 出去游玩'))" | |||||
| {'output': '今天 天气 不错 , 适合 出去 游玩'} | |||||
| ``` | ``` | ||||
| ## 推理 | |||||
| pipeline函数提供了简洁的推理接口,相关介绍和示例请参考[pipeline使用教程](tutorials/pipeline.md) | |||||
| ## 训练 | ## 训练 | ||||
| @@ -75,46 +58,3 @@ to be done | |||||
| ## 评估 | ## 评估 | ||||
| to be done | to be done | ||||
| ## 推理 | |||||
| pipeline函数提供了简洁的推理接口,示例如下, 更多pipeline介绍和示例请参考[pipeline使用教程](tutorials/pipeline.md) | |||||
| ```python | |||||
| import cv2 | |||||
| import os.path as osp | |||||
| from modelscope.pipelines import pipeline | |||||
| from modelscope.utils.constant import Tasks | |||||
| # 根据任务名创建pipeline | |||||
| img_matting = pipeline(Tasks.image_matting, model='damo/image-matting-person') | |||||
| # 直接提供图像文件的url作为pipeline推理的输入 | |||||
| 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")}') | |||||
| ``` | |||||
| 此外,pipeline接口也能接收Dataset作为输入,上面的代码同样可以实现为 | |||||
| ```python | |||||
| import cv2 | |||||
| import os.path as osp | |||||
| from modelscope.pipelines import pipeline | |||||
| from modelscope.utils.constant import Tasks | |||||
| from modelscope.msdatasets import MsDataset | |||||
| # 使用图像url构建MsDataset,此处也可通过 input_location = '/dir/to/images' 来使用本地文件夹 | |||||
| input_location = [ | |||||
| 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png' | |||||
| ] | |||||
| dataset = MsDataset.load(input_location, target='image') | |||||
| img_matting = pipeline(Tasks.image_matting, model='damo/image-matting-person') | |||||
| # 输入为MsDataset时,输出的结果为迭代器 | |||||
| result = img_matting(dataset) | |||||
| cv2.imwrite('result.png', next(result)['output_png']) | |||||
| print(f'Output written to {osp.abspath("result.png")}') | |||||
| ``` | |||||
| @@ -1,84 +1,62 @@ | |||||
| # Pipeline使用教程 | # Pipeline使用教程 | ||||
| 本文将简单介绍如何使用`pipeline`函数加载模型进行推理。`pipeline`函数支持按照任务类型、模型名称从模型仓库 | |||||
| 拉取模型进行进行推理,当前支持的任务有 | |||||
| * 人像抠图 (image-matting) | |||||
| * 基于bert的语义情感分析 (bert-sentiment-analysis) | |||||
| 本文将从如下方面进行讲解如何使用Pipeline模块: | |||||
| 本文简单介绍如何使用`pipeline`函数加载模型进行推理。`pipeline`函数支持按照任务类型、模型名称从模型仓库拉取模型进行进行推理,包含以下几个方面: | |||||
| * 使用pipeline()函数进行推理 | * 使用pipeline()函数进行推理 | ||||
| * 指定特定预处理、特定模型进行推理 | * 指定特定预处理、特定模型进行推理 | ||||
| * 不同场景推理任务示例 | * 不同场景推理任务示例 | ||||
| ## 环境准备 | ## 环境准备 | ||||
| 详细步骤可以参考 [快速开始](../quick_start.md) | 详细步骤可以参考 [快速开始](../quick_start.md) | ||||
| ## Pipeline基本用法 | ## Pipeline基本用法 | ||||
| 下面以中文分词任务为例,说明pipeline函数的基本用法 | |||||
| 1. pipeline函数支持指定特定任务名称,加载任务默认模型,创建对应Pipeline对象 | |||||
| 1. pipeline函数支持指定特定任务名称,加载任务默认模型,创建对应pipeline对象 | |||||
| 执行如下python代码 | 执行如下python代码 | ||||
| ```python | ```python | ||||
| >>> from modelscope.pipelines import pipeline | |||||
| >>> img_matting = pipeline(task='image-matting', model='damo/image-matting-person') | |||||
| from modelscope.pipelines import pipeline | |||||
| word_segmentation = pipeline('word-segmentation') | |||||
| ``` | ``` | ||||
| 2. 传入单张图像url进行处理 | |||||
| 2. 输入文本 | |||||
| ``` python | ``` python | ||||
| >>> import cv2 | |||||
| >>> 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']) | |||||
| >>> import os.path as osp | |||||
| >>> print(f'result file path is {osp.abspath("result.png")}') | |||||
| input = '今天天气不错,适合出去游玩' | |||||
| print(word_segmentation(input)) | |||||
| {'output': '今天 天气 不错 , 适合 出去 游玩'} | |||||
| ``` | ``` | ||||
| pipeline对象也支持传入一个列表输入,返回对应输出列表,每个元素对应输入样本的返回结果 | |||||
| ```python | |||||
| >>> results = img_matting( | |||||
| [ | |||||
| 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png', | |||||
| 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png', | |||||
| 'http://pai-vision-data-hz.oss-cn-zhangjiakou.aliyuncs.com/data/test/maas/image_matting/test.png', | |||||
| ]) | |||||
| ``` | |||||
| 3. 输入多条样本 | |||||
| pipeline对象也支持传入多个样本列表输入,返回对应输出列表,每个元素对应输入样本的返回结果 | |||||
| 如果pipeline对应有一些后处理参数,也支持通过调用时候传入. | |||||
| ```python | ```python | ||||
| >>> pipe = pipeline(task_name) | |||||
| >>> result = pipe(input, post_process_args) | |||||
| inputs = ['今天天气不错,适合出去游玩','这本书很好,建议你看看'] | |||||
| print(word_segmentation(inputs)) | |||||
| [{'output': '今天 天气 不错 , 适合 出去 游玩'}, {'output': '这 本 书 很 好 , 建议 你 看看'}] | |||||
| ``` | ``` | ||||
| ## 指定预处理、模型进行推理 | ## 指定预处理、模型进行推理 | ||||
| pipeline函数支持传入实例化的预处理对象、模型对象,从而支持用户在推理过程中定制化预处理、模型。 | pipeline函数支持传入实例化的预处理对象、模型对象,从而支持用户在推理过程中定制化预处理、模型。 | ||||
| 下面以文本情感分类为例进行介绍。 | |||||
| 由于demo模型为EasyNLP提供的模型,首先,安装EasyNLP | |||||
| ```shell | |||||
| pip install https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/package/whl/easynlp-0.0.4-py2.py3-none-any.whl | |||||
| ``` | |||||
| 下载模型文件 | |||||
| ```shell | |||||
| wget https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/easynlp_modelzoo/alibaba-pai/bert-base-sst2.zip && unzip bert-base-sst2.zip | |||||
| ``` | |||||
| 创建tokenizer和模型 | |||||
| 1. 首先,创建预处理方法和模型 | |||||
| ```python | ```python | ||||
| >>> 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) | |||||
| from modelscope.models import Model | |||||
| from modelscope.preprocessors import TokenClassifcationPreprocessor | |||||
| model = Model.from_pretrained('damo/nlp_structbert_word-segmentation_chinese-base') | |||||
| tokenizer = TokenClassifcationPreprocessor(model.model_dir) | |||||
| ``` | ``` | ||||
| 使用tokenizer和模型对象创建pipeline | |||||
| 2. 使用tokenizer和模型对象创建pipeline | |||||
| ```python | ```python | ||||
| >>> from modelscope.pipelines import pipeline | |||||
| >>> semantic_cls = pipeline('text-classification', model=model, preprocessor=tokenizer) | |||||
| >>> semantic_cls("Hello world!") | |||||
| from modelscope.pipelines import pipeline | |||||
| word_seg = pipeline('word-segmentation', model=model, preprocessor=tokenizer) | |||||
| input = '今天天气不错,适合出去游玩' | |||||
| print(word_seg(input)) | |||||
| {'output': '今天 天气 不错 , 适合 出去 游玩'} | |||||
| ``` | ``` | ||||
| ## 不同场景任务推理示例 | ## 不同场景任务推理示例 | ||||
| 人像抠图、语义分类建上述两个例子。 其他例子未来添加。 | |||||
| 下面以一个图像任务:人像抠图('image-matting')为例,进一步说明pipeline的用法 | |||||
| ```python | |||||
| import cv2 | |||||
| import os.path as osp | |||||
| from modelscope.pipelines import pipeline | |||||
| img_matting = pipeline('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']) | |||||
| ``` | |||||
| @@ -1,6 +1,8 @@ | |||||
| import os | import os | ||||
| import pickle | import pickle | ||||
| import shutil | |||||
| import subprocess | import subprocess | ||||
| from collections import defaultdict | |||||
| from http.cookiejar import CookieJar | from http.cookiejar import CookieJar | ||||
| from os.path import expanduser | from os.path import expanduser | ||||
| from typing import List, Optional, Tuple, Union | from typing import List, Optional, Tuple, Union | ||||
| @@ -8,8 +10,11 @@ from typing import List, Optional, Tuple, Union | |||||
| import requests | import requests | ||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from ..msdatasets.config import DOWNLOADED_DATASETS_PATH, HUB_DATASET_ENDPOINT | |||||
| from ..utils.constant import DownloadMode | |||||
| from .constants import MODELSCOPE_URL_SCHEME | from .constants import MODELSCOPE_URL_SCHEME | ||||
| from .errors import InvalidParameter, NotExistError, is_ok, raise_on_error | |||||
| from .errors import (InvalidParameter, NotExistError, datahub_raise_on_error, | |||||
| is_ok, raise_on_error) | |||||
| from .utils.utils import (get_endpoint, get_gitlab_domain, | from .utils.utils import (get_endpoint, get_gitlab_domain, | ||||
| model_id_to_group_owner_name) | model_id_to_group_owner_name) | ||||
| @@ -18,8 +23,9 @@ logger = get_logger() | |||||
| class HubApi: | class HubApi: | ||||
| def __init__(self, endpoint=None): | |||||
| def __init__(self, endpoint=None, dataset_endpoint=None): | |||||
| self.endpoint = endpoint if endpoint is not None else get_endpoint() | self.endpoint = endpoint if endpoint is not None else get_endpoint() | ||||
| self.dataset_endpoint = dataset_endpoint if dataset_endpoint is not None else HUB_DATASET_ENDPOINT | |||||
| def login( | def login( | ||||
| self, | self, | ||||
| @@ -241,6 +247,70 @@ class HubApi: | |||||
| files.append(file) | files.append(file) | ||||
| return files | return files | ||||
| def list_datasets(self): | |||||
| path = f'{self.dataset_endpoint}/api/v1/datasets' | |||||
| headers = None | |||||
| params = {} | |||||
| r = requests.get(path, params=params, headers=headers) | |||||
| r.raise_for_status() | |||||
| dataset_list = r.json()['Data'] | |||||
| return [x['Name'] for x in dataset_list] | |||||
| def fetch_dataset_scripts(self, | |||||
| dataset_name: str, | |||||
| namespace: str, | |||||
| download_mode: Optional[DownloadMode], | |||||
| version: Optional[str] = 'master'): | |||||
| if namespace is None: | |||||
| raise ValueError( | |||||
| f'Dataset from Hubs.modelscope should have a valid "namespace", but get {namespace}' | |||||
| ) | |||||
| version = version or 'master' | |||||
| cache_dir = os.path.join(DOWNLOADED_DATASETS_PATH, dataset_name, | |||||
| namespace, version) | |||||
| download_mode = DownloadMode(download_mode | |||||
| or DownloadMode.REUSE_DATASET_IF_EXISTS) | |||||
| if download_mode == DownloadMode.FORCE_REDOWNLOAD and os.path.exists( | |||||
| cache_dir): | |||||
| shutil.rmtree(cache_dir) | |||||
| os.makedirs(cache_dir, exist_ok=True) | |||||
| datahub_url = f'{self.dataset_endpoint}/api/v1/datasets/{namespace}/{dataset_name}' | |||||
| r = requests.get(datahub_url) | |||||
| resp = r.json() | |||||
| datahub_raise_on_error(datahub_url, resp) | |||||
| dataset_id = resp['Data']['Id'] | |||||
| datahub_url = f'{self.dataset_endpoint}/api/v1/datasets/{dataset_id}/repo/tree?Revision={version}' | |||||
| r = requests.get(datahub_url) | |||||
| resp = r.json() | |||||
| datahub_raise_on_error(datahub_url, resp) | |||||
| file_list = resp['Data'] | |||||
| if file_list is None: | |||||
| raise NotExistError( | |||||
| f'The modelscope dataset [dataset_name = {dataset_name}, namespace = {namespace}, ' | |||||
| f'version = {version}] dose not exist') | |||||
| file_list = file_list['Files'] | |||||
| local_paths = defaultdict(list) | |||||
| for file_info in file_list: | |||||
| file_path = file_info['Path'] | |||||
| if file_path.endswith('.py'): | |||||
| datahub_url = f'{self.dataset_endpoint}/api/v1/datasets/{dataset_id}/repo/files?' \ | |||||
| f'Revision={version}&Path={file_path}' | |||||
| r = requests.get(datahub_url) | |||||
| r.raise_for_status() | |||||
| content = r.json()['Data']['Content'] | |||||
| local_path = os.path.join(cache_dir, file_path) | |||||
| if os.path.exists(local_path): | |||||
| logger.warning( | |||||
| f"Reusing dataset {dataset_name}'s python file ({local_path})" | |||||
| ) | |||||
| local_paths['py'].append(local_path) | |||||
| continue | |||||
| with open(local_path, 'w') as f: | |||||
| f.writelines(content) | |||||
| local_paths['py'].append(local_path) | |||||
| return local_paths | |||||
| class ModelScopeConfig: | class ModelScopeConfig: | ||||
| path_credential = expanduser('~/.modelscope/credentials') | path_credential = expanduser('~/.modelscope/credentials') | ||||
| @@ -1,6 +1,8 @@ | |||||
| MODELSCOPE_URL_SCHEME = 'http://' | MODELSCOPE_URL_SCHEME = 'http://' | ||||
| DEFAULT_MODELSCOPE_DOMAIN = '47.94.223.21:31090' | |||||
| DEFAULT_MODELSCOPE_IP = '47.94.223.21' | |||||
| DEFAULT_MODELSCOPE_DOMAIN = DEFAULT_MODELSCOPE_IP + ':31090' | |||||
| DEFAULT_MODELSCOPE_GITLAB_DOMAIN = '101.201.119.157:31102' | DEFAULT_MODELSCOPE_GITLAB_DOMAIN = '101.201.119.157:31102' | ||||
| DEFAULT_MODELSCOPE_DATA_ENDPOINT = MODELSCOPE_URL_SCHEME + DEFAULT_MODELSCOPE_IP + ':31752' | |||||
| DEFAULT_MODELSCOPE_GROUP = 'damo' | DEFAULT_MODELSCOPE_GROUP = 'damo' | ||||
| MODEL_ID_SEPARATOR = '/' | MODEL_ID_SEPARATOR = '/' | ||||
| @@ -1,9 +1,7 @@ | |||||
| import hashlib | import hashlib | ||||
| import logging | |||||
| import os | import os | ||||
| import pickle | import pickle | ||||
| import tempfile | import tempfile | ||||
| import time | |||||
| from shutil import move, rmtree | from shutil import move, rmtree | ||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| @@ -1,15 +1,30 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | # Copyright (c) Alibaba, Inc. and its affiliates. | ||||
| from .audio.ans.frcrn import FRCRNModel | |||||
| from .audio.kws import GenericKeyWordSpotting | |||||
| from .audio.tts.am import SambertNetHifi16k | |||||
| from .audio.tts.vocoder import Hifigan16k | |||||
| from .base import Model | from .base import Model | ||||
| from .builder import MODELS, build_model | from .builder import MODELS, build_model | ||||
| from .multi_modal import OfaForImageCaptioning | |||||
| from .nlp import (BertForMaskedLM, BertForSequenceClassification, SbertForNLI, | |||||
| SbertForSentenceSimilarity, SbertForSentimentClassification, | |||||
| SbertForTokenClassification, SbertForZeroShotClassification, | |||||
| SpaceForDialogIntent, SpaceForDialogModeling, | |||||
| SpaceForDialogStateTracking, StructBertForMaskedLM, | |||||
| VecoForMaskedLM) | |||||
| try: | |||||
| from .audio.tts.am import SambertNetHifi16k | |||||
| from .audio.tts.vocoder import Hifigan16k | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'tensorflow'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| try: | |||||
| from .audio.kws import GenericKeyWordSpotting | |||||
| from .multi_modal import OfaForImageCaptioning | |||||
| from .nlp import (BertForMaskedLM, BertForSequenceClassification, | |||||
| SbertForNLI, SbertForSentenceSimilarity, | |||||
| SbertForSentimentClassification, | |||||
| SbertForTokenClassification, | |||||
| SbertForZeroShotClassification, SpaceForDialogIntent, | |||||
| SpaceForDialogModeling, SpaceForDialogStateTracking, | |||||
| StructBertForMaskedLM, VecoForMaskedLM) | |||||
| from .audio.ans.frcrn import FRCRNModel | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'pytorch'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| @@ -108,7 +108,11 @@ class CLIPForMultiModalEmbedding(Model): | |||||
| return text_ids_tensor, text_mask_tensor | return text_ids_tensor, text_mask_tensor | ||||
| def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: | def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: | ||||
| output = {'img_embedding': None, 'text_embedding': None} | |||||
| from modelscope.pipelines.outputs import OutputKeys | |||||
| output = { | |||||
| OutputKeys.IMG_EMBEDDING: None, | |||||
| OutputKeys.TEXT_EMBEDDING: None | |||||
| } | |||||
| if 'img' in input and input['img'] is not None: | if 'img' in input and input['img'] is not None: | ||||
| input_img = input['img'] | input_img = input['img'] | ||||
| if isinstance(input_img, Image.Image): | if isinstance(input_img, Image.Image): | ||||
| @@ -130,7 +134,8 @@ class CLIPForMultiModalEmbedding(Model): | |||||
| img_embedding = self.clip_model( | img_embedding = self.clip_model( | ||||
| input_data=img_tensor, input_type='img') | input_data=img_tensor, input_type='img') | ||||
| output['img_embedding'] = img_embedding.data.cpu().numpy() | |||||
| from modelscope.pipelines.outputs import OutputKeys | |||||
| output[OutputKeys.IMG_EMBEDDING] = img_embedding.data.cpu().numpy() | |||||
| if 'text' in input and input['text'] is not None: | if 'text' in input and input['text'] is not None: | ||||
| text_str = input['text'] | text_str = input['text'] | ||||
| @@ -76,9 +76,10 @@ class OfaForImageCaptioning(Model): | |||||
| input = fairseq.utils.move_to_cuda(input, device=self._device) | input = fairseq.utils.move_to_cuda(input, device=self._device) | ||||
| results, _ = self.eval_caption(self.task, self.generator, self.models, | results, _ = self.eval_caption(self.task, self.generator, self.models, | ||||
| input) | input) | ||||
| from ...pipelines.outputs import OutputKeys | |||||
| return { | return { | ||||
| 'image_id': results[0]['image_id'], | 'image_id': results[0]['image_id'], | ||||
| 'caption': results[0]['caption'] | |||||
| OutputKeys.CAPTION: results[0][OutputKeys.CAPTION] | |||||
| } | } | ||||
| def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | ||||
| @@ -2,6 +2,8 @@ import os | |||||
| from pathlib import Path | from pathlib import Path | ||||
| # Cache location | # Cache location | ||||
| from modelscope.hub.constants import DEFAULT_MODELSCOPE_DATA_ENDPOINT | |||||
| DEFAULT_CACHE_HOME = '~/.cache' | DEFAULT_CACHE_HOME = '~/.cache' | ||||
| CACHE_HOME = os.getenv('CACHE_HOME', DEFAULT_CACHE_HOME) | CACHE_HOME = os.getenv('CACHE_HOME', DEFAULT_CACHE_HOME) | ||||
| DEFAULT_MS_CACHE_HOME = os.path.join(CACHE_HOME, 'modelscope/hub') | DEFAULT_MS_CACHE_HOME = os.path.join(CACHE_HOME, 'modelscope/hub') | ||||
| @@ -18,5 +20,5 @@ DEFAULT_DOWNLOADED_DATASETS_PATH = os.path.join(MS_DATASETS_CACHE, | |||||
| DOWNLOADED_DATASETS_PATH = Path( | DOWNLOADED_DATASETS_PATH = Path( | ||||
| os.getenv('DOWNLOADED_DATASETS_PATH', DEFAULT_DOWNLOADED_DATASETS_PATH)) | os.getenv('DOWNLOADED_DATASETS_PATH', DEFAULT_DOWNLOADED_DATASETS_PATH)) | ||||
| MS_HUB_ENDPOINT = os.environ.get('MS_HUB_ENDPOINT', | |||||
| 'http://47.94.223.21:31752') | |||||
| HUB_DATASET_ENDPOINT = os.environ.get('HUB_DATASET_ENDPOINT', | |||||
| DEFAULT_MODELSCOPE_DATA_ENDPOINT) | |||||
| @@ -11,7 +11,6 @@ from datasets.utils.file_utils import (is_relative_path, | |||||
| relative_to_absolute_path) | relative_to_absolute_path) | ||||
| from modelscope.msdatasets.config import MS_DATASETS_CACHE | from modelscope.msdatasets.config import MS_DATASETS_CACHE | ||||
| from modelscope.msdatasets.utils.ms_api import MsApi | |||||
| from modelscope.utils.constant import DownloadMode, Hubs | from modelscope.utils.constant import DownloadMode, Hubs | ||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| @@ -146,8 +145,9 @@ class MsDataset: | |||||
| use_hf = True | use_hf = True | ||||
| elif is_relative_path(dataset_name) and dataset_name.count( | elif is_relative_path(dataset_name) and dataset_name.count( | ||||
| '/') == 0: | '/') == 0: | ||||
| ms_api = MsApi() | |||||
| dataset_scripts = ms_api.fetch_dataset_scripts( | |||||
| from modelscope.hub.api import HubApi | |||||
| api = HubApi() | |||||
| dataset_scripts = api.fetch_dataset_scripts( | |||||
| dataset_name, namespace, download_mode, version) | dataset_name, namespace, download_mode, version) | ||||
| if 'py' in dataset_scripts: # dataset copied from hf datasets | if 'py' in dataset_scripts: # dataset copied from hf datasets | ||||
| dataset_name = dataset_scripts['py'][0] | dataset_name = dataset_scripts['py'][0] | ||||
| @@ -1,84 +0,0 @@ | |||||
| import os | |||||
| import shutil | |||||
| from collections import defaultdict | |||||
| from typing import Optional | |||||
| import requests | |||||
| from modelscope.hub.errors import NotExistError, datahub_raise_on_error | |||||
| from modelscope.msdatasets.config import (DOWNLOADED_DATASETS_PATH, | |||||
| MS_HUB_ENDPOINT) | |||||
| from modelscope.utils.constant import DownloadMode | |||||
| from modelscope.utils.logger import get_logger | |||||
| logger = get_logger() | |||||
| class MsApi: | |||||
| def __init__(self, endpoint=MS_HUB_ENDPOINT): | |||||
| self.endpoint = endpoint | |||||
| def list_datasets(self): | |||||
| path = f'{self.endpoint}/api/v1/datasets' | |||||
| headers = None | |||||
| params = {} | |||||
| r = requests.get(path, params=params, headers=headers) | |||||
| r.raise_for_status() | |||||
| dataset_list = r.json()['Data'] | |||||
| return [x['Name'] for x in dataset_list] | |||||
| def fetch_dataset_scripts(self, | |||||
| dataset_name: str, | |||||
| namespace: str, | |||||
| download_mode: Optional[DownloadMode], | |||||
| version: Optional[str] = 'master'): | |||||
| if namespace is None: | |||||
| raise ValueError( | |||||
| f'Dataset from Hubs.modelscope should have a valid "namespace", but get {namespace}' | |||||
| ) | |||||
| version = version or 'master' | |||||
| cache_dir = os.path.join(DOWNLOADED_DATASETS_PATH, dataset_name, | |||||
| namespace, version) | |||||
| download_mode = DownloadMode(download_mode | |||||
| or DownloadMode.REUSE_DATASET_IF_EXISTS) | |||||
| if download_mode == DownloadMode.FORCE_REDOWNLOAD and os.path.exists( | |||||
| cache_dir): | |||||
| shutil.rmtree(cache_dir) | |||||
| os.makedirs(cache_dir, exist_ok=True) | |||||
| datahub_url = f'{self.endpoint}/api/v1/datasets/{namespace}/{dataset_name}' | |||||
| r = requests.get(datahub_url) | |||||
| resp = r.json() | |||||
| datahub_raise_on_error(datahub_url, resp) | |||||
| dataset_id = resp['Data']['Id'] | |||||
| datahub_url = f'{self.endpoint}/api/v1/datasets/{dataset_id}/repo/tree?Revision={version}' | |||||
| r = requests.get(datahub_url) | |||||
| resp = r.json() | |||||
| datahub_raise_on_error(datahub_url, resp) | |||||
| file_list = resp['Data'] | |||||
| if file_list is None: | |||||
| raise NotExistError( | |||||
| f'The modelscope dataset [dataset_name = {dataset_name}, namespace = {namespace}, ' | |||||
| f'version = {version}] dose not exist') | |||||
| file_list = file_list['Files'] | |||||
| local_paths = defaultdict(list) | |||||
| for file_info in file_list: | |||||
| file_path = file_info['Path'] | |||||
| if file_path.endswith('.py'): | |||||
| datahub_url = f'{self.endpoint}/api/v1/datasets/{dataset_id}/repo/files?' \ | |||||
| f'Revision={version}&Path={file_path}' | |||||
| r = requests.get(datahub_url) | |||||
| r.raise_for_status() | |||||
| content = r.json()['Data']['Content'] | |||||
| local_path = os.path.join(cache_dir, file_path) | |||||
| if os.path.exists(local_path): | |||||
| logger.warning( | |||||
| f"Reusing dataset {dataset_name}'s python file ({local_path})" | |||||
| ) | |||||
| local_paths['py'].append(local_path) | |||||
| continue | |||||
| with open(local_path, 'w') as f: | |||||
| f.writelines(content) | |||||
| local_paths['py'].append(local_path) | |||||
| return local_paths | |||||
| @@ -1,3 +1,16 @@ | |||||
| from .kws_kwsbp_pipeline import * # noqa F403 | |||||
| from .linear_aec_pipeline import LinearAECPipeline | |||||
| from .text_to_speech_pipeline import * # noqa F403 | |||||
| try: | |||||
| from .kws_kwsbp_pipeline import * # noqa F403 | |||||
| from .linear_aec_pipeline import LinearAECPipeline | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'torch'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| try: | |||||
| from .text_to_speech_pipeline import * # noqa F403 | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'tensorflow'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| @@ -10,6 +10,7 @@ from modelscope.metainfo import Pipelines | |||||
| from modelscope.utils.constant import Tasks | from modelscope.utils.constant import Tasks | ||||
| from ..base import Input, Pipeline | from ..base import Input, Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| def audio_norm(x): | def audio_norm(x): | ||||
| @@ -108,10 +109,10 @@ class ANSPipeline(Pipeline): | |||||
| current_idx += stride | current_idx += stride | ||||
| else: | else: | ||||
| outputs = self.model(ndarray)['wav_l2'][0].cpu().numpy() | outputs = self.model(ndarray)['wav_l2'][0].cpu().numpy() | ||||
| return {'output_pcm': outputs[:nsamples]} | |||||
| return {OutputKeys.OUTPUT_PCM: outputs[:nsamples]} | |||||
| def postprocess(self, inputs: Dict[str, Any], **kwargs) -> Dict[str, Any]: | def postprocess(self, inputs: Dict[str, Any], **kwargs) -> Dict[str, Any]: | ||||
| if 'output_path' in kwargs.keys(): | if 'output_path' in kwargs.keys(): | ||||
| sf.write(kwargs['output_path'], inputs['output_pcm'], | |||||
| sf.write(kwargs['output_path'], inputs[OutputKeys.OUTPUT_PCM], | |||||
| self.SAMPLE_RATE) | self.SAMPLE_RATE) | ||||
| return inputs | return inputs | ||||
| @@ -5,6 +5,8 @@ import stat | |||||
| import subprocess | import subprocess | ||||
| from typing import Any, Dict, List | from typing import Any, Dict, List | ||||
| import json | |||||
| from modelscope.metainfo import Pipelines | from modelscope.metainfo import Pipelines | ||||
| from modelscope.models import Model | from modelscope.models import Model | ||||
| from modelscope.pipelines.base import Pipeline | from modelscope.pipelines.base import Pipeline | ||||
| @@ -39,6 +41,12 @@ class KeyWordSpottingKwsbpPipeline(Pipeline): | |||||
| self._preprocessor = preprocessor | self._preprocessor = preprocessor | ||||
| self._model = model | self._model = model | ||||
| self._keywords = None | |||||
| if 'keywords' in kwargs.keys(): | |||||
| self._keywords = kwargs['keywords'] | |||||
| print('self._keywords len: ', len(self._keywords)) | |||||
| print('self._keywords: ', self._keywords) | |||||
| def __call__(self, kws_type: str, wav_path: List[str]) -> Dict[str, Any]: | def __call__(self, kws_type: str, wav_path: List[str]) -> Dict[str, Any]: | ||||
| assert kws_type in ['wav', 'pos_testsets', 'neg_testsets', | assert kws_type in ['wav', 'pos_testsets', 'neg_testsets', | ||||
| @@ -197,6 +205,16 @@ class KeyWordSpottingKwsbpPipeline(Pipeline): | |||||
| return rst_dict | return rst_dict | ||||
| def _run_with_kwsbp(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | def _run_with_kwsbp(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | ||||
| opts: str = '' | |||||
| # setting customized keywords | |||||
| keywords_json = self._set_customized_keywords() | |||||
| if len(keywords_json) > 0: | |||||
| keywords_json_file = os.path.join(inputs['workspace'], | |||||
| 'keyword_custom.json') | |||||
| with open(keywords_json_file, 'w') as f: | |||||
| json.dump(keywords_json, f) | |||||
| opts = '--keyword-custom ' + keywords_json_file | |||||
| if inputs['kws_set'] == 'roc': | if inputs['kws_set'] == 'roc': | ||||
| inputs['keyword_grammar_path'] = os.path.join( | inputs['keyword_grammar_path'] = os.path.join( | ||||
| @@ -211,7 +229,7 @@ class KeyWordSpottingKwsbpPipeline(Pipeline): | |||||
| ' --sample-rate=' + inputs['sample_rate'] + \ | ' --sample-rate=' + inputs['sample_rate'] + \ | ||||
| ' --keyword-grammar=' + inputs['keyword_grammar_path'] + \ | ' --keyword-grammar=' + inputs['keyword_grammar_path'] + \ | ||||
| ' --wave-scp=' + os.path.join(inputs['pos_data_path'], 'wave.list') + \ | ' --wave-scp=' + os.path.join(inputs['pos_data_path'], 'wave.list') + \ | ||||
| ' --num-thread=1 > ' + dump_log_path + ' 2>&1' | |||||
| ' --num-thread=1 ' + opts + ' > ' + dump_log_path + ' 2>&1' | |||||
| os.system(kws_cmd) | os.system(kws_cmd) | ||||
| if inputs['kws_set'] in ['pos_testsets', 'roc']: | if inputs['kws_set'] in ['pos_testsets', 'roc']: | ||||
| @@ -236,7 +254,7 @@ class KeyWordSpottingKwsbpPipeline(Pipeline): | |||||
| ' --sample-rate=' + inputs['sample_rate'] + \ | ' --sample-rate=' + inputs['sample_rate'] + \ | ||||
| ' --keyword-grammar=' + inputs['keyword_grammar_path'] + \ | ' --keyword-grammar=' + inputs['keyword_grammar_path'] + \ | ||||
| ' --wave-scp=' + wav_list_path + \ | ' --wave-scp=' + wav_list_path + \ | ||||
| ' --num-thread=1 > ' + dump_log_path + ' 2>&1' | |||||
| ' --num-thread=1 ' + opts + ' > ' + dump_log_path + ' 2>&1' | |||||
| p = subprocess.Popen(kws_cmd, shell=True) | p = subprocess.Popen(kws_cmd, shell=True) | ||||
| process.append(p) | process.append(p) | ||||
| j += 1 | j += 1 | ||||
| @@ -268,7 +286,7 @@ class KeyWordSpottingKwsbpPipeline(Pipeline): | |||||
| ' --sample-rate=' + inputs['sample_rate'] + \ | ' --sample-rate=' + inputs['sample_rate'] + \ | ||||
| ' --keyword-grammar=' + inputs['keyword_grammar_path'] + \ | ' --keyword-grammar=' + inputs['keyword_grammar_path'] + \ | ||||
| ' --wave-scp=' + wav_list_path + \ | ' --wave-scp=' + wav_list_path + \ | ||||
| ' --num-thread=1 > ' + dump_log_path + ' 2>&1' | |||||
| ' --num-thread=1 ' + opts + ' > ' + dump_log_path + ' 2>&1' | |||||
| p = subprocess.Popen(kws_cmd, shell=True) | p = subprocess.Popen(kws_cmd, shell=True) | ||||
| process.append(p) | process.append(p) | ||||
| j += 1 | j += 1 | ||||
| @@ -447,3 +465,29 @@ class KeyWordSpottingKwsbpPipeline(Pipeline): | |||||
| threshold_cur += step | threshold_cur += step | ||||
| return output | return output | ||||
| def _set_customized_keywords(self) -> Dict[str, Any]: | |||||
| if self._keywords is not None: | |||||
| word_list_inputs = self._keywords | |||||
| word_list = [] | |||||
| for i in range(len(word_list_inputs)): | |||||
| key = word_list_inputs[i] | |||||
| new_item = {} | |||||
| if key.__contains__('keyword'): | |||||
| name = key['keyword'] | |||||
| new_name: str = '' | |||||
| for n in range(0, len(name), 1): | |||||
| new_name += name[n] | |||||
| new_name += ' ' | |||||
| new_name = new_name.strip() | |||||
| new_item['name'] = new_name | |||||
| if key.__contains__('threshold'): | |||||
| threshold1: float = key['threshold'] | |||||
| new_item['threshold1'] = threshold1 | |||||
| word_list.append(new_item) | |||||
| out = {'word_list': word_list} | |||||
| return out | |||||
| else: | |||||
| return '' | |||||
| @@ -12,6 +12,7 @@ from modelscope.preprocessors.audio import LinearAECAndFbank | |||||
| from modelscope.utils.constant import ModelFile, Tasks | from modelscope.utils.constant import ModelFile, Tasks | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| FEATURE_MVN = 'feature.DEY.mvn.txt' | FEATURE_MVN = 'feature.DEY.mvn.txt' | ||||
| @@ -120,7 +121,7 @@ class LinearAECPipeline(Pipeline): | |||||
| } | } | ||||
| """ | """ | ||||
| output_data = self._process(inputs['feature'], inputs['base']) | output_data = self._process(inputs['feature'], inputs['base']) | ||||
| return {'output_pcm': output_data} | |||||
| return {OutputKeys.OUTPUT_PCM: output_data} | |||||
| def postprocess(self, inputs: Dict[str, Any], **kwargs) -> Dict[str, Any]: | def postprocess(self, inputs: Dict[str, Any], **kwargs) -> Dict[str, Any]: | ||||
| r"""The post process. Will save audio to file, if the output_path is given. | r"""The post process. Will save audio to file, if the output_path is given. | ||||
| @@ -140,8 +141,8 @@ class LinearAECPipeline(Pipeline): | |||||
| """ | """ | ||||
| if 'output_path' in kwargs.keys(): | if 'output_path' in kwargs.keys(): | ||||
| wav.write(kwargs['output_path'], self.preprocessor.SAMPLE_RATE, | wav.write(kwargs['output_path'], self.preprocessor.SAMPLE_RATE, | ||||
| inputs['output_pcm'].astype(np.int16)) | |||||
| inputs['output_pcm'] = inputs['output_pcm'] / 32768.0 | |||||
| inputs[OutputKeys.OUTPUT_PCM].astype(np.int16)) | |||||
| inputs[OutputKeys.OUTPUT_PCM] = inputs[OutputKeys.OUTPUT_PCM] / 32768.0 | |||||
| return inputs | return inputs | ||||
| def _process(self, fbanks, mixture): | def _process(self, fbanks, mixture): | ||||
| @@ -1,5 +1,18 @@ | |||||
| from .action_recognition_pipeline import ActionRecognitionPipeline | |||||
| from .animal_recog_pipeline import AnimalRecogPipeline | |||||
| from .image_cartoon_pipeline import ImageCartoonPipeline | |||||
| from .image_matting_pipeline import ImageMattingPipeline | |||||
| from .ocr_detection_pipeline import OCRDetectionPipeline | |||||
| try: | |||||
| from .action_recognition_pipeline import ActionRecognitionPipeline | |||||
| from .animal_recog_pipeline import AnimalRecogPipeline | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'torch'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| try: | |||||
| from .image_cartoon_pipeline import ImageCartoonPipeline | |||||
| from .image_matting_pipeline import ImageMattingPipeline | |||||
| from .ocr_detection_pipeline import OCRDetectionPipeline | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'tensorflow'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| @@ -16,6 +16,7 @@ from modelscope.utils.constant import ModelFile, Tasks | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| logger = get_logger() | logger = get_logger() | ||||
| @@ -49,7 +50,7 @@ class ActionRecognitionPipeline(Pipeline): | |||||
| def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: | def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: | ||||
| pred = self.perform_inference(input['video_data']) | pred = self.perform_inference(input['video_data']) | ||||
| output_label = self.label_mapping[str(pred)] | output_label = self.label_mapping[str(pred)] | ||||
| return {'output_label': output_label} | |||||
| return {OutputKeys.LABELS: output_label} | |||||
| @torch.no_grad() | @torch.no_grad() | ||||
| def perform_inference(self, data, max_bsz=4): | def perform_inference(self, data, max_bsz=4): | ||||
| @@ -18,6 +18,7 @@ from modelscope.utils.constant import ModelFile, Tasks | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| logger = get_logger() | logger = get_logger() | ||||
| @@ -121,7 +122,9 @@ class AnimalRecogPipeline(Pipeline): | |||||
| label_mapping = f.readlines() | label_mapping = f.readlines() | ||||
| score = torch.max(inputs['outputs']) | score = torch.max(inputs['outputs']) | ||||
| inputs = { | inputs = { | ||||
| 'scores': score.item(), | |||||
| 'labels': label_mapping[inputs['outputs'].argmax()].split('\t')[1] | |||||
| OutputKeys.SCORES: | |||||
| score.item(), | |||||
| OutputKeys.LABELS: | |||||
| label_mapping[inputs['outputs'].argmax()].split('\t')[1] | |||||
| } | } | ||||
| return inputs | return inputs | ||||
| @@ -17,6 +17,7 @@ from modelscope.utils.constant import Tasks | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| if tf.__version__ >= '2.0': | if tf.__version__ >= '2.0': | ||||
| tf = tf.compat.v1 | tf = tf.compat.v1 | ||||
| @@ -94,7 +95,7 @@ class ImageCartoonPipeline(Pipeline): | |||||
| landmarks = self.detect_face(img) | landmarks = self.detect_face(img) | ||||
| if landmarks is None: | if landmarks is None: | ||||
| print('No face detected!') | print('No face detected!') | ||||
| return {'output_png': None} | |||||
| return {OutputKeys.OUTPUT_IMG: None} | |||||
| # background process | # background process | ||||
| pad_bg, pad_h, pad_w = padTo16x(img_brg) | pad_bg, pad_h, pad_w = padTo16x(img_brg) | ||||
| @@ -143,7 +144,7 @@ class ImageCartoonPipeline(Pipeline): | |||||
| res = cv2.resize(res, (ori_w, ori_h), interpolation=cv2.INTER_AREA) | res = cv2.resize(res, (ori_w, ori_h), interpolation=cv2.INTER_AREA) | ||||
| return {'output_png': res} | |||||
| return {OutputKeys.OUTPUT_IMG: res} | |||||
| def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | ||||
| return inputs | return inputs | ||||
| @@ -12,6 +12,7 @@ from modelscope.utils.constant import ModelFile, Tasks | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| logger = get_logger() | logger = get_logger() | ||||
| @@ -60,9 +61,9 @@ class ImageMattingPipeline(Pipeline): | |||||
| def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: | def forward(self, input: Dict[str, Any]) -> Dict[str, Any]: | ||||
| with self._session.as_default(): | with self._session.as_default(): | ||||
| feed_dict = {self.input_name: input['img']} | feed_dict = {self.input_name: input['img']} | ||||
| output_png = self._session.run(self.output, feed_dict=feed_dict) | |||||
| output_png = cv2.cvtColor(output_png, cv2.COLOR_RGBA2BGRA) | |||||
| return {'output_png': output_png} | |||||
| output_img = self._session.run(self.output, feed_dict=feed_dict) | |||||
| output_img = cv2.cvtColor(output_img, cv2.COLOR_RGBA2BGRA) | |||||
| return {OutputKeys.OUTPUT_IMG: output_img} | |||||
| def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | ||||
| return inputs | return inputs | ||||
| @@ -16,6 +16,7 @@ from modelscope.utils.constant import ModelFile, Tasks | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| from .ocr_utils import model_resnet_mutex_v4_linewithchar, ops, utils | from .ocr_utils import model_resnet_mutex_v4_linewithchar, ops, utils | ||||
| if tf.__version__ >= '2.0': | if tf.__version__ >= '2.0': | ||||
| @@ -174,5 +175,5 @@ class OCRDetectionPipeline(Pipeline): | |||||
| dt_nms = utils.nms_python(dt_n9) | dt_nms = utils.nms_python(dt_n9) | ||||
| dt_polygons = np.array([o[:8] for o in dt_nms]) | dt_polygons = np.array([o[:8] for o in dt_nms]) | ||||
| result = {'det_polygons': dt_polygons} | |||||
| result = {OutputKeys.POLYGONS: dt_polygons} | |||||
| return result | return result | ||||
| @@ -1,3 +1,9 @@ | |||||
| from .image_captioning_pipeline import ImageCaptionPipeline | |||||
| from .multi_modal_embedding_pipeline import MultiModalEmbeddingPipeline | |||||
| from .visual_question_answering_pipeline import VisualQuestionAnsweringPipeline | |||||
| try: | |||||
| from .image_captioning_pipeline import ImageCaptionPipeline | |||||
| from .multi_modal_embedding_pipeline import MultiModalEmbeddingPipeline | |||||
| from .visual_question_answering_pipeline import VisualQuestionAnsweringPipeline | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'torch'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| @@ -1,11 +1,17 @@ | |||||
| from .dialog_intent_prediction_pipeline import * # noqa F403 | |||||
| from .dialog_modeling_pipeline import * # noqa F403 | |||||
| from .dialog_state_tracking_pipeline import * # noqa F403 | |||||
| from .fill_mask_pipeline import * # noqa F403 | |||||
| from .nli_pipeline import * # noqa F403 | |||||
| from .sentence_similarity_pipeline import * # noqa F403 | |||||
| from .sentiment_classification_pipeline import * # noqa F403 | |||||
| from .sequence_classification_pipeline import * # noqa F403 | |||||
| from .text_generation_pipeline import * # noqa F403 | |||||
| from .word_segmentation_pipeline import * # noqa F403 | |||||
| from .zero_shot_classification_pipeline import * # noqa F403 | |||||
| try: | |||||
| from .dialog_intent_prediction_pipeline import * # noqa F403 | |||||
| from .dialog_modeling_pipeline import * # noqa F403 | |||||
| from .dialog_state_tracking_pipeline import * # noqa F403 | |||||
| from .fill_mask_pipeline import * # noqa F403 | |||||
| from .nli_pipeline import * # noqa F403 | |||||
| from .sentence_similarity_pipeline import * # noqa F403 | |||||
| from .sentiment_classification_pipeline import * # noqa F403 | |||||
| from .sequence_classification_pipeline import * # noqa F403 | |||||
| from .text_generation_pipeline import * # noqa F403 | |||||
| from .word_segmentation_pipeline import * # noqa F403 | |||||
| from .zero_shot_classification_pipeline import * # noqa F403 | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'torch'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| @@ -8,6 +8,7 @@ from ...preprocessors import DialogIntentPredictionPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['DialogIntentPredictionPipeline'] | __all__ = ['DialogIntentPredictionPipeline'] | ||||
| @@ -44,9 +45,9 @@ class DialogIntentPredictionPipeline(Pipeline): | |||||
| pos = np.where(pred == np.max(pred)) | pos = np.where(pred == np.max(pred)) | ||||
| result = { | result = { | ||||
| 'prediction': pred, | |||||
| 'label_pos': pos[0], | |||||
| 'label': self.categories[pos[0][0]] | |||||
| OutputKeys.PREDICTION: pred, | |||||
| OutputKeys.LABEL_POS: pos[0], | |||||
| OutputKeys.LABEL: self.categories[pos[0][0]] | |||||
| } | } | ||||
| return result | return result | ||||
| @@ -8,6 +8,7 @@ from ...preprocessors import DialogModelingPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Pipeline, Tensor | from ..base import Pipeline, Tensor | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['DialogModelingPipeline'] | __all__ = ['DialogModelingPipeline'] | ||||
| @@ -42,7 +43,6 @@ class DialogModelingPipeline(Pipeline): | |||||
| inputs['resp']) | inputs['resp']) | ||||
| assert len(sys_rsp) > 2 | assert len(sys_rsp) > 2 | ||||
| sys_rsp = sys_rsp[1:len(sys_rsp) - 1] | sys_rsp = sys_rsp[1:len(sys_rsp) - 1] | ||||
| inputs['response'] = sys_rsp | |||||
| inputs[OutputKeys.RESPONSE] = sys_rsp | |||||
| return inputs | return inputs | ||||
| @@ -11,6 +11,7 @@ from ...utils.config import Config | |||||
| from ...utils.constant import ModelFile, Tasks | from ...utils.constant import ModelFile, Tasks | ||||
| from ..base import Pipeline, Tensor | from ..base import Pipeline, Tensor | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['FillMaskPipeline'] | __all__ = ['FillMaskPipeline'] | ||||
| _type_map = {'veco': 'roberta', 'sbert': 'bert'} | _type_map = {'veco': 'roberta', 'sbert': 'bert'} | ||||
| @@ -108,4 +109,4 @@ class FillMaskPipeline(Pipeline): | |||||
| pred_string = rep_tokens(pred_string, self.rep_map[process_type]) | pred_string = rep_tokens(pred_string, self.rep_map[process_type]) | ||||
| pred_strings.append(pred_string) | pred_strings.append(pred_string) | ||||
| return {'text': pred_strings} | |||||
| return {OutputKeys.TEXT: pred_strings} | |||||
| @@ -11,6 +11,7 @@ from ...preprocessors import NLIPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Pipeline | from ..base import Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['NLIPipeline'] | __all__ = ['NLIPipeline'] | ||||
| @@ -69,4 +70,4 @@ class NLIPipeline(Pipeline): | |||||
| cls_names = [self.model.id2label[cid] for cid in cls_ids] | cls_names = [self.model.id2label[cid] for cid in cls_ids] | ||||
| return {'scores': probs, 'labels': cls_names} | |||||
| return {OutputKeys.SCORES: probs, OutputKeys.LABELS: cls_names} | |||||
| @@ -10,6 +10,7 @@ from ...preprocessors import SequenceClassificationPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Input, Pipeline | from ..base import Input, Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['SentenceSimilarityPipeline'] | __all__ = ['SentenceSimilarityPipeline'] | ||||
| @@ -69,4 +70,4 @@ class SentenceSimilarityPipeline(Pipeline): | |||||
| probs = probs[cls_ids].tolist() | probs = probs[cls_ids].tolist() | ||||
| cls_names = [self.model.id2label[cid] for cid in cls_ids] | cls_names = [self.model.id2label[cid] for cid in cls_ids] | ||||
| b = 0 | b = 0 | ||||
| return {'scores': probs[b], 'labels': cls_names[b]} | |||||
| return {OutputKeys.SCORES: probs[b], OutputKeys.LABELS: cls_names[b]} | |||||
| @@ -13,6 +13,7 @@ from ...preprocessors import SentimentClassificationPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Input, Pipeline | from ..base import Input, Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['SentimentClassificationPipeline'] | __all__ = ['SentimentClassificationPipeline'] | ||||
| @@ -73,5 +74,4 @@ class SentimentClassificationPipeline(Pipeline): | |||||
| probs = probs[cls_ids].tolist() | probs = probs[cls_ids].tolist() | ||||
| cls_names = [self.model.id2label[cid] for cid in cls_ids] | cls_names = [self.model.id2label[cid] for cid in cls_ids] | ||||
| return {'scores': probs, 'labels': cls_names} | |||||
| return {OutputKeys.SCORES: probs, OutputKeys.LABELS: cls_names} | |||||
| @@ -9,6 +9,7 @@ from modelscope.utils.constant import Tasks | |||||
| from ...models import Model | from ...models import Model | ||||
| from ..base import Input, Pipeline | from ..base import Input, Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['SequenceClassificationPipeline'] | __all__ = ['SequenceClassificationPipeline'] | ||||
| @@ -64,4 +65,4 @@ class SequenceClassificationPipeline(Pipeline): | |||||
| cls_names = [self.model.id2label[cid] for cid in cls_ids] | cls_names = [self.model.id2label[cid] for cid in cls_ids] | ||||
| return {'scores': probs, 'labels': cls_names} | |||||
| return {OutputKeys.SCORES: probs, OutputKeys.LABELS: cls_names} | |||||
| @@ -9,6 +9,7 @@ from ...preprocessors import TextGenerationPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Pipeline, Tensor | from ..base import Pipeline, Tensor | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['TextGenerationPipeline'] | __all__ = ['TextGenerationPipeline'] | ||||
| @@ -70,4 +71,4 @@ class TextGenerationPipeline(Pipeline): | |||||
| for _old, _new in replace_tokens_roberta: | for _old, _new in replace_tokens_roberta: | ||||
| pred_string = pred_string.replace(_old, _new) | pred_string = pred_string.replace(_old, _new) | ||||
| pred_string.strip() | pred_string.strip() | ||||
| return {'text': pred_string} | |||||
| return {OutputKeys.TEXT: pred_string} | |||||
| @@ -9,6 +9,7 @@ from ...preprocessors import TokenClassifcationPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Pipeline, Tensor | from ..base import Pipeline, Tensor | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['WordSegmentationPipeline'] | __all__ = ['WordSegmentationPipeline'] | ||||
| @@ -73,7 +74,4 @@ class WordSegmentationPipeline(Pipeline): | |||||
| if chunk: | if chunk: | ||||
| chunks.append(chunk) | chunks.append(chunk) | ||||
| seg_result = ' '.join(chunks) | seg_result = ' '.join(chunks) | ||||
| rst = { | |||||
| 'output': seg_result, | |||||
| } | |||||
| return rst | |||||
| return {OutputKeys.OUTPUT: seg_result} | |||||
| @@ -14,6 +14,7 @@ from ...preprocessors import ZeroShotClassificationPreprocessor | |||||
| from ...utils.constant import Tasks | from ...utils.constant import Tasks | ||||
| from ..base import Input, Pipeline | from ..base import Input, Pipeline | ||||
| from ..builder import PIPELINES | from ..builder import PIPELINES | ||||
| from ..outputs import OutputKeys | |||||
| __all__ = ['ZeroShotClassificationPipeline'] | __all__ = ['ZeroShotClassificationPipeline'] | ||||
| @@ -82,7 +83,7 @@ class ZeroShotClassificationPipeline(Pipeline): | |||||
| scores = softmax(logits, axis=-1) | scores = softmax(logits, axis=-1) | ||||
| reversed_index = list(reversed(scores.argsort())) | reversed_index = list(reversed(scores.argsort())) | ||||
| result = { | result = { | ||||
| 'labels': [candidate_labels[i] for i in reversed_index], | |||||
| 'scores': [scores[i].item() for i in reversed_index] | |||||
| OutputKeys.LABELS: [candidate_labels[i] for i in reversed_index], | |||||
| OutputKeys.SCORES: [scores[i].item() for i in reversed_index], | |||||
| } | } | ||||
| return result | return result | ||||
| @@ -2,54 +2,76 @@ | |||||
| from modelscope.utils.constant import Tasks | from modelscope.utils.constant import Tasks | ||||
| class OutputKeys(object): | |||||
| SCORES = 'scores' | |||||
| LABEL = 'label' | |||||
| LABELS = 'labels' | |||||
| LABEL_POS = 'label_pos' | |||||
| POSES = 'poses' | |||||
| CAPTION = 'caption' | |||||
| BOXES = 'boxes' | |||||
| TEXT = 'text' | |||||
| POLYGONS = 'polygons' | |||||
| OUTPUT = 'output' | |||||
| OUTPUT_IMG = 'output_img' | |||||
| OUTPUT_PCM = 'output_pcm' | |||||
| IMG_EMBEDDING = 'img_embedding' | |||||
| TEXT_EMBEDDING = 'text_embedding' | |||||
| RESPONSE = 'response' | |||||
| PREDICTION = 'prediction' | |||||
| TASK_OUTPUTS = { | TASK_OUTPUTS = { | ||||
| # ============ vision tasks =================== | # ============ vision tasks =================== | ||||
| # image classification result for single sample | # image classification result for single sample | ||||
| # { | # { | ||||
| # "labels": ["dog", "horse", "cow", "cat"], | |||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | # "scores": [0.9, 0.1, 0.05, 0.05] | ||||
| # "labels": ["dog", "horse", "cow", "cat"], | |||||
| # } | # } | ||||
| Tasks.image_classification: ['scores', 'labels'], | |||||
| Tasks.image_tagging: ['scores', 'labels'], | |||||
| Tasks.image_classification: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| Tasks.image_tagging: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| # object detection result for single sample | # object detection result for single sample | ||||
| # { | # { | ||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | |||||
| # "labels": ["dog", "horse", "cow", "cat"], | |||||
| # "boxes": [ | # "boxes": [ | ||||
| # [x1, y1, x2, y2], | # [x1, y1, x2, y2], | ||||
| # [x1, y1, x2, y2], | # [x1, y1, x2, y2], | ||||
| # [x1, y1, x2, y2], | # [x1, y1, x2, y2], | ||||
| # ], | # ], | ||||
| # "labels": ["dog", "horse", "cow", "cat"], | |||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | |||||
| # } | # } | ||||
| Tasks.object_detection: ['scores', 'labels', 'boxes'], | |||||
| Tasks.object_detection: | |||||
| [OutputKeys.SCORES, OutputKeys.LABELS, OutputKeys.BOXES], | |||||
| # instance segmentation result for single sample | # instance segmentation result for single sample | ||||
| # { | # { | ||||
| # "masks": [ | |||||
| # np.array in bgr channel order | |||||
| # ], | |||||
| # "scores": [0.9, 0.1, 0.05, 0.05], | |||||
| # "labels": ["dog", "horse", "cow", "cat"], | # "labels": ["dog", "horse", "cow", "cat"], | ||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | |||||
| # "boxes": [ | |||||
| # np.array in bgr channel order | |||||
| # ] | |||||
| # } | # } | ||||
| Tasks.image_segmentation: ['scores', 'labels', 'boxes'], | |||||
| Tasks.image_segmentation: | |||||
| [OutputKeys.SCORES, OutputKeys.LABELS, OutputKeys.BOXES], | |||||
| # image generation/editing/matting result for single sample | # image generation/editing/matting result for single sample | ||||
| # { | # { | ||||
| # "output_png": np.array with shape(h, w, 4) | |||||
| # "output_img": np.array with shape(h, w, 4) | |||||
| # for matting or (h, w, 3) for general purpose | # for matting or (h, w, 3) for general purpose | ||||
| # } | # } | ||||
| Tasks.image_editing: ['output_png'], | |||||
| Tasks.image_matting: ['output_png'], | |||||
| Tasks.image_generation: ['output_png'], | |||||
| Tasks.image_editing: [OutputKeys.OUTPUT_IMG], | |||||
| Tasks.image_matting: [OutputKeys.OUTPUT_IMG], | |||||
| Tasks.image_generation: [OutputKeys.OUTPUT_IMG], | |||||
| # action recognition result for single video | # action recognition result for single video | ||||
| # { | # { | ||||
| # "output_label": "abseiling" | # "output_label": "abseiling" | ||||
| # } | # } | ||||
| Tasks.action_recognition: ['output_label'], | |||||
| Tasks.action_recognition: [OutputKeys.LABELS], | |||||
| # pose estimation result for single sample | # pose estimation result for single sample | ||||
| # { | # { | ||||
| @@ -58,48 +80,55 @@ TASK_OUTPUTS = { | |||||
| # "boxes": np.array with shape [num_pose, 4], each box is | # "boxes": np.array with shape [num_pose, 4], each box is | ||||
| # [x1, y1, x2, y2] | # [x1, y1, x2, y2] | ||||
| # } | # } | ||||
| Tasks.pose_estimation: ['poses', 'boxes'], | |||||
| Tasks.pose_estimation: [OutputKeys.POSES, OutputKeys.BOXES], | |||||
| # ocr detection result for single sample | # ocr detection result for single sample | ||||
| # { | # { | ||||
| # "det_polygons": np.array with shape [num_text, 8], each box is | |||||
| # "polygons": np.array with shape [num_text, 8], each polygon is | |||||
| # [x1, y1, x2, y2, x3, y3, x4, y4] | # [x1, y1, x2, y2, x3, y3, x4, y4] | ||||
| # } | # } | ||||
| Tasks.ocr_detection: ['det_polygons'], | |||||
| Tasks.ocr_detection: [OutputKeys.POLYGONS], | |||||
| # ============ nlp tasks =================== | # ============ nlp tasks =================== | ||||
| # text classification result for single sample | # text classification result for single sample | ||||
| # { | # { | ||||
| # "labels": ["happy", "sad", "calm", "angry"], | |||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | # "scores": [0.9, 0.1, 0.05, 0.05] | ||||
| # "labels": ["happy", "sad", "calm", "angry"], | |||||
| # } | # } | ||||
| Tasks.text_classification: ['scores', 'labels'], | |||||
| Tasks.text_classification: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| # text generation result for single sample | # text generation result for single sample | ||||
| # { | # { | ||||
| # "text": "this is text generated by a model." | |||||
| # "text": "this is the text generated by a model." | |||||
| # } | # } | ||||
| Tasks.text_generation: ['text'], | |||||
| Tasks.text_generation: [OutputKeys.TEXT], | |||||
| # fill mask result for single sample | # fill mask result for single sample | ||||
| # { | # { | ||||
| # "text": "this is the text which masks filled by model." | # "text": "this is the text which masks filled by model." | ||||
| # } | # } | ||||
| Tasks.fill_mask: ['text'], | |||||
| Tasks.fill_mask: [OutputKeys.TEXT], | |||||
| # word segmentation result for single sample | # word segmentation result for single sample | ||||
| # { | # { | ||||
| # "output": "今天 天气 不错 , 适合 出去 游玩" | # "output": "今天 天气 不错 , 适合 出去 游玩" | ||||
| # } | # } | ||||
| Tasks.word_segmentation: ['output'], | |||||
| Tasks.word_segmentation: [OutputKeys.OUTPUT], | |||||
| # sentence similarity result for single sample | # sentence similarity result for single sample | ||||
| # { | # { | ||||
| # "labels": "1", | |||||
| # "scores": 0.9 | # "scores": 0.9 | ||||
| # "labels": "1", | |||||
| # } | # } | ||||
| Tasks.sentence_similarity: ['scores', 'labels'], | |||||
| Tasks.sentence_similarity: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| # sentiment classification result for single sample | |||||
| # { | |||||
| # "labels": ["happy", "sad", "calm", "angry"], | |||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | |||||
| # } | |||||
| Tasks.sentiment_classification: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| # sentiment classification result for single sample | # sentiment classification result for single sample | ||||
| # { | # { | ||||
| @@ -110,10 +139,43 @@ TASK_OUTPUTS = { | |||||
| # zero-shot classification result for single sample | # zero-shot classification result for single sample | ||||
| # { | # { | ||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | |||||
| # "labels": ["happy", "sad", "calm", "angry"], | |||||
| # } | |||||
| Tasks.zero_shot_classification: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| # nli result for single sample | |||||
| # { | |||||
| # "labels": ["happy", "sad", "calm", "angry"], | # "labels": ["happy", "sad", "calm", "angry"], | ||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | # "scores": [0.9, 0.1, 0.05, 0.05] | ||||
| # } | # } | ||||
| Tasks.zero_shot_classification: ['scores', 'labels'], | |||||
| Tasks.nli: [OutputKeys.SCORES, OutputKeys.LABELS], | |||||
| # {'pred': array([2.62349960e-03, 4.12110658e-03, 4.12748595e-05, 3.77560973e-05, | |||||
| # 1.08599677e-04, 1.72710388e-05, 2.95618793e-05, 1.93638436e-04, | |||||
| # 6.45841064e-05, 1.15997791e-04, 5.11605394e-05, 9.87020373e-01, | |||||
| # 2.66957268e-05, 4.72324500e-05, 9.74208378e-05, 4.18022355e-05, | |||||
| # 2.97343540e-05, 5.81317654e-05, 5.44203431e-05, 6.28319322e-05, | |||||
| # 7.34537680e-05, 6.61411541e-05, 3.62534920e-05, 8.58885178e-05, | |||||
| # 8.24327726e-05, 4.66077945e-05, 5.32869453e-05, 4.16190960e-05, | |||||
| # 5.97518992e-05, 3.92273068e-05, 3.44069012e-05, 9.92335918e-05, | |||||
| # 9.25978165e-05, 6.26462061e-05, 3.32317031e-05, 1.32061413e-03, | |||||
| # 2.01607945e-05, 3.36636294e-05, 3.99156743e-05, 5.84108493e-05, | |||||
| # 2.53432900e-05, 4.95731190e-04, 2.64443643e-05, 4.46992999e-05, | |||||
| # 2.42672231e-05, 4.75615161e-05, 2.66230145e-05, 4.00083954e-05, | |||||
| # 2.90536875e-04, 4.23891543e-05, 8.63691166e-05, 4.98188965e-05, | |||||
| # 3.47019341e-05, 4.52718523e-05, 4.20905781e-05, 5.50173208e-05, | |||||
| # 4.92360487e-05, 3.56021264e-05, 2.13957210e-05, 6.17428886e-05, | |||||
| # 1.43893281e-04, 7.32152112e-05, 2.91354867e-04, 2.46623786e-05, | |||||
| # 3.61441926e-05, 3.38475402e-05, 3.44323053e-05, 5.70138109e-05, | |||||
| # 4.31488479e-05, 4.94503947e-05, 4.30105974e-05, 1.00963116e-04, | |||||
| # 2.82062047e-05, 1.15582036e-04, 4.48261271e-05, 3.99339879e-05, | |||||
| # 7.27692823e-05], dtype=float32), 'label_pos': array([11]), 'label': 'lost_or_stolen_card'} | |||||
| Tasks.dialog_intent_prediction: | |||||
| [OutputKeys.PREDICTION, OutputKeys.LABEL_POS, OutputKeys.LABEL], | |||||
| # sys : ['you', 'are', 'welcome', '.', 'have', 'a', 'great', 'day', '!'] | |||||
| Tasks.dialog_modeling: [OutputKeys.RESPONSE], | |||||
| # nli result for single sample | # nli result for single sample | ||||
| # { | # { | ||||
| @@ -189,7 +251,7 @@ TASK_OUTPUTS = { | |||||
| # { | # { | ||||
| # "output_pcm": np.array with shape(samples,) and dtype float32 | # "output_pcm": np.array with shape(samples,) and dtype float32 | ||||
| # } | # } | ||||
| Tasks.speech_signal_process: ['output_pcm'], | |||||
| Tasks.speech_signal_process: [OutputKeys.OUTPUT_PCM], | |||||
| # ============ multi-modal tasks =================== | # ============ multi-modal tasks =================== | ||||
| @@ -197,14 +259,15 @@ TASK_OUTPUTS = { | |||||
| # { | # { | ||||
| # "caption": "this is an image caption text." | # "caption": "this is an image caption text." | ||||
| # } | # } | ||||
| Tasks.image_captioning: ['caption'], | |||||
| Tasks.image_captioning: [OutputKeys.CAPTION], | |||||
| # multi-modal embedding result for single sample | # multi-modal embedding result for single sample | ||||
| # { | # { | ||||
| # "img_embedding": np.array with shape [1, D], | # "img_embedding": np.array with shape [1, D], | ||||
| # "text_embedding": np.array with shape [1, D] | # "text_embedding": np.array with shape [1, D] | ||||
| # } | # } | ||||
| Tasks.multi_modal_embedding: ['img_embedding', 'text_embedding'], | |||||
| Tasks.multi_modal_embedding: | |||||
| [OutputKeys.IMG_EMBEDDING, OutputKeys.TEXT_EMBEDDING], | |||||
| # visual grounding result for single sample | # visual grounding result for single sample | ||||
| # { | # { | ||||
| @@ -215,11 +278,11 @@ TASK_OUTPUTS = { | |||||
| # ], | # ], | ||||
| # "scores": [0.9, 0.1, 0.05, 0.05] | # "scores": [0.9, 0.1, 0.05, 0.05] | ||||
| # } | # } | ||||
| Tasks.visual_grounding: ['boxes', 'scores'], | |||||
| Tasks.visual_grounding: [OutputKeys.BOXES, OutputKeys.SCORES], | |||||
| # text_to_image result for a single sample | # text_to_image result for a single sample | ||||
| # { | # { | ||||
| # "image": np.ndarray with shape [height, width, 3] | |||||
| # "output_img": np.ndarray with shape [height, width, 3] | |||||
| # } | # } | ||||
| Tasks.text_to_image_synthesis: ['image'] | |||||
| Tasks.text_to_image_synthesis: [OutputKeys.OUTPUT_IMG] | |||||
| } | } | ||||
| @@ -1,14 +1,21 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | # Copyright (c) Alibaba, Inc. and its affiliates. | ||||
| from .audio import LinearAECAndFbank | |||||
| from .base import Preprocessor | from .base import Preprocessor | ||||
| from .builder import PREPROCESSORS, build_preprocessor | from .builder import PREPROCESSORS, build_preprocessor | ||||
| from .common import Compose | from .common import Compose | ||||
| from .image import LoadImage, load_image | from .image import LoadImage, load_image | ||||
| from .kws import WavToLists | from .kws import WavToLists | ||||
| from .multi_modal import * # noqa F403 | |||||
| from .nlp import * # noqa F403 | |||||
| from .space.dialog_intent_prediction_preprocessor import * # noqa F403 | |||||
| from .space.dialog_modeling_preprocessor import * # noqa F403 | |||||
| from .space.dialog_state_tracking_preprocessor import * # noqa F403 | |||||
| from .text_to_speech import * # noqa F403 | from .text_to_speech import * # noqa F403 | ||||
| try: | |||||
| from .audio import LinearAECAndFbank | |||||
| from .multi_modal import * # noqa F403 | |||||
| from .nlp import * # noqa F403 | |||||
| from .space.dialog_intent_prediction_preprocessor import * # noqa F403 | |||||
| from .space.dialog_modeling_preprocessor import * # noqa F403 | |||||
| from .space.dialog_state_tracking_preprocessor import * # noqa F403 | |||||
| except ModuleNotFoundError as e: | |||||
| if str(e) == "No module named 'tensorflow'": | |||||
| pass | |||||
| else: | |||||
| raise ModuleNotFoundError(e) | |||||
| @@ -14,8 +14,7 @@ PATH = None | |||||
| logger = get_logger(PATH) | logger = get_logger(PATH) | ||||
| @TRAINERS.register_module( | |||||
| Tasks.text_classification, module_name=r'bert-sentiment-analysis') | |||||
| @TRAINERS.register_module(module_name=r'bert-sentiment-analysis') | |||||
| class SequenceClassificationTrainer(BaseTrainer): | class SequenceClassificationTrainer(BaseTrainer): | ||||
| def __init__(self, cfg_file: str, *args, **kwargs): | def __init__(self, cfg_file: str, *args, **kwargs): | ||||
| @@ -0,0 +1,79 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | |||||
| from modelscope.utils.constant import Fields, Requirements | |||||
| from modelscope.utils.import_utils import requires | |||||
| def get_msg(field): | |||||
| msg = f'\n{field} requirements not installed, please execute ' \ | |||||
| f'`pip install requirements/{field}.txt` or ' \ | |||||
| f'`pip install modelscope[{field}]`' | |||||
| return msg | |||||
| class NLPModuleNotFoundError(ModuleNotFoundError): | |||||
| def __init__(self, e: ModuleNotFoundError) -> None: | |||||
| e.msg += get_msg(Fields.nlp) | |||||
| super().__init__(e) | |||||
| class CVModuleNotFoundError(ModuleNotFoundError): | |||||
| def __init__(self, e: ModuleNotFoundError) -> None: | |||||
| e.msg += get_msg(Fields.cv) | |||||
| super().__init__(e) | |||||
| class AudioModuleNotFoundError(ModuleNotFoundError): | |||||
| def __init__(self, e: ModuleNotFoundError) -> None: | |||||
| e.msg += get_msg(Fields.audio) | |||||
| super().__init__(e) | |||||
| class MultiModalModuleNotFoundError(ModuleNotFoundError): | |||||
| def __init__(self, e: ModuleNotFoundError) -> None: | |||||
| e.msg += get_msg(Fields.multi_modal) | |||||
| super().__init__(e) | |||||
| def check_nlp(): | |||||
| try: | |||||
| requires('nlp models', ( | |||||
| Requirements.torch, | |||||
| Requirements.tokenizers, | |||||
| )) | |||||
| except ImportError as e: | |||||
| raise NLPModuleNotFoundError(e) | |||||
| def check_cv(): | |||||
| try: | |||||
| requires('cv models', ( | |||||
| Requirements.torch, | |||||
| Requirements.tokenizers, | |||||
| )) | |||||
| except ImportError as e: | |||||
| raise CVModuleNotFoundError(e) | |||||
| def check_audio(): | |||||
| try: | |||||
| requires('audio models', ( | |||||
| Requirements.torch, | |||||
| Requirements.tf, | |||||
| )) | |||||
| except ImportError as e: | |||||
| raise AudioModuleNotFoundError(e) | |||||
| def check_multi_modal(): | |||||
| try: | |||||
| requires('multi-modal models', ( | |||||
| Requirements.torch, | |||||
| Requirements.tokenizers, | |||||
| )) | |||||
| except ImportError as e: | |||||
| raise MultiModalModuleNotFoundError(e) | |||||
| @@ -17,9 +17,10 @@ from typing import Dict | |||||
| import addict | import addict | ||||
| from yapf.yapflib.yapf_api import FormatCode | from yapf.yapflib.yapf_api import FormatCode | ||||
| from modelscope.utils.import_utils import (import_modules, | |||||
| import_modules_from_file, | |||||
| validate_py_syntax) | |||||
| from modelscope.utils.logger import get_logger | 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': | if platform.system() == 'Windows': | ||||
| import regex as re # type: ignore | import regex as re # type: ignore | ||||
| @@ -102,5 +102,18 @@ class ModelFile(object): | |||||
| TORCH_MODEL_BIN_FILE = 'pytorch_model.bin' | TORCH_MODEL_BIN_FILE = 'pytorch_model.bin' | ||||
| class Requirements(object): | |||||
| """Requirement names for each module | |||||
| """ | |||||
| protobuf = 'protobuf' | |||||
| sentencepiece = 'sentencepiece' | |||||
| sklearn = 'sklearn' | |||||
| scipy = 'scipy' | |||||
| timm = 'timm' | |||||
| tokenizers = 'tokenizers' | |||||
| tf = 'tf' | |||||
| torch = 'torch' | |||||
| TENSORFLOW = 'tensorflow' | TENSORFLOW = 'tensorflow' | ||||
| PYTORCH = 'pytorch' | PYTORCH = 'pytorch' | ||||
| @@ -0,0 +1,324 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | |||||
| # Part of the implementation is borrowed from huggingface/transformers. | |||||
| import ast | |||||
| import functools | |||||
| import importlib.util | |||||
| import os | |||||
| import os.path as osp | |||||
| import sys | |||||
| import types | |||||
| from collections import OrderedDict | |||||
| from functools import wraps | |||||
| from importlib import import_module | |||||
| from itertools import chain | |||||
| from types import ModuleType | |||||
| from typing import Any | |||||
| import json | |||||
| from packaging import version | |||||
| from modelscope.utils.constant import Fields | |||||
| from modelscope.utils.logger import get_logger | |||||
| if sys.version_info < (3, 8): | |||||
| import importlib_metadata | |||||
| else: | |||||
| import importlib.metadata as importlib_metadata | |||||
| logger = get_logger() | |||||
| def import_modules_from_file(py_file: str): | |||||
| """ Import module from a certrain file | |||||
| Args: | |||||
| py_file: path to a python file to be imported | |||||
| Return: | |||||
| """ | |||||
| dirname, basefile = os.path.split(py_file) | |||||
| if dirname == '': | |||||
| dirname == './' | |||||
| module_name = osp.splitext(basefile)[0] | |||||
| sys.path.insert(0, dirname) | |||||
| validate_py_syntax(py_file) | |||||
| mod = import_module(module_name) | |||||
| sys.path.pop(0) | |||||
| return module_name, mod | |||||
| def import_modules(imports, allow_failed_imports=False): | |||||
| """Import modules from the given list of strings. | |||||
| Args: | |||||
| imports (list | str | None): The given module names to be imported. | |||||
| allow_failed_imports (bool): If True, the failed imports will return | |||||
| None. Otherwise, an ImportError is raise. Default: False. | |||||
| Returns: | |||||
| list[module] | module | None: The imported modules. | |||||
| Examples: | |||||
| >>> osp, sys = import_modules( | |||||
| ... ['os.path', 'sys']) | |||||
| >>> import os.path as osp_ | |||||
| >>> import sys as sys_ | |||||
| >>> assert osp == osp_ | |||||
| >>> assert sys == sys_ | |||||
| """ | |||||
| if not imports: | |||||
| return | |||||
| single_import = False | |||||
| if isinstance(imports, str): | |||||
| single_import = True | |||||
| imports = [imports] | |||||
| if not isinstance(imports, list): | |||||
| raise TypeError( | |||||
| f'custom_imports must be a list but got type {type(imports)}') | |||||
| imported = [] | |||||
| for imp in imports: | |||||
| if not isinstance(imp, str): | |||||
| raise TypeError( | |||||
| f'{imp} is of type {type(imp)} and cannot be imported.') | |||||
| try: | |||||
| imported_tmp = import_module(imp) | |||||
| except ImportError: | |||||
| if allow_failed_imports: | |||||
| logger.warning(f'{imp} failed to import and is ignored.') | |||||
| imported_tmp = None | |||||
| else: | |||||
| raise ImportError | |||||
| imported.append(imported_tmp) | |||||
| if single_import: | |||||
| imported = imported[0] | |||||
| return imported | |||||
| def validate_py_syntax(filename): | |||||
| with open(filename, 'r', encoding='utf-8') as f: | |||||
| # Setting encoding explicitly to resolve coding issue on windows | |||||
| content = f.read() | |||||
| try: | |||||
| ast.parse(content) | |||||
| except SyntaxError as e: | |||||
| raise SyntaxError('There are syntax errors in config ' | |||||
| f'file {filename}: {e}') | |||||
| # following code borrows implementation from huggingface/transformers | |||||
| ENV_VARS_TRUE_VALUES = {'1', 'ON', 'YES', 'TRUE'} | |||||
| ENV_VARS_TRUE_AND_AUTO_VALUES = ENV_VARS_TRUE_VALUES.union({'AUTO'}) | |||||
| USE_TF = os.environ.get('USE_TF', 'AUTO').upper() | |||||
| USE_TORCH = os.environ.get('USE_TORCH', 'AUTO').upper() | |||||
| _torch_version = 'N/A' | |||||
| if USE_TORCH in ENV_VARS_TRUE_AND_AUTO_VALUES and USE_TF not in ENV_VARS_TRUE_VALUES: | |||||
| _torch_available = importlib.util.find_spec('torch') is not None | |||||
| if _torch_available: | |||||
| try: | |||||
| _torch_version = importlib_metadata.version('torch') | |||||
| logger.info(f'PyTorch version {_torch_version} available.') | |||||
| except importlib_metadata.PackageNotFoundError: | |||||
| _torch_available = False | |||||
| else: | |||||
| logger.info('Disabling PyTorch because USE_TF is set') | |||||
| _torch_available = False | |||||
| _tf_version = 'N/A' | |||||
| if USE_TF in ENV_VARS_TRUE_AND_AUTO_VALUES and USE_TORCH not in ENV_VARS_TRUE_VALUES: | |||||
| _tf_available = importlib.util.find_spec('tensorflow') is not None | |||||
| if _tf_available: | |||||
| candidates = ( | |||||
| 'tensorflow', | |||||
| 'tensorflow-cpu', | |||||
| 'tensorflow-gpu', | |||||
| 'tf-nightly', | |||||
| 'tf-nightly-cpu', | |||||
| 'tf-nightly-gpu', | |||||
| 'intel-tensorflow', | |||||
| 'intel-tensorflow-avx512', | |||||
| 'tensorflow-rocm', | |||||
| 'tensorflow-macos', | |||||
| ) | |||||
| _tf_version = None | |||||
| # For the metadata, we have to look for both tensorflow and tensorflow-cpu | |||||
| for pkg in candidates: | |||||
| try: | |||||
| _tf_version = importlib_metadata.version(pkg) | |||||
| break | |||||
| except importlib_metadata.PackageNotFoundError: | |||||
| pass | |||||
| _tf_available = _tf_version is not None | |||||
| if _tf_available: | |||||
| if version.parse(_tf_version) < version.parse('2'): | |||||
| pass | |||||
| else: | |||||
| logger.info(f'TensorFlow version {_tf_version} available.') | |||||
| else: | |||||
| logger.info('Disabling Tensorflow because USE_TORCH is set') | |||||
| _tf_available = False | |||||
| _timm_available = importlib.util.find_spec('timm') is not None | |||||
| try: | |||||
| _timm_version = importlib_metadata.version('timm') | |||||
| logger.debug(f'Successfully imported timm version {_timm_version}') | |||||
| except importlib_metadata.PackageNotFoundError: | |||||
| _timm_available = False | |||||
| def is_scipy_available(): | |||||
| return importlib.util.find_spec('scipy') is not None | |||||
| def is_sklearn_available(): | |||||
| if importlib.util.find_spec('sklearn') is None: | |||||
| return False | |||||
| return is_scipy_available() and importlib.util.find_spec('sklearn.metrics') | |||||
| def is_sentencepiece_available(): | |||||
| return importlib.util.find_spec('sentencepiece') is not None | |||||
| def is_protobuf_available(): | |||||
| if importlib.util.find_spec('google') is None: | |||||
| return False | |||||
| return importlib.util.find_spec('google.protobuf') is not None | |||||
| def is_tokenizers_available(): | |||||
| return importlib.util.find_spec('tokenizers') is not None | |||||
| def is_timm_available(): | |||||
| return _timm_available | |||||
| def is_torch_available(): | |||||
| return _torch_available | |||||
| def is_torch_cuda_available(): | |||||
| if is_torch_available(): | |||||
| import torch | |||||
| return torch.cuda.is_available() | |||||
| else: | |||||
| return False | |||||
| def is_tf_available(): | |||||
| return _tf_available | |||||
| # docstyle-ignore | |||||
| PROTOBUF_IMPORT_ERROR = """ | |||||
| {0} requires the protobuf library but it was not found in your environment. Checkout the instructions on the | |||||
| installation page of its repo: https://github.com/protocolbuffers/protobuf/tree/master/python#installation and | |||||
| follow the ones that match your environment. | |||||
| """ | |||||
| # docstyle-ignore | |||||
| SENTENCEPIECE_IMPORT_ERROR = """ | |||||
| {0} requires the SentencePiece library but it was not found in your environment. Checkout the instructions on the | |||||
| installation page of its repo: https://github.com/google/sentencepiece#installation and follow the ones | |||||
| that match your environment. | |||||
| """ | |||||
| # docstyle-ignore | |||||
| SKLEARN_IMPORT_ERROR = """ | |||||
| {0} requires the scikit-learn library but it was not found in your environment. You can install it with: | |||||
| ``` | |||||
| pip install -U scikit-learn | |||||
| ``` | |||||
| In a notebook or a colab, you can install it by executing a cell with | |||||
| ``` | |||||
| !pip install -U scikit-learn | |||||
| ``` | |||||
| """ | |||||
| # docstyle-ignore | |||||
| TENSORFLOW_IMPORT_ERROR = """ | |||||
| {0} requires the TensorFlow library but it was not found in your environment. Checkout the instructions on the | |||||
| installation page: https://www.tensorflow.org/install and follow the ones that match your environment. | |||||
| """ | |||||
| # docstyle-ignore | |||||
| TIMM_IMPORT_ERROR = """ | |||||
| {0} requires the timm library but it was not found in your environment. You can install it with pip: | |||||
| `pip install timm` | |||||
| """ | |||||
| # docstyle-ignore | |||||
| TOKENIZERS_IMPORT_ERROR = """ | |||||
| {0} requires the 🤗 Tokenizers library but it was not found in your environment. You can install it with: | |||||
| ``` | |||||
| pip install tokenizers | |||||
| ``` | |||||
| In a notebook or a colab, you can install it by executing a cell with | |||||
| ``` | |||||
| !pip install tokenizers | |||||
| ``` | |||||
| """ | |||||
| # docstyle-ignore | |||||
| PYTORCH_IMPORT_ERROR = """ | |||||
| {0} requires the PyTorch library but it was not found in your environment. Checkout the instructions on the | |||||
| installation page: https://pytorch.org/get-started/locally/ and follow the ones that match your environment. | |||||
| """ | |||||
| # docstyle-ignore | |||||
| SCIPY_IMPORT_ERROR = """ | |||||
| {0} requires the scipy library but it was not found in your environment. You can install it with pip: | |||||
| `pip install scipy` | |||||
| """ | |||||
| REQUIREMENTS_MAAPING = OrderedDict([ | |||||
| ('protobuf', (is_protobuf_available, PROTOBUF_IMPORT_ERROR)), | |||||
| ('sentencepiece', (is_sentencepiece_available, | |||||
| SENTENCEPIECE_IMPORT_ERROR)), | |||||
| ('sklearn', (is_sklearn_available, SKLEARN_IMPORT_ERROR)), | |||||
| ('tf', (is_tf_available, TENSORFLOW_IMPORT_ERROR)), | |||||
| ('timm', (is_timm_available, TIMM_IMPORT_ERROR)), | |||||
| ('tokenizers', (is_tokenizers_available, TOKENIZERS_IMPORT_ERROR)), | |||||
| ('torch', (is_torch_available, PYTORCH_IMPORT_ERROR)), | |||||
| ('scipy', (is_scipy_available, SCIPY_IMPORT_ERROR)), | |||||
| ]) | |||||
| def requires(obj, requirements): | |||||
| if not isinstance(requirements, (list, tuple)): | |||||
| requirements = [requirements] | |||||
| if isinstance(obj, str): | |||||
| name = obj | |||||
| else: | |||||
| name = obj.__name__ if hasattr(obj, | |||||
| '__name__') else obj.__class__.__name__ | |||||
| checks = (REQUIREMENTS_MAAPING[req] for req in requirements) | |||||
| failed = [msg.format(name) for available, msg in checks if not available()] | |||||
| if failed: | |||||
| raise ImportError(''.join(failed)) | |||||
| def torch_required(func): | |||||
| # Chose a different decorator name than in tests so it's clear they are not the same. | |||||
| @functools.wraps(func) | |||||
| def wrapper(*args, **kwargs): | |||||
| if is_torch_available(): | |||||
| return func(*args, **kwargs) | |||||
| else: | |||||
| raise ImportError(f'Method `{func.__name__}` requires PyTorch.') | |||||
| return wrapper | |||||
| def tf_required(func): | |||||
| # Chose a different decorator name than in tests so it's clear they are not the same. | |||||
| @functools.wraps(func) | |||||
| def wrapper(*args, **kwargs): | |||||
| if is_tf_available(): | |||||
| return func(*args, **kwargs) | |||||
| else: | |||||
| raise ImportError(f'Method `{func.__name__}` requires TF.') | |||||
| return wrapper | |||||
| @@ -1,90 +0,0 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | |||||
| import ast | |||||
| import os | |||||
| import os.path as osp | |||||
| import sys | |||||
| import types | |||||
| from importlib import import_module | |||||
| from modelscope.utils.logger import get_logger | |||||
| logger = get_logger() | |||||
| def import_modules_from_file(py_file: str): | |||||
| """ Import module from a certrain file | |||||
| Args: | |||||
| py_file: path to a python file to be imported | |||||
| Return: | |||||
| """ | |||||
| dirname, basefile = os.path.split(py_file) | |||||
| if dirname == '': | |||||
| dirname == './' | |||||
| module_name = osp.splitext(basefile)[0] | |||||
| sys.path.insert(0, dirname) | |||||
| validate_py_syntax(py_file) | |||||
| mod = import_module(module_name) | |||||
| sys.path.pop(0) | |||||
| return module_name, mod | |||||
| def import_modules(imports, allow_failed_imports=False): | |||||
| """Import modules from the given list of strings. | |||||
| Args: | |||||
| imports (list | str | None): The given module names to be imported. | |||||
| allow_failed_imports (bool): If True, the failed imports will return | |||||
| None. Otherwise, an ImportError is raise. Default: False. | |||||
| Returns: | |||||
| list[module] | module | None: The imported modules. | |||||
| Examples: | |||||
| >>> osp, sys = import_modules( | |||||
| ... ['os.path', 'sys']) | |||||
| >>> import os.path as osp_ | |||||
| >>> import sys as sys_ | |||||
| >>> assert osp == osp_ | |||||
| >>> assert sys == sys_ | |||||
| """ | |||||
| if not imports: | |||||
| return | |||||
| single_import = False | |||||
| if isinstance(imports, str): | |||||
| single_import = True | |||||
| imports = [imports] | |||||
| if not isinstance(imports, list): | |||||
| raise TypeError( | |||||
| f'custom_imports must be a list but got type {type(imports)}') | |||||
| imported = [] | |||||
| for imp in imports: | |||||
| if not isinstance(imp, str): | |||||
| raise TypeError( | |||||
| f'{imp} is of type {type(imp)} and cannot be imported.') | |||||
| try: | |||||
| imported_tmp = import_module(imp) | |||||
| except ImportError: | |||||
| if allow_failed_imports: | |||||
| logger.warning(f'{imp} failed to import and is ignored.') | |||||
| imported_tmp = None | |||||
| else: | |||||
| raise ImportError | |||||
| imported.append(imported_tmp) | |||||
| if single_import: | |||||
| imported = imported[0] | |||||
| return imported | |||||
| def validate_py_syntax(filename): | |||||
| with open(filename, 'r', encoding='utf-8') as f: | |||||
| # Setting encoding explicitly to resolve coding issue on windows | |||||
| content = f.read() | |||||
| try: | |||||
| ast.parse(content) | |||||
| except SyntaxError as e: | |||||
| raise SyntaxError('There are syntax errors in config ' | |||||
| f'file {filename}: {e}') | |||||
| @@ -1,7 +1,9 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | # Copyright (c) Alibaba, Inc. and its affiliates. | ||||
| import inspect | import inspect | ||||
| from typing import List, Tuple, Union | |||||
| from modelscope.utils.import_utils import requires | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| default_group = 'default' | default_group = 'default' | ||||
| @@ -52,9 +54,14 @@ class Registry(object): | |||||
| def _register_module(self, | def _register_module(self, | ||||
| group_key=default_group, | group_key=default_group, | ||||
| module_name=None, | module_name=None, | ||||
| module_cls=None): | |||||
| module_cls=None, | |||||
| requirements=None): | |||||
| assert isinstance(group_key, | assert isinstance(group_key, | ||||
| str), 'group_key is required and must be str' | str), 'group_key is required and must be str' | ||||
| if requirements is not None: | |||||
| requires(module_cls, requirements) | |||||
| if group_key not in self._modules: | if group_key not in self._modules: | ||||
| self._modules[group_key] = dict() | self._modules[group_key] = dict() | ||||
| @@ -70,23 +77,11 @@ class Registry(object): | |||||
| self._modules[group_key][module_name] = module_cls | self._modules[group_key][module_name] = module_cls | ||||
| module_cls.group_key = group_key | module_cls.group_key = group_key | ||||
| if module_name in self._modules[default_group]: | |||||
| if id(self._modules[default_group][module_name]) == id(module_cls): | |||||
| return | |||||
| else: | |||||
| logger.warning(f'{module_name} is already registered in ' | |||||
| f'{self._name}[{default_group}] and will ' | |||||
| 'be overwritten') | |||||
| logger.warning(f'{self._modules[default_group][module_name]}' | |||||
| f'to {module_cls}') | |||||
| # also register module in the default group for faster access | |||||
| # only by module name | |||||
| self._modules[default_group][module_name] = module_cls | |||||
| def register_module(self, | def register_module(self, | ||||
| group_key: str = default_group, | group_key: str = default_group, | ||||
| module_name: str = None, | module_name: str = None, | ||||
| module_cls: type = None): | |||||
| module_cls: type = None, | |||||
| requirements: Union[List, Tuple] = None): | |||||
| """ Register module | """ Register module | ||||
| Example: | Example: | ||||
| @@ -110,17 +105,18 @@ class Registry(object): | |||||
| default group name is 'default' | default group name is 'default' | ||||
| module_name: Module name | module_name: Module name | ||||
| module_cls: Module class object | module_cls: Module class object | ||||
| requirements: Module necessary requirements | |||||
| """ | """ | ||||
| if not (module_name is None or isinstance(module_name, str)): | if not (module_name is None or isinstance(module_name, str)): | ||||
| raise TypeError(f'module_name must be either of None, str,' | raise TypeError(f'module_name must be either of None, str,' | ||||
| f'got {type(module_name)}') | f'got {type(module_name)}') | ||||
| if module_cls is not None: | if module_cls is not None: | ||||
| self._register_module( | self._register_module( | ||||
| group_key=group_key, | group_key=group_key, | ||||
| module_name=module_name, | module_name=module_name, | ||||
| module_cls=module_cls) | |||||
| module_cls=module_cls, | |||||
| requirements=requirements) | |||||
| return module_cls | return module_cls | ||||
| # if module_cls is None, should return a decorator function | # if module_cls is None, should return a decorator function | ||||
| @@ -128,7 +124,8 @@ class Registry(object): | |||||
| self._register_module( | self._register_module( | ||||
| group_key=group_key, | group_key=group_key, | ||||
| module_name=module_name, | module_name=module_name, | ||||
| module_cls=module_cls) | |||||
| module_cls=module_cls, | |||||
| requirements=requirements) | |||||
| return module_cls | return module_cls | ||||
| return _register | return _register | ||||
| @@ -1,6 +1 @@ | |||||
| -r requirements/runtime.txt | -r requirements/runtime.txt | ||||
| -r requirements/pipeline.txt | |||||
| -r requirements/multi-modal.txt | |||||
| -r requirements/nlp.txt | |||||
| -r requirements/audio.txt | |||||
| -r requirements/cv.txt | |||||
| @@ -1,10 +1,5 @@ | |||||
| #tts | #tts | ||||
| h5py | h5py | ||||
| https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/TTS/requirements/pytorch_wavelets-1.3.0-py3-none-any.whl | |||||
| https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/TTS/requirements/ttsfrd-0.0.2-cp36-cp36m-linux_x86_64.whl; python_version=='3.6' | |||||
| https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/TTS/requirements/ttsfrd-0.0.2-cp37-cp37m-linux_x86_64.whl; python_version=='3.7' | |||||
| https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/TTS/requirements/ttsfrd-0.0.2-cp38-cp38-linux_x86_64.whl; python_version=='3.8' | |||||
| https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/TTS/requirements/ttsfrd-0.0.2-cp39-cp39-linux_x86_64.whl; python_version=='3.9' | |||||
| inflect | inflect | ||||
| keras | keras | ||||
| librosa | librosa | ||||
| @@ -14,6 +9,7 @@ nara_wpe | |||||
| numpy | numpy | ||||
| protobuf>3,<=3.20 | protobuf>3,<=3.20 | ||||
| ptflops | ptflops | ||||
| pytorch_wavelets==1.3.0 | |||||
| PyWavelets>=1.0.0 | PyWavelets>=1.0.0 | ||||
| scikit-learn | scikit-learn | ||||
| SoundFile>0.10 | SoundFile>0.10 | ||||
| @@ -24,4 +20,5 @@ torch | |||||
| torchaudio | torchaudio | ||||
| torchvision | torchvision | ||||
| tqdm | tqdm | ||||
| ttsfrd==0.0.2 | |||||
| unidecode | unidecode | ||||
| @@ -1,8 +1,6 @@ | |||||
| datasets | |||||
| einops | |||||
| fairseq==maas | |||||
| ftfy>=6.0.3 | 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 | |||||
| ofa==0.0.2 | |||||
| pycocoevalcap>=1.2 | pycocoevalcap>=1.2 | ||||
| pycocotools>=2.0.4 | pycocotools>=2.0.4 | ||||
| rouge_score | rouge_score | ||||
| @@ -1,3 +1,4 @@ | |||||
| http://ait-public.oss-cn-hangzhou-zmf.aliyuncs.com/jizhu/en_core_web_sm-2.3.1.tar.gz | http://ait-public.oss-cn-hangzhou-zmf.aliyuncs.com/jizhu/en_core_web_sm-2.3.1.tar.gz | ||||
| https://alinlp.alibaba-inc.com/pypi/sofa-1.0.5-py3-none-any.whl | https://alinlp.alibaba-inc.com/pypi/sofa-1.0.5-py3-none-any.whl | ||||
| sofa==1.0.5 | |||||
| spacy>=2.3.5 | spacy>=2.3.5 | ||||
| @@ -1,6 +0,0 @@ | |||||
| #https://atp-modelzoo-sh.oss-cn-shanghai.aliyuncs.com/release/package/whl/easynlp-0.0.4-py2.py3-none-any.whl | |||||
| # tensorflow | |||||
| #--find-links https://download.pytorch.org/whl/torch_stable.html | |||||
| # torch<1.10,>=1.8.0 | |||||
| # torchaudio | |||||
| # torchvision | |||||
| @@ -1,16 +1,18 @@ | |||||
| addict | addict | ||||
| datasets | datasets | ||||
| easydict | easydict | ||||
| einops | |||||
| filelock>=3.3.0 | filelock>=3.3.0 | ||||
| numpy | numpy | ||||
| opencv-python-headless | |||||
| opencv-python | |||||
| Pillow>=6.2.0 | Pillow>=6.2.0 | ||||
| protobuf>3,<=3.20 | |||||
| pyyaml | pyyaml | ||||
| requests | requests | ||||
| requests==2.27.1 | |||||
| scipy | scipy | ||||
| setuptools==58.0.4 | |||||
| setuptools | |||||
| tokenizers<=0.10.3 | tokenizers<=0.10.3 | ||||
| torch | |||||
| tqdm>=4.64.0 | tqdm>=4.64.0 | ||||
| transformers<=4.16.2 | |||||
| transformers<=4.16.2,>=4.10.3 | |||||
| yapf | yapf | ||||
| @@ -5,6 +5,8 @@ import shutil | |||||
| import subprocess | import subprocess | ||||
| from setuptools import find_packages, setup | from setuptools import find_packages, setup | ||||
| from modelscope.utils.constant import Fields | |||||
| def readme(): | def readme(): | ||||
| with open('README.md', encoding='utf-8') as f: | with open('README.md', encoding='utf-8') as f: | ||||
| @@ -169,6 +171,16 @@ if __name__ == '__main__': | |||||
| pack_resource() | pack_resource() | ||||
| os.chdir('package') | os.chdir('package') | ||||
| install_requires, deps_link = parse_requirements('requirements.txt') | install_requires, deps_link = parse_requirements('requirements.txt') | ||||
| extra_requires = {} | |||||
| all_requires = [] | |||||
| for field in dir(Fields): | |||||
| if field.startswith('_'): | |||||
| continue | |||||
| extra_requires[field], _ = parse_requirements( | |||||
| f'requirements/{field}.txt') | |||||
| all_requires.append(extra_requires[field]) | |||||
| extra_requires['all'] = all_requires | |||||
| setup( | setup( | ||||
| name='model-scope', | name='model-scope', | ||||
| version=get_version(), | version=get_version(), | ||||
| @@ -193,5 +205,6 @@ if __name__ == '__main__': | |||||
| license='Apache License 2.0', | license='Apache License 2.0', | ||||
| tests_require=parse_requirements('requirements/tests.txt'), | tests_require=parse_requirements('requirements/tests.txt'), | ||||
| install_requires=install_requires, | install_requires=install_requires, | ||||
| extras_require=extra_requires, | |||||
| dependency_links=deps_link, | dependency_links=deps_link, | ||||
| zip_safe=False) | zip_safe=False) | ||||
| @@ -8,6 +8,7 @@ import PIL | |||||
| from modelscope.pipelines import Pipeline, pipeline | from modelscope.pipelines import Pipeline, pipeline | ||||
| from modelscope.pipelines.builder import PIPELINES, add_default_pipeline_info | from modelscope.pipelines.builder import PIPELINES, add_default_pipeline_info | ||||
| from modelscope.pipelines.outputs import OutputKeys | |||||
| from modelscope.utils.constant import Tasks | from modelscope.utils.constant import Tasks | ||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from modelscope.utils.registry import default_group | from modelscope.utils.registry import default_group | ||||
| @@ -68,28 +69,28 @@ class CustomPipelineTest(unittest.TestCase): | |||||
| outputs['filename'] = inputs['url'] | outputs['filename'] = inputs['url'] | ||||
| img = inputs['img'] | img = inputs['img'] | ||||
| new_image = img.resize((img.width // 2, img.height // 2)) | new_image = img.resize((img.width // 2, img.height // 2)) | ||||
| outputs['output_png'] = np.array(new_image) | |||||
| outputs[OutputKeys.OUTPUT_IMG] = np.array(new_image) | |||||
| return outputs | return outputs | ||||
| def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: | ||||
| return inputs | return inputs | ||||
| self.assertTrue('custom-image' in PIPELINES.modules[default_group]) | |||||
| self.assertTrue('custom-image' in PIPELINES.modules[dummy_task]) | |||||
| add_default_pipeline_info(dummy_task, 'custom-image', overwrite=True) | add_default_pipeline_info(dummy_task, 'custom-image', overwrite=True) | ||||
| pipe = pipeline(pipeline_name='custom-image') | |||||
| pipe = pipeline(task=dummy_task, pipeline_name='custom-image') | |||||
| pipe2 = pipeline(dummy_task) | pipe2 = pipeline(dummy_task) | ||||
| self.assertTrue(type(pipe) is type(pipe2)) | self.assertTrue(type(pipe) is type(pipe2)) | ||||
| img_url = 'data/test/images/image1.jpg' | img_url = 'data/test/images/image1.jpg' | ||||
| output = pipe(img_url) | output = pipe(img_url) | ||||
| self.assertEqual(output['filename'], img_url) | self.assertEqual(output['filename'], img_url) | ||||
| self.assertEqual(output['output_png'].shape, (318, 512, 3)) | |||||
| self.assertEqual(output[OutputKeys.OUTPUT_IMG].shape, (318, 512, 3)) | |||||
| outputs = pipe([img_url for i in range(4)]) | outputs = pipe([img_url for i in range(4)]) | ||||
| self.assertEqual(len(outputs), 4) | self.assertEqual(len(outputs), 4) | ||||
| for out in outputs: | for out in outputs: | ||||
| self.assertEqual(out['filename'], img_url) | self.assertEqual(out['filename'], img_url) | ||||
| self.assertEqual(out['output_png'].shape, (318, 512, 3)) | |||||
| self.assertEqual(out[OutputKeys.OUTPUT_IMG].shape, (318, 512, 3)) | |||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||
| @@ -3,6 +3,7 @@ | |||||
| import unittest | import unittest | ||||
| from modelscope.pipelines import pipeline | from modelscope.pipelines import pipeline | ||||
| from modelscope.pipelines.outputs import OutputKeys | |||||
| from modelscope.utils.constant import Tasks | from modelscope.utils.constant import Tasks | ||||
| from modelscope.utils.test_utils import test_level | from modelscope.utils.test_utils import test_level | ||||
| @@ -15,7 +16,7 @@ class ImageCaptionTest(unittest.TestCase): | |||||
| Tasks.image_captioning, | Tasks.image_captioning, | ||||
| model='damo/ofa_image-caption_coco_large_en') | model='damo/ofa_image-caption_coco_large_en') | ||||
| result = img_captioning('data/test/images/image_captioning.png') | result = img_captioning('data/test/images/image_captioning.png') | ||||
| print(result['caption']) | |||||
| print(result[OutputKeys.CAPTION]) | |||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||
| @@ -9,6 +9,7 @@ import cv2 | |||||
| from modelscope.fileio import File | from modelscope.fileio import File | ||||
| from modelscope.msdatasets import MsDataset | from modelscope.msdatasets import MsDataset | ||||
| from modelscope.pipelines import pipeline | from modelscope.pipelines import pipeline | ||||
| from modelscope.pipelines.outputs import OutputKeys | |||||
| from modelscope.utils.constant import ModelFile, Tasks | from modelscope.utils.constant import ModelFile, Tasks | ||||
| from modelscope.utils.test_utils import test_level | from modelscope.utils.test_utils import test_level | ||||
| @@ -29,7 +30,7 @@ class ImageMattingTest(unittest.TestCase): | |||||
| img_matting = pipeline(Tasks.image_matting, model=tmp_dir) | img_matting = pipeline(Tasks.image_matting, model=tmp_dir) | ||||
| result = img_matting('data/test/images/image_matting.png') | result = img_matting('data/test/images/image_matting.png') | ||||
| cv2.imwrite('result.png', result['output_png']) | |||||
| cv2.imwrite('result.png', result[OutputKeys.OUTPUT_IMG]) | |||||
| @unittest.skipUnless(test_level() >= 1, 'skip test in current test level') | @unittest.skipUnless(test_level() >= 1, 'skip test in current test level') | ||||
| def test_run_with_dataset(self): | def test_run_with_dataset(self): | ||||
| @@ -41,7 +42,7 @@ class ImageMattingTest(unittest.TestCase): | |||||
| img_matting = pipeline(Tasks.image_matting, model=self.model_id) | 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. | # note that for dataset output, the inference-output is a Generator that can be iterated. | ||||
| result = img_matting(dataset) | result = img_matting(dataset) | ||||
| cv2.imwrite('result.png', next(result)['output_png']) | |||||
| cv2.imwrite('result.png', next(result)[OutputKeys.OUTPUT_IMG]) | |||||
| print(f'Output written to {osp.abspath("result.png")}') | print(f'Output written to {osp.abspath("result.png")}') | ||||
| @unittest.skipUnless(test_level() >= 0, 'skip test in current test level') | @unittest.skipUnless(test_level() >= 0, 'skip test in current test level') | ||||
| @@ -49,7 +50,7 @@ class ImageMattingTest(unittest.TestCase): | |||||
| img_matting = pipeline(Tasks.image_matting, model=self.model_id) | img_matting = pipeline(Tasks.image_matting, model=self.model_id) | ||||
| result = img_matting('data/test/images/image_matting.png') | result = img_matting('data/test/images/image_matting.png') | ||||
| cv2.imwrite('result.png', result['output_png']) | |||||
| cv2.imwrite('result.png', result[OutputKeys.OUTPUT_IMG]) | |||||
| print(f'Output written to {osp.abspath("result.png")}') | print(f'Output written to {osp.abspath("result.png")}') | ||||
| @unittest.skipUnless(test_level() >= 2, 'skip test in current test level') | @unittest.skipUnless(test_level() >= 2, 'skip test in current test level') | ||||
| @@ -57,7 +58,7 @@ class ImageMattingTest(unittest.TestCase): | |||||
| img_matting = pipeline(Tasks.image_matting) | img_matting = pipeline(Tasks.image_matting) | ||||
| result = img_matting('data/test/images/image_matting.png') | result = img_matting('data/test/images/image_matting.png') | ||||
| cv2.imwrite('result.png', result['output_png']) | |||||
| cv2.imwrite('result.png', result[OutputKeys.OUTPUT_IMG]) | |||||
| print(f'Output written to {osp.abspath("result.png")}') | print(f'Output written to {osp.abspath("result.png")}') | ||||
| @unittest.skipUnless(test_level() >= 2, 'skip test in current test level') | @unittest.skipUnless(test_level() >= 2, 'skip test in current test level') | ||||
| @@ -67,7 +68,7 @@ class ImageMattingTest(unittest.TestCase): | |||||
| img_matting = pipeline(Tasks.image_matting, model=self.model_id) | img_matting = pipeline(Tasks.image_matting, model=self.model_id) | ||||
| result = img_matting(dataset) | result = img_matting(dataset) | ||||
| for i in range(10): | for i in range(10): | ||||
| cv2.imwrite(f'result_{i}.png', next(result)['output_png']) | |||||
| cv2.imwrite(f'result_{i}.png', next(result)[OutputKeys.OUTPUT_IMG]) | |||||
| print( | print( | ||||
| f'Output written to dir: {osp.dirname(osp.abspath("result_0.png"))}' | f'Output written to dir: {osp.dirname(osp.abspath("result_0.png"))}' | ||||
| ) | ) | ||||
| @@ -15,8 +15,8 @@ from modelscope.utils.test_utils import test_level | |||||
| KWSBP_URL = 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/KWS/tools/kwsbp' | KWSBP_URL = 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/KWS/tools/kwsbp' | ||||
| POS_WAV_FILE = '20200707_spk57db_storenoise52db_40cm_xiaoyun_sox_6.wav' | |||||
| POS_WAV_URL = 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/KWS/pos_testset/' + POS_WAV_FILE | |||||
| POS_WAV_FILE = 'data/test/audios/kws_xiaoyunxiaoyun.wav' | |||||
| BOFANGYINYUE_WAV_FILE = 'data/test/audios/kws_bofangyinyue.wav' | |||||
| POS_TESTSETS_FILE = 'pos_testsets.tar.gz' | POS_TESTSETS_FILE = 'pos_testsets.tar.gz' | ||||
| POS_TESTSETS_URL = 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/KWS/pos_testsets.tar.gz' | POS_TESTSETS_URL = 'https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/KWS/pos_testsets.tar.gz' | ||||
| @@ -47,12 +47,8 @@ class KeyWordSpottingTest(unittest.TestCase): | |||||
| # wav, neg_testsets, pos_testsets, roc | # wav, neg_testsets, pos_testsets, roc | ||||
| kws_set = 'wav' | kws_set = 'wav' | ||||
| # downloading wav file | |||||
| wav_file_path = os.path.join(self.workspace, POS_WAV_FILE) | |||||
| if not os.path.exists(wav_file_path): | |||||
| r = requests.get(POS_WAV_URL) | |||||
| with open(wav_file_path, 'wb') as f: | |||||
| f.write(r.content) | |||||
| # get wav file | |||||
| wav_file_path = POS_WAV_FILE | |||||
| # downloading kwsbp | # downloading kwsbp | ||||
| kwsbp_file_path = os.path.join(self.workspace, 'kwsbp') | kwsbp_file_path = os.path.join(self.workspace, 'kwsbp') | ||||
| @@ -70,6 +66,7 @@ class KeyWordSpottingTest(unittest.TestCase): | |||||
| self.assertTrue(preprocessor is not None) | self.assertTrue(preprocessor is not None) | ||||
| kwsbp_16k_pipline = pipeline( | kwsbp_16k_pipline = pipeline( | ||||
| task=Tasks.key_word_spotting, | |||||
| pipeline_name=Pipelines.kws_kwsbp, | pipeline_name=Pipelines.kws_kwsbp, | ||||
| model=model, | model=model, | ||||
| preprocessor=preprocessor) | preprocessor=preprocessor) | ||||
| @@ -91,9 +88,73 @@ class KeyWordSpottingTest(unittest.TestCase): | |||||
| """ | """ | ||||
| if kws_result.__contains__('keywords'): | if kws_result.__contains__('keywords'): | ||||
| print('test_run_with_wav keywords: ', kws_result['keywords']) | print('test_run_with_wav keywords: ', kws_result['keywords']) | ||||
| print('test_run_with_wav confidence: ', kws_result['confidence']) | |||||
| print('test_run_with_wav detected result: ', kws_result['detected']) | print('test_run_with_wav detected result: ', kws_result['detected']) | ||||
| print('test_run_with_wav wave time(seconds): ', kws_result['wav_time']) | print('test_run_with_wav wave time(seconds): ', kws_result['wav_time']) | ||||
| @unittest.skipUnless(test_level() >= 0, 'skip test in current test level') | |||||
| def test_run_with_wav_by_customized_keywords(self): | |||||
| # wav, neg_testsets, pos_testsets, roc | |||||
| kws_set = 'wav' | |||||
| # get wav file | |||||
| wav_file_path = BOFANGYINYUE_WAV_FILE | |||||
| # downloading kwsbp | |||||
| kwsbp_file_path = os.path.join(self.workspace, 'kwsbp') | |||||
| if not os.path.exists(kwsbp_file_path): | |||||
| r = requests.get(KWSBP_URL) | |||||
| with open(kwsbp_file_path, 'wb') as f: | |||||
| f.write(r.content) | |||||
| model = Model.from_pretrained(self.model_id) | |||||
| self.assertTrue(model is not None) | |||||
| cfg_preprocessor = dict( | |||||
| type=Preprocessors.wav_to_lists, workspace=self.workspace) | |||||
| preprocessor = build_preprocessor(cfg_preprocessor, Fields.audio) | |||||
| self.assertTrue(preprocessor is not None) | |||||
| # customized keyword if you need. | |||||
| # full settings eg. | |||||
| # keywords = [ | |||||
| # {'keyword':'你好电视', 'threshold': 0.008}, | |||||
| # {'keyword':'播放音乐', 'threshold': 0.008} | |||||
| # ] | |||||
| keywords = [{'keyword': '播放音乐'}] | |||||
| kwsbp_16k_pipline = pipeline( | |||||
| task=Tasks.key_word_spotting, | |||||
| pipeline_name=Pipelines.kws_kwsbp, | |||||
| model=model, | |||||
| preprocessor=preprocessor, | |||||
| keywords=keywords) | |||||
| self.assertTrue(kwsbp_16k_pipline is not None) | |||||
| kws_result = kwsbp_16k_pipline( | |||||
| kws_type=kws_set, wav_path=[wav_file_path, None]) | |||||
| self.assertTrue(kws_result.__contains__('detected')) | |||||
| """ | |||||
| kws result json format example: | |||||
| { | |||||
| 'wav_count': 1, | |||||
| 'kws_set': 'wav', | |||||
| 'wav_time': 9.132938, | |||||
| 'keywords': ['播放音乐'], | |||||
| 'detected': True, | |||||
| 'confidence': 0.660368 | |||||
| } | |||||
| """ | |||||
| if kws_result.__contains__('keywords'): | |||||
| print('test_run_with_wav_by_customized_keywords keywords: ', | |||||
| kws_result['keywords']) | |||||
| print('test_run_with_wav_by_customized_keywords confidence: ', | |||||
| kws_result['confidence']) | |||||
| print('test_run_with_wav_by_customized_keywords detected result: ', | |||||
| kws_result['detected']) | |||||
| print('test_run_with_wav_by_customized_keywords wave time(seconds): ', | |||||
| kws_result['wav_time']) | |||||
| @unittest.skipUnless(test_level() >= 1, 'skip test in current test level') | @unittest.skipUnless(test_level() >= 1, 'skip test in current test level') | ||||
| def test_run_with_pos_testsets(self): | def test_run_with_pos_testsets(self): | ||||
| # wav, neg_testsets, pos_testsets, roc | # wav, neg_testsets, pos_testsets, roc | ||||
| @@ -133,6 +194,7 @@ class KeyWordSpottingTest(unittest.TestCase): | |||||
| self.assertTrue(preprocessor is not None) | self.assertTrue(preprocessor is not None) | ||||
| kwsbp_16k_pipline = pipeline( | kwsbp_16k_pipline = pipeline( | ||||
| task=Tasks.key_word_spotting, | |||||
| pipeline_name=Pipelines.kws_kwsbp, | pipeline_name=Pipelines.kws_kwsbp, | ||||
| model=model, | model=model, | ||||
| preprocessor=preprocessor) | preprocessor=preprocessor) | ||||
| @@ -204,6 +266,7 @@ class KeyWordSpottingTest(unittest.TestCase): | |||||
| self.assertTrue(preprocessor is not None) | self.assertTrue(preprocessor is not None) | ||||
| kwsbp_16k_pipline = pipeline( | kwsbp_16k_pipline = pipeline( | ||||
| task=Tasks.key_word_spotting, | |||||
| pipeline_name=Pipelines.kws_kwsbp, | pipeline_name=Pipelines.kws_kwsbp, | ||||
| model=model, | model=model, | ||||
| preprocessor=preprocessor) | preprocessor=preprocessor) | ||||
| @@ -298,6 +361,7 @@ class KeyWordSpottingTest(unittest.TestCase): | |||||
| self.assertTrue(preprocessor is not None) | self.assertTrue(preprocessor is not None) | ||||
| kwsbp_16k_pipline = pipeline( | kwsbp_16k_pipline = pipeline( | ||||
| task=Tasks.key_word_spotting, | |||||
| pipeline_name=Pipelines.kws_kwsbp, | pipeline_name=Pipelines.kws_kwsbp, | ||||
| model=model, | model=model, | ||||
| preprocessor=preprocessor) | preprocessor=preprocessor) | ||||
| @@ -7,6 +7,7 @@ import cv2 | |||||
| from modelscope.pipelines import pipeline | from modelscope.pipelines import pipeline | ||||
| from modelscope.pipelines.base import Pipeline | from modelscope.pipelines.base import Pipeline | ||||
| from modelscope.pipelines.outputs import OutputKeys | |||||
| from modelscope.utils.constant import Tasks | from modelscope.utils.constant import Tasks | ||||
| from modelscope.utils.test_utils import test_level | from modelscope.utils.test_utils import test_level | ||||
| @@ -22,7 +23,7 @@ class ImageCartoonTest(unittest.TestCase): | |||||
| def pipeline_inference(self, pipeline: Pipeline, input_location: str): | def pipeline_inference(self, pipeline: Pipeline, input_location: str): | ||||
| result = pipeline(input_location) | result = pipeline(input_location) | ||||
| if result is not None: | if result is not None: | ||||
| cv2.imwrite('result.png', result['output_png']) | |||||
| cv2.imwrite('result.png', result[OutputKeys.OUTPUT_IMG]) | |||||
| print(f'Output written to {osp.abspath("result.png")}') | print(f'Output written to {osp.abspath("result.png")}') | ||||
| @unittest.skip('deprecated, download model from model hub instead') | @unittest.skip('deprecated, download model from model hub instead') | ||||
| @@ -12,7 +12,7 @@ from modelscope.metainfo import Pipelines, Preprocessors | |||||
| from modelscope.models import Model | from modelscope.models import Model | ||||
| from modelscope.pipelines import pipeline | from modelscope.pipelines import pipeline | ||||
| from modelscope.preprocessors import build_preprocessor | from modelscope.preprocessors import build_preprocessor | ||||
| from modelscope.utils.constant import Fields | |||||
| from modelscope.utils.constant import Fields, Tasks | |||||
| from modelscope.utils.logger import get_logger | from modelscope.utils.logger import get_logger | ||||
| from modelscope.utils.test_utils import test_level | from modelscope.utils.test_utils import test_level | ||||
| @@ -43,6 +43,7 @@ class TextToSpeechSambertHifigan16kPipelineTest(unittest.TestCase): | |||||
| self.assertTrue(voc is not None) | self.assertTrue(voc is not None) | ||||
| sambert_tts = pipeline( | sambert_tts = pipeline( | ||||
| task=Tasks.text_to_speech, | |||||
| pipeline_name=Pipelines.sambert_hifigan_16k_tts, | pipeline_name=Pipelines.sambert_hifigan_16k_tts, | ||||
| config_file='', | config_file='', | ||||
| model=[am, voc], | model=[am, voc], | ||||
| @@ -0,0 +1,22 @@ | |||||
| # Copyright (c) Alibaba, Inc. and its affiliates. | |||||
| import unittest | |||||
| from typing import List, Union | |||||
| from modelscope.utils.check_requirements import NLPModuleNotFoundError, get_msg | |||||
| from modelscope.utils.constant import Fields | |||||
| class ImportUtilsTest(unittest.TestCase): | |||||
| def test_type_module_not_found(self): | |||||
| with self.assertRaises(NLPModuleNotFoundError) as ctx: | |||||
| try: | |||||
| import not_found | |||||
| except ModuleNotFoundError as e: | |||||
| raise NLPModuleNotFoundError(e) | |||||
| self.assertTrue(get_msg(Fields.nlp) in ctx.exception.msg.msg) | |||||
| if __name__ == '__main__': | |||||
| unittest.main() | |||||