gptel: Emacs y la IA

5 min read Original article ↗

No suelo arrancar el modelo hasta que no lo voy a usar. Como opté por compilar llama.cpp pero no instalarlo, le debo dar los paths completos para la ejecución, tanto del binario ejecutable, como la dirección del modelo que debe cargar. La línea de comandos se me queda así:

~/proyectos/llama.cpp/build/bin/llama server --reasoning off --port 8383 -m ~/modelos-ia/Qwen3.5-9B-Q4_K_M.gguf -t 6 --ctx-size 131072 -np 1

Después de unos segundos, lo que tarde en cargar el modelo en memoria, ya tengo IA corriendo en mi propia máquina. Pero veamos, qué significan las distintas partes de esa línea tan larga. Para empezar, lo cargo en modo server, lo que me permite utilizarlo desde varias herramientas, o programas, a la vez. Puedo cargarlo desde el navegador y desde Emacs, por ejemplo. Algunos de los parámetros son muy claros, pero otros pueden resultar oscuros:

--reasoning
Poniéndolo a off deshabilitas el razonamiento del modelo y aceleras un poco la respuesta. Sus valores pueden ser on, off y auto. También, si lo activas, puedes configurar el esfuerzo de razonamiento con la opción --reasoning-efford que puede tomar los valores minimal, low, medium, hight, xhight o max. Si enlazas al servidor con el navegador, incluso puedes modificar esos valores sobre la marcha.
--port
El número de puerto que se utilizará para conectar con el servidor.
-m o --model
le proporciona al servidor el modelo que va a utilizar. En llama.cpp suele ser un archivo con extensión .gguf.
-t o --threads
le dice al servidor cuántos threads puede utilizar durante el proceso. El número recomendado es el número de procesadores físicos que tenga la CPU. La mía tiene 6 físicos y 6 virtuales. Por tanto, aunque tiene 12 hilos, le paso como parámetro sólo 6.
--ctx-size
es el tamaño (en bytes) del contexto que quieres reservar en memoria. Cuanto más grande sea el contexto, más tardan en aparecer «alucinaciones» en las respuestas del modelo, pero también más RAM va a necesitar.
-np o --parallel
es el número de slots del servidor. Por defecto, el valor es -1 que quiere decir automático. Cada slot consume su parte de memoria, que como ya sabemos es un bien escaso. En mi máquina el modo automático abre 4 slots y consume la correspondiente memoria, por eso, para ahorrar, lo limito a 1. A pesar de contar sólo con un slot sigo pudiendo conectar a la vez, y de manera independiente, Emacs y el navegador para interactuar con el modelo.

Una vez puesto en marcha el modelo, ya podemos conectar con él. Desde Emacs podemos utilizar varios métodos. Puedes crear un buffer para interactuar con él llamando a gptel. Pregunta el nombre del mismo y abre un buffer markdown, con un modo secundario GPT.

Captura_primera-pregunta.png
Figura 1: Captura de pantalla de Emacs con el buffer de interacción con el modelo en el centro.

En la imagen podemos apreciar cómo se muestra un buffer interactivo. Por defecto coloca tres almohadillas donde podemos escribir nuestro prompt y enviarlo pulsando la secuencia de teclas C-c RET. Tras unos segundo, contesta en perfecto markdown.

La mayor parte de las interacciones con el modelo se pueden realizar a través del menú que se muestra mediante el comando gptel-menu:

Captura_gptel-menu.png
Figura 2: El menú de gptel con todas sus opciones.

Hay que poner atención a que si lo llamas desde un buffer cualquiera, al pulsar RET envía el contenido del buffer al modelo y éste escribirá de vuelta en ese mismo buffer. Lo que puede ser un engorro. Sin ir más lejos, mientras editaba este artículo se me fue el dedo al RET mientras hacía la captura anterior. Cuando me quise dar cuenta se puso a escribir en medio de un párrafo que estaba corrigiendo contándome lo interesante que le parecía el tema que estaba tratando y las particularidades de mi configuración... basura textual.

Ese comportamiento se puede cambiar. En el menú, se puede establecer de dónde leerá el prompt y dónde escribirá la respuesta. Por ejemplo, para que al pulsar RET pida el prompt en el minibuffer y escriba la respuesta en el buffer de gptel, podemos pulsar las teclas <m> y <g>, o seleccionar y cortar el prompt pulsando <y>, o que nos dé la respuesta en otro buffer o en el área de eco, o que lo meta el kill-ring. Hay varias opciones y es aconsejable probarlas todas para apreciar cómo podemos ajustar ese comportamiento según las necesidades del momento.

Podemos añadir al contexto buffers y archivos para completar la tarea que queramos. Además el paquete ya viene con cuatro tipos de instrucciones para trabajar directamente. Si pulsamos <s> nos permite elegir unas instrucciones específicas como cabecera del prompt que enviamos. Las directivas son:

nombre prompt
default You are a large language model living in Emacs and a helpful assistant. Respond concisely.
programming You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.
writing You are a large language model and a writing assistant. Respond concisely.
chat You are a large language model and a conversation partner. Respond concisely.

También puedes crear tus propias cabeceras para enviárselas al modelo según tus necesidades.