-
Diferentes formas de ejecutar e interactuar con LlamaCPP
LlamaCPP nos permite ejecutar modelos de inteligencia artificial en local usando ficheros GGUF. Podemos usarlo de varias formas:
- Como comando puntual
- Como conversación interactiva
- Como servidor HTTP
- Como API compatible con clientes estilo OpenAI.
- Etc
En este hack vamos a partir de una instalación local donde tenemos los binarios de LlamaCPP en esta ruta:
/home/usuariox/IA/LlamaCPP/
Y vamos a usar este modelo GGUF como ejemplo:
/home/usuariox/IA/Modelos/GGUF/Llama-3.2-3B-Instruct-Q8_0.gguf
Para no repetir rutas largas constantemente, podemos guardar las rutas en variables de shell:
vLlamaCli="/home/usuariox/IA/LlamaCPP/llama-cli" vLlamaServer="/home/usuariox/IA/LlamaCPP/llama-server" vModelo="/home/usuariox/IA/Modelos/GGUF/Llama-3.2-3B-Instruct-Q8_0.gguf"
Ejecutar una consulta puntual con llama-cli
La forma más simple de usar LlamaCPP es ejecutar el modelo, pasarle un prompt y esperar la respuesta.
"$vLlamaCli" -m "$vModelo" -p "Hazme un script de Python que diga hola" -no-cnv
- -m indica el modelo que vamos a cargar.
- -p indica el prompt.
- -no-cnv desactiva el modo conversación, por lo que el modelo responde una vez y termina.
Esto es útil cuando queremos integrar LlamaCPP en scripts, automatizaciones o pruebas rápidas donde no queremos mantener una conversación abierta.
Limitar la cantidad de tokens generados
Si queremos que la respuesta sea más corta o queremos evitar que el modelo siga generando demasiado texto, podemos limitar la cantidad máxima de tokens de salida con -n.
"$vLlamaCli" -m "$vModelo" -p "Hazme un script de Python que diga hola" -n 128 -no-cnv
- -n 128 indica que el modelo podrá generar como máximo 128 tokens. Esto no significa exactamente 128 palabras, porque los modelos trabajan con tokens, no con palabras completas.
Esta opción es especialmente útil cuando queremos respuestas controladas, rápidas o fáciles de parsear desde otro programa.
Ejecutar LlamaCPP en modo conversación
Si ejecutamos llama-cli sin pasar un prompt cerrado, podemos usarlo en modo interactivo:
"$vLlamaCli" -m "$vModelo"
En este modo podemos escribir mensajes directamente en la terminal e ir conversando con el modelo. Es la forma más cómoda para probar un modelo manualmente antes de usarlo desde scripts o desde una API. También podemos forzar explícitamente el modo conversación con -cnv:
"$vLlamaCli" -m "$vModelo" -cnv
Si queremos pasar un primer mensaje y que la ejecución sea de un solo turno, podemos usar -st:
"$vLlamaCli" -m "$vModelo" -p "Explica qué es un fichero GGUF" -st
Esta opción es útil cuando queremos usar un modelo instruct o chat sin entrar en una sesión interactiva completa.
Usar GPU con CUDA
Si hemos compilado LlamaCPP con soporte CUDA, podemos descargar parte o todo el modelo en la VRAM de la tarjeta gráfica. Para eso se usa -ngl o su forma larga –n-gpu-layers:
"$vLlamaCli" -m "$vModelo" -p "Hazme un resumen de qué es LlamaCPP" -ngl all -no-cnv
La opción -ngl all intenta cargar todas las capas posibles del modelo en la GPU. Si no tenemos suficiente VRAM, podemos usar un número concreto:
"$vLlamaCli" -m "$vModelo" -p "Hazme un resumen de qué es LlamaCPP" -ngl 32 -no-cnv
En este caso estamos indicando que queremos cargar 32 capas del modelo en GPU. Cuantas más capas entren en VRAM, normalmente mejor será el rendimiento. Si nos pasamos, lo normal es que falle por falta de memoria o que el sistema empiece a comportarse de forma inestable. En versiones recientes también podemos dejar que LlamaCPP intente ajustar automáticamente las capas:
"$vLlamaCli" -m "$vModelo" -p "Hazme un resumen de qué es LlamaCPP" -ngl auto -no-cnv
Si tenemos varias GPUs, nos interesa revisar también opciones como –device, –split-mode, –tensor-split y –main-gpu. Para un uso básico con una sola GPU, normalmente nos alcanza con -ngl.
Ajustar el tamaño de contexto
El contexto define cuántos tokens puede tener la conversación completa, contando entrada y salida. Se configura con -c o –ctx-size.
"$vLlamaCli" -m "$vModelo" -c 4096 -p "Explica qué es el contexto de un modelo LLM" -no-cnv
Un contexto mayor permite trabajar con prompts más largos y conversaciones más extensas, pero también consume más RAM o VRAM, especialmente por la caché KV.
Ejecutar LlamaCPP como servidor
Si queremos usar el modelo desde otras aplicaciones, lo más cómodo es levantar llama-server.
"$vLlamaServer" --port 9000 -m "$vModelo"
Con esto tendremos un servidor HTTP escuchando en el puerto 9000. Desde ese momento podemos hacer peticiones al modelo usando curl, Python, aplicaciones web, scripts o clientes compatibles con APIs tipo OpenAI. Si queremos usar GPU también en el servidor, añadimos -ngl:
"$vLlamaServer" --port 9000 -m "$vModelo" -ngl all
Servidor con varios usuarios simultáneos
Para permitir varias secuencias en paralelo se usa -np o –parallel.
Por ejemplo, si queremos permitir 4 secuencias paralelas y asignar un contexto total de 16384 tokens, podemos lanzar el servidor así:
"$vLlamaServer" --port 9000 -m "$vModelo" -c 16384 -np 4
La idea práctica es sencilla: si queremos 4 usuarios simultáneos con 4096 tokens de contexto para cada uno, necesitamos reservar un contexto total aproximado de 16384 tokens.
4096 x 4 = 16384
Esto no significa que siempre debamos multiplicarlo así a ciegas, porque el consumo real depende del modelo, del backend, del tipo de caché KV y de los parámetros de ejecución. Pero como regla práctica inicial nos sirve para dimensionar el servidor.
Consultar llama-server usando /completion
El endpoint /completion es el endpoint propio de llama-server. No es el endpoint compatible con OpenAI, pero es simple y funciona bien para pruebas rápidas.
curl -X POST "http://localhost:9000/completion" \ -H "Content-Type: application/json" \ -d '{ "prompt": "Hola, ¿cómo estás?", "n_predict": 50 }'Es importante que el JSON sea JSON válido. Las claves y los textos deben ir entre comillas dobles.
Esto está mal:
{prompt: Hola, ¿cómo estás?, n_predict: 50}Y esto está bien:
{ "prompt": "Hola, ¿cómo estás?", "n_predict": 50 }Consultar llama-server como API compatible con OpenAI
Además del endpoint propio /completion, llama-server también permite usar endpoints compatibles con OpenAI. Esto es más cómodo si queremos conectar herramientas, librerías o aplicaciones que ya esperan una API con formato OpenAI.
Para chat, podemos usar /v1/chat/completions:
curl "http://localhost:9000/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer no-key" \ -d '{ "model": "local", "messages": [ { "role": "user", "content": "Explícame qué es LlamaCPP en pocas líneas" } ], "max_tokens": 200 }'El campo model puede ser necesario para clientes compatibles con OpenAI. En una configuración simple con un único modelo local, muchas veces podemos usar un nombre genérico como local, aunque en configuraciones con router o varios modelos conviene usar el nombre que corresponda al modelo cargado.
También podemos usar /v1/completions, que trabaja con prompt en vez de messages:
curl "http://localhost:9000/v1/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer no-key" \ -d '{ "model": "local", "prompt": "Escribe una explicación breve sobre los modelos GGUF", "max_tokens": 200 }'Usar streaming
Si queremos recibir la respuesta token a token, podemos activar streaming. Esto es útil para interfaces web, terminales interactivas o integraciones donde no queremos esperar a que el modelo termine toda la respuesta.
curl "http://localhost:9000/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer no-key" \ -d '{ "model": "local", "messages": [ { "role": "user", "content": "Dame tres ventajas de ejecutar modelos en local" } ], "max_tokens": 200, "stream": true }'Usar llama-server desde Python
Si queremos interactuar con llama-server desde Python, podemos usar requests directamente:
#!/usr/bin/env python3 import requests vUrl = "http://localhost:9000/v1/chat/completions" dPayload = { "model": "local", "messages": [ { "role": "user", "content": "Hazme un script de Python que diga hola" } ], "max_tokens": 200 } dHeaders = { "Content-Type": "application/json", "Authorization": "Bearer no-key" } vRespuesta = requests.post(vUrl, headers=dHeaders, json=dPayload, timeout=120) vRespuesta.raise_for_status() dRespuesta = vRespuesta.json() print(dRespuesta["choices"][0]["message"]["content"])Este enfoque es más limpio que ejecutar llama-cli desde subprocess cuando queremos integrar el modelo en una aplicación.
Cuándo usar cada modo
Modo Comando Cuándo usarlo Consulta puntual llama-cli -p … -no-cnv Para scripts, pruebas rápidas y respuestas de un solo turno. Conversación en terminal llama-cli -cnv Para probar modelos manualmente. Servidor HTTP llama-server Para usar el modelo desde otras aplicaciones. Endpoint /completion /completion Para pruebas simples con el endpoint propio de llama-server. API compatible con OpenAI /v1/chat/completions Para integrar clientes, frontends o librerías que ya esperan formato OpenAI. Comandos útiles para comprobar el rendimiento
Mientras ejecutamos el modelo con GPU, podemos comprobar el uso de la gráfica con nvidia-smi:
watch -n 1 nvidia-smi
También podemos lanzar llama-cli con métricas internas:
"$vLlamaCli" -m "$vModelo" -p "Hazme una lista de 10 usos de LlamaCPP" -n 256 -no-cnv --perf
Esto nos ayuda a comparar configuraciones con CPU, GPU parcial, GPU completa, distintos tamaños de contexto y diferentes cuantizaciones del modelo.
Errores habituales
- Si el modelo no usa la GPU, lo primero que debemos revisar es que LlamaCPP haya sido compilado con soporte CUDA y que estemos usando -ngl con un valor adecuado.
- Si el servidor responde mal a curl, casi siempre el problema está en el JSON. Debemos asegurarnos de enviar la cabecera Content-Type y de usar comillas dobles en claves y valores.
- Si el servidor se queda sin memoria, debemos bajar el contexto con -c, reducir -np, reducir -ngl o usar una cuantización más pequeña del modelo.
- Si queremos conectar una aplicación externa, normalmente nos conviene usar /v1/chat/completions antes que /completion, porque el formato es más compatible con herramientas ya existentes.