Commit Graph

3 Commits

Author SHA1 Message Date
Richard Loyer 970f731e01 chantier B STT #3 : decoder zero-copy + sanity vocab + checklist dev
Optim decoder identifiée après bench sur audio FR continu (39 tokens) :
le `std::vector<>::emplace_back(data)` à chaque step recopiait 12 MB de
self KV inutilement = 2.4 GB de bande passante mémoire sur le loop entier.

Refactor zero-copy :
 - Pré-allocation UNE FOIS des buffers persistants (self_k/v, mask, input_ids,
   position_ids) au début de transcribe()
 - Pré-création UNE FOIS des Ort::Value pointant sur ces buffers (les Ort::Value
   sont des "borrowing views" — ORT lit les buffers au Run())
 - Cache des indices k_self_out / v_self_out / logits_out (parsing 1 fois,
   pas N fois dans le loop)
 - Update self KV : memcpy direct depuis dec_outputs vers nos buffers persistants
   (qui sont déjà les inputs du step suivant)
 - mask_buf updaté à 1 fp16 par step (juste le slot R-to-L), pas 200

Bench zero-copy sur Snapdragon 8 Elite :
 - Decoder/token : 98 ms -> 36 ms (-63%)
 - Decoder total 39 tokens : 3831 ms -> 1390 ms (-64%)
 - RTF audio 10s FR continu : 0.42 -> 0.18 (mieux que prod 0.51)
 - RAM peak : 378 MB inchangée (zero-copy n'augmente pas la peak)

Sanity vérifié au runtime :
 - Logits decoder shape = 51865 elements (= constante VOCAB_SIZE OK,
   pas de buffer over-read sur argmax). Le vocab.json contient 50258 tokens
   texte, les 1607 manquants sont les tokens langue/timestamp non décodés.

Doc STT_INTEGRATION.md :
 - Chiffres perf à jour (RTF 0.18, decoder 36 ms/token)
 - Nouvelle section "Checklist d'intégration" (6 points à vérifier en premier
   côté app : System.loadLibrary, transcribe vs WhisperHybridEngine, null/edge,
   VAD drop-in, threading IO, cycle de vie release)
 - Roadmap optim future via Ort::IoBinding (gain estimé 30% sur decoder restant)
2026-05-31 22:26:40 +02:00
Richard Loyer 8f6253204c chantier B STT #2 : S2 + S3 livrés (stt_engine ORT QNN + JNI + façade Kotlin + doc)
S2 port complet WhisperHybridEngine.kt -> C++ :
 - stt_engine.cpp impl complète (ORT 1.24.3 + QNN EP HTP V79, decoder KV-cache
   autoregressif 200 steps, override translate->transcribe, parsers JSON inline
   pour mel_filters et vocab.json, tokenizer BPE byte-level GPT-2/Whisper)
 - kazeia_stt_cli : binaire test (1.3 MB statique)
 - Bench bit-correct vs prod : transcription FR identique sur 3 runs déterministes
   ("Elle mat est un casque de chantier connecté et modulable.")
 - Perf SM8750 : RTF 0.41-0.43 (vs prod 0.51), RAM peak 378 MB (vs 545 MB)
 - Mel C++ 60 ms (FFT) vs prod 189 ms (DFT). Decoder per-token 100 ms vs 23 ms
   prod (overhead memcpy KV; optim IO bindings ORT non-bloquant)

S3 JNI + façade + doc :
 - kazeia_stt_jni.cpp : 7 fonctions JNI exportées (nativeLoad/Transcribe/Free
   + nativeVadNew/Push/Reset/Free). Sortie pipe-séparée parseable côté Kotlin.
 - libkazeia_stt.so : 168 KB SHARED, prête pour jniLibs/arm64-v8a/
 - SttEngine.kt : façade Kotlin minimale (~100 l) parallèle à TtsEngine.kt
   (SttJni / SttEngine / SttVad / SttResult)
 - Suppression côté app : WhisperHybridEngine.kt (527L), MelExtractor.kt,
   VadStage.kt, mel_extractor.cpp, libmel_extractor.so (documentée)

Doc livrable dev :
 - STT_INTEGRATION.md (10 KB) : guide complet migration + perf + erreurs +
   bench rapide + roadmap optim
 - KAZEIA_ENGINE_OVERVIEW.md : vue globale moteur unifié (LLM + TTS + STT),
   architecture des libs, API Kotlin unifiée, empreinte cascade complète
 - CLAUDE.md : section "STT unifié engine (31/05)" + verdict A invalidé

Runtime ORT 1.24.3 + QNN libs : extraites cache Gradle Maven (cf README_ORT.md
+ README_QNN.md dans dist/lib/). Pas de tarball ext. Modèles whisper-small-sm8750
prod inchangés (545 MB QAIRT contexte conservé).
2026-05-31 22:15:58 +02:00
Richard Loyer 4b43d9e3d7 chantier B STT #1 : S1 unification engine (mel partagé + skeleton stt + VAD C++)
S1.1 mel extractor unifié (kazeia_mel.{h,cpp}) :
 - Paramétrable : window (sym/periodic), compression (log/log10), post-norm
   (none/whisper), FFT auto radix-2 (zero-pad N_FFT pas puissance de 2)
 - Configs pré-faites : config_qwen3_tts_speaker() + config_whisper()
 - speaker_encoder.cpp migré dessus : régression damien cos=0.9997 et bit-exact
   (max abs diff = 0) vs avant. E2E clonage in-process intact (RTF inchangé).

S1.2 audit ORT C++ :
 - libonnxruntime.so + headers C++ trouvés dans cache Gradle (AAR Maven
   onnxruntime-android-qnn:1.24.3). API_VERSION=24, QNN EP intégré.
 - headers/ copiés dans dist/include/onnxruntime/ (versionné, ~1 MB)
 - libonnxruntime.so copiée dans dist/lib/ (gitignore, 20 MB, README pour
   reproduire l'extraction).

S1.3 skeleton stt_engine :
 - stt_engine.{h,cpp} : API parallèle à tts_engine.h
   (SttEngineLoadCfg / SttTranscribeCfg / SttTranscribeResult)
 - VAD RMS C++ complet (port de VadStage.kt prod : frame=1600, seuil=150,
   3 frames speech, 8 frames silence)
 - stt_engine_load + stt_engine_transcribe : stubs err=-99 jusqu'au port ORT
   QNN en S2 (encoder NPU + decoder loop KV-cache + tokenizer BPE)
 - Binaire kazeia_stt_test (1.2 MB statique) valide mel Whisper [80,3000] +
   VAD sur audio FR 5s, plage de valeurs cohérente.

Reste S2 : port encoder/decoder NPU via Ort::Session + QNN EP, port tokenizer
BPE byte-level, override transcribe. Quand S2 done : S3 = JNI + façade Kotlin
+ suppression libmel_extractor.so / VadStage.kt / WhisperHybridEngine.kt.
2026-05-31 19:19:28 +02:00