Skip to content
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

feat (provider/amazon-bedrock): remove dependence on AWS SDK Bedrock library #4582

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
3c0d718
feat (provider/amazon-bedrock): remove dependency on AWS SDK Bedrock …
shaper Jan 24, 2025
9c60eab
converse operational w/ nova and claude
shaper Jan 31, 2025
9bf9cf8
streaming operational w/ messy hacks and logging
shaper Feb 1, 2025
ef37e34
clean up stream parsing
shaper Feb 1, 2025
f531e57
fix images, more cleanup
shaper Feb 1, 2025
52ab680
eventstream tests
shaper Feb 1, 2025
96e79ee
cleanup: no snake-case, base64 files, fix tests, baseUrl fn, no conte…
shaper Feb 1, 2025
e032974
more cleanup
shaper Feb 1, 2025
97924ba
changeset and de-turbo
shaper Feb 1, 2025
ad3710b
import cleanup
shaper Feb 1, 2025
e292e14
include responseHeaders in rawResponse
shaper Feb 4, 2025
54851d5
rename bedrock event stream
shaper Feb 4, 2025
8af04d9
update arn in examples, use params in arn, add acct id to env vars
shaper Feb 5, 2025
0875794
add fetch, work on settings
shaper Feb 5, 2025
3c3c5c8
naming for signing fn
shaper Feb 5, 2025
9ce8dbb
fix react/react-dom version mismatch
shaper Feb 5, 2025
3d2a85e
use dummy signing fn
shaper Feb 5, 2025
3a7db9b
use custom signing fn if passed
shaper Feb 5, 2025
4d8ba9f
clear ci cache before install
shaper Feb 5, 2025
aacaf36
more ci debugging
shaper Feb 5, 2025
b3859a9
more debugging
shaper Feb 5, 2025
fbe56fb
test logging
shaper Feb 5, 2025
640cb36
verbose test output
shaper Feb 5, 2025
f687eb6
verbose test output fix
shaper Feb 5, 2025
d972a6b
unwind ci testing
shaper Feb 5, 2025
880997c
simplified override
shaper Feb 5, 2025
54c030b
clean lock and i
shaper Feb 5, 2025
d4cfae2
headers and sign cleanup, tests
shaper Feb 7, 2025
ee73ee5
fix embed test via dummy sign fn
shaper Feb 7, 2025
6b5b7ba
simplify signing, add tests, rm export
shaper Feb 7, 2025
218c808
lockfile
shaper Feb 7, 2025
fb0045c
mock aws4fetch class
shaper Feb 7, 2025
863320b
update docs
shaper Feb 7, 2025
d616201
update changeset to major
shaper Feb 7, 2025
cbaceaa
more docs
shaper Feb 7, 2025
c840532
rm test todo
shaper Feb 7, 2025
ca9a964
support providerOptions
shaper Feb 7, 2025
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
5 changes: 5 additions & 0 deletions .changeset/wicked-yaks-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ai-sdk/amazon-bedrock': major
---

feat (provider/amazon-bedrock): remove dependence on AWS SDK Bedrock client library
109 changes: 79 additions & 30 deletions content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -90,26 +90,15 @@ const bedrock = createAmazonBedrock({
secretAccessKey: 'xxxxxxxxx',
sessionToken: 'xxxxxxxxx',
});

// or with bedrockOptions
const bedrock = createAmazonBedrock({
bedrockOptions: {
region: 'us-east-1',
credentials: {
// ...
},
},
});
```

<Note>
The top level credentials settings below fall back to environment variable
defaults. These may be set by your serverless environment without your
awareness, which can lead to merged/conflicting credential values and provider
errors around failed authentication. If you're experiencing issues try (1)
using the `bedrockOptions` object as it will take precedence over the other
settings and does not inherit environment variable values, or (2) explicitly
specifying all settings (even if `undefined`) to avoid any defaults.
The credentials settings fall back to environment variable defaults described
below. These may be set by your serverless environment without your awareness,
which can lead to merged/conflicting credential values and provider errors
around failed authentication. If you're experiencing issues be sure you are
explicitly specifying all settings (even if `undefined`) to avoid any
defaults.
</Note>

You can use the following optional settings to customize the Amazon Bedrock provider instance:
Expand All @@ -134,19 +123,6 @@ You can use the following optional settings to customize the Amazon Bedrock prov
Optional. The AWS session token that you want to use for the API calls.
It uses the `AWS_SESSION_TOKEN` environment variable by default.

- **bedrockOptions** _object_

Optional. The configuration options used by the [Amazon Bedrock Library](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-bedrock-runtime/)
(`BedrockRuntimeClientConfig`), including:

- **region** _string_
The AWS region that you want to use for the API calls.

- **credentials** _object_
The AWS credentials that you want to use for the API calls.

When `bedrockOptions` are provided, the `region`, `accessKeyId`, and `secretAccessKey` settings are ignored.

## Language Models

You can create models that call the Bedrock API using the provider instance.
Expand Down Expand Up @@ -316,3 +292,76 @@ The following optional settings are available for Bedrock Titan embedding models
| ------------------------------ | ------------------ | ------------------- |
| `amazon.titan-embed-text-v1` | 1536 | <Cross size={18} /> |
| `amazon.titan-embed-text-v2:0` | 1024 | <Check size={18} /> |

## Response Headers

The Amazon Bedrock provider will return the response headers associated with
network requests made of the Bedrock servers.

```ts
import { bedrock } from '@ai-sdk/amazon-bedrock';
import { generateText } from 'ai';

const { text } = await generateText({
model: bedrock('meta.llama3-70b-instruct-v1:0'),
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
});

console.log(result.response.headers);
```

Below is sample output where you can see the `x-amzn-requestid` header. This can
be useful for correlating Bedrock API calls with requests made by the AI SDK:

```js highlight="6"
{
connection: 'keep-alive',
'content-length': '2399',
'content-type': 'application/json',
date: 'Fri, 07 Feb 2025 04:28:30 GMT',
'x-amzn-requestid': 'c9f3ace4-dd5d-49e5-9807-39aedfa47c8e'
}
```

This information is also available with `streamText`:

```ts
import { bedrock } from '@ai-sdk/amazon-bedrock';
import { streamText } from 'ai';

const result = streamText({
model: bedrock('meta.llama3-70b-instruct-v1:0'),
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
});
for await (const textPart of result.textStream) {
process.stdout.write(textPart);
}
console.log('Response headers:', (await result.response).headers);
```

With sample output as:

```js highlight="6"
{
connection: 'keep-alive',
'content-type': 'application/vnd.amazon.eventstream',
date: 'Fri, 07 Feb 2025 04:33:37 GMT',
'transfer-encoding': 'chunked',
'x-amzn-requestid': 'a976e3fc-0e45-4241-9954-b9bdd80ab407'
}
```

## Migrating from `@ai-sdk/amazon-bedrock` pre-v2.x

The Amazon Bedrock provider was rewritten in version 2.x to remove the
dependency on the `@aws-sdk/client-bedrock-runtime` package.

The `bedrockOptions` provider setting previously available has been removed. If
you were using the `bedrockOptions` object, you should now use the `region`,
`accessKeyId`, `secretAccessKey`, and `sessionToken` settings directly instead.

Note that you may need to set all of these explicitly, e.g. even if you're not
using `sessionToken`, set it to `undefined`. If you're running in a serverless
environment, there may be default environment variables set by your containing
environment that the Amazon Bedrock provider will then pick up and could
conflict with the ones you're intending to use.
1 change: 1 addition & 0 deletions examples/ai-core/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ANTHROPIC_API_KEY=""
AWS_ACCESS_KEY_ID=""
AWS_ACCOUNT_ID=""
AWS_SECRET_ACCESS_KEY=""
AWS_REGION=""
AZURE_API_KEY=""
Expand Down
4 changes: 3 additions & 1 deletion examples/ai-core/src/generate-object/amazon-bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { z } from 'zod';

async function main() {
const result = await generateObject({
model: bedrock('anthropic.claude-3-5-sonnet-20240620-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the simple ids here?

),
schema: z.object({
recipe: z.object({
name: z.string(),
Expand Down
4 changes: 3 additions & 1 deletion examples/ai-core/src/generate-text/amazon-bedrock-chatbot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ async function main() {
}

const { text, toolCalls, toolResults, response } = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
tools: { weatherTool },
system: `You are a helpful, respectful and honest assistant. If the weather is requested use the `,
messages,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import 'dotenv/config';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
prompt:
'Invent a new fake holiday and describe its traditions. ' +
'You are a comedian and should insult the audience as much as possible.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import 'dotenv/config';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
maxTokens: 512,
messages: [
{
Expand Down
4 changes: 3 additions & 1 deletion examples/ai-core/src/generate-text/amazon-bedrock-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import fs from 'node:fs';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
maxTokens: 512,
messages: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import 'dotenv/config';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
messages: [
{
role: 'user',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { bedrock } from '@ai-sdk/amazon-bedrock';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-5-sonnet-20240620-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
tools: {
weather: weatherTool,
cityAttractions: tool({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { bedrock } from '@ai-sdk/amazon-bedrock';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
maxTokens: 512,
tools: {
weather: weatherTool,
Expand Down
7 changes: 5 additions & 2 deletions examples/ai-core/src/generate-text/amazon-bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import 'dotenv/config';

async function main() {
const result = await generateText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
prompt: 'Invent a new holiday and describe its traditions.',
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
prompt: 'Give me an overview of the New Zealand Fiordland National Park.',
});

console.log(result.text);
console.log();
console.log('Token usage:', result.usage);
console.log('Finish reason:', result.finishReason);
console.log('Response headers:', result.response.headers);
}

main().catch(console.error);
4 changes: 3 additions & 1 deletion examples/ai-core/src/stream-object/amazon-bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { z } from 'zod';

async function main() {
const result = streamObject({
model: bedrock('anthropic.claude-3-5-sonnet-20240620-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
schema: z.object({
characters: z.array(
z.object({
Expand Down
4 changes: 3 additions & 1 deletion examples/ai-core/src/stream-text/amazon-bedrock-chatbot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ async function main() {
messages.push({ role: 'user', content: userInput });

const result = streamText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
tools: {
weather: tool({
description: 'Get the weather in a location',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { weatherTool } from '../tools/weather-tool';

async function main() {
const result = streamText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
tools: {
weather: weatherTool,
cityAttractions: {
Expand Down
4 changes: 3 additions & 1 deletion examples/ai-core/src/stream-text/amazon-bedrock-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import fs from 'node:fs';

async function main() {
const result = streamText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
maxTokens: 512,
messages: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import 'dotenv/config';

async function main() {
const result = streamText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
maxTokens: 512, // artificial limit for demo purposes
maxSteps: 5,
experimental_continueSteps: true,
Expand Down
4 changes: 3 additions & 1 deletion examples/ai-core/src/stream-text/amazon-bedrock-pdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import fs from 'node:fs';

async function main() {
const result = streamText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
messages: [
{
role: 'user',
Expand Down
7 changes: 5 additions & 2 deletions examples/ai-core/src/stream-text/amazon-bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import 'dotenv/config';

async function main() {
const result = streamText({
model: bedrock('anthropic.claude-3-haiku-20240307-v1:0'),
prompt: 'Invent a new holiday and describe its traditions.',
model: bedrock(
`arn:aws:bedrock:${process.env.AWS_REGION}:${process.env.AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0`,
),
prompt: 'Give me an overview of the New Zealand Fiordland National Park.',
});

for await (const textPart of result.textStream) {
Expand All @@ -15,6 +17,7 @@ async function main() {
console.log();
console.log('Token usage:', await result.usage);
console.log('Finish reason:', await result.finishReason);
console.log('Response headers:', (await result.response).headers);
}

main().catch(console.error);
6 changes: 3 additions & 3 deletions packages/amazon-bedrock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
"dependencies": {
"@ai-sdk/provider": "1.0.7",
"@ai-sdk/provider-utils": "2.1.6",
"@aws-sdk/client-bedrock-runtime": "^3.663.0"
"@smithy/eventstream-codec": "^4.0.1",
"@smithy/util-utf8": "^4.0.0",
"aws4fetch": "^1.0.20"
},
"devDependencies": {
"@smithy/types": "^3.5.0",
"@types/node": "^18.19.54",
"@vercel/ai-tsconfig": "workspace:*",
"aws-sdk-client-mock": "^4.0.2",
"tsup": "^8.3.0",
"typescript": "5.6.3",
"zod": "3.23.8"
Expand Down
Loading
Loading