En este artículo, aprenderá siete patrones asíncronos para ejecutar agentes de IA simultáneamente en Python, para qué es adecuado cada patrón y los obstáculos a nivel de producción a tener en cuenta con cada uno.
Los temas que cubriremos incluyen:
Patrones asíncronos centrales como disparar y olvidar, dispersión, grupos de tareas y colas de productores-consumidores, y cuándo alcanzar cada uno de ellos. Técnicas de gestión de recursos que incluyen contrapresión basada en semáforos y ejecución especulativa, junto con sus compensaciones en el mundo real. Cómo encadenar agentes en canalizaciones asincrónicas y mantener el bucle de eventos en buen estado bajo carga.
Orquestar un único agente de IA es bastante sencillo. Mantener una flota de ellos funcionando simultáneamente sin bloquear el ciclo de eventos o desencadenar errores de límite de velocidad en cascada es un problema completamente diferente.
La biblioteca asyncio de Python le brinda las primitivas para administrar esto. Pero los patrones que uno alcanza son importantes. Cada uno resuelve un problema de coordinación diferente, y elegir el incorrecto crea modos de falla que tardan en emerger y son difíciles de depurar.
Aquí hay siete patrones asíncronos para ejecutar agentes simultáneamente, junto con las capturas de producción que vienen con cada uno.
1. Disparar y olvidar (ejecución en segundo plano independiente)
Inicia una tarea de agente y continúa sin esperar a que finalice. La rutina se ejecuta en segundo plano mientras continúa la ruta de ejecución principal.
Esto funciona bien cuando el resultado de la tarea no afecta nada posterior: el registro, el vaciado del contexto al almacenamiento o la activación de un agente de limpieza en segundo plano.
Tenga cuidado con: las excepciones en tareas independientes son absorbidas silenciosamente por el bucle de eventos. Si un agente en segundo plano falla, nada le avisará a menos que adjunte explícitamente una devolución de llamada de error. Conecte el manejo de excepciones antes de tratar cualquier tarea como realmente segura de ignorar.
2. Estricta reunión de dispersión
Se distribuye desde un agente orquestador hasta varios agentes trabajadores simultáneamente y luego se espera a que todos regresen antes de continuar.
asyncio.gather() multiplexa solicitudes salientes y ensambla resultados en orden de lanzamiento. Piense en cinco agentes que consultan diferentes fuentes de datos en paralelo, y los resultados se recopilan una vez que finaliza el último.
Cuidado con: De forma predeterminada, un solo fallo cancela el resto. Incluso cuando se desactiva ese comportamiento, se sigue aplicando la latencia rezagada: toda la operación espera al agente más lento. Una generación lenta obstaculiza todo lo demás.
3. Grupos de trabajo supervisados
Introducidos en Python 3.11, los grupos de tareas le brindan una versión estructurada de recopilación. Un administrador de contexto hace explícito el alcance de las tareas concurrentes: cuando el bloque sale, todas las tareas se completan o se cancelan y los errores surgen de inmediato.
Para proyectos nuevos en Python 3.11+, los grupos de tareas generalmente son la opción más limpia en lugar de administrar manualmente una colección suelta de tareas.
Tenga cuidado con: Los grupos de tareas cancelan agresivamente las tareas entre hermanos en caso de falla. Si un trabajador comete un error de límite de tasa, todos los demás agentes en ejecución se cancelan. Cree una lógica de reintento dentro de las rutinas de agentes individuales antes de permitir que las excepciones alcancen el nivel de grupo.
4. Productor-Consumidor con colas
No todos los agentes empiezan al mismo tiempo. A veces, un agente genera trabajo y otros lo procesan, y entre ellos hay una cola que actúa como buffer.
Los agentes productores agregan elementos a la cola a medida que encuentran trabajo. Los agentes consumidores aprovechan esto de forma independiente. Las dos partes no necesitan saber nada entre sí, y puedes aumentar o reducir los consumidores sin tocar al productor.
Tenga cuidado con: las colas ilimitadas pierden memoria de forma silenciosa. Si su productor genera tareas más rápido de lo que los consumidores pueden procesarlas, la cola crece hasta que su proceso se queda sin RAM. Establezca un tamaño máximo de cola para imponer contrapresión al productor.
5. Contrapresión mediante semáforos
Usted establece un límite estricto sobre cuántos agentes pueden acceder a un recurso al mismo tiempo. Los agentes que superan el límite esperan su turno en lugar de disparar todos simultáneamente.
Este es uno de los patrones más prácticos para los sistemas de agentes de producción, donde las API externas, los grupos de conexiones de bases de datos y los servicios internos tienen límites de rendimiento.
Cuidado con: los semáforos limitan las conexiones, no los tokens. Puede limitar las solicitudes simultáneas a 10 y aun así superar el límite de tokens por minuto de un proveedor si los 10 agentes generan grandes resultados a la vez. Para un cumplimiento estricto de la API, combine los semáforos con una limitación basada en tokens.
6. Ejecución especulativa (el primero en completarse gana)
Compites con varios agentes contra el mismo objetivo y cancelas a los perdedores en el momento en que uno arroja un resultado válido. Esto cambia la eficiencia informática por la velocidad.
Un caso de uso común es competir con un modelo más pequeño y más rápido contra uno más grande y más lento y aceptar el que termine dentro de su objetivo de latencia.
Tenga cuidado con: cancelar una tarea interrumpe su conexión local pero no detiene la generación en los servidores del proveedor. El modelo sigue ejecutándose y consumiendo tokens en su cuenta incluso después de que usted haya seguido adelante. Usted paga por cada agente perdedor, siempre.
7. Encadenamiento de canalizaciones asincrónicas
Cada agente de una cadena toma como entrada la salida del anterior. El agente A recupera datos sin procesar, el agente B los limpia, el agente C los analiza y el agente D formatea la salida.
Esto se corresponde bien con los procesos de recuperación de múltiples etapas y los flujos de trabajo de razonamiento donde cada etapa tiene una responsabilidad distinta, un manejo de errores aislado y configuraciones de modelo potencialmente diferentes.
Tenga cuidado con: Rastrear las fallas a lo largo de la cadena es difícil sin instrumentación. Para cuando el Agente D falla en una entrada con formato incorrecto, es posible que la violación del esquema haya comenzado en el Agente A. Inyecte identificadores de seguimiento en las cargas útiles que pasan entre etapas.
Discusión
Aquí hay algunos consejos rápidos para elegir el patrón correcto:
Tareas independientes, todas necesarias: grupos de tareas o de recolección dispersa. Cargas de trabajo de flujo continuo o de volumen desconocido: productor-consumidor con una cola. Recursos externos con límites de velocidad: contrapresión a través de semáforos. Velocidad sobre integridad: ejecución especulativa. Lógica secuencial entre agentes especializados: encadenamiento de canalizaciones. Tareas en segundo plano sin valor de retorno necesario: disparar y olvidar.
La mayoría de los sistemas de producción combinan dos o tres de estos. Una canalización podría utilizar semáforos dentro de cada etapa. Una configuración productor-consumidor podría utilizar la recopilación dentro de cada grupo de consumidores.
Una cosa más: ver el bucle de su evento
Incluso con una red perfectamente asíncrona, las operaciones síncronas vinculadas a la CPU, como el análisis intensivo de JSON o la ejecución de un tokenizador, bloquearán el bucle de eventos. Cuando el bucle se bloquea, las solicitudes en curso pierden sus latidos de tiempo de espera y desencadenan fallas en cascada en su arquitectura que de otro modo sería asíncrona.
Perfile su bucle con regularidad y descargue las operaciones que requieren mucha CPU a un grupo de subprocesos cuando se presenten como cuellos de botella. Los patrones anteriores manejan la coordinación vinculada a E/S. Mantener el bucle despejado es lo que los hace aguantar.
Conclusión
Estos siete patrones le brindan un vocabulario para pensar en la coordinación de agentes antes de que surjan problemas en la producción. Comience con reuniones o grupos de tareas para casos simples, agregue semáforos y colas a medida que crece la complejidad y trate las notas de “cuidado” como las partes con mayor probabilidad de costarle a escala.
Los patrones son la arquitectura. Hacerlas bien es lo que separa a un prototipo frágil de un sistema que se mantiene en funcionamiento.