diff --git a/modelscope/hub/api.py b/modelscope/hub/api.py index e4b9b1af..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() @@ -268,7 +271,7 @@ class HubApi: Returns: True if the repository exists, False otherwise. """ - if (repo_type is not None) and repo_type.lower != 'model': + 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) @@ -280,16 +283,25 @@ class HubApi: r = self.session.get(path, cookies=cookies, headers=self.builder_headers(self.headers)) code = handle_http_response(r, logger, cookies, repo_id, False) - logger.info(f'check repo_exists status code {code}.') 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, @@ -357,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, @@ -382,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/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/utils/utils.py b/modelscope/hub/utils/utils.py index 6cc53285..bb38f26a 100644 --- a/modelscope/hub/utils/utils.py +++ b/modelscope/hub/utils/utils.py @@ -38,6 +38,30 @@ def get_model_masked_directory(directory, model_id): return masked_directory +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/pipelines/multi_modal/ovis_vl_pipeline.py b/modelscope/pipelines/multi_modal/ovis_vl_pipeline.py new file mode 100644 index 00000000..f19eddff --- /dev/null +++ b/modelscope/pipelines/multi_modal/ovis_vl_pipeline.py @@ -0,0 +1,103 @@ +from typing import Any, Dict, Union + +import torch + +from modelscope import AutoModelForCausalLM +from modelscope.metainfo import Pipelines, Preprocessors +from modelscope.models.base import Model +from modelscope.outputs import OutputKeys +from modelscope.pipelines.base import Pipeline +from modelscope.pipelines.builder import PIPELINES +from modelscope.pipelines.multi_modal.visual_question_answering_pipeline import \ + VisualQuestionAnsweringPipeline +from modelscope.preprocessors import Preprocessor, load_image +from modelscope.utils.constant import Fields, Frameworks, Tasks + + +@PIPELINES.register_module( + Tasks.visual_question_answering, module_name='ovis-vl') +class VisionChatPipeline(VisualQuestionAnsweringPipeline): + + def __init__(self, + model: Union[Model, str], + preprocessor: Preprocessor = None, + config_file: str = None, + device: str = 'gpu', + auto_collate=True, + **kwargs): + # super().__init__ + self.device_name = device + self.framework = Frameworks.torch + self._model_prepare = True + self._auto_collate = auto_collate + + # ovis + torch_dtype = kwargs.get('torch_dtype', torch.float16) + multimodal_max_length = kwargs.get('multimodal_max_length', 8192) + self.device = 'cuda' if device == 'gpu' else device + self.model = AutoModelForCausalLM.from_pretrained( + model, + torch_dtype=torch_dtype, + multimodal_max_length=multimodal_max_length, + trust_remote_code=True).to(self.device) + self.text_tokenizer = self.model.get_text_tokenizer() + self.visual_tokenizer = self.model.get_visual_tokenizer() + + def preprocess(self, inputs: Dict[str, Any]): + text = inputs['text'] + image_path_or_url = inputs['image'] + image = load_image(image_path_or_url) + query = f'\n{text}' + _, input_ids, pixel_values = self.model.preprocess_inputs( + query, [image]) + attention_mask = torch.ne(input_ids, self.text_tokenizer.pad_token_id) + input_ids = input_ids.unsqueeze(0).to(device=self.model.device) + attention_mask = attention_mask.unsqueeze(0).to( + device=self.model.device) + pixel_values = [ + pixel_values.to( + dtype=self.visual_tokenizer.dtype, + device=self.visual_tokenizer.device) + ] + + return { + 'input_ids': input_ids, + 'pixel_values': pixel_values, + 'attention_mask': attention_mask + } + + def forward(self, inputs: Dict[str, Any], + **forward_params) -> Dict[str, Any]: + input_ids = inputs['input_ids'] + pixel_values = inputs['pixel_values'] + attention_mask = inputs['attention_mask'] + + max_new_tokens = forward_params.get('max_new_tokens', 1024) + do_sample = forward_params.get('do_sample', False) + top_p = forward_params.get('top_p', None) + top_k = forward_params.get('top_k', None) + temperature = forward_params.get('temperature', None) + repetition_penalty = forward_params.get('repetition_penalty', None) + with torch.inference_mode(): + gen_kwargs = dict( + max_new_tokens=max_new_tokens, + do_sample=do_sample, + top_p=top_p, + top_k=top_k, + temperature=temperature, + repetition_penalty=repetition_penalty, + eos_token_id=self.model.generation_config.eos_token_id, + pad_token_id=self.text_tokenizer.pad_token_id, + use_cache=True) + output_ids = self.model.generate( + input_ids, + pixel_values=pixel_values, + attention_mask=attention_mask, + **gen_kwargs)[0] + return {'output_ids': output_ids} + + def postprocess(self, inputs: Dict[str, Any]) -> Dict[str, Any]: + output_ids = inputs['output_ids'] + output = self.text_tokenizer.decode( + output_ids, skip_special_tokens=True) + return {OutputKeys.TEXT: output} 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/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__':