Este artículo fue escrito en colaboración con Enrique Rodriguez
Prepárate para embarcarte en un emocionante viaje mientras combinamos el poder de ReactJS, Amazon Bedrock y el AWS JavaScript SDK para crear una aplicación de IA generativa con código mínimo de integración.
Integrar la IA generativa en aplicaciones existentes presenta desafíos. Muchos desarrolladores tienen poca experiencia en el entrenamiento de modelos de fundación, pero el objetivo es integrar las capacidades de IA generativa con cambios mínimos de código.
Para resolver esto, creamos una aplicación que integra el poder de la IA generativa con una llamada a la API de Amazon Bedrock desde una aplicación web SPA construida con JavaScript y el framework de React. Sin middleware, reduciendo la barrera para incorporar la generación de IA a través de una integración de código mínima.
A lo largo de este tutorial, aprenderás a utilizar las credenciales de Amazon Cognito y los Roles de IAM para acceder de forma segura a la API de Amazon Bedrock dentro de una aplicación ReactJS construida con el sistema de diseño CloudScape. Te guiaremos a través del proceso de despliegue de todos los recursos necesarios y el hosting de la aplicación utilizando AWS Amplify, simplificando el proceso de configuración y despliegue.
Para mejorar la flexibilidad y personalización del modelo de fundación (FM), demostraremos cómo asignar diferentes roles utilizando System Prompt. Al crear una tabla de Amazon DynamoDB, podrás almacenar y recuperar varios roles, permitiéndote administrar y acceder a distintos System Prompts asociados con cada rol que desees asignar al FM. Este enfoque de repositorio centralizado permite la asignación dinámica de roles y respuestas de IA personalizadas según el rol seleccionado.
¿Cómo funciona esta aplicación?
En el repositorio de esta aplicación, encontrarás el código listo para desplegar el backend y el frontend.
✅ Backend: Un grupo de usuarios de Amazon Cognito y un grupo de identidades, con un rol de AWS Identity and Access Management (rol de IAM) que contiene la política con los permisos para invocar Amazon Bedrock.
{ policyName: "amplify-permissions-custom-resources",
policyDocument: {
Version: "2012-10-17",
Statement: [
{
Resource: "*",
Action: ["bedrock:InvokeModel*", "bedrock:List*", "bedrock:Retrieve*"],
Effect: "Allow",
}
]
}
}
Consulta la guía "Integrar la autenticación y autorización de Amazon Cognito con aplicaciones web y móviles" para invocar operaciones de la API de AWS por parte de usuarios autenticados con Amazon Cognito.
Estos permisos se pueden personalizar aquí: Código del rol de IAM
✅ Frontend: una aplicación de página única (SPA) de reactjs construida con el sistema de diseño CloudScape.
Esta aplicación comprende 4 demostraciones:
- Chat con Amazon Bedrock Multimodal.
- Indicaciones del sistema.
- Bases de conocimiento para Amazon Bedrock.
- Agentes para Amazon Bedrock.
Todas las demostraciones tienen en común el uso del BedrockRuntimeClient o BedrockAgentRuntimeClient para invocar el servicio Bedrock o BedrockAgent para una interacción conversacional. El BedrockAgentClient también se utiliza para listar las bases de conocimiento de Bedrock actualmente desplegadas en la misma cuenta.
import { BedrockAgentClient} from "@aws-sdk/client-bedrock-agent"
import { BedrockAgentRuntimeClient} from "@aws-sdk/client-bedrock-agent-runtime"
Amazon Bedrock es un servicio totalmente administrado que ofrece una selección de modelos de fundación (FM) de alto rendimiento junto con un amplio conjunto de capacidades que necesitas para construir y escalar aplicaciones de IA generativa.
Para seleccionar un LLM
Para invocar un FM necesitas especificar la región, las respuestas de streaming y las credenciales de API de la autenticación de grupo de usuarios. Para los argumentos del modelo, especificas el modelo para muestrear hasta 1000 tokens y para una generación más creativa y libertad, usa una temperatura de 1. Lo hacemos con la función getModel
de llmLib.js
export const getModel = async (modelId = "anthropic.claude-instant-v1") => {
const session = await fetchAuthSession(); //Amplify helper to fetch current logged in user
let region = session.identityId.split(":")[0] //
const model = new Bedrock({
model: modelId, // model-id you can try others if you want
region: region, // app region
streaming: true, // this enables to get the response in streaming manner
credentials: session.credentials, // the user credentials that allows to invoke bedrock service
// try to limit to 1000 tokens for generation
// temperature = 1 means more creative and freedom
modelKwargs: { max_tokens_to_sample: 1000, temperature: 1 },
});
return model;
};
Para seleccionar el modelID primero listas los modelos de fundación de Amazon Bedrock usando ListFoundationModels en la función getFMs
(llmLib.js). Cada FM tiene su propia forma de invocar el modelo, y este blog se enfoca únicamente en los modelos multimodales de Anthropic.
export const getFMs = async () => {
const session = await fetchAuthSession()
let region = session.identityId.split(":")[0]
const client = new BedrockClient({ region: region, credentials: session.credentials })
A continuación se muestra un ejemplo de código para enviar un mensaje de texto al modelo Anthropic Claude 3 en Amazon Bedrock:
const body = {
messages: [
{
role: "user",
content: "Hello, how are you doing today?"
}
]
}
const response = await client.send(new InvokeModelWithResponseStreamCommand({
body: JSON.stringify(body),
contentType: "application/json",
accept: "application/json",
modelId: "claude-3"
}));
Esto envía un simple mensaje de texto "Hola, ¿cómo estás hoy?" al modelo de Claude. La respuesta contendrá la respuesta del asistente como mensaje de texto.
{"role": "user", "content": [{"type": "text", "text": "Hola, Claude"}]}
-
type
igual aimage
:
{"role": "user", "content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "/9j/4AAQSkZJRg...",
}
},
{"type": "text", "text": "¿Qué hay en esta imagen?"}
]}
Este es un ejemplo de un body:
content = [
{"type": "image", "source": {"type": "base64",
"media_type": "image/jpeg", "data": content_image}},
{"type":"text","text":text}
]
body = {
"system": "Eres un Asistente de IA, siempre responde en el idioma original del texto del usuario.",
"messages":content,"anthropic_version": anthropic_version,"max_tokens":max_tokens}
🖼️ Anthropic actualmente admite el tipo de fuente base64 para imágenes y los tipos de medios image/jpeg, image/png, image/gif e image/webp. Puedes ver la conversión de imágenes a base64 para esta aplicación en la función
buildContent
de messageHelpers.js. Consulta más ejemplos de entrada.
Crear y reutilizar prompt
La API de Mensajes nos permite agregar contexto o instrucciones al modelo a través de un System Prompt (system).
Mediante la utilización del System Prompt, podemos asignar al FM un rol específico o proporcionarle instrucciones previas antes de alimentarlo con la entrada. Para permitir que el FM asuma múltiples roles, creamos un componente de react que le permite generar un System Prompt, almacenarlo en una tabla de Amazon DynamoDB y luego seleccionarlo cuando desee asignar ese rol particular al FM.
Todas las operaciones de API para administrar prompts son manejadas por un endpoint de API GraphQL de AWS AppSync. AWS AppSync le permite crear y administrar APIs GraphQL, que proporcionan una forma flexible y eficiente de obtener y manipular datos de múltiples fuentes a través de un único endpoint. (Tutorial de AWS AppSync: resolvers de DynamoDB)
Revisemos un ejemplo de un prompt donde le decimos al FM que es un experto en JavaScript:
En el siguiente gif, el modelo proporciona código y explicaciones detalladas, como un experto.
Bases de Conocimiento para Amazon Bedrock
En esta demo, harás preguntas a las Bases de Conocimiento para Amazon Bedrock aprovechando la generación aumentada por recuperación (RAG). Debes tener al menos una base de conocimiento creada, hazlo siguiendo la guía Crear una base de conocimiento.
Las preguntas a las Bases de Conocimiento para Amazon Bedrock se harán de dos maneras:
- Amazon Bedrock Retrieve => LLM:
Lista las bases de conocimiento con ListKnowledgeBasesCommand de la siguiente manera:
import { ListKnowledgeBasesCommand } from "@aws-sdk/client-bedrock-agent"
export const getBedrockKnowledgeBases = async () => {
const session = await fetchAuthSession()
let region = session.identityId.split(":")[0]
const client = new BedrockAgentClient({ region: region, credentials: session.credentials })
const command = new ListKnowledgeBasesCommand({})
const response = await client.send(command)
return response.knowledgeBaseSummaries
}
La clase AmazonKnowledgeBaseRetriever de Langchain crea un recuperador, un objeto capaz de recuperar documentos similares a una consulta desde una base de conocimiento (en este caso es una Base de Conocimiento de Bedrock)
import { AmazonKnowledgeBaseRetriever } from "@langchain/community/retrievers/amazon_knowledge_base";
export const getBedrockKnowledgeBaseRetriever = async (knowledgeBaseId) => {
const session = await fetchAuthSession();
let region = session.identityId.split(":")[0]
const retriever = new AmazonKnowledgeBaseRetriever({
topK: 10, // devuelve los 10 documentos principales
knowledgeBaseId: knowledgeBaseId,
region: region,
clientOptions: { credentials: session.credentials }
})
return retriever
}
La ConversationalRetrievalQAChain se instancia con el recuperador y la memoria. Se encarga de la memoria, consulta al recuperador y formula la respuesta (con los documentos) utilizando la instancia llm.
import { ConversationalRetrievalQAChain } from "langchain/chains";
export const getConversationalRetrievalQAChain = async (llm, retriever, memory) => {
const chain = ConversationalRetrievalQAChain.fromLLM(
llm, retriever = retriever)
chain.memory = memory
//Aquí modificas el prompt predeterminado para agregar el prefijo Human y el sufijo Assistant necesarios por Claude.
//de lo contrario, obtendrás una excepción
//esta es la indicación que utiliza el historial de chat y la última pregunta para formular una pregunta completa e independiente
chain.questionGeneratorChain.prompt.template = "Human: " + chain.questionGeneratorChain.prompt.template +"\nAssistant:"
// Aquí finalmente respondes la pregunta utilizando los documentos recuperados.
chain.combineDocumentsChain.llmChain.prompt.template = `Human: Utiliza los siguientes fragmentos de contexto para responder la pregunta al final. Si no sabes la respuesta, simplemente di que no lo sabes, no intentes inventar una respuesta.
{context}
Pregunta: {question}
Respuesta útil:
Assistant:`
return chain
}
Código BedrockKBRetrieve.jsx
- Amazon Bedrock Recuperar y Generar:
Aquí utilizarás un servicio RAG administrado completo de AWS. No se necesitan paquetes adicionales (Langchain) ni una mayor complejidad con las indicaciones. Utilizarás solo una llamada API a BedrockAgentRuntimeClient. Además, el servicio gestiona la memoria utilizando un sessionId.
Bedrock se inicializa con BedrockAgentRuntimeClient y con RetrieveAndGenerateCommand consulta una base de conocimientos y un modelo de fundación genera respuestas basadas en los resultados recuperados. En esta demostración no se necesita Langchain.
import { BedrockAgentRuntimeClient, RetrieveAndGenerateCommand } from "@aws-sdk/client-bedrock-agent-runtime"
export const ragBedrockKnowledgeBase = async (sessionId, knowledgeBaseId, query, modelId = "anthropic.claude-instant-v1") => {
const session = await fetchAuthSession()
let region = session.identityId.split(":")[0]
const client = new BedrockAgentRuntimeClient({ region: region, credentials: session.credentials });
const input = {
input: { text: query }, // pregunta del usuario
retrieveAndGenerateConfiguration: {
type: "KNOWLEDGE_BASE",
knowledgeBaseConfiguration: {
knowledgeBaseId: knowledgeBaseId,
//su base de conocimientos existente en la misma región/cuenta
// Arn de un modelo Bedrock, en este caso saltamos a claude 2.1, el más reciente. Siéntase libre de usar otro
modelArn: `arn:aws:bedrock:${region}::foundation-model/${modelId}`, // Arn de un modelo Bedrock
},
}
}
if (sessionId) {
// puedes pasar el sessionId para continuar un diálogo.
input.sessionId = sessionId
}
const command = new RetrieveAndGenerateCommand(input);
const response = await client.send(command)
return response
}
Código BedrockKBAndGenerate.jsx
Agentes para Amazon Bedrock
Un agente de Amazon Bedrock es un componente de software que utiliza los modelos de IA proporcionados por el servicio Amazon Bedrock para ofrecer funcionalidades orientadas al usuario, como chatbots, asistentes virtuales o herramientas de generación de texto. Estos agentes se pueden personalizar y adaptar a las necesidades específicas de cada aplicación, proporcionando una interfaz de usuario para que los usuarios finales interactúen con las capacidades de IA subyacentes. Los agentes de Bedrock manejan la integración con los modelos de lenguaje, procesan las entradas del usuario, generan respuestas y, potencialmente, otras acciones basadas en la salida de los modelos de IA.
Para integrar agentes de Amazon Bedrock en esta aplicación, debes crear uno, sigue los pasos Crear un agente en Amazon Bedrock
En Amazon Bedrock, puedes crear una nueva versión de tu agente creando un alias que apunte a la nueva versión por defecto, los alias se enumeran con ListAgentAliasesCommand (llmLib.js):
import { BedrockAgentClient, ListAgentAliasesCommand } from "@aws-sdk/client-bedrock-agent";
const client = new BedrockAgentRuntimeClient({ region: region, credentials: session.credentials })
export const getBedrockAgentAliases = async (client, agent) => {
const agentCommand = new ListAgentAliasesCommand({ agentId: agent.agentId })
const response = await client.send(agentCommand)
return response.agentAliasSummaries
}
Para enviar un prompt para que el agente lo procese y responda, utilice InvokeAgentCommand
import { BedrockAgentRuntimeClient, InvokeAgentCommand } from "@aws-sdk/client-bedrock-agent-runtime";
export const invokeBedrockAgent = async (sessionId, agentId, agentAlias, query) => {
const session = await fetchAuthSession()
let region = session.identityId.split(":")[0]
const client = new BedrockAgentRuntimeClient({ region: region, credentials: session.credentials })
const input = {
sessionId: sessionId,
agentId: agentId,
agentAliasId: agentAlias,
inputText: query
}
console.log(input)
const command = new InvokeAgentCommand(input)
const response = await client.send(command,)
console.log("response:", response)
let completion = ""
let decoder = new TextDecoder("utf-8")
for await (const chunk of response.completion) {
console.log("chunk:", chunk)
const text = decoder.decode(chunk.chunk.bytes)
completion += text
console.log(text)
}
return completion
}
En el agente de este primer gif, crea un ticket para soporte técnico:
En el segundo gif, el usuario pregunta al agente sobre el estado del ticket:
Implementemos una Aplicación de IA Generativa React con Amazon Bedrock y AWS Javascript SDK
Paso 1 - Habilitar el Hosting de AWS Amplify:
La aplicación está construida con AWS Amplify. Para desplegarla en tu cuenta:
- Primero bifurca este repositorio:
https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/forks
Crea una nueva rama:
dev-branch
.Luego sigue los pasos en la guía de inicio con código existente.
En el Paso 1 Agregar rama de repositorio, selecciona la rama principal y ¿Conectando un monorepo? Elige una carpeta e ingresa
reactjs-gen-ai-apps
como directorio raíz.
- Para el siguiente paso, Configuración de compilación, selecciona
building-a-gen-ai-gen-ai-personal-assistant-reactjs-apps(this app)
como nombre de la aplicación, en Entorno selecciona Crear un nuevo entorno y escribedev
Si no existe un rol existente, crea uno nuevo para el servicio Amplify.
Implementa tu aplicación.
Paso 2 - Accede a la URL de la aplicación:
Una vez que la aplicación haya sido implementada, ve al enlace de la aplicación, que se encuentra debajo del cuadro blanco.
Cuando ingreses al enlace, aparecerá la ventana de Iniciar sesión, por lo que debes crear un Usuario de Amazon Cognito User Pool.
✅ Cómo crear un usuario
En la aplicación, ve a Entornos de backend y haz clic en Autenticación.
Luego, debajo de Autenticación, haz clic en Ver en Cognito:
En el User Pool, haga clic en el nombre de su user pool y Create User.
Cree su usuario y luego inicie sesión.
Nota: Puede crear el usuario directamente desde la aplicación cambiando False
hideSignUp: false
en App.jsx, pero esto puede introducir una falla de seguridad al dar acceso a cualquier persona.
Probemos la aplicación de IA Generativa de React con Amazon Bedrock Javascript SDK
Antes de poder utilizar un modelo de fundación en Amazon Bedrock, debe solicitar acceso a él. Siga el paso en la guía de acceso al modelo.
Ve al enlace de la aplicación e inicie sesión con el usuario que creó.
🤖🚀 ¡Pruebe y pruebe la aplicación!
Conclusión
En esta publicación, demostramos cómo puede crear una aplicación web de React que accede directamente a la API de Amazon Bedrock utilizando Amazon Cognito para la autenticación segura. Al aprovechar los servicios administrados de AWS como Cognito e IAM, puede integrar de manera transparente potentes capacidades de IA generativa en sus aplicaciones javascript sin necesidad de código de backend.
Este enfoque permite a los desarrolladores concentrarse en crear experiencias conversacionales atractivas al tiempo que aprovechan el servicio de conocimiento administrado de Amazon Bedrock. Las respuestas de streaming mejoran la experiencia del usuario al reducir los tiempos de espera y permitir interacciones más naturales con la IA conversacional.
Además, mostramos cómo puede asignar múltiples roles al modelo de fundación utilizando System Prompts almacenados en una tabla de Amazon DynamoDB. Este repositorio centralizado proporciona flexibilidad y versatilidad, permitiéndole recuperar y asignar de manera eficiente roles distintos al modelo según su caso de uso específico.
Al seguir los pasos descritos en esta publicación, puede desbloquear el potencial de la IA generativa en sus aplicaciones de React. Ya sea que esté creando una aplicación nueva desde cero o mejorando una existente, Amazon Bedrock y el AWS JavaScript SDK facilitan más que nunca la incorporación de capacidades de IA de vanguardia.
Lo alentamos a explorar los ejemplos de código y los recursos proporcionados para comenzar a crear sus propias aplicaciones de IA generativa. Si tiene alguna pregunta o comentario, déjelo a continuación. ¡Feliz codificación!
Top comments (0)