09a1c98514
- pocket_server.py (Produktions-TTS mit Stimmen-Waechter), text_norm, Bench-/Diag-Skripte - lucy-f5: f5_server/f5_test/bench_dml (DirectML-Experiment, Phase C/D offen) - .gitignore: venvs/Modelle/Audio/Logs der beiden Ordner + box_recon/gemma_swap-Scratch Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
48 lines
2.8 KiB
Python
48 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""ABSCHLUSS-TEST: beweist die Prompt-Wirkung. Dieselbe Lucy-Antwort im NEUEN Stil (kurze Sätze,
|
|
Punkte) vs. ALTEM Stil (Komma-Kette). Rendert auf :8134 + Desktop, misst Pausen (Whisper)."""
|
|
import os, io, json, urllib.request
|
|
import numpy as np, soundfile as sf
|
|
from faster_whisper import WhisperModel
|
|
|
|
SERVER = "http://127.0.0.1:8134/tts"
|
|
OUT = os.path.join(os.path.expanduser("~"), "Desktop", "lucy_test"); os.makedirs(OUT, exist_ok=True)
|
|
|
|
# Gleicher Inhalt, zwei Stile — so würde Lucy VORHER (Komma-Kette) und NACHHER (Prompt: kurze Sätze) antworten.
|
|
PAIRS = [
|
|
("A_backup",
|
|
"Klar, Commander, das Backup ist heute Nacht durchgelaufen, es gab keine Fehler, und die Datenbank läuft stabil bei 92 Prozent.",
|
|
"Klar, Commander. Das Backup lief heute Nacht durch. Keine Fehler. Die Datenbank ist stabil bei 92 Prozent."),
|
|
("B_status",
|
|
"Also, wenn ich das kurz zusammenfasse, die Verbindung war weg, dann lief das Update durch, danach musste ich neu starten, und jetzt sind alle Dienste wieder oben.",
|
|
"Kurz zusammengefasst, Commander. Die Verbindung war weg. Das Update lief durch. Ich musste neu starten. Jetzt sind alle Dienste wieder oben."),
|
|
]
|
|
|
|
def render(text):
|
|
req = urllib.request.Request(SERVER, data=json.dumps({"text": text}).encode("utf-8"),
|
|
headers={"Content-Type": "application/json"})
|
|
return urllib.request.urlopen(req, timeout=180).read()
|
|
|
|
w = WhisperModel("small", device="cpu", compute_type="int8")
|
|
|
|
def measure(tag, text):
|
|
wav = render(text); path = os.path.join(OUT, tag + ".wav"); open(path, "wb").write(wav)
|
|
a, sr = sf.read(io.BytesIO(wav)); a = np.asarray(a, dtype=np.float32).reshape(-1); dur = len(a)/sr
|
|
segs, _ = w.transcribe(path, language="de", beam_size=5, word_timestamps=True)
|
|
words = [x for s in segs for x in (s.words or [])]
|
|
gaps = [words[i+1].start - words[i].end for i in range(len(words)-1)]
|
|
lang = [(words[i].word.strip(), gaps[i]) for i in range(len(gaps)) if gaps[i] >= 0.30]
|
|
total_pause = sum(g for g in gaps if g >= 0.15)
|
|
return dur, len(lang), total_pause, lang
|
|
|
|
for name, alt, neu in PAIRS:
|
|
d_a, n_a, tp_a, l_a = measure(f"{name}_ALT_komma", alt)
|
|
d_n, n_n, tp_n, l_n = measure(f"{name}_NEU_kurz", neu)
|
|
print(f"\n### {name}")
|
|
print(f" ALT (Komma-Kette): {d_a:4.1f}s | {n_a} LANG-Pausen | Summe Pausen {tp_a*1000:4.0f}ms")
|
|
print(f" LANG: " + (", ".join(f'„{ww}\"={gg*1000:.0f}ms' for ww, gg in l_a) or "keine"))
|
|
print(f" NEU (kurze Sätze): {d_n:4.1f}s | {n_n} LANG-Pausen | Summe Pausen {tp_n*1000:4.0f}ms")
|
|
print(f" LANG: " + (", ".join(f'„{ww}\"={gg*1000:.0f}ms' for ww, gg in l_n) or "keine"))
|
|
print(f" -> {d_a-d_n:+.1f}s Dauer, {tp_a*1000-tp_n*1000:+.0f}ms Pausen-Summe")
|
|
print("\n=== ABSCHLUSS-TEST FERTIG === (WAVs im Desktop\\lucy_test)")
|