Phase 11 - Lesson 02

Few-Shot, Chain-of-Thought, Tree-of-Thought

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Decirle a un modelo qué hacer es prompting. Mostrarle cómo pensar es ingeniería. La diferencia entre el 78% y el 91% de precisión en el mismo modelo, la misma tarea y los mismos datos no se debe a un modelo mejor. Se debe a una mejor estrategia de razonamiento.

Tipo: Build Idiomas: Python Prerrequisitos: Lección 11.01 (Ingeniería de Prompts) Tiempo: ~45 minutos

Objetivos de Aprendizaje

  • Implementar few-shot prompting seleccionando y formateando demostraciones de ejemplos que maximicen la precisión de la tarea
  • Aplicar el razonamiento de cadena de pensamiento (CoT) para mejorar la precisión en problemas de múltiples pasos, como problemas matemáticos de texto
  • Construir un prompt de árbol de pensamiento (Tree-of-Thought) que explore múltiples caminos de razonamiento y seleccione el mejor
  • Medir la mejora de precisión entre zero-shot vs few-shot vs CoT en un benchmark estándar

El Problema

Construyes una aplicación de tutoría de matemáticas. Tu prompt dice: "Resuelve este problema matemático". El GPT-5 lo hace bien el 94% de las veces en GSM8K, el benchmark estándar de matemáticas de primaria. Crees que ya alcanzaste el límite. No es así: la cadena de pensamiento (chain-of-thought) todavía añade de 3 a 4 puntos.

Agrega cinco palabras — "Pensemos paso a paso" — y la precisión sube al 91%. Agrega unos pocos ejemplos resueltos y llega al 95%. El mismo modelo. La misma temperatura. El mismo costo de API. La única diferencia es que le diste papel de borrador al modelo.

Esto no es un truco. Es cómo funciona el razonamiento. Los humanos no resuelven problemas de múltiples pasos en un solo salto mental. Los transformers tampoco. Cuando obligas a un modelo a generar tokens intermedios, esos tokens se convierten en parte del contexto para el siguiente token. Cada paso de razonamiento alimenta al siguiente. El modelo literalmente calcula su camino hacia la respuesta.

Pero "pensar paso a paso" es el comienzo, no el final. ¿Qué pasaría si seleccionaras cinco caminos de razonamiento y realizaras una votación por mayoría? ¿Qué pasaría si dejaras que el modelo explorara un árbol de posibilidades, evaluando y podando ramas? ¿Qué pasaría si intercalaras el razonamiento con el uso de herramientas? Estos no son casos hipotéticos. Son técnicas publicadas con mejoras medidas, y las construirás todas en esta lección.

El Concepto

Zero-Shot vs Few-Shot: Cuando los Ejemplos Superan a las Instrucciones

El prompt zero-shot le da al modelo una tarea y nada más. El prompt few-shot le da ejemplos primero.

Wei et al. (2022) midieron esto en 8 benchmarks. Para tareas simples como la clasificación de opiniones (sentiment classification), zero-shot y few-shot tuvieron un rendimiento con una diferencia del 2% entre si. Para tareas complejas como aritmética de varios pasos y razonamiento simbólico, few-shot mejoró la precisión en un 10-25%.

La intuición: los ejemplos son instrucciones comprimidas. En lugar de describir el formato de salida, lo muestras. En lugar de explicar el proceso de razonamiento, lo demuestras. El modelo coincide con los patrones de los ejemplos de manera más confiable que al interpretar instrucciones abstractas.

graph TD
    subgraph Comparison["Zero-Shot vs Few-Shot"]
        direction LR
        Z["Zero-Shot\n'Clasifica esta reseña'\nEl modelo adivina el formato\n78% en GSM8K"]
        F["Few-Shot\n'Aquí hay 3 ejemplos...\nAhora clasifica esta reseña'\nEl modelo coincide con el patrón\n85% en GSM8K"]
    end

    Z ~~~ F

    style Z fill:#1a1a2e,stroke:#e94560,color:#fff
    style F fill:#1a1a2e,stroke:#51cf66,color:#fff

Cuándo gana few-shot: tareas sensibles al formato, clasificación, extracción estructurada, jerga específica del dominio, cualquier tarea en la que el modelo necesite coincidir con un patrón específico.

Cuándo gana zero-shot: preguntas de hechos simples, tareas creativas donde los ejemplos limitan la creatividad, tareas en las que encontrar buenos ejemplos es más difícil que escribir buenas instrucciones.

Selección de Ejemplos: Los Similares Superan a los Aleatorios

No todos los ejemplos son iguales. Elegir ejemplos similares a la entrada de destino supera a la selección aleatoria por un 5-15% en tareas de clasificación (Liu et al., 2022). Tres principios:

  1. Similitud semántica: elije los ejemplos más cercanos a la entrada en el espacio de incrustación (embedding space)
  2. Diversidad de etiquetas: cubre todas las categorías de salida en tus ejemplos
  3. Coincidencia de dificultad: coincide con el nivel de complejidad del problema de destino

La cantidad óptima de ejemplos para la mayoría de las tareas es de 3 a 5. Por debajo de 3, el modelo no tiene suficiente señal para extraer el patrón. Por encima de 5, se llega a un rendimiento decreciente y se desperdician tokens de la ventana de contexto. Para clasificación con muchas etiquetas, usa un ejemplo por etiqueta.

Cadena de Pensamiento (Chain-of-Thought): Dando Papel de Borrador a los Modelos

El prompt de cadena de pensamiento (CoT) fue introducido por Wei et al. (2022) en Google Brain. La idea es simple: en lugar de pedirle al modelo solo la respuesta, pídele que muestre primero sus pasos de razonamiento.

graph LR
    subgraph Standard["Prompting Estándar"]
        Q1["P: Roger tiene 5 bolas.\nCompra 2 latas de 3.\n¿Cuántas bolas?"] --> A1["R: 11"]
    end

    subgraph CoT["Prompting de Cadena de Pensamento"]
        Q2["P: Roger tiene 5 bolas.\nCompra 2 latas de 3.\n¿Cuántas bolas?"] --> R2["Roger comienza con 5.\n2 latas de 3 = 6.\n5 + 6 = 11."] --> A2["R: 11"]
    end

    style Q1 fill:#1a1a2e,stroke:#e94560,color:#fff
    style A1 fill:#1a1a2e,stroke:#e94560,color:#fff
    style Q2 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style R2 fill:#1a1a2e,stroke:#ffa500,color:#fff
    style A2 fill:#1a1a2e,stroke:#51cf66,color:#fff

¿Por qué funciona esto mecánicamente? Cada token que genera un transformer se convierte en contexto para el siguiente token. Sin CoT, el modelo debe comprimir todo el razonamiento en el estado oculto de una sola pasada hacia adelante (forward pass). Con CoT, el modelo externaliza los cálculos intermedios en forma de tokens. Cada token de razonamiento extiende la profundidad de cálculo efectiva.

Benchmarks GSM8K (matemáticas de primaria, 8.5 mil problemas):

Modelo Zero-Shot Zero-Shot CoT Few-Shot CoT
GPT-4o 78% 91% 95%
GPT-5 94% 97% 98%
o4-mini (razonamiento) 97%
Claude Opus 4.7 93% 97% 98%
Gemini 3 Pro 92% 96% 98%
Llama 4 70B 80% 89% 94%
DeepSeek-V3.1 89% 94% 96%

Nota sobre modelos de razonamiento. Los modelos como la serie-o de OpenAI (o3, o4-mini) y DeepSeek-R1 ejecutan internamente la cadena de pensamiento antes de emitir su respuesta. Agregar "Pensemos paso a paso" a un modelo de razonamiento es redundante y, a veces, contraproducente — ya lo han hecho.

Dos variantes de CoT:

Zero-shot CoT: agrega "Pensemos paso a paso" al prompt. No se necesitan ejemplos. Kojima et al. (2022) demostraron que esta simple frase mejora la precisión en tareas de aritmética, sentido común y razonamiento simbólico.

Few-shot CoT: proporciona ejemplos que incluyan pasos de razonamiento. Es más efectivo que zero-shot CoT porque el modelo ve el formato exacto de razonamiento que esperas.

Cuándo perjudica el CoT: recuperación de hechos simples ("¿Cuál es la capital de Francia?"), clasificación de un solo paso, tareas donde la velocidad importa más que la precisión. CoT añade una sobrecarga de razonamiento de 50 a 200 tokens por consulta. Para tareas de alto rendimiento (throughput) y baja complejidad, esto es un desperdicio de costo.

Autoconsistencia (Self-Consistency): Muestrear Varios, Votar una Vez

Wang et al. (2023) presentaron la autoconsistencia. La idea clave: una sola ruta de CoT puede contener errores de razonamiento. Pero si muestras N rutas de razonamiento independientes (usando temperature > 0) y realizas una votación por mayoría sobre la respuesta final, los errores se cancelan.

graph TD
    P["Problema: 'Una tienda tiene 48 manzanas.\nVenden 1/3 el lunes\ny 1/4 del resto el martes.\n¿Cuántas quedan?'"]

    P --> Path1["Camino 1: 48 - 16 = 32\n32 - 8 = 24\nRespuesta: 24"]
    P --> Path2["Camino 2: 1/3 de 48 = 16\nRestante: 32\n1/4 de 32 = 8\n32 - 8 = 24\nRespuesta: 24"]
    P --> Path3["Camino 3: 48/3 = 16 vendidas\n48 - 16 = 32\n32/4 = 8 vendidas\n32 - 8 = 24\nRespuesta: 24"]
    P --> Path4["Camino 4: Vende 1/3: 48 - 12 = 36\nVende 1/4: 36 - 9 = 27\nRespuesta: 27"]
    P --> Path5["Camino 5: Lunes: 48 * 2/3 = 32\nMartes: 32 * 3/4 = 24\nRespuesta: 24"]

    Path1 --> V["Voto de la Mayoría\n24: 4 votos\n27: 1 voto\nFinal: 24"]
    Path2 --> V
    Path3 --> V
    Path4 --> V
    Path5 --> V

    style P fill:#1a1a2e,stroke:#ffa500,color:#fff
    style Path1 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style Path2 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style Path3 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style Path4 fill:#1a1a2e,stroke:#e94560,color:#fff
    style Path5 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style V fill:#1a1a2e,stroke:#51cf66,color:#fff

La autoconsistencia mejoró la precisión de GSM8K del 56,5% (CoT único) al 74,4% con N=40 en los experimentos originales de PaLM 540B. En GPT-5, la mejora es pequeña (97% a 98%) porque la precisión base ya está saturada. La técnica brilla más en modelos con un 60-85% de precisión base de CoT, el punto óptimo donde los errores de una sola ruta son comunes pero no sistemáticos. Para modelos de razonamiento (serie-o, R1), la autoconsistencia está integrada en el muestreo interno.

La compensación: N muestras significa N veces el costo y la latência de la API. En la práctica, N=5 captura la mayor parte del beneficio. N=3 es el mínimo para una votación significativa. N > 10 tiene rendimientos decrecientes para la mayoría de las tareas.

Árbol de Pensamiento (Tree-of-Thought): Exploración por Ramificación

Yao et al. (2023) introdujeron Tree-of-Thought (ToT). Mientras que CoT sigue un único camino lineal de razonamiento, ToT explora múltiples ramas y evalúa cuáles son las más prometedoras antes de continuar.

graph TD
    Root["Problema"] --> B1["Pensamento 1a"]
    Root --> B2["Pensamento 1b"]
    Root --> B3["Pensamento 1c"]

    B1 --> E1["Evaluación: 0.8"]
    B2 --> E2["Evaluación: 0.3"]
    B3 --> E3["Evaluación: 0.9"]

    E1 -->|Continuar| B1a["Pensamento 2a"]
    E1 -->|Continuar| B1b["Pensamento 2b"]
    E3 -->|Continuar| B3a["Pensamento 2a"]
    E3 -->|Continuar| B3b["Pensamento 2b"]

    E2 -->|Podar| X["X"]

    B1a --> E4["Evaluación: 0.7"]
    B3a --> E5["Evaluación: 0.95"]

    E5 -->|Mejor camino| Final["Solución"]

    style Root fill:#1a1a2e,stroke:#ffa500,color:#fff
    style E2 fill:#1a1a2e,stroke:#e94560,color:#fff
    style X fill:#1a1a2e,stroke:#e94560,color:#fff
    style E5 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style Final fill:#1a1a2e,stroke:#51cf66,color:#fff
    style B1 fill:#1a1a2e,stroke:#808080,color:#fff
    style B2 fill:#1a1a2e,stroke:#808080,color:#fff
    style B3 fill:#1a1a2e,stroke:#808080,color:#fff
    style B1a fill:#1a1a2e,stroke:#808080,color:#fff
    style B1b fill:#1a1a2e,stroke:#808080,color:#fff
    style B3a fill:#1a1a2e,stroke:#808080,color:#fff
    style B3b fill:#1a1a2e,stroke:#808080,color:#fff
    style E1 fill:#1a1a2e,stroke:#808080,color:#fff
    style E3 fill:#1a1a2e,stroke:#808080,color:#fff
    style E4 fill:#1a1a2e,stroke:#808080,color:#fff

ToT tiene tres componentes:

  1. Generación de pensamientos: producir múltiples candidatos para los siguientes pasos
  2. Evaluación del estado: puntuar cada candidato (se puede usar el propio LLM como evaluador)
  3. Algoritmo de búsqueda: BFS (búsqueda en anchura) o DFS (búsqueda en profundidad) a través del árbol, podando las ramas de baja puntuación

En la tarea del Game of 24 (combinar 4 números usando aritmética para obtener 24), GPT-4 con prompting estándar resuelve el 7,3% de los problemas. Con CoT, el 4,0% (CoT en realidad perjudica aquí porque el espacio de búsqueda es amplio). Con ToT, el 74%.

ToT es costoso. Cada nodo en el árbol requiere una llamada de LLM. Un árbol con un factor de ramificación de 3 y una profundidad de 3 requiere hasta 39 llamadas de LLM. Úsalo solo para problemas donde el espacio de búsqueda es grande pero evaluable — planificación, resolución de acertijos, resolución creativa de problemas con restricciones.

ReAct: Pensar + Actuar

Yao et al. (2022) combinaron trazas de razonamiento con acciones. El modelo alterna entre pensar (generar razonamiento) y actuar (llamar a herramientas, buscar, computar).

graph LR
    Q["Pregunta:\n¿Cuál es la\npoblación del\npaís donde\nse encuentra\nla Eiffel Tower?"]
    T1["Pensamento: Necesito\nencontrar qué país\ntiene la Eiffel Tower"]
    A1["Acción: buscar\n'ubicación de la Eiffel Tower'"]
    O1["Observación:\nParís, Francia"]
    T2["Pensamento: Agora preciso\nla población de Francia"]
    A2["Acción: buscar\n'población de Francia 2024'"]
    O2["Observación:\n68.4 millones"]
    T3["Pensamento: Tengo\nla respuesta"]
    F["Respuesta:\n68.4 millones"]

    Q --> T1 --> A1 --> O1 --> T2 --> A2 --> O2 --> T3 --> F

    style Q fill:#1a1a2e,stroke:#ffa500,color:#fff
    style T1 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style A1 fill:#1a1a2e,stroke:#e94560,color:#fff
    style O1 fill:#1a1a2e,stroke:#808080,color:#fff
    style T2 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style A2 fill:#1a1a2e,stroke:#e94560,color:#fff
    style O2 fill:#1a1a2e,stroke:#808080,color:#fff
    style T3 fill:#1a1a2e,stroke:#51cf66,color:#fff
    style F fill:#1a1a2e,stroke:#51cf66,color:#fff

ReAct supera a CoT puro en tareas intensivas en conocimiento porque puede fundamentar su razonamiento en datos reales. En HotpotQA (preguntas y respuestas de múltiples saltos), ReAct con GPT-4 logra un 35,1% de coincidencia exacta frente al 29,4% de CoT solo. El poder real es que los errores de razonamiento se corrigen mediante observaciones — el modelo puede actualizar su plan a mitad de la ejecución.

ReAct es la base de los agentes de IA modernos. Cada framework de agentes (LangChain, CrewAI, AutoGen) implementa alguna variante del ciclo Pensamiento-Acción-Observación (Thought-Action-Observation). Construirás agentes completos en la Fase 14. Esta lección cubre el patrón de prompting.

Prompting Estructurado: Etiquetas XML, Delimitadores, Encabezados

A medida que los prompts se vuelven complejos, la estructura evita que el modelo confunda las secciones. Tres enfoques:

Etiquetas XML (funciona mejor con Claude, sólido en todas partes):

<context>
You are reviewing a pull request.
The codebase uses TypeScript and React.
</context>

<task>
Review the following diff for bugs, security issues, and style violations.
</task>

<diff>
{diff_content}
</diff>

<output_format>
List each issue with: file, line, severity (critical/warning/info), description.
</output_format>

Encabezados Markdown (universal):

## Role
Senior security engineer at a fintech company.

## Task
Analyze this API endpoint for vulnerabilities.

## Input
{api_code}

## Rules
- Focus on OWASP Top 10
- Rate each finding: critical, high, medium, low
- Include remediation steps

Delimitadores (mínimo pero efectivo):

---INPUT---
{user_text}
---END INPUT---

---INSTRUCTIONS---
Summarize the above in 3 bullet points.
---END INSTRUCTIONS---

Encadenamiento de Prompts (Prompt Chaining): Descomposición Secuencial

Algunas tareas son demasiado complejas para un solo prompt. El encadenamiento de prompts las divide en pasos, donde la salida de un prompt se convierte en la entrada del siguiente.

graph LR
    I["Entrada Bruta"] --> P1["Prompt 1:\nExtraer\nhechos clave"]
    P1 --> O1["Hechos"]
    O1 --> P2["Prompt 2:\nAnalizar\nhechos"]
    P2 --> O2["Análisis"]
    O2 --> P3["Prompt 3:\nGenerar\nrecomendación"]
    P3 --> F["Salida Final"]

    style I fill:#1a1a2e,stroke:#808080,color:#fff
    style P1 fill:#1a1a2e,stroke:#e94560,color:#fff
    style O1 fill:#1a1a2e,stroke:#ffa500,color:#fff
    style P2 fill:#1a1a2e,stroke:#e94560,color:#fff
    style O2 fill:#1a1a2e,stroke:#ffa500,color:#fff
    style P3 fill:#1a1a2e,stroke:#e94560,color:#fff
    style F fill:#1a1a2e,stroke:#51cf66,color:#fff

El encadenamiento supera al prompt único por tres razones:

  1. Cada paso es más sencillo: el modelo maneja una tarea enfocada en lugar de lidiar con todo a la vez
  2. Las saídas intermedias se pueden inspeccionar: puedes validar y corregir entre pasos
  3. Diferentes pasos pueden usar diferentes modelos: usa un modelo económico para la extracción y uno costoso para el razonamiento

Comparación de Rendimiento

Técnica Ideal Para Precisión GSM8K (GPT-5) Llamadas de API Sobrecarga de Tokens Complejidad
Zero-Shot Tareas simples 94% 1 Ninguna Trivial
Few-Shot Coincidencia de formato 96% 1 200-500 tokens Baja
Zero-Shot CoT Impulso rápido de razonamiento 97% 1 50-200 tokens Trivial
Few-Shot CoT Precisión máxima en llamada única 98% 1 300-600 tokens Baja
Autoconsistencia (N=5) Razonamiento de alto riesgo 98.5% 5 Costo de tokens 5x Media
Modelo de razonamiento (o4-mini) Reemplazo directo de CoT 97% 1 oculto (2-10x interno) Trivial
Tree-of-Thought Problemas de búsqueda/planificación N/A (74% en Game of 24) 10-40+ Costo de tokens 10-40x Alta
ReAct Razonamiento fundamentado en conocimiento N/A (35.1% en HotpotQA) 3-10+ Variable Alta
Encadenamiento de Prompts Tareas complejas de varios pasos 96% (pipeline) 2-5 Costo de tokens 2-5x Media

La técnica correcta depende de tres factores: el requisito de precisión, el límite de latencia y la tolerancia al costo. Para la mayoría de los sistemas en producción, CoT de pocos ejemplos con un fallback de autoconsistencia de 3 muestras cubre el 90% de los casos de uso.

Implementación

Construiremos un resolvedor de problemas matemáticos que combina prompting de pocos ejemplos (few-shot prompting), razonamiento de cadena de pensamiento (chain-of-thought) y votación de autoconsistencia (self-consistency) en un único pipeline. Luego agregaremos tree-of-thought para problemas difíciles.

La implementación completa se encuentra en code/advanced_prompting.py. Aquí están los componentes clave.

Paso 1: Almacén de Ejemplos Few-Shot

El primer componente gestiona los ejemplos de pocos disparos (few-shot) y selecciona los más relevantes para un problema dado.

GSM8K_EXAMPLES = [
    {
        "question": "Janet's ducks lay 16 eggs per day. She eats three for breakfast every morning and bakes muffins for her friends every day with four. She sells every egg at the farmers' market for 
. How much does she make every day at the farmers' market?", "reasoning": "Janet's ducks lay 16 eggs per day. She eats 3 and bakes 4, using 3 + 4 = 7 eggs. So she has 16 - 7 = 9 eggs left. She sells each for , so she makes 9 * 2 =
8 per day.", "answer": "18" }, ... ]

Cada ejemplo consta de tres partes: la pregunta, la cadena de razonamiento y la respuesta final. La cadena de razonamiento é lo que transforma un ejemplo few-shot regular en un ejemplo few-shot de CoT.

Paso 2: Construtor de Prompts Chain-of-Thought

El constructor de prompts reúne un mensaje del sistema, ejemplos few-shot con cadenas de razonamiento y la pregunta objetivo en un solo prompt.

def build_cot_prompt(question, examples, num_examples=3):
    system = (
        "You are a math problem solver. "
        "For each problem, show your step-by-step reasoning, "
        "then give the final numerical answer on the last line "
        "in the format: 'The answer is [number]'."
    )

    example_text = ""
    for ex in examples[:num_examples]:
        example_text += f"Q: {ex['question']}\n"
        example_text += f"A: {ex['reasoning']} The answer is {ex['answer']}.\n\n"

    user = f"{example_text}Q: {question}\nA:"
    return system, user

La restricción de formato ("The answer is [number]") es crítica. Sin ella, la autoconsistencia no puede extraer ni comparar respuestas entre muestras.

Paso 3: Votación de Autoconsistencia

Muestrea N caminos de razonamiento y toma la respuesta mayoritaria.

def self_consistency_solve(question, examples, client, model, n_samples=5):
    system, user = build_cot_prompt(question, examples)

    answers = []
    reasonings = []
    for _ in range(n_samples):
        response = client.chat.completions.create(
            model=model,
            messages=[
                {"role": "system", "content": system},
                {"role": "user", "content": user}
            ],
            temperature=0.7
        )
        text = response.choices[0].message.content
        reasonings.append(text)
        answer = extract_answer(text)
        if answer is not None:
            answers.append(answer)

    vote_counts = Counter(answers)
    best_answer = vote_counts.most_common(1)[0][0] if vote_counts else None
    confidence = vote_counts[best_answer] / len(answers) if best_answer else 0

    return best_answer, confidence, reasonings, vote_counts

La temperatura de 0.7 es importante. A una temperatura de 0.0, las N muestras serían idénticas, lo que anula el propósito. Necesitas suficiente aleatoriedad para obtener diversos caminos de razonamiento, pero no tanta como para que el modelo produzca sinsentidos.

Paso 4: Resolvedor Tree-of-Thought

Para problemas donde el razonamiento lineal falla, ToT explora múltiples enfoques y evalúa qué dirección es más prometedora.

def tree_of_thought_solve(question, client, model, breadth=3, depth=3):
    thoughts = generate_initial_thoughts(question, client, model, breadth)
    scored = [(t, evaluate_thought(t, question, client, model)) for t in thoughts]
    scored.sort(key=lambda x: x[1], reverse=True)

    for current_depth in range(1, depth):
        next_thoughts = []
        for thought, score in scored[:2]:
            extensions = extend_thought(thought, question, client, model, breadth)
            for ext in extensions:
                ext_score = evaluate_thought(ext, question, client, model)
                next_thoughts.append((ext, ext_score))
        scored = sorted(next_thoughts, key=lambda x: x[1], reverse=True)

    best_thought = scored[0][0] if scored else ""
    return extract_answer(best_thought), best_thought

El evaluador es en sí mismo una llamada de LLM. Le preguntas al modelo: "En una escala de 0.0 a 1.0, ¿qué tan prometedor es este camino de razonamiento para resolver el problema?" Esta es la idea clave de ToT: el modelo evalúa sus propias soluciones parciales.

Paso 5: Pipeline Completo

El pipeline combina todas las técnicas con una estrategia de escalada.

def solve_with_escalation(question, examples, client, model):
    system, user = build_cot_prompt(question, examples)
    single_response = call_llm(client, model, system, user, temperature=0.0)
    single_answer = extract_answer(single_response)

    sc_answer, confidence, _, _ = self_consistency_solve(
        question, examples, client, model, n_samples=5
    )

    if confidence >= 0.8:
        return sc_answer, "self_consistency", confidence

    tot_answer, _ = tree_of_thought_solve(question, client, model)
    return tot_answer, "tree_of_thought", None

La lógica de escalamiento: intentar primero el camino barato (CoT único). Si la confianza de autoconsistencia es inferior a 0.8 (menos de 4 de 5 muestras coinciden), escalar a ToT. Esto equilibra costo y precisión: la mayoría de los problemas se resuelven de forma económica, los problemas difíciles obtienen más cómputo.

Cómo Usarlo

Con LangChain

LangChain proporciona soporte integrado para plantillas de prompts y análisis sintáctico de salida (parsers) que simplifican los patrones few-shot y CoT:

from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI

example_prompt = PromptTemplate(
    input_variables=["question", "reasoning", "answer"],
    template="Q: {question}\nA: {reasoning} The answer is {answer}."
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    suffix="Q: {input}\nA: Let's think step by step.",
    input_variables=["input"]
)

llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
chain = few_shot_prompt | llm
result = chain.invoke({"input": "If a train travels 120 km in 2 hours..."})

LangChain también cuenta con clases ExampleSelector para la selección por similitud semántica:

from langchain_core.example_selectors import SemanticSimilarityExampleSelector
from langchain_openai import OpenAIEmbeddings

selector = SemanticSimilarityExampleSelector.from_examples(
    examples,
    OpenAIEmbeddings(),
    k=3
)

Con DSPy

DSPy trata as estrategias de prompt como módulos optimizables. En lugar de crear prompts de CoT a mano, defines una firma (signature) y dejas que DSPy optimice el prompt:

import dspy

dspy.configure(lm=dspy.LM("openai/gpt-4o", temperature=0.7))

class MathSolver(dspy.Module):
    def __init__(self):
        self.solve = dspy.ChainOfThought("question -> answer")

    def forward(self, question):
        return self.solve(question=question)

solver = MathSolver()
result = solver(question="Janet's ducks lay 16 eggs per day...")

El módulo ChainOfThought de DSPy agrega automáticamente trazas de razonamiento. La función dspy.majority implementa la autoconsistencia:

result = dspy.majority(
    [solver(question=q) for _ in range(5)],
    field="answer"
)

Comparación: Desde Cero vs Frameworks

Característica Desde Cero (esta lección) LangChain DSPy
Control sobre el formato del prompt Total Basado en plantillas Automático
Autoconsistencia Votación manual Manual Integrada (dspy.majority)
Selección de ejemplos Lógica personalizada ExampleSelector dspy.BootstrapFewShot
Tree-of-Thought Búsqueda en árbol personalizada Community chains No integrado
Optimización de prompts Iteración manual Manual Compilación automática
Ideal para Aprendizaje, pipelines personalizados Flujos de trabajo estándar Investigación, optimización

Conclusión

Esta lección produce dos artefactos.

1. Prompt de Cadena de Razonamiento (outputs/prompt-reasoning-chain.md): una plantilla de prompt lista para producción para few-shot CoT con autoconsistencia. Conecta tus ejemplos y el dominio de tu problema.

2. Habilidade de Seleção de Patrones CoT (outputs/skill-cot-patterns.md): un marco de decisión para elegir la técnica de razonamiento adecuada según el tipo de tarea, los requisitos de precisión y las limitaciones de costo.

Ejercicios

  1. Mide la brecha: Toma 10 problemas GSM8K. Resuelve cada uno con zero-shot, few-shot, zero-shot CoT y few-shot CoT. Registra la precisión para cada uno. ¿Qué técnica le da el mayor impulso a tu modelo?

  2. Experimento de selección de ejemplos: Para los mismos 10 problemas, compara la selección aleatoria de ejemplos frente a ejemplos similares elegidos a mano. Mide la diferencia de precisión. ¿En qué punto importa más la calidad del ejemplo que la cantidad de ejemplos?

  3. Curva de costo de autoconsistencia: Ejecuta la autoconsistencia con N=1, 3, 5, 7, 10 en 20 problemas GSM8K. Grafica precisión vs costo (tokens totales). ¿Dónde está el "codo" de la curva para tu modelo?

  4. Construye un ciclo ReAct: Extiende el pipeline con una herramienta de calculadora. Cuando el modelo genere una expresión matemática, ejecútala con eval() de Python (en un entorno seguro) y devuelve el resultado. Mide si el razonamiento basado en herramientas supera al CoT puro.

  5. ToT para tareas creativas: Adapta el resolvedor Tree-of-Thought para una tarea de escritura creativa: "Escribe una historia de 6 palabras que sea divertida y triste a la vez". Usa el LLM como evaluador. ¿La exploración por ramificación produce mejores resultados creativos que la generación en un solo intento (single-shot)?

Términos Clave

Término Lo que dice la gente Lo que realmente significa
Few-shot prompting "Dale algunos ejemplos" Incluir demostraciones de entrada-salida en el prompt para anclar el formato de salida y el comportamiento del modelo
Chain-of-Thought "Haz que piense paso a paso" Provocar tokens de razonamiento intermedio que extiendan el cómputo efectivo del modelo antes de producir una respuesta final
Autoconsistencia (Self-Consistency) "Ejecútalo varias veces" Muestrear N rutas de razonamiento diversas a una temperatura > 0 y seleccionar la respuesta final más común por votación mayoritaria
Tree-of-Thought "Deja que explore opciones" Búsqueda estructurada sobre ramas de razonamiento donde cada solución parcial se evalúa y solo se expanden las rutas prometedoras
ReAct "Razonamiento + uso de herramientas" Intercalar trazas de razonamiento con acciones externas (búsqueda, cómputo, llamadas de API) en un ciclo de Pensamiento-Acción-Observación
Encadenamiento de prompts (Prompt chaining) "Divídelo en pasos" Descomponer una tarea compleja en prompts secuenciales donde cada salida alimenta la siguiente entrada
Zero-shot CoT "Solo agrega 'piensa paso a paso'" Agregar una frase desencadenante de razonamiento a un prompt sin ningún ejemplo, confiando en la capacidad latente de razonamiento del modelo

Lecturas Adicionales

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).