30#include <unordered_map>
37inline const std::vector<std::string>&
specials() {
38 static const std::vector<std::string>
s = {
"<unk>",
"<|endoftext|>",
"<|user|>",
"<|assistant|>"};
47 const int base =
static_cast<int>(
specials().size()) + 256;
48 for (
size_t r = 0;
r < merges.size(); ++
r) {
49 const auto sp = merges[
r].find(
' ');
67 std::string
decode(
const std::vector<int>& ids)
const {
70 if (
id >= 0 &&
static_cast<size_t>(
id) <
tokens_.size())
s +=
tokens_[
id];
78 return (
c >=
'A' &&
c <=
'Z') || (
c >=
'a' &&
c <=
'z') ||
c ==
'\'' ||
c >= 0x80;
80 static bool digit(
unsigned char c) {
return c >=
'0' &&
c <=
'9'; }
81 static bool space(
unsigned char c) {
return c ==
' ' || (
c >=
'\t' &&
c <=
'\r'); }
84 static std::vector<std::pair<std::string, int>>
pretokenize(
const std::string&
b) {
85 std::vector<std::pair<std::string, int>>
out;
86 const size_t n =
b.size();
100 const unsigned char c =
b[
i];
101 const size_t j = (
c ==
' ' &&
i + 1 <
n &&
letter(
b[
i + 1])) ?
i + 1 :
i;
111 if (
k ==
i)
k =
i + 1;
115 if (
k ==
i)
k =
i + 1;
117 out.emplace_back(
b.substr(
i,
k -
i), -1);
130 const int off =
static_cast<int>(
specials().size());
131 std::vector<int> ids;
132 for (
unsigned char c :
chunk) ids.push_back(
off +
c);
133 while (ids.size() > 1) {
134 int best = -1,
at = -1,
id = -1;
135 for (
size_t k = 0;
k + 1 < ids.size(); ++
k) {
139 at =
static_cast<int>(
k);
145 ids.erase(ids.begin() +
at + 1);
147 out.insert(
out.end(), ids.begin(), ids.end());
151 std::unordered_map<uint64_t, Merge>
rank_;
165 std::ifstream
f(
path, std::ios::binary);
166 if (!
f)
throw std::runtime_error(
"cannot open " +
path);
167 std::string
buf((std::istreambuf_iterator<char>(
f)), std::istreambuf_iterator<char>());
169 auto need = [&](
size_t n) {
170 if (
p +
n >
buf.size())
throw std::runtime_error(
path +
": truncated GGUF");
175 if (
u32() != 0x46554747u)
throw std::runtime_error(
path +
": not GGUF");
179 std::vector<std::string> tokens, merges;
180 std::string model, pre;
181 std::vector<int32_t> token_type;
183 static const size_t sz[] = {1, 1, 2, 2, 4, 4, 4, 1, 0, 0, 8, 8, 8};
194 throw std::runtime_error(
path +
": unknown GGUF type");
198 const std::string
k =
str();
200 if ((
k ==
"tokenizer.ggml.tokens" ||
k ==
"tokenizer.ggml.merges") &&
t == 9) {
203 if (
et != 8)
throw std::runtime_error(
path +
": " +
k +
" is not a string array");
204 auto&
dst =
k ==
"tokenizer.ggml.tokens" ? tokens : merges;
206 }
else if (
k ==
"tokenizer.ggml.token_type" &&
t == 9) {
211 token_type.push_back(
static_cast<int32_t>(
u32()));
215 }
else if (
k ==
"tokenizer.ggml.model" &&
t == 8) {
217 }
else if (
k ==
"tokenizer.ggml.pre" &&
t == 8) {
223 return {std::move(model), std::move(tokens), std::move(merges), std::move(pre), std::move(token_type)};
231 if (g.
model !=
"bpe")
throw std::runtime_error(
path +
": tokenizer.ggml.model is '" + g.
model +
"', not 'bpe'");
static bool digit(unsigned char c)
void encode_chunk(const std::string &chunk, std::vector< int > &out) const
static bool letter(unsigned char c)
Tokenizer(std::vector< std::string > tokens, const std::vector< std::string > &merges)
std::vector< int > encode(const std::string &text) const
static uint64_t key(int a, int b)
std::string decode(const std::vector< int > &ids) const
static std::vector< std::pair< std::string, int > > pretokenize(const std::string &b)
std::vector< std::string > tokens_
static bool space(unsigned char c)
std::unordered_map< uint64_t, Merge > rank_
const std::vector< std::string > & tokens() const
const float * p[kIrDepthSourcesMax]
GgufTokenizer read_gguf_tokenizer(const std::string &path)
Tokenizer load_gguf(const std::string &path)
const std::vector< std::string > & specials()
std::vector< std::string > merges
std::vector< std::string > tokens
std::vector< int32_t > token_type