Integrar IA local en terminal (solo win11)


Buenas gente, resumen rápido, como estoy aprendiendo y la IA me ayuda, que mejor forma de aprender que tener una IA personal en la terminal que me vaya ayudando con alguna duda sin tener ni que salir de terminal, full vago, como soy yo, lo he echo lo mas ligero y sencillo posible por ende, es un poco cutre pero funcional y mejorable, si alguien tiene alguna idea para mejorar que me lo diga.

DEPENDENCIAS:
Esto es vital para que todo funcione, se instala en tu sistema de fondo ocupa poco espacio y son las herramientas de el programilla.

Empieza por lo mas fácil, abre una terminal y escribe: pip install requests

Ahora descarga e instala C++ 2019 https://learn.microsoft.com/es-es/c...-170#latest-supported-redistributable-version

y por ultimo y mas importante Python (yo he usado 3.14) https://www.python.org/ftp/python/3.14.0/python-3.14.0-amd64.exe


PASOS:
Entramos en https://huggingface.co/QuantFactory y descargamos el modelo que quieras (en mi caso, llama-3.2-1B.gguf) asegurate de que es un .gguf y no otra cosa.

Ahora mientras se te descarga necesitamos a el que va a hacer de interprete con el modelo (en mi caso el compilador llama.cpp) os doy el enlace de descarga pero teneis que escoger la versión para vuestro dispositivo (en mi caso windows x64) https://github.com/ggml-org/llama.cpp/releases.

Descomprime el .zip y no me tardes que esto es rápido, ahora mete tu estúpido modelo de lenguaje en la carpeta que has descomprimido (yo le cambio el nombre de llama.cpp... a llama.cpp porque me toc que el nombre sea largo).

Ya tienes el modelo en la carpeta de llama.cpp? ahora en la misma carpeta crea un documento de txt y llámalo iniciar.py y pegas el siguiente código:

Antes de nada, muy importante que cambies el nombre de el modelo.gguf en el código (linea 8) por el nombre.gguf exacto de vuestro modelo porque como ya digo,
esto tira desde uno de 500Mb hasta uno de 200Gb, y para terminar se ejecuta muy sencillo, abre la carpeta en la terminal (la que lo contiene todo tete) y usa el comando: python3 iniciar.py

Bienvenido a tu terminal interactiva!

Python:
#!/usr/***/env python3

import os
import subprocess
import requests
import time
import sys
import signal
import json

MODEL = "llama3.gguf"  # <------- ¡¡¡ nombre exacto de tu modelo !!!
HOST = "127.0.0.1"
PORT = 8080

SERVER_CMD = [
    "llama-server.exe",
    "-m", MODEL,
    "--port", str(PORT),
    "--ctx-size", "4096"
]

def start_server():
    print(f"🚀 Iniciando llama-server con modelo {MODEL}...")
    proc = subprocess.Popen(
        SERVER_CMD,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.STDOUT,
        creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
    )
    return proc

def wait_for_server():
    print("⏳ Esperando a que el servidor arranque...", end="", flush=True)
    for _ in range(30):
        try:
            r = requests.get(f"http://{HOST}:{PORT}/health")
            if r.ok:
                print(" ✅ Listo.\n")
                return True
        except:
            pass
        print(".", end="", flush=True)
        time.sleep(1)
    print("\n❌ No se pudo conectar al servidor.")
    return False

def query_model(prompt):
    try:
        response = requests.post(
            f"http://{HOST}:{PORT}/completion",
            json={
                "prompt": prompt,
                "n_predict": 256,
                "temperature": 0.7
            },
            timeout=120
        )
        data = response.json()
        text = data.get("content", data.get("text", ""))
        print(text.strip())
    except Exception as e:
        print(f"⚠️ Error consultando el modelo: {e}")

def is_command_not_found(stderr_output: str):
    """Detecta si PowerShell devolvió un error por comando inexistente"""
    return "CommandNotFoundException" in stderr_output or "no se reconoce como" in stderr_output

def main():
    server = start_server()
    try:
        if not wait_for_server():
            server.terminate()
            sys.exit(1)

        print("💬 Terminal integrada lista.")
        print(" - Escribe texto para hablar con el modelo.")
        print(" - Usa comandos del sistema (dir, cd, cls, etc.) para ejecutarlos.")
        print(" - Escribe 'exit' para salir.\n")

        while True:
            prompt = f"PS {os.getcwd()}> "
            user_input = input(prompt).strip()

            if not user_input:
                continue
            if user_input.lower() in ("exit", "salir", "quit"):
                print("👋 Cerrando...")
                break

            if user_input.startswith("cd "):
                try:
                    os.chdir(user_input[3:].strip('" '))
                except FileNotFoundError:
                    print("⚠️ Carpeta no encontrada.")
                continue
            elif user_input in ("cls", "clear"):
                os.system("cls")
                continue

            result = subprocess.run(
                ["powershell", "-Command", user_input],
                capture_output=True,
                text=True
            )

            if result.returncode == 0 and result.stdout.strip():
                print(result.stdout.strip())
                continue
            elif is_command_not_found(result.stderr):
                # No es comando válido → texto para el modelo
                query_model(user_input)
            elif result.stderr.strip():
                print(result.stderr.strip())
            else:
                # No hay salida → mandarlo al modelo también
                query_model(user_input)

    except KeyboardInterrupt:
        print("\n🛑 Interrumpido por el usuario.")
    finally:
        print("🧹 Cerrando servidor...")
        try:
            server.send_signal(signal.CTRL_BREAK_EVENT)
        except Exception:
            pass
        time.sleep(1)

if __name__ == "__main__":
    main()