diff --git a/docker/Dockerfile.extra_install b/docker/Dockerfile.extra_install index 820001eb..6737ff1c 100644 --- a/docker/Dockerfile.extra_install +++ b/docker/Dockerfile.extra_install @@ -138,4 +138,5 @@ RUN set -eux; \ pip --version # end of install python -RUN pip install tf-keras -i https://mirrors.aliyun.com/pypi/simple +RUN pip install tensorflow-cpu==2.16.1 +RUN pip install tf-keras==2.16.0 --no-dependencies diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu index 056c0026..1e43c3fd 100644 --- a/docker/Dockerfile.ubuntu +++ b/docker/Dockerfile.ubuntu @@ -46,6 +46,8 @@ RUN cd /tmp && GIT_LFS_SKIP_SMUDGE=1 git clone -b {swift_branch} --single-branc RUN pip install --no-cache-dir torch=={torch_version} torchvision=={torchvision_version} torchaudio=={torchaudio_version} {index_url} +RUN pip install --no-cache-dir transformers -U huggingface-hub==0.25.0 + RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple && \ pip config set install.trusted-host mirrors.aliyun.com && \ cp /tmp/resources/ubuntu2204.aliyun /etc/apt/sources.list @@ -54,3 +56,4 @@ ENV SETUPTOOLS_USE_DISTUTILS=stdlib ENV VLLM_USE_MODELSCOPE=True ENV LMDEPLOY_USE_MODELSCOPE=True ENV MODELSCOPE_CACHE=/mnt/workspace/.cache/modelscope +SHELL ["/bin/bash", "-c"] diff --git a/modelscope/hub/api.py b/modelscope/hub/api.py index 41c11282..d9157bca 100644 --- a/modelscope/hub/api.py +++ b/modelscope/hub/api.py @@ -22,6 +22,8 @@ import requests from requests import Session from requests.adapters import HTTPAdapter, Retry +from modelscope import utils +from modelscope.fileio import io from modelscope.hub.constants import (API_HTTP_CLIENT_MAX_RETRIES, API_HTTP_CLIENT_TIMEOUT, API_RESPONSE_FIELD_DATA, @@ -48,13 +50,14 @@ from modelscope.utils.constant import (DEFAULT_DATASET_REVISION, DEFAULT_MODEL_REVISION, DEFAULT_REPOSITORY_REVISION, MASTER_MODEL_BRANCH, META_FILES_FORMAT, + REPO_TYPE_MODEL, ConfigFields, DatasetFormations, DatasetMetaFormats, DatasetVisibilityMap, DownloadChannel, - DownloadMode, ModelFile, - VirgoDatasetConfig) + DownloadMode, Frameworks, ModelFile, + Tasks, VirgoDatasetConfig) from modelscope.utils.logger import get_logger -from .utils.utils import (get_endpoint, get_release_datetime, - model_id_to_group_owner_name) +from .utils.utils import (get_endpoint, get_readable_folder_size, + get_release_datetime, model_id_to_group_owner_name) logger = get_logger() @@ -248,6 +251,57 @@ class HubApi: else: raise_for_http_status(r) + def repo_exists( + self, + repo_id: str, + *, + repo_type: Optional[str] = None, + ) -> bool: + """ + Checks if a repository exists on ModelScope + + Args: + repo_id (`str`): + A namespace (user or an organization) and a repo name separated + by a `/`. + repo_type (`str`, *optional*): + `None` or `"model"` if getting repository info from a model. Default is `None`. + TODO: support dataset and studio + + Returns: + True if the repository exists, False otherwise. + """ + if (repo_type is not None) and repo_type.lower != REPO_TYPE_MODEL: + raise Exception('Not support repo-type: %s' % repo_type) + if (repo_id is None) or repo_id.count('/') != 1: + raise Exception('Invalid repo_id: %s, must be of format namespace/name' % repo_type) + + cookies = ModelScopeConfig.get_cookies() + owner_or_group, name = model_id_to_group_owner_name(repo_id) + path = f'{self.endpoint}/api/v1/models/{owner_or_group}/{name}' + + r = self.session.get(path, cookies=cookies, + headers=self.builder_headers(self.headers)) + code = handle_http_response(r, logger, cookies, repo_id, False) + if code == 200: + return True + elif code == 404: + return False + else: + logger.warn(f'Check repo_exists return status code {code}.') + raise Exception( + 'Failed to check existence of repo: %s, make sure you have access authorization.' + % repo_type) + + @staticmethod + def _create_default_config(model_dir): + cfg_file = os.path.join(model_dir, ModelFile.CONFIGURATION) + cfg = { + ConfigFields.framework: Frameworks.torch, + ConfigFields.task: Tasks.other, + } + io.dump(cfg, cfg_file) + def push_model(self, model_id: str, model_dir: str, @@ -315,23 +369,23 @@ class HubApi: raise InvalidParameter('model_dir must be a valid directory.') cfg_file = os.path.join(model_dir, ModelFile.CONFIGURATION) if not os.path.exists(cfg_file): - raise ValueError(f'{model_dir} must contain a configuration.json.') + logger.warning( + f'No {ModelFile.CONFIGURATION} file found in {model_dir}, creating a default one.') + HubApi._create_default_config(model_dir) + cookies = ModelScopeConfig.get_cookies() if cookies is None: raise NotLoginException('Must login before upload!') files_to_save = os.listdir(model_dir) + folder_size = get_readable_folder_size(model_dir) if ignore_file_pattern is None: ignore_file_pattern = [] if isinstance(ignore_file_pattern, str): ignore_file_pattern = [ignore_file_pattern] - try: - self.get_model(model_id=model_id) - except Exception: - if visibility is None or license is None: - raise InvalidParameter( - 'visibility and license cannot be empty if want to create new repo' - ) - logger.info('Create new model %s' % model_id) + if visibility is None or license is None: + raise InvalidParameter('Visibility and License cannot be empty for new model.') + if not self.repo_exists(model_id): + logger.info('Creating new model [%s]' % model_id) self.create_model( model_id=model_id, visibility=visibility, @@ -340,11 +394,13 @@ class HubApi: original_model_id=original_model_id) tmp_dir = tempfile.mkdtemp() git_wrapper = GitCommandWrapper() + logger.info(f'Pushing folder {model_dir} as model {model_id}.') + logger.info(f'Total folder size {folder_size}, this may take a while depending on actual pushing size...') try: repo = Repository(model_dir=tmp_dir, clone_from=model_id) branches = git_wrapper.get_remote_branches(tmp_dir) if revision not in branches: - logger.info('Create new branch %s' % revision) + logger.info('Creating new branch %s' % revision) git_wrapper.new_branch(tmp_dir, revision) git_wrapper.checkout(tmp_dir, revision) files_in_repo = os.listdir(tmp_dir) diff --git a/modelscope/hub/errors.py b/modelscope/hub/errors.py index e2288787..986425d2 100644 --- a/modelscope/hub/errors.py +++ b/modelscope/hub/errors.py @@ -2,6 +2,7 @@ import logging from http import HTTPStatus +from typing import Optional import requests from requests.exceptions import HTTPError @@ -86,8 +87,11 @@ def handle_http_post_error(response, url, request_body): (url, request_body, message, get_request_id(response))) from error -def handle_http_response(response: requests.Response, logger, cookies, - model_id): +def handle_http_response(response: requests.Response, + logger, + cookies, + model_id, + raise_on_error: Optional[bool] = True) -> int: http_error_msg = '' if isinstance(response.reason, bytes): try: @@ -113,9 +117,11 @@ def handle_http_response(response: requests.Response, logger, cookies, elif 500 <= response.status_code < 600: http_error_msg = u'%s Server Error: %s, Request id: %s, for url: %s' % ( response.status_code, reason, request_id, response.url) - if http_error_msg: # there is error. + if http_error_msg and raise_on_error: # there is error. logger.error(http_error_msg) raise HTTPError(http_error_msg, response=response) + else: + return response.status_code def raise_on_error(rsp): diff --git a/modelscope/hub/git.py b/modelscope/hub/git.py index 581f248f..144d9d69 100644 --- a/modelscope/hub/git.py +++ b/modelscope/hub/git.py @@ -56,11 +56,18 @@ class GitCommandWrapper(metaclass=Singleton): response.check_returncode() return response except subprocess.CalledProcessError as error: - output = 'stdout: %s, stderr: %s' % ( - response.stdout.decode('utf8'), error.stderr.decode('utf8')) - logger.error('Running git command: %s failed, output: %s.' % - (command, output)) - raise GitError(output) + std_out = response.stdout.decode('utf8') + std_err = error.stderr.decode('utf8') + if 'nothing to commit' in std_out: + logger.info( + 'Nothing to commit, your local repo is upto date with remote' + ) + return response + else: + logger.error( + 'Running git command: %s failed \n stdout: %s \n stderr: %s' + % (command, std_out, std_err)) + raise GitError(std_err) def config_auth_token(self, repo_dir, auth_token): url = self.get_repo_remote_url(repo_dir) diff --git a/modelscope/hub/snapshot_download.py b/modelscope/hub/snapshot_download.py index a4eda17b..1fe94b82 100644 --- a/modelscope/hub/snapshot_download.py +++ b/modelscope/hub/snapshot_download.py @@ -193,7 +193,9 @@ def _snapshot_download( temporary_cache_dir, cache = create_temporary_directory_and_cache( repo_id, local_dir=local_dir, cache_dir=cache_dir, repo_type=repo_type) - + system_cache = cache_dir if cache_dir is not None else os.getenv( + 'MODELSCOPE_CACHE', + Path.home().joinpath('.cache', 'modelscope')) if local_files_only: if len(cache.cached_files) == 0: raise ValueError( @@ -217,6 +219,8 @@ def _snapshot_download( if cookies is None: cookies = ModelScopeConfig.get_cookies() repo_files = [] + directory = os.path.join(system_cache, 'hub', repo_id) + print(f'Downloading Model to directory: {directory}') if repo_type == REPO_TYPE_MODEL: revision_detail = _api.get_valid_revision_detail( repo_id, revision=revision, cookies=cookies) @@ -257,6 +261,8 @@ def _snapshot_download( allow_patterns=allow_patterns) elif repo_type == REPO_TYPE_DATASET: + directory = os.path.join(system_cache, 'datasets', repo_id) + print(f'Downloading Dataset to directory: {directory}') group_or_owner, name = model_id_to_group_owner_name(repo_id) if not revision: revision = DEFAULT_DATASET_REVISION diff --git a/modelscope/hub/utils/utils.py b/modelscope/hub/utils/utils.py index 3c3c75da..3ed853b1 100644 --- a/modelscope/hub/utils/utils.py +++ b/modelscope/hub/utils/utils.py @@ -29,6 +29,30 @@ def model_id_to_group_owner_name(model_id): return group_or_owner, name +def convert_readable_size(size_bytes): + import math + if size_bytes == 0: + return '0B' + size_name = ('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB') + i = int(math.floor(math.log(size_bytes, 1024))) + p = math.pow(1024, i) + s = round(size_bytes / p, 2) + return f'{s} {size_name[i]}' + + +def get_folder_size(folder_path): + total_size = 0 + for path in Path(folder_path).rglob('*'): + if path.is_file(): + total_size += path.stat().st_size + return total_size + + +# return a readable string that describe size of for a given folder (MB, GB etc.) +def get_readable_folder_size(folder_path) -> str: + return convert_readable_size(get_folder_size(folder_path=folder_path)) + + def get_cache_dir(model_id: Optional[str] = None): """cache dir precedence: function parameter > environment > ~/.cache/modelscope/hub diff --git a/modelscope/models/nlp/bart/text_error_correction.py b/modelscope/models/nlp/bart/text_error_correction.py index 97c3a7a9..09b867c4 100644 --- a/modelscope/models/nlp/bart/text_error_correction.py +++ b/modelscope/models/nlp/bart/text_error_correction.py @@ -82,5 +82,5 @@ class BartForTextErrorCorrection(TorchModel): batch_preds = [] for i in range(batch_size): # get 1-best List[Tensor] - batch_preds.append(translations[i][0]['tokens']) + batch_preds.append(translations[i][0]['tokens'].tolist()) return TextErrorCorrectionOutput(predictions=batch_preds) diff --git a/modelscope/outputs/nlp_outputs.py b/modelscope/outputs/nlp_outputs.py index ed42cb5a..747f5bd3 100644 --- a/modelscope/outputs/nlp_outputs.py +++ b/modelscope/outputs/nlp_outputs.py @@ -326,7 +326,7 @@ class TextErrorCorrectionOutput(ModelOutputBase): """The output class for information extraction models. """ - predictions: np.ndarray = None + predictions: List = None @dataclass diff --git a/modelscope/pipelines/audio/ans_pipeline.py b/modelscope/pipelines/audio/ans_pipeline.py index 0b03beca..39cd12e8 100644 --- a/modelscope/pipelines/audio/ans_pipeline.py +++ b/modelscope/pipelines/audio/ans_pipeline.py @@ -151,9 +151,8 @@ class ANSZipEnhancerPipeline(Pipeline): if isinstance(inputs, bytes): data1, fs = sf.read(io.BytesIO(inputs)) elif isinstance(inputs, str): - # file_bytes = File.read(inputs) - # data1, fs = sf.read(io.BytesIO(file_bytes)) - data1, fs = sf.read(inputs) + file_bytes = File.read(inputs) + data1, fs = sf.read(io.BytesIO(file_bytes)) else: raise TypeError(f'Unsupported type {type(inputs)}.') if len(data1.shape) > 1: diff --git a/modelscope/pipelines/base.py b/modelscope/pipelines/base.py index 693f04d8..1495eaee 100644 --- a/modelscope/pipelines/base.py +++ b/modelscope/pipelines/base.py @@ -481,7 +481,10 @@ class DistributedPipeline(Pipeline): def __del__(self): if hasattr(self, 'model_pool') and self.model_pool is not None: - self.model_pool.terminate() + try: + self.model_pool.terminate() + except AttributeError: + pass def __getstate__(self): self_dict = self.__dict__.copy() diff --git a/modelscope/pipelines/cv/ocr_detection_pipeline.py b/modelscope/pipelines/cv/ocr_detection_pipeline.py index cb7522c0..c23f6e6e 100644 --- a/modelscope/pipelines/cv/ocr_detection_pipeline.py +++ b/modelscope/pipelines/cv/ocr_detection_pipeline.py @@ -6,7 +6,6 @@ from typing import Any, Dict import cv2 import numpy as np -import tensorflow as tf import torch from modelscope.metainfo import Pipelines @@ -19,18 +18,7 @@ from modelscope.utils.config import Config from modelscope.utils.constant import ModelFile, Tasks from modelscope.utils.device import device_placement from modelscope.utils.logger import get_logger -from .ocr_utils import (SegLinkDetector, boxes_from_bitmap, cal_width, - combine_segments_python, decode_segments_links_python, - nms_python, polygons_from_bitmap, rboxes_to_polygons) - -if tf.__version__ >= '2.0': - import tf_slim as slim -else: - from tensorflow.contrib import slim - -if tf.__version__ >= '2.0': - tf = tf.compat.v1 -tf.compat.v1.disable_eager_execution() +from .ocr_utils import cal_width, nms_python, rboxes_to_polygons logger = get_logger() @@ -40,12 +28,6 @@ OFFSET_DIM = 6 WORD_POLYGON_DIM = 8 OFFSET_VARIANCE = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1] -FLAGS = tf.app.flags.FLAGS -tf.app.flags.DEFINE_float('node_threshold', 0.4, - 'Confidence threshold for nodes') -tf.app.flags.DEFINE_float('link_threshold', 0.6, - 'Confidence threshold for links') - @PIPELINES.register_module( Tasks.ocr_detection, module_name=Pipelines.ocr_detection) @@ -99,6 +81,16 @@ class OCRDetectionPipeline(Pipeline): logger.info('loading model done') else: # for model seglink++ + import tensorflow as tf + + if tf.__version__ >= '2.0': + tf = tf.compat.v1 + tf.compat.v1.disable_eager_execution() + + tf.app.flags.DEFINE_float('node_threshold', 0.4, + 'Confidence threshold for nodes') + tf.app.flags.DEFINE_float('link_threshold', 0.6, + 'Confidence threshold for links') tf.reset_default_graph() model_path = osp.join( osp.join(self.model, ModelFile.TF_CHECKPOINT_FOLDER), @@ -125,6 +117,7 @@ class OCRDetectionPipeline(Pipeline): variable_averages = tf.train.ExponentialMovingAverage( 0.997, global_step) + from .ocr_utils import SegLinkDetector, combine_segments_python, decode_segments_links_python # detector detector = SegLinkDetector() all_maps = detector.build_model( @@ -198,6 +191,19 @@ class OCRDetectionPipeline(Pipeline): result = self.preprocessor(input) return result else: + # for model seglink++ + import tensorflow as tf + + if tf.__version__ >= '2.0': + tf = tf.compat.v1 + + tf.compat.v1.disable_eager_execution() + + tf.app.flags.DEFINE_float('node_threshold', 0.4, + 'Confidence threshold for nodes') + tf.app.flags.DEFINE_float('link_threshold', 0.6, + 'Confidence threshold for links') + img = LoadImage.convert_to_ndarray(input) h, w, c = img.shape diff --git a/modelscope/pipelines/nlp/text_error_correction_pipeline.py b/modelscope/pipelines/nlp/text_error_correction_pipeline.py index dc4bc40a..9fa5a2a8 100644 --- a/modelscope/pipelines/nlp/text_error_correction_pipeline.py +++ b/modelscope/pipelines/nlp/text_error_correction_pipeline.py @@ -80,7 +80,8 @@ class TextErrorCorrectionPipeline(Pipeline): sc_tensor = inputs['predictions'] if isinstance(sc_tensor, list): - sc_tensor = sc_tensor[0] + if isinstance(sc_tensor[0], list): + sc_tensor = sc_tensor[0] sc_sent = self.vocab.string( sc_tensor, extra_symbols_to_ignore={self.vocab.pad()}) sc_sent = (sc_sent + ' ').replace('##', '').rstrip() diff --git a/modelscope/preprocessors/templates/loader.py b/modelscope/preprocessors/templates/loader.py index 4f83a9a9..ccbd6e09 100644 --- a/modelscope/preprocessors/templates/loader.py +++ b/modelscope/preprocessors/templates/loader.py @@ -1,6 +1,7 @@ import re +import json from dataclasses import dataclass -from typing import Any, Dict, List +from typing import Any, Dict, List, Union, Optional, Tuple import requests @@ -16,7 +17,7 @@ class TemplateInfo: template: str = None template_regex: str = None - modelfile_link: str = None + modelfile_prefix: str = None def cases(*names): @@ -48,52 +49,374 @@ def no_multi_modal(): return no('audio', 'video', 'vl', 'vision') +# Order matters template_info = [ # llama + ## "llama3" + TemplateInfo( + template=TemplateType.llama3, + template_regex= + f'.*{cases("llama3.2", "llama-3.2")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama3.2', + ), + TemplateInfo( + template=TemplateType.llama3, + template_regex= + f'.*{cases("llama3.1", "llama-3.1")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama3.1', + ), + TemplateInfo( + template_regex= + f'.*{cases("llama3", "llama-3")}.*{no_multi_modal()}.*{chat_suffix}.*{cases("gradient")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama3-gradient', + ), + TemplateInfo( + template_regex= + f'.*{cases("llama3", "llama-3")}.*{no_multi_modal()}.*{cases("groq")}.*{cases("tool-use", "tool_use")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama3-groq-tool-use', + ), + TemplateInfo( + template_regex= + f'.*{cases("llama3", "llama-3")}.*{no_multi_modal()}.*{cases("chatqa")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama3-chatqa', + ), + TemplateInfo( + template_regex=f'.*{cases("llava-llama-3")}.*', + modelfile_prefix='https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llava-llama3'), + TemplateInfo( + template_regex=f'.*{cases("dolphin")}.*{cases("llama3")}.*', + modelfile_prefix='https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/dolphin-llama3'), TemplateInfo( template=TemplateType.llama3, template_regex= f'.*{cases("llama3", "llama-3")}{no_multi_modal()}.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama-3.modelfile', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama3', + ), + + ## "llama" + TemplateInfo( + template_regex= + f'.*{cases("llama2", "llama-2")}{no_multi_modal()}.*{cases("chinese")}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama2-chinese', + ), + TemplateInfo( + template_regex= + f'.*{cases("codellama")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/codellama', + ), + TemplateInfo( + template_regex= + f'.*{cases("tinyllama")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/tinyllama', + ), + TemplateInfo( + template_regex= + f'.*{cases("llama-pro", "llama_pro")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama-pro', + ), + TemplateInfo( + template_regex= + f'.*{cases("llama")}.*{cases("guard")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama-guard3', ), TemplateInfo( template=TemplateType.llama, template_regex= - f'.*{cases("llama2", "llama-2", "mistral", "codestral", "mixtral")}{no_multi_modal()}.*{chat_suffix}.*' + f'.*{cases("llama")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llama2', ), # qwen TemplateInfo( template=TemplateType.qwen, - template_regex=f'.*{cases("qwen")}{no_multi_modal()}.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/qwen2.modelfile', + template_regex=f'.*{cases("qwen2.5")}.*{cases("coder")}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/qwen2.5-coder', + ), + TemplateInfo( + template=TemplateType.qwen, + template_regex=f'.*{cases("qwen2.5")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/qwen2.5', + ), + TemplateInfo( + template_regex=f'.*{cases("qwen2-math")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/qwen2-math', ), - - # codeqwen1.5 TemplateInfo( template_regex= f'.*{cases("codeqwen1.5", "codeqwen-1.5")}.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/codeqwen1.5.modelfile', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/codeqwen', + ), + TemplateInfo( + template=TemplateType.qwen, + template_regex=f'.*{cases("qwen2", "qwen1.5")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/qwen2', + ), + TemplateInfo( + template=TemplateType.qwen, + template_regex=f'.*{cases("qwen")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/qwen', ), - # chatml + # gemma + TemplateInfo( + template_regex= + f'.*{cases("codegemma")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/codegemma', + ), + TemplateInfo( + template=TemplateType.gemma, + template_regex= + f'{no("pali")}.*{cases("gemma2", "gemma-2")}\\b.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/gemma2', + ), + TemplateInfo( + template_regex= + f'.*{cases("shieldgemma")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/shieldgemma', + ), + TemplateInfo( + template=TemplateType.gemma, + template_regex= + f'{no("pali")}.*{cases("gemma")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/gemma', + ), + + # "dolphin" + TemplateInfo( + template_regex= + f'.*{cases("dolphin")}.*{cases("-mixtral")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/dolphin-mixtral', + ), + TemplateInfo( + template_regex= + f'.*{cases("dolphin")}.*{cases("mistral")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/dolphin-mistral', + ), + + # "phi" + TemplateInfo( + template_regex= + f'.*{cases("llava-phi3", "llava-phi-3")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llava-phi3', + ), + TemplateInfo( + template_regex= + f'.*{cases("phi3.5", "phi-3.5")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/phi3.5', + ), + TemplateInfo( + template=TemplateType.phi3, + template_regex= + f'.*{cases("phi3", "phi-3")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/phi3', + ), + TemplateInfo( + template_regex= + f'.*{cases("phi")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/phi', + ), + + # "mistral" + TemplateInfo( + template_regex= + f'.*{cases("yarn")}.*{cases("mistral")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/yarn-mistral', + ), + TemplateInfo( + template_regex= + f'.*{cases("mistral")}.*{cases("large")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistral-large', + ), + TemplateInfo( + template_regex= + f'.*{cases("mistral")}.*{cases("small")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistral-small', + ), + TemplateInfo( + template=TemplateType.mistral_nemo, + template_regex=f'.*{cases("Mistral-Nemo")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistral-nemo', + ), + TemplateInfo( + template_regex= + f'.*{cases("mistral")}.*{cases("openorca")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistral-openorca', + ), + TemplateInfo( + template_regex= + f'.*{cases("mistrallite")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistrallite', + ), + ## other mistral: set Type.llama + TemplateInfo( + template=TemplateType.llama, + template_regex= + f'.*{cases("mistral")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistral', + ), + + # "mixtral" + TemplateInfo( + template_regex= + f'.*{cases("nous-hermes2", "nous-hermes-2")}.*{cases("mixtral")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nous-hermes2-mixtral', + ), + TemplateInfo( + template=TemplateType.llama, + template_regex= + f'.*{cases("mixtral")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mixtral', + ), + + # codestral + TemplateInfo( + template=TemplateType.llama, + template_regex= + f'.*{cases("codestral")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/codestral', + ), + + # nous-hermes2 + TemplateInfo( + template_regex= + f'.*{cases("nous-hermes2", "nous-hermes-2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nous-hermes2', + ), + TemplateInfo( + template_regex=f'.*{cases("nous-hermes")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nous-hermes'), + + # "deepseek" + TemplateInfo( + template=TemplateType.deepseek2_5, + template_regex= + f'.*{cases("deepseek")}.*{cases("v2.5")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek-v2.5', + ), + TemplateInfo( + template=TemplateType.deepseek_coder, + template_regex= + f'.*{cases("deepseek")}.*{cases("coder")}.*{cases("v2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek-coder-v2', + ), + TemplateInfo( + template=TemplateType.deepseek_coder, + template_regex= + f'.*{cases("deepseek")}{no("v2", "v2.5")}.*{cases("coder")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek-coder', + ), + TemplateInfo( + template=TemplateType.deepseek2, + template_regex= + f'.*{cases("deepseek")}.*{cases("v2")}{no("v2.5")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek-v2', + ), + TemplateInfo( + template=TemplateType.deepseek, + template_regex= + f'.*{cases("deepseek")}{no("v2", "v2.5", "coder")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek-llm', + ), + + # "yi" + TemplateInfo( + template=TemplateType.yi_coder, + template_regex=f'.*{cases("yi")}.*{cases("coder")}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/yi-coder', + ), TemplateInfo( template=TemplateType.chatml, template_regex= f'.*{cases("yi")}{no_multi_modal()}{no("coder")}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/yi-1.5.modelfile', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/yi', ), - # chatml + # "llava" + TemplateInfo( + template_regex= + f'.*{cases("bakllava")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/bakllava', + ), + TemplateInfo( + template_regex= + f'.*{cases("llava")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llava', + ), + + # "nemotron" + TemplateInfo( + template_regex= + f'.*{cases("nemotron-mini")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nemotron-mini', + ), + TemplateInfo( + template_regex= + f'.*{cases("nemotron")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nemotron', + ), + + # "minicpm" + TemplateInfo( + template_regex=f'.*{cases("minicpm-v")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/minicpm-v' + ), TemplateInfo( template=TemplateType.chatml, template_regex=f'.*{cases("minicpm")}{no("-v")}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/yi-1.5.modelfile' + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/yi' ), # chatglm @@ -105,37 +428,98 @@ template_info = [ template_regex=f'.*{cases("chatglm3")}{no_multi_modal()}.*'), TemplateInfo( template=TemplateType.chatglm4, - template_regex=f'.*{cases("glm4")}{no_multi_modal()}.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/glm4.modelfile', + template_regex=f'.*{cases("glm4", "glm-4")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/glm4', ), - TemplateInfo( - template_regex=f'.*{cases("llava-llama-3")}.*', - modelfile_link='https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/llava-llama-3.modelfile'), - # baichuan TemplateInfo( template=TemplateType.baichuan, template_regex= f'.*{cases("baichuan")}{no_multi_modal()}.*{chat_suffix}.*'), + # "command-r" + TemplateInfo( + template_regex= + f'.*{cases("command-r-plus")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/command-r-plus', + ), + TemplateInfo( + template_regex= + f'.*{cases("command-r")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/command-r', + ), + # codegeex TemplateInfo( template=TemplateType.codegeex4, - template_regex=f'.*{cases("codegeex4")}{no_multi_modal()}.*'), + template_regex=f'.*{cases("codegeex4")}{no_multi_modal()}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/codegeex4', + ), + + # wizard + TemplateInfo( + template_regex= + f'.*{cases("wizard-vicuna")}.*{cases("uncensored")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/wizard-vicuna-uncensored', + ), + TemplateInfo( + template_regex= + f'.*{cases("wizardlm2", "wizardlm-2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/wizardlm2', + ), + TemplateInfo( + template_regex= + f'.*{cases("wizardcoder")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/wizardcoder', + ), + TemplateInfo( + template_regex= + f'.*{cases("wizard-math", "wizardmath")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/wizard-math', + ), + TemplateInfo( + template_regex= + f'.*{cases("wizardlm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/wizardlm', + ), + + # vicuna + TemplateInfo( + template_regex= + f'.*{cases("vicuna")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/vicuna', + ), + + # "stable" + TemplateInfo( + template_regex= + f'.*{cases("stable-code")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/stable-code', + ), + TemplateInfo( + template_regex= + f'.*{cases("stablelm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/stablelm2', + ), # idefics3 TemplateInfo( template=TemplateType.idefics3, template_regex=f'.*{cases("idefics3")}{no_multi_modal()}.*'), - # mistral-nemo - TemplateInfo( - template=TemplateType.mistral_nemo, - template_regex=f'.*{cases("Mistral-Nemo")}{no_multi_modal()}.*', - modelfile_link='https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mistral-nemo.modelfile'), - # internlm TemplateInfo( template=TemplateType.internlm, @@ -147,12 +531,10 @@ template_info = [ TemplateInfo( template=TemplateType.internlm2, template_regex= - f'.*{cases("internlm2")}{no_multi_modal()}.*{chat_suffix}.*'), - - # yi-coder - TemplateInfo( - template=TemplateType.yi_coder, - template_regex=f'.*{cases("yi")}.*{cases("coder")}.*{chat_suffix}.*'), + f'.*{cases("internlm2")}{no_multi_modal()}.*{chat_suffix}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/internlm2', + ), # yuan TemplateInfo( @@ -194,8 +576,8 @@ template_info = [ template=TemplateType.deepseek2, template_regex= f'.*{cases("deepseek")}.*{cases("v2")}{no("v2.5")}{no_multi_modal()}.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek_v2.modelfile', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/deepseek_v2', ), # deepseek_coder @@ -217,24 +599,6 @@ template_info = [ template_regex=f'.*{cases("orion")}{no_multi_modal()}.*{chat_suffix}.*' ), - # gemma - TemplateInfo( - template=TemplateType.gemma, - template_regex= - f'{no("pali")}.*{cases("gemma2", "gemma-2")}\\b.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/gemma2.modelfile', - ), - - # phi3 - TemplateInfo( - template=TemplateType.phi3, - template_regex= - f'.*{cases("phi3", "phi-3")}{no_multi_modal()}.*{chat_suffix}.*', - modelfile_link= - 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/phi3.modelfile', - ), - # telechat TemplateInfo( template=TemplateType.telechat, @@ -244,6 +608,164 @@ template_info = [ TemplateInfo( template=TemplateType.telechat_v2, template_regex=f'.*{cases("TeleChat")}.*{cases("v2")}.*'), + + TemplateInfo( + template_regex=f'.*{cases("nomic-embed-text")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nomic-embed-text'), + TemplateInfo( + template_regex=f'.*{cases("mxbai-embed-large")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mxbai-embed-large'), + TemplateInfo( + template_regex=f'.*{cases("starcoder2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/starcoder2'), + TemplateInfo( + template_regex=f'.*{cases("orca-mini", "orca_mini")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/orca-mini'), + TemplateInfo( + template_regex=f'.*{cases("zephyr")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/zephyr'), + TemplateInfo( + template_regex=f'.*{cases("snowflake-arctic-embed")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/snowflake-arctic-embed'), + TemplateInfo( + template_regex=f'.*{cases("starcoder")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/starcoder'), + TemplateInfo( + template_regex=f'.*{cases("granite")}.*{cases("code")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/granite-code'), + TemplateInfo( + template_regex=f'.*{cases("all-minilm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/all-minilm'), + TemplateInfo( + template_regex=f'.*{cases("openchat")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/openchat'), + TemplateInfo( + template_regex=f'.*{cases("aya")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/aya'), + TemplateInfo( + template_regex=f'.*{cases("openhermes")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/openhermes'), + TemplateInfo( + template_regex=f'.*{cases("reflection")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/reflection'), + TemplateInfo( + template_regex=f'.*{cases("neural-chat")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/neural-chat'), + TemplateInfo( + template_regex=f'.*{cases("moondream")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/moondream'), + TemplateInfo( + template_regex=f'.*{cases("xwin")}.*{cases("lm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/xwinlm'), + TemplateInfo( + template_regex=f'.*{cases("smollm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/smollm'), + TemplateInfo( + template_regex=f'.*{cases("sqlcoder")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/sqlcoder'), + TemplateInfo( + template_regex=f'.*{cases("starling-lm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/starling-lm'), + TemplateInfo( + template_regex=f'.*{cases("falcon")}.*{cases("-2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/falcon2'), + TemplateInfo( + template_regex=f'.*{cases("falcon")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/falcon'), + TemplateInfo( + template_regex=f'.*{cases("solar-pro")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/solar-pro'), + TemplateInfo( + template_regex=f'.*{cases("solar")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/solar'), + TemplateInfo( + template_regex=f'.*{cases("orca2", "orca-2", "orca_2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/orca2'), + TemplateInfo( + template_regex=f'.*{cases("hermes3", "hermes-3", "hermes_3")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/hermes3'), + TemplateInfo( + template_regex=f'.*{cases("meditron")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/meditron'), + TemplateInfo( + template_regex=f'.*{cases("nexusraven")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nexusraven'), + TemplateInfo( + template_regex=f'.*{cases("magicoder")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/magicoder'), + TemplateInfo( + template_regex=f'.*{cases("bge-m3")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/bge-m3'), + TemplateInfo( + template_regex=f'.*{cases("notux")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/notux'), + TemplateInfo( + template_regex=f'.*{cases("open")}.*{cases("orca")}.*{cases("platypus2")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/open-orca-platypus2'), + TemplateInfo( + template_regex=f'.*{cases("notus")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/notus'), + TemplateInfo( + template_regex=f'.*{cases("mathstral")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/mathstral'), + TemplateInfo( + template_regex=f'.*{cases("dbrx")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/dbrx'), + TemplateInfo( + template_regex=f'.*{cases("nuextract")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/nuextract'), + TemplateInfo( + template_regex=f'.*{cases("reader-lm")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/reader-lm'), + TemplateInfo( + template_regex=f'.*{cases("alfred")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/alfred'), + TemplateInfo( + template_regex=f'.*{cases("bge-large")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/bge-large'), + TemplateInfo( + template_regex=f'.*{cases("paraphrase-multilingual")}.*', + modelfile_prefix= + 'https://modelscope.oss-cn-beijing.aliyuncs.com/llm_template/ollama/paraphrase-multilingual'), + ] @@ -318,12 +840,35 @@ class TemplateLoader: raise ValueError(f'Unknown token: {attr}') return final_str + @staticmethod + def _format_return(template_lines: str, params: Dict, split: bool, license: Optional[str] = None) -> Union[str, Dict]: + if split: + if params: + params = json.dumps(params) + return {'params': params, 'template': template_lines, 'license': license} + + content = '' + content += 'FROM {gguf_file}\n\n' + if params: + for key, values in params.items(): + if isinstance(values, list): + for value in values: + content += f'PARAMETER {key} {json.dumps(value)}\n' + else: + content += f'PARAMETER {key} {json.dumps(values)}\n' + content += '\n' + if template_lines: + content += ('TEMPLATE """' + template_lines + '"""\n') + return content + @staticmethod def to_ollama(model_id: str = None, template_name: str = None, gguf_file: str = None, gguf_meta: Dict[str, Any] = None, - **kwargs) -> str: + split: bool = False, + debug: bool = False, + **kwargs) -> Union[str, Dict, Tuple[Dict, TemplateInfo], Tuple[str, TemplateInfo], None]: """Export to ollama ModelFile Args: @@ -331,20 +876,44 @@ class TemplateLoader: template_name: An extra template name to use gguf_file: An extra gguf_file path to use in the `FROM` field gguf_meta: An gguf extra meta info + split: bool. Return str modelfile content, or dict of params and template + debug: bool. Whether or not to return the matched TemplateInfo Returns: - The ModelFile content, returns `None` if no template found + The ModelFile content, or dictionary of params and template, returns `None` if no template found """ - if not model_id and not template_name: + + if not model_id and not template_name and not gguf_meta: raise ValueError( f'Please make sure you model_id: {model_id} ' f'and template_name: {template_name} is supported.') logger.info('Exporting to ollama:') + names = [] + if gguf_meta: + gguf_header_name = gguf_meta.get("general.name", None) + names.append(gguf_header_name) if model_id: + names.append(model_id) + for name in names: for _info in template_info: - if re.fullmatch(_info.template_regex, model_id): - if _info.modelfile_link and not kwargs.get('ignore_oss_model_file', False): - return TemplateLoader._read_content_from_url( - _info.modelfile_link) + if re.fullmatch(_info.template_regex, name): + if _info.modelfile_prefix and not kwargs.get('ignore_oss_model_file', False): + template_str = TemplateLoader._read_content_from_url( + _info.modelfile_prefix + '.template') + if not template_str: + logger.info(f'{name} has no template file.') + params = TemplateLoader._read_content_from_url(_info.modelfile_prefix + '.params') + if params: + params = json.loads(params) + else: + logger.info(f'{name} has no params file.') + license = TemplateLoader._read_content_from_url( + _info.modelfile_prefix + '.license') + if not template_str: + logger.info(f'{name} has no license file.') + format_out = TemplateLoader._format_return(template_str, params, split, license) + if debug: + return format_out, _info + return format_out if template_name: template = TemplateLoader.load_by_template_name( template_name, **kwargs) @@ -352,30 +921,31 @@ class TemplateLoader: template = TemplateLoader.load_by_model_id( model_id, **kwargs) - if template is None: + if not template: return None - - content = '' - content += 'FROM {gguf_file}\n' + + # template + template_lines = '' _prefix = TemplateLoader.replace_and_concat(template, template.prefix, "", "") if _prefix: - content += ( - f'TEMPLATE """{{{{ if .System }}}}' + template_lines += ( + f'{{{{ if .System }}}}' f'{TemplateLoader.replace_and_concat(template, template.system_prefix or [], "{{SYSTEM}}", "{{ .System }}")}' f'{{{{ else }}}}{_prefix}' f'{{{{ end }}}}') else: - content += ( - f'TEMPLATE """{{{{ if .System }}}}' + template_lines += ( + f'{{{{ if .System }}}}' f'{TemplateLoader.replace_and_concat(template, template.system_prefix or [], "{{SYSTEM}}", "{{ .System }}")}' f'{{{{ end }}}}') - content += ( + template_lines += ( f'{{{{ if .Prompt }}}}' f'{TemplateLoader.replace_and_concat(template, template.prompt, "{{QUERY}}", "{{ .Prompt }}")}' f'{{{{ end }}}}') - content += '{{ .Response }}' - content += TemplateLoader.replace_and_concat(template, template.suffix, - '', '') + '"""\n' + template_lines += '{{ .Response }}' + template_lines += TemplateLoader.replace_and_concat(template, template.suffix, + '', '') + # stop tokens all_eos_tokens = {TemplateLoader.replace_and_concat(template, template.suffix, "", "")} if getattr(template, 'tokenizer', None): eos_token = TemplateLoader.replace_and_concat(template, [["eos_token_id"]], "", "") @@ -384,13 +954,20 @@ class TemplateLoader: eos_token_id = template.config.eos_token_id eos_token = TemplateLoader.replace_and_concat(template, [[eos_token_id]], "", "") all_eos_tokens.add(eos_token) + + stop_tokens = list() for eos_token in all_eos_tokens: - content += f'PARAMETER stop "{eos_token}"\n' - return content + stop_tokens.append(eos_token) + params = {'stop': stop_tokens} + + return TemplateLoader._format_return(template_lines, params, split) @staticmethod def _read_content_from_url(url): - response = requests.get(url) - response.raise_for_status() + try: + response = requests.get(url) + response.raise_for_status() + except requests.exceptions.HTTPError as e: + return None content = response.content return content.decode('utf-8') diff --git a/modelscope/utils/constant.py b/modelscope/utils/constant.py index ae2f647c..ffc6f816 100644 --- a/modelscope/utils/constant.py +++ b/modelscope/utils/constant.py @@ -293,6 +293,10 @@ class ScienceTasks(object): protein_structure = 'protein-structure' +class Other(object): + other = 'other' + + class TasksIODescriptions(object): image_to_image = 'image_to_image', images_to_image = 'images_to_image', @@ -310,7 +314,8 @@ class TasksIODescriptions(object): efficient_diffusion_tuning = 'efficient_diffusion_tuning' -class Tasks(CVTasks, NLPTasks, AudioTasks, MultiModalTasks, ScienceTasks): +class Tasks(CVTasks, NLPTasks, AudioTasks, MultiModalTasks, ScienceTasks, + Other): """ Names for tasks supported by modelscope. Holds the standard task name to use for identifying different tasks. diff --git a/modelscope/utils/hub.py b/modelscope/utils/hub.py index 20fb0e20..39ca644a 100644 --- a/modelscope/utils/hub.py +++ b/modelscope/utils/hub.py @@ -22,15 +22,9 @@ def create_model_if_not_exist( model_id: str, chinese_name: str, visibility: Optional[int] = ModelVisibility.PUBLIC, - license: Optional[str] = Licenses.APACHE_V2, - revision: Optional[str] = DEFAULT_MODEL_REVISION): - exists = True - try: - api.get_model(model_id=model_id, revision=revision) - except HTTPError: - exists = False - if exists: - print(f'model {model_id} already exists, skip creation.') + license: Optional[str] = Licenses.APACHE_V2): + if api.repo_exists(model_id): + logger.info(f'model {model_id} already exists, skip creation.') return False else: api.create_model( @@ -39,7 +33,7 @@ def create_model_if_not_exist( license=license, chinese_name=chinese_name, ) - print(f'model {model_id} successfully created.') + logger.info(f'model {model_id} successfully created.') return True diff --git a/requirements/nlp.txt b/requirements/nlp.txt index f69f869b..2bff6747 100644 --- a/requirements/nlp.txt +++ b/requirements/nlp.txt @@ -17,7 +17,7 @@ sacremoses>=0.0.41 scikit_learn sentencepiece seqeval -spacy>=2.3.5 +spacy>=2.3.5,<=3.7.0 stanza subword_nmt>=0.3.8 termcolor diff --git a/tests/hub/test_hub_examples.py b/tests/hub/test_hub_examples.py index d1f7594e..ab3cff1d 100644 --- a/tests/hub/test_hub_examples.py +++ b/tests/hub/test_hub_examples.py @@ -6,7 +6,7 @@ from modelscope.hub.api import HubApi from modelscope.utils.hub import create_model_if_not_exist # note this is temporary before official account management is ready -YOUR_ACCESS_TOKEN = 'token' +YOUR_ACCESS_TOKEN = 'Get SDK token from https://www.modelscope.cn/my/myaccesstoken' class HubExampleTest(unittest.TestCase): @@ -18,10 +18,10 @@ class HubExampleTest(unittest.TestCase): @unittest.skip('to be used for local test only') def test_example_model_creation(self): # ATTENTION:change to proper model names before use - model_name = 'cv_unet_person-image-cartoon_compound-models' - model_chinese_name = '达摩卡通化模型' - model_org = 'damo' - model_id = '%s/%s' % (model_org, model_name) + model_name = 'model-name' + model_chinese_name = '我的测试模型' + model_owner = 'iic' + model_id = '%s/%s' % (model_owner, model_name) created = create_model_if_not_exist(self.api, model_id, model_chinese_name) if not created: diff --git a/tests/hub/test_hub_upload.py b/tests/hub/test_hub_upload.py index 2a66cb8b..8a67a9de 100644 --- a/tests/hub/test_hub_upload.py +++ b/tests/hub/test_hub_upload.py @@ -47,6 +47,12 @@ class HubUploadTest(unittest.TestCase): except Exception: pass + def test_repo_exist(self): + res = self.api.repo_exists('Qwen/Qwen2.5-7B-Instruct') + self.assertTrue(res) + res = self.api.repo_exists('Qwen/not-a-repo') + self.assertFalse(res) + def test_upload_exits_repo_master(self): logger.info('basic test for upload!') self.api.login(TEST_ACCESS_TOKEN1) diff --git a/tests/pipelines/test_text_error_correction.py b/tests/pipelines/test_text_error_correction.py index b4bf5be9..b2a5fd4d 100644 --- a/tests/pipelines/test_text_error_correction.py +++ b/tests/pipelines/test_text_error_correction.py @@ -41,12 +41,16 @@ class TextErrorCorrectionTest(unittest.TestCase): @unittest.skipUnless(test_level() >= 0, 'skip test in current test level') def test_run_with_model_name_batch(self): - run_kwargs = {'batch_size': 2} pipeline_ins = pipeline( task=Tasks.text_error_correction, model=self.model_id) - print( - 'batch: ', - pipeline_ins([self.input, self.input_2, self.input_3], run_kwargs)) + sents = [ + self.input, self.input_2, self.input_3, self.input_4, + self.input_law + ] + rs1 = pipeline_ins(sents, batch_size=2) + rs2 = pipeline_ins(sents) + print('batch: ', rs1, rs2) + self.assertEqual(rs1, rs2) @unittest.skipUnless(test_level() >= 1, 'skip test in current test level') def test_run_with_model_from_modelhub(self): diff --git a/tests/tools/test_to_ollama.py b/tests/tools/test_to_ollama.py index ad7a3e87..d64af6dd 100644 --- a/tests/tools/test_to_ollama.py +++ b/tests/tools/test_to_ollama.py @@ -7,6 +7,12 @@ from modelscope.preprocessors.templates.loader import TemplateLoader from modelscope.utils.test_utils import test_level +def _test_check_tmpl_type(model, tmpl_type): + ollama, info = TemplateLoader.to_ollama(model, debug=True) + assert info.__dict__.get('modelfile_prefix').split( + '/')[-1] == tmpl_type, info + + class TestToOllama(unittest.TestCase): @unittest.skipUnless(test_level() >= 0, 'skip test in current test level') @@ -39,7 +45,7 @@ class TestToOllama(unittest.TestCase): self.assertTrue(template.template_type == TemplateType.deepseek) template = TemplateLoader.load_by_model_id( - 'deepseek-ai/DeepSeek-Coder-V2-Instruct') + 'deepseek-ai/DeepSeek-V2-Lite-Chat') self.assertTrue(template.template_type == TemplateType.deepseek2) template = TemplateLoader.load_by_model_id('01ai/Yi-1.5-9B-Chat') @@ -53,11 +59,11 @@ class TestToOllama(unittest.TestCase): self.assertTrue(template.template_type == TemplateType.gemma) template = TemplateLoader.load_by_model_id('AI-ModelScope/gemma-2b') - self.assertTrue(template is None) + self.assertTrue(template.template_type == TemplateType.gemma) template = TemplateLoader.load_by_model_id( 'AI-ModelScope/gemma-2b-instruct') - self.assertTrue(template is None) + self.assertTrue(template.template_type == TemplateType.gemma) template = TemplateLoader.load_by_model_id( 'AI-ModelScope/gemma2-2b-instruct') @@ -108,6 +114,187 @@ class TestToOllama(unittest.TestCase): ollama = TemplateLoader.to_ollama( '01ai/Yi-1.5-9B-Chat', ignore_oss_model_file=True) self.assertTrue(ollama is not None) + ollama = TemplateLoader.to_ollama( + 'QuantFactory/Mistral-7B-Instruct-v0.1-GGUF', + ignore_oss_model_file=True) + self.assertTrue(ollama is not None) + + @unittest.skipUnless(test_level() >= 0, 'skip test in current test level') + def test_check_template_type(self): + _test_check_tmpl_type('LLM-Research/Meta-Llama-3.2-8B-Instruct-GGUF', + 'llama3.2') + _test_check_tmpl_type('LLM-Research/Meta-Llama-3.1-8B-Instruct-GGUF', + 'llama3.1') + _test_check_tmpl_type('LLM-Research/Meta-Llama-3-8B-Instruct-GGUF', + 'llama3') + _test_check_tmpl_type( + 'LLM-Research/Llama-3-8B-Instruct-Gradient-4194k-GGUF', + 'llama3-gradient') + _test_check_tmpl_type('QuantFactory/Llama-3-Groq-8B-Tool-Use-GGUF', + 'llama3-groq-tool-use') + _test_check_tmpl_type('QuantFactory/Llama3-ChatQA-1.5-8B-GGUF', + 'llama3-chatqa') + _test_check_tmpl_type('SinpxAI/Llama2-Chinese-7B-Chat-GGUF', + 'llama2-chinese') + _test_check_tmpl_type('QuantFactory/dolphin-2.9-llama3-70b-GGUF', + 'dolphin-llama3') + _test_check_tmpl_type('AI-ModelScope/llava-llama-3-8b-v1_1-gguf', + 'llava-llama3') + _test_check_tmpl_type('Xorbits/Llama-2-7b-Chat-GGUF', 'llama2') + _test_check_tmpl_type('QuantFactory/MathCoder2-CodeLlama-7B-GGUF', + 'codellama') + _test_check_tmpl_type('QuantFactory/TinyLlama-1.1B-Chat-v1.0-GGUF', + 'tinyllama') + _test_check_tmpl_type('AI-ModelScope/LLaMA-Pro-8B-Instruct', + 'llama-pro') + _test_check_tmpl_type('LLM-Research/Llama-Guard-3-8B', 'llama-guard3') + _test_check_tmpl_type('Qwen/Qwen2.5-3B-Instruct-GGUF', 'qwen2.5') + _test_check_tmpl_type('Xorbits/Qwen-14B-Chat-GGUF', 'qwen') + _test_check_tmpl_type('QuantFactory/Qwen2-7B-GGUF', 'qwen2') + _test_check_tmpl_type('QuantFactory/Qwen2-Math-7B-GGUF', 'qwen2-math') + _test_check_tmpl_type('Qwen/CodeQwen1.5-7B-Chat-GGUF', 'codeqwen') + _test_check_tmpl_type('Qwen/Qwen2.5-Coder-7B-Instruct-GGUF', + 'qwen2.5-coder') + _test_check_tmpl_type('QuantFactory/Gemma-2-Ataraxy-9B-Chat-GGUF', + 'gemma2') + _test_check_tmpl_type( + 'QuantFactory/Athene-codegemma-2-7b-it-alpaca-v1.1-GGUF', + 'codegemma') + _test_check_tmpl_type('QuantFactory/gemma-7b-GGUF', 'gemma') + _test_check_tmpl_type('QuantFactory/shieldgemma-2b-GGUF', + 'shieldgemma') + _test_check_tmpl_type( + 'ZhaoningLi/laser-dolphin-mixtral-2x7b-dpo.fp16.gguf', + 'dolphin-mixtral') + _test_check_tmpl_type('QuantFactory/dolphin-2.1-mistral-7b-GGUF', + 'dolphin-mistral') + _test_check_tmpl_type('xtuner/llava-phi-3-mini', 'llava-phi3') + _test_check_tmpl_type('QuantFactory/Phi-3.5-mini-instruct-GGUF', + 'phi3.5') + _test_check_tmpl_type('AI-ModelScope/Phi-3-medium-128k-instruct-GGUF', + 'phi3') + _test_check_tmpl_type('QuantFactory/phi-2-GGUF', 'phi') + _test_check_tmpl_type('alignmentforever/alpaca-Yarn-Mistral-7b-128k', + 'yarn-mistral') + _test_check_tmpl_type('LLM-Research/Mistral-Large-Instruct-2407', + 'mistral-large') + _test_check_tmpl_type('AI-ModelScope/MistralLite', 'mistrallite') + _test_check_tmpl_type('AI-ModelScope/Mistral-Small-Instruct-2409', + 'mistral-small') + _test_check_tmpl_type('LLM-Research/Mistral-Nemo-Instruct-2407-GGUF', + 'mistral-nemo') + _test_check_tmpl_type('QuantFactory/Mistral-7B-OpenOrca-GGUF', + 'mistral-openorca') + _test_check_tmpl_type('QuantFactory/Mistral-7B-Instruct-v0.1-GGUF', + 'mistral') + _test_check_tmpl_type( + 'second-state/Nous-Hermes-2-Mixtral-8x7B-SFT-GGUF', + 'nous-hermes2-mixtral') + _test_check_tmpl_type('AI-ModelScope/Mixtral-8x22B-v0.1-GGUF', + 'mixtral') + _test_check_tmpl_type('QuantFactory/Nemotron-Mini-4B-Instruct-GGUF', + 'nemotron-mini') + _test_check_tmpl_type('AI-ModelScope/Nemotron-4-340B-Instruct', + 'nemotron') + _test_check_tmpl_type('TIGER-Lab/Mantis-bakllava-7b', 'bakllava') + _test_check_tmpl_type('fireicewolf/llava-v1.6-34B-gguf', 'llava') + _test_check_tmpl_type( + 'AI-ModelScope/DeepSeek-Coder-V2-Lite-Instruct-GGUF', + 'deepseek-coder-v2') + _test_check_tmpl_type('QuantFactory/deepseek-coder-6.7B-kexer-GGUF', + 'deepseek-coder') + _test_check_tmpl_type('deepseek-ai/DeepSeek-V2.5', 'deepseek-v2.5') + _test_check_tmpl_type('deepseek-ai/DeepSeek-V2-Lite-Chat', + 'deepseek-v2') + _test_check_tmpl_type('deepseek-ai/deepseek-llm-67b-chat', + 'deepseek-llm') + _test_check_tmpl_type('LLM-Research/glm-4-9b-chat-GGUF', 'glm4') + _test_check_tmpl_type('AI-ModelScope/Yi-Coder-9B-Chat-GGUF', + 'yi-coder') + _test_check_tmpl_type('01ai/Yi-1.5-9B-Chat', 'yi') + _test_check_tmpl_type('AI-ModelScope/c4ai-command-r-plus', + 'command-r-plus') + _test_check_tmpl_type('AI-ModelScope/c4ai-command-r-v01', 'command-r') + _test_check_tmpl_type('LLM-Research/codegeex4-all-9b-GGUF', + 'codegeex4') + _test_check_tmpl_type('a7823093/Wizard-Vicuna-13B-Uncensored-HF', + 'wizard-vicuna-uncensored') + _test_check_tmpl_type('AI-ModelScope/WizardLM-2-8x22B-GGUF', + 'wizardlm2') + _test_check_tmpl_type('AI-ModelScope/WizardCoder-Python-34B-V1.0', + 'wizardcoder') + _test_check_tmpl_type('AI-ModelScope/WizardMath-7B-V1.0', + 'wizard-math') + _test_check_tmpl_type('AI-ModelScope/WizardLM-7B-V1.0', 'wizardlm') + _test_check_tmpl_type('QuantFactory/vicuna-13b-v1.5-GGUF', 'vicuna') + _test_check_tmpl_type('QuantFactory/Nous-Hermes-2-SOLAR-10.7B-GGUF', + 'nous-hermes2') + _test_check_tmpl_type('QuantFactory/stable-code-instruct-3b-GGUF', + 'stable-code') + _test_check_tmpl_type('AI-ModelScope/stablelm-tuned-alpha-7b', + 'stablelm2') + _test_check_tmpl_type('QuantFactory/internlm2-chat-7b-GGUF', + 'internlm2') + _test_check_tmpl_type('openbmb/MiniCPM-V-2-gguf', 'minicpm-v') + _test_check_tmpl_type('QuantFactory/Codestral-22B-v0.1-GGUF', + 'codestral') + _test_check_tmpl_type('AI-ModelScope/nomic-embed-text-v1', + 'nomic-embed-text') + _test_check_tmpl_type('AI-ModelScope/mxbai-embed-large-v1', + 'mxbai-embed-large') + _test_check_tmpl_type('AI-ModelScope/starcoder2-7b', 'starcoder2') + _test_check_tmpl_type('QwenCollection/orca_mini_v7_72b', 'orca-mini') + _test_check_tmpl_type('modelscope/zephyr-7b-beta', 'zephyr') + _test_check_tmpl_type('LLM-Research/snowflake-arctic-embed-m', + 'snowflake-arctic-embed') + _test_check_tmpl_type('TabbyML/StarCoder-1B', 'starcoder') + _test_check_tmpl_type('QuantFactory/granite-8b-code-instruct-4k-GGUF', + 'granite-code') + _test_check_tmpl_type('AI-ModelScope/all-MiniLM-L6-v2', 'all-minilm') + _test_check_tmpl_type('QuantFactory/openchat-3.6-8b-20240522-GGUF', + 'openchat') + _test_check_tmpl_type('AI-ModelScope/aya-101', 'aya') + _test_check_tmpl_type('LLM-Research/OpenHermes-2.5-Mistral-7B', + 'openhermes') + _test_check_tmpl_type('AI-ModelScope/Reflection-Llama-3.1-70B', + 'reflection') + _test_check_tmpl_type('AI-ModelScope/neural-chat-7b-v3-1', + 'neural-chat') + _test_check_tmpl_type('AI-ModelScope/moondream1', 'moondream') + _test_check_tmpl_type('AI-ModelScope/Xwin-LM-70B-V0.1', 'xwinlm') + _test_check_tmpl_type( + 'QuantFactory/smollm-360M-instruct-add-basics-GGUF', 'smollm') + _test_check_tmpl_type('AI-ModelScope/sqlcoder-7b-2', 'sqlcoder') + _test_check_tmpl_type('LLM-Research/Starling-LM-7B-beta', + 'starling-lm') + _test_check_tmpl_type('AI-ModelScope/falcon-7b', 'falcon') + _test_check_tmpl_type('QuantFactory/SOLAR-10.7B-v1.0-GGUF', 'solar') + _test_check_tmpl_type('AI-ModelScope/Orca-2-13b', 'orca2') + _test_check_tmpl_type('AI-ModelScope/Hermes-3-Llama-3.1-8B', 'hermes3') + _test_check_tmpl_type('QuantFactory/meditron-7b-GGUF', 'meditron') + _test_check_tmpl_type('QuantFactory/NexusRaven-V2-13B-GGUF', + 'nexusraven') + _test_check_tmpl_type('davideuler/Magicoder-s-DS-6.7B-GGUF', + 'magicoder') + _test_check_tmpl_type('ZhejiangLab-LifeScience/falcon-assistant-2', + 'falcon2') + _test_check_tmpl_type('Xorbits/bge-m3', 'bge-m3') + _test_check_tmpl_type('AI-ModelScope/notux-8x7b-v1', 'notux') + _test_check_tmpl_type('AI-ModelScope/OpenOrca-Platypus2-13B', + 'open-orca-platypus2') + _test_check_tmpl_type('QuantFactory/notus-7b-v1-GGUF', 'notus') + _test_check_tmpl_type('AI-ModelScope/mathstral-7B-v0.1', 'mathstral') + _test_check_tmpl_type('AI-ModelScope/solar-pro-preview-instruct', + 'solar-pro') + _test_check_tmpl_type('AI-ModelScope/dbrx-instruct', 'dbrx') + _test_check_tmpl_type('QuantFactory/NuExtract-GGUF', 'nuextract') + _test_check_tmpl_type('QuantFactory/reader-lm-1.5b-GGUF', 'reader-lm') + _test_check_tmpl_type( + 'SDXL-LoRA/KappaNeuro-alfred-augustus-glendening-style', 'alfred') + _test_check_tmpl_type('AI-ModelScope/bge-large-zh-v1.5', 'bge-large') + _test_check_tmpl_type( + 'Ceceliachenen/paraphrase-multilingual-MiniLM-L12-v2', + 'paraphrase-multilingual') if __name__ == '__main__':