Add Generative AI to a JavaScript Web App 2.0
Get ready to embark on an exciting journey as we combine the power of Amazon Bedrock, ReactJS and the AWS JavaScript SDK to create a generative AI application with minimal integration code.

1
2
3
4
5
6
7
8
9
10
11
12
{ policyName: "amplify-permissions-custom-resources",
policyDocument: {
Version: "2012-10-17",
Statement: [
{
Resource: "*",
Action: ["bedrock:InvokeModel*", "bedrock:List*", "bedrock:Retrieve*"],
Effect: "Allow",
}
]
}
}
This permissions can be customized here: IAM Role Code
- Chat with Amazon Bedrock Multimodal.
- System Prompts.
- Knowledge Bases for Amazon Bedrock.
- Agents for Amazon Bedrock.

1
2
import { BedrockAgentClient} from "@aws-sdk/client-bedrock-agent"
import { BedrockAgentRuntimeClient} from "@aws-sdk/client-bedrock-agent-runtime"
getModel
function of llmLib.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
};
getFMs
function ( llmLib.js ). Each FM has its own way of invoking the model, and this blog is only focusing on the multimodal models of Anthropic.1
2
3
4
5
6
7
8
9
export const getFMs = async () => {
const session = await fetchAuthSession()
let region = session.identityId.split(":")[0]
const client = new BedrockClient({ region: region, credentials: session.credentials })
const input = { byProvider: "Anthropic", byOutputModality: "TEXT",byInferenceType: "ON_DEMAND"}
const command = new ListFoundationModelsCommand(input)
const response = await client.send(command)
return response.modelSummaries
}


1
2
3
4
5
6
7
8
9
10
11
const session = await fetchAuthSession()
let region = session.identityId.split(":")[0]
const client = new BedrockRuntimeClient({ region: region, credentials: session.credentials })
const input = {
body: JSON.stringify(body),
contentType: "application/json",
accept: "application/json",
modelId: modelId
}
const command = new InvokeModelWithResponseStreamCommand(input)
const response = await client.send(command)
messages=[{"role": "user", "content": content}]
.role
(user or assistant) and content. The content
can be in either a single string or an array of content blocks, each block having its own designated type
(text or image).type
equaltext
:
1
{"role": "user", "content": [{"type": "text", "text": "Hello, Claude"}]}
type
equalimage
:
1
2
3
4
5
6
7
8
9
10
11
{"role": "user", "content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "/9j/4AAQSkZJRg...",
}
},
{"type": "text", "text": "What is in this image?"}
]}
- This is an example of a body:
1
2
3
4
5
6
7
8
9
10
```
content = [
{"type": "image", "source": {"type": "base64",
"media_type": "image/jpeg", "data": content_image}},
{"type":"text","text":text}
]
body = {
"system": "You are an AI Assistant, always reply in the original user text language.",
"messages":content,"anthropic_version": anthropic_version,"max_tokens":max_tokens}
```
🖼️ Anthropic currently support the base64 source type for images, and the image/jpeg, image/png, image/gif, and image/webp media types. You can see the conversion of images to base64 for this app inbuildContent
function of messageHelpers.js. See more input examples.





1
2
3
4
5
6
7
8
9
10
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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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, // return top 10 documents
knowledgeBaseId: knowledgeBaseId,
region: region,
clientOptions: { credentials: session.credentials }
})
return retriever
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 }, // 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:${region}::foundation-model/${modelId}`, // 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
}
1
2
3
4
5
6
7
8
9
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
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
}
- first fork this repo:
1
https://github.com/build-on-aws/building-reactjs-gen-ai-apps-with-amazon-bedrock-javascript-sdk/forks
- Create a New branch:
dev-branch
. - Then follow the steps in Getting started with existing code guide.
- In Step 1 Add repository branch, select main branch and Connecting a monorepo? Pick a folder and enter
reactjs-gen-ai-apps
as a root directory.Add repository branch - For the next Step, Build settings, select
building-a-gen-ai-gen-ai-personal-assistant-reactjs-apps(this app)
as App name, in Enviroment select Create a new envitoment and writedev.

- If there is no existing role, create a new one to service Amplify.
- Deploy your app.




hideSignUp: false
in App.jsx, but this can introduce a security flaw by giving anyone access to it.Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.