Skip to content

Javascript (v3): Bedrock Runtime Agent - Invoke Agent #6129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .doc_gen/metadata/bedrock-agent-runtime_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@ bedrock-agent-runtime_InvokeAgent:
- description: Invoke an agent.
snippet_tags:
- python.example_code.bedrock-agent-runtime.InvokeAgent
JavaScript:
versions:
- sdk_version: 3
github: javascriptv3/example_code/bedrock-agent-runtime
sdkguide:
excerpts:
- description:
snippet_files:
- javascriptv3/example_code/bedrock-agent-runtime/actions/invoke-agent.js
services:
bedrock-agent-runtime: {InvokeAgent}
95 changes: 95 additions & 0 deletions javascriptv3/example_code/bedrock-agent-runtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Agents for Amazon Bedrock Runtime code examples for the SDK for JavaScript (v3)

## Overview

Shows how to use the AWS SDK for JavaScript (v3) to work with Agents for Amazon Bedrock Runtime.

<!--custom.overview.start-->
<!--custom.overview.end-->

_Agents for Amazon Bedrock Runtime offers you the ability to run autonomous agents in your application._

## ⚠ Important

* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
* Running the tests might result in charges to your AWS account.
* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).

<!--custom.important.start-->
<!--custom.important.end-->

## Code examples

### Prerequisites

For prerequisites, see the [README](../../README.md#Prerequisites) in the `javascriptv3` folder.


<!--custom.prerequisites.start-->

> ⚠ You must create an agent before you can invoke it. For more information, see [Create an agent](https://docs.aws.amazon.com/bedrock/latest/userguide/agents-create.html). Additionally, you must grant access to the model you specify during agent creation. For more information, see [Model access](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/modelaccess).

<!--custom.prerequisites.end-->

### Single actions

Code excerpts that show you how to call individual service functions.

- [Invoke an agent](actions/invoke-agent.js) (`InvokeAgent`)


<!--custom.examples.start-->
<!--custom.examples.end-->

## Run the examples

### Instructions

**Note**: All code examples are written in ECMAscript 6 (ES6). For guidelines on converting to CommonJS, see
[JavaScript ES6/CommonJS syntax](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/sdk-examples-javascript-syntax.html).

**Run a single action**

```bash
node ./actions/<fileName>
```

**Run a scenario**
Most scenarios can be run with the following command:
```bash
node ./scenarios/<fileName>
```

<!--custom.instructions.start-->
<!--custom.instructions.end-->



### Tests

⚠ Running tests might result in charges to your AWS account.


To find instructions for running these tests, see the [README](../../README.md#Tests)
in the `javascriptv3` folder.



<!--custom.tests.start-->
<!--custom.tests.end-->

## Additional resources

- [Agents for Amazon Bedrock Runtime User Guide](https://docs.aws.amazon.com/bedrock/latest/userguide/agents.html)
- [Agents for Amazon Bedrock Runtime API Reference](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_Operations_Agents_for_Amazon_Bedrock_Runtime.html)
- [SDK for JavaScript (v3) Agents for Amazon Bedrock Runtime reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/bedrock-agent-runtime)

<!--custom.resources.start-->
<!--custom.resources.end-->

---

Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import {
BedrockAgentRuntimeClient,
InvokeAgentCommand,
} from "@aws-sdk/client-bedrock-agent-runtime";

/**
* @typedef {Object} ResponseBody
* @property {string} completion
*/

/**
* Invokes a Bedrock agent to run an inference using the input
* provided in the request body.
*
* @param {string} prompt - The prompt that you want the Agent to complete.
* @param {string} sessionId - An arbitrary identifier for the session.
*/
export const invokeBedrockAgent = async (prompt, sessionId) => {
const client = new BedrockAgentRuntimeClient({ region: "us-east-1" });
// const client = new BedrockAgentRuntimeClient({
// region: "us-east-1",
// credentials: {
// accessKeyId: "accessKeyId", // permission to invoke agent
// secretAccessKey: "accessKeySecret",
// },
// });

const agentId = "AJBHXXILZN";
const agentAliasId = "AVKP1ITZAA";

const command = new InvokeAgentCommand({
agentId,
agentAliasId,
sessionId,
inputText: prompt,
});

try {
let completion = "";
const response = await client.send(command);

if (response.completion === undefined) {
throw new Error("Completion is undefined");
}

for await (let chunkEvent of response.completion) {
const chunk = chunkEvent.chunk;
console.log(chunk);
const decodedResponse = new TextDecoder("utf-8").decode(chunk.bytes);
completion += decodedResponse;
}

return { sessionId: sessionId, completion };
} catch (err) {
console.error(err);
}
};

// Call function if run directly
import { fileURLToPath } from "url";
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const result = await invokeBedrockAgent("I need help.", "123");
console.log(result);
}
17 changes: 17 additions & 0 deletions javascriptv3/example_code/bedrock-agent-runtime/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "bedrock-agent-runtime-examples",
"version": "1.0.0",
"author": "Dinuda Yaggahavita <ydinuda@gmail.com>",
"license": "Apache-2.0",
"type": "module",
"scripts": {
"test": "vitest run **/*.unit.test.js"
},
"dependencies": {
"@aws-sdk/client-bedrock-agent-runtime": "^3.501.0"
},
"devDependencies": {
"vitest": "^1.2.1",
"zod": "^3.22.4"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { describe, it, expect, vi } from "vitest";
import { invokeBedrockAgent } from "../actions/invoke-agent.js";

const mocks = vi.hoisted(() => ({
clientSendResolve: () =>
Promise.resolve({
completion: [
{
chunk: {
bytes: new Uint8Array([
116, 101, 115, 116, 32, 99, 111, 109, 112, 108, 101, 116, 105,
111, 110,
]),
},
},
],
}),
clientSendReject: () => Promise.reject(new Error("Mocked error")),
send: vi.fn(),
}));

vi.mock("@aws-sdk/client-bedrock-agent-runtime", () => {
return {
BedrockAgentRuntimeClient: vi.fn(() => ({ send: mocks.send })),
InvokeAgentCommand: vi.fn(),
};
});

describe("invokeBedrockAgent", () => {
it("should return an object with sessionId and completion", async () => {
const prompt = "Test prompt";
const sessionId = "123";
mocks.send.mockImplementationOnce(mocks.clientSendResolve);

const result = await invokeBedrockAgent(prompt, sessionId);

expect(result).toEqual({
sessionId: sessionId,
completion: "test completion",
});
});

it("should log errors", async () => {
mocks.send.mockImplementationOnce(mocks.clientSendReject);
const spy = vi.spyOn(console, "error");
const prompt = "Test prompt";
const sessionId = "123";

await invokeBedrockAgent(prompt, sessionId);

expect(spy).toHaveBeenCalledWith(
expect.objectContaining({ message: "Mocked error" }),
);
});
});
11 changes: 11 additions & 0 deletions javascriptv3/example_code/bedrock-agent-runtime/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { defineConfig } from "vitest/config";

export default defineConfig({
test: {
testTimeout: 50000,
threads: false,
},
});
2 changes: 2 additions & 0 deletions javascriptv3/example_code/bedrock-runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `javas


<!--custom.prerequisites.start-->

> ⚠ You must request access to a model before you can use it. If you try to use the model (with the API or console) before you have requested access to it, you will receive an error message. For more information, see [Model access](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).

<!--custom.prerequisites.end-->

### Single actions
Expand Down
85 changes: 47 additions & 38 deletions javascriptv3/example_code/bedrock-runtime/actions/invoke-claude.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import {fileURLToPath} from "url";
import { fileURLToPath } from "url";

import {BedrockRuntimeClient, InvokeModelCommand} from "@aws-sdk/client-bedrock-runtime";
import {
AccessDeniedException,
BedrockRuntimeClient,
InvokeModelCommand,
} from "@aws-sdk/client-bedrock-runtime";

/**
* @typedef {Object} ResponseBody
Expand All @@ -18,53 +22,58 @@ import {BedrockRuntimeClient, InvokeModelCommand} from "@aws-sdk/client-bedrock-
* @returns {string} The inference response (completion) from the model.
*/
export const invokeClaude = async (prompt) => {
const client = new BedrockRuntimeClient( { region: 'us-east-1' } );
const client = new BedrockRuntimeClient({ region: "us-east-1" });

const modelId = 'anthropic.claude-v2';
const modelId = "anthropic.claude-v2";

/* Claude requires you to enclose the prompt as follows: */
const enclosedPrompt = `Human: ${prompt}\n\nAssistant:`;
/* Claude requires you to enclose the prompt as follows: */
const enclosedPrompt = `Human: ${prompt}\n\nAssistant:`;

/* The different model providers have individual request and response formats.
* For the format, ranges, and default values for Anthropic Claude, refer to:
* https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-claude.html
*/
const payload = {
prompt: enclosedPrompt,
max_tokens_to_sample: 500,
temperature: 0.5,
stop_sequences: [ '\n\nHuman:' ],
};
/* The different model providers have individual request and response formats.
* For the format, ranges, and default values for Anthropic Claude, refer to:
* https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-claude.html
*/
const payload = {
prompt: enclosedPrompt,
max_tokens_to_sample: 500,
temperature: 0.5,
stop_sequences: ["\n\nHuman:"],
};

const command = new InvokeModelCommand({
body: JSON.stringify(payload),
contentType: 'application/json',
accept: 'application/json',
modelId,
});
const command = new InvokeModelCommand({
body: JSON.stringify(payload),
contentType: "application/json",
accept: "application/json",
modelId,
});

try {
const response = await client.send(command);
const decodedResponseBody = new TextDecoder().decode(response.body);
try {
const response = await client.send(command);
const decodedResponseBody = new TextDecoder().decode(response.body);

/** @type {ResponseBody} */
const responseBody = JSON.parse(decodedResponseBody);
/** @type {ResponseBody} */
const responseBody = JSON.parse(decodedResponseBody);

return responseBody.completion;

} catch (err) {
console.error(err);
return responseBody.completion;
} catch (err) {
if (err instanceof AccessDeniedException) {
console.error(
`Access denied. Ensure you have the correct permissions to invoke ${modelId}.`,
);
} else {
throw err;
}
}
};

// Invoke the function if this file was run directly.
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const prompt = 'Complete the following: "Once upon a time..."';
console.log('\nModel: Anthropic Claude v2');
console.log(`Prompt: ${prompt}`);
const prompt = 'Complete the following: "Once upon a time..."';
console.log("\nModel: Anthropic Claude v2");
console.log(`Prompt: ${prompt}`);

const completion = await invokeClaude(prompt);
console.log('Completion:');
console.log(completion);
console.log('\n');
const completion = await invokeClaude(prompt);
console.log("Completion:");
console.log(completion);
console.log("\n");
}
Loading