Servir modelos de razonamiento: el borrador invisible que decide tu latencia y tu factura

TL;DR

Un modelo de razonamiento genera, antes de la respuesta que ves, un bloque de pensamiento —cientos o miles de tokens encerrados entre <think> y </think>— que el usuario no lee pero que consume el mismo cómputo, la misma VRAM y la misma factura que cualquier otro token. Servirlos en producción no es “servir un modelo más grande”: es servir un modelo cuyo coste por petición es variable y, por defecto, descontrolado. Tres palancas cambian la ecuación: elegir bien entre modo think / non-think (los modelos híbridos de 2026 lo permiten en el mismo peso), poner un presupuesto de razonamiento (thinking_token_budget en vLLM, budget forcing tipo s1) y medir el impacto en el KV cache (una cadena de 30k tokens de razonamiento puede comerse ~9 GB de KV en FP16). Bien gestionado, ganas precisión donde importa; mal gestionado, pagas hasta 113× más energía por una respuesta que no necesitaba pensar tanto.


La analogía

Imagina a un opositor en el examen. Antes de escribir la respuesta buena en el folio oficial, llena tres folios de sucio: tantea enfoques, se corrige, descarta. Esos folios de sucio no se entregan —el tribunal solo lee la respuesta final— pero el opositor ha gastado tinta, tiempo y media hora de examen en ellos.

Un modelo de razonamiento hace exactamente eso. El bloque <think>…</think> es el folio de sucio: razona en voz alta, se contradice, vuelve atrás, y al final emite la respuesta “limpia”. El problema de producción es que tú pagas también el sucio: cada token de razonamiento ocupa una ranura en el batch, crece el KV cache y suma a la factura igual que un token de salida. Y, como cualquier opositor nervioso, el modelo tiende a sobrepensar: escribe cinco folios cuando con uno bastaba.

La pregunta operativa de este post no es “¿razona bien?”, sino “¿cuánto sucio le dejo escribir, y cuándo le quito el boli?”.


Qué cambia cuando el modelo “piensa”

En un modelo normal, una petición es: prompt → tokens de salida. En un modelo de razonamiento la secuencia tiene dos tramos:

  1. Bloque de razonamiento (<think> … </think>): la cadena de pensamiento (CoT). Largo, variable, normalmente oculto al usuario final.
  2. Respuesta final: lo que el usuario ve.

vLLM modela esto explícitamente. Al arrancar con un reasoning parser, la salida trae un campo reasoning_content separado del content:

vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-32B \
  --reasoning-parser deepseek_r1

El parser detecta los delimitadores de pensamiento y separa ambos tramos en la respuesta de la API (vLLM · Reasoning Outputs). Esto importa para serving por una razón práctica: si tu gateway o tu UI no separan reasoning_content de content, acabarás mostrando el folio de sucio —o, peor, registrándolo en logs y trazas sin querer.

Peticiónprompt + sistema(visible · facturable)Bloque de razonamiento <think> … </think>cientos–miles de tokens OCULTOS al usuariocrecen el KV cache · suman a la factura como salidatope: thinking_token_budget → fuerza </think>Respuestacontent final(lo único queve el usuario)Coste por petición = prompt + razonamiento + respuestaEl razonamiento es invisible en la UI pero NO en la GPU ni en la factura. Es la variable que descontrola tu coste por request.Regla operativa: separa reasoning_content del content en el gateway, y pon un presupuesto de pensamiento por ruta.

El panorama 2026: del modelo “que razona siempre” al híbrido conmutable

La primera generación (o1, DeepSeek-R1, QwQ-32B) eran modelos que siempre razonaban. En 2026 el patrón dominante es el híbrido: un único peso que conmuta entre think y non-think.

  • DeepSeek-V3.1 introdujo una arquitectura de razonamiento híbrido en un solo modelo: DeepSeek-V3.1-Think para problemas complejos y un modo directo más rápido para lo trivial, conmutables por el usuario (InfoQ). Importante para serving: el razonamiento viene desactivado por defecto y se activa con thinking=True en chat_template_kwargs.
  • Qwen3 trae Hybrid Thinking Modes y un Thinking Budget explícito para acotar el cómputo de razonamiento; en su serie el pensamiento viene activado por defecto (como QwQ-32B).
  • gpt-oss muestra una estructura de razonamiento distinta a la de la familia R1/Qwen, lo que en la práctica significa que el parser y los delimitadores no son universales: cada familia tiene los suyos.

La consecuencia arquitectónica es clara: en 2026 ya no decides “modelo que razona” vs “modelo que no”, sino cuándo dejas que el mismo modelo razone. Eso convierte el razonamiento en una decisión de routing y de presupuesto, no de catálogo de modelos. Conecta directamente con el router de inferencia L7: la ruta “barata” desactiva el pensamiento; la “cara” lo activa con un tope.


La economía: por qué el folio de sucio dispara la factura

Aquí está el corazón del problema. Los tokens de razonamiento son invisibles para el usuario pero reales en cómputo y en facturación. Los proveedores los cobran como tokens de salida —por ejemplo, los proveedores de API facturan esos reasoning tokens al precio de salida, no gratis (Test-Time Compute Quietly Changed the Economics of Inference). En on-premise no hay factura externa, pero sí hay coste: ocupan ranuras de batch, VRAM de KV y vatios.

El coste facturable (o el coste-equivalente en GPU·hora) de una petición es:

$$\text{tokens de cómputo} = \text{prompt} + \underbrace{\text{tokens de razonamiento}}_{\text{ocultos, variables}} + \text{respuesta visible}$$

El término del medio es el que se descontrola. En tareas difíciles la ratio razonamiento/respuesta visible puede ser enorme, y el análisis empírico llega a medir hasta 113× el coste energético frente a la inferencia estándar en ciertas tareas de código (Towards Data Science · Inference Scaling).

Y no siempre compra precisión. El fenómeno del overthinking está documentado: más pensamiento no garantiza mejor respuesta, y a partir de cierto punto empeora. Hay trabajos que muestran que las cadenas más cortas son hasta un 34,5 % más precisas que la más larga muestreada para la misma pregunta (Don’t Overthink it), y estudios sobre el “espejismo” del test-time scaling (Mirage of Test-Time Scaling) y sobre cuándo pensar de más hace daño (When More Thinking Hurts). El primer estudio a gran escala del test-time scaling —más de 30.000 millones de tokens generados con 8 LLM open source de 7B a 235B sobre 4 datasets de razonamiento— sistematiza dónde escala y dónde no (The Art of Scaling Test-Time Compute).

La lectura operativa: el razonamiento es un coste que hay que presupuestar, no un interruptor de “más calidad” que dejas siempre a tope.


Controlar el presupuesto de pensamiento

Tres mecanismos, de menos a más fino.

1. Conmutar think / non-think

Lo más barato es no razonar cuando no hace falta. En modelos híbridos, desactiva el pensamiento para clasificación, extracción, formato, respuestas triviales:

# DeepSeek-V3.1: razonamiento OFF por defecto; se activa explícitamente
chat_template_kwargs = {"thinking": True}   # solo en la ruta "difícil"

Esto es el 80 % del ahorro con el 20 % del esfuerzo: enruta por dificultad y reserva el pensamiento para lo que de verdad lo paga.

2. Poner un tope: thinking_token_budget

vLLM incorpora un sampling parameter thinking_token_budget que cuenta los tokens de razonamiento y, al llegar al límite, fuerza el cierre del bloque (reasoning_end_str, típicamente </think>), obligando al modelo a responder ya. Si no se especifica, no hay más límite que max_tokens (PR #37112, nota de implementación). Por debajo, un ReasoningBudgetLogitsProcessor inyecta algo como “Let me stop thinking and answer now.</think> cuando se alcanza el tope.

# Define los delimitadores del bloque de razonamiento
vllm serve Qwen/Qwen3-32B \
  --reasoning-parser qwen3 \
  --reasoning-config '{"reasoning_start_str":"<think>","reasoning_end_str":"</think>"}'
// por petición: corta el sucio a 1024 tokens
{"messages":[...], "thinking_token_budget": 1024}

3. Budget forcing (estado del arte)

La técnica que popularizó el control fino es budget forcing, del paper s1: para gastar menos, se termina el pensamiento forzando el delimitador de fin; para gastar más, se suprime el fin y se anexa la palabra “Wait”, lo que empuja al modelo a revisar y a menudo corregir su propio razonamiento. Con esto, s1-32B (un Qwen2.5-32B-Instruct afinado sobre solo 1.000 ejemplos) superó a o1-preview hasta en un 27 % en AIME24/MATH (s1: Simple Test-Time Scaling). La lección de serving: el presupuesto no es solo un tope de coste, es una palanca de calidad bidireccional.

$$\text{precisión} \approx f(\text{tokens de razonamiento}) \quad\text{con un máximo, no monótona}$$

La curva sube, satura y en muchas tareas baja. Tu trabajo es operarla cerca del codo, no en el extremo.


El impacto que casi nadie mide: el KV cache

Aquí es donde el razonamiento muerde el serving de verdad. Cada token del folio de sucio es un token más en el KV cache. Una cadena larga de razonamiento infla la memoria de trabajo igual que un contexto largo de entrada.

El tamaño del KV crece linealmente con la secuencia (incluido el razonamiento):

$$\text{KV bytes} = 2 \times L \times h_{kv} \times d_{head} \times s \times b$$

donde (L) son capas, (h_{kv}) cabezas KV (con GQA, pocas), (d_{head}) la dimensión por cabeza, (s) la longitud de secuencia y (b) los bytes por elemento. El término que dispara el razonamiento es (s): una respuesta “normal” de 500 tokens y una con 8.000 tokens de pensamiento no ocupan lo mismo, ni de lejos.

Los números reales asustan: para un modelo destilado de razonamiento con atención estándar como DeepSeek-R1-Distill-Llama-70B, una sola cadena de 30.000 tokens de razonamiento consume ~9 GB de KV en FP16, que la cuantización de KV a FP8 reduce a ~4,5 GB —una de las optimizaciones de mayor impacto para cargas de cadena-de-pensamiento (Spheron · KV Cache Optimization). Multiplica eso por la concurrencia y entiendes por qué un cluster que servía 200 peticiones simultáneas de un modelo “normal” se queda en 40 con el mismo modelo razonando.

Dos matices del estado del arte que conviene conocer:

  • Prefix caching no es gratis aquí. El estudio empírico de serving de modelos de razonamiento encuentra que el prefix caching mejora claramente la velocidad en modelos de 14B o más, pero perjudica en modelos de 7B (la gestión del caché cuesta más de lo que ahorra) (Reasoning Language Model Inference Serving Unveiled). Y como el grueso del coste del razonamiento está en el decode (generar tokens uno a uno), el prefix caching —que solo acelera el prefill— apenas toca la fase cara. Conecta con prefix cache: ingeniería del hit rate.
  • Compresión de KV específica de razonamiento. Han aparecido técnicas como R-KV, que comprime el KV explotando la redundancia típica de las cadenas de pensamiento (el modelo repite y divaga), recuperando memoria sin tocar la calidad (R-KV).

La palanca más rentable y disponible hoy sigue siendo KV en FP8 (ver FP8 end-to-end) combinada con un presupuesto de razonamiento que evite las colas de 30k tokens en primer lugar.


Razonamiento + salida estructurada: el orden importa

Si sirves structured output (JSON con esquema) y razonamiento a la vez, hay una trampa sutil: la gramática no debe aplicarse durante el bloque de pensamiento. El modelo necesita texto libre para razonar; forzarle el esquema dentro del <think> rompe el razonamiento. vLLM lo resuelve haciendo que el motor de structured output (xgrammar) use el end_token_id del razonador para saltarse la restricción mientras dura el bloque y aplicarla solo a la respuesta final (vLLM · Reasoning Outputs). Si montas esto a mano en otro motor, recuérdalo: primero deja pensar, luego impón el formulario. Enlaza con structured output.


Arquitectura de referencia

Sobre el cluster de ejemplo del blog —un nodo 4×H100 SXM (80 GB, NVLink)— una topología sensata para servir razonamiento sin arruinar el SLO:

  1. Clasificador de dificultad barato delante (un modelo pequeño o reglas) que decide ruta. La mayoría del tráfico no necesita pensar.
  2. Ruta rápida (non-think): el mismo modelo híbrido con razonamiento desactivado. TTFT bajo, coste predecible.
  3. Ruta de razonamiento (think): razonamiento activado con thinking_token_budget por defecto (p. ej. 1–2k tokens) y posibilidad de subirlo por petición para los casos de verdad difíciles.
  4. KV en FP8 en el motor de la ruta de razonamiento, y métricas de longitud de razonamiento por petición exportadas a tu observabilidad (instrumentar vLLM con OTel).

Para prototipar este routing fuera del cluster, una RTX 5090 (Blackwell, 32 GB) sirve un modelo de razonamiento de 7–14B y te deja validar parsers, presupuestos y separación reasoning_content/content antes de tocar las H100. No esperes servir 32B en think a concurrencia alta en una tarjeta de consumo: el KV del razonamiento se come los 32 GB enseguida.

El dimensionamiento parte, como siempre, de un SLO; la diferencia es que ahora el “tamaño de respuesta” de tu capacity planning debe contar el sucio, no solo la respuesta visible.


Pitfalls operativos (y escepticismo honesto)

  1. Fugar el reasoning_content. Si el gateway no lo separa, acabas mostrando o logueando el folio de sucio —que puede contener tanteos incorrectos, datos sensibles o lenguaje que no quieres en tu UI. Sepáralo siempre en el L7.
  2. Servir razonamiento “por si acaso”. El overthinking es real y a veces baja la precisión. No actives think por defecto: actívalo por ruta, con presupuesto.
  3. Olvidar el KV. El error más común: dimensionar concurrencia con la longitud de la respuesta visible. El KV lo dicta la secuencia total, razonamiento incluido. Mide tokens de razonamiento p50/p95 por endpoint.
  4. Prefix caching como bala de plata. En modelos pequeños puede empeorar, y en cualquier caso no toca el decode, que es donde se va el coste del razonamiento.
  5. Asumir delimitadores universales. R1, Qwen3 y gpt-oss no comparten estructura de razonamiento. Usa el --reasoning-parser correcto por familia y prueba el streaming (el parser tiene que separar bien token a token).
  6. Creer que más cómputo = más inteligencia. El estado del arte (s1, short-m@k, “When More Thinking Hurts”) apunta a lo contrario en muchos casos: hay un codo y operar más allá es quemar vatios. El test-time compute es una herramienta con rendimientos decrecientes —y a veces negativos—, no una palanca lineal.

Una nota de prudencia para junio de 2026: el campo del control de razonamiento (budget forcing, compresión de KV específica, early-exit del pensamiento) se mueve rápido y casi todo es muy reciente. Las cifras concretas —el 113×, el 34,5 %, los 9 GB— dependen de modelo, tarea y configuración; tómalas como orden de magnitud para diseñar, no como constantes. Mide en tu carga antes de comprometer SLOs.


Cierre

Servir un modelo de razonamiento es servir un modelo cuyo coste por petición lo decides tú con el presupuesto de pensamiento, no el catálogo. La cadena va: enruta por dificultad → desactiva think donde no aporta → pon thinking_token_budget por defecto en la ruta que piensa → cuantiza el KV a FP8 → mide la longitud de razonamiento como una métrica de primera clase. Hazlo, y el razonamiento se convierte en una capacidad que pagas solo cuando compra precisión. No lo hagas, y tu cluster servirá la quinta parte de usuarios mientras el modelo escribe folios de sucio que nadie va a leer.

Fuentes