38#include <unordered_map>
54 if (
cpt >= 0x110000)
return 0x0001;
67 f.letter =
c & 0x0004;
76 std::vector<uint32_t>
out;
77 out.reserve(
s.size());
78 const auto b = [&](
size_t i) {
return static_cast<unsigned char>(
s[
i]); };
79 const auto cont = [&](
size_t i) {
return (
b(
i) & 0xC0) == 0x80; };
81 while (
i <
s.size()) {
82 const unsigned char c =
b(
i);
86 }
else if (!(
c & 0x40)) {
87 out.push_back(0xFFFD);
89 }
else if (!(
c & 0x20)) {
90 if (
i + 1 >=
s.size() || !cont(
i + 1)) {
91 out.push_back(0xFFFD);
94 out.push_back(((
c & 0x1Fu) << 6) | (
b(
i + 1) & 0x3Fu));
97 }
else if (!(
c & 0x10)) {
98 if (
i + 2 >=
s.size() || !cont(
i + 1) || !cont(
i + 2)) {
99 out.push_back(0xFFFD);
102 out.push_back(((
c & 0x0Fu) << 12) | ((
b(
i + 1) & 0x3Fu) << 6) | (
b(
i + 2) & 0x3Fu));
105 }
else if (!(
c & 0x08)) {
106 if (
i + 3 >=
s.size() || !cont(
i + 1) || !cont(
i + 2) || !cont(
i + 3)) {
107 out.push_back(0xFFFD);
110 out.push_back(((
c & 0x07u) << 18) | ((
b(
i + 1) & 0x3Fu) << 12) | ((
b(
i + 2) & 0x3Fu) << 6) |
115 out.push_back(0xFFFD);
124 out.push_back(
static_cast<char>(
cpt));
125 }
else if (
cpt <= 0x7FF) {
126 out.push_back(
static_cast<char>(0xC0 | ((
cpt >> 6) & 0x1F)));
127 out.push_back(
static_cast<char>(0x80 | (
cpt & 0x3F)));
128 }
else if (
cpt <= 0xFFFF) {
129 out.push_back(
static_cast<char>(0xE0 | ((
cpt >> 12) & 0x0F)));
130 out.push_back(
static_cast<char>(0x80 | ((
cpt >> 6) & 0x3F)));
131 out.push_back(
static_cast<char>(0x80 | (
cpt & 0x3F)));
132 }
else if (
cpt <= 0x10FFFF) {
133 out.push_back(
static_cast<char>(0xF0 | ((
cpt >> 18) & 0x07)));
134 out.push_back(
static_cast<char>(0x80 | ((
cpt >> 12) & 0x3F)));
135 out.push_back(
static_cast<char>(0x80 | ((
cpt >> 6) & 0x3F)));
136 out.push_back(
static_cast<char>(0x80 | (
cpt & 0x3F)));
138 throw std::invalid_argument(
"invalid codepoint");
147 const size_t n =
cp.size();
149 const auto get = [&](
size_t p) {
return p <
n ?
cp[
p] :
kOut; };
153 const auto lower = [](
uint32_t c) {
return c >=
'A' &&
c <=
'Z' ?
c + 32 :
c; };
154 std::vector<std::string>
words;
156 const auto add = [&](
size_t end) {
157 const size_t len =
end - prev;
159 words.emplace_back();
165 for (
size_t pos = 0;
pos <
n;) {
169 if (
c ==
'\'' &&
pos + 1 <
n) {
171 if (
c1 ==
's' ||
c1 ==
't' ||
c1 ==
'm' ||
c1 ==
'd') {
177 if ((
c1 ==
'r' &&
c2 ==
'e') || (
c1 ==
'v' &&
c2 ==
'e') || (
c1 ==
'l' &&
c2 ==
'l')) {
184 if (!(
c ==
'\r' ||
c ==
'\n' ||
f.number)) {
185 if (
f.letter ||
fl(
pos + 1).letter) {
206 if (!(
f2.whitespace ||
f2.letter ||
f2.number) &&
f.any) {
207 pos +=
c ==
' ' ? 1 : 0;
208 while (!(
f2.whitespace ||
f2.letter ||
f2.number) &&
f2.any)
f2 =
fl(++
pos);
210 while (
c2 ==
'\r' ||
c2 ==
'\n')
c2 = get(++
pos);
243 static const std::vector<std::string>
m = [] {
244 std::vector<std::string>
v(256);
245 std::vector<bool>
direct(256,
false);
246 for (
int c = 0x21;
c <= 0x7E; ++
c)
direct[
c] =
true;
247 for (
int c = 0xA1;
c <= 0xAC; ++
c)
direct[
c] =
true;
248 for (
int c = 0xAE;
c <= 0xFF; ++
c)
direct[
c] =
true;
269 const std::vector<int32_t>& token_type,
size_t max_digits = 3)
273 for (
size_t r = 0;
r < merges.size(); ++
r)
rank_.emplace(merges[
r],
static_cast<int>(
r));
275 for (
size_t i = 0;
i < token_type.size() &&
i <
tokens_.size(); ++
i) {
276 const int t = token_type[
i];
277 if (
t == 2 ||
t == 3 ||
t == 4) {
284 [&](
int a,
int b) { return tokens_[a].size() > tokens_[b].size(); });
289 std::vector<std::pair<std::string, int>>
frags = {{
text, -1}};
292 if (
s.empty())
continue;
293 std::vector<std::pair<std::string, int>> next;
294 for (
auto& [
t,
id] :
frags) {
296 next.emplace_back(std::move(
t),
id);
300 for (
size_t m; (
m =
t.find(
s,
at)) != std::string::npos;
at =
m +
s.size()) {
301 if (
m >
at) next.emplace_back(
t.substr(
at,
m -
at), -1);
302 next.emplace_back(std::string(),
sid);
304 if (
at <
t.size()) next.emplace_back(
t.substr(
at), -1);
306 frags = std::move(next);
308 std::vector<int>
out;
309 for (
const auto& [
t,
id] :
frags) {
320 std::string
decode(
const std::vector<int>& ids)
const {
323 if (
id < 0 ||
static_cast<size_t>(
id) >=
tokens_.size())
continue;
329 for (
size_t i = 0;
i <
t.size();) {
330 const size_t len =
utf8_len(
static_cast<unsigned char>(
t[
i]));
332 if (
it !=
unbyte_.end())
s.push_back(
static_cast<char>(
it->second));
344 static const size_t lookup[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4};
345 return lookup[
c >> 4];
358 return l.rank >
r.rank || (
l.rank ==
r.rank &&
l.left >
r.left);
364 std::vector<Symbol>
sym;
366 sym.push_back({-1, -1, 0,
word.size()});
370 const int idx =
static_cast<int>(
sym.size());
371 sym.push_back({idx - 1,
off + len ==
word.size() ? -1 : idx + 1,
off, len});
375 std::priority_queue<Bigram, std::vector<Bigram>,
Later> q;
377 const auto push = [&](
int l,
int r) {
378 if (
l < 0 ||
r < 0)
return;
389 if (
L.n == 0 ||
R.n == 0 ||
text(
bg.left) +
text(
bg.right) !=
bg.text)
continue;
393 if (
R.next >= 0)
sym[
R.next].prev =
bg.left;
398 if (
s.n == 0)
continue;
399 const std::string
t =
word.substr(
s.start,
s.n);
400 const auto it =
id_.find(
t);
401 if (
it !=
id_.end()) {
402 out.push_back(
it->second);
406 const auto b =
id_.find(std::string(1,
c));
407 if (
b !=
id_.end())
out.push_back(
b->second);
417 std::unordered_map<std::string, unsigned char>
unbyte_;
424 if (g.
model !=
"gpt2" || (g.
pre !=
"llama-bpe" && g.
pre !=
"qwen2"))
425 throw std::runtime_error(
path +
": tokenizer is '" + g.
model +
"'/'" + g.
pre +
426 "', not 'gpt2'/'llama-bpe' or 'gpt2'/'qwen2'");
Tokenizer(std::vector< std::string > tokens, const std::vector< std::string > &merges, const std::vector< int32_t > &token_type, size_t max_digits=3)
std::vector< int > specials_
std::unordered_map< std::string, unsigned char > unbyte_
std::unordered_map< std::string, int > id_
std::unordered_map< std::string, int > rank_
static size_t utf8_len(unsigned char c)
const std::vector< std::string > & tokens() const
std::vector< std::string > tokens_
void encode_word(const std::string &word, std::vector< int > &out) const
std::vector< bool > special_
std::string decode(const std::vector< int > &ids) const
std::vector< int > encode(const std::string &text) const
const float * p[kIrDepthSourcesMax]
GgufTokenizer read_gguf_tokenizer(const std::string &path)
constexpr uint32_t kRangeStart[kRangeCount]
constexpr uint16_t kRangeFlags[kRangeCount]
constexpr uint32_t kWhitespace[kWhitespaceCount]
constexpr uint32_t kRangeCount
constexpr uint32_t kWhitespaceCount
const std::vector< std::string > & byte_to_unicode()
std::vector< uint32_t > cpts_from_utf8(const std::string &s)
CptFlags flags_of(uint32_t cpt)
void append_utf8(uint32_t cpt, std::string &out)
Tokenizer load_gguf(const std::string &path)
std::vector< std::string > split_words(const std::string &text, size_t max_digits=3)
std::string byte_encode(const std::string &word)
uint16_t category_bits(uint32_t cpt)
std::vector< std::string > merges
std::vector< std::string > tokens
std::vector< int32_t > token_type
bool operator()(const Bigram &l, const Bigram &r) const