Artículo

Laboratorio de SMLs: La ciencia del ajuste, el monitor de rendimiento

Jesús Manuel Nieto Carracedo etani.es Agentes LmStudio Ollama Llama.cpp Offgrid

Cuando trabajamos con modelos de lenguaje locales, especialmente en entornos con hardware limitado como un VPS o un portátil sin GPU dedicada, la configuración deja de ser una opción y se convierte en una necesidad. Aquí es donde entra la ingeniería de parámetros: el arte de equilibrar las capacidades del modelo con las limitaciones de tu máquina para obtener un rendimiento fluido y útil.

Los pilares del ajuste: Parámetros clave

Para dar un paso más en nuestro laboratorio, vamos a movernos desde el ajuste visual de LM Studio hacia Ollama. Es un punto intermedio ideal: nos aleja de la interfaz gráfica amigable pero sin lanzarnos todavía a las "catacumbas" de la terminal donde habitan los ingenieros que pastorean sistemas complejos. Más adelante completaremos la transición hacia llama.cpp, que es capaz de exprimir hasta la última gota de rendimiento combinando hardware y modelos de pesos abiertos.

No busco darte un tutorial de configuración paso a paso; mi objetivo es aportarte experiencia y dirección. No me detendré en cada detalle técnico innecesario, sino que te daré las pinceladas necesarias para que aprendas herramientas nuevas y tu creatividad haga el resto.

Aunque Ollama es menos eficiente que otras opciones, su sencillez nos permite entender qué hacen realmente los "mandos" que movemos. Cada uno impacta directamente en la velocidad, la calidad y el consumo de recursos. He seleccionado los parámetros que durante el laboratorio he entendido que más influyen cuando estás empezando, porque recuerda, no soy ningún experto, yo también estoy empezando:

El num_ctx funciona como la memoria a corto plazo del modelo; define cuánto texto puede "leer" y recordar simultáneamente (incluyendo tu prompt e historial). Un valor alto te permite procesar documentos largos, pero ten en cuenta que esto devora RAM y aumenta la latencia. Por otro lado, el num_predict es tu límite de generación: determina cuántos tokens puede producir el modelo en una sola respuesta, algo vital para evitar que se extienda innecesariamente o para asegurar que termine tareas largas como escribir código.

Ten en cuenta que cuando uses plugins como copilotos, por ejemplo Roo Code ahora denominado Zoo Code, Continúe, etc... o aplicaciones diversas que usan un System prompt personalizado, del tipo "Eres un asistente de código en visual studio", es decir, aplicaciones tipo agentes, los prompts que generan a parte de condicionar la respuesta del modelo, también consumen tokens de contexto. Lo descubrí por las malas. Cuando en modo chat, conseguía hablar con un modelo en CPU de 7B, arrojando 2-3 tokens/segundo, si intentaba usar ese mismo modelo en un plugin, bajaba a ser insufrible, generando 1 ó 0.5 tokens/segundo. Cuantas más palabras tenga el prompt que le envías al modelo, más lento procesará todo. Si usas fuerza bruta, mucho más hardware del necesario, esto no lo notarás mucho como un problema.

Por este motivo, si tu hardware es muy limitado, (un teléfono móvil que ejecuta la app Off Grid con un modelo pequeño muy cuantizado, configura contextos pequeños, si quieres ganar velocidad.

Observa la cantidad de tokens que tiene tu contexto, esta métrica la ofrecen casi todos o todos los clientes que se conecten a tu servidor vía Api. Podrás ver que, en modo chat con programas como Llama, un simple Hola modelo serán poquitos tokens, en cambio, ese mismo prompt usando Zoo Code puede crecer hasta los 1.000 tokens. Si eres curioso, es bueno que monitorices, sobre todo al principio, la respuesta "verbosa" del servidor, porque podrás observar que junto a tu prompt, el plugin introduce más contexto.

Otra forma que tienes para probarlo, es interactuar directamente vía Api, con comandos como curlde consola, o aplicaciones como postman, insomnia.

Aunque prometí no ponerme muy técnico, aquí debo ser responsable y avisarte, sino bajas al barro, si no analizas el tráfico de la API (solicitudes y respuestas del servidor), tu curva de aprendizaje en ingeniería de parámetros se verá seriamente limitada. Mi consejo es que decidas hasta qué punto deseas profundizar en este análisis técnico.

Para controlar la "personalidad" del modelo, tenemos la temperature. Es el termómetro de la creatividad: valores bajos (como 0.2) te darán respuestas precisas y deterministas, ideales para programación; valores altos permiten más variedad y "sorpresa", pero es aquí donde debes vigilar las temidas alucinaciones. Complementamos esto con top_k y top_p, que actúan como filtros de probabilidad para mantener la coherencia y evitar que el modelo elija palabras fuera de contexto. Finalmente, el repeat_penalty es tu seguro contra bucles infinitos, penalizando las repeticiones para que el modelo no se quede atrapado diciendo lo mismo una y otra vez.

No añadiría mucho más. Hay un concepto que está en el límite del bien y del mal con respecto a que es muy técnico y que es lo que necesitas para empezar, y es manejar el número de capas num_gpu que puedes cargar en VRAM. Podríamos decir que, lo ideal es cargar todas las capas del modelo en la memoria de la tarjeta gráfica, es lo más decisivo en la optimización, sino tendrás que ir haciendo pruebas para ajustar cuantas capas, cuantas partes indivisibles del modelo por así llamarlo, puedes almacenar en VRAM. Cuando te sorprendas a ti mismo jugando con este parámetro, es porque empezarás a entender la correlación entre RAM y VRAM, con respecto al rendimiento en tokens/segundo de un modelo y ya empezarás a estar preparado para trascender al siguiente nivel, no tanto de principiante, a llama.cpp y jugar con las optimizaciones mtp.

Está entre el bien y el mal, porque si vas sobrado de VRAM, ejecutarás cualquier modelo pequeño, por encima de 8GB, con 12GB de VRAM, modelos de 4B, cuantizados a 4 bits, van a cargarse completos, solo con saber descargar modelos Q4_K_M, será suficiente.

Si usas sistemas de memoria unificada como los chips M de Apple (M4) o las Apus Ryzer de memoria unificada (no recomiendo procesadores con memorias que no sean DDR5), no podrás jugar con esta variable ya que no hacen distinción entre memoria VRAM y RAM, en este caso ejecutarán en la misma memoria todas las capas, siempre y cuando tengas memoria libre suficiente.

Si el concepto anterior te ha hecho sentir como un auténtico "cazador de replicantes", te haré otro spoiler, con llama.cpp podrías incluso repartir el modelo en varias Gpus, tendrás a tu disposición técnicas tan increíbles como cargar un modelo grande, y un pequeño modelo borrador, que resuelva las consultas más mundanas y sencillas (mtp), etc... Es decir, el camino en cuanto a la optimización es largo y apasionante.

Recuerda, si empieza a agobiarte tanto con tanto concepto, tu decides en qué nivel de optimización te detienes.

Al principio mucha gente se queda en la siguiente prueba:

  • "Escucha hablar de los modelos de pesos abiertos, decide descargar LM Studio, bien, parece divertido y sencillo, es fácil aunque lento en ocasiones descargar un primer modelo, lo cargan en memoria, dicen "hola modelo", les hace gracia, y se quedan ahí."
  • En muchas ocasiones el modelo se rompe, no carga, o va lento, y viendo los parámetros de configuración del modelo, "a puerta fría", "mucho texto, bro..." y no volvemos a usarlos.

Entender el uso de 4-5 parámetros esenciales te permitirá exprimir tu hardware al máximo, antes de decidir comprar uno nuevo. Recuerda, a los ingenieros de sistemas, nos encanta pasar horas toqueteando ficheros, y perder horas de vida, es nuestro sueño ... (evidentemente, espero se note el sarcasmo...)

Otro consejo, si estás empezando, usa modelos grandes comerciales, indica tu hardware y el modelo, además de qué quieres consultar, y te ayudará bastante a darte tanto configuración como prompts más eficientes y efectivos para modelos pequeños.

Otro caso de uso interesante es que, las Apis, exponen un formato compatible con la api de OpenAI, si has usado alguna de las apis comerciales, te habrás dado cuenta que suelen sorprendentemente baratas. Esto por cierto, es un comentario "top" que tacharás de tu lista de comentarios esperados, cada vez que te sientas en una presentación de IA generativa, "animaros, yo metí 5-10€ y llevo meses sin gastarlos"... Esto es una verdad a medias, normalmente quien suele hacer estas presentaciones, no se dedica a explotar una api a nivel comercial, o bien no suele usarla para programar en modo agente, si mantienes una o varias plataformas, tendrás que medir mucho las pruebas en producción que usan apis, para que una sencilla prueba no se convierta un un agujero negro, si tu equipo de trabajo no es consciente que, procesar por ejemplo un cubo de S3 de medio TB, en desarrollo, bucles infinitos que dejamos pensando "lo que tarda, ya terminará", etc.., hacen que esos 10-15€ que al ponente le duran una vida, a ti te duran un café... Además si haces uso agéntico, programar usando tokens de apis comerciales, ya lo habrás vivido.

Pues bien, una solución es prototipar y probar la integración entre tu software tradicional, y una api, con un modelo pequeño de lenguaje, luego cambias el endpoint y listo, si aun así necesitas usar una api comercial concreta.

Otro caso de uso, es poder probar en tu modelo de pesos abiertos local, valores que puedes toquetear también en apis comerciales, donde pagarás cada prueba que quieras hacer. Siempre "disparas con balas de verdad".

El "Monitor" de rendimiento en tiempo real

No podemos mejorar lo que no podemos medir. Cuando usas el cliente de línea de comandos, a veces me olvido al escribir este artículo que, seguramente mucha gente que quiera usar Gemma4 para redactar blogs, como yo hoy en este momento, no tiene ni idea, ni lo necesita, ni lo pretende, de que es un servidor o una api...

Bueno te daré algunos trucos sencillos para poder monitorizar lo más básico, cuando usamos el cliente de línea de comandos CLI de Ollama, para diagnosticar cómo está respondiendo realmente tu servidor, necesitamos activar el modo verbose.

Aquí es donde entra una herramienta de diagnóstico vital para el "trasteo" real: el comando /set verbose. En la mayor parte de clientes con interfaz gráfica se muestra por defecto, o lo activas en su menú de configuración. Al ejecutarlo (o usar la bandera --verbose), Ollama nos entrega métricas críticas al final de cada respuesta, como la duración total y la cantidad de tokens. Pero la métrica reina es, sin duda, los Tokens por segundo. Es el dato que te dirá si tu configuración es realmente usable en producción o si tu hardware está sufriendo demasiado.

Ten en cuenta que no solo tienes que vigilar los tokens por segundo de generación de texto, sino también los de codificación (lectura) del prompt. Las tarjetas Nvidia, pueden leer a 400, o 4000 tokens/segundo, y aunque el modelo escriba despacio, el proceso global es rápido, de nada sirve que el modelo genere tokens a 40 por segundo, si lee (codifica) el prompt a la misma velocidad. Esto es un problema de los sistemas de memoria unificada que tienes que vigilar antes de adquirir hardware.

Persistencia vs. Flexibilidad: Modelfile y Comandos Internos

Un error común es confundir dónde aplicar cada ajuste. En nuestra metodología, distinguimos dos niveles:

  1. Ajustes Persistentes (Modelfile): Se usan para definir la "identidad" del modelo. Aquí configuramos parámetros que no cambian, como el sistema (SYSTEM), la plantilla de chat (TEMPLATE) y los valores base de inferencia. Al usar ollama create, estos ajustes se graban en un "lanzador" permanente; es el equivalente a la configuración fija en LM Studio, o la lista de parámetros que usamos cuando ejecutamos un servidor llama.cpp.

  2. Ajustes de Sesión (Comandos internos): Utilizando comandos como /set parameter, podemos experimentar en caliente durante una conversación interactiva. Es ideal para probar rápidamente cómo afecta un cambio de temperatura o contexto sin tener que recrear el modelo completo cada vez. No todos los parámetros se pueden cambiar en caliente, pero a estas alturas, si estás empezando, esta no debería ser una de tus preocupaciones.

Si quieres que te hable de mi experiencia, te hablaré del modelo Qwen3.6-35B-A3B-MTP, no voy a entrar a detalle, solo te diré que, en LM Studio, no lo pude ni descargar para el hardware en el que lo probé, porque presuponía que no se podía ejecutar. Bien, descargué este modelo directamente desde su repositorio, y lo ejecuté con una configuración mínima, sin ajustar mucho, y sin esperanza, parece fuera del alcance de mi RTX 3060 laptop de 6GB de VRAM. En la primera ejecución dió 1-2 tokens/segundo, sin apenas contexto, poco más que un "hola modelo". Optimizaciones posteriores en la configuración, elevaron su rendimiento a solo 20.16 tokens/segundo para la lectura de prompt, y 9.01 tokens/segundo para la generación de tokens. No es una velocidad espectacular, pero convierte al modelo en un modelo usable.

Ten en cuenta que los modelos tienen un arranque en frío lento, puede llevar hasta 3 prompts procesados, si acabas de cargar el modelo en memoria, que alcance su velocidad de crucero, por eso recomiendan que los 3 primeros prompts cuando pruebas un modelo, sean muy muy sencillos, si el programa que usas te permite escribir un espacio, servirá.

Lo interesante de las métricas de velocidad es que, si nos situamos en 2021-2022, que un modelo de lenguaje pudiera hacernos un script en python, una receta de cocina, un plan de trabajo para gimnasio, o escribirnos una publicación en linkedin, en 12-14h nos sonaba a magia negra. Nos hemos vuelto exigentes... Si quieres referencias, un modelo que escribe a 9 tokens/segundo, ya lo hace seguramente más rápido que la mayoría de los humanos podemos leer el contenido producido. Es un ejemplo donde el verdadero cuello de botella está en los escasos tokens de lectura de prompt.
.

Entrada Anterior Siguiente Entrada