El mes pasado me tocó tomar una decisión que probablemente muchos de ustedes han enfrentado: nuestro equipo quería integrar un LLM en el pipeline de revisión de PRs, y alguien tenía que elegir cuál usar en producción. Ese alguien fui yo.
Así que dediqué dos semanas a probar Claude (Sonnet 4.6 y Opus 4.6), GPT-4o, y Gemini 2.0 (Flash y Pro) con tareas reales de nuestro flujo de trabajo — revisión de código, generación de tests, análisis de logs de errores, y documentación técnica. No benchmarks artificiales. Tareas que hago o que mi equipo hace todos los días.
Lo que encontré me sorprendió en algunos casos y confirmó lo que ya sospechaba en otros.
Por qué esta prueba era diferente a leer un leaderboard
Trabajamos en un equipo de seis personas construyendo una plataforma SaaS de analytics. Stack principal: TypeScript, React, Node.js, PostgreSQL. El proyecto de revisión de PRs consistía en analizar diffs de código y generar comentarios estructurados — identificar posibles bugs, sugerir mejoras de performance, verificar que los tests cubran los casos edge relevantes.
Para cada modelo usé la misma batería de prompts sobre los mismos PRs reales (con nombres de variables y datos sensibles sanitizados, obvio). Medí calidad de los comentarios, tiempo de respuesta, consumo de tokens para tareas equivalentes, y si el output era consistente entre llamadas o errático.
Gasté alrededor de $40 en total entre las tres APIs. No es una fortuna, pero fue suficiente para tener una muestra decente. También anoté en qué tareas fallaba cada uno y con qué frecuencia, no solo cuándo brillaba.
Generación de código: Claude gana, pero GPT-4o no se queda atrás
La verdad, para generación de código complejo, Claude Sonnet 4.6 fue mi favorito. No por un margen enorme, pero sí consistente. Cuando le pedía refactorizar funciones asíncronas complicadas o generar lógica de manejo de errores para edge cases específicos, el código que producía necesitaba menos correcciones manuales.
Un ejemplo concreto: teníamos una función que manejaba reintentos de peticiones a una API externa con backoff exponencial, con lógica especial para códigos de error específicos. Le pasé el código original y le pedí a cada modelo que lo refactorizara para hacerlo más testeable.
// Prompt: "Refactoriza esta función para que sea más fácil de testear.
// Necesito poder mockear el delay y controlar qué errores se reintentan."
// Versión original (simplificada):
async function fetchWithRetry(url: string, maxRetries = 3): Promise<Response> {
let lastError: Error;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url);
if (response.status === 429 || response.status >= 500) {
await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
continue;
}
return response;
} catch (err) {
lastError = err as Error;
await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
}
}
throw lastError!;
}
// Claude Sonnet 4.6 propuso inyección de dependencias así:
interface RetryConfig {
maxRetries?: number;
delay?: (attempt: number) => Promise<void>; // mockeable en tests
shouldRetry?: (response: Response) => boolean; // lógica separada y testeable
}
async function fetchWithRetry(
url: string,
config: RetryConfig = {}
): Promise<Response> {
const {
maxRetries = 3,
delay = (attempt) =>
new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000)),
shouldRetry = (res) => res.status === 429 || res.status >= 500,
} = config;
// ... resto idéntico pero ahora con las dependencias inyectadas
}
GPT-4o llegó a una solución similar, aunque con un diseño de interfaz ligeramente diferente. Perfectamente usable. Gemini 2.0 Pro también lo resolvió, pero — y este es un patrón que noté varias veces — tendía a over-engineer la solución, añadiendo abstracciones que nadie pidió, una clase RetryManager completa con métodos estáticos para una función que perfectamente podría quedarse como función.
El gotcha que más me costó tiempo vino de GPT-4o: en una tarea de análisis de código Python (no nuestro stack principal, pero a veces revisamos contribuciones externas), me sugirió usar async-timeout con una API que ya no existe en las versiones recientes del paquete. Error pequeño, pero me costó 15 minutos descubrir por qué el código no funcionaba. Con Claude no tuve ese problema en las mismas tareas — aunque no diría al 100% que sea inmune a este tipo de confabulación, simplemente no me pasó en esta muestra.
Razonamiento y análisis: donde Claude realmente se distancia
Aquí la diferencia fue más clara. Para tareas que requerían razonamiento sobre código — "¿por qué este query de PostgreSQL está siendo lento dado este execution plan?" o "analiza este stack trace y dime qué puede estar causando el memory leak en Node" — Claude Opus 4.6 era notablemente mejor. Más preciso, con más contexto útil, y con menos relleno.
El problema: Opus 4.6 cuesta considerablemente más. Para uso intensivo en producción, el costo escala rápido y se siente.
Gemini 2.0 Flash fue una sorpresa positiva para tareas más simples. Muy rápido, barato, y para "¿tiene este código algún bug obvio?" o "genera el JSDoc para esta función", funciona bien. Donde se rompe es cuando la tarea requiere mantener contexto de múltiples archivos o razonar sobre interacciones entre distintos módulos del sistema.
Una cosa que noté con Gemini 2.0 Pro, y que nadie en los reviews que leí mencionaba con honestidad: tiene una ventana de contexto de dos millones de tokens, lo cual en papel suena increíble. En la práctica, cuando le pasaba contextos muy largos — varios archivos de código a la vez — la calidad de las respuestas era inconsistente. No siempre usaba bien toda esa información disponible. Los release notes de febrero mencionan mejoras en este aspecto, pero a la fecha de esta prueba todavía lo notaba. Tu experiencia puede variar si estás en un caso de uso donde el contexto largo es más estructurado.
El factor costo: lo que cambia cuando lo usas en producción real
Aquí está la parte que la mayoría de las comparativas no tocan con suficiente honestidad.
En desarrollo y pruebas, todos los modelos se sienten baratos porque los usas ocasionalmente. Cuando los integras en un pipeline que procesa cientos de solicitudes al día, la matemática cambia. Mis estimaciones para nuestro caso de uso (análisis de PRs medianos, ~2.000 tokens de input y ~800 de output):
- Gemini 2.0 Flash: el más barato por un margen considerable. Difícil ignorarlo para volumen alto.
- Claude Sonnet 4.6: precio razonable. El mejor equilibrio calidad/costo de los que probé.
- GPT-4o: similar a Sonnet en precio, ligeramente más caro dependiendo del volumen.
- Claude Opus 4.6: significativamente más caro. Tiene sentido para tareas críticas donde la calidad extra lo justifica, no para uso masivo.
Lo que terminamos haciendo fue routing por complejidad:
def select_model_for_review(diff_size: int, complexity_score: float) -> str:
"""
complexity_score: float 0-1, calculado en base a número de archivos,
profundidad de cambios, y si toca partes críticas del sistema.
"""
if diff_size < 200 and complexity_score < 0.4:
# Cambios pequeños y simples: Flash es suficiente y mucho más barato
return "gemini-2.0-flash"
elif complexity_score >= 0.7 or diff_size > 1000:
# Cambios grandes o arquitectónicamente complejos: vale la pena Sonnet
return "claude-sonnet-4-6"
else:
# Zona gris: depende del rate limit actual de cada API
return "gpt-4o"
No es la arquitectura más elegante del mundo, pero en tres semanas de producción ha funcionado. No estoy 100% seguro de que este approach escale sin fricciones cuando tengamos diez veces más PRs, pero por ahora el ahorro en tokens es real.
Lo que cada modelo hace mejor, sin rodeos
Después de dos semanas, esto es lo que realmente pienso:
Claude Sonnet 4.6 sigue instrucciones complejas con más fidelidad que los otros dos. No inventa APIs que no existen con la misma frecuencia. Cuando no sabe algo, tiende a decirlo en lugar de generar algo plausible-pero-incorrecto. Para código TypeScript y Python, la calidad es consistentemente alta sin necesitar prompts muy elaborados.
GPT-4o brilla en integración con el ecosistema Azure/OpenAI si ya estás en él, y para tareas de generación de texto que no son código puro — documentación, mensajes de commit detallados, resúmenes de changelogs. El soporte multimodal también es sólido si necesitas analizar screenshots de errores junto con código. Una cosa concreta que le da ventaja: el acceso a herramientas como web search nativo dentro del mismo contexto es útil para ciertos flujos de trabajo.
Gemini 2.0 Flash es el modelo que más me sorprendió en sentido positivo por el costo. Para tareas de volumen donde la precisión no necesita ser perfecta, es difícil justificar pagar más. Gemini 2.0 Pro es más capaz pero no aprovecha bien su ventana de contexto enorme, lo cual es la característica más impresionante que tiene sobre el papel.
Algo que nadie menciona suficiente: la latencia importa más de lo que parece cuando integras estos modelos en herramientas interactivas. Claude tiende a ser algo más lento en respuestas iniciales para prompts cortos comparado con GPT-4o. Para casos batch no importa. Para un copilot interactivo dentro de tu editor, sí lo vas a notar.
Qué usaría yo y qué le recomiendo a mi equipo
Si estás construyendo algo nuevo y tienes que elegir un modelo como default sin más contexto: Claude Sonnet 4.6.
No porque sea perfecto en todo — no lo es. Sino porque tiene el mejor balance entre calidad, consistencia y costo para tareas típicas de desarrollo de software. Los errores que comete tienden a ser más detectables que los de los otros modelos, lo cual en producción vale mucho.
Si tu equipo ya está integrado profundamente con Azure/OpenAI, o si tienes casos de uso que dependen de funcionalidades específicas de GPT-4o, tiene todo el sentido quedarse ahí. No cambies lo que funciona sin una razón real.
Y si el costo es tu limitante principal — volúmenes grandes, presupuesto ajustado — dale una oportunidad seria a Gemini 2.0 Flash antes de descartarlo. En nuestro pipeline cubre alrededor del 40% de las solicitudes sin que la diferencia de calidad sea perceptible en el output final.
Mi setup actual: Sonnet 4.6 como modelo principal, Gemini 2.0 Flash para el tier de bajo costo, y Opus 4.6 reservado para las tareas de análisis más críticas. GPT-4o lo sigo usando en experimentos side, pero ya no es mi primer instinto para código.
Lo que más importa no es el modelo que elijas hoy — es que tu arquitectura haga fácil cambiar de modelo cuando salga algo mejor. Y ese algo mejor siempre está a dos meses de distancia.
Top comments (0)