45 memset(tok, 0,
sizeof(*tok));
112 for (
size_t i = 0; i < tok->
vocab_size; i++) {
139 for (
size_t i = 0; i < tok->
vocab_size; i++) {
163 if (!tok || !
token) {
170 while (new_cap <= (
size_t)
id) {
173 char **new_array = (
char **)realloc(tok->
id_to_token, new_cap *
sizeof(
char *));
186 existing->score =
score;
194 TokenInfo *info = (TokenInfo *)malloc(
sizeof(TokenInfo));
195 if (!info)
return -1;
198 info->is_special =
false;
219 if (!tok || !name)
return -1;
223 if (info) info->is_special =
true;
230 if (strcmp(name,
"<unk>") == 0 || strcmp(name,
"[UNK]") == 0) tok->
unk_id =
id;
231 else if (strcmp(name,
"<s>") == 0 || strcmp(name,
"<bos>") == 0 || strcmp(name,
"[BOS]") == 0) tok->
bos_id =
id;
232 else if (strcmp(name,
"</s>") == 0 || strcmp(name,
"<eos>") == 0 || strcmp(name,
"[EOS]") == 0) tok->
eos_id =
id;
233 else if (strcmp(name,
"<pad>") == 0 || strcmp(name,
"[PAD]") == 0) tok->
pad_id =
id;
296 for (
size_t i = 0; i < tok->
vocab_size; i++) {
298 if (!
token)
continue;
300 unsigned char c0 = (
unsigned char)
token[0];
301 unsigned char c1 = (
unsigned char)
token[1];
304 if (c0 == 0xC4 && c1 == 0xA0) {
308 else if (c0 == 0xE2 && c1 == 0x96 && (
unsigned char)
token[2] == 0x81) {
315 if (spm_count > gpt2_count * 2 && spm_count > 0) {
317 }
else if (gpt2_count > 0) {
331 if (!tok || !
token)
return -1;
333 return info ? info->id : tok->
unk_id;
338 if (!tok || id < 0 || id >= (int32_t)tok->
vocab_size)
return NULL;
346 return tok ? tok->
unk_id : -1;
350 return token_id >= 0 ? token_id : tok->
unk_id;
357 return tok ? tok->
unk_id : -1;
363 int32_t best_id = tok->
unk_id;
366 for (
size_t len =
max_len; len >= 1; len--) {
368 memcpy(tmp,
text + pos, len);
379 *match_len = best_len;
407 if (
out_len + 3 > out_max)
return -1;
413 for (
int i = 0; i <
text_len; i++) {
414 if (
text[i] ==
' ') {
417 if (
out_len + 3 > out_max)
return -1;
423 if (
out_len + 2 > out_max)
return -1;
428 if (
out_len + 1 > out_max)
return -1;
447 char preprocessed[8192];
448 const char *input =
text;
460 preprocessed[pp_len] =
'\0';
461 input = preprocessed;
472 while (pos < (
size_t)input_len && out_idx <
max_ids) {
473 size_t match_len = 0;
476 if (match_len == 0) {
497 for (
int i = 0; i <
num_ids; i++) {
499 if (
id < 0)
continue;
501 if (!
token)
continue;
502 int token_len = (int)strlen(
token);
505 unsigned char c0 = (
unsigned char)
token[0];
506 unsigned char c1 = (
unsigned char)
token[1];
508 if (c0 == 0xC4 && c1 == 0xA0) {
511 token += 2; token_len -= 2;
512 }
else if (c0 == 0xE2 && c1 == 0x96 && (
unsigned char)
token[2] == 0x81) {
515 token += 3; token_len -= 3;
520 if (token_len == 6 &&
token[0] ==
'<' &&
token[1] ==
'0' &&
522 unsigned int byte_val = 0;
523 if (sscanf(
token,
"<0x%02X>", &byte_val) == 1 && byte_val < 256) {
524 if (len <
max_len - 1)
text[len++] = (char)byte_val;
529 for (
int j = 0; j < token_len && len <
max_len - 1; ) {
530 if (j + 2 < token_len &&
531 (
unsigned char)
token[j] == 0xE2 &&
532 (
unsigned char)
token[j + 1] == 0x96 &&
533 (
unsigned char)
token[j + 2] == 0x81) {
#define CK_TOKENIZER_HT_BUCKETS_LARGE
void ck_tokenizer_hash_table_free(CKTokenizerHashTable *table, bool free_values)
int ck_tokenizer_hash_table_insert(CKTokenizerHashTable *table, const char *key, void *value)
CKTokenizerHashTable * ck_tokenizer_hash_table_create(size_t bucket_count)
void * ck_tokenizer_hash_table_lookup(CKTokenizerHashTable *table, const char *key)
void ck_tokenizer_hash_table_clear(CKTokenizerHashTable *table, bool free_values)
CKTrie * ck_trie_create(size_t max_nodes)
void ck_trie_clear(CKTrie *trie)
int32_t ck_trie_find_longest(const CKTrie *trie, const char *text, size_t text_len, size_t start_pos, size_t *match_len)
int ck_trie_insert(CKTrie *trie, const char *token, int32_t token_id, bool is_special, int32_t priority)
void ck_trie_free(CKTrie *trie)
int ck_tokenizer_mempool_init(CKTokenizerMemPool *pool, size_t size)
void ck_tokenizer_mempool_free(CKTokenizerMemPool *pool)
bool space_prefix_detected
CKSpacePrefixStyle space_prefix_style
CKTokenizerHashTable * vocab
void ck_tokenizer_set_add_bos_eos(CKTokenizer *tok, bool add_bos, bool add_eos)
int32_t ck_tokenizer_lookup(const CKTokenizer *tok, const char *token)
int ck_tokenizer_decode(const CKTokenizer *tok, const int32_t *ids, int num_ids, char *text, int max_len)
int ck_tokenizer_add_token(CKTokenizer *tok, const char *token, int32_t id, float score)
CKSpacePrefixStyle ck_tokenizer_detect_space_prefix_style(CKTokenizer *tok)
int ck_tokenizer_load_text(CKTokenizer *tok, const char *path)
int ck_tokenizer_load_gguf(CKTokenizer *tok, const char *path)
int ck_tokenizer_load_json(CKTokenizer *tok, const char *path)
void ck_tokenizer_set_spm_mode(CKTokenizer *tok, CKSpmMode spm_mode)
static int32_t find_longest_match(const CKTokenizer *tok, const char *text, size_t text_len, size_t pos, size_t *match_len)
int ck_tokenizer_load_binary(CKTokenizer *tok, int vocab_size, const int32_t *offsets, const char *strings, int num_merges, const int32_t *merges)
int ck_tokenizer_encode_spm_dispatch(const CKTokenizer *tok, const char *text, int text_len, int32_t *ids, int max_ids)
CKTokenizer * ck_tokenizer_create(CKTokenizerType type)
int ck_tokenizer_add_merge(CKTokenizer *tok, int32_t left, int32_t right, int32_t merged, int32_t priority)
int ck_tokenizer_encode(const CKTokenizer *tok, const char *text, int text_len, int32_t *ids, int max_ids)
void ck_tokenizer_set_special_ids(CKTokenizer *tok, int32_t unk, int32_t bos, int32_t eos, int32_t pad, int32_t mask)
static int32_t find_longest_match_trie(const CKTokenizer *tok, const char *text, size_t text_len, size_t pos, size_t *match_len)
void ck_tokenizer_reset(CKTokenizer *tok)
int ck_tokenizer_add_special_token(CKTokenizer *tok, const char *name, int32_t id)
void ck_tokenizer_free(CKTokenizer *tok)
int ck_tokenizer_load_merges(CKTokenizer *tok, const char *path)
static int preprocess_bpe_spaces(const char *text, int text_len, char *out, int out_max, CKSpacePrefixStyle style)
const char * ck_tokenizer_id_to_token(const CKTokenizer *tok, int32_t id)
void ck_tokenizer_set_use_trie(CKTokenizer *tok, bool use_trie)
void ck_tokenizer_set_add_space_prefix(CKTokenizer *tok, bool add_space_prefix)
static int32_t find_longest_match_hash(const CKTokenizer *tok, const char *text, size_t text_len, size_t pos, size_t *match_len)
void ck_tokenizer_set_space_prefix_style(CKTokenizer *tok, CKSpacePrefixStyle style)
int32_t int32_t int32_t int32_t int32_t mask
int ck_tokenizer_load_binary_with_scores(CKTokenizer *tok, int vocab_size, const int32_t *offsets, const char *strings, const float *scores, const uint8_t *types, int num_merges, const int32_t *merges)
const int32_t int num_ids
int32_t int32_t int32_t eos
int32_t int32_t int32_t int32_t pad
const int32_t int int * out_len
const CKBPEConfig * config
int const int32_t const char int num_merges
int const int32_t const char * strings
int const int32_t const char int const int32_t * merges
int32_t int32_t int32_t int32_t priority
const int32_t int char int max_len
int const int32_t * offsets
const char int int32_t int max_ids
const char const char * right