diff --git a/kazeia-android/app/src/main/java/com/kazeia/core/PipelineMetrics.kt b/kazeia-android/app/src/main/java/com/kazeia/core/PipelineMetrics.kt index 6eb6bbf..fa1eb6b 100644 --- a/kazeia-android/app/src/main/java/com/kazeia/core/PipelineMetrics.kt +++ b/kazeia-android/app/src/main/java/com/kazeia/core/PipelineMetrics.kt @@ -141,26 +141,24 @@ class PipelineMetrics(val tag: String = "Pipeline") { // Bloc temps par étape (ne liste que les étapes réellement mesurées). // Construit une fois, envoyé aux DEUX puits : summarySink (flot de logs) et // timingsSink (encart persistant qui ne défile pas). - // DEUX BLOCS additifs : TRAITEMENT (latence avant le 1er son, ce qui compte - // pour la perf) + LECTURE (durée de la voix, dépend de la longueur du texte). - // Traitement + Lecture == TOTAL (exact). Le TTFT est un REPÈRE inclus dans - // Speaker, pas un poste à additionner. + // GÉNÉRATION seule : on ne compte que le temps pour PRODUIRE la réponse + // (STT · Thinker · Speaker · TTS jusqu'au 1er son). La durée de LECTURE + // audio est exclue (ce n'est pas de la génération, elle dépend de la + // longueur du texte). Les lignes s'additionnent exactement au TOTAL gén. + // Le TTFT est un REPÈRE inclus dans Speaker, pas un poste à additionner. run { - val b = StringBuilder("⏱─── TEMPS DU TOUR ($status) ───\n") + val b = StringBuilder("⏱─── GÉNÉRATION ($status) ───\n") fun row(name: String, value: String) { b.append(" ${name.padEnd(11)} $value\n") } - // first_audio = frontière traitement / lecture ; à défaut (pas de TTS, - // ex. mode texte) tout est « traitement ». - val processingMs = firstAudio ?: total - val readingMs = (total - processingMs).coerceAtLeast(0) - b.append(" TRAITEMENT (avant le 1er son) : $processingMs ms\n") - if (sttDur != null) row("· STT", "$sttDur ms") - if (thinkerDur != null) row("· Thinker", "$thinkerDur ms") - if (speakerGen != null) row("· Speaker", "$speakerGen ms" + - (speakerTtft?.let { " (dont 1er token $it)" } ?: "")) - if (ttsSynth != null) row("· TTS→son", "$ttsSynth ms") - if (firstAudio != null) b.append(" LECTURE (durée parlée) : $readingMs ms\n") - b.append(" ─────────────────────────────\n") - b.append(" TOTAL : $total ms") + var gen = 0L + if (sttDur != null) { row("STT", "$sttDur ms"); gen += sttDur } + if (thinkerDur != null) { row("Thinker", "$thinkerDur ms"); gen += thinkerDur } + if (speakerGen != null) { + row("Speaker", "$speakerGen ms" + (speakerTtft?.let { " (dont 1er token $it)" } ?: "")) + gen += speakerGen + } + if (ttsSynth != null) { row("TTS→son", "$ttsSynth ms"); gen += ttsSynth } + b.append(" ──────────\n") + b.append(" ${"TOTAL gén.".padEnd(11)} $gen ms") val block = b.toString() runCatching { timingsSink?.invoke(block) } summarySink?.let { sink -> block.lineSequence().forEach { runCatching { sink(it) } } }