JARVIS/nucleo/saber/enriquece/correr_noche.sh
sito 8e4bc8ad94 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.
2026-08-16 15:34:37 +02:00

92 lines
5 KiB
Bash
Executable file

#!/usr/bin/env bash
# El pipeline de la noche: mejora el RAG hasta nivel pentesting profesional.
#
# ./correr_noche.sh corre las cuatro fases y decide
# ./correr_noche.sh --sin-promo igual, pero NO sustituye el indice vivo
#
# ── Que hace, en orden ─────────────────────────────────────────────────────
#
# 1. COSECHA rescata la metodologia de COFRE que el indexador se dejaba
# (el OSCP_Vault entero, 0 de 72 notas estaban en el indice).
# 2. SINTETIZA por cada fragmento, preguntas en castellano que lo encuentran.
# Es la fase larga: horas, con el modelo local. Reanudable.
# 3. REINDEXA une vivo + cosecha + sintesis y calcula los vectores. Escribe
# a saber.jsonl.nuevo. NO toca el indice vivo.
# 4. EVALUA mide recuperacion del vivo contra el candidato, con numeros.
#
# ── No rompe nada ──────────────────────────────────────────────────────────
#
# El indice vivo solo se sustituye si evalua DICE que el candidato es mejor, y
# antes se guarda una copia con fecha. Si el candidato empeora, se queda el
# vivo y el candidato espera revision. Reversible siempre.
#
# Cada fase se salta si ya esta hecha, asi que relanzarlo continua donde iba.
set -uo pipefail
AQUI=$(cd -P "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)
RAIZ=$(cd -P "$AQUI/../.." && pwd) # .../nucleo
DATOS="$RAIZ/datos"
PY="$RAIZ/venv/bin/python"
[ -x "$PY" ] || PY=python3
LOG="$DATOS/noche_rag.log"
# El modelo NO se fija aqui a proposito: sintetiza.py mira que tiene ollama
# cargado y usa ESE, para no forzar cambios en la tarjeta de 4 GB. Si el verde
# esta abierto, generara con el verde; si no, cae al naranja. Solo se fuerza si
# exportas JARVIS_MODELO tu. Aun asi, para la noche mas rapida y limpia, lo
# suyo es cerrar el TUI verde: con un solo modelo ollama no recarga nada.
PROMO=si
[ "${1:-}" = "--sin-promo" ] && PROMO=no
fecha() { date '+%Y-%m-%d %H:%M:%S'; }
fase() { echo "" | tee -a "$LOG"; echo "[$(fecha)] === FASE $* ===" | tee -a "$LOG"; }
echo "[$(fecha)] arranca el pipeline de la noche (modelo $JARVIS_MODELO)" | tee -a "$LOG"
# ── 1. COSECHA ─────────────────────────────────────────────────────────────
fase "1/4 COSECHA"
if [ -s "$DATOS/cosecha.jsonl" ]; then
echo " ya hecha ($(wc -l <"$DATOS/cosecha.jsonl") fragmentos), se salta" | tee -a "$LOG"
else
"$PY" "$AQUI/cosecha.py" 2>&1 | tee -a "$LOG"
fi
# ── 2. SINTETIZA (la larga) ────────────────────────────────────────────────
fase "2/4 SINTETIZA (horas; reanudable)"
# hecha del todo = el .hecho llego al ultimo fragmento
TOTAL=$(wc -l <"$DATOS/cosecha.jsonl")
HECHO=$(cat "$DATOS/sintesis.jsonl.hecho" 2>/dev/null || echo -1)
if [ "$HECHO" -ge "$((TOTAL - 1))" ] 2>/dev/null; then
echo " ya completa ($(wc -l <"$DATOS/sintesis.jsonl" 2>/dev/null || echo 0) preguntas)" | tee -a "$LOG"
else
"$PY" "$AQUI/sintetiza.py" 2>&1 | tee -a "$LOG"
fi
# ── 3. REINDEXA ────────────────────────────────────────────────────────────
fase "3/4 REINDEXA"
"$PY" "$AQUI/reindexa.py" 2>&1 | tee -a "$LOG"
# ── 4. EVALUA ──────────────────────────────────────────────────────────────
fase "4/4 EVALUA"
INFORME="$DATOS/informe_rag.txt"
"$PY" "$AQUI/evalua.py" 2>&1 | tee "$INFORME" | tee -a "$LOG"
VEREDICTO=$(grep -oE 'VEREDICTO (PROMOCIONAR|MANTENER)' "$INFORME" | awk '{print $2}' | tail -1)
# ── Decision ───────────────────────────────────────────────────────────────
fase "DECISION"
if [ "$PROMO" = no ]; then
echo " --sin-promo: dejo el candidato en saber.jsonl.nuevo sin tocar el vivo" | tee -a "$LOG"
elif [ "$VEREDICTO" = PROMOCIONAR ]; then
COPIA="$DATOS/saber.jsonl.antes-$(date +%Y%m%d-%H%M)"
cp "$DATOS/saber.jsonl" "$COPIA"
mv "$DATOS/saber.jsonl.nuevo" "$DATOS/saber.jsonl"
echo " PROMOCIONADO. El candidato es mejor y ya es el indice vivo." | tee -a "$LOG"
echo " copia del anterior: $COPIA" | tee -a "$LOG"
echo " para deshacer: cp '$COPIA' '$DATOS/saber.jsonl'" | tee -a "$LOG"
else
echo " MANTENIDO el vivo: el candidato no mejora la evaluacion." | tee -a "$LOG"
echo " candidato en saber.jsonl.nuevo e informe en informe_rag.txt para revisar." | tee -a "$LOG"
fi
echo "[$(fecha)] pipeline terminado" | tee -a "$LOG"