Rama JARVIS-GREEN, independiente de master (el nucleo naranja queda intacto). - README propio del carril verde con diagrama de arquitectura y capturas del panel. - verde/: arranque, panel web, puente de voz (escucha local con faster-whisper + habla con la voz del naranja), pruebas (07 voz, 08 escucha), config y notas. - Integracion RAG: nucleo/saber/busca_cli.py + skill buscar-en-apuntes, para que el agente consulte el mismo indice que el nucleo. - Todo local (127.0.0.1); sin datos personales (rutas y modelo de GPU scrubeados).
73 lines
3.1 KiB
Bash
Executable file
73 lines
3.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Que el verde ESCUCHE, y en local. El complemento del 07 (que hable).
|
|
#
|
|
# El TUI de Hermes no tiene microfono, y su STT nativo es para notas de voz de
|
|
# mensajeria —que saldrian de la maquina—. El puente escucha-verde.sh cierra el
|
|
# hueco con faster-whisper local (el mismo 'small' en espanol que ya declara la
|
|
# seccion stt: del config.yaml), en CPU para no pelear por la VRAM con el 4B.
|
|
#
|
|
# La prueba no necesita microfono: hace un BUCLE. Genera voz con el mismo TTS del
|
|
# verde (voz-verde.sh, 07), la transcribe con escucha_transcribe.py, y comprueba
|
|
# que el texto vuelve entero. Si el oido funciona, lo que entro por el altavoz
|
|
# sale por el transcriptor.
|
|
|
|
cd "$(dirname "$0")" && . ./comun.sh
|
|
|
|
PY=$RAIZ/nucleo/venv/bin/python
|
|
[ -x "$PY" ] || PY=$(command -v python3)
|
|
TRANS=$VERDE/escucha_transcribe.py
|
|
|
|
titulo "Las piezas"
|
|
|
|
afirma "existe escucha_transcribe.py" test -f "$TRANS"
|
|
afirma "existe el puente escucha-verde.sh" test -x "$VERDE/escucha-verde.sh"
|
|
afirma "faster-whisper importa" "$PY" -c "import faster_whisper"
|
|
afirma "el TTS del verde existe (para el bucle)" test -x "$VERDE/voz-verde.sh"
|
|
|
|
# quita acentos y baja a minusculas, para comparar sin depender de la tilde
|
|
_norm() { "$PY" -c "import sys,unicodedata as u; t=u.normalize('NFD',sys.stdin.read().lower()); print(''.join(c for c in t if u.category(c)!='Mn'))"; }
|
|
|
|
titulo "El bucle voz -> texto"
|
|
|
|
# (frase dicha, palabras clave que TIENEN que volver). Se evita 'jarvis' a
|
|
# proposito: es un nombre raro y whisper lo oye 'harvis'; eso no mide el oido.
|
|
probar_frase() {
|
|
local frase=$1 claves=$2
|
|
local wav=$TMP/oir.wav txt=$TMP/oir.txt
|
|
printf '%s' "$frase" > "$txt"
|
|
rm -f "$wav"
|
|
"$VERDE/voz-verde.sh" "$wav" "$txt" >/dev/null 2>&1
|
|
if [ ! -s "$wav" ]; then
|
|
echo " $(rojo FALLO) no se genero el WAV para: $frase"; _fallo=$((_fallo+1)); return
|
|
fi
|
|
local ini out norm falta=""
|
|
ini=$(date +%s.%N)
|
|
out=$(timeout 120 "$PY" "$TRANS" "$wav" 2>/dev/null)
|
|
local tardo; tardo=$(awk "BEGIN{printf \"%.1f\", $(date +%s.%N) - $ini}")
|
|
norm=$(printf '%s' "$out" | _norm)
|
|
local c
|
|
for c in $claves; do
|
|
printf '%s' "$norm" | grep -q "$c" || falta="$falta $c"
|
|
done
|
|
if [ -z "$falta" ]; then
|
|
printf ' %s escucho: "%s" (%ss)\n' "$(verde OK)" "$out" "$tardo"; _ok=$((_ok+1))
|
|
else
|
|
printf ' %s faltan [%s] en: "%s"\n' "$(rojo FALLO)" "$falta" "$out"; _fallo=$((_fallo+1))
|
|
fi
|
|
}
|
|
|
|
probar_frase "cuanto espacio libre queda en el disco" "espacio disco"
|
|
probar_frase "abre el navegador y busca el tiempo en madrid" "navegador tiempo madrid"
|
|
probar_frase "apaga las luces del salon a las diez" "luces salon"
|
|
|
|
titulo "Local de verdad"
|
|
|
|
# El transcriptor no debe abrir ningun socket a la nube: se comprueba que el
|
|
# codigo no importa clientes de APIs de STT de pago.
|
|
if grep -qiE "openai|groq|mistral|requests\.post|urllib.*http" "$TRANS"; then
|
|
echo " $(rojo FALLO) el transcriptor referencia una API remota"; _fallo=$((_fallo+1))
|
|
else
|
|
echo " $(verde OK) el transcriptor no llama a ninguna API remota"; _ok=$((_ok+1))
|
|
fi
|
|
|
|
resumen
|