119 lines
5.0 KiB
C++
119 lines
5.0 KiB
C++
// Smoke test : charge le Talker (qwen3 dense + M-RoPE) via le DENSE path engine,
|
|
// puis exerce les primitives embeds (prefillEmbeds/decodeEmbed) avec un input bidon.
|
|
//
|
|
// But : prouver que (a) Patch 2 active M-RoPE (log "mrope sections = [24,20,20,0]"),
|
|
// (b) Patch 1 fait tourner llama_decode embeds-only + ressort hidden state + logits.
|
|
// Pas de vérification de qualité ici — c'est le job du câblage CP+Decoder (Patch 3).
|
|
//
|
|
// Usage : ./test_talker <gguf>
|
|
//
|
|
// Build : copie dans dist/jni/, link avec libkazeia_engine.so dépendances.
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
#include <vector>
|
|
#include "llama.h"
|
|
#include "ggml-backend.h"
|
|
|
|
static ggml_backend_dev_t find_htp() {
|
|
for (size_t i = 0; i < ggml_backend_dev_count(); ++i) {
|
|
auto d = ggml_backend_dev_get(i);
|
|
if (!strcmp(ggml_backend_dev_name(d), "HTP0")) return d;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc < 2) { printf("usage: %s <gguf>\n", argv[0]); return 1; }
|
|
|
|
// dense path : HMX off (cf. kazeia_engine_jni)
|
|
setenv("GGML_HEXAGON_USE_HMX", "0", 1);
|
|
llama_backend_init();
|
|
|
|
auto mp = llama_model_default_params();
|
|
// 2e argument optionnel : "cpu" force le path CPU même si HTP dispo (utile pour itérer
|
|
// sans payer l'upload HTP de 1.66GB f32 à chaque smoke test).
|
|
const bool force_cpu = (argc >= 3 && !strcmp(argv[2], "cpu"));
|
|
ggml_backend_dev_t devs[2] = { force_cpu ? nullptr : find_htp(), nullptr };
|
|
if (devs[0]) { mp.n_gpu_layers = 99; mp.devices = devs; printf("HTP0 -> ngl=99\n"); }
|
|
else { mp.n_gpu_layers = 0; printf("CPU only%s\n", force_cpu ? " (force)" : " (pas de HTP)"); }
|
|
|
|
auto m = llama_model_load_from_file(argv[1], mp);
|
|
if (!m) { printf("model load FAILED\n"); return 1; }
|
|
printf("model loaded. n_embd=%d, n_vocab=%d\n",
|
|
llama_model_n_embd(m), llama_vocab_n_tokens(llama_model_get_vocab(m)));
|
|
|
|
auto cp = llama_context_default_params();
|
|
cp.n_ctx = 1024; cp.n_batch = 1024; cp.n_threads = 4;
|
|
cp.flash_attn_type = LLAMA_FLASH_ATTN_TYPE_ENABLED;
|
|
cp.embeddings = true; // équivaut à llama_set_embeddings(ctx, true)
|
|
|
|
auto ctx = llama_init_from_model(m, cp);
|
|
if (!ctx) { printf("ctx init FAILED\n"); return 1; }
|
|
|
|
const int n_embd = llama_model_n_embd(m);
|
|
const int n_vocab = llama_vocab_n_tokens(llama_model_get_vocab(m));
|
|
|
|
// --- prefill : 4 positions d'embeds aléatoires (juste pour valider le pipeline,
|
|
// PAS pour produire du français sensé) ---
|
|
const int T = 4;
|
|
std::vector<float> embd(T * n_embd);
|
|
srand(42);
|
|
for (auto& x : embd) x = (rand() / (float)RAND_MAX - 0.5f) * 0.01f;
|
|
|
|
std::vector<llama_pos> pos(T);
|
|
std::vector<int32_t> nsd(T, 1);
|
|
std::vector<llama_seq_id> sid0(T, 0);
|
|
std::vector<llama_seq_id*> sids(T);
|
|
std::vector<int8_t> lg(T, 0);
|
|
for (int i = 0; i < T; ++i) { pos[i] = i; sids[i] = &sid0[i]; }
|
|
lg[T-1] = 1;
|
|
|
|
llama_batch b{};
|
|
b.n_tokens = T; b.token = nullptr; b.embd = embd.data();
|
|
b.pos = pos.data(); b.n_seq_id = nsd.data(); b.seq_id = sids.data(); b.logits = lg.data();
|
|
|
|
if (llama_decode(ctx, b) != 0) { printf("prefill embeds FAILED\n"); return 1; }
|
|
printf("prefill OK (T=%d)\n", T);
|
|
|
|
const float* h_prefill = llama_get_embeddings_ith(ctx, -1);
|
|
if (!h_prefill) { printf("get_embeddings_ith FAILED\n"); return 1; }
|
|
float h_sum = 0, h_min = h_prefill[0], h_max = h_prefill[0];
|
|
for (int i = 0; i < n_embd; ++i) {
|
|
h_sum += h_prefill[i];
|
|
if (h_prefill[i] < h_min) h_min = h_prefill[i];
|
|
if (h_prefill[i] > h_max) h_max = h_prefill[i];
|
|
}
|
|
printf("hidden[prefill] : mean=%.6f min=%.6f max=%.6f\n", h_sum / n_embd, h_min, h_max);
|
|
|
|
const float* logits = llama_get_logits_ith(ctx, -1);
|
|
if (!logits) { printf("get_logits_ith FAILED\n"); return 1; }
|
|
int argmax = 0; float lmax = logits[0];
|
|
for (int i = 1; i < n_vocab; ++i) if (logits[i] > lmax) { lmax = logits[i]; argmax = i; }
|
|
printf("logits[prefill] : argmax=%d (val=%.3f)\n", argmax, lmax);
|
|
|
|
// --- decode step : un seul embed de plus ---
|
|
std::vector<float> embd1(n_embd);
|
|
for (auto& x : embd1) x = (rand() / (float)RAND_MAX - 0.5f) * 0.01f;
|
|
|
|
llama_pos p1 = T;
|
|
int32_t n1 = 1;
|
|
llama_seq_id s1 = 0; llama_seq_id* sp1 = &s1;
|
|
int8_t l1 = 1;
|
|
llama_batch b1{};
|
|
b1.n_tokens = 1; b1.token = nullptr; b1.embd = embd1.data();
|
|
b1.pos = &p1; b1.n_seq_id = &n1; b1.seq_id = &sp1; b1.logits = &l1;
|
|
|
|
if (llama_decode(ctx, b1) != 0) { printf("decode embeds FAILED\n"); return 1; }
|
|
const float* h_step = llama_get_embeddings_ith(ctx, -1);
|
|
const float* l_step = llama_get_logits_ith(ctx, -1);
|
|
int argmax_s = 0; float lmax_s = l_step[0];
|
|
for (int i = 1; i < n_vocab; ++i) if (l_step[i] > lmax_s) { lmax_s = l_step[i]; argmax_s = i; }
|
|
printf("step OK : argmax=%d (val=%.3f), hidden[0..2]=%.4f %.4f %.4f\n",
|
|
argmax_s, lmax_s, h_step[0], h_step[1], h_step[2]);
|
|
|
|
llama_free(ctx);
|
|
llama_model_free(m);
|
|
return 0;
|
|
}
|