aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/extra/qwentts.cpp/examples/server-test.sh
diff options
context:
space:
mode:
authorelvis <elvis@claros.ar>2026-09-06 19:21:16 -0300
committerelvis <elvis@claros.ar>2026-09-06 19:23:37 -0300
commitf8f98e83481e7376a235fb305a095552433f79ab (patch)
tree6d0ecddb26bef8430a086431de40f8ce9b1039e6 /vendor/extra/qwentts.cpp/examples/server-test.sh
downloadasist-p-f8f98e83481e7376a235fb305a095552433f79ab.tar.gz
asist-p-f8f98e83481e7376a235fb305a095552433f79ab.zip
Local voice assistant on top of Canary, llama.cpp and qwentts
Pipeline en Rust de hilos y canales que une los tres motores: el micrófono alimenta un segmentador con VAD, las intervenciones cerradas van al reconocedor, la transcripción al modelo y cada frase que este cierra sale hacia el sintetizador sin esperar al resto de la respuesta. Dos reglas sostienen el diseño: ninguna etapa bloquea a la anterior —quien va sobrado descarta trabajo en lugar de acumular retraso— y todo lo que viaja por los canales lleva el turno al que pertenece, así que interrumpir es subir el contador y levantar dos banderas de cancelación. Seis crates: core (configuración, eventos, HTTP, telemetría, herramientas), audio (cpal, VAD, anillo de reproducción), asr, llm, tts y app (supervisor de procesos y orquestador). Los motores van como submódulos fijados a un commit, con los cambios locales en vendor/patches. Midiendo el pipeline aparecieron tres cuellos de botella de configuración que valieron más que cualquier cambio de código, todos documentados en docs/RENDIMIENTO.md: - tts-server decodificaba el audio en bloques de 24 s, de modo que el modo «streaming» llegaba de una pieza: 4948 ms -> 585 ms hasta el primer audio. - La plantilla de chat del modelo abre <think> y no lo cierra nunca, sin variable que lo apague: 8630 ms -> 413 ms hasta el primer token, con una copia de la plantilla que deja el bloque cerrado de entrada. - Cualquier indicación de estilo junto a la guía de herramientas hace que este modelo de 2B deje de llamarlas y se invente el dato (8/8 aciertos con la guía sola, 0/8 con la persona de asistente de voz). El turno alterna ahora entre dos instrucciones de sistema. La ejecución de órdenes del sistema queda implementada y apagada, tras cuatro barreras: lista blanca sobre el ejecutable, rutas rechazadas, sin shell que interprete metacaracteres y plazo máximo. 68 pruebas unitarias sin modelos, más seis de integración que se saltan solas si no hay servidores y se turnan la GPU: en paralelo, los dos servidores no caben en 4 GB y miden contención en vez de latencia. Claude-Session: https://claude.ai/code/session_01FNxz5cSdQSscJH9H7b8uGU
Diffstat (limited to 'vendor/extra/qwentts.cpp/examples/server-test.sh')
-rwxr-xr-xvendor/extra/qwentts.cpp/examples/server-test.sh51
1 files changed, 51 insertions, 0 deletions
diff --git a/vendor/extra/qwentts.cpp/examples/server-test.sh b/vendor/extra/qwentts.cpp/examples/server-test.sh
new file mode 100755
index 0000000..7242afe
--- /dev/null
+++ b/vendor/extra/qwentts.cpp/examples/server-test.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+# Prueba de punta a punta del tts-server (API OpenAI-compatible).
+set -u
+cd "$(dirname "$0")"
+OUT=out; mkdir -p "$OUT"
+PORT=8080; H=127.0.0.1; B="http://$H:$PORT"
+
+echo "== arrancando tts-server (base 1.7B) =="
+../build/tts-server \
+ --model ../models/qwen-talker-1.7b-base-Q8_0.gguf \
+ --codec ../models/qwen-tokenizer-12hz-Q8_0.gguf \
+ --alias qwen3-tts-base --host $H --port $PORT --lang auto \
+ >"$OUT/server.log" 2>&1 &
+SRV=$!
+trap 'kill $SRV 2>/dev/null' EXIT
+
+echo -n "esperando readiness"
+for i in $(seq 1 60); do
+ curl -sf "$B/v1/models" >/dev/null 2>&1 && { echo " listo"; break; }
+ kill -0 $SRV 2>/dev/null || { echo " el server murio"; tail -20 "$OUT/server.log"; exit 1; }
+ printf '.'; sleep 1
+done
+
+echo "== 1) GET /v1/models =="
+curl -s "$B/v1/models"; echo
+
+echo "== 2) voz por defecto -> wav =="
+curl -s -X POST "$B/v1/audio/speech" -H "Content-Type: application/json" \
+ -d '{"input":"This is the default server voice.","response_format":"wav","seed":42}' \
+ -o "$OUT/srv_default.wav"
+echo " $(du -h "$OUT/srv_default.wav" | cut -f1) $OUT/srv_default.wav"
+
+echo "== 3) registrar voz clonada 'freeman' (spk+rvq b64) =="
+curl -s -X POST "$B/v1/audio/voices" -H "Content-Type: application/json" \
+ -d "{\"name\":\"freeman\",\"ref_text\":\"$(cat freeman.txt)\",
+ \"spk_b64\":\"$(base64 -w0 freeman.spk)\",\"rvq_b64\":\"$(base64 -w0 freeman.rvq)\"}"
+echo
+
+echo "== 4) sintesis con la voz clonada -> wav =="
+curl -s -X POST "$B/v1/audio/speech" -H "Content-Type: application/json" \
+ -d '{"input":"Now I am speaking with the cloned voice.","voice":"freeman","response_format":"wav","seed":42,"temperature":0.8}' \
+ -o "$OUT/srv_freeman.wav"
+echo " $(du -h "$OUT/srv_freeman.wav" | cut -f1) $OUT/srv_freeman.wav"
+
+echo "== 5) streaming PCM (s16le) -> archivo raw =="
+curl -s -X POST "$B/v1/audio/speech" -H "Content-Type: application/json" \
+ -d '{"input":"Streaming pcm chunks.","response_format":"pcm","seed":42}' \
+ -o "$OUT/srv_stream.pcm"
+echo " $(du -h "$OUT/srv_stream.pcm" | cut -f1) $OUT/srv_stream.pcm (s16le mono 24k)"
+
+echo "== ok, parando server =="