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.
81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Pone el cerebro en Ollama sobre GPU y mata el razonamiento.
|
|
|
|
Se ejecuta DENTRO del flatpak, con la app CERRADA (si no, al salir puede
|
|
reescribir los ajustes con lo que tenia en memoria):
|
|
|
|
flatpak run --command=python3 io.github.qwersyk.Newelle//master \
|
|
~/COFRE/CODERS/JARVIS/config/set_backend.py
|
|
|
|
Por que Ollama y no el llamacpp interno: el llama.cpp que empaqueta el
|
|
flatpak es el prebuilt de CPU, sin CUDA, asi que el modelo corria entero
|
|
en procesador. Ollama ya esta en GPU. Los dos son locales igual.
|
|
|
|
Medido el 10 ago 2026 con qwen3.5:4b, misma pregunta:
|
|
|
|
think=true 41.2 s 749 tokens (casi todos de monologo interno)
|
|
think=false 2.5 s 44 tokens
|
|
|
|
De paso deja sana la ruta de llamacpp por si se vuelve a ella: el mismo
|
|
razonamiento se apaga alli con --reasoning-budget 0, y el contexto por
|
|
defecto (0 = el del modelo) abria 262144 por slot, unos 10 GB de RAM.
|
|
"""
|
|
import json
|
|
import sys
|
|
|
|
from gi.repository import Gio
|
|
|
|
SCHEMA = "io.github.qwersyk.Newelle"
|
|
MODELO = "qwen3.5:4b"
|
|
|
|
AJUSTES_OLLAMA = {
|
|
"endpoint": "http://localhost:11434",
|
|
"model": MODELO,
|
|
"custom_model": False,
|
|
"thinking": False, # lo que baja de 41 s a 2.5 s
|
|
"native_tool_calling": True,
|
|
"serve": False, # el servicio del sistema ya esta levantado
|
|
}
|
|
|
|
AJUSTES_LLAMACPP = {
|
|
"custom_args": "--reasoning-budget 0",
|
|
"ctx": 8192,
|
|
}
|
|
|
|
|
|
def main():
|
|
settings = Gio.Settings.new(SCHEMA)
|
|
|
|
try:
|
|
llm = json.loads(settings.get_string("llm-settings") or "{}")
|
|
except json.JSONDecodeError:
|
|
llm = {}
|
|
|
|
# merge, no reemplazo: ahi viven los ajustes de todos los proveedores
|
|
llm.setdefault("ollama", {}).update(AJUSTES_OLLAMA)
|
|
llm.setdefault("llamacpp", {}).update(AJUSTES_LLAMACPP)
|
|
|
|
settings.set_string("llm-settings", json.dumps(llm))
|
|
settings.set_string("language-model", "ollama")
|
|
Gio.Settings.sync()
|
|
|
|
# releer de gsettings, no fiarse de lo que acabamos de escribir
|
|
guardado = json.loads(settings.get_string("llm-settings"))
|
|
motor = settings.get_string("language-model")
|
|
ollama = guardado.get("ollama", {})
|
|
|
|
print(f"language-model: {motor}")
|
|
print(f"modelo: {ollama.get('model')}")
|
|
print(f"thinking: {ollama.get('thinking')}")
|
|
print(f"llamacpp: {guardado.get('llamacpp', {}).get('custom_args')} "
|
|
f"· ctx {guardado.get('llamacpp', {}).get('ctx')}")
|
|
|
|
ok = (motor == "ollama"
|
|
and ollama.get("model") == MODELO
|
|
and ollama.get("thinking") is False)
|
|
print("verificado" if ok else "FALLO: no quedo como se pidio")
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|