thucbert-mm / cctokenizer.py
chengzl18's picture
Upload folder using huggingface_hub
fec14e9
"""Tokenization classes for ChineseCharTokenizer."""
from typing import Optional, Tuple, Union
from transformers import BertTokenizer
import numpy as np
import os
import re
import shutil
# https://www.ling.upenn.edu/courses/Spring_2003/ling538/UnicodeRanges.html
# https://www.microfocus.com/documentation/idol/IDOL/Servers/IDOLServer/11.2/Guides/html/English/expert/Content/IDOLExpert/Languages/Script_Ranges.htm
# https://www.ssec.wisc.edu/~tomw/java/unicode.html
# https://character-table.netlify.app/
# https://character-table.netlify.app/french/
# https://www.compart.com/en/unicode/U+31CE 重要:看各个unicode的编码语义信息,属于哪个编码段(block/plane)
# 联合国六个官方语言:阿拉伯文、中文、英文、法文、俄文、西班牙文
# [U_LAT] 拉丁语系的文字,包括英语、法语、西班牙语、德语等
# [U_RUS] 俄语等
# [U_ARA] 表示阿拉伯语
# [U_JAP] 日语
# [U_KOR] 韩语
# [U_LAN] 某种语言的文字,藏语, 泰语等等
# [U_CHI] 未知中文
# [U_PHO] 注音文字,音标等
# [U_RAD] 部首,笔画
# [U_PUN] 标点
# [U_GRE] 希腊字母
# [U_SYM] 各种各样的符号
# [U_COM] 组合符号,包括上下标
# [U_NUM] 序号,包括VIII,(1),(一)等,也包含一些数字
# [U_MAT] 数学符号
# [U_EMO] 表情
# ¤ 货币符号
unicode_map = [
{'token': '[U_LAT]', 'range': (0x0000, 0x007F), 'meaning': 'Basic Latin', },
{'token': '[U_LAT]', 'range': (0x0080, 0x00FF), 'meaning': 'C1 Controls and Latin-1 Supplement', }, # 拉丁字符,有德语、法语
{'token': '[U_LAT]', 'range': (0x0100, 0x017F), 'meaning': 'Latin Extended-A', }, # 有法语,例如œ
{'token': '[U_LAT]', 'range': (0x0180, 0x024F), 'meaning': 'Latin Extended-B', }, # 有法语,例如Ÿ
{'token': '[U_PHO]', 'range': (0x0250, 0x02AF), 'meaning': 'IPA Extensions', }, # 国际音标,例如ə
{'token': '[U_PHO]', 'range': (0x02B0, 0x02FF), 'meaning': 'Spacing Modifier Letters', }, # 国际音标,例如ʳ
{'token': '[U_PHO]', 'range': (0x0300, 0x036F), 'meaning': 'Combining Diacritical Marks', }, # 变音符号
{'token': '[U_GRE]', 'range': (0x0370, 0x03FF), 'meaning': 'Greek/Coptic', }, # 希腊字符,例如α
{'token': '[U_RUS]', 'range': (0x0400, 0x04FF), 'meaning': 'Cyrillic', }, # 有俄语
{'token': '[U_RUS]', 'range': (0x0500, 0x052F), 'meaning': 'Cyrillic Supplement', },
{'token': '[U_LAN]', 'range': (0x0530, 0x058F), 'meaning': 'Armenian', }, # 亚美尼亚语,属于印欧语系
{'token': '[U_LAN]', 'range': (0x0590, 0x05FF), 'meaning': 'Hebrew', }, # 希伯来语,犹太族用,有以色列,属于亚非语系
{'token': '[U_ARA]', 'range': (0x0600, 0x06FF), 'meaning': 'Arabic', }, # 阿拉伯语,联合国用,有沙特,属于亚非语系
{'token': '[U_LAN]', 'range': (0x0700, 0x074F), 'meaning': 'Syriac', }, # 古叙利亚语
{'token': '[U_ARA]', 'range': (0x0750, 0x077F), 'meaning': 'Undefined -> Arabic', },
{'token': '[U_LAN]', 'range': (0x0780, 0x07BF), 'meaning': 'Thaana', }, # 它拿字母, 马尔代夫用,属于印欧语系
{'token': '[U_ARA]', 'range': (0x07C0, 0x08FF), 'meaning': 'Undefined -> Arabic', },
{'token': '[U_LAN]', 'range': (0x0900, 0x097F), 'meaning': 'Devanagari', }, # 梵语, 印度宗教用,属于印欧语系
{'token': '[U_LAN]', 'range': (0x0980, 0x09FF), 'meaning': 'Bengali/Assamese', }, # 孟加拉语
{'token': '[U_LAN]', 'range': (0x0A00, 0x0A7F), 'meaning': 'Gurmukhi', }, # 古木基文,彭加语,印度用
{'token': '[U_LAN]', 'range': (0x0A80, 0x0AFF), 'meaning': 'Gujarati', }, # 古吉拉特语,印度用
{'token': '[U_LAN]', 'range': (0x0B00, 0x0B7F), 'meaning': 'Oriya', }, # 印度用
{'token': '[U_LAN]', 'range': (0x0B80, 0x0BFF), 'meaning': 'Tamil', }, # 印度用
{'token': '[U_LAN]', 'range': (0x0C00, 0x0C7F), 'meaning': 'Telugu', }, # 印度用
{'token': '[U_LAN]', 'range': (0x0C80, 0x0CFF), 'meaning': 'Kannada', }, # 印度用
{'token': '[U_LAN]', 'range': (0x0D00, 0x0DFF), 'meaning': 'Malayalam', }, # 印度用
# {'token': '[U_LAN]', 'range': (0x0D80, 0x0DFF), 'meaning': 'Sinhala', }, # 僧伽罗语,斯里兰卡用,近印度
{'token': '[U_LAN]', 'range': (0x0E00, 0x0E7F), 'meaning': 'Thai', }, # 泰语
{'token': '[U_LAN]', 'range': (0x0E80, 0x0EFF), 'meaning': 'Lao', }, # 老挝语
{'token': '[U_LAN]', 'range': (0x0F00, 0x0FFF), 'meaning': 'Tibetan', }, # 藏语 NOTE: 藏语是否需要单独列出?
{'token': '[U_LAN]', 'range': (0x1000, 0x109F), 'meaning': 'Myanmar', }, # 缅甸语
{'token': '[U_LAN]', 'range': (0x10A0, 0x10FF), 'meaning': 'Georgian', }, # 格鲁吉亚语,伊朗也用
{'token': '[U_KOR]', 'range': (0x1100, 0x11FF), 'meaning': 'Hangul Jamo', }, # 谚文,有古韩语
{'token': '[U_LAN]', 'range': (0x1200, 0x137F), 'meaning': 'Ethiopic', }, # 埃塞俄比亚语,非洲,仅次于阿拉伯语
{'token': '[U_LAN]', 'range': (0x1380, 0x139F), 'meaning': 'Undefined -> Ethiopic', },
{'token': '[U_LAN]', 'range': (0x13A0, 0x13FF), 'meaning': 'Cherokee', }, # 切罗基语,北美原住民
{'token': '[U_LAN]', 'range': (0x1400, 0x167F), 'meaning': 'Unified Canadian Aboriginal Syllabics', }, # 加拿大澳大利亚音标
{'token': '[U_LAN]', 'range': (0x1680, 0x169F), 'meaning': 'Ogham', }, # 欧甘字母,古爱尔兰用
{'token': '[U_LAN]', 'range': (0x16A0, 0x16FF), 'meaning': 'Runic', }, # 卢恩字母,古北欧用
{'token': '[U_LAN]', 'range': (0x1700, 0x171F), 'meaning': 'Tagalog', }, # 他加禄语,菲律宾及东南亚用
{'token': '[U_LAN]', 'range': (0x1720, 0x173F), 'meaning': 'Hanunoo', }, # 菲律宾用
{'token': '[U_LAN]', 'range': (0x1740, 0x175F), 'meaning': 'Buhid', }, # 菲律宾用
{'token': '[U_LAN]', 'range': (0x1760, 0x177F), 'meaning': 'Tagbanwa', }, # 菲律宾用
{'token': '[U_LAN]', 'range': (0x1780, 0x17FF), 'meaning': 'Khmer', }, # 高棉语,柬埔寨用
{'token': '[U_LAN]', 'range': (0x1800, 0x18AF), 'meaning': 'Mongolian', }, # 蒙古语
{'token': '[U_LAN]', 'range': (0x18B0, 0x18FF), 'meaning': 'Undefined -> Unified Canadian Aboriginal Syllabics', },
{'token': '[U_LAN]', 'range': (0x1900, 0x194F), 'meaning': 'Limbu', }, # 林布语,尼泊尔用
{'token': '[U_LAN]', 'range': (0x1950, 0x197F), 'meaning': 'Tai Le', }, # 傣语,云南用
{'token': '[U_LAN]', 'range': (0x1980, 0x19DF), 'meaning': 'Undefined -> New Tai Lue', }, # 新傣语
{'token': '[U_LAN]', 'range': (0x19E0, 0x19FF), 'meaning': 'Khmer Symbols', }, # 高棉标点,柬埔寨用
{'token': '[U_LAN]', 'range': (0x1A00, 0x1CFF), 'meaning': 'Undefined -> Ol Chiki', }, # 桑塔利语,印度用
{'token': '[U_PHO]', 'range': (0x1D00, 0x1D7F), 'meaning': 'Phonetic Extensions', }, # 音标,例如法语的ᵈ
{'token': '[U_PHO]', 'range': (0x1D80, 0x1DFF), 'meaning': 'Undefined -> Phonetic Extensions Supplement', },
{'token': '[U_LAT]', 'range': (0x1E00, 0x1EFF), 'meaning': 'Latin Extended Additional', }, # 拉丁带修饰符号,例如ṡ
{'token': '[U_GRE]', 'range': (0x1F00, 0x1FFF), 'meaning': 'Greek Extended', }, # 希腊字符带修饰,例如Ᾱ
{'token': '[U_SYM]', 'range': (0x2000, 0x206F), 'meaning': 'General Punctuation', }, # 各种符号,例如千分之‰
{'token': '[U_COM]', 'range': (0x2070, 0x209F), 'meaning': 'Superscripts and Subscripts', }, # 上下标,例如₂
{'token': '¤', 'range': (0x20A0, 0x20CF), 'meaning': 'Currency Symbols', }, # 货币符号,例如欧元€
{'token': '[U_COM]', 'range': (0x20D0, 0x20FF), 'meaning': 'Combining Diacritical Marks for Symbols', }, # 奇怪的可组合符号
{'token': '[U_SYM]', 'range': (0x2100, 0x214F), 'meaning': 'Letterlike Symbols', }, # 符号,例如普朗克常数ℎ,摄氏度℃
{'token': '[U_NUM]', 'range': (0x2150, 0x218F), 'meaning': 'Number Forms', }, # 特殊形式数字,例如三分之一⅓,八Ⅷ
{'token': '[U_SYM]', 'range': (0x2190, 0x21FF), 'meaning': 'Arrows', }, # 箭头,例如→
{'token': '[U_MAT]', 'range': (0x2200, 0x22FF), 'meaning': 'Mathematical Operators', }, # 数学符号,例如减号−,不属于∉
{'token': '[U_SYM]', 'range': (0x2300, 0x23FF), 'meaning': 'Miscellaneous Technical', }, # 杂乱的符号,例如放大倍数⌀,右上角⌝
{'token': '[U_SYM]', 'range': (0x2400, 0x243F), 'meaning': 'Control Pictures', }, # 描述符:表达控制的符号,例如空␀,退出␛
{'token': '[U_SYM]', 'range': (0x2440, 0x245F), 'meaning': 'Optical Character Recognition', }, # OCR符号,例如⑀,⑂
{'token': '[U_NUM]', 'range': (0x2460, 0x24FF), 'meaning': 'Enclosed Alphanumerics', }, # 带框序号,例如①,⒆
{'token': '[U_SYM]', 'range': (0x2500, 0x257F), 'meaning': 'Box Drawing', }, # 画盒子符,例如┋,┓
{'token': '[U_SYM]', 'range': (0x2580, 0x259F), 'meaning': 'Block Elements', }, # 画块符,例如▉,▀
{'token': '[U_SYM]', 'range': (0x25A0, 0x25FF), 'meaning': 'Geometric Shapes', }, # 几何形状,例如△
{'token': '[U_SYM]', 'range': (0x2600, 0x26FF), 'meaning': 'Miscellaneous Symbols', }, # 杂乱的符号,例如多云☁,女♀
{'token': '[U_SYM]', 'range': (0x2700, 0x27BF), 'meaning': 'Dingbats', }, # 杂乱的符号✈➓
{'token': '[U_MAT]', 'range': (0x27C0, 0x27EF), 'meaning': 'Miscellaneous Mathematical Symbols-A', }, # 杂乱的数学符号⟂⟘
{'token': '[U_SYM]', 'range': (0x27F0, 0x27FF), 'meaning': 'Supplemental Arrows-A', }, # 补充箭头⟹
{'token': '[U_LAN]', 'range': (0x2800, 0x28FF), 'meaning': 'Braille Patterns', }, # 盲文,点字文,⠝⠟
{'token': '[U_SYM]', 'range': (0x2900, 0x297F), 'meaning': 'Supplemental Arrows-B', }, # ⥬
{'token': '[U_MAT]', 'range': (0x2980, 0x29FF), 'meaning': 'Miscellaneous Mathematical Symbols-B', }, # ⭬
{'token': '[U_MAT]', 'range': (0x2A00, 0x2AFF), 'meaning': 'Supplemental Mathematical Operators', }, # ⪆
{'token': '[U_SYM]', 'range': (0x2B00, 0x2BFF), 'meaning': 'Miscellaneous Symbols and Arrows'}, # ⭬
{'token': '[U_LAN]', 'range': (0x2C00, 0x2E7F), 'meaning': 'Undefined -> Coptic', }, # 科普特语,埃塞俄比亚语
{'token': '[U_RAD]', 'range': (0x2E80, 0x2EFF), 'meaning': 'CJK Radicals Supplement', }, # CJK中日韩统一表意文字,部首,例如⺘
{'token': '[U_RAD]', 'range': (0x2F00, 0x2FDF), 'meaning': 'Kangxi Radicals', }, # 康熙字典部首
{'token': '[U_SYM]', 'range': (0x2FE0, 0x2FEF), 'meaning': 'Undefined -> Symbol', },
{'token': '[U_SYM]', 'range': (0x2FF0, 0x2FFF), 'meaning': 'Ideographic Description Characters', }, # 描述符:表意文字结构,例如上下结构,左右结构,半包围结构
{'token': '[U_PUN]', 'range': (0x3000, 0x303F), 'meaning': 'CJK Symbols and Punctuation', }, # 中文标点 。
{'token': '[U_JAP]', 'range': (0x3040, 0x309F), 'meaning': 'Hiragana', }, # 日语平假名
{'token': '[U_JAP]', 'range': (0x30A0, 0x30FF), 'meaning': 'Katakana', }, # 日语片假名
{'token': '[U_PHO]', 'range': (0x3100, 0x312F), 'meaning': 'Bopomofo', }, # 汉语拼音字,例如 ㄠㄎ
{'token': '[U_KOR]', 'range': (0x3130, 0x318F), 'meaning': 'Hangul Compatibility Jamo', }, # 韩文
{'token': '[U_JAP]', 'range': (0x3190, 0x319F), 'meaning': 'Kanbun (Kunten)', }, # 汉文,日本用
{'token': '[U_PHO]', 'range': (0x31A0, 0x31BF), 'meaning': 'Bopomofo Extended', }, # 汉语拼音字,例如ㆠ
{'token': '[U_RAD]', 'range': (0x31C0, 0x31EF), 'meaning': 'Undefined -> CJK Strokes', }, # 汉字笔画
{'token': '[U_JAP]', 'range': (0x31F0, 0x31FF), 'meaning': 'Katakana Phonetic Extensions', }, # 片假名音标
{'token': '[U_NUM]', 'range': (0x3200, 0x32FF), 'meaning': 'Enclosed CJK Letters and Months', }, # 汉字序号,例如㈠
{'token': '[U_SYM]', 'range': (0x3300, 0x33FF), 'meaning': 'CJK Compatibility', }, # 单字符表达单位 平方厘米㎠,毫克㎎,23点㍯
{'token': '[U_CHI]', 'range': (0x3400, 0x4DBF), 'meaning': 'CJK Unified Ideographs Extension A', }, # 中文罕见字
{'token': '[U_SYM]', 'range': (0x4DC0, 0x4DFF), 'meaning': 'Yijing Hexagram Symbols', }, # 易经六十四卦,䷁ ䷖
{'token': '[U_CHI]', 'range': (0x4E00, 0x9FAF), 'meaning': 'CJK Unified Ideographs', }, # 中文
{'token': '[U_CHI]', 'range': (0x9FB0, 0x9FFF), 'meaning': 'Undefined -> CJK Unified Ideographs', }, # 中文
{'token': '[U_LAN]', 'range': (0xA000, 0xA48F), 'meaning': 'Yi Syllables', }, # 彝文字符,凉山彝族用
{'token': '[U_LAN]', 'range': (0xA490, 0xA4CF), 'meaning': 'Yi Radicals', }, # 彝文部首
{'token': '[U_LAN]', 'range': (0xA4D0, 0xABFF), 'meaning': 'Undefined -> Cherokee'}, # 彻罗基族, 北美印第安人
{'token': '[U_KOR]', 'range': (0xAC00, 0xD7AF), 'meaning': 'Hangul Syllables', }, # 韩语音节
{'token': '[U_KOR]', 'range': (0xD7B0, 0xD7FF), 'meaning': 'Undefined -> Hangul Jamo Extended-B', },
{'range': (0xD800, 0xDBFF), 'meaning': 'High Surrogate Area', 'token': '[UNK]'},
{'range': (0xDC00, 0xDFFF), 'meaning': 'Low Surrogate Area', 'token': '[UNK]'},
{'range': (0xE000, 0xF8FF), 'meaning': 'Private Use Area', 'token': '[UNK]'}, # NOTE 统计字频时,有很多落无法显示的字符落到了这一区域
{'token': '[U_CHI]', 'range': (0xF900, 0xFAFF), 'meaning': 'CJK Compatibility Ideographs', }, # 中文
{'token': '[U_LAT]', 'range': (0xFB00, 0xFB4F), 'meaning': 'Alphabetic Presentation Forms', }, # 拉丁、希伯来语字母排版符号
{'token': '[U_ARA]', 'range': (0xFB50, 0xFDFF), 'meaning': 'Arabic Presentation Forms-A', }, # 阿拉伯语排版符号
{'token': '[U_SYM]', 'range': (0xFE00, 0xFE0F), 'meaning': 'Variation Selectors', }, # 描述符: 表示选择第几个
{'token': '[U_PUN]', 'range': (0xFE10, 0xFE1F), 'meaning': 'Undefined -> Vertical Forms', }, # 竖排标点
{'token': '[U_COM]', 'range': (0xFE20, 0xFE2F), 'meaning': 'Combining Half Marks', }, # 可组合符号 例如$︡a
{'token': '[U_PUN]', 'range': (0xFE30, 0xFE4F), 'meaning': 'CJK Compatibility Forms', }, # 中文排版符号,例如竖排的符号︻︼
{'token': '[U_PUN]', 'range': (0xFE50, 0xFE6F), 'meaning': 'Small Form Variants', }, # 小符号,小逗号﹐,小问号﹖
{'token': '[U_ARA]', 'range': (0xFE70, 0xFEFF), 'meaning': 'Arabic Presentation Forms-B', }, # 阿拉伯语排版符号
{'token': '[U_LAT]', 'range': (0xFF00, 0xFFEF), 'meaning': 'Halfwidth and Fullwidth Forms', }, # 中文全角字符0c, TODO: 这里视为拉丁文,应该映射回拉丁的半角字符
{'token': '[U_SYM]', 'range': (0xFFF0, 0xFFFF), 'meaning': 'Specials', }, # 描述符: 可表示替换等操作
{'token': '[U_LAN]', 'range': (0x10000, 0x1007F), 'meaning': 'Linear B Syllabary', }, # 线形文字,像象形文字
{'token': '[U_LAN]', 'range': (0x10080, 0x100FF), 'meaning': 'Linear B Ideograms', },
{'token': '[U_LAN]', 'range': (0x10100, 0x1013F), 'meaning': 'Aegean Numbers', }, # 爱琴海象形数字
{'token': '[U_LAN]', 'range': (0x10140, 0x102FF), 'meaning': 'Undefined -> Carian', },
{'token': '[U_LAN]', 'range': (0x10300, 0x1032F), 'meaning': 'Old Italic', }, # 古意大利
{'token': '[U_LAN]', 'range': (0x10330, 0x1034F), 'meaning': 'Gothic', }, # 哥特语
{'range': (0x10350, 0x1037F), 'meaning': 'Undefined', 'token': '[UNK]'},
{'token': '[U_LAN]', 'range': (0x10380, 0x1039F), 'meaning': 'Ugaritic', }, # 古文字在叙利亚发现
{'token': '[U_LAN]', 'range': (0x103A0, 0x103FF), 'meaning': 'Undefined -> Old Persian', }, # 古波斯语
{'token': '[U_LAN]', 'range': (0x10400, 0x1044F), 'meaning': 'Deseret', }, # 北美原住民用
{'token': '[U_PHO]', 'range': (0x10450, 0x1047F), 'meaning': 'Shavian', }, # 萧伯纳的音标
{'token': '[U_LAN]', 'range': (0x10480, 0x104AF), 'meaning': 'Osmanya', }, # 索马里曾经用
{'token': '[U_LAN]', 'range': (0x104B0, 0x107FF), 'meaning': 'Undefined -> Osage', }, # 欧塞奇语
{'token': '[U_LAN]', 'range': (0x10800, 0x1083F), 'meaning': 'Cypriot Syllabary', }, # 塞浦路斯,地中海岛国
{'token': '[U_LAN]', 'range': (0x10840, 0x1CFFF), 'meaning': 'Undefined -> Cuneiform, Chakma, Kharoshthi...', }, # 许多种语言,包括楔形文字, 和一些符号𓆝 1319d 𓆟 1319f
{'token': '[U_LAN]', 'range': (0x1D000, 0x1D0FF), 'meaning': 'Byzantine Musical Symbols', }, # 拜占庭人音乐符号
{'token': '[U_SYM]', 'range': (0x1D100, 0x1D1FF), 'meaning': 'Musical Symbols', }, # 音乐符号
{'range': (0x1D200, 0x1D2FF), 'meaning': 'Undefined', 'token': '[UNK]'},
{'token': '[U_SYM]', 'range': (0x1D300, 0x1D35F), 'meaning': 'Tai Xuan Jing Symbols', }, # 太玄经符号
{'range': (0x1D360, 0x1D3FF), 'meaning': 'Undefined', 'token': '[UNK]'},
{'token': '[U_MAT]', 'range': (0x1D400, 0x1D7FF), 'meaning': 'Mathematical Alphanumeric Symbols', }, # 数学中用的字母,例如斜体的字母
{'token': '[U_LAN]', 'range': (0x1D800, 0x1F003), 'meaning': 'Undefined -> Adlam', }, # 阿德拉姆字母,用于西非
{'token': '[U_EMO]', 'range': (0x1F004, 0x1FAF8), 'meaning': 'Undefined -> Emoji', }, # emoji
{'token': '[U_SYM]', 'range': (0x1FAF9, 0x1FFFF), 'meaning': 'Undefined -> Symbols for Legacy Computing', },
{'token': '[U_CHI]', 'range': (0x20000, 0x2A6DF), 'meaning': 'CJK Unified Ideographs Extension B', }, # 中文罕见字
{'token': '[U_CHI]', 'range': (0x2A6E0, 0x2F7FF), 'meaning': 'Undefined -> CJK Unified Ideographs Extension F...', }, # 中文罕见字
{'token': '[U_CHI]', 'range': (0x2F800, 0x2FA1F), 'meaning': 'CJK Compatibility Ideographs Supplement', }, # 中文罕见字
{'range': (0x2FA20, 0x2FAAF), 'meaning': 'Undefined', 'token': '[UNK]'},
{'range': (0x2FAB0, 0x2FFFF), 'meaning': 'Unused', 'token': '[UNK]'},
{'token': '[U_CHI]', 'range': (0x30000, 0x3134F), 'meaning': 'Unused -> CJK Unified Ideographs Extension G (unassigned)', }, # 未使用的中文编码区间
{'range': (0x31350, 0xDFFFF), 'meaning': 'Unused', 'token': '[UNK]'},
{'token': '[U_SYM]', 'range': (0xE0000, 0xE007F), 'meaning': 'Tags', }, # 描述符: 表示标签
{'range': (0xE0080, 0xE00FF), 'meaning': 'Unused', 'token': '[UNK]'},
{'token': '[U_SYM]', 'range': (0xE0100, 0xE01EF), 'meaning': 'Variation Selectors Supplement', }, # 描述符: 表示选择
{'range': (0xE01F0, 0xEFFFF), 'meaning': 'Unused', 'token': '[UNK]'},
{'range': (0xF0000, 0xFFFFD), 'meaning': 'Supplementary Private Use Area-A', 'token': '[UNK]'},
{'range': (0xFFFFE, 0xFFFFF), 'meaning': 'Unused', 'token': '[UNK]'},
{'range': (0x100000, 0x10FFFD), 'meaning': 'Supplementary Private Use Area-B', 'token': '[UNK]'},
]
def get_unicode_ranges():
# 检查区间是否连续
left_bounds = [m['range'][0] for m in unicode_map]
right_bounds = [m['range'][1] for m in unicode_map]
for right, left in zip(right_bounds[:-1], left_bounds[1:]):
assert right+1 == left
return np.array(right_bounds)
def _is_chinese_char(cp):
# copied from transformers.models.bert.tokenization_bert.BasicTokenizer._is_chinese_char
"""Checks whether CP is the codepoint of a CJK character."""
# This defines a "chinese character" as anything in the CJK Unicode block:
# https://en.wikipedia.org/wiki/CJK_Unified_Ideographs_(Unicode_block)
#
# Note that the CJK Unicode block is NOT all Japanese and Korean characters,
# despite its name. The modern Korean Hangul alphabet is a different block,
# as is Japanese Hiragana and Katakana. Those alphabets are used to write
# space-separated words, so they are not treated specially and handled
# like the all of the other languages.
if (
(cp >= 0x4E00 and cp <= 0x9FFF)
or (cp >= 0x3400 and cp <= 0x4DBF) #
or (cp >= 0x20000 and cp <= 0x2A6DF) #
or (cp >= 0x2A700 and cp <= 0x2B73F) #
or (cp >= 0x2B740 and cp <= 0x2B81F) #
or (cp >= 0x2B820 and cp <= 0x2CEAF) #
or (cp >= 0xF900 and cp <= 0xFAFF)
or (cp >= 0x2F800 and cp <= 0x2FA1F) #
): #
return True
return False
def show_unicode(start=0x1F004, end=0x1FAF8):
# emoji 文件 https://www.unicode.org/Public/emoji/latest/emoji-sequences.txt
# https://github.com/hidehalo/emoji/issues/3
# https://apps.timwhitlock.info/emoji/tables/unicode
for i in range(start, end):
print(chr(i), end=' ')
print()
def load_json(file):
import json
with open(file, 'r', encoding='utf-8') as f:
obj = json.load(f)
return obj
class ChineseCharTokenizer(BertTokenizer):
vocab_files_names = {"vocab_file": "vocab.txt", 'mapping_file': "replace.json"}
def __init__(self, vocab_file, *args, **kwargs):
super(ChineseCharTokenizer, self).__init__(vocab_file, *args, **kwargs)
self.unicoder_ranges = get_unicode_ranges()
self.enclosed_tokens = {token for token in self.vocab if token[0] == '[' and token[-1] == ']' and 'unused' not in token}
self.enclosed_tokens_by_len = [
[token for token in self.enclosed_tokens if len(token) == 5],
[token for token in self.enclosed_tokens if len(token) == 6],
[token for token in self.enclosed_tokens if len(token) == 7]
]
self.dir = os.path.join(os.path.dirname(vocab_file))
self.replace_map = load_json(os.path.join(self.dir, 'replace.json'))
# # [EOS]相当于逗号、换行,不用看作special token
def convert_token_to_representative(self, token: str) -> str:
token = self.replace_map.get(token, token) # 异体字转换,繁简转换,全半角转换,大小写转换等
if token in self.vocab:
return token
else:
assert len(token) == 1, token
if re.match(r'\s', token): # 匹配\u2003, \t等
return ' '
v = ord(token)
if _is_chinese_char(v):
return '[U_CHI]'
elif v <= 0x10FFFD:
i = np.searchsorted(self.unicoder_ranges, v) # 找到插入位置 ranges[i-1] < v <= ranges[i]
return unicode_map[i]['token']
else:
return '[UNK]'
# bert的tokenize会加上CLS?
def _tokenize(self, text):
# 如果没有人为加的特殊赋好,可以不用这个tokenize,list(text)就是tokenize的结果
split_tokens = []
i = 0
while i < len(text):
if text[i:i+5] in self.enclosed_tokens_by_len[0]:
split_tokens.append(text[i:i+5])
i += 5
elif text[i:i+6] == '[MASK]':
split_tokens.append('[MASK]')
i += 6
elif text[i:i+7] in self.enclosed_tokens_by_len[2]:
split_tokens.append(text[i:i+7])
i += 7
else:
split_tokens.append(self.convert_token_to_representative(text[i]))
i += 1
return split_tokens
def _convert_token_to_id(self, token):
return self.vocab.get(self.convert_token_to_representative(token), self.vocab.get(self.unk_token)) # BUG: convert_token_to_representative 不是 id!
def convert_tokens_to_string(self, tokens):
return ''.join(tokens)
def save_pretrained(self, save_directory: Union[str, os.PathLike], legacy_format: Optional[bool] = None, filename_prefix: Optional[str] = None, push_to_hub: bool = False, **kwargs) -> Tuple[str]:
ret = super().save_pretrained(save_directory, legacy_format, filename_prefix, push_to_hub, **kwargs)
shutil.copyfile(os.path.join(self.dir, 'replace.json'), f'{save_directory}/replace.json')
shutil.copyfile(os.path.join(self.dir, 'cctokenizer.py'), f'{save_directory}/cctokenizer.py')
return ret