Bedrock y LLM son los chicos más populares de la ciudad. Decidí averiguar lo fácil que es crear un chatbot utilizando la capacidad de los agentes de Bedrock para activar una API basada en el esquema OpenAPI con el nuevo soporte de Bedrock que ofrece Powertools para AWS.
En esta publicación, aprenderá a utilizar los agentes de Amazon Bedrock para automatizar las llamadas a la API basadas en funciones Lambda mediante Powertools para AWS y CDK para Python. También analizaremos las limitaciones y los problemas de esta solución con los agentes de Bedrock.
Descargo de responsabilidad: no soy experto en inteligencia artificial, por lo que si quieres aprender más sobre cómo funciona, este no es tu blog. Te mostraré un código práctico para configurar agentes Bedrock con tus API en 5 minutos.
Tabla de contenido
Introducción al lecho rocoso
Amazon Bedrock es un servicio completamente administrado que ofrece una selección de modelos de base (FM) de alto rendimiento de empresas líderes en IA. https://aws.amazon.com/bedrock/
Bedrock presenta una afirmación audaz:
La forma más sencilla de crear y escalar aplicaciones de IA generativa con modelos básicos
Sin embargo, el hecho de que pudiera crear una aplicación de este tipo en una hora aproximadamente dice mucho sobre esta afirmación. Sin embargo, recibí ayuda: utilicé Powertool para la excelente documentación de AWS Lambda y el nuevo soporte para agentes Bedrock.
En mi opinión, Bedrock ofrece una amplia gama de API y agentes que le permiten interactuar con LLM de terceros y utilizarlos para cualquier propósito, dependiendo de la experiencia del LLM, ya sea como ayudante de propósito general, escribir música, crear imágenes a partir de texto o llamar a API en su nombre.
Bedrock no requiere ninguna infraestructura en particular para su implementación (VPC, etc.) o administración. Es un servicio completamente administrado y usted paga solo por lo que usa, pero puede resultar costoso. El modelo de precios es bastante complejo y varía en gran medida según los modelos que use y las funciones que seleccione.
Las características muy solicitadas, como las barreras de protección (filtros de lenguaje limpio, escáneres de información personal identificable, etc.) aumentan el costo, pero una vez más, están completamente administradas.
Agentes de Bedrock
Los agentes permiten que las aplicaciones de IA generativa ejecuten tareas de varios pasos en los sistemas y fuentes de datos de la empresa.
Los agentes son chatbots amigables que pueden ejecutar tareas de varios pasos. En nuestro caso, llamarán a las API según la información ingresada por el usuario.
Los agentes de lecho rocoso tienen varios componentes:
Modelo: el LLM que selecciona para que lo utilice el agente.
Instrucciones: el mensaje inicial que establece el contexto para la sesión del agente. Se trata de una práctica clásica de ingeniería de mensajes : "usted es un agente de ventas que vende X a los clientes".
Grupos de acciones: define las acciones del agente para el usuario. Proporciona un esquema OpenAPI y una función Lambda que implementa ese esquema OpenAPI.
Bases de conocimiento: opcional. El agente consulta la base de conocimiento para obtener contexto adicional que permita aumentar la generación de respuestas y la entrada en los pasos del proceso de orquestación.
Si desea saber cómo funcionan, consulte la documentación de AWS .
Herramientas potentes para el soporte de AWS Bedrock
Los agentes de Bedrock, o simplemente "agentes", comprenden la entrada de texto libre, encuentran la API correcta para activar, crean la carga útil de acuerdo con OpenAPI y saben si la llamada fue exitosa.
Al principio, no me di cuenta de que Bedrock espera que sus API cambien.
Por lo general, utilizo API Gateway para enviar mis API, que activa mis funciones Lambda. El evento enviado a la función tiene metadatos e información de API Gateway, y el cuerpo viene como una cadena codificada en JSON.
Los agentes no interactúan con una URL de API Gateway, sino con una función Lambda (o más de una), cada una de las cuales proporciona un archivo OpenAPI diferente. Los agentes invocan las funciones directamente, envían una entrada diferente a API GW y esperan una respuesta diferente a la respuesta de API Gateway habitual .
Powertools abstrae estas diferencias. Pude tomar una función Lambda que funcionaba detrás de una API Gateway, usar el controlador de eventos de Powertools para API Gateway y cambiar el tipo de controlador de eventos a controlador Bedrock, y funcionó con los agentes. ¡Increíble!
A continuación, puedes ver el flujo de eventos:
Los agentes utilizan LLM y la entrada del usuario para comprender qué API (función Lambda) invocar utilizando el archivo OpenAPI que describe la API.
Powertools se encarga del análisis de la entrada del agente Bedrock, la validación y las rutas a la función interna correcta. Cada función interna maneja una ruta API diferente, creando así un Lambda monolítico .
Su lógica empresarial personalizada se ejecuta y devuelve una respuesta que se adhiere al esquema OpenAPI.
Powertools devuelve una respuesta en formato Bedrock que contiene la respuesta de la sección 3.
Esto me lleva al problema número uno: no se puede usar la función Lambda con agentes Bedrock y una API Gateway. Solo se debe elegir uno.
Este es un problema importante. Significa que necesito duplicar mis API: una para Bedrock y otra para los clientes habituales. Las entradas y las respuestas son demasiado diferentes. Es una verdadera lástima que Bedrock no haya ampliado el modelo de API Gateway agregando contexto y encabezados a los agentes de Bedrock.
Si quieres ver una variación de TypeScript sin Powertools, te recomiendo que consultes la publicación de Lee Gilmore .
¿Qué estamos construyendo?
Crearemos un agente de Bedrock que representará a un vendedor. Le pediremos al agente que compre pedidos en nuestro nombre. Usaremos mi proyecto de código abierto de plantilla AWS Lambda Handler Cookbook que representa un servicio de pedidos. Puede realizar pedidos llamando a la API POST '/api/orders' con una carga útil JSON del nombre del cliente y la cantidad de artículos. Los pedidos se guardan en una tabla de DynamoDB mediante una función Lambda.
La plantilla de libro de recetas apareció recientemente en un artículo de AWS .
Modifiqué la plantilla y reemplacé la API Gateway con agentes Bedrock. Construiremos las siguientes partes:
Agentes con infraestructura CDK como código
Generar archivo de esquema OpenAPI
Código del controlador de funciones Lambda para soportar Bedrock
Todos los ejemplos de código se pueden encontrar en la rama bedrock .
Infraestructura
Comenzaremos con el código CDK para implementar la función Lambda y el agente.
También puedes utilizar SAM según la documentación de Powertool.
Primero, agregue las construcciones 'cdklabs' a su archivo de poesía.
Repasemos el constructo Bedrock.
Esta construcción es en un 90% la que se mostró en la excelente documentación de Powertool:
En las líneas 18-24, creamos el agente Bedrock.
En la línea 21, seleccionamos el modelo que deseamos utilizar.
En la línea 22 proporcionamos la instrucción de ingeniería rápida.
En la línea 23, preparamos el agente para ser utilizado y probado inmediatamente después de la implementación.
En las líneas 26 a 38, preparamos el grupo de acciones y conectamos la función Lambda. Obtenemos la entrada para el archivo OpenAPI. El archivo OpenAPI en este ejemplo se encuentra en el archivo 'docs/swagger/openapi.json'.
Controlador de funciones Lambda: herramientas potentes para Bedrock
Repasemos el código de la función Lambda que implementa la API del servicio de pedidos.
En la línea 17, iniciamos el controlador de eventos de Bedrock Powertools. La validación de entrada está habilitada de forma predeterminada.
En las líneas 27 a 43, definimos nuestra API POST/API/orders. Estos metadatos ayudan a Powertools a generar un archivo OpenAPI para nosotros (consulte la siguiente sección). Define la descripción de la API, el esquema de entrada, las respuestas HTTP y sus esquemas.
En las líneas 59 a 62, definimos el punto de entrada de la función. Según la ruta de entrada y el comando HTTP (POST), enrutará la solicitud del agente Bedrock a la función interna correcta. En este ejemplo, solo hay una función en la línea 20.
En las líneas 49 a 53, manejamos la entrada (¡validada automáticamente por Powertools!) y la pasamos al controlador lógico interno para crear el pedido y guardarlo en la base de datos. Esta es una implementación arquitectónica hexagonal. Puede obtener más información al respecto aquí .
En la línea 56, devolvemos un objeto de respuesta de Pydantic y Powertools maneja el formato de respuesta de Bedrock por nosotros.
Encuentra el código completo aquí .
Generando archivo OpenAPI
Powertools para AWS Lambda proporciona una manera de generar el archivo OpenAPI requerido a partir del código.
Veamos la versión simplificada a continuación:
Puede ejecutar este código y luego mover el archivo de salida a la carpeta que asigne en la construcción CDK en la línea 28.
El agente Bedrock en acción
Después de implementar nuestro servicio, podemos ingresar a la consola Bedrock y ver a nuestro nuevo agente esperándonos:
Probémoslo y charlemos con él en la consola:
¡Éxito! Comprendió que queríamos realizar un pedido, creó la entrada de carga útil, ejecutó la función Lambda con éxito e incluso mostró su salida.
Veamos qué entrada envió a la función (la imprimí de los registros de Lambda)
Como puede ver, es muy diferente del esquema de API Gateway. La línea 8 contiene todo tipo de metadatos sobre el origen del agente, la ruta de la API, la carga útil, las líneas 9 a 18 y el comando HTTP, que se muestra en la línea 20.
Verifiquemos la funcionalidad de la función y la precisión de los agentes examinando el orden que se guardó correctamente en la tabla DynamoDB.
Como puede ver, el ID del pedido coincide con la respuesta del agente y los parámetros de entrada.
Limitaciones y trampas
La documentación y los ejemplos de código de Powertools eran perfectos. Funcionó de inmediato.
Powertools hizo un excelente trabajo. Sin embargo, tuve varios problemas con los agentes de Bedrock:
Los agentes de Bedrock actualmente admiten el esquema OpenAPI 3.0.0, pero no el 3.1.0. Pydantic 2, que utilizo para definir mis modelos, genera la última versión. Tuve que cambiar el número a 3.0.0 manualmente y esperar que mi API no use ninguna característica especial de 3.1.0. Afortunadamente, no lo hizo, pero fue difícil encontrar el error, ya que se generó durante la implementación de CloudFormation ('Archivo OpenAPI rechazado') y no explicó por qué mi archivo de esquema no era adecuado. El excelente soporte de Powertool a través de su canal de Discord me ayudó. ¡Gracias, Leandro!
Su Lambda debe ser monolítico y contener todas las rutas de su OpenAPI. Una alternativa sería crear varios grupos de acciones con varios archivos OpenAPI, lo cual es factible pero no es escalable con una gran cantidad de rutas y API.
Este es un problema importante : no se puede usar la función Lambda con agentes y una API Gateway. Es necesario elegir. Esto significa que necesito duplicar mis API: una para Bedrock y otra para los clientes habituales. Las entradas y las respuestas son demasiado diferentes. Es una verdadera lástima que Bedrock no haya ampliado el modelo de API Gateway agregando contexto y encabezados a los agentes de Bedrock.
Mi agente envió un tipo de carga útil incorrecto. Marcó la carga útil como un entero, pero siguió enviando el objeto JSON como una cadena en lugar de un número. Mi API tiene una validación estricta, por lo que no convirtió la cadena en un número y falló la solicitud. Tuve que depurar el problema, lo que no fue tan fácil como esperaba. Tus resultados pueden variar con diferentes LLM; elegí el "más simple".
Resumen
Es increíble poder conversar con un "agente" que dio como resultado la creación de una entrada en DynamoDB. Y lo que es aún más sorprendente es que pude lograr que esto funcionara tan rápido. ¡Los servicios administrados con soporte de CDK son el camino a seguir!
Espero que Bedrock haga cambios de acuerdo con mis comentarios y mejore la experiencia del usuario. La implementación actual no me permite utilizarla en API de producción sin duplicar una gran cantidad de código.