Program-of-Thought: Cómo los Modelos Pequeños Superan a los Modelos Grandes
La técnica de Chain-of-Thought (CoT) revolucionó la forma en que los modelos de lenguaje resuelven problemas complejos al hacer que “piensen paso a paso”. Pero hay un defecto fundamental: los modelos de lenguaje son terribles en aritmética.
Aquí entra Program-of-Thought (PoT) — una técnica que logra un 12-15% mejor rendimiento que Chain-of-Thought haciendo algo sorprendentemente simple: dejar que los modelos escriban código en lugar de hacer matemáticas.
La Perspectiva Central
El artículo revolucionario “Program of Thoughts Prompting: Disentangling Computation from Reasoning“ revela una idea crítica: el razonamiento y la computación son habilidades diferentes.
Los modelos de lenguaje sobresalen en:
- Comprender problemas
- Planificar estrategias de solución
- Expresar lógica en código
Los modelos de lenguaje tienen dificultades con:
- Aritmética de múltiples dígitos
- Mantener precisión a través de pasos de cálculo
- Evitar errores acumulativos
PoT separa estas preocupaciones: los modelos hacen el razonamiento y escriben código Python, mientras que un runtime determinístico (como unsandbox) ejecuta los cálculos perfectamente.
Chain-of-Thought vs Program-of-Thought
Chain-of-Thought (CoT)
Pregunta: Una tienda tenía 20 manzanas. Vendieron 8, recibieron 15 más,
luego vendieron 12. ¿Cuántas manzanas quedan?
Respuesta CoT:
Déjame pensar paso a paso:
1. Comenzar con 20 manzanas
2. Después de vender 8: 20 - 8 = 12 manzanas
3. Después de recibir 15: 12 + 15 = 27 manzanas
4. Después de vender 12: 27 - 12 = 15 manzanas
Respuesta: 15 manzanas
Problema: El modelo debe realizar aritmética y razonamiento. Los pequeños errores se acumulan.
Program-of-Thought (PoT)
# Pregunta: Una tienda tenía 20 manzanas. Vendieron 8, recibieron 15 más,
# luego vendieron 12. ¿Cuántas manzanas quedan?
def solve():
apples = 20
apples -= 8 # Sold 8
apples += 15 # Received 15
apples -= 12 # Sold 12
return apples
result = solve()
print(f"Remaining apples: {result}")
Ejecución (via unsandbox):
Remaining apples: 15
El modelo se enfoca puramente en comprender y traducir a código. El cálculo se delega a Python.
Por Qué Esto Hace Que los Modelos Pequeños Golpeen Por Encima de Su Peso
Aquí es donde se pone emocionante para implementaciones prácticas:
1. Los Modelos Cuantizados Se Vuelven Viables
Un modelo Llama 3.1 8B cuantizado a 4 bits ejecutándose localmente ahora puede superar a GPT-4 en problemas matemáticos — no porque sea mejor en razonamiento, sino porque no necesita ser bueno en aritmética.
# Incluso un modelo fuertemente cuantizado puede escribir esto correctamente:
def compound_interest(principal, rate, years):
return principal * (1 + rate) ** years
# unsandbox lo ejecuta con precisión perfecta
2. Inferencia Más Rápida, Costos Más Bajos
Las respuestas PoT son típicamente más cortas que las respuestas CoT:
- CoT: ~500 tokens (mostrando todos los pasos de cálculo)
- PoT: ~150 tokens (solo el código)
Ahorro de costos: 70% menos tokens de salida × modelos pequeños más baratos = reducción de costos de 10-20x
3. Resultados Determinísticos y Auditables
A diferencia de CoT donde el modelo podría calcular 127 × 43 diferentemente cada vez, PoT produce:
result = 127 * 43 # Siempre 5461, cada vez
print(result)
Esto es crítico para aplicaciones financieras, científicas y de salud donde la reproducibilidad importa.
Ejemplo del Mundo Real: Análisis Financiero
Tarea: Calcular la tasa interna de retorno (TIR) para una serie de flujos de efectivo.
Enfoque CoT (GPT-4):
Calculemos la TIR usando prueba y error...
Intentar r = 0.10: VPN = -$234.52
Intentar r = 0.12: VPN = $45.23
Intentar r = 0.115: VPN = -$12.34
...
[El modelo tiene dificultades con métodos numéricos iterativos]
Resultado: Incorrecto o “No puedo calcular esto con precisión”
Enfoque PoT (Llama 3.1 8B + unsandbox):
import numpy_financial as npf
def calculate_irr(cash_flows):
"""
Calculate internal rate of return for cash flows
cash_flows: list of cash flows, first element is initial investment (negative)
"""
return npf.irr(cash_flows)
# Cash flows: -$1000 investment, then $300, $400, $500 returns
cash_flows = [-1000, 300, 400, 500]
irr = calculate_irr(cash_flows)
print(f"IRR: {irr:.2%}")
Resultado: IRR: 8.90% (matemáticamente correcto, cada vez)
Cómo unsandbox Habilita PoT a Escala
unsandbox está diseñado específicamente para flujos de trabajo Program-of-Thought:
1. Ejecución de Confianza Cero
# El código del usuario se ejecuta en contenedor aislado
# Sin acceso al sistema de archivos, red u otros procesos
# Límites automáticos de recursos previenen cálculos descontrolados
2. Soporte para más de 42 Lenguajes
No todos los modelos son mejores en Python. Algunos sobresalen en:
- Julia para computación numérica
- R para análisis estadístico
- JavaScript para manipulación JSON
- Rust para cálculos críticos de rendimiento
curl https://api.unsandbox.com/execute \
-H "Authorization: Bearer unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx" \
-d '{
"language": "julia",
"code": "# Your Julia code here"
}'
3. Ejecución en Menos de un Segundo
Latencia promedio del flujo de trabajo PoT:
- El modelo genera código: ~800ms
- unsandbox ejecuta código: ~150ms
- Total: <1 segundo
Comparar con CoT:
- El modelo genera razonamiento: ~2000ms
- Todavía podría estar equivocado
4. Decodificación de Auto-Consistencia
Ejecutar el mismo prompt PoT 5 veces, ejecutar todas las muestras de código, devolver el resultado más común:
# Example: Self-consistency with voting
# Run multiple code samples and pick the most common result
results = []
# Sample 1
def solve1(): return 42 * 1.15
results.append(solve1())
# Sample 2
def solve2(): return 42 * 1.15
results.append(solve2())
# Sample 3 would fail: def solve3(): return 42 × 1.15 # Syntax error
# Sample 4
def solve4(): return 42 * 1.15
results.append(solve4())
# Sample 5 (model error)
def solve5(): return 42 * 1.51
results.append(solve5())
# Find consensus (most common result)
from collections import Counter
consensus = Counter(results).most_common(1)[0][0]
print(f"Consensus result: {consensus:.1f}")
# Output: Consensus result: 48.3
Resultado: Incluso con errores ocasionales del modelo, la votación de consenso + ejecución de código produce respuestas correctas.
Patrones de Implementación
Aquí hay un flujo de trabajo PoT completo que funciona con cualquier modelo + unsandbox:
Guía de Selección de Modelos
Modelos API (alojados, pago por token):
- GPT-4.1 Nano: $0.10/1M entrada, $0.40/1M salida - La opción más barata jamás
- GPT-4.1 Mini: $0.40/1M entrada, $1.60/1M salida - Mejor equilibrio, contexto de 1M
- GPT-4o Mini: $0.00015/1K entrada, $0.0006/1K salida - OpenAI legacy
Modelos Locales (auto-alojados, cero costos API):
- Qwen 3 Coder 30B: Mejor precisión, necesita RTX 4090/3090 (24GB VRAM)
- Hermes-3-Llama-3.1-8B: Excelente seguimiento de instrucciones, RTX 4090/3090
Implementación Universal
El patrón es idéntico para todos los modelos — solo cambia el endpoint del modelo:
import requests
from openai import OpenAI # For API models, or use requests for local
# ===== CONFIGURATION: Choose your model =====
# All models use OpenAI-compatible /v1 endpoints - just change base_url!
# Option 1: OpenAI API models
BASE_URL = "https://api.openai.com/v1"
MODEL_NAME = "gpt-4.1-nano" # or "gpt-4.1-mini" or "gpt-4o-mini"
API_KEY = "YOUR_OPENAI_KEY"
# Option 2: Free uncloseai.com - Hermes 8B (tested, works!)
# BASE_URL = "https://hermes.ai.unturf.com/v1"
# MODEL_NAME = "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic"
# API_KEY = "not-needed"
# Option 3: Free uncloseai.com - Qwen Coder 30B (tested, works!)
# BASE_URL = "https://qwen.ai.unturf.com/v1"
# MODEL_NAME = "hf.co/unsloth/Qwen3-Coder-30B-A3B-Instruct-GGUF:Q4_K_M"
# API_KEY = "not-needed"
# Option 4: Local Ollama (port 11434)
# BASE_URL = "http://localhost:11434/v1"
# MODEL_NAME = "qwen3-coder:30b-q4"
# API_KEY = "ollama"
# Option 5: Local vLLM (port 18888)
# BASE_URL = "http://localhost:18888/v1"
# MODEL_NAME = "adamo1139/Hermes-3-Llama-3.1-8B-FP8-Dynamic"
# API_KEY = "token-abc123"
# unsandbox API key (get free key at unsandbox.com)
UNSANDBOX_KEY = "unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx"
# ===== STEP 1: Generate Code =====
# Same code works for ALL models - just change base_url above!
problem = """Solve this problem by writing Python code.
Output ONLY the code, no explanations.
Problem: A company's revenue grew 15% annually for 3 years,
starting from $1.2M. What's the revenue in year 3?"""
client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
response = client.chat.completions.create(
model=MODEL_NAME,
max_tokens=2048,
messages=[{"role": "user", "content": problem}]
)
code = response.choices[0].message.content
# ===== STEP 2: Execute via unsandbox =====
exec_response = requests.post(
"https://api.unsandbox.com/execute",
headers={"Authorization": f"Bearer {UNSANDBOX_KEY}"},
json={"language": "python", "code": code, "timeout": 5}
)
result = exec_response.json()
print(result["stdout"]) # $1,825,305.00
Análisis de Costos Por Modelo
| Model | Code Generation | unsandbox | Total/Query | Speed |
|---|---|---|---|---|
| GPT-4.1 Nano | ~$0.0003 | $0.000023 | $0.000323 | ~3-4s |
| GPT-4.1 Mini | ~$0.0011 | $0.000023 | $0.001123 | ~3-4s |
| GPT-4o Mini | ~$0.0002 | $0.000023 | $0.000223 | ~5s |
| Qwen 3 Coder 30B (local) | $0 | $0.000023 | $0.000023 | ~1-2s |
| Hermes-3 8B (local) | $0 | $0.000023 | $0.000023 | ~1-2s |
Nota: unsandbox cuesta $0.000023 por solicitud para todos los planes (Dev, Production, Business) - pagas más por límites de velocidad más altos, no por precios por solicitud.
Niveles de precios de unsandbox (costo por solicitud a utilización completa):
| Tier | Monthly Cost | Requests/Month | Cost/Request |
|---|---|---|---|
| Development | $7 | 302,400 | $0.000023 |
| Production | $91 | 3,931,200 | $0.000023 |
| Business | $175 | 7,560,000 | $0.000023 |
Perspectiva clave: Los modelos locales eliminan los costos de API por completo — solo pagas por la ejecución de unsandbox ($0.000023/consulta).
Benchmarks: Modelos Pequeños vs Modelos Grandes
La investigación del artículo PoT muestra mejoras dramáticas:
| Dataset | GPT-3 CoT | GPT-3 PoT | Improvement |
|---|---|---|---|
| GSM8K (math) | 68.2% | 78.5% | +10.3% |
| SVAMP (word problems) | 74.1% | 85.3% | +11.2% |
| FinQA (financial) | 52.3% | 67.8% | +15.5% |
| ConvFinQA | 48.6% | 63.2% | +14.6% |
Perspectiva clave: La mejora es mayor en problemas más difíciles donde la aritmética de varios pasos acumula errores.
Por Qué PoT Funciona con Modelos Modernos (2025)
La investigación original usó modelos de la era GPT-3, pero la técnica es aún más poderosa hoy:
- Modelos locales más pequeños (Qwen 3 Coder 30B, Hermes-3-Llama-3.1-8B) pueden generar código Python correcto
- Ejecución de código a través de unsandbox elimina completamente los errores aritméticos
- Costo dramáticamente más bajo: Modelos locales + unsandbox (~$0.000023/consulta) vs GPT-4 API ($0.02-0.05/consulta)
- Privacidad preservada: La generación de código ocurre localmente, solo la ejecución va a unsandbox
La perspectiva clave: no necesitas un modelo masivo para escribir código correcto - solo necesitas que comprenda el problema y exprese la lógica. El cálculo real es manejado por Python, que nunca comete errores.
Velocidad: Los Modelos Cuantizados Más Pequeños Son Más Rápidos
Aquí está la parte contraintuitiva: los modelos cuantizados te dan respuestas correctas más rápido que los modelos API grandes.
Comparación de Latencia (Mismo Problema)
| Model | Generation Time | Execution Time | Total | Result |
|---|---|---|---|---|
| GPT-4 API (CoT) | ~3,500ms | N/A | 3,500ms | ❌ A veces incorrecto |
| GPT-4 API (PoT) | ~2,000ms | ~150ms | 2,150ms | ✅ Siempre correcto |
| Qwen 3 Coder 30B Q4 (Local PoT) | ~800ms | ~150ms | 950ms | ✅ Siempre correcto |
| Hermes-3 8B FP8 (Local PoT) | ~400ms | ~150ms | 550ms | ✅ Siempre correcto |
Por qué los modelos cuantizados son más rápidos:
- Menor huella de memoria → generación de tokens más rápida (Q4/FP8 se ejecuta completamente en caché GPU)
- Salidas más cortas → El código es más conciso que las explicaciones aritméticas paso a paso
- Sin latencia de API → La inferencia local elimina los viajes de ida y vuelta por red
- Ejecución paralela → unsandbox puede ejecutar múltiples fragmentos de código simultáneamente
Impacto en el mundo real:
Procesando 100 problemas matemáticos:
GPT-4 CoT: 100 × 3,500ms = 350 segundos (5.8 minutos)
Hermes-3 FP8 PoT: 100 × 550ms = 55 segundos (< 1 minuto)
Obtienes respuestas correctas 6× más rápido a 1/200 del costo usando un modelo cuantizado en una GPU de consumidor.
Más Allá de las Matemáticas: Otras Aplicaciones PoT
1. Análisis de Datos
# Model generates pandas code for business intelligence queries
import pandas as pd
df = pd.read_csv('sales_data.csv')
monthly_revenue = df.groupby(df['date'].dt.month)['revenue'].sum()
growth_rate = monthly_revenue.pct_change().mean()
print(f"Average monthly growth: {growth_rate:.2%}")
2. Computación Científica
# Physics simulations the model can't do in its "head"
import numpy as np
from scipy.integrate import odeint
def projectile_motion(state, t, g=9.81):
x, vx, y, vy = state
return [vx, 0, vy, -g]
# Solve trajectory
solution = odeint(projectile_motion, [0, 10, 0, 15], np.linspace(0, 3, 100))
max_height = solution[:, 2].max()
print(f"Max height: {max_height:.2f} meters")
3. Manipulación de Cadenas
# Complex regex/parsing that models hallucinate
import re
def extract_emails(text):
pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
return re.findall(pattern, text)
text = "Contact us at hello@example.com or support@test.org for help"
emails = extract_emails(text)
print(f"Found {len(emails)} emails: {emails}")
# Output: Found 2 emails: ['hello@example.com', 'support@test.org']
La Economía de PoT
Para una empresa que procesa 1M consultas/mes:
CoT Tradicional con GPT-4:
- Entrada: 500 tokens × $0.01/1K = $5,000
- Salida: 800 tokens × $0.03/1K = $24,000
- Total: $29,000/mes
PoT con Qwen 3 Coder 30B (Q4_K_M) + unsandbox:
- Modelo (auto-alojado en RTX 4090): ~$0/mes (ya posees GPU)
- Entrada: 500 tokens × $0.00 = $0
- Salida: 200 tokens × $0.00 = $0
- Ejecución unsandbox: 1M × $0.000023 = $23/mes
- Total: $23/mes
Ahorro: $28,977/mes (99.9% reducción de costos)
Además:
- 3x más rápido (modelo más pequeño + salida más corta)
- Más preciso en tareas numéricas
- Resultados determinísticos
- Privacidad completa (ejecutar modelos localmente)
Consejos de Implementación
1. Plantilla de Prompt de Sistema
You are a mathematical reasoning assistant.
When solving problems:
1. Write Python code to solve the problem
2. Use descriptive variable names
3. Add comments explaining your logic
4. Output ONLY executable code
5. End with a print() statement showing the result
DO NOT:
- Show arithmetic in comments
- Explain your reasoning in natural language
- Approximate or estimate - write exact calculations
2. Auto-Corrección con Retroalimentación stderr/stdout
La función asesina: unsandbox devuelve tanto stdout como stderr, habilitando auto-corrección automática:
def solve_with_retry(problem, model_client, max_retries=3):
"""
Generate code, execute it, and retry with error feedback if it fails.
"""
for attempt in range(max_retries):
# Step 1: Generate code
response = model_client.chat.completions.create(
model="gpt-4.1-nano",
max_tokens=2048,
messages=[{
"role": "user",
"content": f"Solve this problem by writing Python code.\nOutput ONLY the code.\n\n{problem}"
}]
)
code = response.choices[0].message.content
# Step 2: Execute via unsandbox
result = requests.post(
"https://api.unsandbox.com/execute",
headers={"Authorization": "Bearer unsb-sk-xxxx"},
json={"language": "python", "code": code, "timeout": 5}
).json()
# Step 3: Check for errors
if result.get("stderr") == "" and result.get("stdout"):
# Success!
return result["stdout"]
# Step 4: Retry with error feedback
error_msg = result.get("stderr", "No output produced")
problem = f"""
Previous attempt failed with error:
{error_msg}
Failed code:
{code}
Original problem: {problem}
Fix the syntax or logic error and write corrected Python code.
"""
return None # Failed after max retries
Ejemplo real:
Intento 1: El modelo escribe `printt(result)` → stderr: "NameError: name 'printt' is not defined"
Intento 2: El modelo corrige el error tipográfico → `print(result)` → ¡Éxito!
Esto mejora dramáticamente la precisión para modelos más pequeños que ocasionalmente cometen errores de sintaxis.
3. Validación
# Run simple assertion tests
def validate_solution(code, expected_properties):
result = execute_code_via_unsandbox(code)
assert isinstance(result, (int, float)), "Result must be numeric"
assert result > 0, "Result must be positive"
assert result < 1_000_000, "Result seems unreasonably large"
return result
Limitaciones y Direcciones Futuras
Limitaciones Actuales
-
Calidad de Generación de Código: Los modelos pequeños a veces generan código sintácticamente incorrecto
- Solución: Votación de múltiples muestras, lógica de reintento o ajuste fino del modelo
-
Comprensión del Problema: Los modelos pueden malinterpretar preguntas ambiguas
- Solución: Aclaración de prompt, ejemplos few-shot
-
Algoritmos Complejos: Los modelos tienen dificultades con desafíos algorítmicos novedosos
- Solución: Proporcionar funciones de biblioteca, dividir en sub-problemas
El Futuro: Chain-of-Code
La investigación emergente muestra resultados aún mejores con enfoques híbridos:
# Step 1: Natural language reasoning
# "I need to find the compound annual growth rate..."
# Step 2: Code for calculations
def cagr(start_value, end_value, years):
return (end_value / start_value) ** (1 / years) - 1
# Step 3: Natural language interpretation
# "A CAGR of 12.5% means the investment grew by about 12.5% per year"
Esto combina las fortalezas de ambos enfoques.
Pruébalo Tú Mismo
Inicio Rápido con unsandbox:
-
Obtén una clave API gratuita: unsandbox.com
-
Ejecuta tu primera consulta PoT:
curl https://api.unsandbox.com/execute \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "language": "python", "code": "def compound_growth(principal, rate, years):\n return principal * (1 + rate) ** years\n\nresult = compound_growth(10000, 0.07, 10)\nprint(f\"Final value: ${result:,.2f}\")" }' -
Integra con tu LLM:
# See full example in our docs: # https://unsandbox.com/docs/python
Prompts de Ejemplo
Prueba estos con tu modelo preferido + unsandbox:
-
Finanzas: “Calculate the present value of receiving $10,000 annually for 20 years at a 5% discount rate”
-
Estadísticas: “Generate 1000 random samples from a normal distribution with mean=100, std=15. What percentage fall between 85 and 115?”
-
Física: “A ball is thrown at 20 m/s at a 45° angle. How far does it travel before hitting the ground?”
Conclusión
Program-of-Thought representa un cambio de paradigma: deja de pedirle a los modelos que hagan matemáticas; pídeles que escriban código.
Las implicaciones son profundas:
- Los modelos más pequeños se vuelven viables para producción
- Los modelos cuantizados igualan o superan el rendimiento de los modelos grandes
- Los costos caen entre 90-99%
- Los resultados se vuelven determinísticos y auditables
- La implementación local es práctica (no se necesitan GPUs masivas)
Con unsandbox proporcionando ejecución de código segura y rápida en más de 42 lenguajes, PoT ya no es una técnica de investigación — es una estrategia lista para producción para construir sistemas de IA precisos y asequibles.
El futuro no son modelos más grandes. Es arquitectura más inteligente.
Recursos:
Prueba Program-of-Thought: Obtén una clave API gratuita en unsandbox.com — 1 solicitud cada 42 segundos, perfecta para experimentación.