From ae7af0a6c25c77e96761df64c6bc1305c6c574d5 Mon Sep 17 00:00:00 2001 From: Joshua Lochner Date: Tue, 6 Feb 2024 12:44:30 +0200 Subject: [PATCH] Add support for Qwen2 models (#570) * Add support for `Qwen2Tokenizer` * Add qwen-specific tokenizer unit test * Add support for qwen2 models * Fix typo --- README.md | 1 + docs/snippets/6_supported-models.snippet | 1 + scripts/convert.py | 4 +++ scripts/supported_models.py | 9 ++++++ src/models.js | 36 ++++++++++++++++++++++++ src/tokenizers.js | 19 ++++++++++++- tests/generate_tests.py | 10 ++++++- 7 files changed, 78 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 87abab110..ed320d40a 100644 --- a/README.md +++ b/README.md @@ -325,6 +325,7 @@ You can refine your search by selecting the task you're interested in (e.g., [te 1. **[OPT](https://huggingface.co/docs/transformers/master/model_doc/opt)** (from Meta AI) released with the paper [OPT: Open Pre-trained Transformer Language Models](https://arxiv.org/abs/2205.01068) by Susan Zhang, Stephen Roller, Naman Goyal, Mikel Artetxe, Moya Chen, Shuohui Chen et al. 1. **[OWL-ViT](https://huggingface.co/docs/transformers/model_doc/owlvit)** (from Google AI) released with the paper [Simple Open-Vocabulary Object Detection with Vision Transformers](https://arxiv.org/abs/2205.06230) by Matthias Minderer, Alexey Gritsenko, Austin Stone, Maxim Neumann, Dirk Weissenborn, Alexey Dosovitskiy, Aravindh Mahendran, Anurag Arnab, Mostafa Dehghani, Zhuoran Shen, Xiao Wang, Xiaohua Zhai, Thomas Kipf, and Neil Houlsby. 1. **[Phi](https://huggingface.co/docs/transformers/main/model_doc/phi)** (from Microsoft) released with the papers - [Textbooks Are All You Need](https://arxiv.org/abs/2306.11644) by Suriya Gunasekar, Yi Zhang, Jyoti Aneja, Caio César Teodoro Mendes, Allie Del Giorno, Sivakanth Gopi, Mojan Javaheripi, Piero Kauffmann, Gustavo de Rosa, Olli Saarikivi, Adil Salim, Shital Shah, Harkirat Singh Behl, Xin Wang, Sébastien Bubeck, Ronen Eldan, Adam Tauman Kalai, Yin Tat Lee and Yuanzhi Li, [Textbooks Are All You Need II: phi-1.5 technical report](https://arxiv.org/abs/2309.05463) by Yuanzhi Li, Sébastien Bubeck, Ronen Eldan, Allie Del Giorno, Suriya Gunasekar and Yin Tat Lee. +1. **[Qwen2](https://huggingface.co/docs/transformers/model_doc/qwen2)** (from the Qwen team, Alibaba Group) released with the paper [Qwen Technical Report](https://arxiv.org/abs/2309.16609) by Jinze Bai, Shuai Bai, Yunfei Chu, Zeyu Cui, Kai Dang, Xiaodong Deng, Yang Fan, Wenbin Ge, Yu Han, Fei Huang, Binyuan Hui, Luo Ji, Mei Li, Junyang Lin, Runji Lin, Dayiheng Liu, Gao Liu, Chengqiang Lu, Keming Lu, Jianxin Ma, Rui Men, Xingzhang Ren, Xuancheng Ren, Chuanqi Tan, Sinan Tan, Jianhong Tu, Peng Wang, Shijie Wang, Wei Wang, Shengguang Wu, Benfeng Xu, Jin Xu, An Yang, Hao Yang, Jian Yang, Shusheng Yang, Yang Yao, Bowen Yu, Hongyi Yuan, Zheng Yuan, Jianwei Zhang, Xingxuan Zhang, Yichang Zhang, Zhenru Zhang, Chang Zhou, Jingren Zhou, Xiaohuan Zhou and Tianhang Zhu. 1. **[ResNet](https://huggingface.co/docs/transformers/model_doc/resnet)** (from Microsoft Research) released with the paper [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385) by Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun. 1. **[RoBERTa](https://huggingface.co/docs/transformers/model_doc/roberta)** (from Facebook), released together with the paper [RoBERTa: A Robustly Optimized BERT Pretraining Approach](https://arxiv.org/abs/1907.11692) by Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov. 1. **[RoFormer](https://huggingface.co/docs/transformers/model_doc/roformer)** (from ZhuiyiTechnology), released together with the paper [RoFormer: Enhanced Transformer with Rotary Position Embedding](https://arxiv.org/abs/2104.09864) by Jianlin Su and Yu Lu and Shengfeng Pan and Bo Wen and Yunfeng Liu. diff --git a/docs/snippets/6_supported-models.snippet b/docs/snippets/6_supported-models.snippet index 6d4082379..4eb762aa1 100644 --- a/docs/snippets/6_supported-models.snippet +++ b/docs/snippets/6_supported-models.snippet @@ -60,6 +60,7 @@ 1. **[OPT](https://huggingface.co/docs/transformers/master/model_doc/opt)** (from Meta AI) released with the paper [OPT: Open Pre-trained Transformer Language Models](https://arxiv.org/abs/2205.01068) by Susan Zhang, Stephen Roller, Naman Goyal, Mikel Artetxe, Moya Chen, Shuohui Chen et al. 1. **[OWL-ViT](https://huggingface.co/docs/transformers/model_doc/owlvit)** (from Google AI) released with the paper [Simple Open-Vocabulary Object Detection with Vision Transformers](https://arxiv.org/abs/2205.06230) by Matthias Minderer, Alexey Gritsenko, Austin Stone, Maxim Neumann, Dirk Weissenborn, Alexey Dosovitskiy, Aravindh Mahendran, Anurag Arnab, Mostafa Dehghani, Zhuoran Shen, Xiao Wang, Xiaohua Zhai, Thomas Kipf, and Neil Houlsby. 1. **[Phi](https://huggingface.co/docs/transformers/main/model_doc/phi)** (from Microsoft) released with the papers - [Textbooks Are All You Need](https://arxiv.org/abs/2306.11644) by Suriya Gunasekar, Yi Zhang, Jyoti Aneja, Caio César Teodoro Mendes, Allie Del Giorno, Sivakanth Gopi, Mojan Javaheripi, Piero Kauffmann, Gustavo de Rosa, Olli Saarikivi, Adil Salim, Shital Shah, Harkirat Singh Behl, Xin Wang, Sébastien Bubeck, Ronen Eldan, Adam Tauman Kalai, Yin Tat Lee and Yuanzhi Li, [Textbooks Are All You Need II: phi-1.5 technical report](https://arxiv.org/abs/2309.05463) by Yuanzhi Li, Sébastien Bubeck, Ronen Eldan, Allie Del Giorno, Suriya Gunasekar and Yin Tat Lee. +1. **[Qwen2](https://huggingface.co/docs/transformers/model_doc/qwen2)** (from the Qwen team, Alibaba Group) released with the paper [Qwen Technical Report](https://arxiv.org/abs/2309.16609) by Jinze Bai, Shuai Bai, Yunfei Chu, Zeyu Cui, Kai Dang, Xiaodong Deng, Yang Fan, Wenbin Ge, Yu Han, Fei Huang, Binyuan Hui, Luo Ji, Mei Li, Junyang Lin, Runji Lin, Dayiheng Liu, Gao Liu, Chengqiang Lu, Keming Lu, Jianxin Ma, Rui Men, Xingzhang Ren, Xuancheng Ren, Chuanqi Tan, Sinan Tan, Jianhong Tu, Peng Wang, Shijie Wang, Wei Wang, Shengguang Wu, Benfeng Xu, Jin Xu, An Yang, Hao Yang, Jian Yang, Shusheng Yang, Yang Yao, Bowen Yu, Hongyi Yuan, Zheng Yuan, Jianwei Zhang, Xingxuan Zhang, Yichang Zhang, Zhenru Zhang, Chang Zhou, Jingren Zhou, Xiaohuan Zhou and Tianhang Zhu. 1. **[ResNet](https://huggingface.co/docs/transformers/model_doc/resnet)** (from Microsoft Research) released with the paper [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385) by Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun. 1. **[RoBERTa](https://huggingface.co/docs/transformers/model_doc/roberta)** (from Facebook), released together with the paper [RoBERTa: A Robustly Optimized BERT Pretraining Approach](https://arxiv.org/abs/1907.11692) by Yinhan Liu, Myle Ott, Naman Goyal, Jingfei Du, Mandar Joshi, Danqi Chen, Omer Levy, Mike Lewis, Luke Zettlemoyer, Veselin Stoyanov. 1. **[RoFormer](https://huggingface.co/docs/transformers/model_doc/roformer)** (from ZhuiyiTechnology), released together with the paper [RoFormer: Enhanced Transformer with Rotary Position Embedding](https://arxiv.org/abs/2104.09864) by Jianlin Su and Yu Lu and Shengfeng Pan and Bo Wen and Yunfeng Liu. diff --git a/scripts/convert.py b/scripts/convert.py index 78232aab7..445dbb429 100644 --- a/scripts/convert.py +++ b/scripts/convert.py @@ -79,6 +79,10 @@ 'per_channel': False, 'reduce_range': False, }, + 'qwen2': { + 'per_channel': False, + 'reduce_range': False, + }, # Encoder-decoder models 'whisper': { diff --git a/scripts/supported_models.py b/scripts/supported_models.py index 6ca884e43..fd9ea99cb 100644 --- a/scripts/supported_models.py +++ b/scripts/supported_models.py @@ -731,6 +731,15 @@ 'susnato/phi-1_5_dev', ], }, + 'qwen2': { + # Text generation + 'text-generation': [ + 'Qwen/Qwen1.5-0.5B', + 'Qwen/Qwen1.5-0.5B-Chat', + 'Qwen/Qwen1.5-1.8B', + 'Qwen/Qwen1.5-1.8B-Chat', + ], + }, 'roberta': { # Feature extraction 'feature-extraction': [ diff --git a/src/models.js b/src/models.js index 19119ecfe..aa181d2e2 100644 --- a/src/models.js +++ b/src/models.js @@ -3556,6 +3556,40 @@ export class LlamaModel extends LlamaPreTrainedModel { } export class LlamaForCausalLM extends LlamaPreTrainedModel { } ////////////////////////////////////////////////// +////////////////////////////////////////////////// +// Qwen2 models + +/** + * The bare Qwen2 Model outputting raw hidden-states without any specific head on top. + */ +export class Qwen2PreTrainedModel extends PreTrainedModel { + /** + * Creates a new instance of the `Qwen2PreTrainedModel` class. + * @param {Object} config The model configuration object. + * @param {Object} session The ONNX session object. + * @param {GenerationConfig} generation_config The generation configuration. + */ + constructor(config, session, generation_config) { + super(config, session); + this.generation_config = generation_config; + + // config doesn't contain pad_token_id, so we assume it is the eos_token_id + this.config.pad_token_id = this.config.eos_token_id + + this.num_heads = this.config.num_key_value_heads ?? this.config.num_attention_heads + this.num_layers = this.config.num_hidden_layers + this.dim_kv = this.config.hidden_size / this.config.num_attention_heads + } +} +/** + * The bare Qwen2 Model outputting raw hidden-states without any specific head on top. + */ +export class Qwen2Model extends Qwen2PreTrainedModel { } + +export class Qwen2ForCausalLM extends Qwen2PreTrainedModel { } +////////////////////////////////////////////////// + + ////////////////////////////////////////////////// // Phi models @@ -5249,6 +5283,7 @@ const MODEL_MAPPING_NAMES_DECODER_ONLY = new Map([ ['gpt_neox', ['GPTNeoXModel', GPTNeoXModel]], ['codegen', ['CodeGenModel', CodeGenModel]], ['llama', ['LlamaModel', LlamaModel]], + ['qwen2', ['Qwen2Model', Qwen2Model]], ['phi', ['PhiModel', PhiModel]], ['mpt', ['MptModel', MptModel]], ['opt', ['OPTModel', OPTModel]], @@ -5327,6 +5362,7 @@ const MODEL_WITH_LM_HEAD_MAPPING_NAMES = new Map([ ['gpt_neox', ['GPTNeoXForCausalLM', GPTNeoXForCausalLM]], ['codegen', ['CodeGenForCausalLM', CodeGenForCausalLM]], ['llama', ['LlamaForCausalLM', LlamaForCausalLM]], + ['qwen2', ['Qwen2ForCausalLM', Qwen2ForCausalLM]], ['phi', ['PhiForCausalLM', PhiForCausalLM]], ['mpt', ['MptForCausalLM', MptForCausalLM]], ['opt', ['OPTForCausalLM', OPTForCausalLM]], diff --git a/src/tokenizers.js b/src/tokenizers.js index a604b20ca..563e39319 100644 --- a/src/tokenizers.js +++ b/src/tokenizers.js @@ -113,7 +113,13 @@ function createPattern(pattern, invert = true) { // This isn't an issue when creating the regex w/o the 'u' flag, but it is when the 'u' flag is used. // For this reason, it is necessary to remove these backslashes before creating the regex. // See https://stackoverflow.com/a/63007777/13989043 for more information - const regex = pattern.Regex.replace(/\\([#&~])/g, '$1'); // TODO: add more characters to this list if necessary + let regex = pattern.Regex.replace(/\\([#&~])/g, '$1'); // TODO: add more characters to this list if necessary + + // We also handle special cases where the regex contains invalid (non-JS compatible) syntax. + for (const [key, value] of PROBLEMATIC_REGEX_MAP) { + regex = regex.replaceAll(key, value); + } + return new RegExp(regex, 'gu'); } else if (pattern.String !== undefined) { @@ -229,6 +235,14 @@ function whitespace_split(text) { const PUNCTUATION_REGEX = '\\p{P}\\u0021-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u007E'; +// A mapping of regex patterns to their equivalent (but longer) JS-compatible versions. +const PROBLEMATIC_REGEX_MAP = new Map([ + // This uses the case insensitive group modifier, which is not supported in JavaScript. + // When parsing the regex, an "Invalid group" error is thrown. + ["(?i:'s|'t|'re|'ve|'m|'ll|'d)", "(?:'([sS]|[tT]|[rR][eE]|[vV][eE]|[mM]|[lL][lL]|[dD]))"], +]) + + /** * Represent a token added by the user on top of the existing Model vocabulary. * AddedToken can be configured to specify the behavior they should have in various situations like: @@ -3188,6 +3202,8 @@ export class GPTNeoXTokenizer extends PreTrainedTokenizer { } export class EsmTokenizer extends PreTrainedTokenizer { } +export class Qwen2Tokenizer extends PreTrainedTokenizer { } + /** * Helper function to build translation inputs for an `NllbTokenizer` or `M2M100Tokenizer`. * @param {PreTrainedTokenizer} self The tokenizer instance. @@ -4292,6 +4308,7 @@ export class AutoTokenizer { SpeechT5Tokenizer, NougatTokenizer, VitsTokenizer, + Qwen2Tokenizer, // Base case: PreTrainedTokenizer, diff --git a/tests/generate_tests.py b/tests/generate_tests.py index f389d5cf6..81836b901 100644 --- a/tests/generate_tests.py +++ b/tests/generate_tests.py @@ -29,9 +29,13 @@ # 'Xenova/t5-tokenizer-new', ], 'bert': [ - # Uses `Whitespace` pretokenizer + # Uses `Whitespace` pretokenizer 'Xenova/jina-embeddings-v2-base-zh-tokenizer', ], + 'qwen2': [ + # Uses a pretokenizer regex which is not compatible with JavaScript. + 'Qwen/Qwen1.5-0.5B-Chat', + ], } MODELS_TO_IGNORE = [ @@ -137,6 +141,10 @@ # Special treatment of characters in certain language "ț ţ", ], + + "qwen2": [ + "i'm i'M i've i've i'Ve i'vE i'VE", + ], }, "custom": { "facebook/blenderbot_small-90M": [