Kazeia-engine/dist/jni/cp_inference.h

45 lines
1.8 KiB
C++

// Code Predictor (Qwen3-TTS) inference, extrait de
// /opt/Kazeia/kazeia-tts-decoder-ggml/src/cp_runner.cpp et exposé en API
// utilisable depuis tts_orchestrate. Architecture : transformer qwen3 5 couches,
// hidden 1024, GQA 16/8, head_dim 128, RMS eps 1e-6, RoPE NEOX theta=1e6.
// q_norm/k_norm AVANT RoPE (gotcha critique).
//
// Forward autoregressif RVQ : 15 passes pour produire CB1..CB15 depuis
// (hidden_Talker[1024], cb0_emb[1024]). Approche "recompute" (T<=16 -> coût
// quadratique négligeable, pas de KV cache manuel).
#pragma once
#include "sampler.h"
#include <cstdint>
#include <string>
#include <vector>
#include <unordered_map>
struct ggml_context;
struct ggml_tensor;
struct CPState {
ggml_context * weights_ctx = nullptr;
std::unordered_map<std::string, ggml_tensor*> tensors; // weights par nom
std::vector<float> heads; // [15, 2048, 1024] f32
std::vector<float> codec_embs; // [15, 2048, 1024] f32
int n_threads = 4;
// Sampler HF-style (rep_penalty + top_k + top_p + temperature). Par défaut = greedy
// (top_k=1 -> argmax). Pour TTS prod, configurer en {temp=0.9, top_k=50, rep_penalty=1.05}
// ce qui matche Python subtalker_*.
Sampler sampler = { /*temp=*/0.0f, /*top_k=*/1, /*top_p=*/1.0f, /*rep_penalty=*/1.0f,
/*rep_window=*/16, /*rng_state=*/1u, {} };
};
// Charge cp_f16.gguf + cp_heads.bin + cp_codec_embs.bin. Retourne false en cas d'échec.
bool cp_load(CPState& s, const char* gguf_path, const char* heads_path, const char* embs_path);
// Libère les ressources.
void cp_free(CPState& s);
// Prédit CB1..CB15 (15 codes int32) depuis le hidden state du Talker et l'embed de CB0.
// hidden : float[1024]
// cb0_emb: float[1024]
// out_codes : int32_t[15] (CB1..CB15)
void cp_predict(CPState& s, const float* hidden, const float* cb0_emb, int32_t* out_codes);