JARVIS: asistente de voz local para Linux
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.
This commit is contained in:
commit
8e4bc8ad94
125 changed files with 25033 additions and 0 deletions
60
config/set_ruido.py
Normal file
60
config/set_ruido.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Endurece la escucha para que no se dispare con ruido de fuera.
|
||||
|
||||
flatpak run --command=python3 io.github.qwersyk.Newelle//master \
|
||||
~/COFRE/CODERS/JARVIS/config/set_ruido.py [--suave]
|
||||
|
||||
NO es reconocimiento de hablante: Newelle no distingue quien habla, no hay
|
||||
nada de eso en el codigo. Esto solo sube el liston de que se considera voz.
|
||||
Para que responda unicamente a una persona haria falta un modelo de huella
|
||||
vocal (ECAPA, Resemblyzer) delante del STT, que es otro proyecto.
|
||||
|
||||
Las tres capas, de menos a mas efectiva:
|
||||
|
||||
1. la palabra clave, que ya filtra casi todo
|
||||
2. estos umbrales
|
||||
3. supresion de ruido en PipeWire (RNNoise), antes de que el audio llegue
|
||||
a la app; esa vale para todo el sistema y no cuesta CPU a Newelle
|
||||
|
||||
Valores por defecto de Newelle: energia 300, VAD 1.
|
||||
"""
|
||||
import sys
|
||||
|
||||
from gi.repository import Gio
|
||||
|
||||
SCHEMA = "io.github.qwersyk.Newelle"
|
||||
|
||||
# vad-aggressiveness va de 0 a 3: cuanto descarta lo que no suena a voz.
|
||||
DURO = {
|
||||
"wakeword-energy-threshold": 800, # por debajo de esto ni escucha
|
||||
"wakeword-vad-aggressiveness": 3,
|
||||
}
|
||||
SUAVE = {
|
||||
"wakeword-energy-threshold": 500,
|
||||
"wakeword-vad-aggressiveness": 2,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
perfil = SUAVE if "--suave" in sys.argv else DURO
|
||||
settings = Gio.Settings.new(SCHEMA)
|
||||
|
||||
print("antes:")
|
||||
for clave in perfil:
|
||||
print(f" {clave} = {settings.get_int(clave)}")
|
||||
|
||||
for clave, valor in perfil.items():
|
||||
settings.set_int(clave, valor)
|
||||
Gio.Settings.sync()
|
||||
|
||||
print("despues:")
|
||||
for clave in perfil:
|
||||
print(f" {clave} = {settings.get_int(clave)}")
|
||||
|
||||
ok = all(settings.get_int(c) == v for c, v in perfil.items())
|
||||
print("verificado" if ok else "FALLO: no quedo como se pidio")
|
||||
return 0 if ok else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue