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.
92 lines
5 KiB
Bash
Executable file
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"
|