mirror of
https://github.com/ggerganov/llama.cpp.git
synced 2024-12-28 12:24:35 +00:00
1012 lines
80 KiB
C++
1012 lines
80 KiB
C++
|
#ifndef CMPNCT_GPT2BPE
|
|||
|
#define CMPNCT_GPT2BPE
|
|||
|
|
|||
|
#include <vector>
|
|||
|
#include <string>
|
|||
|
#include <algorithm>
|
|||
|
#include <utility>
|
|||
|
#include <iostream>
|
|||
|
#include <map>
|
|||
|
#include <unordered_map>
|
|||
|
#include <queue>
|
|||
|
#include <cstring>
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* https://github.com/cmp-nct/ggllm.cpp
|
|||
|
* Minimal library for high performance handling and categorization of UTF8 strings and characters
|
|||
|
* Using std::string
|
|||
|
*/
|
|||
|
|
|||
|
enum CNCTCharType {
|
|||
|
DIGIT, // a numerical char in any language
|
|||
|
LETTER, // a letter in any language
|
|||
|
WHITESPACE, // any form of whitespace
|
|||
|
ACCENT_MARK, // letter modifiers like ´ in é
|
|||
|
PUNCTUATION, // punctuation including brackets
|
|||
|
SYMBOL, // math, currency, other symbols
|
|||
|
CONTROL, // control characters
|
|||
|
MIXED, // a mix of the above
|
|||
|
UNIDENTIFIED // something more exotic like emoji or separators
|
|||
|
};
|
|||
|
|
|||
|
struct CNCTUnicode;
|
|||
|
|
|||
|
struct CNCTString {
|
|||
|
std::string str;
|
|||
|
size_t utf8_chars;
|
|||
|
|
|||
|
CNCTCharType char_type=UNIDENTIFIED;
|
|||
|
bool is_sequential=false;
|
|||
|
|
|||
|
size_t seq_offset_bytes=0;
|
|||
|
size_t seq_offset_utf8_chars=0;
|
|||
|
|
|||
|
bool operator==(const std::string &other) const;
|
|||
|
bool operator==(const char other) const;
|
|||
|
bool operator==(const CNCTString &other) const;
|
|||
|
CNCTString &operator+=(const std::string &other);
|
|||
|
CNCTString &operator+=(const char other);
|
|||
|
friend CNCTString operator+(CNCTString lhs, const std::string &rhs);
|
|||
|
friend CNCTString operator+(CNCTString lhs, const char rhs);
|
|||
|
CNCTString& operator+=(const CNCTString& other);
|
|||
|
friend CNCTString operator+(CNCTString lhs, const CNCTString& rhs);
|
|||
|
};
|
|||
|
|
|||
|
struct CNCTUnicode {
|
|||
|
static bool check_code_range(int c, const std::vector<std::pair<int, int>>& ranges);
|
|||
|
static CNCTCharType get_code_type(int c);
|
|||
|
static CNCTCharType get_code_type(const std::string &utf8_char);
|
|||
|
static int utf8_len(const char c);
|
|||
|
static int strlen_utf8(std::string src);
|
|||
|
static std::vector<std::string> split_utf8(const std::string &src);
|
|||
|
static std::vector<CNCTString> split_utf8_enhanced(const std::string &src);
|
|||
|
static CNCTCharType string_identify(const std::string& str);
|
|||
|
static bool string_test(const std::string& str, CNCTCharType chartype);
|
|||
|
};
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> digit_ranges = {
|
|||
|
{0x30, 0x39}, {0xB2, 0xB3}, {0xB9, 0xB9}, {0x660, 0x669}, {0x6F0, 0x6F9}, {0x7C0, 0x7C9}, {0x966, 0x96F}, {0x9E6, 0x9EF}, {0xA66, 0xA6F}, {0xAE6, 0xAEF}, {0xB66, 0xB6F}, {0xBE6, 0xBEF}, {0xC66, 0xC6F}, {0xCE6, 0xCEF}, {0xD66, 0xD6F}, {0xDE6, 0xDEF}, {0xE50, 0xE59}, {0xED0, 0xED9}, {0xF20, 0xF29}, {0x1040, 0x1049}, {0x1090, 0x1099}, {0x1369, 0x1371}, {0x17E0, 0x17E9}, {0x1810, 0x1819}, {0x1946, 0x194F}, {0x19D0, 0x19DA}, {0x1A80, 0x1A89}, {0x1A90, 0x1A99}, {0x1B50, 0x1B59}, {0x1BB0, 0x1BB9}, {0x1C40, 0x1C49}, {0x1C50, 0x1C59}, {0x2070, 0x2070}, {0x2074, 0x2079}, {0x2080, 0x2089}, {0x2460, 0x2468}, {0x2474, 0x247C}, {0x2488, 0x2490}, {0x24EA, 0x24EA}, {0x24F5, 0x24FD}, {0x24FF, 0x24FF}, {0x2776, 0x277E}, {0x2780, 0x2788}, {0x278A, 0x2792}, {0xA620, 0xA629}, {0xA8D0, 0xA8D9}, {0xA900, 0xA909}, {0xA9D0, 0xA9D9}, {0xA9F0, 0xA9F9}, {0xAA50, 0xAA59}, {0xABF0, 0xABF9}, {0xFF10, 0xFF19}, {0x104A0, 0x104A9}, {0x10A40, 0x10A43}, {0x10D30, 0x10D39}, {0x10E60, 0x10E68}, {0x11052, 0x1105A}, {0x11066, 0x1106F}, {0x110F0, 0x110F9}, {0x11136, 0x1113F}, {0x111D0, 0x111D9}, {0x112F0, 0x112F9}, {0x11450, 0x11459}, {0x114D0, 0x114D9}, {0x11650, 0x11659}, {0x116C0, 0x116C9}, {0x11730, 0x11739}, {0x118E0, 0x118E9}, {0x11950, 0x11959}, {0x11C50, 0x11C59}, {0x11D50, 0x11D59}, {0x11DA0, 0x11DA9}, {0x16A60, 0x16A69}, {0x16B50, 0x16B59}, {0x1D7CE, 0x1D7FF}, {0x1E140, 0x1E149}, {0x1E2F0, 0x1E2F9}, {0x1E950, 0x1E959}, {0x1F100, 0x1F10A}, {0x1FBF0, 0x1FBF9}, };
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> letter_ranges = {
|
|||
|
{0x41, 0x5A}, {0x61, 0x7A}, {0xAA, 0xAA}, {0xB5, 0xB5}, {0xBA, 0xBA}, {0xC0, 0xD6}, {0xD8, 0xF6}, {0xF8, 0x2C1}, {0x2C6, 0x2D1}, {0x2E0, 0x2E4}, {0x2EC, 0x2EC}, {0x2EE, 0x2EE}, {0x370, 0x374}, {0x376, 0x377}, {0x37A, 0x37D}, {0x37F, 0x37F}, {0x386, 0x386}, {0x388, 0x38A}, {0x38C, 0x38C}, {0x38E, 0x3A1}, {0x3A3, 0x3F5}, {0x3F7, 0x481}, {0x48A, 0x52F}, {0x531, 0x556}, {0x559, 0x559}, {0x560, 0x588}, {0x5D0, 0x5EA}, {0x5EF, 0x5F2}, {0x620, 0x64A}, {0x66E, 0x66F}, {0x671, 0x6D3}, {0x6D5, 0x6D5}, {0x6E5, 0x6E6}, {0x6EE, 0x6EF}, {0x6FA, 0x6FC}, {0x6FF, 0x6FF}, {0x710, 0x710}, {0x712, 0x72F}, {0x74D, 0x7A5}, {0x7B1, 0x7B1}, {0x7CA, 0x7EA}, {0x7F4, 0x7F5}, {0x7FA, 0x7FA}, {0x800, 0x815}, {0x81A, 0x81A}, {0x824, 0x824}, {0x828, 0x828}, {0x840, 0x858}, {0x860, 0x86A}, {0x8A0, 0x8B4}, {0x8B6, 0x8C7}, {0x904, 0x939}, {0x93D, 0x93D}, {0x950, 0x950}, {0x958, 0x961}, {0x971, 0x980}, {0x985, 0x98C}, {0x98F, 0x990}, {0x993, 0x9A8}, {0x9AA, 0x9B0}, {0x9B2, 0x9B2}, {0x9B6, 0x9B9}, {0x9BD, 0x9BD}, {0x9CE, 0x9CE}, {0x9DC, 0x9DD}, {0x9DF, 0x9E1}, {0x9F0, 0x9F1}, {0x9FC, 0x9FC}, {0xA05, 0xA0A}, {0xA0F, 0xA10}, {0xA13, 0xA28}, {0xA2A, 0xA30}, {0xA32, 0xA33}, {0xA35, 0xA36}, {0xA38, 0xA39}, {0xA59, 0xA5C}, {0xA5E, 0xA5E}, {0xA72, 0xA74}, {0xA85, 0xA8D}, {0xA8F, 0xA91}, {0xA93, 0xAA8}, {0xAAA, 0xAB0}, {0xAB2, 0xAB3}, {0xAB5, 0xAB9}, {0xABD, 0xABD}, {0xAD0, 0xAD0}, {0xAE0, 0xAE1}, {0xAF9, 0xAF9}, {0xB05, 0xB0C}, {0xB0F, 0xB10}, {0xB13, 0xB28}, {0xB2A, 0xB30}, {0xB32, 0xB33}, {0xB35, 0xB39}, {0xB3D, 0xB3D}, {0xB5C, 0xB5D}, {0xB5F, 0xB61}, {0xB71, 0xB71}, {0xB83, 0xB83}, {0xB85, 0xB8A}, {0xB8E, 0xB90}, {0xB92, 0xB95}, {0xB99, 0xB9A}, {0xB9C, 0xB9C}, {0xB9E, 0xB9F}, {0xBA3, 0xBA4}, {0xBA8, 0xBAA}, {0xBAE, 0xBB9}, {0xBD0, 0xBD0}, {0xC05, 0xC0C}, {0xC0E, 0xC10}, {0xC12, 0xC28}, {0xC2A, 0xC39}, {0xC3D, 0xC3D}, {0xC58, 0xC5A}, {0xC60, 0xC61}, {0xC80, 0xC80}, {0xC85, 0xC8C}, {0xC8E, 0xC90}, {0xC92, 0xCA8}, {0xCAA, 0xCB3}, {0xCB5, 0xCB9}, {0xCBD, 0xCBD}, {0xCDE, 0xCDE}, {0xCE0, 0xCE1}, {0xCF1, 0xCF2}, {0xD04, 0xD0C}, {0xD0E, 0xD10}, {0xD12, 0xD3A}, {0xD3D, 0xD3D}, {0xD4E, 0xD4E}, {0xD54, 0xD56}, {0xD5F, 0xD61}, {0xD7A, 0xD7F}, {0xD85, 0xD96}, {0xD9A, 0xDB1}, {0xDB3, 0xDBB}, {0xDBD, 0xDBD}, {0xDC0, 0xDC6}, {0xE01, 0xE30}, {0xE32, 0xE33}, {0xE40, 0xE46}, {0xE81, 0xE82}, {0xE84, 0xE84}, {0xE86, 0xE8A}, {0xE8C, 0xEA3}, {0xEA5, 0xEA5}, {0xEA7, 0xEB0}, {0xEB2, 0xEB3}, {0xEBD, 0xEBD}, {0xEC0, 0xEC4}, {0xEC6, 0xEC6}, {0xEDC, 0xEDF}, {0xF00, 0xF00}, {0xF40, 0xF47}, {0xF49, 0xF6C}, {0xF88, 0xF8C}, {0x1000, 0x102A}, {0x103F, 0x103F}, {0x1050, 0x1055}, {0x105A, 0x105D}, {0x1061, 0x1061}, {0x1065, 0x1066}, {0x106E, 0x1070}, {0x1075, 0x1081}, {0x108E, 0x108E}, {0x10A0, 0x10C5}, {0x10C7, 0x10C7}, {0x10CD, 0x10CD}, {0x10D0, 0x10FA}, {0x10FC, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, {0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288}, {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, {0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135A}, {0x1380, 0x138F}, {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1401, 0x166C}, {0x166F, 0x167F}, {0x1681, 0x169A}, {0x16A0, 0x16EA}, {0x16F1, 0x16F8}, {0x1700, 0x170C}, {0x170E, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176C}, {0x176E, 0x1770}, {0x1780, 0x17B3}, {0x17D7, 0x17D7}, {0x17DC, 0x17DC}, {0x1820, 0x1878}, {0x1880, 0x1884}, {0x1887, 0x18A8}, {0x18AA, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, {0x1950, 0x196D}, {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, {0x1A00, 0x1A16}, {0x1A20, 0x1A54}, {0x1AA7, 0x1AA7}, {0x1B05, 0x1B33}, {0x1B45, 0x1B4B}, {0x1B83, 0x1BA0}, {0x1BAE, 0x1BAF}, {0x1BBA, 0x1BE5}, {0x1C00, 0x1C23}, {0x1C4D, 0x1C4F}, {0x1C5A, 0x1C7D}, {0x1C80, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CBF}, {0x1CE9, 0x1CEC}, {0x1CEE, 0x1CF3}, {0x1CF5, 0x1CF6}, {0x1CFA, 0x1CFA}, {0x1D00, 0x1DBF}, {0x1E00, 0x1F15}, {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, {0x1FB6, 0x1FBC}, {0x1FBE, 0x1FBE}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FC
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> whitespace_ranges = {
|
|||
|
{0x9, 0xD}, {0x1C, 0x20}, {0x85, 0x85}, {0xA0, 0xA0}, {0x1680, 0x1680}, {0x2000, 0x200A}, {0x2028, 0x2029}, {0x202F, 0x202F}, {0x205F, 0x205F}, {0x3000, 0x3000}, };
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> accent_mark_ranges = {
|
|||
|
{0x300, 0x36F}, {0x483, 0x489}, {0x591, 0x5BD}, {0x5BF, 0x5BF}, {0x5C1, 0x5C2}, {0x5C4, 0x5C5}, {0x5C7, 0x5C7}, {0x610, 0x61A}, {0x64B, 0x65F}, {0x670, 0x670}, {0x6D6, 0x6DC}, {0x6DF, 0x6E4}, {0x6E7, 0x6E8}, {0x6EA, 0x6ED}, {0x711, 0x711}, {0x730, 0x74A}, {0x7A6, 0x7B0}, {0x7EB, 0x7F3}, {0x7FD, 0x7FD}, {0x816, 0x819}, {0x81B, 0x823}, {0x825, 0x827}, {0x829, 0x82D}, {0x859, 0x85B}, {0x8D3, 0x8E1}, {0x8E3, 0x903}, {0x93A, 0x93C}, {0x93E, 0x94F}, {0x951, 0x957}, {0x962, 0x963}, {0x981, 0x983}, {0x9BC, 0x9BC}, {0x9BE, 0x9C4}, {0x9C7, 0x9C8}, {0x9CB, 0x9CD}, {0x9D7, 0x9D7}, {0x9E2, 0x9E3}, {0x9FE, 0x9FE}, {0xA01, 0xA03}, {0xA3C, 0xA3C}, {0xA3E, 0xA42}, {0xA47, 0xA48}, {0xA4B, 0xA4D}, {0xA51, 0xA51}, {0xA70, 0xA71}, {0xA75, 0xA75}, {0xA81, 0xA83}, {0xABC, 0xABC}, {0xABE, 0xAC5}, {0xAC7, 0xAC9}, {0xACB, 0xACD}, {0xAE2, 0xAE3}, {0xAFA, 0xAFF}, {0xB01, 0xB03}, {0xB3C, 0xB3C}, {0xB3E, 0xB44}, {0xB47, 0xB48}, {0xB4B, 0xB4D}, {0xB55, 0xB57}, {0xB62, 0xB63}, {0xB82, 0xB82}, {0xBBE, 0xBC2}, {0xBC6, 0xBC8}, {0xBCA, 0xBCD}, {0xBD7, 0xBD7}, {0xC00, 0xC04}, {0xC3E, 0xC44}, {0xC46, 0xC48}, {0xC4A, 0xC4D}, {0xC55, 0xC56}, {0xC62, 0xC63}, {0xC81, 0xC83}, {0xCBC, 0xCBC}, {0xCBE, 0xCC4}, {0xCC6, 0xCC8}, {0xCCA, 0xCCD}, {0xCD5, 0xCD6}, {0xCE2, 0xCE3}, {0xD00, 0xD03}, {0xD3B, 0xD3C}, {0xD3E, 0xD44}, {0xD46, 0xD48}, {0xD4A, 0xD4D}, {0xD57, 0xD57}, {0xD62, 0xD63}, {0xD81, 0xD83}, {0xDCA, 0xDCA}, {0xDCF, 0xDD4}, {0xDD6, 0xDD6}, {0xDD8, 0xDDF}, {0xDF2, 0xDF3}, {0xE31, 0xE31}, {0xE34, 0xE3A}, {0xE47, 0xE4E}, {0xEB1, 0xEB1}, {0xEB4, 0xEBC}, {0xEC8, 0xECD}, {0xF18, 0xF19}, {0xF35, 0xF35}, {0xF37, 0xF37}, {0xF39, 0xF39}, {0xF3E, 0xF3F}, {0xF71, 0xF84}, {0xF86, 0xF87}, {0xF8D, 0xF97}, {0xF99, 0xFBC}, {0xFC6, 0xFC6}, {0x102B, 0x103E}, {0x1056, 0x1059}, {0x105E, 0x1060}, {0x1062, 0x1064}, {0x1067, 0x106D}, {0x1071, 0x1074}, {0x1082, 0x108D}, {0x108F, 0x108F}, {0x109A, 0x109D}, {0x135D, 0x135F}, {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, {0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD}, {0x180B, 0x180D}, {0x1885, 0x1886}, {0x18A9, 0x18A9}, {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1A17, 0x1A1B}, {0x1A55, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A7F}, {0x1AB0, 0x1AC0}, {0x1B00, 0x1B04}, {0x1B34, 0x1B44}, {0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, {0x1BA1, 0x1BAD}, {0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, {0x1CD0, 0x1CD2}, {0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF4, 0x1CF4}, {0x1CF7, 0x1CF9}, {0x1DC0, 0x1DF9}, {0x1DFB, 0x1DFF}, {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F}, {0x2DE0, 0x2DFF}, {0x302A, 0x302F}, {0x3099, 0x309A}, {0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F}, {0xA6F0, 0xA6F1}, {0xA802, 0xA802}, {0xA806, 0xA806}, {0xA80B, 0xA80B}, {0xA823, 0xA827}, {0xA82C, 0xA82C}, {0xA880, 0xA881}, {0xA8B4, 0xA8C5}, {0xA8E0, 0xA8F1}, {0xA8FF, 0xA8FF}, {0xA926, 0xA92D}, {0xA947, 0xA953}, {0xA980, 0xA983}, {0xA9B3, 0xA9C0}, {0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, {0xAA43, 0xAA43}, {0xAA4C, 0xAA4D}, {0xAA7B, 0xAA7D}, {0xAAB0, 0xAAB0}, {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, {0xAABE, 0xAABF}, {0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, {0xAAF5, 0xAAF6}, {0xABE3, 0xABEA}, {0xABEC, 0xABED}, {0xFB1E, 0xFB1E}, {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, {0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x10D24, 0x10D27}, {0x10EAB, 0x10EAC}, {0x10F46, 0x10F50}, {0x11000, 0x11002}, {0x11038, 0x11046}, {0x1107F, 0x11082}, {0x110B0, 0x110BA}, {0x11100, 0x11102}, {0x11127, 0x11134}, {0x11145, 0x11146}, {0x11173, 0x11173}, {0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111C9, 0x111CC}, {0x111CE, 0x111CF}, {0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x112DF, 0x112EA}, {0x11300, 0x11303}, {0x1133B, 0x1133C}, {0x1133E, 0x11344}, {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357}, {0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11435, 0x11446}, {0x1145E, 0x1145E}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, {0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640}, {0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x1182C, 0x1183A}, {0x11930, 0x11935}, {0x
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> punctuation_ranges = {
|
|||
|
{0x21, 0x23}, {0x25, 0x2A}, {0x2C, 0x2F}, {0x3A, 0x3B}, {0x3F, 0x40}, {0x5B, 0x5D}, {0x5F, 0x5F}, {0x7B, 0x7B}, {0x7D, 0x7D}, {0xA1, 0xA1}, {0xA7, 0xA7}, {0xAB, 0xAB}, {0xB6, 0xB7}, {0xBB, 0xBB}, {0xBF, 0xBF}, {0x37E, 0x37E}, {0x387, 0x387}, {0x55A, 0x55F}, {0x589, 0x58A}, {0x5BE, 0x5BE}, {0x5C0, 0x5C0}, {0x5C3, 0x5C3}, {0x5C6, 0x5C6}, {0x5F3, 0x5F4}, {0x609, 0x60A}, {0x60C, 0x60D}, {0x61B, 0x61B}, {0x61E, 0x61F}, {0x66A, 0x66D}, {0x6D4, 0x6D4}, {0x700, 0x70D}, {0x7F7, 0x7F9}, {0x830, 0x83E}, {0x85E, 0x85E}, {0x964, 0x965}, {0x970, 0x970}, {0x9FD, 0x9FD}, {0xA76, 0xA76}, {0xAF0, 0xAF0}, {0xC77, 0xC77}, {0xC84, 0xC84}, {0xDF4, 0xDF4}, {0xE4F, 0xE4F}, {0xE5A, 0xE5B}, {0xF04, 0xF12}, {0xF14, 0xF14}, {0xF3A, 0xF3D}, {0xF85, 0xF85}, {0xFD0, 0xFD4}, {0xFD9, 0xFDA}, {0x104A, 0x104F}, {0x10FB, 0x10FB}, {0x1360, 0x1368}, {0x1400, 0x1400}, {0x166E, 0x166E}, {0x169B, 0x169C}, {0x16EB, 0x16ED}, {0x1735, 0x1736}, {0x17D4, 0x17D6}, {0x17D8, 0x17DA}, {0x1800, 0x180A}, {0x1944, 0x1945}, {0x1A1E, 0x1A1F}, {0x1AA0, 0x1AA6}, {0x1AA8, 0x1AAD}, {0x1B5A, 0x1B60}, {0x1BFC, 0x1BFF}, {0x1C3B, 0x1C3F}, {0x1C7E, 0x1C7F}, {0x1CC0, 0x1CC7}, {0x1CD3, 0x1CD3}, {0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205E}, {0x207D, 0x207E}, {0x208D, 0x208E}, {0x2308, 0x230B}, {0x2329, 0x232A}, {0x2768, 0x2775}, {0x27C5, 0x27C6}, {0x27E6, 0x27EF}, {0x2983, 0x2998}, {0x29D8, 0x29DB}, {0x29FC, 0x29FD}, {0x2CF9, 0x2CFC}, {0x2CFE, 0x2CFF}, {0x2D70, 0x2D70}, {0x2E00, 0x2E2E}, {0x2E30, 0x2E4F}, {0x2E52, 0x2E52}, {0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301F}, {0x3030, 0x3030}, {0x303D, 0x303D}, {0x30A0, 0x30A0}, {0x30FB, 0x30FB}, {0xA4FE, 0xA4FF}, {0xA60D, 0xA60F}, {0xA673, 0xA673}, {0xA67E, 0xA67E}, {0xA6F2, 0xA6F7}, {0xA874, 0xA877}, {0xA8CE, 0xA8CF}, {0xA8F8, 0xA8FA}, {0xA8FC, 0xA8FC}, {0xA92E, 0xA92F}, {0xA95F, 0xA95F}, {0xA9C1, 0xA9CD}, {0xA9DE, 0xA9DF}, {0xAA5C, 0xAA5F}, {0xAADE, 0xAADF}, {0xAAF0, 0xAAF1}, {0xABEB, 0xABEB}, {0xFD3E, 0xFD3F}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, {0xFE54, 0xFE61}, {0xFE63, 0xFE63}, {0xFE68, 0xFE68}, {0xFE6A, 0xFE6B}, {0xFF01, 0xFF03}, {0xFF05, 0xFF0A}, {0xFF0C, 0xFF0F}, {0xFF1A, 0xFF1B}, {0xFF1F, 0xFF20}, {0xFF3B, 0xFF3D}, {0xFF3F, 0xFF3F}, {0xFF5B, 0xFF5B}, {0xFF5D, 0xFF5D}, {0xFF5F, 0xFF65}, {0x10100, 0x10102}, {0x1039F, 0x1039F}, {0x103D0, 0x103D0}, {0x1056F, 0x1056F}, {0x10857, 0x10857}, {0x1091F, 0x1091F}, {0x1093F, 0x1093F}, {0x10A50, 0x10A58}, {0x10A7F, 0x10A7F}, {0x10AF0, 0x10AF6}, {0x10B39, 0x10B3F}, {0x10B99, 0x10B9C}, {0x10EAD, 0x10EAD}, {0x10F55, 0x10F59}, {0x11047, 0x1104D}, {0x110BB, 0x110BC}, {0x110BE, 0x110C1}, {0x11140, 0x11143}, {0x11174, 0x11175}, {0x111C5, 0x111C8}, {0x111CD, 0x111CD}, {0x111DB, 0x111DB}, {0x111DD, 0x111DF}, {0x11238, 0x1123D}, {0x112A9, 0x112A9}, {0x1144B, 0x1144F}, {0x1145A, 0x1145B}, {0x1145D, 0x1145D}, {0x114C6, 0x114C6}, {0x115C1, 0x115D7}, {0x11641, 0x11643}, {0x11660, 0x1166C}, {0x1173C, 0x1173E}, {0x1183B, 0x1183B}, {0x11944, 0x11946}, {0x119E2, 0x119E2}, {0x11A3F, 0x11A46}, {0x11A9A, 0x11A9C}, {0x11A9E, 0x11AA2}, {0x11C41, 0x11C45}, {0x11C70, 0x11C71}, {0x11EF7, 0x11EF8}, {0x11FFF, 0x11FFF}, {0x12470, 0x12474}, {0x16A6E, 0x16A6F}, {0x16AF5, 0x16AF5}, {0x16B37, 0x16B3B}, {0x16B44, 0x16B44}, {0x16E97, 0x16E9A}, {0x16FE2, 0x16FE2}, {0x1BC9F, 0x1BC9F}, {0x1DA87, 0x1DA8B}, {0x1E95E, 0x1E95F}, };
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> symbol_ranges = {
|
|||
|
{0x24, 0x24}, {0x2B, 0x2B}, {0x3C, 0x3E}, {0x5E, 0x5E}, {0x60, 0x60}, {0x7C, 0x7C}, {0x7E, 0x7E}, {0xA2, 0xA6}, {0xA8, 0xA9}, {0xAC, 0xAC}, {0xAE, 0xB1}, {0xB4, 0xB4}, {0xB8, 0xB8}, {0xD7, 0xD7}, {0xF7, 0xF7}, {0x2C2, 0x2C5}, {0x2D2, 0x2DF}, {0x2E5, 0x2EB}, {0x2ED, 0x2ED}, {0x2EF, 0x2FF}, {0x375, 0x375}, {0x384, 0x385}, {0x3F6, 0x3F6}, {0x482, 0x482}, {0x58D, 0x58F}, {0x606, 0x608}, {0x60B, 0x60B}, {0x60E, 0x60F}, {0x6DE, 0x6DE}, {0x6E9, 0x6E9}, {0x6FD, 0x6FE}, {0x7F6, 0x7F6}, {0x7FE, 0x7FF}, {0x9F2, 0x9F3}, {0x9FA, 0x9FB}, {0xAF1, 0xAF1}, {0xB70, 0xB70}, {0xBF3, 0xBFA}, {0xC7F, 0xC7F}, {0xD4F, 0xD4F}, {0xD79, 0xD79}, {0xE3F, 0xE3F}, {0xF01, 0xF03}, {0xF13, 0xF13}, {0xF15, 0xF17}, {0xF1A, 0xF1F}, {0xF34, 0xF34}, {0xF36, 0xF36}, {0xF38, 0xF38}, {0xFBE, 0xFC5}, {0xFC7, 0xFCC}, {0xFCE, 0xFCF}, {0xFD5, 0xFD8}, {0x109E, 0x109F}, {0x1390, 0x1399}, {0x166D, 0x166D}, {0x17DB, 0x17DB}, {0x1940, 0x1940}, {0x19DE, 0x19FF}, {0x1B61, 0x1B6A}, {0x1B74, 0x1B7C}, {0x1FBD, 0x1FBD}, {0x1FBF, 0x1FC1}, {0x1FCD, 0x1FCF}, {0x1FDD, 0x1FDF}, {0x1FED, 0x1FEF}, {0x1FFD, 0x1FFE}, {0x2044, 0x2044}, {0x2052, 0x2052}, {0x207A, 0x207C}, {0x208A, 0x208C}, {0x20A0, 0x20BF}, {0x2100, 0x2101}, {0x2103, 0x2106}, {0x2108, 0x2109}, {0x2114, 0x2114}, {0x2116, 0x2118}, {0x211E, 0x2123}, {0x2125, 0x2125}, {0x2127, 0x2127}, {0x2129, 0x2129}, {0x212E, 0x212E}, {0x213A, 0x213B}, {0x2140, 0x2144}, {0x214A, 0x214D}, {0x214F, 0x214F}, {0x218A, 0x218B}, {0x2190, 0x2307}, {0x230C, 0x2328}, {0x232B, 0x2426}, {0x2440, 0x244A}, {0x249C, 0x24E9}, {0x2500, 0x2767}, {0x2794, 0x27C4}, {0x27C7, 0x27E5}, {0x27F0, 0x2982}, {0x2999, 0x29D7}, {0x29DC, 0x29FB}, {0x29FE, 0x2B73}, {0x2B76, 0x2B95}, {0x2B97, 0x2BFF}, {0x2CE5, 0x2CEA}, {0x2E50, 0x2E51}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3004, 0x3004}, {0x3012, 0x3013}, {0x3020, 0x3020}, {0x3036, 0x3037}, {0x303E, 0x303F}, {0x309B, 0x309C}, {0x3190, 0x3191}, {0x3196, 0x319F}, {0x31C0, 0x31E3}, {0x3200, 0x321E}, {0x322A, 0x3247}, {0x3250, 0x3250}, {0x3260, 0x327F}, {0x328A, 0x32B0}, {0x32C0, 0x33FF}, {0x4DC0, 0x4DFF}, {0xA490, 0xA4C6}, {0xA700, 0xA716}, {0xA720, 0xA721}, {0xA789, 0xA78A}, {0xA828, 0xA82B}, {0xA836, 0xA839}, {0xAA77, 0xAA79}, {0xAB5B, 0xAB5B}, {0xAB6A, 0xAB6B}, {0xFB29, 0xFB29}, {0xFBB2, 0xFBC1}, {0xFDFC, 0xFDFD}, {0xFE62, 0xFE62}, {0xFE64, 0xFE66}, {0xFE69, 0xFE69}, {0xFF04, 0xFF04}, {0xFF0B, 0xFF0B}, {0xFF1C, 0xFF1E}, {0xFF3E, 0xFF3E}, {0xFF40, 0xFF40}, {0xFF5C, 0xFF5C}, {0xFF5E, 0xFF5E}, {0xFFE0, 0xFFE6}, {0xFFE8, 0xFFEE}, {0xFFFC, 0xFFFD}, {0x10137, 0x1013F}, {0x10179, 0x10189}, {0x1018C, 0x1018E}, {0x10190, 0x1019C}, {0x101A0, 0x101A0}, {0x101D0, 0x101FC}, {0x10877, 0x10878}, {0x10AC8, 0x10AC8}, {0x1173F, 0x1173F}, {0x11FD5, 0x11FF1}, {0x16B3C, 0x16B3F}, {0x16B45, 0x16B45}, {0x1BC9C, 0x1BC9C}, {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D164}, {0x1D16A, 0x1D16C}, {0x1D183, 0x1D184}, {0x1D18C, 0x1D1A9}, {0x1D1AE, 0x1D1E8}, {0x1D200, 0x1D241}, {0x1D245, 0x1D245}, {0x1D300, 0x1D356}, {0x1D6C1, 0x1D6C1}, {0x1D6DB, 0x1D6DB}, {0x1D6FB, 0x1D6FB}, {0x1D715, 0x1D715}, {0x1D735, 0x1D735}, {0x1D74F, 0x1D74F}, {0x1D76F, 0x1D76F}, {0x1D789, 0x1D789}, {0x1D7A9, 0x1D7A9}, {0x1D7C3, 0x1D7C3}, {0x1D800, 0x1D9FF}, {0x1DA37, 0x1DA3A}, {0x1DA6D, 0x1DA74}, {0x1DA76, 0x1DA83}, {0x1DA85, 0x1DA86}, {0x1E14F, 0x1E14F}, {0x1E2FF, 0x1E2FF}, {0x1ECAC, 0x1ECAC}, {0x1ECB0, 0x1ECB0}, {0x1ED2E, 0x1ED2E}, {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F02B}, {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, {0x1F0C1, 0x1F0CF}, {0x1F0D1, 0x1F0F5}, {0x1F10D, 0x1F1AD}, {0x1F1E6, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, {0x1F250, 0x1F251}, {0x1F260, 0x1F265}, {0x1F300, 0x1F6D7}, {0x1F6E0, 0x1F6EC}, {0x1F6F0, 0x1F6FC}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D8}, {0x1F7E0, 0x1F7EB}, {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0x1F8B0, 0x1F8B1}, {0x1F900, 0x1F978}, {0x1F97A, 0x1F9CB}, {0x1F9CD, 0x1FA53}, {0x1FA60, 0x1FA6D}, {0x1FA70, 0x1FA74}, {0x1FA78, 0x1FA7A}, {0x1FA80, 0x1FA86}, {0x1FA90, 0x1FAA8}, {0x1FAB0, 0x1FAB6}, {0x1FAC0, 0x1FAC2}, {0x1FAD
|
|||
|
|
|||
|
static const std::vector<std::pair<int, int>> control_ranges = {
|
|||
|
{0x0, 0x8}, {0xE, 0x1B}, {0x7F, 0x84}, {0x86, 0x9F}, {0xAD, 0xAD}, {0x378, 0x379}, {0x380, 0x383}, {0x38B, 0x38B}, {0x38D, 0x38D}, {0x3A2, 0x3A2}, {0x530, 0x530}, {0x557, 0x558}, {0x58B, 0x58C}, {0x590, 0x590}, {0x5C8, 0x5CF}, {0x5EB, 0x5EE}, {0x5F5, 0x605}, {0x61C, 0x61D}, {0x6DD, 0x6DD}, {0x70E, 0x70F}, {0x74B, 0x74C}, {0x7B2, 0x7BF}, {0x7FB, 0x7FC}, {0x82E, 0x82F}, {0x83F, 0x83F}, {0x85C, 0x85D}, {0x85F, 0x85F}, {0x86B, 0x89F}, {0x8B5, 0x8B5}, {0x8C8, 0x8D2}, {0x8E2, 0x8E2}, {0x984, 0x984}, {0x98D, 0x98E}, {0x991, 0x992}, {0x9A9, 0x9A9}, {0x9B1, 0x9B1}, {0x9B3, 0x9B5}, {0x9BA, 0x9BB}, {0x9C5, 0x9C6}, {0x9C9, 0x9CA}, {0x9CF, 0x9D6}, {0x9D8, 0x9DB}, {0x9DE, 0x9DE}, {0x9E4, 0x9E5}, {0x9FF, 0xA00}, {0xA04, 0xA04}, {0xA0B, 0xA0E}, {0xA11, 0xA12}, {0xA29, 0xA29}, {0xA31, 0xA31}, {0xA34, 0xA34}, {0xA37, 0xA37}, {0xA3A, 0xA3B}, {0xA3D, 0xA3D}, {0xA43, 0xA46}, {0xA49, 0xA4A}, {0xA4E, 0xA50}, {0xA52, 0xA58}, {0xA5D, 0xA5D}, {0xA5F, 0xA65}, {0xA77, 0xA80}, {0xA84, 0xA84}, {0xA8E, 0xA8E}, {0xA92, 0xA92}, {0xAA9, 0xAA9}, {0xAB1, 0xAB1}, {0xAB4, 0xAB4}, {0xABA, 0xABB}, {0xAC6, 0xAC6}, {0xACA, 0xACA}, {0xACE, 0xACF}, {0xAD1, 0xADF}, {0xAE4, 0xAE5}, {0xAF2, 0xAF8}, {0xB00, 0xB00}, {0xB04, 0xB04}, {0xB0D, 0xB0E}, {0xB11, 0xB12}, {0xB29, 0xB29}, {0xB31, 0xB31}, {0xB34, 0xB34}, {0xB3A, 0xB3B}, {0xB45, 0xB46}, {0xB49, 0xB4A}, {0xB4E, 0xB54}, {0xB58, 0xB5B}, {0xB5E, 0xB5E}, {0xB64, 0xB65}, {0xB78, 0xB81}, {0xB84, 0xB84}, {0xB8B, 0xB8D}, {0xB91, 0xB91}, {0xB96, 0xB98}, {0xB9B, 0xB9B}, {0xB9D, 0xB9D}, {0xBA0, 0xBA2}, {0xBA5, 0xBA7}, {0xBAB, 0xBAD}, {0xBBA, 0xBBD}, {0xBC3, 0xBC5}, {0xBC9, 0xBC9}, {0xBCE, 0xBCF}, {0xBD1, 0xBD6}, {0xBD8, 0xBE5}, {0xBFB, 0xBFF}, {0xC0D, 0xC0D}, {0xC11, 0xC11}, {0xC29, 0xC29}, {0xC3A, 0xC3C}, {0xC45, 0xC45}, {0xC49, 0xC49}, {0xC4E, 0xC54}, {0xC57, 0xC57}, {0xC5B, 0xC5F}, {0xC64, 0xC65}, {0xC70, 0xC76}, {0xC8D, 0xC8D}, {0xC91, 0xC91}, {0xCA9, 0xCA9}, {0xCB4, 0xCB4}, {0xCBA, 0xCBB}, {0xCC5, 0xCC5}, {0xCC9, 0xCC9}, {0xCCE, 0xCD4}, {0xCD7, 0xCDD}, {0xCDF, 0xCDF}, {0xCE4, 0xCE5}, {0xCF0, 0xCF0}, {0xCF3, 0xCFF}, {0xD0D, 0xD0D}, {0xD11, 0xD11}, {0xD45, 0xD45}, {0xD49, 0xD49}, {0xD50, 0xD53}, {0xD64, 0xD65}, {0xD80, 0xD80}, {0xD84, 0xD84}, {0xD97, 0xD99}, {0xDB2, 0xDB2}, {0xDBC, 0xDBC}, {0xDBE, 0xDBF}, {0xDC7, 0xDC9}, {0xDCB, 0xDCE}, {0xDD5, 0xDD5}, {0xDD7, 0xDD7}, {0xDE0, 0xDE5}, {0xDF0, 0xDF1}, {0xDF5, 0xE00}, {0xE3B, 0xE3E}, {0xE5C, 0xE80}, {0xE83, 0xE83}, {0xE85, 0xE85}, {0xE8B, 0xE8B}, {0xEA4, 0xEA4}, {0xEA6, 0xEA6}, {0xEBE, 0xEBF}, {0xEC5, 0xEC5}, {0xEC7, 0xEC7}, {0xECE, 0xECF}, {0xEDA, 0xEDB}, {0xEE0, 0xEFF}, {0xF48, 0xF48}, {0xF6D, 0xF70}, {0xF98, 0xF98}, {0xFBD, 0xFBD}, {0xFCD, 0xFCD}, {0xFDB, 0xFFF}, {0x10C6, 0x10C6}, {0x10C8, 0x10CC}, {0x10CE, 0x10CF}, {0x1249, 0x1249}, {0x124E, 0x124F}, {0x1257, 0x1257}, {0x1259, 0x1259}, {0x125E, 0x125F}, {0x1289, 0x1289}, {0x128E, 0x128F}, {0x12B1, 0x12B1}, {0x12B6, 0x12B7}, {0x12BF, 0x12BF}, {0x12C1, 0x12C1}, {0x12C6, 0x12C7}, {0x12D7, 0x12D7}, {0x1311, 0x1311}, {0x1316, 0x1317}, {0x135B, 0x135C}, {0x137D, 0x137F}, {0x139A, 0x139F}, {0x13F6, 0x13F7}, {0x13FE, 0x13FF}, {0x169D, 0x169F}, {0x16F9, 0x16FF}, {0x170D, 0x170D}, {0x1715, 0x171F}, {0x1737, 0x173F}, {0x1754, 0x175F}, {0x176D, 0x176D}, {0x1771, 0x1771}, {0x1774, 0x177F}, {0x17DE, 0x17DF}, {0x17EA, 0x17EF}, {0x17FA, 0x17FF}, {0x180E, 0x180F}, {0x181A, 0x181F}, {0x1879, 0x187F}, {0x18AB, 0x18AF}, {0x18F6, 0x18FF}, {0x191F, 0x191F}, {0x192C, 0x192F}, {0x193C, 0x193F}, {0x1941, 0x1943}, {0x196E, 0x196F}, {0x1975, 0x197F}, {0x19AC, 0x19AF}, {0x19CA, 0x19CF}, {0x19DB, 0x19DD}, {0x1A1C, 0x1A1D}, {0x1A5F, 0x1A5F}, {0x1A7D, 0x1A7E}, {0x1A8A, 0x1A8F}, {0x1A9A, 0x1A9F}, {0x1AAE, 0x1AAF}, {0x1AC1, 0x1AFF}, {0x1B4C, 0x1B4F}, {0x1B7D, 0x1B7F}, {0x1BF4, 0x1BFB}, {0x1C38, 0x1C3A}, {0x1C4A, 0x1C4C}, {0x1C89, 0x1C8F}, {0x1CBB, 0x1CBC}, {0x1CC8, 0x1CCF}, {0x1CFB, 0x1CFF}, {0x1DFA, 0x1DFA}, {0x1F16, 0x1F17}, {0x1F1E, 0x1F1F}, {0x1F46, 0x1F47}, {0x1F4E, 0x1F4F}, {0x1F58, 0x1F58}, {0x1F5A, 0x1F5A}, {0x1F5C, 0x1F5C}, {0x1F5E, 0x1F5E}, {0x1F7E, 0x1F7F}, {0x1FB5, 0x1FB5}, {0x1FC5, 0x1FC5}, {0x1FD4, 0x1FD5}, {0x1FDC, 0x1FDC}, {0x1FF0, 0x1FF
|
|||
|
|
|||
|
//String
|
|||
|
bool CNCTString::operator==(const std::string& other) const {
|
|||
|
return str.compare(other) == 0;
|
|||
|
}
|
|||
|
bool CNCTString::operator==(const char other) const {
|
|||
|
return str.compare(std::string(1, other)) == 0;
|
|||
|
}
|
|||
|
bool CNCTString::operator==(const CNCTString& other) const {
|
|||
|
return str.compare(other.str) == 0;
|
|||
|
}
|
|||
|
// + operators
|
|||
|
CNCTString& CNCTString::operator+=(const std::string& other) {
|
|||
|
str += other;
|
|||
|
int new_len = CNCTUnicode::strlen_utf8(other);
|
|||
|
utf8_chars += new_len;
|
|||
|
char_type = CNCTUnicode::string_identify(str);
|
|||
|
seq_offset_bytes += other.size();
|
|||
|
seq_offset_utf8_chars += new_len;
|
|||
|
return *this;
|
|||
|
}
|
|||
|
|
|||
|
CNCTString& CNCTString::operator+=(const char other) {
|
|||
|
std::string str = std::string(1, other);
|
|||
|
*this += str;
|
|||
|
return *this;
|
|||
|
}
|
|||
|
|
|||
|
CNCTString& CNCTString::operator+=(const CNCTString& other) {
|
|||
|
str += other.str;
|
|||
|
utf8_chars += other.utf8_chars;
|
|||
|
char_type = CNCTUnicode::string_identify(str);
|
|||
|
seq_offset_bytes += other.str.size();
|
|||
|
seq_offset_utf8_chars += other.utf8_chars;
|
|||
|
return *this;
|
|||
|
}
|
|||
|
|
|||
|
struct CRCompare {
|
|||
|
bool operator()(const std::pair<int, int>& p, int i) {
|
|||
|
return p.second < i;
|
|||
|
}
|
|||
|
bool operator()(int i, const std::pair<int, int>& p) {
|
|||
|
return i < p.first;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// binary search for code range
|
|||
|
bool CNCTUnicode::check_code_range(int c, const std::vector<std::pair<int, int>> &ranges)
|
|||
|
{
|
|||
|
auto it = std::upper_bound(ranges.begin(), ranges.end(), c, CRCompare());
|
|||
|
if (it != ranges.begin()) {
|
|||
|
--it;
|
|||
|
}
|
|||
|
return c >= it->first && c <= it->second;
|
|||
|
}
|
|||
|
|
|||
|
// these are binary searches, it takes only a few operations
|
|||
|
CNCTCharType CNCTUnicode::get_code_type(int c)
|
|||
|
{
|
|||
|
if (check_code_range(c, letter_ranges))
|
|||
|
return LETTER;
|
|||
|
if (check_code_range(c, digit_ranges))
|
|||
|
return DIGIT;
|
|||
|
if (check_code_range(c, whitespace_ranges))
|
|||
|
return WHITESPACE;
|
|||
|
if (check_code_range(c, punctuation_ranges))
|
|||
|
return PUNCTUATION;
|
|||
|
if (check_code_range(c, symbol_ranges))
|
|||
|
return SYMBOL;
|
|||
|
if (check_code_range(c, accent_mark_ranges))
|
|||
|
return ACCENT_MARK;
|
|||
|
if (check_code_range(c, control_ranges))
|
|||
|
return CONTROL;
|
|||
|
return UNIDENTIFIED;
|
|||
|
}
|
|||
|
|
|||
|
static int utf8_to_unicode(const std::string& utf8_char) {
|
|||
|
int c = 0;
|
|||
|
int len = (int)utf8_char.size();
|
|||
|
if (len == 1) {
|
|||
|
c = utf8_char[0];
|
|||
|
} else if (len == 2) {
|
|||
|
c = ((utf8_char[0] & 0x1F) << 6) | (utf8_char[1] & 0x3F);
|
|||
|
} else if (len == 3) {
|
|||
|
c = ((utf8_char[0] & 0x0F) << 12) | ((utf8_char[1] & 0x3F) << 6) | (utf8_char[2] & 0x3F);
|
|||
|
} else if (len == 4) {
|
|||
|
c = ((utf8_char[0] & 0x07) << 18) | ((utf8_char[1] & 0x3F) << 12) | ((utf8_char[2] & 0x3F) << 6) | (utf8_char[3] & 0x3F);
|
|||
|
}
|
|||
|
return c;
|
|||
|
}
|
|||
|
|
|||
|
CNCTCharType CNCTUnicode::get_code_type(const std::string &utf8_char)
|
|||
|
{
|
|||
|
return get_code_type(utf8_to_unicode(utf8_char));
|
|||
|
}
|
|||
|
|
|||
|
int CNCTUnicode::utf8_len(const char c)
|
|||
|
{
|
|||
|
if ((c & 0x80) == 0)
|
|||
|
return 1; // ASCII character
|
|||
|
if ((c & 0xE0) == 0xC0)
|
|||
|
return 2; // 2-byte character
|
|||
|
if ((c & 0xF0) == 0xE0)
|
|||
|
return 3; // 3-byte character
|
|||
|
if ((c & 0xF0) == 0xF0)
|
|||
|
return 4; // 4-byte character
|
|||
|
return 1; // not valid utf8
|
|||
|
// static const uint8_t lookup[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4 };
|
|||
|
// return lookup[static_cast<uint8_t>(c) >> 4];
|
|||
|
}
|
|||
|
|
|||
|
int CNCTUnicode::strlen_utf8(const std::string src)
|
|||
|
{
|
|||
|
int len = 0;
|
|||
|
for (std::string::const_iterator it = src.begin(); it != src.end(); ++it)
|
|||
|
{
|
|||
|
int char_len = utf8_len(*it);
|
|||
|
if (char_len > 1)
|
|||
|
{
|
|||
|
it += char_len - 1;
|
|||
|
}
|
|||
|
len += 1;
|
|||
|
}
|
|||
|
return len;
|
|||
|
}
|
|||
|
|
|||
|
// split a string into unicode strings
|
|||
|
std::vector<std::string> CNCTUnicode::split_utf8(const std::string &src)
|
|||
|
{
|
|||
|
std::vector<std::string> result;
|
|||
|
for (std::string::const_iterator it = src.begin(); it != src.end(); ++it)
|
|||
|
{
|
|||
|
int char_len = utf8_len(*it);
|
|||
|
std::string str(it, it + char_len);
|
|||
|
result.push_back(str);
|
|||
|
if (char_len > 1)
|
|||
|
{
|
|||
|
it += char_len - 1;
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
// split a string into unicode strings (CNCTString) with sequence information
|
|||
|
std::vector<CNCTString> CNCTUnicode::split_utf8_enhanced(const std::string &src)
|
|||
|
{
|
|||
|
std::vector<CNCTString> result;
|
|||
|
int seq_offset_bytes=0;
|
|||
|
int seq_offset_utf8_chars=0;
|
|||
|
for (std::string::const_iterator it = src.begin(); it != src.end(); ++it)
|
|||
|
{
|
|||
|
int char_len = utf8_len(*it);
|
|||
|
std::string str(it, it + char_len);
|
|||
|
CNCTString cnct_str;
|
|||
|
cnct_str.seq_offset_bytes = seq_offset_bytes;
|
|||
|
cnct_str.seq_offset_utf8_chars = seq_offset_utf8_chars;
|
|||
|
cnct_str.str = str;
|
|||
|
cnct_str.utf8_chars = 1;
|
|||
|
cnct_str.char_type = get_code_type(str);
|
|||
|
#if 0
|
|||
|
switch (cnct_str.char_type)
|
|||
|
{
|
|||
|
case DIGIT:
|
|||
|
printf("%s = DIGIT\n", str.c_str());
|
|||
|
break;
|
|||
|
case LETTER:
|
|||
|
printf("%s = LETTER\n", str.c_str());
|
|||
|
break;
|
|||
|
case WHITESPACE:
|
|||
|
printf("%s = WHITESPACE\n", str.c_str());
|
|||
|
break;
|
|||
|
case PUNCTUATION:
|
|||
|
printf("%s = PUNCTUATION\n", str.c_str());
|
|||
|
break;
|
|||
|
case UNIDENTIFIED:
|
|||
|
printf("%s = UNIDENTIFIED\n", str.c_str());
|
|||
|
break;
|
|||
|
case SYMBOL:
|
|||
|
printf("%s = SYMBOL\n", str.c_str());
|
|||
|
break;
|
|||
|
case CONTROL:
|
|||
|
printf("%s = CONTROL\n", str.c_str());
|
|||
|
break;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
result.push_back(cnct_str);
|
|||
|
seq_offset_bytes += char_len;
|
|||
|
seq_offset_utf8_chars += 1;
|
|||
|
if (char_len > 1)
|
|||
|
{
|
|||
|
it += char_len - 1;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
// return the type of the string
|
|||
|
CNCTCharType CNCTUnicode::string_identify(const std::string &str)
|
|||
|
{
|
|||
|
CNCTCharType result = UNIDENTIFIED;
|
|||
|
std::string::const_iterator it = str.begin();
|
|||
|
while (it != str.end())
|
|||
|
{
|
|||
|
int len = utf8_len(*it);
|
|||
|
int c = 0;
|
|||
|
for (int i = 0; i < len && it != str.end(); ++i, ++it)
|
|||
|
{
|
|||
|
c = (c << 8) | static_cast<unsigned char>(*it);
|
|||
|
}
|
|||
|
switch (get_code_type(c))
|
|||
|
{
|
|||
|
case DIGIT:
|
|||
|
if (result == UNIDENTIFIED)
|
|||
|
{
|
|||
|
result = DIGIT;
|
|||
|
}
|
|||
|
else if (result != DIGIT)
|
|||
|
{
|
|||
|
return MIXED;
|
|||
|
}
|
|||
|
break;
|
|||
|
case LETTER:
|
|||
|
if (result == UNIDENTIFIED)
|
|||
|
{
|
|||
|
result = LETTER;
|
|||
|
}
|
|||
|
else if (result != LETTER)
|
|||
|
{
|
|||
|
return MIXED;
|
|||
|
}
|
|||
|
break;
|
|||
|
case WHITESPACE:
|
|||
|
if (result == UNIDENTIFIED)
|
|||
|
{
|
|||
|
result = WHITESPACE;
|
|||
|
}
|
|||
|
else if (result != WHITESPACE)
|
|||
|
{
|
|||
|
return MIXED;
|
|||
|
}
|
|||
|
break;
|
|||
|
case PUNCTUATION:
|
|||
|
if (result == UNIDENTIFIED)
|
|||
|
{
|
|||
|
result = PUNCTUATION;
|
|||
|
}
|
|||
|
else if (result != PUNCTUATION)
|
|||
|
{
|
|||
|
return MIXED;
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
return MIXED;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
// verify the content of a string
|
|||
|
bool CNCTUnicode::string_test(const std::string &str, CNCTCharType chartype)
|
|||
|
{
|
|||
|
std::string::const_iterator it = str.begin();
|
|||
|
while (it != str.end())
|
|||
|
{
|
|||
|
int len = utf8_len(*it);
|
|||
|
int c = 0;
|
|||
|
for (int i = 0; i < len && it != str.end(); ++i, ++it)
|
|||
|
{
|
|||
|
c = (c << 8) | static_cast<unsigned char>(*it);
|
|||
|
}
|
|||
|
if (get_code_type(c) != chartype)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
// Ported from libfalcon.cpp (https://github.com/cmp-nct/ggllm.cpp)
|
|||
|
|
|||
|
std::string replaceAll(std::string str, const std::string& from, const std::string& to) {
|
|||
|
size_t start_pos = 0;
|
|||
|
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
|||
|
str.replace(start_pos, from.length(), to);
|
|||
|
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
|
|||
|
}
|
|||
|
return str;
|
|||
|
}
|
|||
|
|
|||
|
struct TrieNode {
|
|||
|
std::map<char, TrieNode*> map;
|
|||
|
int32_t Id = -1;
|
|||
|
};
|
|||
|
|
|||
|
struct Trie {
|
|||
|
TrieNode *root;
|
|||
|
|
|||
|
Trie() : root(new TrieNode()) {}
|
|||
|
~Trie() {
|
|||
|
if(root)
|
|||
|
deleteTrie(root);
|
|||
|
}
|
|||
|
// Move constructor
|
|||
|
Trie(Trie&& other) noexcept : root(other.root) {
|
|||
|
other.root = nullptr;
|
|||
|
}
|
|||
|
|
|||
|
// Move assignment operator
|
|||
|
Trie& operator=(Trie&& other) noexcept {
|
|||
|
if (this != &other) {
|
|||
|
if(root)
|
|||
|
deleteTrie(root);
|
|||
|
root = other.root;
|
|||
|
other.root = nullptr;
|
|||
|
}
|
|||
|
return *this;
|
|||
|
}
|
|||
|
|
|||
|
void insert(const std::string &token, int32_t Id) {
|
|||
|
TrieNode* current = root;
|
|||
|
for(auto ch : token) {
|
|||
|
if(current->map.find(ch) == current->map.end())
|
|||
|
current->map[ch] = new TrieNode();
|
|||
|
current = current->map[ch];
|
|||
|
}
|
|||
|
current->Id = Id;
|
|||
|
}
|
|||
|
|
|||
|
void reset()
|
|||
|
{
|
|||
|
deleteTrie(root);
|
|||
|
root = new TrieNode();
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
void deleteTrie(TrieNode* node) {
|
|||
|
for(auto &it: node->map) {
|
|||
|
deleteTrie(it.second);
|
|||
|
}
|
|||
|
delete node;
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
struct gpt2bpe_vocab {
|
|||
|
using id = int32_t;
|
|||
|
using token = std::string;
|
|||
|
std::map<std::string, uint32_t> max_token_length; // max length, for each 2byte prefix
|
|||
|
|
|||
|
std::map<std::pair<std::string,std::string>, int> bpe_ranks;
|
|||
|
std::vector<std::pair<std::string, std::string>> bpe_merges;
|
|||
|
std::map<std::string, int> special_tokens;
|
|||
|
|
|||
|
id special_bos_id = 0;
|
|||
|
id special_eos_id = 0;
|
|||
|
id special_unk_id = 0;
|
|||
|
id special_sep_id = 0;
|
|||
|
id special_pad_id = 0;
|
|||
|
|
|||
|
bool special_have_bos = false;
|
|||
|
bool special_have_eos = false;
|
|||
|
bool special_have_unk = false;
|
|||
|
bool special_have_sep = false;
|
|||
|
bool special_have_pad = false;
|
|||
|
|
|||
|
std::unordered_map<token, id> token_to_id;
|
|||
|
std::unordered_map<id, token> id_to_token;
|
|||
|
|
|||
|
Trie trie; // highspeed access to tokens by prefix tree
|
|||
|
|
|||
|
// populate trie from map
|
|||
|
void populate_trie_from_map() {
|
|||
|
trie.reset();
|
|||
|
for (const auto& pair : token_to_id) {
|
|||
|
trie.insert(pair.first, pair.second);
|
|||
|
if (pair.first.size() >= 2)
|
|||
|
{
|
|||
|
std::string prefix = pair.first.substr(0, 2);
|
|||
|
max_token_length[prefix] = std::max(max_token_length[prefix], (uint32_t)pair.first.size());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// populate token ranks map
|
|||
|
int populate_bpe_ranks(std::vector<std::pair<std::string, std::string>> bpe_merges_) {
|
|||
|
for (int i = 0; i < (int)bpe_merges_.size(); i++) {
|
|||
|
bpe_ranks.emplace(bpe_merges_[i], i);
|
|||
|
}
|
|||
|
bpe_merges = bpe_merges_;
|
|||
|
|
|||
|
// populate special tokens too (0-11 and if available 65024++)
|
|||
|
|
|||
|
#if 0
|
|||
|
for (int i = 0; i < 12; i++) {
|
|||
|
special_tokens[id_to_token[i].tok] = i;
|
|||
|
}
|
|||
|
for (int i = 65024; i < (int)id_to_token.size(); i++) {
|
|||
|
special_tokens[id_to_token[i].tok] = i;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
// token_to_id["</s>"] = 11; // bugfix for TII instruct training (blocks stopwords)
|
|||
|
// special_tokens["</s>"] = 11; // bugfix for TII instruct training (blocks stopwords)
|
|||
|
|
|||
|
|
|||
|
return bpe_merges_.size();
|
|||
|
}
|
|||
|
|
|||
|
// Trim whitespace characters from the beginning and end of the string
|
|||
|
void trim(std::string& str) {
|
|||
|
// Remove whitespace characters from the beginning of the string
|
|||
|
str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](int ch) {
|
|||
|
return !std::isspace(ch);
|
|||
|
}));
|
|||
|
|
|||
|
// Remove whitespace characters from the end of the string
|
|||
|
str.erase(std::find_if(str.rbegin(), str.rend(), [](int ch) {
|
|||
|
return !std::isspace(ch);
|
|||
|
}).base(), str.end());
|
|||
|
}
|
|||
|
|
|||
|
// removed, merges loaded from gguf model file:
|
|||
|
// requires the standard HF type tokenizer.json (pretty printed)
|
|||
|
// std::vector<std::pair<std::string, std::string>> parse_json_to_bpe_merges(const std::string& filename) {
|
|||
|
|
|||
|
// get max token length available for a prefix of 2 bytes (string at least 2 bytes long)
|
|||
|
int get_max_token_length(const std::string& string) const {
|
|||
|
if (string.size() < 2)
|
|||
|
return -1;
|
|||
|
std::string prefix = string.substr(0, 2);
|
|||
|
if (max_token_length.find(prefix) == max_token_length.end())
|
|||
|
return 0;
|
|||
|
return max_token_length.at(prefix);
|
|||
|
}
|
|||
|
|
|||
|
// function to find if two tokens match in bpe_rank, return rank or -1
|
|||
|
int find_bpe_rank(const std::string& token1, const std::string& token2) const
|
|||
|
{
|
|||
|
std::string left_token = token1;
|
|||
|
std::string right_token = token2;
|
|||
|
left_token = replaceAll(left_token, " ", "Ġ");
|
|||
|
left_token = replaceAll(left_token, "\n", "Ċ");
|
|||
|
right_token = replaceAll(right_token, " ", "Ġ");
|
|||
|
right_token = replaceAll(right_token, "\n", "Ċ");
|
|||
|
|
|||
|
auto it = bpe_ranks.find(std::make_pair(left_token, right_token));
|
|||
|
if (it == bpe_ranks.end())
|
|||
|
return -1;
|
|||
|
return it->second;
|
|||
|
}
|
|||
|
|
|||
|
std::pair<gpt2bpe_vocab::id, std::string> find_longest_match(const std::string& snippet) const {
|
|||
|
TrieNode* current = trie.root;
|
|||
|
gpt2bpe_vocab::id last_matched_id = -1;
|
|||
|
std::string last_matched_token = "";
|
|||
|
std::string current_token = "";
|
|||
|
for (auto ch : snippet) {
|
|||
|
if (current->map.find(ch) == current->map.end()) {
|
|||
|
break;
|
|||
|
}
|
|||
|
current = current->map[ch];
|
|||
|
current_token += ch;
|
|||
|
if (current->Id != -1) {
|
|||
|
last_matched_id = current->Id;
|
|||
|
last_matched_token = current_token;
|
|||
|
}
|
|||
|
}
|
|||
|
return {last_matched_id, last_matched_token};
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// tokenizer - bpe type, gpt2 tokenization compatible
|
|||
|
//
|
|||
|
|
|||
|
struct ggllm_bpe_symbol {
|
|||
|
using index = int;
|
|||
|
index prev;
|
|||
|
index next;
|
|||
|
const char * text;
|
|||
|
size_t n;
|
|||
|
};
|
|||
|
|
|||
|
static_assert(std::is_trivially_copyable<ggllm_bpe_symbol>::value, "ggllm_bpe_symbol is not trivially copyable");
|
|||
|
|
|||
|
struct ggllm_bpe_bigram {
|
|||
|
struct comparator
|
|||
|
{
|
|||
|
bool operator()(ggllm_bpe_bigram & l, ggllm_bpe_bigram & r)
|
|||
|
{
|
|||
|
return l.rank > r.rank || (l.rank == r.rank && l.left > r.left);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
using queue_storage = std::vector<ggllm_bpe_bigram>;
|
|||
|
using queue = std::priority_queue<ggllm_bpe_bigram, queue_storage, comparator>;
|
|||
|
ggllm_bpe_symbol::index left;
|
|||
|
ggllm_bpe_symbol::index right;
|
|||
|
std::string text;
|
|||
|
int rank;
|
|||
|
size_t size;
|
|||
|
};
|
|||
|
|
|||
|
struct gpt2bpe_tokenizer {
|
|||
|
gpt2bpe_tokenizer(const gpt2bpe_vocab & vocab, bool g2ws_): vocab_(vocab) { flag_g2ws = g2ws_; }
|
|||
|
|
|||
|
void tokenize(const std::string & text, std::vector<gpt2bpe_vocab::id> & output) {
|
|||
|
int final_prev_index = -1;
|
|||
|
// auto start = ggml_time_us();
|
|||
|
auto word_collection = bpe_gpt2_preprocess(text);
|
|||
|
// auto end = ggml_time_us();
|
|||
|
// fprintf(stderr, "%s: preprocessing took %0.3f ms\n", __func__, (end - start) / 1000.0);
|
|||
|
|
|||
|
|
|||
|
symbols_final.clear();
|
|||
|
|
|||
|
for (auto & word : word_collection)
|
|||
|
{
|
|||
|
work_queue_ = ggllm_bpe_bigram::queue();
|
|||
|
symbols_.clear();
|
|||
|
bool is_special = false;
|
|||
|
for (auto it = vocab_.special_tokens.begin(); it != vocab_.special_tokens.end(); ++it)
|
|||
|
{
|
|||
|
std::string special_token = it->first;
|
|||
|
if (word.compare(special_token) == 0)
|
|||
|
{
|
|||
|
ggllm_bpe_symbol sym;
|
|||
|
sym.text = word.c_str();
|
|||
|
sym.n = word.size();
|
|||
|
sym.prev = -1;
|
|||
|
sym.next = -1;
|
|||
|
symbols_.emplace_back(sym);
|
|||
|
is_special = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int index = 0;
|
|||
|
size_t offset = 0;
|
|||
|
if (!is_special)
|
|||
|
{
|
|||
|
|
|||
|
while (offset < word.size())
|
|||
|
{
|
|||
|
ggllm_bpe_symbol sym;
|
|||
|
size_t char_len = std::min(word.size() - offset, (size_t) CNCTUnicode::utf8_len(word[offset]));
|
|||
|
sym.text = word.c_str() + offset;
|
|||
|
sym.n = 1;
|
|||
|
sym.n = char_len;
|
|||
|
offset += sym.n;
|
|||
|
sym.prev = index - 1;
|
|||
|
sym.next = offset == word.size() ? -1 : index + 1;
|
|||
|
index++;
|
|||
|
symbols_.emplace_back(sym);
|
|||
|
}
|
|||
|
for (size_t i = 1; i < symbols_.size(); ++i) {
|
|||
|
add_new_bigram(i - 1, i);
|
|||
|
}
|
|||
|
}
|
|||
|
// build token(s)
|
|||
|
while (!work_queue_.empty())
|
|||
|
{
|
|||
|
auto bigram = work_queue_.top();
|
|||
|
work_queue_.pop();
|
|||
|
|
|||
|
auto & left_symbol = symbols_[bigram.left];
|
|||
|
auto & right_symbol = symbols_[bigram.right];
|
|||
|
|
|||
|
if (left_symbol.n == 0 || right_symbol.n == 0) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
std::string left_token = std::string(left_symbol.text, left_symbol.n);
|
|||
|
std::string right_token = std::string(right_symbol.text, right_symbol.n);
|
|||
|
if (left_token + right_token != bigram.text) {
|
|||
|
continue; // Skip this bigram if it's outdated
|
|||
|
}
|
|||
|
|
|||
|
// merge the right sym into the left one
|
|||
|
left_symbol.n += right_symbol.n;
|
|||
|
right_symbol.n = 0;
|
|||
|
|
|||
|
// remove the right sym from the chain
|
|||
|
left_symbol.next = right_symbol.next;
|
|||
|
if (right_symbol.next >= 0) {
|
|||
|
symbols_[right_symbol.next].prev = bigram.left;
|
|||
|
}
|
|||
|
|
|||
|
add_new_bigram(left_symbol.prev, bigram.left); // left side of current symbol
|
|||
|
add_new_bigram(bigram.left, left_symbol.next); // right side of current symbol
|
|||
|
}
|
|||
|
// add the fnished tokens to the final list keeping correct order for next and prev
|
|||
|
|
|||
|
for (auto & sym : symbols_)
|
|||
|
{
|
|||
|
if (sym.n > 0)
|
|||
|
{
|
|||
|
sym.prev = final_prev_index;
|
|||
|
sym.next = -1;
|
|||
|
if (final_prev_index != -1)
|
|||
|
{
|
|||
|
symbols_final[final_prev_index].next = symbols_final.size();
|
|||
|
}
|
|||
|
symbols_final.emplace_back(sym);
|
|||
|
final_prev_index = symbols_final.size() - 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
symbols_ = symbols_final;
|
|||
|
if (symbols_.size())
|
|||
|
for (int i = 0; i != -1; i = symbols_[i].next) {
|
|||
|
auto & symbol = symbols_[i];
|
|||
|
if (symbol.n == 0) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
std::string str = std::string(symbol.text, symbol.n);
|
|||
|
std::string str_decoded = decode_token(str);
|
|||
|
auto token = vocab_.token_to_id.find(str_decoded);
|
|||
|
|
|||
|
if (token == vocab_.token_to_id.end()) {
|
|||
|
for (auto j = str_decoded.begin(); j != str_decoded.end(); ++j) {
|
|||
|
std::string byte_str(1, *j);
|
|||
|
auto token_multibyte = vocab_.token_to_id.find(byte_str);
|
|||
|
if (token_multibyte == vocab_.token_to_id.end()) {
|
|||
|
fprintf(stderr,"ERROR: byte not found in vocab: '%s'\n", byte_str.c_str());
|
|||
|
}
|
|||
|
output.push_back((*token_multibyte).second);
|
|||
|
}
|
|||
|
} else {
|
|||
|
output.push_back((*token).second);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
void add_new_bigram(int left, int right)
|
|||
|
{
|
|||
|
if (left == -1 || right == -1) return;
|
|||
|
|
|||
|
std::string left_token = std::string(symbols_[left].text, symbols_[left].n);
|
|||
|
std::string right_token = std::string(symbols_[right].text, symbols_[right].n);
|
|||
|
|
|||
|
int rank_found = -1;
|
|||
|
rank_found = vocab_.find_bpe_rank(left_token, right_token);
|
|||
|
|
|||
|
if (rank_found < 0) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ggllm_bpe_bigram bigram;
|
|||
|
bigram.left = left;
|
|||
|
bigram.right = right;
|
|||
|
bigram.rank = rank_found;
|
|||
|
bigram.size = left_token.size() + right_token.size();
|
|||
|
bigram.text = left_token + right_token;
|
|||
|
work_queue_.push(bigram);
|
|||
|
}
|
|||
|
|
|||
|
std::unordered_map<unsigned char, std::string> bytes_to_unicode() {
|
|||
|
static std::unordered_map<unsigned char, std::string> hex_map = { { 0x21, "\x21" }, { 0x22, "\x22" }, { 0x23, "\x23" }, { 0x24, "\x24" }, { 0x25, "\x25" }, { 0x26, "\x26" }, { 0x27, "\x27" }, { 0x28, "\x28" }, { 0x29, "\x29" }, { 0x2A, "\x2A" }, { 0x2B, "\x2B" }, { 0x2C, "\x2C" }, { 0x2D, "\x2D" }, { 0x2E, "\x2E" }, { 0x2F, "\x2F" }, { 0x30, "\x30" }, { 0x31, "\x31" }, { 0x32, "\x32" }, { 0x33, "\x33" }, { 0x34, "\x34" }, { 0x35, "\x35" }, { 0x36, "\x36" }, { 0x37, "\x37" }, { 0x38, "\x38" }, { 0x39, "\x39" }, { 0x3A, "\x3A" }, { 0x3B, "\x3B" }, { 0x3C, "\x3C" }, { 0x3D, "\x3D" }, { 0x3E, "\x3E" }, { 0x3F, "\x3F" }, { 0x40, "\x40" }, { 0x41, "\x41" }, { 0x42, "\x42" }, { 0x43, "\x43" }, { 0x44, "\x44" }, { 0x45, "\x45" }, { 0x46, "\x46" }, { 0x47, "\x47" }, { 0x48, "\x48" }, { 0x49, "\x49" }, { 0x4A, "\x4A" }, { 0x4B, "\x4B" }, { 0x4C, "\x4C" }, { 0x4D, "\x4D" }, { 0x4E, "\x4E" }, { 0x4F, "\x4F" }, { 0x50, "\x50" }, { 0x51, "\x51" }, { 0x52, "\x52" }, { 0x53, "\x53" }, { 0x54, "\x54" }, { 0x55, "\x55" }, { 0x56, "\x56" }, { 0x57, "\x57" }, { 0x58, "\x58" }, { 0x59, "\x59" }, { 0x5A, "\x5A" }, { 0x5B, "\x5B" }, { 0x5C, "\x5C" }, { 0x5D, "\x5D" }, { 0x5E, "\x5E" }, { 0x5F, "\x5F" }, { 0x60, "\x60" }, { 0x61, "\x61" }, { 0x62, "\x62" }, { 0x63, "\x63" }, { 0x64, "\x64" }, { 0x65, "\x65" }, { 0x66, "\x66" }, { 0x67, "\x67" }, { 0x68, "\x68" }, { 0x69, "\x69" }, { 0x6A, "\x6A" }, { 0x6B, "\x6B" }, { 0x6C, "\x6C" }, { 0x6D, "\x6D" }, { 0x6E, "\x6E" }, { 0x6F, "\x6F" }, { 0x70, "\x70" }, { 0x71, "\x71" }, { 0x72, "\x72" }, { 0x73, "\x73" }, { 0x74, "\x74" }, { 0x75, "\x75" }, { 0x76, "\x76" }, { 0x77, "\x77" }, { 0x78, "\x78" }, { 0x79, "\x79" }, { 0x7A, "\x7A" }, { 0x7B, "\x7B" }, { 0x7C, "\x7C" }, { 0x7D, "\x7D" }, { 0x7E, "\x7E" }, { 0xA1, "\xC2\xA1" }, { 0xA2, "\xC2\xA2" }, { 0xA3, "\xC2\xA3" }, { 0xA4, "\xC2\xA4" }, { 0xA5, "\xC2\xA5" }, { 0xA6, "\xC2\xA6" }, { 0xA7, "\xC2\xA7" }, { 0xA8, "\xC2\xA8" }, { 0xA9, "\xC2\xA9" }, { 0xAA, "\xC2\xAA" }, { 0xAB, "\xC2\xAB" }, { 0xAC, "\xC2\xAC" }, { 0xAE, "\xC2\xAE" }, { 0xAF, "\xC2\xAF" }, { 0xB0, "\xC2\xB0" }, { 0xB1, "\xC2\xB1" }, { 0xB2, "\xC2\xB2" }, { 0xB3, "\xC2\xB3" }, { 0xB4, "\xC2\xB4" }, { 0xB5, "\xC2\xB5" }, { 0xB6, "\xC2\xB6" }, { 0xB7, "\xC2\xB7" }, { 0xB8, "\xC2\xB8" }, { 0xB9, "\xC2\xB9" }, { 0xBA, "\xC2\xBA" }, { 0xBB, "\xC2\xBB" }, { 0xBC, "\xC2\xBC" }, { 0xBD, "\xC2\xBD" }, { 0xBE, "\xC2\xBE" }, { 0xBF, "\xC2\xBF" }, { 0xC0, "\xC3\x80" }, { 0xC1, "\xC3\x81" }, { 0xC2, "\xC3\x82" }, { 0xC3, "\xC3\x83" }, { 0xC4, "\xC3\x84" }, { 0xC5, "\xC3\x85" }, { 0xC6, "\xC3\x86" }, { 0xC7, "\xC3\x87" }, { 0xC8, "\xC3\x88" }, { 0xC9, "\xC3\x89" }, { 0xCA, "\xC3\x8A" }, { 0xCB, "\xC3\x8B" }, { 0xCC, "\xC3\x8C" }, { 0xCD, "\xC3\x8D" }, { 0xCE, "\xC3\x8E" }, { 0xCF, "\xC3\x8F" }, { 0xD0, "\xC3\x90" }, { 0xD1, "\xC3\x91" }, { 0xD2, "\xC3\x92" }, { 0xD3, "\xC3\x93" }, { 0xD4, "\xC3\x94" }, { 0xD5, "\xC3\x95" }, { 0xD6, "\xC3\x96" }, { 0xD7, "\xC3\x97" }, { 0xD8, "\xC3\x98" }, { 0xD9, "\xC3\x99" }, { 0xDA, "\xC3\x9A" }, { 0xDB, "\xC3\x9B" }, { 0xDC, "\xC3\x9C" }, { 0xDD, "\xC3\x9D" }, { 0xDE, "\xC3\x9E" }, { 0xDF, "\xC3\x9F" }, { 0xE0, "\xC3\xA0" }, { 0xE1, "\xC3\xA1" }, { 0xE2, "\xC3\xA2" }, { 0xE3, "\xC3\xA3" }, { 0xE4, "\xC3\xA4" }, { 0xE5, "\xC3\xA5" }, { 0xE6, "\xC3\xA6" }, { 0xE7, "\xC3\xA7" }, { 0xE8, "\xC3\xA8" }, { 0xE9, "\xC3\xA9" }, { 0xEA, "\xC3\xAA" }, { 0xEB, "\xC3\xAB" }, { 0xEC, "\xC3\xAC" }, { 0xED, "\xC3\xAD" }, { 0xEE, "\xC3\xAE" }, { 0xEF, "\xC3\xAF" }, { 0xF0, "\xC3\xB0" }, { 0xF1, "\xC3\xB1" }, { 0xF2, "\xC3\xB2" }, { 0xF3, "\xC3\xB3" }, { 0xF4, "\xC3\xB4" }, { 0xF5, "\xC3\xB5" }, { 0xF6, "\xC3\xB6" }, { 0xF7, "\xC3\xB7" }, { 0xF8, "\xC3\xB8" }, { 0xF9, "\xC3\xB9" }, { 0xFA, "\xC3\xBA" }, { 0xFB, "\xC3\xBB" }, { 0xFC, "\xC3\xBC" }, { 0xFD, "\xC3\xBD" }, { 0xFE, "\xC3\xBE" }, { 0xFF, "\xC3\xBF" }, { 0x00, "\xC4\x80" }, { 0x01, "\xC4\x81" }, { 0x02, "\xC4\x82" }, { 0x03, "\xC4\x83" }, { 0x04, "\xC4\x84" }, { 0x05, "\xC4\x85" }, { 0x06, "\xC4\x86" }, { 0x07, "\xC4\x87" }, { 0x08, "\xC4\x88" }, { 0x09, "\xC4\x89" }, { 0x0A, "\xC4\x8A" }, { 0x0B, "\xC4\x8B"
|
|||
|
return hex_map;
|
|||
|
}
|
|||
|
|
|||
|
std::unordered_map<std::string, unsigned char> unicode_to_bytes() {
|
|||
|
static std::unordered_map<std::string, unsigned char> hex_map = { { "\x21", 0x21 }, { "\x22", 0x22 }, { "\x23", 0x23 }, { "\x24", 0x24 }, { "\x25", 0x25 }, { "\x26", 0x26 }, { "\x27", 0x27 }, { "\x28", 0x28 }, { "\x29", 0x29 }, { "\x2A", 0x2A }, { "\x2B", 0x2B }, { "\x2C", 0x2C }, { "\x2D", 0x2D }, { "\x2E", 0x2E }, { "\x2F", 0x2F }, { "\x30", 0x30 }, { "\x31", 0x31 }, { "\x32", 0x32 }, { "\x33", 0x33 }, { "\x34", 0x34 }, { "\x35", 0x35 }, { "\x36", 0x36 }, { "\x37", 0x37 }, { "\x38", 0x38 }, { "\x39", 0x39 }, { "\x3A", 0x3A }, { "\x3B", 0x3B }, { "\x3C", 0x3C }, { "\x3D", 0x3D }, { "\x3E", 0x3E }, { "\x3F", 0x3F }, { "\x40", 0x40 }, { "\x41", 0x41 }, { "\x42", 0x42 }, { "\x43", 0x43 }, { "\x44", 0x44 }, { "\x45", 0x45 }, { "\x46", 0x46 }, { "\x47", 0x47 }, { "\x48", 0x48 }, { "\x49", 0x49 }, { "\x4A", 0x4A }, { "\x4B", 0x4B }, { "\x4C", 0x4C }, { "\x4D", 0x4D }, { "\x4E", 0x4E }, { "\x4F", 0x4F }, { "\x50", 0x50 }, { "\x51", 0x51 }, { "\x52", 0x52 }, { "\x53", 0x53 }, { "\x54", 0x54 }, { "\x55", 0x55 }, { "\x56", 0x56 }, { "\x57", 0x57 }, { "\x58", 0x58 }, { "\x59", 0x59 }, { "\x5A", 0x5A }, { "\x5B", 0x5B }, { "\x5C", 0x5C }, { "\x5D", 0x5D }, { "\x5E", 0x5E }, { "\x5F", 0x5F }, { "\x60", 0x60 }, { "\x61", 0x61 }, { "\x62", 0x62 }, { "\x63", 0x63 }, { "\x64", 0x64 }, { "\x65", 0x65 }, { "\x66", 0x66 }, { "\x67", 0x67 }, { "\x68", 0x68 }, { "\x69", 0x69 }, { "\x6A", 0x6A }, { "\x6B", 0x6B }, { "\x6C", 0x6C }, { "\x6D", 0x6D }, { "\x6E", 0x6E }, { "\x6F", 0x6F }, { "\x70", 0x70 }, { "\x71", 0x71 }, { "\x72", 0x72 }, { "\x73", 0x73 }, { "\x74", 0x74 }, { "\x75", 0x75 }, { "\x76", 0x76 }, { "\x77", 0x77 }, { "\x78", 0x78 }, { "\x79", 0x79 }, { "\x7A", 0x7A }, { "\x7B", 0x7B }, { "\x7C", 0x7C }, { "\x7D", 0x7D }, { "\x7E", 0x7E }, { "\xC2\xA1", 0xA1 }, { "\xC2\xA2", 0xA2 }, { "\xC2\xA3", 0xA3 }, { "\xC2\xA4", 0xA4 }, { "\xC2\xA5", 0xA5 }, { "\xC2\xA6", 0xA6 }, { "\xC2\xA7", 0xA7 }, { "\xC2\xA8", 0xA8 }, { "\xC2\xA9", 0xA9 }, { "\xC2\xAA", 0xAA }, { "\xC2\xAB", 0xAB }, { "\xC2\xAC", 0xAC }, { "\xC2\xAE", 0xAE }, { "\xC2\xAF", 0xAF }, { "\xC2\xB0", 0xB0 }, { "\xC2\xB1", 0xB1 }, { "\xC2\xB2", 0xB2 }, { "\xC2\xB3", 0xB3 }, { "\xC2\xB4", 0xB4 }, { "\xC2\xB5", 0xB5 }, { "\xC2\xB6", 0xB6 }, { "\xC2\xB7", 0xB7 }, { "\xC2\xB8", 0xB8 }, { "\xC2\xB9", 0xB9 }, { "\xC2\xBA", 0xBA }, { "\xC2\xBB", 0xBB }, { "\xC2\xBC", 0xBC }, { "\xC2\xBD", 0xBD }, { "\xC2\xBE", 0xBE }, { "\xC2\xBF", 0xBF }, { "\xC3\x80", 0xC0 }, { "\xC3\x81", 0xC1 }, { "\xC3\x82", 0xC2 }, { "\xC3\x83", 0xC3 }, { "\xC3\x84", 0xC4 }, { "\xC3\x85", 0xC5 }, { "\xC3\x86", 0xC6 }, { "\xC3\x87", 0xC7 }, { "\xC3\x88", 0xC8 }, { "\xC3\x89", 0xC9 }, { "\xC3\x8A", 0xCA }, { "\xC3\x8B", 0xCB }, { "\xC3\x8C", 0xCC }, { "\xC3\x8D", 0xCD }, { "\xC3\x8E", 0xCE }, { "\xC3\x8F", 0xCF }, { "\xC3\x90", 0xD0 }, { "\xC3\x91", 0xD1 }, { "\xC3\x92", 0xD2 }, { "\xC3\x93", 0xD3 }, { "\xC3\x94", 0xD4 }, { "\xC3\x95", 0xD5 }, { "\xC3\x96", 0xD6 }, { "\xC3\x97", 0xD7 }, { "\xC3\x98", 0xD8 }, { "\xC3\x99", 0xD9 }, { "\xC3\x9A", 0xDA }, { "\xC3\x9B", 0xDB }, { "\xC3\x9C", 0xDC }, { "\xC3\x9D", 0xDD }, { "\xC3\x9E", 0xDE }, { "\xC3\x9F", 0xDF }, { "\xC3\xA0", 0xE0 }, { "\xC3\xA1", 0xE1 }, { "\xC3\xA2", 0xE2 }, { "\xC3\xA3", 0xE3 }, { "\xC3\xA4", 0xE4 }, { "\xC3\xA5", 0xE5 }, { "\xC3\xA6", 0xE6 }, { "\xC3\xA7", 0xE7 }, { "\xC3\xA8", 0xE8 }, { "\xC3\xA9", 0xE9 }, { "\xC3\xAA", 0xEA }, { "\xC3\xAB", 0xEB }, { "\xC3\xAC", 0xEC }, { "\xC3\xAD", 0xED }, { "\xC3\xAE", 0xEE }, { "\xC3\xAF", 0xEF }, { "\xC3\xB0", 0xF0 }, { "\xC3\xB1", 0xF1 }, { "\xC3\xB2", 0xF2 }, { "\xC3\xB3", 0xF3 }, { "\xC3\xB4", 0xF4 }, { "\xC3\xB5", 0xF5 }, { "\xC3\xB6", 0xF6 }, { "\xC3\xB7", 0xF7 }, { "\xC3\xB8", 0xF8 }, { "\xC3\xB9", 0xF9 }, { "\xC3\xBA", 0xFA }, { "\xC3\xBB", 0xFB }, { "\xC3\xBC", 0xFC }, { "\xC3\xBD", 0xFD }, { "\xC3\xBE", 0xFE }, { "\xC3\xBF", 0xFF }, { "\xC4\x80", 0x00 }, { "\xC4\x81", 0x01 }, { "\xC4\x82", 0x02 }, { "\xC4\x83", 0x03 }, { "\xC4\x84", 0x04 }, { "\xC4\x85", 0x05 }, { "\xC4\x86", 0x06 }, { "\xC4\x87", 0x07 }, { "\xC4\x88", 0x08 }, { "\xC4\x89", 0x09 }, { "\xC4\x8A", 0x0A }, { "\xC4\x8B", 0x0B
|
|||
|
return hex_map;
|
|||
|
}
|
|||
|
|
|||
|
// len must be available
|
|||
|
bool inline str_is_equal(const char* str1, const char* str2, size_t len) {
|
|||
|
for (size_t i = 0; i < len; ++i) {
|
|||
|
if (str1[i] != str2[i]) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
std::vector<std::string> bpe_gpt2_preprocess(const std::string& text)
|
|||
|
{
|
|||
|
static std::unordered_map< unsigned char, std::string> byte_encoder = bytes_to_unicode();
|
|||
|
std::vector<std::string> bpe_words;
|
|||
|
std::vector<std::string> bpe_encoded_words;
|
|||
|
|
|||
|
|
|||
|
std::string token="";
|
|||
|
const char *raw_text_p = text.c_str();
|
|||
|
// GPT2 system regex: 's|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+
|
|||
|
bool collecting_numeric = false;
|
|||
|
bool collecting_letter = false;
|
|||
|
bool collecting_special = false;
|
|||
|
bool collecting_whitespace_lookahead = false;
|
|||
|
bool collecting=false;
|
|||
|
|
|||
|
std::vector<CNCTString> text_utf;
|
|||
|
text_utf.reserve(text.size());
|
|||
|
bpe_words.reserve(text.size());
|
|||
|
bpe_encoded_words.reserve(text.size());
|
|||
|
|
|||
|
text_utf = CNCTUnicode::split_utf8_enhanced(text);
|
|||
|
std::map<std::string, int> special_tokens = vocab_.special_tokens;
|
|||
|
int smallest_len_special_tokens = 0;
|
|||
|
if (special_tokens.size())
|
|||
|
{
|
|||
|
smallest_len_special_tokens = special_tokens.begin()->first.size();
|
|||
|
for (auto it = special_tokens.begin(); it != special_tokens.end(); ++it)
|
|||
|
{
|
|||
|
if (it->first.size() < (size_t)smallest_len_special_tokens)
|
|||
|
smallest_len_special_tokens = it->first.size();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < (int)text_utf.size(); i++)
|
|||
|
{
|
|||
|
const CNCTString &utf_char = text_utf[i];
|
|||
|
bool split_condition = false;
|
|||
|
const char *text_pos = raw_text_p + utf_char.seq_offset_bytes;
|
|||
|
int bytes_remain = strlen(text_pos);
|
|||
|
// forward backward lookups
|
|||
|
const CNCTString &utf_char_next = (i+1 < (int)text_utf.size()) ? text_utf[i+1] : CNCTString();
|
|||
|
const CNCTString &utf_char_next_next = (i+2 < (int)text_utf.size()) ? text_utf[i+2] : CNCTString();
|
|||
|
// const CNCTString &utf_char_prev = (i > 0) ? text_utf[i-1] : CNCTString();
|
|||
|
|
|||
|
// handling special tokens
|
|||
|
bool special_token_found = false;
|
|||
|
if (bytes_remain >= (int)smallest_len_special_tokens)
|
|||
|
for (auto it = special_tokens.begin(); it != special_tokens.end(); ++it)
|
|||
|
{
|
|||
|
if ((bytes_remain) < (int)it->first.size())
|
|||
|
continue;
|
|||
|
|
|||
|
if (str_is_equal(text_pos, it->first.c_str(), it->first.size()))
|
|||
|
{
|
|||
|
if (token.size())
|
|||
|
{
|
|||
|
bpe_words.emplace_back(token); // push previous content as token
|
|||
|
token.clear();
|
|||
|
collecting = false;
|
|||
|
collecting_letter = false;
|
|||
|
collecting_numeric = false;
|
|||
|
collecting_special = false;
|
|||
|
collecting_whitespace_lookahead = false;
|
|||
|
}
|
|||
|
|
|||
|
bpe_words.emplace_back(it->first); // push special token as token
|
|||
|
|
|||
|
// we now advance i until the token is fulfilled by the utf_chars
|
|||
|
int st_bytes = (int)it->first.size();
|
|||
|
for (;st_bytes;st_bytes -= text_utf[i++].str.size());
|
|||
|
i--;
|
|||
|
special_token_found = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (special_token_found) continue;
|
|||
|
|
|||
|
|
|||
|
// handling contractions
|
|||
|
if (!split_condition && bytes_remain >= 2)
|
|||
|
{
|
|||
|
// 's|'t|'m|'d
|
|||
|
if (utf_char == '\'' && (utf_char_next == 's' || utf_char_next == 't' || utf_char_next == 'm' || utf_char_next == 'd'))
|
|||
|
split_condition = true;
|
|||
|
if (split_condition)
|
|||
|
{
|
|||
|
if (token.size())
|
|||
|
bpe_words.emplace_back(token); // push previous content as token
|
|||
|
token = utf_char.str + utf_char_next.str;
|
|||
|
bpe_words.emplace_back(token);
|
|||
|
token="";
|
|||
|
i++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
if (!split_condition && bytes_remain >= 3)
|
|||
|
{
|
|||
|
// 're|'ve|'ll
|
|||
|
if (utf_char == '\'' && (
|
|||
|
(utf_char_next == 'r' || utf_char_next_next == 'e') ||
|
|||
|
(utf_char_next == 'v' || utf_char_next_next == 'e') ||
|
|||
|
(utf_char_next == 'l' || utf_char_next_next == 'l'))
|
|||
|
)
|
|||
|
split_condition = true;
|
|||
|
if (split_condition)
|
|||
|
{
|
|||
|
// current token + next token can be defined
|
|||
|
if (token.size())
|
|||
|
bpe_words.emplace_back(token); // push previous content as token
|
|||
|
token = utf_char.str + utf_char_next.str + utf_char_next_next.str;
|
|||
|
bpe_words.emplace_back(token); // the contraction
|
|||
|
token="";
|
|||
|
i+=2;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!split_condition && !collecting)
|
|||
|
{
|
|||
|
if (utf_char.char_type == CNCTCharType::LETTER || (!token.size() && utf_char==" " && utf_char_next.char_type == CNCTCharType::LETTER))
|
|||
|
{
|
|||
|
collecting_letter = true;
|
|||
|
collecting = true;
|
|||
|
}
|
|||
|
else if (utf_char.char_type == CNCTCharType::DIGIT || (!token.size() && utf_char==" " && utf_char_next.char_type == CNCTCharType::DIGIT))
|
|||
|
{
|
|||
|
collecting_numeric = true;
|
|||
|
collecting = true;
|
|||
|
}
|
|||
|
else if (
|
|||
|
((utf_char.char_type != CNCTCharType::LETTER && utf_char.char_type != CNCTCharType::DIGIT) && (utf_char.char_type != CNCTCharType::WHITESPACE)) ||
|
|||
|
(!token.size() && utf_char==" " && utf_char_next.char_type != CNCTCharType::LETTER && utf_char_next.char_type != CNCTCharType::DIGIT && utf_char_next.char_type != CNCTCharType::WHITESPACE)
|
|||
|
)
|
|||
|
{
|
|||
|
collecting_special = true;
|
|||
|
collecting = true;
|
|||
|
}
|
|||
|
else if (utf_char.char_type == CNCTCharType::WHITESPACE && utf_char_next.char_type == CNCTCharType::WHITESPACE)
|
|||
|
{
|
|||
|
collecting_whitespace_lookahead = true;
|
|||
|
collecting = true;
|
|||
|
} else if (utf_char.char_type == CNCTCharType::WHITESPACE)
|
|||
|
{
|
|||
|
split_condition = true;
|
|||
|
}
|
|||
|
} else
|
|||
|
if (!split_condition && collecting)
|
|||
|
{
|
|||
|
if (collecting_letter && utf_char.char_type != CNCTCharType::LETTER)
|
|||
|
{
|
|||
|
split_condition = true;
|
|||
|
}
|
|||
|
else if (collecting_numeric && utf_char.char_type != CNCTCharType::DIGIT)
|
|||
|
{
|
|||
|
split_condition = true;
|
|||
|
}
|
|||
|
else if (collecting_special && (utf_char.char_type == CNCTCharType::LETTER || utf_char.char_type == CNCTCharType::DIGIT || utf_char.char_type == CNCTCharType::WHITESPACE))
|
|||
|
{
|
|||
|
split_condition = true;
|
|||
|
}
|
|||
|
else if (collecting_whitespace_lookahead && utf_char_next.char_type != CNCTCharType::WHITESPACE)
|
|||
|
{
|
|||
|
split_condition = true;
|
|||
|
}
|
|||
|
}
|
|||
|
if(utf_char_next.str.size() == 0)
|
|||
|
{
|
|||
|
split_condition = true; // final
|
|||
|
token += utf_char.str;
|
|||
|
}
|
|||
|
|
|||
|
if (split_condition)
|
|||
|
{
|
|||
|
if (token.size())
|
|||
|
bpe_words.emplace_back(token);
|
|||
|
token = utf_char.str;
|
|||
|
collecting = false;
|
|||
|
collecting_letter = false;
|
|||
|
collecting_numeric = false;
|
|||
|
collecting_special = false;
|
|||
|
collecting_whitespace_lookahead = false;
|
|||
|
} else token += utf_char.str;
|
|||
|
}
|
|||
|
|
|||
|
for (std::string& word : bpe_words)
|
|||
|
{
|
|||
|
std::string encoded_token="";
|
|||
|
for (char& c : word)
|
|||
|
{
|
|||
|
encoded_token += byte_encoder[c];
|
|||
|
}
|
|||
|
bpe_encoded_words.emplace_back(encoded_token);
|
|||
|
}
|
|||
|
|
|||
|
return bpe_encoded_words;
|
|||
|
}
|
|||
|
|
|||
|
// decoder (for one token)
|
|||
|
std::string decode_token(const std::string& token)
|
|||
|
{
|
|||
|
static std::unordered_map< std::string, unsigned char> byte_decoder = unicode_to_bytes();
|
|||
|
std::string decoded_token="";
|
|||
|
auto unicode_seqeunces = CNCTUnicode::split_utf8(token);
|
|||
|
for (auto& unicode_sequence : unicode_seqeunces)
|
|||
|
{
|
|||
|
decoded_token += byte_decoder[unicode_sequence];
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return decoded_token;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
const gpt2bpe_vocab & vocab_;
|
|||
|
std::vector<ggllm_bpe_symbol> symbols_;
|
|||
|
std::vector<ggllm_bpe_symbol> symbols_final;
|
|||
|
ggllm_bpe_bigram::queue work_queue_;
|
|||
|
bool flag_g2ws=false;
|
|||
|
};
|
|||
|
|
|||
|
static std::vector<gpt2bpe_vocab::id> gpt2bpe_tokenize(const gpt2bpe_vocab & vocab, const std::string & text, bool bos, bool g2ws ) {
|
|||
|
gpt2bpe_tokenizer tokenizer(vocab, g2ws);
|
|||
|
std::vector<gpt2bpe_vocab::id> output;
|
|||
|
|
|||
|
if (text.empty()) {
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
if (bos && vocab.special_have_bos) {
|
|||
|
output.push_back(vocab.special_bos_id);
|
|||
|
}
|
|||
|
|
|||
|
tokenizer.tokenize(text, output);
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif // CMPNCT_GPT2BPE
|