Chain of Thought (CoT): Mecanismos de inferencia y tokens de razonamiento oculto

Análisis técnico de Chain of Thought (CoT) y la integración de tokens de pensamiento en el proceso de inferencia. Se examina la formulación probabilística de pasos intermedios, el impacto en la latencia de inferencia y la transición de CoT vía prompting a arquitecturas con razonamiento latente.

Los Large Language Models (LLMs) estándar operan bajo un mecanismo de predicción greedy o de muestreo sobre la distribución del siguiente token, optimizando la verosimilitud inmediata. Este enfoque es eficiente para tareas semánticas directas, pero falla en problemas que requieren razonamiento simbólico, aritmética o lógica de múltiples pasos. El modelo intenta mapear $Input \rightarrow Output$ directamente, colapsando la complejidad computacional necesaria en un solo paso de generación.

Chain of Thought (CoT) desacopla este proceso introduciendo pasos de razonamiento intermedios ($z$) entre la entrada ($x$) y la salida final ($y$). El estado del arte ha evolucionado desde el prompt engineering (Wei et al., 2022) hacia modelos de razonamiento nativo (como la serie o1 de OpenAI o arquitecturas similares), donde estos pasos intermedios no siempre son visibles para el usuario final, sino que se procesan como "tokens de pensamiento" ocultos o estados latentes antes de emitir la respuesta final. Esto permite al modelo dedicar tiempo de cómputo (inference-time compute) para refinar la lógica antes de la generación del output.

El siguiente diagrama ilustra la diferencia fundamental entre ambos enfoques de inferencia:


Fundamentos matemáticos

En un modelo de lenguaje estándar, la probabilidad de una secuencia de salida $y$ dada una entrada $x$ se factoriza como:

$$P(y|x) = \prod_{t=1}^{T} P(y_t | x, y_{

Chain of Thought introduce una variable latente o explicita $z$ (la cadena de pensamiento). El objetivo es maximizar la probabilidad de la respuesta correcta marginalizando sobre las posibles cadenas de razonamiento:

$$P(y|x) = \sum_{z} P(y, z | x) = \sum_{z} P(y|z, x) P(z|x)$$

En la práctica, debido a la inviabilidad de calcular la suma sobre todo el espacio $z$, se aproxima buscando una cadena $z$ óptima tal que:

$$\hat{y} = \underset{y}{\text{argmax}} \ P(y | \hat{z}, x) \quad \text{donde} \quad \hat{z} \sim P(z|x)$$

En modelos de razonamiento con "tokens ocultos", el modelo genera $z$ en un espacio de embedding o mediante tokens especiales de control que no se decodifican al usuario, aumentando la profundidad computacional del grafo de computación antes de la salida final. La función de pérdida durante el entrenamiento (o fine-tuning con RLHF) penaliza no solo la incorrección de $y$, sino la inconsistencia lógica en $z$.


Implementación práctica

La implementación de CoT puede realizarse vía prompting en modelos estándar o invocando modelos especializados. A continuación, se muestra una rutina en Python para estructurar CoT explícito y parsear la lógica separada de la respuesta final, simulando el comportamiento de separación de reasoning traces.

import re
from typing import Optional, Dict

class CoTInference:
    def __init__(self, client, model_id: str):
        self.client = client
        self.model = model_id
        
        # System prompt diseñado para forzar la estructura de pensamiento
        self.sys_prompt = (
            "Resuelve el problema paso a paso. "
            "Debes encerrar tu razonamiento dentro de las etiquetas <thinking>...</thinking>. "
            "La respuesta final debe estar en <answer>...</answer>."
        )

    def generate(self, query: str, temperature: float = 0.2) -> Dict[str, Optional[str]]:
        """
        Ejecuta inferencia forzando la generación de pasos intermedios.
        """
        messages = [
            {"role": "system", "content": self.sys_prompt},
            {"role": "user", "content": query}
        ]

        response = self.client.chat.completions.create(
            model=self.model,
            messages=messages,
            temperature=temperature, # Baja temperatura para estabilidad lógica
            max_tokens=2048
        )
        
        raw_content = response.choices[0].message.content
        return self._parse_output(raw_content)

    def _parse_output(self, content: str) -> Dict[str, Optional[str]]:
        # Extracción vía RegEx de los componentes de razonamiento y respuesta
        thinking_pattern = r"<thinking>(.*?)</thinking>"
        answer_pattern = r"<answer>(.*?)</answer>"
        
        thinking_match = re.search(thinking_pattern, content, re.DOTALL)
        answer_match = re.search(answer_pattern, content, re.DOTALL)
        
        return {
            "reasoning_trace": thinking_match.group(1).strip() if thinking_match else None,
            "final_answer": answer_match.group(1).strip() if answer_match else content,
            "raw": content
        }

# Uso hipotético
# engine = CoTInference(client, "model-v4-reasoning")
# result = engine.generate("Si un tren viaja a...")


Análisis de comportamiento

El uso de CoT altera significativamente las métricas de operación del modelo:

  1. Latencia Lineal vs. Complejidad: La latencia de inferencia ya no es proporcional solo a la longitud de la respuesta esperada, sino a la complejidad del problema. Un "sí" o "no" final puede requerir cientos de tokens de razonamiento ($z$) previos.
  2. Ventana de Contexto: El reasoning trace consume ventana de contexto. En implementaciones de tokens ocultos, esto aumenta el consumo de memoria (KV cache) aunque no se muestre en el output visual.
  3. Faithfulness (Fidelidad): Existe un fenómeno conocido donde el modelo genera una cadena de razonamiento $z$ correcta pero una respuesta $y$ incorrecta, o viceversa (razonamiento alucinatorio que llega a la respuesta correcta por azar). La correlación entre la calidad de $z$ y $y$ no es absoluta en modelos no optimizados específicamente para esto.
  4. Estabilidad Numérica: CoT reduce la varianza en tareas aritméticas, pero aumenta la sensibilidad a la formulación del prompt inicial en modelos zero-shot.

Comparativas o referencias técnicas

Comparación de rendimiento en benchmarks de razonamiento (tipo GSM8K o MATH) y costes asociados:

Enfoque Precisión Lógica Latencia (Time-to-First-Token) Throughput (Tokens/s) Coste Computacional
Standard Inference (Zero-shot) Baja Muy Baja Alto Bajo
Few-Shot CoT Media/Alta Baja Medio Medio (Input tokens extra)
Reasoning Models (Hidden CoT) Muy Alta Alta (Procesamiento oculto) Variable Alto (Inference compute)

Los modelos de razonamiento dedicados superan a los enfoques few-shot en tareas de alta complejidad simbólica, pero introducen un overhead significativo en el tiempo total de respuesta.


Limitaciones y casos donde no conviene usarlo

El uso de CoT es contraproducente en los siguientes escenarios:

  • Tareas de recuperación simple (RAG fáctico): Si la respuesta está explícita en el contexto, forzar un razonamiento paso a paso introduce latencia innecesaria y aumenta el riesgo de alucinación sobre los datos recuperados.
  • Clasificación de baja latencia: En sistemas de routing de intención o análisis de sentimiento en tiempo real, el coste adicional de generar $z$ degrada la experiencia de usuario sin ganancia de accuracy.
  • Limitaciones de Contexto: En interacciones largas, acumular los reasoning traces en el historial de chat satura la ventana de contexto rápidamente, degradando el rendimiento en turnos posteriores.
  • Error Propagation: Un error en los primeros pasos de la cadena $z$ se propaga y condiciona irremediablemente la salida $y$, un fenómeno difícil de corregir sin intervención externa o backtracking.