mirror of
https://github.com/modelscope/modelscope.git
synced 2025-12-16 16:27:45 +01:00
swing deploy api
Link: https://code.alibaba-inc.com/Ali-MaaS/MaaS-lib/codereview/14103985 * tester * bug fixed: download_file not import * input example analyzer * api: get_task_input_examples * update chat * 43 task * fix decode_base64 * json format * schema
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
recursive-include modelscope/configs *.py *.cu *.h *.cpp
|
recursive-include modelscope/configs *.py *.cu *.h *.cpp
|
||||||
recursive-include modelscope/cli/template *.tpl
|
recursive-include modelscope/cli/template *.tpl
|
||||||
|
recursive-include modelscope/utils *.json
|
||||||
|
|||||||
@@ -82,6 +82,34 @@ def check_input_type(input_type, input):
|
|||||||
|
|
||||||
|
|
||||||
TASK_INPUTS = {
|
TASK_INPUTS = {
|
||||||
|
Tasks.image_text_retrieval: {
|
||||||
|
InputKeys.IMAGE: InputType.IMAGE,
|
||||||
|
InputKeys.TEXT: InputType.TEXT
|
||||||
|
},
|
||||||
|
Tasks.general_recognition: {
|
||||||
|
InputKeys.IMAGE: InputType.IMAGE,
|
||||||
|
InputKeys.TEXT: InputType.TEXT
|
||||||
|
},
|
||||||
|
Tasks.video_depth_estimation: {
|
||||||
|
InputKeys.IMAGE: InputType.IMAGE,
|
||||||
|
InputKeys.TEXT: InputType.TEXT
|
||||||
|
},
|
||||||
|
Tasks.indoor_layout_estimation:
|
||||||
|
InputType.IMAGE,
|
||||||
|
Tasks.image_demoireing:
|
||||||
|
InputType.IMAGE,
|
||||||
|
Tasks.panorama_depth_estimation:
|
||||||
|
InputType.IMAGE,
|
||||||
|
Tasks.video_depth_estimation:
|
||||||
|
InputType.VIDEO,
|
||||||
|
Tasks.animal_recognition:
|
||||||
|
InputType.IMAGE,
|
||||||
|
Tasks.motion_generation:
|
||||||
|
InputType.TEXT,
|
||||||
|
Tasks.video_panoptic_segmentation:
|
||||||
|
InputType.VIDEO,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Tasks.task_template: {
|
Tasks.task_template: {
|
||||||
'image': InputType.IMAGE,
|
'image': InputType.IMAGE,
|
||||||
|
|||||||
@@ -297,12 +297,11 @@ class ChatGLM6bV2TextGenerationPipeline(Pipeline):
|
|||||||
class QWenChatPipeline(Pipeline):
|
class QWenChatPipeline(Pipeline):
|
||||||
|
|
||||||
def __init__(self, model: Union[Model, str], **kwargs):
|
def __init__(self, model: Union[Model, str], **kwargs):
|
||||||
from modelscope.models.nlp import (QWenConfig, QWenForTextGeneration,
|
from modelscope import AutoModelForCausalLM, AutoTokenizer
|
||||||
QWenTokenizer)
|
|
||||||
torch_dtype = kwargs.get('torch_dtype', torch.bfloat16)
|
torch_dtype = kwargs.get('torch_dtype', torch.bfloat16)
|
||||||
device_map = kwargs.get('device_map', 'auto')
|
device_map = kwargs.get('device_map', 'auto')
|
||||||
use_max_memory = kwargs.get('use_max_memory', False)
|
use_max_memory = kwargs.get('use_max_memory', False)
|
||||||
quantization_config = kwargs.get('quantization_config', None)
|
revision = kwargs.get('model_revision', 'v.1.0.5')
|
||||||
|
|
||||||
if use_max_memory:
|
if use_max_memory:
|
||||||
max_memory = f'{int(torch.cuda.mem_get_info()[0] / 1024 ** 3) - 2}GB'
|
max_memory = f'{int(torch.cuda.mem_get_info()[0] / 1024 ** 3) - 2}GB'
|
||||||
@@ -310,31 +309,24 @@ class QWenChatPipeline(Pipeline):
|
|||||||
max_memory = {i: max_memory for i in range(n_gpus)}
|
max_memory = {i: max_memory for i in range(n_gpus)}
|
||||||
else:
|
else:
|
||||||
max_memory = None
|
max_memory = None
|
||||||
|
if torch_dtype == 'bf16' or torch_dtype == torch.bfloat16:
|
||||||
|
bf16 = True
|
||||||
|
else:
|
||||||
|
bf16 = False
|
||||||
|
|
||||||
if isinstance(model, str):
|
if isinstance(model, str):
|
||||||
model_dir = snapshot_download(
|
self.tokenizer = AutoTokenizer.from_pretrained(
|
||||||
model) if not os.path.exists(model) else model
|
model, revision=revision, trust_remote_code=True)
|
||||||
|
self.model = AutoModelForCausalLM.from_pretrained(
|
||||||
config = read_config(model_dir)
|
model,
|
||||||
model_config = QWenConfig.from_pretrained(model_dir)
|
|
||||||
model_config.torch_dtype = torch_dtype
|
|
||||||
|
|
||||||
model = QWenForTextGeneration.from_pretrained(
|
|
||||||
model_dir,
|
|
||||||
cfg_dict=config,
|
|
||||||
config=model_config,
|
|
||||||
device_map=device_map,
|
device_map=device_map,
|
||||||
torch_dtype=torch_dtype,
|
revision=revision,
|
||||||
quantization_config=quantization_config,
|
trust_remote_code=True,
|
||||||
max_memory=max_memory)
|
fp16=bf16).eval()
|
||||||
model.generation_config = GenerationConfig.from_pretrained(
|
self.model.generation_config = GenerationConfig.from_pretrained(
|
||||||
model_dir)
|
model, trust_remote_code=True) # 可指定不同的生成长度、top_p等相关超参
|
||||||
|
|
||||||
self.model = model
|
super().__init__(model=self.model, **kwargs)
|
||||||
self.model.eval()
|
|
||||||
self.tokenizer = QWenTokenizer.from_pretrained(self.model.model_dir)
|
|
||||||
|
|
||||||
super().__init__(model=model, **kwargs)
|
|
||||||
# skip pipeline model placement
|
# skip pipeline model placement
|
||||||
self._model_prepare = True
|
self._model_prepare = True
|
||||||
|
|
||||||
@@ -345,12 +337,19 @@ class QWenChatPipeline(Pipeline):
|
|||||||
return inputs
|
return inputs
|
||||||
|
|
||||||
# define the forward pass
|
# define the forward pass
|
||||||
def forward(self, inputs: str, **forward_params) -> Dict[str, Any]:
|
def forward(self, inputs: Union[Dict, str],
|
||||||
history = forward_params.get('history', None)
|
**forward_params) -> Dict[str, Any]:
|
||||||
|
if isinstance(inputs, Dict):
|
||||||
|
text = inputs.get('text', None)
|
||||||
|
history = inputs.get('history', None)
|
||||||
|
else:
|
||||||
|
text = inputs
|
||||||
|
history = forward_params.get('history', None)
|
||||||
system = forward_params.get('system', 'You are a helpful assistant.')
|
system = forward_params.get('system', 'You are a helpful assistant.')
|
||||||
append_history = forward_params.get('append_history', True)
|
append_history = forward_params.get('append_history', True)
|
||||||
return self.model.chat(self.tokenizer, inputs, history, system,
|
res = self.model.chat(self.tokenizer, text, history, system,
|
||||||
append_history)
|
append_history)
|
||||||
|
return {'response': res[0], 'history': res[1]}
|
||||||
|
|
||||||
# format the outputs from pipeline
|
# format the outputs from pipeline
|
||||||
def postprocess(self, input, **kwargs) -> Dict[str, Any]:
|
def postprocess(self, input, **kwargs) -> Dict[str, Any]:
|
||||||
@@ -362,12 +361,11 @@ class QWenChatPipeline(Pipeline):
|
|||||||
class QWenTextGenerationPipeline(Pipeline):
|
class QWenTextGenerationPipeline(Pipeline):
|
||||||
|
|
||||||
def __init__(self, model: Union[Model, str], **kwargs):
|
def __init__(self, model: Union[Model, str], **kwargs):
|
||||||
from modelscope.models.nlp import (QWenConfig, QWenForTextGeneration,
|
from modelscope import AutoModelForCausalLM, AutoTokenizer
|
||||||
QWenTokenizer)
|
|
||||||
torch_dtype = kwargs.get('torch_dtype', torch.bfloat16)
|
torch_dtype = kwargs.get('torch_dtype', torch.bfloat16)
|
||||||
device_map = kwargs.get('device_map', 'auto')
|
device_map = kwargs.get('device_map', 'auto')
|
||||||
use_max_memory = kwargs.get('use_max_memory', False)
|
use_max_memory = kwargs.get('use_max_memory', False)
|
||||||
quantization_config = kwargs.get('quantization_config', None)
|
revision = kwargs.get('model_revision', 'v.1.0.4')
|
||||||
|
|
||||||
if use_max_memory:
|
if use_max_memory:
|
||||||
max_memory = f'{int(torch.cuda.mem_get_info()[0] / 1024 ** 3) - 2}GB'
|
max_memory = f'{int(torch.cuda.mem_get_info()[0] / 1024 ** 3) - 2}GB'
|
||||||
@@ -375,31 +373,27 @@ class QWenTextGenerationPipeline(Pipeline):
|
|||||||
max_memory = {i: max_memory for i in range(n_gpus)}
|
max_memory = {i: max_memory for i in range(n_gpus)}
|
||||||
else:
|
else:
|
||||||
max_memory = None
|
max_memory = None
|
||||||
|
if torch_dtype == 'bf16' or torch_dtype == torch.bfloat16:
|
||||||
|
bf16 = True
|
||||||
|
else:
|
||||||
|
bf16 = False
|
||||||
|
|
||||||
if isinstance(model, str):
|
if isinstance(model, str):
|
||||||
model_dir = snapshot_download(
|
self.model = AutoModelForCausalLM.from_pretrained(
|
||||||
model) if not os.path.exists(model) else model
|
model,
|
||||||
|
|
||||||
config = read_config(model_dir)
|
|
||||||
model_config = QWenConfig.from_pretrained(model_dir)
|
|
||||||
model_config.torch_dtype = torch_dtype
|
|
||||||
|
|
||||||
model = QWenForTextGeneration.from_pretrained(
|
|
||||||
model_dir,
|
|
||||||
cfg_dict=config,
|
|
||||||
config=model_config,
|
|
||||||
device_map=device_map,
|
device_map=device_map,
|
||||||
torch_dtype=torch_dtype,
|
revision=revision,
|
||||||
quantization_config=quantization_config,
|
trust_remote_code=True,
|
||||||
max_memory=max_memory)
|
bf16=bf16).eval()
|
||||||
model.generation_config = GenerationConfig.from_pretrained(
|
self.tokenizer = AutoTokenizer.from_pretrained(
|
||||||
model_dir)
|
model, revision=revision, trust_remote_code=True)
|
||||||
|
self.model.generation_config = GenerationConfig.from_pretrained(
|
||||||
|
model)
|
||||||
|
else:
|
||||||
|
self.model = model
|
||||||
|
self.tokenizer = kwargs.get('tokenizer', None)
|
||||||
|
|
||||||
self.model = model
|
super().__init__(model=self.model, **kwargs)
|
||||||
self.model.eval()
|
|
||||||
self.tokenizer = QWenTokenizer.from_pretrained(self.model.model_dir)
|
|
||||||
|
|
||||||
super().__init__(model=model, **kwargs)
|
|
||||||
# skip pipeline model placement
|
# skip pipeline model placement
|
||||||
self._model_prepare = True
|
self._model_prepare = True
|
||||||
|
|
||||||
@@ -411,10 +405,12 @@ class QWenTextGenerationPipeline(Pipeline):
|
|||||||
|
|
||||||
# define the forward pass
|
# define the forward pass
|
||||||
def forward(self, inputs: str, **forward_params) -> Dict[str, Any]:
|
def forward(self, inputs: str, **forward_params) -> Dict[str, Any]:
|
||||||
|
inputs = self.tokenizer(inputs, return_tensors='pt').to('cuda:0')
|
||||||
return {
|
return {
|
||||||
OutputKeys.TEXT:
|
OutputKeys.TEXT:
|
||||||
self.model.chat(self.tokenizer, inputs,
|
self.tokenizer.decode(
|
||||||
history=None)[OutputKeys.RESPONSE]
|
self.model.generate(**inputs).cpu()[0],
|
||||||
|
skip_special_tokens=True)
|
||||||
}
|
}
|
||||||
|
|
||||||
# format the outputs from pipeline
|
# format the outputs from pipeline
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from PIL import Image, ImageOps
|
|||||||
|
|
||||||
from modelscope.fileio import File
|
from modelscope.fileio import File
|
||||||
from modelscope.metainfo import Preprocessors
|
from modelscope.metainfo import Preprocessors
|
||||||
|
from modelscope.pipeline_inputs import InputKeys
|
||||||
from modelscope.utils.constant import Fields
|
from modelscope.utils.constant import Fields
|
||||||
from modelscope.utils.type_assert import type_assert
|
from modelscope.utils.type_assert import type_assert
|
||||||
from .base import Preprocessor
|
from .base import Preprocessor
|
||||||
@@ -92,6 +93,10 @@ class LoadImage:
|
|||||||
if len(input.shape) == 2:
|
if len(input.shape) == 2:
|
||||||
input = cv2.cvtColor(input, cv2.COLOR_GRAY2BGR)
|
input = cv2.cvtColor(input, cv2.COLOR_GRAY2BGR)
|
||||||
img = input[:, :, ::-1]
|
img = input[:, :, ::-1]
|
||||||
|
elif isinstance(input, Dict):
|
||||||
|
img = input.get(InputKeys.IMAGE, None)
|
||||||
|
if img:
|
||||||
|
img = np.array(load_image(img))
|
||||||
else:
|
else:
|
||||||
raise TypeError(f'input should be either str, PIL.Image,'
|
raise TypeError(f'input should be either str, PIL.Image,'
|
||||||
f' np.array, but got {type(input)}')
|
f' np.array, but got {type(input)}')
|
||||||
@@ -108,6 +113,10 @@ class LoadImage:
|
|||||||
img = cv2.cvtColor(input, cv2.COLOR_GRAY2BGR)
|
img = cv2.cvtColor(input, cv2.COLOR_GRAY2BGR)
|
||||||
img = input[:, :, ::-1]
|
img = input[:, :, ::-1]
|
||||||
img = Image.fromarray(img.astype('uint8')).convert('RGB')
|
img = Image.fromarray(img.astype('uint8')).convert('RGB')
|
||||||
|
elif isinstance(input, Dict):
|
||||||
|
img = input.get(InputKeys.IMAGE, None)
|
||||||
|
if img:
|
||||||
|
img = load_image(img)
|
||||||
else:
|
else:
|
||||||
raise TypeError(f'input should be either str, PIL.Image,'
|
raise TypeError(f'input should be either str, PIL.Image,'
|
||||||
f' np.array, but got {type(input)}')
|
f' np.array, but got {type(input)}')
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import ast
|
|||||||
import base64
|
import base64
|
||||||
import importlib
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
|
import os
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
|
import json
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from modelscope.hub.api import HubApi
|
from modelscope.hub.api import HubApi
|
||||||
@@ -243,6 +245,33 @@ def process_arg_type_annotation(arg, default_value):
|
|||||||
return arg.arg, 'object'
|
return arg.arg, 'object'
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_value(item):
|
||||||
|
if isinstance(item, ast.Str):
|
||||||
|
return item.s
|
||||||
|
elif hasattr(ast, 'Bytes') and isinstance(item, ast.Bytes):
|
||||||
|
return item.s
|
||||||
|
elif isinstance(item, ast.Tuple):
|
||||||
|
return tuple(convert_to_value(i) for i in item.elts)
|
||||||
|
elif isinstance(item, ast.Num):
|
||||||
|
return item.n
|
||||||
|
elif isinstance(item, ast.Name):
|
||||||
|
result = VariableKey(item=item)
|
||||||
|
constants_lookup = {
|
||||||
|
'True': True,
|
||||||
|
'False': False,
|
||||||
|
'None': None,
|
||||||
|
}
|
||||||
|
return constants_lookup.get(
|
||||||
|
result.name,
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
elif isinstance(item, ast.NameConstant):
|
||||||
|
# None, True, False are nameconstants in python3, but names in 2
|
||||||
|
return item.value
|
||||||
|
else:
|
||||||
|
return UnhandledKeyType()
|
||||||
|
|
||||||
|
|
||||||
def process_args(args):
|
def process_args(args):
|
||||||
arguments = []
|
arguments = []
|
||||||
# name, type, has_default, default
|
# name, type, has_default, default
|
||||||
@@ -259,7 +288,7 @@ def process_args(args):
|
|||||||
# process defaults arg.
|
# process defaults arg.
|
||||||
for arg, dft in zip(args.args[n_args - n_args_default:], args.defaults):
|
for arg, dft in zip(args.args[n_args - n_args_default:], args.defaults):
|
||||||
# compatible with python3.7 ast.Num no value.
|
# compatible with python3.7 ast.Num no value.
|
||||||
value = dft.value if hasattr(dft, 'value') else dft.n
|
value = convert_to_value(dft)
|
||||||
arg_name, arg_type = process_arg_type_annotation(arg, value)
|
arg_name, arg_type = process_arg_type_annotation(arg, value)
|
||||||
arguments.append((arg_name, arg_type, True, value))
|
arguments.append((arg_name, arg_type, True, value))
|
||||||
|
|
||||||
@@ -398,7 +427,7 @@ meta_type_schema_map = {
|
|||||||
|
|
||||||
def generate_pipeline_parameters_schema(parameters):
|
def generate_pipeline_parameters_schema(parameters):
|
||||||
parameters_schema = {'type': 'object', 'properties': {}}
|
parameters_schema = {'type': 'object', 'properties': {}}
|
||||||
if len(parameters) == 0:
|
if parameters is None or len(parameters) == 0:
|
||||||
return {}
|
return {}
|
||||||
for param in parameters:
|
for param in parameters:
|
||||||
name, param_type, has_default, default_value = param
|
name, param_type, has_default, default_value = param
|
||||||
@@ -523,16 +552,18 @@ def is_url(url: str):
|
|||||||
|
|
||||||
|
|
||||||
def decode_base64_to_image(content):
|
def decode_base64_to_image(content):
|
||||||
if content.startswith('http') or content.startswith('oss'):
|
if content.startswith('http') or content.startswith(
|
||||||
|
'oss') or os.path.exists(content):
|
||||||
return content
|
return content
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
image_file_content = base64.b64decode(content)
|
image_file_content = base64.b64decode(content, '-_')
|
||||||
return Image.open(BytesIO(image_file_content))
|
return Image.open(BytesIO(image_file_content))
|
||||||
|
|
||||||
|
|
||||||
def decode_base64_to_audio(content):
|
def decode_base64_to_audio(content):
|
||||||
if content.startswith('http') or content.startswith('oss'):
|
if content.startswith('http') or content.startswith(
|
||||||
|
'oss') or os.path.exists(content):
|
||||||
return content
|
return content
|
||||||
|
|
||||||
file_content = base64.b64decode(content)
|
file_content = base64.b64decode(content)
|
||||||
@@ -540,7 +571,8 @@ def decode_base64_to_audio(content):
|
|||||||
|
|
||||||
|
|
||||||
def decode_base64_to_video(content):
|
def decode_base64_to_video(content):
|
||||||
if content.startswith('http') or content.startswith('oss'):
|
if content.startswith('http') or content.startswith(
|
||||||
|
'oss') or os.path.exists(content):
|
||||||
return content
|
return content
|
||||||
|
|
||||||
file_content = base64.b64decode(content)
|
file_content = base64.b64decode(content)
|
||||||
@@ -594,13 +626,14 @@ def call_pipeline_with_json(pipeline_info: PipelineInfomation,
|
|||||||
pipeline (Pipeline): The pipeline object.
|
pipeline (Pipeline): The pipeline object.
|
||||||
body (Dict): The input object, include input and parameters
|
body (Dict): The input object, include input and parameters
|
||||||
"""
|
"""
|
||||||
if pipeline_info.is_custom_call:
|
# TODO: is_custom_call misjudgment
|
||||||
pipeline_inputs = body['input']
|
# if pipeline_info.is_custom_call:
|
||||||
result = pipeline(**pipeline_inputs)
|
# pipeline_inputs = body['input']
|
||||||
else:
|
# result = pipeline(**pipeline_inputs)
|
||||||
pipeline_inputs, parameters = service_base64_input_to_pipeline_input(
|
# else:
|
||||||
pipeline_info.task_name, body)
|
pipeline_inputs, parameters = service_base64_input_to_pipeline_input(
|
||||||
result = pipeline(pipeline_inputs, **parameters)
|
pipeline_info.task_name, body)
|
||||||
|
result = pipeline(pipeline_inputs, **parameters)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -737,6 +770,9 @@ def pipeline_output_to_service_base64_output(task_name, pipeline_output):
|
|||||||
task_outputs = []
|
task_outputs = []
|
||||||
if task_name in TASK_OUTPUTS:
|
if task_name in TASK_OUTPUTS:
|
||||||
task_outputs = TASK_OUTPUTS[task_name]
|
task_outputs = TASK_OUTPUTS[task_name]
|
||||||
|
# TODO: for batch
|
||||||
|
if isinstance(pipeline_output, list):
|
||||||
|
pipeline_output = pipeline_output[0]
|
||||||
for key, value in pipeline_output.items():
|
for key, value in pipeline_output.items():
|
||||||
if key not in task_outputs:
|
if key not in task_outputs:
|
||||||
continue # skip the output not defined.
|
continue # skip the output not defined.
|
||||||
@@ -768,3 +804,77 @@ def pipeline_output_to_service_base64_output(task_name, pipeline_output):
|
|||||||
json_serializable_output[key] = value
|
json_serializable_output[key] = value
|
||||||
|
|
||||||
return _convert_to_python_type(json_serializable_output)
|
return _convert_to_python_type(json_serializable_output)
|
||||||
|
|
||||||
|
|
||||||
|
def get_task_input_examples(task):
|
||||||
|
current_work_dir = os.path.dirname(__file__)
|
||||||
|
with open(current_work_dir + '/pipeline_inputs.json', 'r') as f:
|
||||||
|
input_examples = json.load(f)
|
||||||
|
if task in input_examples:
|
||||||
|
return input_examples[task]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_task_schemas(task):
|
||||||
|
current_work_dir = os.path.dirname(__file__)
|
||||||
|
with open(current_work_dir + '/pipeline_schema.json', 'r') as f:
|
||||||
|
schema = json.load(f)
|
||||||
|
if task in schema:
|
||||||
|
return schema[task]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from modelscope.utils.ast_utils import load_index
|
||||||
|
index = load_index()
|
||||||
|
task_schemas = {}
|
||||||
|
for key, value in index['index'].items():
|
||||||
|
reg, task_name, class_name = key
|
||||||
|
if reg == 'PIPELINES' and task_name != 'default':
|
||||||
|
print(
|
||||||
|
f"value['filepath']: {value['filepath']}, class_name: {class_name}"
|
||||||
|
)
|
||||||
|
input, parameters = get_pipeline_input_parameters(
|
||||||
|
value['filepath'], class_name)
|
||||||
|
try:
|
||||||
|
if task_name in TASK_INPUTS and task_name in TASK_OUTPUTS:
|
||||||
|
# delete the first default input which is defined by task.
|
||||||
|
# parameters.pop(0)
|
||||||
|
parameters_schema = generate_pipeline_parameters_schema(
|
||||||
|
parameters)
|
||||||
|
input_schema = get_input_schema(task_name, None)
|
||||||
|
output_schema = get_output_schema(task_name)
|
||||||
|
schema = {
|
||||||
|
'input': input_schema,
|
||||||
|
'parameters': parameters_schema,
|
||||||
|
'output': output_schema
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
'Task: %s input is defined: %s, output is defined: %s which is not completed'
|
||||||
|
% (task_name, task_name in TASK_INPUTS, task_name
|
||||||
|
in TASK_OUTPUTS))
|
||||||
|
input_schema = None
|
||||||
|
output_schema = None
|
||||||
|
if task_name in TASK_INPUTS:
|
||||||
|
input_schema = get_input_schema(task_name, None)
|
||||||
|
if task_name in TASK_OUTPUTS:
|
||||||
|
output_schema = get_output_schema(task_name)
|
||||||
|
parameters_schema = generate_pipeline_parameters_schema(
|
||||||
|
parameters)
|
||||||
|
schema = {
|
||||||
|
'input': input_schema if input_schema else
|
||||||
|
parameters_schema, # all parameter is input
|
||||||
|
'parameters':
|
||||||
|
parameters_schema if input_schema else {},
|
||||||
|
'output': output_schema if output_schema else {
|
||||||
|
'type': 'object',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
except BaseException:
|
||||||
|
continue
|
||||||
|
task_schemas[task_name] = schema
|
||||||
|
|
||||||
|
s = json.dumps(task_schemas)
|
||||||
|
with open('./task_schema.json', 'w') as f:
|
||||||
|
f.write(s)
|
||||||
|
|||||||
277
modelscope/utils/pipeline_inputs.json
Normal file
277
modelscope/utils/pipeline_inputs.json
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
{
|
||||||
|
"action-detection":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/action_detection_test_video.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"action-recognition":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/action_recognition_test_video.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"animal-recognition":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/dogs.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chat":{
|
||||||
|
"input":{
|
||||||
|
"text":"你有什么推荐吗?",
|
||||||
|
"history":[
|
||||||
|
[
|
||||||
|
"今天天气真好,",
|
||||||
|
"今天天气真好,出去走走怎么样?"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"domain-specific-object-detection":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_traffic_sign.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"face-2d-keypoints":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/face_detection.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"face-attribute-recognition":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/face_recognition_1.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"facial-expression-recognition":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/facial_expression_recognition.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"general-recognition":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/dogs.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"human-detection":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_detection.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-captioning":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_captioning.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-classification":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/content_check.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-demoireing":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/shop_segmentation.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-object-detection":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_detection.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-portrait-stylization":{
|
||||||
|
"input":{
|
||||||
|
"image":"https://modelscope.oss-cn-beijing.aliyuncs.com/test/images/image_cartoon.png"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-segmentation":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_semantic_segmentation.jpg"
|
||||||
|
},
|
||||||
|
"parameters":{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"image-text-retrieval":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_mplug_vqa.jpg",
|
||||||
|
"text":"What is the woman doing?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indoor-layout-estimation":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_traffic_sign.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"live-category":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/live_category_test_video.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"motion-generation":{
|
||||||
|
"input":{
|
||||||
|
"text":"the person walked forward and is picking up his toolbox"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"named-entity-recognition":{
|
||||||
|
"input":{
|
||||||
|
"text":"这与温岭市新河镇的一个神秘的传说有关。[SEP]地名"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nli":{
|
||||||
|
"input":[
|
||||||
|
"四川商务职业学院和四川财经职业学院哪个好?",
|
||||||
|
"四川商务职业学院商务管理在哪个校区?"
|
||||||
|
],
|
||||||
|
"parameters":{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ocr-recognition":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_ocr_recognition.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"panorama-depth-estimation":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/panorama_depth_estimation.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semantic-segmentation":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_salient_detection.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shop-segmentation":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/shop_segmentation.jpg"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-classification":{
|
||||||
|
"input":{
|
||||||
|
"text":"i like this wonderful place"
|
||||||
|
},
|
||||||
|
"parameters":{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-driven-segmentation":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/text_driven_segmentation.jpg",
|
||||||
|
"text":"bear"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-generation":{
|
||||||
|
"input":{
|
||||||
|
"text":"蒙古国的首都是乌兰巴托(Ulaanbaatar)\n冰岛的首都是雷克雅未克(Reykjavik)\n埃塞俄比亚的首都是"
|
||||||
|
},
|
||||||
|
"parameters":{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-ranking":{
|
||||||
|
"input":{
|
||||||
|
"source_sentence":[
|
||||||
|
"how long it take to get a master's degree"
|
||||||
|
],
|
||||||
|
"sentences_to_compare":[
|
||||||
|
"On average, students take about 18 to 24 months to complete a master's degree.",
|
||||||
|
"On the other hand, some students prefer to go at a slower pace and choose to take several years to complete their studies.",
|
||||||
|
"It can take anywhere from two semesters"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-summarization":{
|
||||||
|
"input":{
|
||||||
|
"text":"five-time world champion michelle kwan withdrew from the #### us figure skating championships on wednesday , but will petition us skating officials for the chance to compete at the #### turin olympics ."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text-to-video-synthesis":{
|
||||||
|
"input":{
|
||||||
|
"text":"A panda eating bamboo on a rock."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"translation":{
|
||||||
|
"input":{
|
||||||
|
"text":"声明补充说,沃伦的同事都深感震惊,并且希望他能够投案自首。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-captioning":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/video_caption_and_qa_test.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-category":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/video_category_test_video.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-depth-estimation":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/video_depth_estimation.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-embedding":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/action_recognition_test_video.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-multi-object-tracking":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/MOT17-03-partial.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-panoptic-segmentation":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/kitti-step_testing_image_02_0000.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-question-answering":{
|
||||||
|
"input":{
|
||||||
|
"video":"data/test/videos/video_caption_and_qa_test.mp4",
|
||||||
|
"text":"How many people are there?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"video-summarization":{
|
||||||
|
"input":{
|
||||||
|
"text":"data/test/videos/video_category_test_video.mp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"visual-entailment":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/dogs.jpg",
|
||||||
|
"text":"there are two birds."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"visual-grounding":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/visual_grounding.png",
|
||||||
|
"text":"a blue turtle-like pokemon with round head"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"visual-question-answering":{
|
||||||
|
"input":{
|
||||||
|
"image":"data/test/images/image_mplug_vqa.jpg",
|
||||||
|
"text":"What is the woman doing?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"word-segmentation":{
|
||||||
|
"input":{
|
||||||
|
"text":"今天天气不错,适合出去游玩"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zero-shot-classification":{
|
||||||
|
"input":{
|
||||||
|
"text":"全新突破 解放军运20版空中加油机曝光"
|
||||||
|
},
|
||||||
|
"parameters":{
|
||||||
|
"candidate_labels":[
|
||||||
|
"文化",
|
||||||
|
"体育",
|
||||||
|
"娱乐",
|
||||||
|
"财经",
|
||||||
|
"家居",
|
||||||
|
"汽车",
|
||||||
|
"教育",
|
||||||
|
"科技",
|
||||||
|
"军事"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3781
modelscope/utils/pipeline_schema.json
Normal file
3781
modelscope/utils/pipeline_schema.json
Normal file
File diff suppressed because it is too large
Load Diff
76
tests/json_call_test.py
Normal file
76
tests/json_call_test.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from modelscope.hub.api import HubApi
|
||||||
|
from modelscope.hub.file_download import model_file_download
|
||||||
|
from modelscope.hub.utils.utils import get_cache_dir
|
||||||
|
from modelscope.pipelines import pipeline
|
||||||
|
from modelscope.utils.config import Config
|
||||||
|
from modelscope.utils.constant import ModelFile
|
||||||
|
from modelscope.utils.input_output import (
|
||||||
|
call_pipeline_with_json, get_pipeline_information_by_pipeline,
|
||||||
|
get_task_input_examples, pipeline_output_to_service_base64_output)
|
||||||
|
|
||||||
|
|
||||||
|
class ModelJsonTest:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.api = HubApi()
|
||||||
|
|
||||||
|
def test_single(self, model_id: str, model_revision=None):
|
||||||
|
# get model_revision & task info
|
||||||
|
cache_root = get_cache_dir()
|
||||||
|
configuration_file = os.path.join(cache_root, model_id,
|
||||||
|
ModelFile.CONFIGURATION)
|
||||||
|
if not model_revision:
|
||||||
|
model_revision = self.api.list_model_revisions(
|
||||||
|
model_id=model_id)[0]
|
||||||
|
if not os.path.exists(configuration_file):
|
||||||
|
|
||||||
|
configuration_file = model_file_download(
|
||||||
|
model_id=model_id,
|
||||||
|
file_path=ModelFile.CONFIGURATION,
|
||||||
|
revision=model_revision)
|
||||||
|
cfg = Config.from_file(configuration_file)
|
||||||
|
task = cfg.safe_get('task')
|
||||||
|
|
||||||
|
# init pipeline
|
||||||
|
ppl = pipeline(
|
||||||
|
task=task, model=model_id, model_revision=model_revision)
|
||||||
|
pipeline_info = get_pipeline_information_by_pipeline(ppl)
|
||||||
|
|
||||||
|
# call pipeline
|
||||||
|
data = get_task_input_examples(task)
|
||||||
|
print(task, data)
|
||||||
|
infer_result = call_pipeline_with_json(pipeline_info, ppl, data)
|
||||||
|
result = pipeline_output_to_service_base64_output(task, infer_result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
model_list = [
|
||||||
|
'damo/nlp_structbert_nli_chinese-base',
|
||||||
|
'damo/nlp_structbert_word-segmentation_chinese-base',
|
||||||
|
'damo/nlp_structbert_zero-shot-classification_chinese-base',
|
||||||
|
'damo/cv_unet_person-image-cartoon_compound-models',
|
||||||
|
'damo/nlp_structbert_sentiment-classification_chinese-tiny',
|
||||||
|
'damo/nlp_csanmt_translation_zh2en',
|
||||||
|
'damo/nlp_rom_passage-ranking_chinese-base',
|
||||||
|
'damo/ofa_image-caption_muge_base_zh',
|
||||||
|
'damo/nlp_raner_named-entity-recognition_chinese-base-ecom-50cls',
|
||||||
|
'damo/nlp_structbert_sentiment-classification_chinese-ecommerce-base',
|
||||||
|
'damo/text-to-video-synthesis',
|
||||||
|
'qwen/Qwen-7B',
|
||||||
|
'qwen/Qwen-7B-Chat',
|
||||||
|
'ZhipuAI/ChatGLM-6B',
|
||||||
|
]
|
||||||
|
tester = ModelJsonTest()
|
||||||
|
for model in model_list:
|
||||||
|
try:
|
||||||
|
res = tester.test_single(model)
|
||||||
|
print(f'\nmodel_id {model} call_pipeline_with_json run ok.\n')
|
||||||
|
except BaseException as e:
|
||||||
|
print(
|
||||||
|
f'\nmodel_id {model} call_pipeline_with_json run failed: {e}.\n'
|
||||||
|
)
|
||||||
@@ -62,7 +62,10 @@ class AnalysisTestFile(ast.NodeVisitor):
|
|||||||
|
|
||||||
class AnalysisTestClass(ast.NodeVisitor):
|
class AnalysisTestClass(ast.NodeVisitor):
|
||||||
|
|
||||||
def __init__(self, test_class_node, builder_function_name) -> None:
|
def __init__(self,
|
||||||
|
test_class_node,
|
||||||
|
builder_function_name,
|
||||||
|
file_analyzer=None) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.test_class_node = test_class_node
|
self.test_class_node = test_class_node
|
||||||
self.builder_function_name = builder_function_name
|
self.builder_function_name = builder_function_name
|
||||||
@@ -72,6 +75,44 @@ class AnalysisTestClass(ast.NodeVisitor):
|
|||||||
] # class method trainer builder(call build_trainer)
|
] # class method trainer builder(call build_trainer)
|
||||||
self.custom_class_method_builder_calls = [
|
self.custom_class_method_builder_calls = [
|
||||||
] # the builder call statement
|
] # the builder call statement
|
||||||
|
self.variables = {}
|
||||||
|
|
||||||
|
def get_variables(self, key: str):
|
||||||
|
if key in self.variables:
|
||||||
|
return self.variables[key]
|
||||||
|
return key
|
||||||
|
|
||||||
|
def get_ast_value(self, statements):
|
||||||
|
if not isinstance(statements, list):
|
||||||
|
statements = [statements]
|
||||||
|
res = []
|
||||||
|
for item in statements:
|
||||||
|
if isinstance(item, ast.Name):
|
||||||
|
res.append(self.get_variables(item.id))
|
||||||
|
elif isinstance(item, ast.Attribute):
|
||||||
|
res.append(self.get_variables(item.value.id))
|
||||||
|
elif isinstance(item, ast.Str):
|
||||||
|
res.append(self.get_variables(item.s))
|
||||||
|
elif isinstance(item, ast.Dict):
|
||||||
|
keys = [i.s for i in item.keys]
|
||||||
|
values = self.get_ast_value(item.values)
|
||||||
|
res.append(dict(zip(keys, values)))
|
||||||
|
return res
|
||||||
|
|
||||||
|
def get_final_variables(self, statement: ast.Assign):
|
||||||
|
if len(statement.targets) == 1 and \
|
||||||
|
isinstance(statement.targets[0], ast.Name):
|
||||||
|
if isinstance(statement.value, ast.Call):
|
||||||
|
if isinstance(statement.value.func, ast.Attribute) and \
|
||||||
|
isinstance(statement.value.func.value, ast.Name) and \
|
||||||
|
statement.value.func.value.id == 'Image':
|
||||||
|
self.variables[str(
|
||||||
|
statement.targets[0].id)] = self.get_ast_value(
|
||||||
|
statement.value.args[0])
|
||||||
|
else:
|
||||||
|
self.variables[str(
|
||||||
|
statement.targets[0].id)] = self.get_ast_value(
|
||||||
|
statement.value)
|
||||||
|
|
||||||
def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
|
def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
|
||||||
if node.name.startswith('setUp'):
|
if node.name.startswith('setUp'):
|
||||||
@@ -83,6 +124,7 @@ class AnalysisTestClass(ast.NodeVisitor):
|
|||||||
self.setup_variables[str(
|
self.setup_variables[str(
|
||||||
statement.targets[0].attr)] = str(
|
statement.targets[0].attr)] = str(
|
||||||
statement.value.attr)
|
statement.value.attr)
|
||||||
|
self.get_final_variables(statement)
|
||||||
elif node.name.startswith('test_'):
|
elif node.name.startswith('test_'):
|
||||||
self.test_methods.append(node)
|
self.test_methods.append(node)
|
||||||
else:
|
else:
|
||||||
@@ -312,6 +354,48 @@ def analysis_trainer_test_suite(test_file, modified_register_modules):
|
|||||||
return tested_trainers
|
return tested_trainers
|
||||||
|
|
||||||
|
|
||||||
|
def get_test_parameters(test_method, analyzer):
|
||||||
|
for node in ast.walk(test_method):
|
||||||
|
func = None
|
||||||
|
if not isinstance(node, ast.FunctionDef):
|
||||||
|
continue
|
||||||
|
for statement in node.body:
|
||||||
|
if isinstance(statement, ast.Assign):
|
||||||
|
analyzer.get_final_variables(statement)
|
||||||
|
if not func and isinstance(statement, ast.Assign):
|
||||||
|
if isinstance(statement.value, ast.Call) and isinstance(
|
||||||
|
statement.value.func, ast.Name) and ( # noqa W504
|
||||||
|
'pipeline' in statement.value.func.id
|
||||||
|
or 'Pipeline' in statement.value.func.id):
|
||||||
|
func = statement.targets[0].id
|
||||||
|
if func and isinstance(statement, ast.Assign) and isinstance(
|
||||||
|
statement.value, ast.Call) and isinstance(
|
||||||
|
statement.value.func, ast.Name):
|
||||||
|
if statement.value.func.id == func:
|
||||||
|
inputs = statement.value.args
|
||||||
|
return analyzer.get_ast_value(inputs)
|
||||||
|
|
||||||
|
|
||||||
|
def analysis_pipeline_test_examples(test_file):
|
||||||
|
examples = []
|
||||||
|
with open(test_file, 'rb') as tsf:
|
||||||
|
src = tsf.read()
|
||||||
|
test_root = ast.parse(src, test_file)
|
||||||
|
test_file_analyzer = AnalysisTestFile(
|
||||||
|
test_file, SYSTEM_PIPELINE_BUILDER_FUNCTION_NAME)
|
||||||
|
test_file_analyzer.visit(test_root)
|
||||||
|
|
||||||
|
for test_class in test_file_analyzer.test_classes:
|
||||||
|
test_class_analyzer = AnalysisTestClass(
|
||||||
|
test_class, SYSTEM_PIPELINE_BUILDER_FUNCTION_NAME,
|
||||||
|
test_file_analyzer)
|
||||||
|
test_class_analyzer.visit(test_class)
|
||||||
|
for test_method in test_class_analyzer.test_methods:
|
||||||
|
parameters = get_test_parameters(test_method, test_class_analyzer)
|
||||||
|
examples.append(parameters)
|
||||||
|
return examples
|
||||||
|
|
||||||
|
|
||||||
def analysis_pipeline_test_suite(test_file, modified_register_modules):
|
def analysis_pipeline_test_suite(test_file, modified_register_modules):
|
||||||
tested_tasks = []
|
tested_tasks = []
|
||||||
with open(test_file, 'rb') as tsf:
|
with open(test_file, 'rb') as tsf:
|
||||||
@@ -413,7 +497,18 @@ def get_pipelines_trainers_test_info(register_modules):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_file = 'tests/pipelines/test_action_detection.py'
|
all_pipeline_cases = [
|
||||||
tasks = analysis_pipeline_test_suite(test_file, None)
|
os.path.join(dp, f) for dp, dn, filenames in os.walk(
|
||||||
|
os.path.join(os.getcwd(), 'tests', 'pipelines')) for f in filenames
|
||||||
|
if os.path.splitext(f)[1] == '.py'
|
||||||
|
]
|
||||||
|
for test_file in all_pipeline_cases:
|
||||||
|
print('\n', test_file)
|
||||||
|
tasks = analysis_pipeline_test_suite(test_file, None)
|
||||||
|
examples = analysis_pipeline_test_examples(test_file)
|
||||||
|
|
||||||
print(tasks)
|
from modelsope.metainfo import Tasks
|
||||||
|
for task, example in zip(tasks, examples):
|
||||||
|
task_convert = f't = Tasks.{task}'
|
||||||
|
exec(task_convert)
|
||||||
|
print(t, example)
|
||||||
|
|||||||
Reference in New Issue
Block a user