Cómo usar Headroom con LiteLLM para gastar menos tokens

El router de complejidad de LiteLLM te cobra dos llamadas a modelo en cada request: una pequeña para decidir qué nivel responde, y la real que responde. Desde la versión del 5 de septiembre de 2026 puedes comprimir esos dos prompts por separado, y las pruebas internas de LiteLLM sitúan el ahorro adicional sobre la llamada de ruteo en un 32%.

Hasta esta versión los dos saltos compartían una sola configuración de compresión. Y esa es una restricción real, no cosmética: el modelo que responde necesita contexto suficiente para dar una buena respuesta, así que el nivel de compresión que elegías quedaba limitado por lo que toleraba ese modelo. Al clasificador —que solo tiene que devolver una etiqueta de nivel— le estabas pasando mucho más contexto del que necesita, con una compresión pensada para otro trabajo.

Por Devy · Categoría: AI Dev Tools

¿Qué es LiteLLM?

LiteLLM es un gateway open source que se ubica entre tu aplicación y los proveedores de modelos. Apuntas tu cliente compatible con OpenAI al proxy de LiteLLM en lugar de apuntarlo directo a OpenAI o Anthropic, y el gateway se encarga de credenciales, presupuestos, fallbacks, logging y ruteo detrás de un solo endpoint. Lo ejecutas tú mismo, con litellm --config config.yaml.

Si leíste nuestra nota sobre CodeGate, la forma te resulta familiar: un único punto de paso controlado por donde cruza tu tráfico, y donde vive la política.

¿Qué es AutoRouter y por qué hace dos llamadas?

AutoRouter es la función de LiteLLM que clasifica cada request entrante y le asigna un nivel de modelo, en vez de obligarte a fijar uno a mano. El router de complejidad define niveles —SIMPLE, MEDIUM, COMPLEX, REASONING— y asocia cada uno a un modelo.

La clasificación se puede hacer de tres maneras, según la documentación de LiteLLM: un scorer heurístico de menos de un milisegundo, reglas por palabras clave, o un modelo pequeño. Si defines classifier_type: llm, el clasificador pasa a ser una llamada a modelo de verdad. LiteLLM aclara que esa llamada atraviesa la misma instancia de Router, así que se le aplican tus credenciales, presupuestos y fallbacks; y que ante un timeout, contenido vacío o un schema que no cuadra, cae de vuelta al scorer heurístico.

Es un diseño sensato. También es la llamada que nadie audita. No aparece en el código de tu aplicación, no produce ninguna salida visible para el usuario, y se ejecuta en absolutamente todos los requests.

Si no tienes del todo claro por qué esa llamada invisible te cuesta dinero, empieza por Qué son los tokens en la IA y por qué te cobran por ellos: ahí está la aritmética que hace que todo lo demás de esta nota tenga sentido.

¿Qué cambió en esta versión?

Dos campos nuevos dentro de complexity_router_config, cada uno apuntando a un guardrail con nombre:

  • auto_router_routing_compression — la compresión que se aplica al prompt del clasificador
  • auto_router_model_compression — la compresión que se aplica al prompt del modelo que responde

Separados así, puedes comprimir el salto de ruteo de forma agresiva y dejar el salto del modelo en moderado. La nota de LiteLLM reporta que esto “recortó los costos de clasificación un 32% adicional por encima de lo que la compresión compartida ya venía ahorrando, sin cambios en la precisión del ruteo”.

Lee ese número por exactamente lo que es. Son pruebas internas de LiteLLM, publicadas sin metodología, midiendo su propia función. Es una dirección plausible y una magnitud sin verificar. Al momento de publicar esta nota, nadie fuera de BerriAI la ha reproducido.

¿Cómo se configura?

Este es el ejemplo publicado por LiteLLM, reproducido tal como ellos lo escribieron:

model_list:
  - model_name: smart-router
    litellm_params:
      model: auto_router/complexity_router
      complexity_router_config:
        tiers:
          SIMPLE: gpt-4o-mini
          MEDIUM: gpt-4o
          COMPLEX: gpt-4-turbo
        classifier_type: llm
        auto_router_routing_compression: headroom-aggressive
        auto_router_model_compression: headroom-moderate

guardrails:
  - guardrail_name: headroom-aggressive
    litellm_params:
      guardrail: headroom
      mode: pre_call
      api_base: https://api.berri.ai/headroom
      model: o1
      tokens_to_retain: 200
  - guardrail_name: headroom-moderate
    litellm_params:
      guardrail: headroom
      mode: pre_call
      api_base: https://api.berri.ai/headroom
      model: gpt-4o-mini
      tokens_to_retain: 1000

El mecanismo está en tokens_to_retain: 200 tokens para el clasificador, 1000 para el modelo que responde. El clasificador solo tiene que emitir una etiqueta de nivel, así que sobrevive con una fracción del contexto.

Ten en cuenta que los dos nombres de guardrail de este ejemplo —headroom-aggressive y headroom-moderate— son etiquetas que LiteLLM eligió para su propio ejemplo, no palabras reservadas. Los tuyos se llaman como quieras; lo único que importa es que los campos coincidan.

¿Qué es Headroom y tienes que usar el servicio alojado de LiteLLM?

Headroom es el servicio de compresión de prompts que hace el trabajo real. Lo cubrimos en Headroom: cómo cortar hasta 95% de tus tokens sin cambiar las respuestas: reescribe el prompt antes de despacharlo, conservando el significado y bajando el volumen.

Aquí está el detalle que conviene no pasar por alto. El config de ejemplo de LiteLLM apunta api_base a https://api.berri.ai/headroom, que es el endpoint alojado por la propia LiteLLM. Es decir que si copias ese bloque tal cual, tus prompts viajan a un servicio de terceros antes de llegar al modelo, aunque tu gateway esté auto-alojado.

Eso es una propiedad del ejemplo, no de la función. La documentación de Headroom en LiteLLM lo describe como un servicio sidecar que corres junto al proxy, desplegado desde un Dockerfile que ellos proveen, y api_base es simplemente la dirección donde escucha tu servicio de Headroom. Apúntalo a tu propio sidecar y todo el camino se queda dentro de tu infraestructura. Los parámetros documentados del guardrail son guardrail, mode (que debe ser pre_call; aplicarlo del lado de la respuesta no hace nada), api_base, un api_key opcional, y un default_on opcional que comprime todos los requests que pasan por el proxy en lugar de activarse ruta por ruta.

Si en tu organización el contenido de los prompts saliendo de tu red es una pregunta de cumplimiento, esta es la línea que hay que leer con cuidado antes de pegar el ejemplo.

¿LiteLLM u OpenRouter?

La diferencia práctica es dónde corre el ruteo: OpenRouter decide por ti en su infraestructura, LiteLLM decide en la tuya. Todo lo demás se desprende de ahí.

OpenRouter es un servicio alojado. Apuntas tu cliente a https://openrouter.ai/api/v1 con una API key y accedes a cientos de modelos por un solo endpoint, con fallbacks automáticos. LiteLLM es un gateway que ejecutas tú: el proxy vive en tu infraestructura, las credenciales de los proveedores son tuyas, y las políticas de ruteo las escribes en tu propio config.yaml.

LiteLLM OpenRouter
Dónde corre Tu infraestructura Servicio alojado
Claves de proveedor Tuyas, en tu proxy De OpenRouter (también admite traer las tuyas)
Cómo elige proveedor Las reglas que escribes en config.yaml Balanceo por precio ponderado, descartando proveedores con caídas recientes
Control de ruteo Total: niveles, clasificador, fallbacks, presupuestos Por request, vía el objeto provider
Compresión por salto Sí, con los dos campos de esta nota No expuesto
Qué operas Un proxy, y opcionalmente un sidecar de Headroom Nada

¿Cuándo conviene OpenRouter?

Cuando no quieres operar infraestructura. El control que ofrece no es poco: en el objeto provider de cada request puedes fijar order para probar proveedores en un orden dado, sort para priorizar por price, throughput o latency, only e ignore para permitir o descartar proveedores, y require_parameters para quedarte solo con los que soportan todos los parámetros que enviaste.

Para equipos con requisitos de datos hay dos controles que vale la pena conocer: data_collection: "deny" excluye proveedores que puedan almacenar datos para entrenamiento, y zdr: true limita el ruteo a endpoints Zero Data Retention. Su documentación indica que por defecto no registran prompts ni respuestas, y que ofrecen un descuento sobre el uso a quien decida activar ese registro.

En cuanto al costo, su FAQ señala que trasladan el precio del proveedor subyacente sin recargo, y que cobran una comisión sobre la compra de créditos —5,5% vía Stripe al momento de publicar esta nota—. Verifica ese número antes de proyectar nada: es de los que cambian.

¿Cuándo conviene LiteLLM?

Cuando el ruteo mismo es algo que necesitas ajustar, auditar o abaratar.

Y esta nota es el ejemplo exacto. La compresión por salto existe porque tú controlas el proceso que arma el prompt del clasificador: puedes decidir que ese prompt viaje con 200 tokens mientras el del modelo que responde viaja con 1000. Esa palanca no está expuesta cuando el ruteo lo decide un servicio alojado, porque el prompt del clasificador ni siquiera es tuyo.

La regla práctica: si tu problema es acceso a muchos modelos, OpenRouter lo resuelve sin que despliegues nada. Si tu problema es el costo y el comportamiento del ruteo en sí —y ya tienes suficiente tráfico como para que un 32% sobre la llamada de clasificación signifique algo—, esa optimización solo existe del lado que operas tú. Elegir LiteLLM es aceptar mantener una pieza de infraestructura a cambio de poder ajustar cosas como esta.

¿Conviene activarlo hoy?

Tres cosas que conviene pesar con honestidad, todas ciertas al momento de publicar esta nota:

AutoRouter figura como Beta en la documentación de LiteLLM, con el config explícitamente sujeto a cambios. El 32% es auto-reportado. Y LiteLLM sigue reclutando design partners para AutoRouter y juntando resultados en la discusión #32168 de GitHub, lo que te dice que la función está publicada y es usable, pero todavía no está asentada.

El contrapeso es que el riesgo es bajo y reversible. Son dos líneas de configuración sobre un gateway que ya corres, el clasificador cae de vuelta al scorer heurístico cuando algo falla, y puedes medir el efecto sobre tu propio tráfico en lugar de confiar en el benchmark de nadie. Si ya estás corriendo el router de complejidad con classifier_type: llm, ya estás pagando esa segunda llamada en todos los requests. La única pregunta es cuánto contexto necesita para seguir haciendo su trabajo, y la respuesta casi seguro es menos del que necesita el modelo que responde.

El token más barato sigue siendo el que nunca envías.