Incorpora IA generativa a una aplicación web de JavaScript
Tags: javascript, aws, llm, genai
Published: 2024-02-20 19:52:41

🇻🇪🇨🇱 [Dev.to](https://dev.to/elizabethfuentes12) [Linkedin](https://www.linkedin.com/in/lizfue/) [GitHub](https://github.com/elizabethfuentes12/) [Twitter](https://twitter.com/elizabethfue12) [Instagram](https://www.instagram.com/elifue.tech) [Youtube](https://www.youtube.com/channel/UCr0Gnc-t30m4xyrvsQpNp2Q)
[Linktr](https://linktr.ee/elizabethfuentesleone)

---
# Crea una aplicación React GenAI con Amazon Bedrock y AWS SDK

Este artículo fue escrito en colaboración con [Enrique Rodriguez](https://dev.to/ensamblador)

{% embed https://dev.to/ensamblador %}

Integrar la IA generativa en las aplicaciones existentes presenta desafíos. Muchos desarrolladores tienen una experiencia limitada en el entrenamiento de modelos básicos, pero el objetivo es integrar las capacidades de la IA generativa con un mínimo de cambios en el código.

Para solucionarlo, creamos una aplicación que integra el poder de la IA generativa con una llamada a la [Amazon Bedrock API](https://docs.aws.amazon.com/bedrock/latest/APIReference/welcome.html)  desde una aplicación web[SPA](https://developer.mozilla.org/en-US/docs/Glossary/SPA) creada con JavaScript y React Framework. Sin middleware, se reduce la barrera para incorporar la generación de IA mediante una integración mínima del código.

En este blog aprenderás a usar [Amazon Cognito](https://aws.amazon.com/pm/cognito/) credenciales y funciones de IAM que invocar [Amazon Bedrock](https://aws.amazon.com/bedrock/) La API en una aplicación basada en reacciones con JavaScript y el sistema de diseño de [CloudScape](https://cloudscape.design/) design system. Desplegarás todos los recursos y alojarás la aplicación usando [AWS Amplify](https://aws.amazon.com/amplify/).

![Authentication](https://assets.community.aws/a/2cdbKCbYGP6jhUBL1fe5NjFHz0g/auth-jpg.webp)


## ¿Cómo funciona esta aplicación?

En el [repository of this application](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/), encontrarás el código listo para implementar el backend y el frontend.

✅ **Backend:** Un grupo de usuarios e identidades de Amazon Cognito, con un [AWS Identity and Access Managemen Role](https://docs.aws.amazon.com/es_es/IAM/latest/UserGuide/id_roles.html) (IAM Role) 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",
                    }
                ]
            }
        }
```

Revisa la guia ["Integrating Amazon Cognito authentication and authorization with web and mobile apps"](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html) configura e invoca la API para la autenticación y autorización de los usuarios.

> Estos permisos se pueden personalizar aquí: [IAM Role Code](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/blob/main/reactjs-gen-ai-apps/amplify/backend/awscloudformation/override.ts)

✅ **Frontend:**  una aplicación Reactjs de una sola página (SPA) y [CloudScape](https://cloudscape.design/) como sistema de diseño.

Esta aplicación incluye 2 demostraciones:
- Chatea con Amazon Bedrock
- Bases de conocimiento de Amazon Bedrock

![demos menu](https://assets.community.aws/a/2cdc3cMlEAIcmSmCjLqeQk1w5o6/demos_menu-jpg.webp)

Todas las demostraciones tienen en común el uso del [BedrockRuntimeClient](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/bedrock-runtime/) or [BedrockAgentRuntimeClient](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/bedrock-agent-runtime/) invocar el servicio Bedrock o BedrockAgent para una interacción conversacional. El [BedrockAgentClient](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/bedrock-agent/) se usa también para listas las bases de conocimiento de Bedrock actuales desplegadas en la misma cuenta.

``` Javascript
import { BedrockAgentClient} from "@aws-sdk/client-bedrock-agent"
import { BedrockAgentRuntimeClient} from "@aws-sdk/client-bedrock-agent-runtime"
```

[Amazon  Bedrock](https://aws.amazon.com/bedrock/) es un servicio totalmente gestionado que ofrece una selección de modelos básicos (FM) de alto rendimiento junto con un amplio conjunto de capacidades que necesitas para crear aplicaciones de IA generativas.

### Un ejemplo de un modelo lingüístico amplio

Para usar un modelo en tu aplicación (por ejemplo [anthropic.claude-instant-v1](https://aws.amazon.com/bedrock/claude/)) inicializas [Bedrock Class from Langchain](https://js.langchain.com/docs/integrations/llms/bedrock). Tienes que especificar la región, las respuestas de streaming y las credenciales de la API del [user pool authentication](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html). Para los argumentos del modelo, especificas el modelo para muestrear hasta 1000 fichas y, para mayor creatividad y libertad de generación, utiliza una temperatura de 1.

```Javascript
export const getModel = async () => {
    const session = await fetchAuthSession(); //Amplify helper to fetch current logged in user
    const model = new Bedrock({
        model: "anthropic.claude-instant-v1", // model-id you can try others if you want
        region: "us-east-1", // 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;
};
```

> **Code** --> [llmLib.js](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/blob/main/reactjs-gen-ai-apps/src/llmLib.js)

Te explicaremos cada grupo de demos para destacar sus diferencias.

### Primero: charla con Amazon Bedrock

![Chat With Amazon Bedrock](https://assets.community.aws/a/2cdcy1xpIInW6kfqv86bTVSsMJy/chat_with_amazon_bedrock-jpg.webp)

Aquí hablarás directamente con el modelo de lenguaje grande (LLM) implementado por la API de Bedrock a través de un [chain](https://js.langchain.com/docs/modules/chains/), de dos maneras diferentes:

**- Chat Q&A:**  Envía un prompt y el modelo responde con una salida generada.

![Chat Q&A](https://assets.community.aws/a/2cdcnFg3O9RaRC0l6FsSCPquKXg/chat_q_a-jpg.webp)


**- Chat with Memory:** Envía un prompt junto con los mensajes anteriores (si existen) y el modelo responde con un resultado generado. Esta implementación usa memoria local.

![Chat with Memory](https://assets.community.aws/a/2cdd4facscABEceMqZShfk2VG1r/chat_with_memory-jpg.webp)

Este chat está creado con un [ConversationChain](https://api.js.langchain.com/classes/langchain_chains.ConversationChain.html) con[Buffer Memory](https://js.langchain.com/docs/modules/memory/types/buffer_memory_chat) para almacenar y pasar los cuadros de diálogo. Hay otros tipos de memoria, más información en [Working With Your Live Data Using LangChain](https://community.aws/posts/working-with-your-live-data-using-langchain).  

Para configurar esta demostración, es necesario iniciar  [Bedrock](https://js.langchain.com/docs/integrations/llms/bedrock) library para Langchain,  [ConservationChain](https://js.langchain.com/docs/modules/chains/) para gestionar la conversación y [BufferMemory](https://js.langchain.com/docs/modules/memory/types/buffer) para invocar el uso de la memoria.

``` Javascript
import { Bedrock } from "@langchain/community/llms/bedrock/web";
import { ConversationChain} from "langchain/chains";
import { BufferMemory } from "langchain/memory";
```

```Javascript
// create a memory object
const memory = new BufferMemory({ humanPrefix: "H",  memoryKey:"chat_history"});
```

**¿Por qué HumanPrefix: «H»?**

[Anthropic Claude](https://aws.amazon.com/bedrock/claude/) ha recibido entrenamiento para entender los términos de [Human: and Assistant:](https://docs.anthropic.com/claude/docs/human-and-assistant-formatting) indicators. For memory you use "H:" to identify the human part (instead of Human:) como indicadores. Para la memoria, usas la «H»: para identificar la parte humana (en lugar de la humana:) y evitar confusiones entre modelos sobre dónde comienza la última instrucción humana.

La cadena analizará chat_history  objeto de memoria para recuperar los diálogos  anteriores.

### Segundo: Bases de conocimiento de Amazon Bedrock

En esta demostración, harás preguntas a [Knowledge Bases for Amazon Bedrock](https://aws.amazon.com/bedrock/knowledge-bases/) aprovechando el [retrieval augmented generation (RAG)](https://aws.amazon.com/what-is/retrieval-augmented-generation/). Debes tener al menos una base de conocimientos creada, hazlo siguiendo la guia [Create a knowledge base](https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-create.html).

Las preguntas a las bases de conocimiento de Amazon Bedrock se formularán de dos maneras:

![Knowledge Bases for Amazon Bedrock](https://assets.community.aws/a/2cddGn1Xekhol4lekLusbgM3ZbC/knowledge_bases-jpg.webp)

**- Amazon Bedrock Retrieve => LLM:** 

![Amazon Bedrock Retrieve => LLM](https://assets.community.aws/a/2cddNbYSTORYQtFgh30eN059FBl/bedrock_retrieve_LLM-jpg.webp)

Lista las bases de conocimiento con [ListKnowledgeBasesCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-bedrock-agent/Class/ListKnowledgeBasesCommand/)de la siguiente manera:

```Javascript
import { ListKnowledgeBasesCommand } from "@aws-sdk/client-bedrock-agent"

export const getBedrockKnowledgeBases = async () => {
    const session = await fetchAuthSession()
    const client = new BedrockAgentClient({ region: "us-east-1", credentials: session.credentials })
    const command = new ListKnowledgeBasesCommand({})
    const response = await client.send(command)
    return response.knowledgeBaseSummaries
}
```
La clase[AmazonKnowledgeBaseRetriever](https://js.langchain.com/docs/integrations/retrievers/bedrock-knowledge-bases) de Langchain crea un retriever, un objeto capaz de recuperar documentos similares a una consulta de una base de conocimientos (en este caso es una base de conocimientos de Bedrock)

```Javascript
import { AmazonKnowledgeBaseRetriever } from "@langchain/community/retrievers/amazon_knowledge_base";

export const getBedrockKnowledgeBaseRetriever = async (knowledgeBaseId) => {
    const session = await fetchAuthSession();

    const retriever = new AmazonKnowledgeBaseRetriever({
        topK: 10, // return top 10 documents
        knowledgeBaseId: knowledgeBaseId,
        region: "us-east-1",
        clientOptions: { credentials: session.credentials }
    })

    return retriever
}
```

El [ConversationalRetrievalQAChain](https://api.js.langchain.com/classes/langchain_chains.ConversationalRetrievalQAChain.html) se instancia con el retriever y la memoria. Se ocupa la memoria, consulta al retriever y formula la respuesta (con los documentos) mediante la instancia de llm.

```Javascript
import { ConversationalRetrievalQAChain } from "langchain/chains";

export const getConversationalRetrievalQAChain = async (llm, retriever, memory) => {

    const chain = ConversationalRetrievalQAChain.fromLLM(
        llm, retriever = retriever)
    chain.memory = memory

    //Here you modify the default prompt to add the Human prefix and Assistant suffix needed by Claude.
    //otherwise you get an exception
    //this is the prompt that uses chat history and last question to formulate a complete standalone question

    chain.questionGeneratorChain.prompt.template = "Human: " + chain.questionGeneratorChain.prompt.template +"\nAssistant:"
     // Here you finally answer the question using the retrieved documents.

    chain.combineDocumentsChain.llmChain.prompt.template = `Human: Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. 

{context}

Question: {question}
Helpful Answer:
Assistant:`

return chain
}
```


**- Amazon Bedrock Retrieve & Generate:** 

Aquí utilizarás un servicio RAG gestionado completamente por AWS. No se necesitan paquetes adicionales (Langchain) ni aumentar la complejidad con prompt. Solo utilizarás una llamada a la API para **BedrockAgentRuntimeClient**. Además, el servicio gestiona la memoria mediante un **sessionId**. 

![Amazon Bedrock Retrieve & Generate](https://assets.community.aws/a/2cddiTw4UNefE81x5XWQoyhECYr/retrieve_and_generate-jpg.webp)

Bedrock se inicializa con [BedrockAgentRuntimeClient](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-bedrock-agent-runtime/Class/BedrockAgentRuntimeClient/) y [RetrieveAndGenerateCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-bedrock-agent-runtime/Class/RetrieveAndGenerateCommand/) consulta una base de conocimientos y un FM genera la respuestas en función de los resultados recuperados. En esta demostración no se necesita Langchain.

```Javascript
import { BedrockAgentRuntimeClient, RetrieveAndGenerateCommand } from "@aws-sdk/client-bedrock-agent-runtime"

export const ragBedrockKnowledgeBase = async (sessionId, knowledgeBaseId, query) => {
    const session = await fetchAuthSession()
    const client = new BedrockAgentRuntimeClient({ region: "us-east-1", credentials: session.credentials });
    const input = {
        input: { text: query }, // user question
        retrieveAndGenerateConfiguration: {
            type: "KNOWLEDGE_BASE",
            knowledgeBaseConfiguration: {
                knowledgeBaseId: knowledgeBaseId,
                //your existing KnowledgeBase in the same region/ account
                // Arn of a Bedrock model, in this case we jump to claude 2.1, the latest. Feel free to use another
                modelArn: "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-v2:1", // Arn of a Bedrock model
            },
        }
    }

    if (sessionId) {
        // you can pass the sessionId to continue a dialog.
        input.sessionId = sessionId
    }

    const command = new RetrieveAndGenerateCommand(input);
    const response = await client.send(command)
    return response
}
```


## Vamos a implementar la aplicación de IA generativa React con Amazon Bedrock y AWS Javascript SDK

### Paso 1: Habilitar el host de AWS Amplify:

La aplicación está creada con [AWS Amplify](https://docs.aws.amazon.com/amplify/latest/userguide/welcome.html). Para implementarlo en tu cuenta:

1. primero [fork](https://docs.github.com/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) este repo: 

```
https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/forks
```

2. Crea una [Nueva branch](https://docs.github.com/en/desktop/making-changes-in-a-branch/managing-branches-in-github-desktop): `dev-branch`.

3. Sigue los pasos en la guia de [Getting started with existing code guide](https://docs.aws.amazon.com/amplify/latest/userguide/getting-started.html). 

4. En **Step 1 Add repository branch**,  selecciona la branch dev-branch y en **Connecting a monorepo? Pick a folder** y escribe reactjs-gen-ai-apps como directorio raíz.

![Add repository branch](https://assets.community.aws/a/2cde3ATyQhQjhegJz5w6n3cHXmz/repository_branch-jpg.webp)

5. Para el próximo paso, **Build settings**, selecciona `building-a-gen-ai-gen-ai-personal-assistant-reactjs-apps(this app)` como nombre de App, en Enviroment selecciona **Create a new envitoment** y escribe `dev`

![App build and test settings](https://assets.community.aws/a/2cde8qGNpmapBi87nftPMchdQNS/build_settings-jpg.webp)

6. Si no hay ningún ROLE existente, crea uno [nuevo para service Amplify](https://docs.aws.amazon.com/amplify/latest/userguide/how-to-service-role-amplify-console.html).

7. Despliega tu aplicación.

### Paso 2: Acceso a la URL de la aplicación:

Una vez desplegada la aplicación, ve al enlace de la aplicación que se encuentra debajo del cuadro blanco.

![Amplify Deploy](https://assets.community.aws/a/2cdeHSfiKXRByvSPjPZXmYbyEPM/amplify_done-jpg.webp)

Al introducir el enlace, aparecerá la ventana Iniciar sesión, por lo que debes crear un usuario del [Amazon Cognito User Pool](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) User.

![Sing In Window](https://assets.community.aws/a/2cdeLe0NQR1Rgke5Xk8pMoHzdTB/sing_in-jpg.webp)

#### ✅  Cómo crear un usuario

En la aplicación, ve a  **Backend environments** y haz clic en Autenticación

![Backend environments](https://assets.community.aws/a/2cdeQsjNgT2fTFdDIIovhdARVso/backend_env-jpg.webp)

Luego, en Autenticación, haz clic en **View in Cognito**:

![View in Cognito](https://assets.community.aws/a/2cdefQMpji4U3FWPDS9sNoGwqqQ/view_in_cognito-jpg.webp)

En el **User Pool**, haz clic en el nombre de tu grupo de usuarios y **Create User**.

[Create your user](https://docs.aws.amazon.com/cognito/latest/developerguide/managing-users.html?icmpid=docs_cognito_console_help_panel) and then sing in.

> **Note:** Puedes crear el usuario directamente desde la aplicación cambiando Falso `hideSignUp: false` en [App.jsx](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/blob/main/reactjs-gen-ai-apps/src/App.jsx), pero esto puede introducir un fallo de seguridad al dar a cualquiera acceso a él.

## Probemos la aplicación de IA generativa React con el SDK de Javascript de Amazon Bedrock

Antes de poder utilizar un modelo de base en Amazon Bedrock, debes solicitar acceso a él. Sigue la guia de [Add model access guide](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html). 

Ve al enlace de la aplicación e inicia sesión con el usuario que has creado.

### 🤖🚀 ¡Prueba la aplicación!

✅ Chat with Amazon Bedrock:  

![Chat Q&A](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/raw/main/imagenes/demo-q-a.gif)

✅ Haz preguntas de seguimiento y comprueba las funciones multilingües del modelo

![Chat Memory](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/raw/main/imagenes/demo-memory.gif)

✅ Consulta la base de conocimientos con el LLM para obtener la mejor respuesta

![Chat LLM](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/raw/main/imagenes/demo-LLM.gif)

✅ Por último, consulta la base de datos de conocimientos directamente sin intermediarios

![Chat LLM](https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/raw/main/imagenes/demo-bedrock-ret.gif)

## Conclusión

En este blog, has creado una aplicación web de React que puede acceder directamente a la API de Amazon Bedrock mediante la autenticación de Amazon Cognito. La integración segura de servicios de IA generativa como Bedrock en una interfaz de React se puede lograr aprovechando los servicios gestionados de AWS, como Cognito e IAM.

Con esto, puedes incorporar el poder de IA generativa de Amazon Bedrock en las aplicaciones React nuevas y existentes. Esto permite a los desarrolladores centrarse en crear experiencias de conversación y RAG atractivas con un servicio de conocimiento gestionado, sin necesidad de código de fondo. También demuestra el poder de las respuestas en streaming, que mejoran la experiencia de usuario y los tiempos de espera con la IA conversacional.

## 🚀 Algunos enlaces para que sigas aprendiendo y construyendo:

- [Amplify Workshops](https://workshops.aws/categories/Amplify)
- [Amplify JavaScript Sample Applications](https://github.com/aws-amplify/amplify-js-samples)
- [Actions and scenarios using SDK for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/javascript_code_examples_categorized.html)

{% embed https://dev.to/elizabethfuentes12 %}
{% embed https://dev.to/ensamblador %}

---

🇻🇪🇨🇱 [Dev.to](https://dev.to/elizabethfuentes12) [Linkedin](https://www.linkedin.com/in/lizfue/) [GitHub](https://github.com/elizabethfuentes12/) [Twitter](https://twitter.com/elizabethfue12) [Instagram](https://www.instagram.com/elifue.tech) [Youtube](https://www.youtube.com/channel/UCr0Gnc-t30m4xyrvsQpNp2Q)
[Linktr](https://linktr.ee/elizabethfuentesleone)