saber: lo instalado en la maquina y los docs de repos clonados entran al indice
instalado.py lee los .desktop y los paquetes para saber que hay en el equipo y para que sirve cada cosa. indexa.py lo engancha, y con el los docs markdown de las herramientas clonadas en CODERS. Las dos fuentes son personales: se quedan en el indice de la maquina y no entran en el publico. busca_cli.py expone el mismo motor que usa el cerebro (saber.busca) para consultar el indice desde la terminal, con --n y --json. reentrena_noche.sh encadena las fases del reentrenamiento largo y las deja corriendo horas; cada fase es reanudable por su cuenta. eval del indice vivo: hit@1 43/57 (75%), hit@5 55/57 (96%), sim 0.909.
This commit is contained in:
parent
b1f8118272
commit
7c5381eea7
7 changed files with 369 additions and 2 deletions
61
nucleo/saber/busca_cli.py
Executable file
61
nucleo/saber/busca_cli.py
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Busca en el indice del RAG desde la linea de comandos.
|
||||
|
||||
busca_cli.py "como saco una shell reversa"
|
||||
busca_cli.py --n 3 "gestor de contraseñas autoalojado"
|
||||
busca_cli.py --json "kerberoasting"
|
||||
|
||||
Es el mismo motor que usa el cerebro del naranja (saber.busca), expuesto para que
|
||||
lo llame cualquiera: un script, o un agente por su herramienta de terminal. Asi el
|
||||
carril verde (Hermes) puede consultar tus apuntes sin duplicar el RAG.
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
AQUI = os.path.dirname(os.path.abspath(__file__))
|
||||
NUCLEO = os.path.dirname(AQUI)
|
||||
if NUCLEO not in sys.path:
|
||||
sys.path.insert(0, NUCLEO)
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Busca en los apuntes indexados (RAG)")
|
||||
p.add_argument("consulta", nargs="+", help="lo que quieres buscar")
|
||||
p.add_argument("--n", type=int, default=5, help="cuantos resultados (def. 5)")
|
||||
p.add_argument("--json", action="store_true", help="salida JSON en vez de texto")
|
||||
a = p.parse_args()
|
||||
|
||||
from saber import busca
|
||||
if not busca.disponible():
|
||||
print("no hay indice: corre nucleo/saber/indexa.py", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
consulta = " ".join(a.consulta)
|
||||
res = busca.busca(consulta, cuantos=a.n)
|
||||
|
||||
if a.json:
|
||||
salida = [{"herramienta": r.get("herramienta"),
|
||||
"fuente": r.get("fuente") or r.get("perfil"),
|
||||
"fichero": r.get("fichero"),
|
||||
"texto": r.get("texto", "")[:600]} for r in res]
|
||||
print(json.dumps(salida, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
if not res:
|
||||
print("sin resultados")
|
||||
return 0
|
||||
for i, r in enumerate(res, 1):
|
||||
fuente = r.get("fuente") or r.get("perfil") or ""
|
||||
cabecera = f"{i}. {r.get('herramienta', '?')}"
|
||||
if fuente:
|
||||
cabecera += f" ({fuente})"
|
||||
print(cabecera)
|
||||
print(" " + r.get("texto", "").strip().replace("\n", "\n ")[:500])
|
||||
print()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue