Nucleo propio: oye con whisper.cpp, piensa con un modelo de Ollama, habla con Piper, y hace RAG sobre los apuntes del usuario. 100% local, sin cuentas ni claves. Escrito bajo una restriccion dura, 4 GB de VRAM: el cerebro y whisper comparten tarjeta y solo caben porque estan dimensionados para ello. El RAG usa embeddings estaticos con busqueda hibrida; la voz clonada se sirve de una cache de frases. Incluye instalador (install.sh), requisitos, y documentacion del stack, del manejo de root y de las acciones. Los apuntes indexados y el diario NO se incluyen: son privados y el .gitignore los bloquea.
94 lines
3.4 KiB
Bash
Executable file
94 lines
3.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Le da ordenes a JARVIS en directo, para verlo trabajar en la pantalla.
|
|
#
|
|
# Cada orden se dice EN VOZ ALTA con la voz activa (para oir como suena de
|
|
# verdad, no en un banco de pruebas) y luego se ejecuta la accion que le
|
|
# corresponde, igual que haria el asistente al oirte.
|
|
#
|
|
# No se ejecuta nada destructivo ni nada con root: eso pasa por un dialogo que
|
|
# aprueba una persona, y aqui no hay persona delante del dialogo.
|
|
#
|
|
# ./demo_en_directo.sh las que salen por pantalla incluidas
|
|
# ./demo_en_directo.sh --mudo sin voz, solo resultados
|
|
set -uo pipefail
|
|
RAIZ=$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd)
|
|
MUDO=no; [ "${1:-}" = "--mudo" ] && MUDO=si
|
|
|
|
CATALOGO=$RAIZ/newelle/data/acciones/acciones.json
|
|
TMPWAV=$(mktemp --suffix=.wav)
|
|
trap 'rm -f "$TMPWAV"' EXIT
|
|
|
|
# La orden que se le diria, y la accion del catalogo que le toca.
|
|
# Se eligen las que se VEN o las que contestan algo concreto.
|
|
ORDENES=(
|
|
"cuanto espacio queda|disco_libre"
|
|
"cuanta memoria|memoria"
|
|
"que temperatura hay|temperatura"
|
|
"que procesos consumen mas|procesos_top"
|
|
"cual es mi ip|red_ip"
|
|
"cuanto lleva encendido|uptime"
|
|
"busca el fichero README|buscar_fichero|README.md"
|
|
"busca dentro JARVIS|grep_recursivo|JARVIS"
|
|
"hazme una captura|captura_pantalla"
|
|
"abre una terminal|terminal_abrir"
|
|
"que peliculas tengo|videos_listar"
|
|
"pon la pelicula screencast|pelicula_abrir|Screencast"
|
|
"abre la carpeta de jarvis|abrir_carpeta|$RAIZ"
|
|
)
|
|
|
|
dice() {
|
|
[ "$MUDO" = si ] && return 0
|
|
"$RAIZ/config/jarvis-voz.sh" "$TMPWAV" "$1" >/dev/null 2>&1 \
|
|
|| JARVIS_PIPER_VOZ=es_ES-davefx-medium "$RAIZ/config/jarvis-piper.sh" "$TMPWAV" "$1" >/dev/null 2>&1
|
|
[ -s "$TMPWAV" ] && { paplay "$TMPWAV" 2>/dev/null || aplay -q "$TMPWAV" 2>/dev/null; }
|
|
}
|
|
|
|
campo() { # campo <id_accion> <clave>
|
|
python3 -c "
|
|
import json,sys
|
|
d=json.load(open('$CATALOGO',encoding='utf-8'))
|
|
for a in d.get('acciones', d if isinstance(d,list) else []):
|
|
if a['id']==sys.argv[1]: print(a.get(sys.argv[2],'') or ''); break
|
|
" "$1" "$2"
|
|
}
|
|
|
|
for entrada in "${ORDENES[@]}"; do
|
|
IFS='|' read -r frase accion argumento <<< "$entrada"
|
|
comando=$(campo "$accion" comando)
|
|
acuse=$(campo "$accion" acuse)
|
|
respuesta=$(campo "$accion" respuesta)
|
|
|
|
if [ -z "$comando" ]; then
|
|
printf '\n ── "%s" → accion %s NO EXISTE en el catalogo\n' "$frase" "$accion"
|
|
continue
|
|
fi
|
|
|
|
printf '\n ── tu dices: "%s"\n' "$frase"
|
|
printf ' jarvis: %s\n' "${acuse:-...}"
|
|
dice "${acuse:-Un momento}"
|
|
|
|
# sustituir el argumento igual que hace el motor
|
|
real=${comando//\{argumento\}/$(printf '%q' "${argumento:-}")}
|
|
salida=$(timeout 30 bash -lc "$real" 2>&1 | head -6)
|
|
|
|
if [ -n "$salida" ]; then
|
|
printf ' resultado: %s\n' "$(echo "$salida" | head -1 | cut -c1-100)"
|
|
echo "$salida" | tail -n +2 | sed 's/^/ /' | cut -c1-100
|
|
else
|
|
printf ' resultado: (hecho, sin salida que enseñar)\n'
|
|
fi
|
|
|
|
# decir la respuesta con la plantilla, si la tiene y es corta
|
|
if [ -n "$respuesta" ] && [ -n "$salida" ]; then
|
|
ultima=$(echo "$salida" | tail -1)
|
|
hablado=${respuesta//\{ultima\}/$ultima}
|
|
hablado=${hablado//\{salida\}/$ultima}
|
|
case "$hablado" in
|
|
*"{"*) ;; # plantilla con campos que no sabemos
|
|
*) [ ${#hablado} -lt 160 ] && { printf ' jarvis: %s\n' "$hablado"; dice "$hablado"; };;
|
|
esac
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
printf '\n ── fin de la demostracion\n'
|