2025-10-06

Diagnóstico de latencia: Cómo hacer que los agentes de productos de IA sean tres veces más rápidos

A man squats in front of a server while holding a laptop
Por Jason Toews, desarrollador de IA, Orium y David Azoulay, director de I+D de agentes, Orium
8 minutos de lectura

La visión era simple: seleccionar hasta tres artículos, identificar sus diferencias clave y ofrecer ventajas y desventajas personalizadas, adaptadas a diferentes tipos de compradores. El comparador se diseñó para ser el compañero de compras inteligente que siempre quisimos: rápido, perspicaz y realmente útil.

Y funcionó. El asistente extrajo especificaciones detalladas, generó cinco viñetas por producto y continuó con párrafos bien estructurados para diferentes grupos demográficos.

Al principio, no creíamos que tuviéramos un problema de rendimiento. Claro, parecía un poco lento, pero lo atribuimos a peculiaridades del modo de desarrollo.

Luego introdujimos los evaluadores de rendimiento.

Fue entonces cuando vimos la cifra real: 13 segundos desde la carga de la página hasta la respuesta. De repente, lo que parecía "bueno" ya no lo parecía tanto. Sin fallos. Sin fallos del modelo. Solo una función inteligente oculta tras una experiencia lenta.

Habíamos creado un producto que funcionaba técnicamente, pero no parecía funcionar, al menos no para los usuarios reales.

Y en IA, la percepción es rendimiento.

El costo real de hacerlo todo a la vez

¿Qué fallaba entonces? El agente hacía exactamente lo que le pedimos: procesaba varios productos a la vez, recuperaba las especificaciones relevantes y generaba un resultado completo en una sola llamada LLM.

Pero eso implicaba generar 15 viñetas y 3 párrafos personalizados por sesión, cada uno con matices y adaptado al cliente. Es una tarea ardua. Si a esto le añadimos datos completos del producto, contexto adicional e historial de mensajes detallado, la latencia se volvió inevitable. Desafortunadamente, también es inaceptable.

Mejorar el rendimiento no se limitaba a perseguir cifras de referencia. Un rendimiento lento implica una experiencia general deficiente, y los estudios demuestran que ese retraso anula la interacción con el cliente y cuesta ventas. Mejorar los tiempos de carga mejora la experiencia, por eso hicimos del rendimiento un requisito del producto, no solo una preocupación del backend.

Rompiendo el cuello de botella

Al igual que con muchas cosas en el complejo mundo de la tecnología empresarial y la IA, no existía una solución mágica. En cambio, realizamos una serie de cambios específicos para mejorar la capacidad de respuesta, tanto en la estructura de datos como en la orquestación de la generación.

Paralelismo potenciado por LangGraph

Una de las mejoras más impactantes provino de cómo utilizamos LangGraph para paralelizar la generación.

La función Send[] de LangGraph nos permitió ejecutar múltiples tareas de generación al mismo tiempo, con cada ruta recibiendo un prompt y esquema diferentes. En nuestro caso, queríamos producir tanto comparaciones en formato de viñetas como resúmenes en estilo de párrafo—dos resultados distintos que podían generarse independientemente.

En lugar de ejecutar estos pasos secuencialmente, utilizamos la función Send[] de LangGraph para ejecutarlos simultáneamente, lo que redujo significativamente la latencia y simplificó la orquestación.

Aquí hay una versión simplificada de cómo activamos ambos prompts en paralelo:

TEXT
123456789101112
const prompts = [
  process.env.COMPARE_PROMPT_KEY || "compare-prompt",
  process.env.COMPARE_SUMMARY_PROMPT_KEY || "compare-summary-prompt"
];

return prompts.map((prompt) => {
  return new Send("compareProducts", {
    ...state,
    prompt,
  });
});

Este enfoque nos proporcionó:

  • Ejecución paralela de viñetas y resúmenes en párrafos
  • Uso más eficiente del tiempo del modelo
  • Estructura de gráfico limpia y mantenible sin duplicar lógica
  • Resultados más rápidos de extremo a extremo para los usuarios

Al aprovechar las características de concurrencia de LangGraph, pudimos reducir drásticamente el tiempo de generación mientras manteníamos nuestra arquitectura simple y escalable.

Limpieza de datos y reducción de contexto

Antes de enviar cualquier cosa al modelo, limpiamos y aplanamos los datos en una estructura ligera y lista para el prompt. Eliminamos campos anidados, metadatos irrelevantes e incluimos solo lo estrictamente necesario.

También minimizamos el contexto pasado al LLM. Sin historiales completos de mensajes. Sin carga extra. Cada tarea de generación recibió solo la entrada que necesitaba, nada más.

Esto resultó en:

  • Generación más rápida – Menos entrada = menos procesamiento
  • Menor uso de tokens – Prompts y salidas más pequeños
  • Respuestas más enfocadas – Sin distracciones (solo lo esencial) y menos alucinaciones
  • Control de prompt más fácil – Entrada más limpia = mejor alineación

Cambio de modelo en tiempo de ejecución

Para apoyar la experimentación y los compromisos entre costo y calidad, habilitamos el cambio de modelo en tiempo de ejecución sin necesidad de redespliegue.

Esto nos dio la flexibilidad para probar diferentes LLMs en condiciones reales, optimizar para diferentes escenarios y avanzar rápidamente sin interrumpir el flujo de trabajo.

Con esta configuración, pudimos:

  • Realizar pruebas A/B del rendimiento del modelo bajo demanda
  • Adaptarnos dinámicamente a objetivos cambiantes de latencia o presupuesto
  • Reducir la fricción de despliegue al desacoplar la elección del modelo del código
  • Elegir el modelo adecuado para cada tarea en tiempo real

La agilidad aquí significó velocidad, control y confianza.

Ajuste de configuración del modelo

No solo elegimos el modelo, sino que ajustamos cómo lo usábamos. Para cada paso de generación, optimizamos la configuración:

  • Reducimos max_tokens para disminuir la verbosidad y controlar la longitud de salida
  • Ajustamos la temperatura y la profundidad de razonamiento para respuestas más enfocadas y consistentes
  • Usamos modelos de alto nivel solo donde era necesario, y más ligeros donde eran suficientes

Estos ajustes nos dieron resultados de alta calidad con menos tokens y menor latencia, sin comprometer la fiabilidad, especialmente donde más importaba. Por ejemplo, para procesos críticos que requerían la menor latencia posible, establecimos el service_tier en priority. Esto aumentó un poco el costo, pero mejoró significativamente la latencia de salida, y el compromiso en estos casos tiene sentido.

Salida estructurada: Respuestas JSON personalizadas

En lugar de devolver markdown o texto libre, el asistente genera JSON estructurado basado en esquemas predefinidos, adaptados a la tarea. Por ejemplo, las respuestas en viñetas incluyen una lista de productos, cada uno con marca, SKU y cinco diferenciadores, mientras que los resúmenes en párrafos devuelven un conjunto de descripciones tituladas que comparan artículos según las necesidades del usuario.

Este enfoque nos proporcionó:

  • Formato perfecto, siempre – Sin necesidad de analizar o corregir
  • Menos tokens de salida – Más compacto = más barato y rápido
  • Menos trabajo de formato para el LLM – Reduce la latencia
  • Prompts más simples, contexto más pequeño – Limpio y fácil de razonar

El uso de JSON estructurado ayudó a hacer que la salida del asistente fuera más consistente, eficiente y lista para producción.

TEXT
12345678910111213141516171819202122
const schema = {
 type: "object",
 properties: {
   summaries: {
     type: "array",
     minItems: 3,
     maxItems: 5,
     items: {
       type: "object",
       properties: {
         title: {
           type: "string",
         },
         description: {
           type: "string",
         },
       },
       required: ["title", "description"],
     },
   },
 }

Simplificación de prompts

También reelaboramos nuestros prompts para hacerlos más concisos y específicos. Las versiones iniciales pedían al modelo que analizara, explicara o describiera, lo que llevaba a resultados inconsistentes y salidas infladas. Refinamos los prompts para pedir al modelo que resumiera o seleccionara en su lugar.

Esto hizo que las instrucciones fueran más claras y las salidas más predecibles.

Los beneficios incluyeron:

  • Ejecución más rápida – Menos razonamiento requerido
  • Menos tokens – Instrucciones más simples, salidas más pequeñas
  • Respuestas más consistentes – Mejor alineación con la intención
  • Más fácil de evaluar – Menos variabilidad entre ejecuciones

La ingeniería de prompts resultó ser una palanca de rendimiento de alto impacto.

Poda de consultas

Finalmente, nuestras consultas GraphQL también eran parte del problema. Inicialmente, recuperábamos registros completos de productos, incluyendo campos que el asistente no necesitaba. Eso significaba cargas más pesadas, más procesamiento y más tokens.

Revisamos y reescribimos esas consultas para devolver solo lo que el asistente realmente usaba. ¿El resultado?

  • Cargas de datos más pequeñas
  • Manejo de solicitudes más rápido
  • Prompts más cortos
  • Menor uso de tokens LLM

Fue un cambio simple con un gran impacto. Nuestras consultas GraphQL eran originalmente tan grandes que teníamos que usar solicitudes POST para hacer llamadas API, lo que resultaba en que no se almacenaban en caché. Después de reducir significativamente lo que consultábamos, pudimos cambiar a solicitudes GET, permitiendo que se almacenaran en caché, reduciendo aún más la latencia.

Los resultados: 3 veces más rápido

Estas optimizaciones tuvieron un impacto claro:

  • La latencia total se redujo en más de dos tercios
  • El tiempo de generación de LLM se redujo significativamente
  • El asistente ahora se siente receptivo y confiable

La experiencia pasó de "esperar y ver" a "hacer clic y comparar". El contenido se mantuvo igual de completo, solo que ahora llega con la suficiente rapidez como para ser relevante.

¿Que sigue?

El rendimiento no es algo que se termina, sino algo que se mejora continuamente.

Estamos explorando otras maneras de seguir mejorando el rendimiento, incluyendo el renderizado progresivo, que mostraría primero las viñetas y luego transmitiría párrafos completos; la transmisión del lado del cliente, que completaría los resultados a medida que estén disponibles; la vectorización de la información del producto en una base de datos vectorial, lo que aumentaría significativamente el rendimiento, reduciría el tamaño del contexto e incluso podría mejorar las respuestas; y el renderizado priorizado, que mostraría primero el producto más relevante, especialmente en comparaciones escalonadas.

Porque en un mundo que cambia rápidamente, incluso la respuesta más inteligente debe llegar a tiempo.

Observaciones finales

La velocidad no tiene por qué significar tomar atajos. Al simplificar el proceso, reducir las entradas y optimizar el comportamiento del modelo, preservamos la inteligencia del agente de comparación y lo hicimos sentir rápido.

Ahora, cuando los usuarios abren una comparación, simplemente funciona. Rápida, inteligente y confiablemente. Y eso es exactamente lo que se supone que hacen los asistentes inteligentes.

Artículos populares