// 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 #include #include 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 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 kz_tok_encode_tts_prompt(const KzTextTokenizer & t, const std::string & content);