← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
tokenizer.h File Reference
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "tokenizer/murmurhash3.h"
#include "tokenizer/memory_pool.h"
#include "tokenizer/hash_table.h"
#include "tokenizer/utf8.h"
#include "data_structures/tries/trie.h"

Go to the source code of this file.

Data Structures

struct  CKTokenizer
 
struct  CKTokenizerConfig
 
struct  CKTokenizerToken
 

Macros

#define CK_TOKENIZER_API   __attribute__((visibility("default")))
 
#define CK_TOKENIZER_DEFAULT_HT_SIZE   65536
 
#define CK_TOKENIZER_MAX_TOKEN_LEN   256
 
#define CK_TOKENIZER_MAX_VOCAB_SIZE   256000
 

Enumerations

enum  CKSpacePrefixStyle { CK_SPACE_PREFIX_AUTO = 0 , CK_SPACE_PREFIX_GPT2 = 1 , CK_SPACE_PREFIX_SPM = 2 , CK_SPACE_PREFIX_ASCII = 3 }
 
enum  CKSpmMode { CK_SPM_MODE_UNIGRAM = 0 , CK_SPM_MODE_LLAMA = 1 }
 
enum  CKTokenizerType { CK_TOKENIZER_BPE = 0 , CK_TOKENIZER_WORDPIECE = 1 , CK_TOKENIZER_SPM = 2 }
 

Functions

 __attribute__ ((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)
 
int ck_tokenizer_add_merge (CKTokenizer *tok, int32_t left_id, int32_t right_id, int32_t merged_id, int32_t priority)
 
int ck_tokenizer_add_special_token (CKTokenizer *tok, const char *name, int32_t id)
 
int ck_tokenizer_add_token (CKTokenizer *tok, const char *token, int32_t id, float score)
 
static CKTokenizerck_tokenizer_create_bpe (void)
 
static CKTokenizerck_tokenizer_create_spm (void)
 
static CKTokenizerck_tokenizer_create_wordpiece (void)
 
int ck_tokenizer_decode (const CKTokenizer *tok, const int32_t *ids, int num_ids, char *text, int max_len)
 
int ck_tokenizer_encode (const CKTokenizer *tok, const char *text, int text_len, int32_t *ids, int max_ids)
 
int ck_tokenizer_encode_tokens (const CKTokenizer *tok, const char *text, int text_len, const char **out_tokens, int max_tokens)
 
int ck_tokenizer_encode_with_special (CKTokenizer *tok, const char *text, int text_len, int32_t *ids, int max_ids, bool add_special)
 
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_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)
 
int ck_tokenizer_load_gguf (CKTokenizer *tok, const char *path)
 
int ck_tokenizer_load_json (CKTokenizer *tok, const char *path)
 
int ck_tokenizer_load_merges (CKTokenizer *tok, const char *path)
 
int ck_tokenizer_load_text (CKTokenizer *tok, const char *path)
 
static size_t ck_tokenizer_vocab_size (const CKTokenizer *tok)
 

Variables

bool add_bos
 
bool bool add_eos
 
bool add_space_prefix
 
int32_t int32_t bos
 
int32_t int32_t int32_t eos
 
int32_t id
 
const int32_t * ids
 
bool lowercase
 
int32_t int32_t int32_t int32_t int32_t mask
 
const int32_t int num_ids
 
const int32_t int int * out_len
 
int32_t int32_t int32_t int32_t pad
 
int32_t float * score
 
CKSpmMode spm_mode
 
CKSpacePrefixStyle style
 
const char * text
 
const char * token
 
int32_t unk
 
bool use_trie
 

Macro Definition Documentation

◆ CK_TOKENIZER_API

#define CK_TOKENIZER_API   __attribute__((visibility("default")))

Definition at line 40 of file tokenizer.h.

◆ CK_TOKENIZER_DEFAULT_HT_SIZE

#define CK_TOKENIZER_DEFAULT_HT_SIZE   65536

Definition at line 50 of file tokenizer.h.

◆ CK_TOKENIZER_MAX_TOKEN_LEN

#define CK_TOKENIZER_MAX_TOKEN_LEN   256

Definition at line 44 of file tokenizer.h.

◆ CK_TOKENIZER_MAX_VOCAB_SIZE

#define CK_TOKENIZER_MAX_VOCAB_SIZE   256000

Definition at line 47 of file tokenizer.h.

Enumeration Type Documentation

◆ CKSpacePrefixStyle

Enumerator
CK_SPACE_PREFIX_AUTO 
CK_SPACE_PREFIX_GPT2 
CK_SPACE_PREFIX_SPM 
CK_SPACE_PREFIX_ASCII 

Definition at line 60 of file tokenizer.h.

60 {
61 CK_SPACE_PREFIX_AUTO = 0, /* Auto-detect from vocabulary */
62 CK_SPACE_PREFIX_GPT2 = 1, /* GPT-2 style: Ġ (U+0120, bytes 0xC4 0xA0) */
63 CK_SPACE_PREFIX_SPM = 2, /* SentencePiece style: ▁ (U+2581, bytes 0xE2 0x96 0x81) */
64 CK_SPACE_PREFIX_ASCII = 3 /* ASCII identity mode: no UTF-8/byte remap */
CKSpacePrefixStyle
Definition tokenizer.h:60
@ CK_SPACE_PREFIX_AUTO
Definition tokenizer.h:61
@ CK_SPACE_PREFIX_SPM
Definition tokenizer.h:63
@ CK_SPACE_PREFIX_GPT2
Definition tokenizer.h:62
@ CK_SPACE_PREFIX_ASCII
Definition tokenizer.h:64

◆ CKSpmMode

enum CKSpmMode
Enumerator
CK_SPM_MODE_UNIGRAM 
CK_SPM_MODE_LLAMA 

Definition at line 68 of file tokenizer.h.

68 {
69 CK_SPM_MODE_UNIGRAM = 0, /* SentencePiece unigram/Viterbi */
70 CK_SPM_MODE_LLAMA = 1 /* llama.cpp merge-style SPM */
71} CKSpmMode;
CKSpmMode
Definition tokenizer.h:68
@ CK_SPM_MODE_UNIGRAM
Definition tokenizer.h:69
@ CK_SPM_MODE_LLAMA
Definition tokenizer.h:70

◆ CKTokenizerType

Enumerator
CK_TOKENIZER_BPE 
CK_TOKENIZER_WORDPIECE 
CK_TOKENIZER_SPM 

Definition at line 53 of file tokenizer.h.

53 {
54 CK_TOKENIZER_BPE = 0, /* Byte-Pair Encoding (GPT-2, LLaMA, Qwen) */
55 CK_TOKENIZER_WORDPIECE = 1, /* WordPiece (BERT, RoBERTa) */
56 CK_TOKENIZER_SPM = 2 /* SentencePiece (unigram) */
CKTokenizerType
Definition tokenizer.h:53
@ CK_TOKENIZER_BPE
Definition tokenizer.h:54
@ CK_TOKENIZER_SPM
Definition tokenizer.h:56
@ CK_TOKENIZER_WORDPIECE
Definition tokenizer.h:55

Function Documentation

◆ __attribute__()

__attribute__ ( (visibility("default"))  )

Create a new tokenizer.

Parameters
typeTokenizer type (BPE, WordPiece, SPM)
Returns
Newly allocated tokenizer, or NULL on error

Free a tokenizer.

Parameters
tokTokenizer to free

Reset tokenizer state (clear vocab but keep config).

Parameters
tokTokenizer to reset

Set special token IDs.

Parameters
tokTokenizer
unkUnknown token ID
bosBeginning-of-sequence token ID
eosEnd-of-sequence token ID
padPadding token ID
maskMask token ID

Set whether to add BOS/EOS tokens during encoding.

Parameters
tokTokenizer
add_bosIf true, prepend BOS token (if available)
add_eosIf true, append EOS token (if available)

Set whether to add the SentencePiece space prefix (▁) at the start.

This mirrors SentencePiece's add_dummy_prefix behavior.

Parameters
tokTokenizer
add_space_prefixIf true, add leading ▁ when appropriate

Set SentencePiece mode.

Parameters
tokTokenizer
spm_modeSPM mode (unigram or llama-style)

Set whether to lowercase input text before tokenizing.

Parameters
tokTokenizer
lowercaseIf true, convert text to lowercase

Set lookup method (trie vs hash table).

Parameters
tokTokenizer
use_trieIf true, use trie (faster for longest-match), false = hash table

Set space prefix style for BPE tokenizers.

GPT-2/Qwen use Ġ (U+0120), LLaMA/SentencePiece use ▁ (U+2581). Default is AUTO which auto-detects from vocabulary.

Parameters
tokTokenizer
styleSpace prefix style (AUTO, GPT2, or SPM)

Auto-detect space prefix style from vocabulary.

Checks for presence of tokens starting with Ġ vs ▁ to determine style.

Parameters
tokTokenizer
Returns
Detected style (GPT2 or SPM)

Look up token ID by string.

Parameters
tokTokenizer
tokenToken string
Returns
Token ID, or unk_id if not found

Get token string by ID.

Parameters
tokTokenizer
idToken ID
Returns
Token string, or NULL if invalid

Get token info by ID.

Parameters
tokTokenizer
idToken ID
scoreOutput: token score
Returns
Token string, or NULL if invalid

Decode to buffer allocated by caller.

Parameters
tokTokenizer
idsInput token IDs
num_idsNumber of IDs
out_lenOutput: length of decoded string
Returns
Newly allocated string, or NULL on error

Get the tokenizer type name.

Parameters
tokTokenizer
Returns
Type name string

Check if token is special.

Parameters
tokTokenizer
idToken ID
Returns
true if special token

Estimate encoded token count.

Parameters
tokTokenizer
textInput text
Returns
Estimated number of tokens

Get last error message.

Returns
Last error message, or NULL if no error

Free a True BPE tokenizer.

Parameters
bpeTokenizer to free

Add a token to the vocabulary.

Parameters
bpeTokenizer
tokenToken string (UTF-8)
idToken ID
scoreToken score (for unigram models, 0.0 for BPE)
Returns
0 on success, -1 on error

Add a BPE merge rule by token IDs.

Merge rules define how tokens are combined during encoding. Rules with lower priority numbers are applied first.

Parameters
bpeTokenizer
left_idLeft token ID
right_idRight token ID
merged_idResulting merged token ID
priorityMerge priority (lower = applied first)
Returns
0 on success, -1 on error

Add a BPE merge rule by token strings.

This looks up the token IDs automatically and determines the merged token. The merged token must already exist in the vocabulary.

Parameters
bpeTokenizer
leftLeft token string
rightRight token string
priorityMerge priority (lower = applied first)
Returns
0 on success, -1 on error

Set special token IDs.

Parameters
bpeTokenizer
unkUnknown token ID (-1 to disable)
bosBeginning-of-sequence token ID (-1 to disable)
eosEnd-of-sequence token ID (-1 to disable)
padPadding token ID (-1 to disable)

Add a special token that should be matched BEFORE BPE encoding.

Special tokens like <|im_start|>, <|im_end|>, <|endoftext|> are matched literally in the input text before BPE processing. Without this, BPE would break them into individual characters.

Parameters
bpeTokenizer
tokenToken string to match literally (e.g., "<|im_end|>")
idToken ID to output when matched
Returns
0 on success, -1 on error

Set tokenizer configuration.

Parameters
bpeTokenizer
configConfiguration to apply

Load vocabulary + merges from binary buffers.

Parameters
bpeTokenizer
vocab_sizeNumber of tokens
offsetsOffsets array (length vocab_size)
stringsNull-terminated token strings blob
num_mergesNumber of merge rules
mergesMerge triples [left_id, right_id, merged_id] (length num_merges*3)
Returns
0 on success, -1 on error

Look up a token ID by string.

Parameters
bpeTokenizer
tokenToken string
Returns
Token ID, or unk_id if not found

Get a token string by ID.

Parameters
bpeTokenizer
idToken ID
Returns
Token string, or NULL if invalid

Get vocabulary size.

Parameters
bpeTokenizer
Returns
Number of tokens in vocabulary

Get number of merge rules.

Parameters
bpeTokenizer
Returns
Number of merge rules

Auto-detect space prefix style from vocabulary.

Counts tokens starting with Ġ (GPT-2) vs ▁ (SentencePiece) to determine style. The detected style is cached in the config.

Parameters
bpeTokenizer
Returns
Detected style (GPT2 or SPM)

Encode text to token IDs using true BPE algorithm.

This applies merge rules in priority order (not greedy longest-match).

Parameters
bpeTokenizer
textInput text (UTF-8)
text_lenText length in bytes, or -1 for null-terminated
idsOutput token IDs array
max_idsMaximum IDs to write
Returns
Number of tokens written

Decode token IDs to text.

Parameters
bpeTokenizer
idsInput token IDs
num_idsNumber of IDs
textOutput text buffer
max_lenMaximum text length
Returns
Number of bytes written (excluding null terminator)

Referenced by __attribute__(), fused_mlp_swiglu_decode(), fused_mlp_swiglu_decode_tiled(), fused_mlp_swiglu_decode_v2(), gelu_backward_exact(), gelu_backward_fast(), gelu_fast_inplace(), recurrent_dt_gate_forward_pytorch_fp32(), recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output(), recurrent_silu_forward_pytorch_bf16_input_fp32_output(), recurrent_silu_forward_pytorch_bf16_storage(), rmsnorm_qkv_q4k_fused(), swiglu_backward(), swiglu_forward(), and swiglu_forward_pytorch_bf16_storage().

◆ ck_tokenizer_add_merge()

int ck_tokenizer_add_merge ( CKTokenizer tok,
int32_t  left_id,
int32_t  right_id,
int32_t  merged_id,
int32_t  priority 
)

Add a BPE merge rule.

Parameters
tokTokenizer
left_idLeft token ID
right_idRight token ID
merged_idMerged token ID
priorityLower = higher priority (applied first)
Returns
0 on success, -1 on error

Definition at line 560 of file tokenizer.c.

560 {
561 (void)tok; (void)left; (void)right; (void)merged; (void)priority; return 0;
562}
int32_t int32_t int32_t int32_t priority
Definition true_bpe.h:123
const char * left
Definition true_bpe.h:138
const char const char * right
Definition true_bpe.h:139

References left, priority, and right.

◆ ck_tokenizer_add_special_token()

int ck_tokenizer_add_special_token ( CKTokenizer tok,
const char *  name,
int32_t  id 
)

Add special token (UNK, BOS, EOS, PAD, MASK).

Parameters
tokTokenizer
nameSpecial token name ("unk", "bos", "eos", "pad", "mask")
idToken ID
Returns
0 on success, -1 on error

Definition at line 218 of file tokenizer.c.

218 {
219 if (!tok || !name) return -1;
220 if (ck_tokenizer_add_token(tok, name, id, -1e10f) != 0) return -1;
221
222 TokenInfo *info = (TokenInfo *)ck_tokenizer_hash_table_lookup(tok->vocab, name);
223 if (info) info->is_special = true;
224
225 /* Also add to trie as special */
226 if (tok->vocab_trie) {
227 ck_trie_insert(tok->vocab_trie, name, id, true, 0);
228 }
229
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;
234
235 return 0;
236}
void * ck_tokenizer_hash_table_lookup(CKTokenizerHashTable *table, const char *key)
Definition hash_table.c:202
int ck_trie_insert(CKTrie *trie, const char *token, int32_t token_id, bool is_special, int32_t priority)
Definition trie.c:110
int32_t bos_id
int32_t unk_id
CKTrie * vocab_trie
Definition tokenizer.h:104
int32_t eos_id
CKTokenizerHashTable * vocab
Definition tokenizer.h:101
int32_t pad_id
int ck_tokenizer_add_token(CKTokenizer *tok, const char *token, int32_t id, float score)
Definition tokenizer.c:162
int32_t id
Definition tokenizer.h:316

References CKTokenizer::bos_id, ck_tokenizer_add_token(), ck_tokenizer_hash_table_lookup(), ck_trie_insert(), CKTokenizer::eos_id, id, CKTokenizer::pad_id, CKTokenizer::unk_id, CKTokenizer::vocab, and CKTokenizer::vocab_trie.

Referenced by main().

◆ ck_tokenizer_add_token()

int ck_tokenizer_add_token ( CKTokenizer tok,
const char *  token,
int32_t  id,
float  score 
)

Add a token to vocabulary.

Parameters
tokTokenizer
tokenToken string
idToken ID
scoreToken score (for SPM)
Returns
0 on success, -1 on error

Definition at line 162 of file tokenizer.c.

162 {
163 if (!tok || !token) {
164 return -1;
165 }
166
167 /* Ensure we have space in reverse vocab */
168 if (id >= (int32_t)tok->vocab_capacity) {
169 size_t new_cap = tok->vocab_capacity * 2;
170 while (new_cap <= (size_t)id) {
171 new_cap *= 2;
172 }
173 char **new_array = (char **)realloc(tok->id_to_token, new_cap * sizeof(char *));
174 if (!new_array) {
175 return -1;
176 }
177 memset(new_array + tok->vocab_capacity, 0, (new_cap - tok->vocab_capacity) * sizeof(char *));
178 tok->id_to_token = new_array;
179 tok->vocab_capacity = new_cap;
180 }
181
182 /* Check if token already exists */
183 TokenInfo *existing = (TokenInfo *)ck_tokenizer_hash_table_lookup(tok->vocab, token);
184 if (existing) {
185 existing->id = id;
186 existing->score = score;
187 if (id >= (int32_t)tok->vocab_size) tok->vocab_size = id + 1;
188 if (tok->id_to_token[id]) free(tok->id_to_token[id]);
189 tok->id_to_token[id] = strdup(token);
190 return 0;
191 }
192
193 /* Create new token info */
194 TokenInfo *info = (TokenInfo *)malloc(sizeof(TokenInfo));
195 if (!info) return -1;
196 info->id = id;
197 info->score = score;
198 info->is_special = false;
199
200 if (ck_tokenizer_hash_table_insert(tok->vocab, token, info) != 0) {
201 free(info);
202 return -1;
203 }
204
205 /* Also add to trie for fast longest-match lookups */
206 if (tok->vocab_trie) {
207 ck_trie_insert(tok->vocab_trie, token, id, false, 0);
208 }
209
210 if (id >= (int32_t)tok->vocab_size) tok->vocab_size = id + 1;
211 if (tok->id_to_token[id]) free(tok->id_to_token[id]);
212 tok->id_to_token[id] = strdup(token);
213
214 return 0;
215}
int ck_tokenizer_hash_table_insert(CKTokenizerHashTable *table, const char *key, void *value)
Definition hash_table.c:162
size_t vocab_capacity
Definition tokenizer.h:109
char ** id_to_token
const char * token
Definition tokenizer.h:307
int32_t float * score
Definition tokenizer.h:328

References ck_tokenizer_hash_table_insert(), ck_tokenizer_hash_table_lookup(), ck_trie_insert(), id, CKTokenizer::id_to_token, score, token, CKTokenizer::vocab, CKTokenizer::vocab_capacity, CKTokenizer::vocab_size, and CKTokenizer::vocab_trie.

Referenced by ck_tokenizer_add_special_token().

◆ ck_tokenizer_create_bpe()

static CKTokenizer * ck_tokenizer_create_bpe ( void  )
inlinestatic

Create tokenizer with default BPE config.

Definition at line 157 of file tokenizer.h.

157 {
159}
CKTokenizer * ck_tokenizer_create(CKTokenizerType type)
Definition tokenizer.c:39

References CK_TOKENIZER_BPE, and ck_tokenizer_create().

Referenced by main().

◆ ck_tokenizer_create_spm()

static CKTokenizer * ck_tokenizer_create_spm ( void  )
inlinestatic

Create tokenizer with default SPM config.

Definition at line 171 of file tokenizer.h.

171 {
173}

References ck_tokenizer_create(), and CK_TOKENIZER_SPM.

◆ ck_tokenizer_create_wordpiece()

static CKTokenizer * ck_tokenizer_create_wordpiece ( void  )
inlinestatic

Create tokenizer with default WordPiece config.

Definition at line 164 of file tokenizer.h.

References ck_tokenizer_create(), and CK_TOKENIZER_WORDPIECE.

◆ ck_tokenizer_decode()

int ck_tokenizer_decode ( const CKTokenizer tok,
const int32_t *  ids,
int  num_ids,
char *  text,
int  max_len 
)

Decode token IDs to text.

Parameters
tokTokenizer
idsInput token IDs
num_idsNumber of IDs
textOutput text buffer
max_lenMaximum text length
Returns
Number of bytes written

Definition at line 734 of file ck_tokenizer.c.

738 {
739 int len = 0;
740
741 for (int i = 0; i < num_ids; i++) {
742 /* Skip special tokens */
743 if (ids[i] == tok->bos_id || ids[i] == tok->eos_id || ids[i] == tok->pad_id) {
744 continue;
745 }
746
747 const char *token = ck_tokenizer_id_to_token(tok, ids[i]);
748 if (!token) continue;
749
750 int token_len = (int)strlen(token);
751
752 /* Handle byte tokens <0xXX> */
753 if (token_len == 6 && token[0] == '<' && token[1] == '0' && token[2] == 'x') {
754 char hex[3] = {token[3], token[4], 0};
755 unsigned int byte = (unsigned int)strtol(hex, NULL, 16);
756 if (len < max_len - 1) {
757 text[len++] = (char)byte;
758 }
759 continue;
760 }
761
762 /* Handle tokenizer space prefixes:
763 * GPT/byte-level BPE: Ġ (0xC4 0xA0)
764 * SentencePiece BPE: ▁ (0xE2 0x96 0x81)
765 */
766 const char *src = token;
767 if ((unsigned char)token[0] == 0xC4 && (unsigned char)token[1] == 0xA0) {
768 if (len < max_len - 1) {
769 text[len++] = ' ';
770 }
771 src = token + 2;
772 token_len -= 2;
773 } else if ((unsigned char)token[0] == 0xE2 &&
774 (unsigned char)token[1] == 0x96 &&
775 (unsigned char)token[2] == 0x81) {
776 if (len < max_len - 1) {
777 text[len++] = ' ';
778 }
779 src = token + 3;
780 token_len -= 3;
781 }
782
783 /* Copy token, normalizing any embedded SentencePiece markers too.
784 * Some Gemma tokenizer pieces contain repeated ▁ markers after
785 * indentation or punctuation; those are word-boundary spaces, not
786 * literal output characters.
787 */
788 for (int j = 0; j < token_len && len < max_len - 1; ) {
789 if (j + 2 < token_len &&
790 (unsigned char)src[j] == 0xE2 &&
791 (unsigned char)src[j + 1] == 0x96 &&
792 (unsigned char)src[j + 2] == 0x81) {
793 text[len++] = ' ';
794 j += 3;
795 continue;
796 }
797 text[len++] = src[j++];
798 }
799 }
800
801 text[len] = '\0';
802 return len;
803}
const char * ck_tokenizer_id_to_token(const CKTokenizer *tok, int32_t id)
const int32_t * ids
Definition tokenizer.h:444
const int32_t int num_ids
Definition tokenizer.h:445
const char * text
Definition tokenizer.h:564
const int32_t int char int max_len
Definition true_bpe.h:288

References ck_tokenizer_id_to_token(), ids, max_len, num_ids, text, and token.

◆ ck_tokenizer_encode()

int ck_tokenizer_encode ( const CKTokenizer tok,
const char *  text,
int  text_len,
int32_t *  ids,
int  max_ids 
)

Encode text to token IDs using greedy longest-match.

For BPE: applies merge rules iteratively. For WordPiece/SPM: greedy longest-match from vocabulary.

Parameters
tokTokenizer
textInput text
text_lenText length, or -1 for null-terminated
idsOutput token IDs
max_idsMaximum IDs to write
Returns
Number of tokens written

Definition at line 635 of file ck_tokenizer.c.

639 {
640 if (text_len < 0) text_len = (int)strlen(text);
641
642 /* Pre-tokenize: split on whitespace, keep spaces as tokens */
643 /* For simplicity, treat each byte as initial token, then apply BPE */
644
645 /* Initial tokens: one per byte */
646 int32_t *tokens = (int32_t *)malloc(text_len * sizeof(int32_t));
647 int num_tokens = 0;
648
649 for (int i = 0; i < text_len; i++) {
650 /* Look up single-character token */
651 char c[2] = {text[i], '\0'};
652 int32_t id = ck_tokenizer_lookup(tok, c, 1);
653
654 /* Handle special byte tokens like <0xXX> */
655 if (id == tok->unk_id) {
656 char byte_token[8];
657 snprintf(byte_token, sizeof(byte_token), "<0x%02X>", (unsigned char)text[i]);
658 id = ck_tokenizer_lookup(tok, byte_token, -1);
659 }
660
661 /* Try UTF-8 multi-byte sequences */
662 if (id == tok->unk_id && (unsigned char)text[i] >= 0x80) {
663 int utf8_len = 1;
664 if ((text[i] & 0xE0) == 0xC0) utf8_len = 2;
665 else if ((text[i] & 0xF0) == 0xE0) utf8_len = 3;
666 else if ((text[i] & 0xF8) == 0xF0) utf8_len = 4;
667
668 if (i + utf8_len <= text_len) {
669 id = ck_tokenizer_lookup(tok, text + i, utf8_len);
670 if (id != tok->unk_id) {
671 tokens[num_tokens++] = id;
672 i += utf8_len - 1;
673 continue;
674 }
675 }
676 }
677
678 tokens[num_tokens++] = id;
679 }
680
681 /* Apply BPE merges iteratively */
682 bool changed = true;
683 while (changed && num_tokens > 1) {
684 changed = false;
685
686 /* Find best merge (lowest priority = earliest in merge list) */
687 int best_pos = -1;
688 int best_priority = tok->num_merges;
689
690 for (int i = 0; i < num_tokens - 1; i++) {
691 int merge_idx = ck_tokenizer_lookup_merge(tok, tokens[i], tokens[i + 1]);
692 if (merge_idx >= 0 && tok->merges[merge_idx].priority < best_priority) {
693 best_pos = i;
694 best_priority = tok->merges[merge_idx].priority;
695 }
696 }
697
698 if (best_pos >= 0) {
699 int merge_idx = ck_tokenizer_lookup_merge(tok, tokens[best_pos], tokens[best_pos + 1]);
700 tokens[best_pos] = tok->merges[merge_idx].merged;
701
702 /* Shift remaining tokens */
703 for (int i = best_pos + 1; i < num_tokens - 1; i++) {
704 tokens[i] = tokens[i + 1];
705 }
706 num_tokens--;
707 changed = true;
708 }
709 }
710
711 /* Copy to output */
712 int out_len = 0;
713
714 if (tok->add_bos && out_len < max_ids) {
715 ids[out_len++] = tok->bos_id;
716 }
717
718 for (int i = 0; i < num_tokens && out_len < max_ids; i++) {
719 ids[out_len++] = tokens[i];
720 }
721
722 if (tok->add_eos && out_len < max_ids) {
723 ids[out_len++] = tok->eos_id;
724 }
725
726 free(tokens);
727 return out_len;
728}
int32_t ck_tokenizer_lookup(const CKTokenizer *tok, const char *token, int len)
int ck_tokenizer_lookup_merge(const CKTokenizer *tok, int32_t left, int32_t right)
int32_t merged
CKMergeRule * merges
const int32_t int int * out_len
Definition tokenizer.h:446
static int utf8_len(unsigned char c)
const char int text_len
Definition true_bpe.h:270
const char int int32_t int max_ids
Definition true_bpe.h:272

References CKTokenizerConfig::add_bos, CKTokenizerConfig::add_eos, CKTokenizer::bos_id, CK_TOKENIZER_BPE, ck_tokenizer_detect_space_prefix_style(), ck_tokenizer_encode_spm_dispatch(), CK_TOKENIZER_SPM, CKTokenizer::config, config, CKTokenizer::eos_id, find_longest_match(), id, ids, max_ids, preprocess_bpe_spaces(), style, text, text_len, CKTokenizerConfig::type, and CKTokenizer::unk_id.

◆ ck_tokenizer_encode_tokens()

int ck_tokenizer_encode_tokens ( const CKTokenizer tok,
const char *  text,
int  text_len,
const char **  out_tokens,
int  max_tokens 
)

Encode and return tokens as array of strings.

Parameters
tokTokenizer
textInput text
text_lenText length
out_tokensOutput token strings (caller must free each)
max_tokensMaximum tokens
Returns
Number of tokens written

◆ ck_tokenizer_encode_with_special()

int ck_tokenizer_encode_with_special ( CKTokenizer tok,
const char *  text,
int  text_len,
int32_t *  ids,
int  max_ids,
bool  add_special 
)

Encode with special token handling.

Parameters
tokTokenizer
textInput text
text_lenText length, or -1 for null-terminated
idsOutput token IDs
max_idsMaximum IDs to write
add_specialAdd BOS/EOS tokens
Returns
Number of tokens written

◆ ck_tokenizer_load_binary()

int ck_tokenizer_load_binary ( CKTokenizer tok,
int  vocab_size,
const int32_t *  offsets,
const char *  strings,
int  num_merges,
const int32_t *  merges 
)

Load vocabulary from memory-mapped binary data.

Parameters
tokTokenizer
vocab_sizeNumber of tokens
offsetsArray of offsets into strings pool
stringsString pool containing null-terminated tokens
num_mergesNumber of BPE merges
mergesMerge rules as (left, right, merged) triplets
Returns
0 on success, -1 on error

Definition at line 18 of file ck_tokenizer_v2.c.

23 {
24 if (!tok || !offsets || !strings) return -1;
25
26 // We assume ck_tokenizer_init was already called to alloc hash tables
27 tok->vocab_size = 0;
28
29 for (int i = 0; i < vocab_size; i++) {
30 const char *token = strings + offsets[i];
31 int len = (int)strlen(token);
32
33 CKVocabEntry *entry = (CKVocabEntry *)ck_pool_alloc(&tok->pool, sizeof(CKVocabEntry));
34 entry->token = (char *)token;
35 entry->token_len = len;
36 entry->id = i;
37
38 uint32_t bucket = hash_string(token, len) % tok->vocab_hash_size;
39 entry->next = tok->vocab_hash[bucket];
40 tok->vocab_hash[bucket] = entry;
41
42 tok->id_to_token[i] = entry->token;
43 tok->vocab_size++;
44 }
45
46 if (merges && num_merges > 0) {
47 for (int i = 0; i < num_merges; i++) {
48 int32_t left = merges[i*3 + 0];
49 int32_t right = merges[i*3 + 1];
50 int32_t merged = merges[i*3 + 2];
51 ck_tokenizer_add_merge(tok, left, right, merged);
52 }
53 }
54
55 return 0;
56}
int ck_tokenizer_add_merge(CKTokenizer *tok, int32_t left, int32_t right, int32_t merged)
void * ck_pool_alloc(CKMemPool *pool, size_t size)
static uint32_t hash_string(const char *s, int len)
CKMemPool pool
CKVocabEntry ** vocab_hash
int vocab_hash_size
struct CKVocabEntry * next
int const int32_t const char int num_merges
Definition true_bpe.h:196
int const int32_t const char * strings
Definition true_bpe.h:195
int const int32_t const char int const int32_t * merges
Definition true_bpe.h:197
int vocab_size
Definition true_bpe.h:193
int const int32_t * offsets
Definition true_bpe.h:194

References ck_pool_alloc(), ck_tokenizer_add_merge(), ck_tokenizer_load_binary_with_scores(), hash_string(), hash_string(), hash_string(), hash_string(), hash_string(), CKVocabEntry::id, CKTokenizer::id_to_token, left, merges, CKVocabEntry::next, num_merges, offsets, CKTokenizer::pool, right, strings, CKVocabEntry::token, token, CKVocabEntry::token_len, CKTokenizer::vocab_hash, CKTokenizer::vocab_hash_size, CKTokenizer::vocab_size, and vocab_size.

Referenced by main().

◆ ck_tokenizer_load_binary_with_scores()

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 
)

Load vocabulary from memory-mapped binary data with scores and types.

This extended version supports SPM (SentencePiece) tokenizers which require token scores for Viterbi/DP encoding.

Parameters
tokTokenizer
vocab_sizeNumber of tokens
offsetsArray of offsets into strings pool
stringsString pool containing null-terminated tokens
scoresArray of token scores (float32), can be NULL
typesArray of token types (uint8), can be NULL
num_mergesNumber of BPE merges
mergesMerge rules as (left, right, merged) triplets
Returns
0 on success, -1 on error

Definition at line 858 of file tokenizer_spm.c.

865 {
866 if (!tok || !offsets || !strings) return -1;
868
869 /* Free any existing scores/types arrays before reallocating */
870 if (tok->scores) {
871 free(tok->scores);
872 tok->scores = NULL;
873 tok->scores_size = 0;
874 }
875 if (tok->types) {
876 free(tok->types);
877 tok->types = NULL;
878 tok->types_size = 0;
879 }
880
881 /* Allocate scores and types arrays if provided */
882 if (scores && vocab_size > 0) {
883 tok->scores = (float *)malloc(vocab_size * sizeof(float));
884 if (!tok->scores) return -1;
885 memcpy(tok->scores, scores, vocab_size * sizeof(float));
886 tok->scores_size = (size_t)vocab_size;
887 }
888 if (types && vocab_size > 0) {
889 tok->types = (uint8_t *)malloc(vocab_size * sizeof(uint8_t));
890 if (!tok->types) {
891 if (tok->scores) {
892 free(tok->scores);
893 tok->scores = NULL;
894 }
895 return -1;
896 }
897 memcpy(tok->types, types, vocab_size * sizeof(uint8_t));
898 tok->types_size = (size_t)vocab_size;
899 }
900
901 for (int i = 0; i < vocab_size; i++) {
902 const char *token = strings + offsets[i];
903 float score = scores ? scores[i] : 0.0f;
905 }
906
907 /* Build byte token lookup table if types are available */
908 if (types && vocab_size > 0) {
910
911 /* Log token type statistics */
912 int count_normal = 0, count_unknown = 0, count_control = 0, count_byte = 0, count_other = 0;
913 int max_type = 0;
914 for (int i = 0; i < vocab_size; i++) {
915 uint8_t t = tok->types[i];
916 if (t > max_type) max_type = t;
917 switch (t) {
918 case GGUF_TOKEN_NORMAL: count_normal++; break;
919 case GGUF_TOKEN_UNKNOWN: count_unknown++; break;
920 case GGUF_TOKEN_CONTROL: count_control++; break;
921 case GGUF_TOKEN_BYTE: count_byte++; break;
922 default: count_other++; break;
923 }
924 }
925 fprintf(stderr, "[TOKENIZER] Loaded %d tokens: normal=%d, unknown=%d, control=%d, byte=%d, other=%d\n",
926 vocab_size, count_normal, count_unknown, count_control, count_byte, count_other);
927 if (max_type > GGUF_TOKEN_BYTE) {
928 fprintf(stderr, "[TOKENIZER] Warning: Unexpected token type %d\n", max_type);
929 }
930 }
931
932 /* TODO: Merges */
933 (void)num_merges; (void)merges;
934 return 0;
935}
int32_t ck_tokenizer_add_token(CKTokenizer *tok, const char *token, int len)
float * scores
Definition tokenizer.h:112
size_t types_size
Definition tokenizer.h:115
uint8_t * types
Definition tokenizer.h:114
size_t scores_size
Definition tokenizer.h:113
void ck_tokenizer_reset(CKTokenizer *tok)
Definition tokenizer.c:130
#define GGUF_TOKEN_CONTROL
static void spm_build_byte_lookup(CKTokenizer *tok, const char *strings, const int32_t *offsets, int vocab_size)
#define GGUF_TOKEN_BYTE
#define GGUF_TOKEN_UNKNOWN
#define GGUF_TOKEN_NORMAL

References ck_tokenizer_add_token(), ck_tokenizer_reset(), GGUF_TOKEN_BYTE, GGUF_TOKEN_CONTROL, GGUF_TOKEN_NORMAL, GGUF_TOKEN_UNKNOWN, merges, num_merges, offsets, score, CKTokenizer::scores, CKTokenizer::scores_size, spm_build_byte_lookup(), strings, token, CKTokenizer::types, CKTokenizer::types_size, and vocab_size.

Referenced by ck_tokenizer_load_binary().

◆ ck_tokenizer_load_gguf()

int ck_tokenizer_load_gguf ( CKTokenizer tok,
const char *  path 
)

Load vocabulary from GGUF file.

Parameters
tokTokenizer
pathPath to GGUF file
Returns
0 on success, -1 on error

Definition at line 556 of file tokenizer.c.

556{ (void)tok; (void)path; return -1; }

◆ ck_tokenizer_load_json()

int ck_tokenizer_load_json ( CKTokenizer tok,
const char *  path 
)

Load vocabulary from JSON file (HuggingFace format).

Parameters
tokTokenizer
pathPath to vocab.json or tokenizer.json
Returns
0 on success, -1 on error

Definition at line 557 of file tokenizer.c.

557{ (void)tok; (void)path; return -1; }

◆ ck_tokenizer_load_merges()

int ck_tokenizer_load_merges ( CKTokenizer tok,
const char *  path 
)

Load BPE merges from text file.

Format: token1 token2 (one merge per line)

Parameters
tokTokenizer
pathPath to merges.txt
Returns
0 on success, -1 on error

Definition at line 559 of file tokenizer.c.

559{ (void)tok; (void)path; return -1; }

◆ ck_tokenizer_load_text()

int ck_tokenizer_load_text ( CKTokenizer tok,
const char *  path 
)

Load vocabulary from text file (one token per line).

Format: token_string [id] [score] Lines starting with # are comments.

Parameters
tokTokenizer
pathPath to vocabulary file
Returns
0 on success, -1 on error

Definition at line 558 of file tokenizer.c.

558{ (void)tok; (void)path; return -1; }

◆ ck_tokenizer_vocab_size()

static size_t ck_tokenizer_vocab_size ( const CKTokenizer tok)
inlinestatic

Get vocabulary size.

Definition at line 333 of file tokenizer.h.

333 {
334 return tok ? tok->vocab_size : 0;
335}

References CKTokenizer::vocab_size.

Variable Documentation

◆ add_bos

bool add_bos

Definition at line 243 of file tokenizer.h.

Referenced by ck_tokenizer_set_add_bos_eos().

◆ add_eos

bool bool add_eos

Definition at line 243 of file tokenizer.h.

Referenced by ck_tokenizer_set_add_bos_eos().

◆ add_space_prefix

bool add_space_prefix

◆ bos

◆ eos

int32_t int32_t int32_t eos

◆ id

◆ ids

◆ lowercase

bool lowercase

Definition at line 269 of file tokenizer.h.

◆ mask

◆ num_ids

const int32_t int num_ids

Definition at line 445 of file tokenizer.h.

Referenced by ck_tokenizer_decode(), ck_true_bpe_decode(), and main().

◆ out_len

◆ pad

int32_t int32_t int32_t int32_t pad

Definition at line 233 of file tokenizer.h.

Referenced by ck_tokenizer_set_special_ids(), and ck_true_bpe_set_special_ids().

◆ score

◆ spm_mode

CKSpmMode spm_mode

Definition at line 261 of file tokenizer.h.

Referenced by ck_tokenizer_set_spm_mode().

◆ style

◆ text

◆ token

const char * token

Definition at line 307 of file tokenizer.h.

Referenced by attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract(), attention_output_index(), ck_attention_llama_regular_impl(), ck_attention_llama_regular_query(), ck_gemma4_prepare_bf16_range(), ck_gemma4_prepare_q5_range(), ck_model_decode(), ck_multimodal_mrope_positions_2d(), ck_tokenizer_add_token(), ck_tokenizer_add_token(), ck_tokenizer_decode(), ck_tokenizer_detect_space_prefix_style(), ck_tokenizer_encode_spm_impl(), ck_tokenizer_load(), ck_tokenizer_load_binary(), ck_tokenizer_load_binary_with_scores(), ck_tokenizer_lookup(), ck_tokenizer_lookup(), ck_tokenizer_lookup_exact(), ck_trie_insert(), ck_true_bpe_add_special_token(), ck_true_bpe_add_token(), ck_true_bpe_decode(), ck_true_bpe_detect_space_style(), ck_true_bpe_load_binary(), ck_true_bpe_lookup(), decode_bpe_token(), decode_bpe_token(), ds_mla_attention_f32_work(), ds_qkv_idx(), eos_is_potential_prefix(), eos_is_potential_prefix(), is_eos_token(), is_eos_token(), lookup_token_exact(), main(), model_decode(), model_decode_token(), model_decode_token(), model_decode_token(), model_decode_token(), output_token(), output_token(), qwen2_0_5b_decode_decode(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen4_ple_ngram_embed_impl(), qwen4_qsa_index_select_bf16(), rope_forward_qk_pairwise_llama_cpu(), run_benchmark(), run_benchmark(), run_generation_test(), run_generation_test(), run_inference(), run_inference(), run_inference(), spm_build_byte_lookup(), spm_token_is_byte_format(), token_has_gpt2_bytes(), topology_discover_numa(), and yarn_rope_cache_explicit_positions_impl().

◆ unk

int32_t unk

Definition at line 230 of file tokenizer.h.

Referenced by ck_tokenizer_set_special_ids(), and ck_true_bpe_set_special_ids().

◆ use_trie

bool use_trie

Definition at line 277 of file tokenizer.h.

Referenced by ck_tokenizer_set_use_trie().