@@ -519,6 +519,13 @@ struct llm_tokenizer_bpe : llm_tokenizer {
519519 " (?:'[sS]|'[tT]|'[rR][eE]|'[vV][eE]|'[mM]|'[lL][lL]|'[dD])|[^\\ r\\ n\\ p{L}\\ p{N}]?\\ p{L}+|\\ p{N}+| ?[^\\ s\\ p{L}\\ p{N}]+[\\ r\\ n]*|\\ s*[\\ r\\ n]+|\\ s+(?!\\ S)|\\ s+" ,
520520 };
521521 break ;
522+ case LLAMA_VOCAB_PRE_TYPE_WHITESPACE :
523+ // whitespace pre-tokenizer (jinaai/jina-embeddings-v2-base-zh)
524+ regex_exprs = {
525+ " \\ S+" ,
526+ };
527+ byte_encode = false ;
528+ break ;
522529 default :
523530 // default regex for BPE tokenization pre-processing
524531 regex_exprs = {
@@ -1671,6 +1678,35 @@ struct llm_tokenizer_hybriddna_session : llm_tokenizer_bpe_session {
16711678 const llama_vocab & vocab;
16721679};
16731680
1681+ struct llm_tokenizer_whitespace_session : llm_tokenizer_bpe_session {
1682+ llm_tokenizer_whitespace_session (const llama_vocab & vocab, const llm_tokenizer_bpe & tokenizer) : llm_tokenizer_bpe_session{vocab, tokenizer}, vocab{vocab} {}
1683+
1684+ void tokenize (const std::string & text, std::vector<llama_token> & output) override {
1685+ const bool lowercase = vocab.get_normalizer_lowercase ();
1686+
1687+ std::string segment;
1688+ auto flush = [&]() {
1689+ if (!segment.empty ()) {
1690+ llm_tokenizer_bpe_session::tokenize (segment, output);
1691+ segment.clear ();
1692+ }
1693+ };
1694+
1695+ for (uint32_t cpt : unicode_cpts_from_utf8 (text)) {
1696+ // drop whitespace
1697+ if (unicode_cpt_flags_from_cpt (cpt).is_whitespace ) {
1698+ flush ();
1699+ } else {
1700+ segment += unicode_cpt_to_utf8 (lowercase ? unicode_tolower (cpt) : cpt);
1701+ }
1702+ }
1703+ flush ();
1704+ }
1705+
1706+ private:
1707+ const llama_vocab & vocab;
1708+ };
1709+
16741710//
16751711// impl
16761712//
@@ -1751,6 +1787,7 @@ struct llama_vocab::impl {
17511787 bool remove_extra_whitespaces = false ;
17521788 bool escape_whitespaces = true ;
17531789 bool treat_whitespace_as_suffix = false ;
1790+ bool normalizer_lowercase = true ; // Lowercase normalizer (tokenizer.json)
17541791
17551792 std::unordered_map<std::string, llama_token> token_to_id;
17561793 std::vector<token_data> id_to_token;
@@ -1900,7 +1937,7 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
19001937 special_mask_id = 103 ;
19011938
19021939 add_sep = true ;
1903- } else if (tokenizer_model == " gpt2" || tokenizer_model == " hybriddna" ) {
1940+ } else if (tokenizer_model == " gpt2" || tokenizer_model == " hybriddna" || tokenizer_model == " whitespace " ) {
19041941 type = LLAMA_VOCAB_TYPE_BPE ;
19051942
19061943 // read bpe merges and populate bpe ranks
@@ -2119,6 +2156,9 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
21192156 tokenizer_pre == " roberta-bpe" ) {
21202157 pre_type = LLAMA_VOCAB_PRE_TYPE_GPT2 ;
21212158 add_sep = true ;
2159+ } else if (
2160+ tokenizer_pre == " whitespace" ) {
2161+ pre_type = LLAMA_VOCAB_PRE_TYPE_WHITESPACE ;
21222162 } else if (
21232163 tokenizer_pre == " refact" ) {
21242164 pre_type = LLAMA_VOCAB_PRE_TYPE_REFACT ;
@@ -2299,8 +2339,9 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
22992339 pre_type = LLAMA_VOCAB_PRE_TYPE_DEFAULT ;
23002340 }
23012341
2302- ml.get_key (LLM_KV_TOKENIZER_ADD_PREFIX , add_space_prefix, false );
2303- ml.get_key (LLM_KV_TOKENIZER_REMOVE_EXTRA_WS , remove_extra_whitespaces, false );
2342+ ml.get_key (LLM_KV_TOKENIZER_ADD_PREFIX , add_space_prefix, false );
2343+ ml.get_key (LLM_KV_TOKENIZER_REMOVE_EXTRA_WS , remove_extra_whitespaces, false );
2344+ ml.get_key (LLM_KV_TOKENIZER_NORMALIZER_LOWERCASE , normalizer_lowercase, false );
23042345 }
23052346
23062347 const int token_idx = gguf_find_key (ctx, kv (LLM_KV_TOKENIZER_LIST ).c_str ());
@@ -3264,6 +3305,8 @@ std::vector<llama_token> llama_vocab::impl::tokenize(
32643305 std::unique_ptr<llm_tokenizer_bpe_session> session;
32653306 if (vocab.get_tokenizer_model () == " hybriddna" ) {
32663307 session = std::make_unique<llm_tokenizer_hybriddna_session>(vocab, *tok_bpe);
3308+ } else if (vocab.get_tokenizer_model () == " whitespace" ) {
3309+ session = std::make_unique<llm_tokenizer_whitespace_session>(vocab, *tok_bpe);
32673310 } else {
32683311 session = std::make_unique<llm_tokenizer_bpe_session>(vocab, *tok_bpe);
32693312 }
@@ -3892,6 +3935,10 @@ bool llama_vocab::get_treat_whitespace_as_suffix() const {
38923935 return pimpl->treat_whitespace_as_suffix ;
38933936}
38943937
3938+ bool llama_vocab::get_normalizer_lowercase () const {
3939+ return pimpl->normalizer_lowercase ;
3940+ }
3941+
38953942int llama_vocab::max_token_len () const {
38963943 return pimpl->max_token_len ;
38973944}
0 commit comments