Kazeia-engine/dist/jni/kazeia_text_tokenizer.h

44 lines
1.9 KiB
C++

// Tokenizer texte pour Qwen3-TTS, wrappé sur libllama.
//
// Plutôt que de porter le BPE Qwen3 (NFC + pre-tokenize regex unicode + byte-level
// + merges + ignore_merges) à la main en C++, on charge n'importe quelle GGUF Qwen3
// en `vocab_only=true` -> ~50 MB RAM au lieu des 2-4 GB de poids, et on appelle
// llama_tokenize(parse_special=true) qui gère tout, bit-exact contre HF.
//
// Tradeoff assumé : dépendance libllama (qu'on a déjà), 50 MB RAM en plus, vs
// quelques centaines de lignes risquées à porter et à maintenir.
//
// Pour le TTS, on a juste besoin d'envelopper le contenu dans le template chat
// Qwen3 attendu par le talker :
// <|im_start|>assistant\n{content}<|im_end|>\n<|im_start|>assistant\n
//
// (déduit du dump golden : 16 tokens [151644, 77091, 198, 81581, ..., 151645,
// 198, 151644, 77091, 198] pour "Bonjour je m'appelle Kazeia").
#pragma once
#include <cstdint>
#include <string>
#include <vector>
struct llama_model;
struct llama_vocab;
struct KzTextTokenizer {
llama_model * model = nullptr;
const llama_vocab * vocab = nullptr;
};
// Charge le vocab depuis un GGUF Qwen3 (vocab_only=true). Aucun poids n'est chargé.
// IMPORTANT : llama_backend_init() doit déjà avoir été appelé par l'appelant.
bool kz_tok_load(KzTextTokenizer & t, const char * gguf_path);
void kz_tok_free(KzTextTokenizer & t);
// Tokenize raw : parse_special=true pour reconnaître <|im_start|> etc. comme tokens.
std::vector<int32_t> kz_tok_encode(const KzTextTokenizer & t,
const std::string & text,
bool parse_special);
// Enveloppe `content` dans le template chat Qwen3-TTS et tokenize. Renvoie la séquence
// prête à être feed dans la construction prefill_embeds.
std::vector<int32_t> kz_tok_encode_tts_prompt(const KzTextTokenizer & t,
const std::string & content);