Skip to content

Commit e6b1a50

Browse files
committed
Fix for ggml-org#2310
Waiting for the fallout ...
1 parent 0e74a72 commit e6b1a50

File tree

10 files changed

+119
-115
lines changed

10 files changed

+119
-115
lines changed

examples/common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ std::string gpt_random_prompt(std::mt19937 & rng) {
564564
// TODO: not great allocating this every time
565565
std::vector<llama_token> llama_tokenize(struct llama_context * ctx, const std::string & text, bool add_bos) {
566566
// initialize to prompt numer of chars, since n_tokens <= n_prompt_chars
567-
std::vector<llama_token> res(text.size() + (int) add_bos);
567+
std::vector<llama_token> res(text.size() + (int) add_bos + 1);
568568
const int n = llama_tokenize(ctx, text.c_str(), res.data(), res.size(), add_bos);
569569
assert(n >= 0);
570570
res.resize(n);

examples/embedding/embedding.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int main(int argc, char ** argv) {
6767
fprintf(stderr, "%s: prompt: '%s'\n", __func__, params.prompt.c_str());
6868
fprintf(stderr, "%s: number of tokens in prompt = %zu\n", __func__, embd_inp.size());
6969
for (int i = 0; i < (int) embd_inp.size(); i++) {
70-
fprintf(stderr, "%6d -> '%s'\n", embd_inp[i], llama_token_to_str(ctx, embd_inp[i]));
70+
fprintf(stderr, "%6d -> '%s'\n", embd_inp[i], llama_token_to_str(ctx, embd_inp[i]).c_str());
7171
}
7272
fprintf(stderr, "\n");
7373
}

examples/main/main.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,6 @@ int main(int argc, char ** argv) {
196196

197197
// tokenize the prompt
198198
std::vector<llama_token> embd_inp;
199-
200-
// Add a space in front of the first character to match OG llama tokenizer behavior
201-
params.prompt.insert(0, 1, ' ');
202-
203199
if (params.interactive_first || params.instruct || !params.prompt.empty() || session_tokens.empty()) {
204200
embd_inp = ::llama_tokenize(ctx, params.prompt, true);
205201
} else {
@@ -283,22 +279,22 @@ int main(int argc, char ** argv) {
283279
fprintf(stderr, "%s: prompt: '%s'\n", __func__, params.prompt.c_str());
284280
fprintf(stderr, "%s: number of tokens in prompt = %zu\n", __func__, embd_inp.size());
285281
for (int i = 0; i < (int) embd_inp.size(); i++) {
286-
fprintf(stderr, "%6d -> '%s'\n", embd_inp[i], llama_token_to_str(ctx, embd_inp[i]));
282+
fprintf(stderr, "%6d -> '%s'\n", embd_inp[i], llama_token_to_str(ctx, embd_inp[i]).c_str());
287283
}
288284

289285
if (ctx_guidance) {
290286
fprintf(stderr, "\n");
291287
fprintf(stderr, "%s: negative prompt: '%s'\n", __func__, params.cfg_negative_prompt.c_str());
292288
fprintf(stderr, "%s: number of tokens in negative prompt = %zu\n", __func__, guidance_inp.size());
293289
for (int i = 0; i < (int) guidance_inp.size(); i++) {
294-
fprintf(stderr, "%6d -> '%s'\n", guidance_inp[i], llama_token_to_str(ctx, guidance_inp[i]));
290+
fprintf(stderr, "%6d -> '%s'\n", guidance_inp[i], llama_token_to_str(ctx, guidance_inp[i]).c_str());
295291
}
296292
}
297293

298294
if (params.n_keep > 0) {
299295
fprintf(stderr, "%s: static prompt based on n_keep: '", __func__);
300296
for (int i = 0; i < params.n_keep; i++) {
301-
fprintf(stderr, "%s", llama_token_to_str(ctx, embd_inp[i]));
297+
fprintf(stderr, "%s", llama_token_to_str(ctx, embd_inp[i]).c_str());
302298
}
303299
fprintf(stderr, "'\n");
304300
}
@@ -636,7 +632,7 @@ int main(int argc, char ** argv) {
636632
// display text
637633
if (input_echo) {
638634
for (auto id : embd) {
639-
printf("%s", llama_token_to_str(ctx, id));
635+
printf("%s", llama_token_to_str(ctx, id).c_str());
640636
}
641637
fflush(stdout);
642638
}

examples/save-load-state/save-load-state.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ int main(int argc, char ** argv) {
9191
auto next_token_str = llama_token_to_str(ctx, next_token);
9292
last_n_tokens_data.push_back(next_token);
9393

94-
printf("%s", next_token_str);
94+
printf("%s", next_token_str.c_str());
9595
if (llama_eval(ctx, &next_token, 1, n_past, params.n_threads)) {
9696
fprintf(stderr, "\n%s : failed to evaluate\n", __func__);
9797
llama_free(ctx);
@@ -151,7 +151,7 @@ int main(int argc, char ** argv) {
151151
auto next_token_str = llama_token_to_str(ctx2, next_token);
152152
last_n_tokens_data.push_back(next_token);
153153

154-
printf("%s", next_token_str);
154+
printf("%s", next_token_str.c_str());
155155
if (llama_eval(ctx2, &next_token, 1, n_past, params.n_threads)) {
156156
fprintf(stderr, "\n%s : failed to evaluate\n", __func__);
157157
llama_free(ctx2);

examples/simple/simple.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ int main(int argc, char ** argv)
102102

103103
for( auto id : tokens_list )
104104
{
105-
printf( "%s" , llama_token_to_str( ctx , id ) );
105+
printf( "%s" , llama_token_to_str( ctx , id ).c_str() );
106106
}
107107

108108
fflush(stdout);
@@ -162,7 +162,7 @@ int main(int argc, char ** argv)
162162
}
163163

164164
// Print the new token :
165-
printf( "%s" , llama_token_to_str( ctx , new_token_id ) );
165+
printf( "%s" , llama_token_to_str( ctx , new_token_id ).c_str() );
166166
fflush( stdout );
167167

168168
// Push this new token for next evaluation :

examples/train-text-from-scratch/train-text-from-scratch.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,7 +1959,7 @@ void print_matrix(struct ggml_tensor * probs) {
19591959

19601960

19611961
void print_token(struct llama_context * ctx, llama_token token) {
1962-
printf("%s", llama_token_to_str(ctx, token));
1962+
printf("%s", llama_token_to_str(ctx, token).c_str());
19631963
}
19641964

19651965
void print_tokens(struct llama_context* ctx, struct ggml_tensor * tokens) {
@@ -2198,17 +2198,17 @@ int tokenize_file(struct llama_context * lctx, const char * filename, std::vecto
21982198
const char * in = buf.data();
21992199
const char * end = buf.data() + buf.size();
22002200
for (int i = 0; i < (int) out.size(); ++i) {
2201-
const char * s = llama_token_to_str(lctx, out[i]);
2202-
int len = strlen(s);
2201+
std::string s = llama_token_to_str(lctx, out[i]);
2202+
int len = s.length();
22032203
if (in >= end) {
22042204
printf("%s: unexpected end of original text.\n", __func__);
22052205
break;
22062206
}
2207-
const bool matches = (strncmp(in, s, len) == 0);
2207+
const bool matches = (strncmp(in, s.c_str(), len) == 0);
22082208
if (matches) {
22092209
in += len;
22102210
} else {
2211-
printf("%s: mismatch: expected '%s', but got '%s'\n", __func__, std::string(in, len).c_str(), s);
2211+
printf("%s: mismatch: expected '%s', but got '%s'\n", __func__, std::string(in, len).c_str(), s.c_str());
22122212
}
22132213
}
22142214
}

llama.cpp

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,6 @@ struct llama_kv_cache {
242242
}
243243
};
244244

245-
struct llama_trie {
246-
std::unordered_map<std::string, llama_trie> map;
247-
};
248-
249-
void llama_trie_insert(struct llama_trie& trie, const std::string& text, size_t offs);
250-
size_t llama_trie_find(const struct llama_trie& trie, const std::string& text, size_t offs);
251-
252245
struct llama_vocab {
253246
using id = int32_t;
254247
using token = std::string;
@@ -260,7 +253,6 @@ struct llama_vocab {
260253

261254
std::unordered_map<token, id> token_to_id;
262255
std::vector<token_score> id_to_token;
263-
struct llama_trie trie;
264256
};
265257

266258
struct llama_model {
@@ -524,13 +516,12 @@ struct llama_file_loader {
524516
float score = 0.0f;
525517
file.read_raw(&score, sizeof(score));
526518

519+
assert(vocab.token_to_id.find(word) == vocab.token_to_id.end());
527520
vocab.token_to_id[word] = i;
528521

529522
auto & tok_score = vocab.id_to_token[i];
530523
tok_score.tok = word;
531524
tok_score.score = score;
532-
533-
llama_trie_insert(vocab.trie, word, 0);
534525
}
535526
}
536527
void read_tensor_metadata(llama_load_tensors_map & tensors_map) {
@@ -1804,26 +1795,37 @@ struct llama_sp_bigram {
18041795
size_t size;
18051796
};
18061797

1807-
void llama_trie_insert(struct llama_trie& trie, const std::string& text, size_t offs) {
1808-
if (offs < text.size()) {
1809-
size_t char_len = utf8_len(text[offs]);
1810-
std::string key = text.substr(offs, char_len);
1811-
if (trie.map.find(key) == trie.map.end()) {
1812-
trie.map[key] = llama_trie();
1798+
static std::string llama_escape_whitespace(const std::string& text) {
1799+
std::string result;
1800+
bool escaping = false;
1801+
result += char(0xe2);
1802+
result += char(0x96);
1803+
result += char(0x81);
1804+
for (size_t offs = 0; offs < text.length(); ++offs) {
1805+
if (text[offs] == ' ') {
1806+
if (!escaping) {
1807+
result += char(0xe2);
1808+
result += char(0x96);
1809+
result += char(0x81);
1810+
escaping = true;
1811+
}
1812+
}
1813+
else {
1814+
escaping = false;
1815+
result += text[offs];
18131816
}
1814-
llama_trie_insert(trie.map.at(key), text, offs + char_len);
18151817
}
1818+
return result;
18161819
}
18171820

1818-
size_t llama_trie_find(const struct llama_trie& trie, const std::string & text, size_t offs) {
1819-
if (offs < text.size()) {
1820-
size_t char_len = utf8_len(text[offs]);
1821-
std::string key = text.substr(offs, char_len);
1822-
if (trie.map.find(key) != trie.map.end()) {
1823-
return char_len + llama_trie_find(trie.map.at(key), text, offs + char_len);
1824-
}
1825-
}
1826-
return 0;
1821+
static std::string llama_unescape_whitespace(const std::string& word) {
1822+
if (word.length() >= 3 &&
1823+
word[0] == char(0xe2) &&
1824+
word[1] == char(0x96) &&
1825+
word[2] == char(0x81)) {
1826+
return std::string(" ") + word.substr(3);
1827+
}
1828+
return word;
18271829
}
18281830

18291831
// original implementation:
@@ -1832,13 +1834,12 @@ struct llama_tokenizer {
18321834
llama_tokenizer(const llama_vocab & vocab): vocab_(vocab) {}
18331835

18341836
void tokenize(const std::string & text, std::vector<llama_vocab::id> & output) {
1835-
// split string into utf8 chars / token?
1837+
// split string into utf8 chars
18361838
int index = 0;
18371839
size_t offs = 0;
18381840
while (offs < text.size()) {
18391841
llama_sp_symbol sym;
18401842
size_t len = utf8_len(text[offs]);
1841-
// size_t len = llama_trie_find(vocab_.trie, text, offs);
18421843
if (len == 0) {
18431844
len = utf8_len(text[offs]);
18441845
}
@@ -1908,7 +1909,7 @@ struct llama_tokenizer {
19081909

19091910
if (p == rev_merge.end()) {
19101911
// output any symbols that did not form tokens as bytes.
1911-
for (int j = 0; j < (int) symbol.n; ++j) {
1912+
for (int j = 0; j < (int)symbol.n; ++j) {
19121913
llama_vocab::id token_id = static_cast<uint8_t>(symbol.text[j]) + 3;
19131914
output.push_back(token_id);
19141915
}
@@ -1954,18 +1955,25 @@ struct llama_tokenizer {
19541955
std::map<std::string, std::pair<int, int> > rev_merge;
19551956
};
19561957

1957-
static std::vector<llama_vocab::id> llama_tokenize(const llama_vocab & vocab, const std::string & text, bool bos) {
1958+
static std::vector<llama_vocab::id> llama_tokenize(const llama_vocab & vocab, const std::string & raw_text, bool bos, bool escape) {
19581959
llama_tokenizer tokenizer(vocab);
19591960
std::vector<llama_vocab::id> output;
19601961

1961-
if (text.empty()) {
1962+
if (raw_text.empty()) {
19621963
return output;
19631964
}
19641965

19651966
if (bos) {
19661967
output.push_back(llama_token_bos());
19671968
}
19681969

1970+
std::string text;
1971+
if (escape) {
1972+
text = llama_escape_whitespace(raw_text);
1973+
} else {
1974+
text = raw_text;
1975+
}
1976+
19691977
tokenizer.tokenize(text, output);
19701978
return output;
19711979
}
@@ -3620,7 +3628,7 @@ int llama_tokenize_with_model(
36203628
llama_token * tokens,
36213629
int n_max_tokens,
36223630
bool add_bos) {
3623-
auto res = llama_tokenize(model->vocab, text, add_bos);
3631+
auto res = llama_tokenize(model->vocab, text, add_bos, true);
36243632

36253633
if (n_max_tokens < (int) res.size()) {
36263634
fprintf(stderr, "%s: too many tokens\n", __func__);
@@ -3643,6 +3651,27 @@ int llama_tokenize(
36433651
return llama_tokenize_with_model(&ctx->model, text, tokens, n_max_tokens, add_bos);
36443652
}
36453653

3654+
int llama_tokenize_bpe(
3655+
struct llama_context * ctx,
3656+
const char * text,
3657+
llama_token * tokens,
3658+
int n_max_tokens,
3659+
bool add_bos) {
3660+
auto res = llama_tokenize(ctx->model.vocab, text, add_bos, false);
3661+
3662+
if (n_max_tokens < (int) res.size()) {
3663+
fprintf(stderr, "%s: too many tokens\n", __func__);
3664+
return -((int) res.size());
3665+
}
3666+
3667+
for (size_t i = 0; i < res.size(); i++) {
3668+
tokens[i] = res[i];
3669+
}
3670+
3671+
return res.size();
3672+
}
3673+
3674+
36463675
int llama_n_vocab_from_model(const struct llama_model * model) {
36473676
return model->vocab.id_to_token.size();
36483677
}
@@ -3696,18 +3725,26 @@ float * llama_get_embeddings(struct llama_context * ctx) {
36963725
return ctx->embedding.data();
36973726
}
36983727

3699-
const char * llama_token_to_str_with_model(const struct llama_model * model, llama_token token) {
3728+
std::string llama_token_to_str_with_model(const struct llama_model * model, llama_token token) {
37003729
if (token >= llama_n_vocab_from_model(model)) {
37013730
return nullptr;
37023731
}
37033732

3704-
return model->vocab.id_to_token[token].tok.c_str();
3733+
return llama_unescape_whitespace(model->vocab.id_to_token[token].tok);
37053734
}
37063735

3707-
const char * llama_token_to_str(const struct llama_context * ctx, llama_token token) {
3736+
std::string llama_token_to_str(const struct llama_context * ctx, llama_token token) {
37083737
return llama_token_to_str_with_model(&ctx->model, token);
37093738
}
37103739

3740+
std::string llama_token_to_str_bpe(const struct llama_context * ctx, llama_token token) {
3741+
if (token >= llama_n_vocab_from_model(&ctx->model)) {
3742+
return nullptr;
3743+
}
3744+
3745+
return ctx->model.vocab.id_to_token[token].tok;
3746+
}
3747+
37113748
llama_token llama_token_bos() {
37123749
return 1;
37133750
}

llama.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <stddef.h>
1212
#include <stdint.h>
1313
#include <stdbool.h>
14+
#include <string>
1415

1516
#ifdef LLAMA_SHARED
1617
# if defined(_WIN32) && !defined(__MINGW32__)
@@ -278,6 +279,13 @@ extern "C" {
278279
int n_max_tokens,
279280
bool add_bos);
280281

282+
LLAMA_API int llama_tokenize_bpe(
283+
struct llama_context * ctx,
284+
const char * text,
285+
llama_token * tokens,
286+
int n_max_tokens,
287+
bool add_bos);
288+
281289
LLAMA_API int llama_tokenize_with_model(
282290
const struct llama_model * model,
283291
const char * text,
@@ -319,11 +327,15 @@ extern "C" {
319327
LLAMA_API float * llama_get_embeddings(struct llama_context * ctx);
320328

321329
// Token Id -> String. Uses the vocabulary in the provided context
322-
LLAMA_API const char * llama_token_to_str(
330+
LLAMA_API std::string llama_token_to_str(
331+
const struct llama_context * ctx,
332+
llama_token token);
333+
334+
LLAMA_API std::string llama_token_to_str_bpe(
323335
const struct llama_context * ctx,
324336
llama_token token);
325337

326-
LLAMA_API const char * llama_token_to_str_with_model(
338+
LLAMA_API std::string llama_token_to_str_with_model(
327339
const struct llama_model * model,
328340
llama_token token);
329341

0 commit comments

Comments
 (0)