// 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 // // Build : copie dans dist/jni/, link avec libkazeia_engine.so dépendances. #include #include #include #include #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 \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 embd(T * n_embd); srand(42); for (auto& x : embd) x = (rand() / (float)RAND_MAX - 0.5f) * 0.01f; std::vector pos(T); std::vector nsd(T, 1); std::vector sid0(T, 0); std::vector sids(T); std::vector 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 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; }