Files
supabase/apps/studio/lib/ai/bedrock.ts
T
cddc472705 Test GPT-OSS (#37710)
* try a really long context window to maximize caching

* update examples

* attempt to update packages and useChat

* update endpoints

* update zod

* zod

* update to v5

* message update

* Revert "zod"

This reverts commit ec39bac6b6.

* revert zod

* zod i

* fix complete endpoints

* remove async

* change to content

* type cleanup

* Revert the package bumps to rebuild them.

* Bump zod to 2.25.76 in all packages.

* Bump openai in all packages.

* Bump ai and ai-related packages.

* Remove unneeded files.

* Fix the rest of the migration stuff.

* Prettier fixes.

* testing new gptoss models

* sonnet as pro

* back to 3.7

* revert test

* add policy list tool

* fix

* refactor

* ai sdk 5 fixes

* refactor complete endpoint

* edge function prompt

* remove example

* use limited model for completions

* remove duplicate

* Update bedrock.ts

Co-authored-by: divit <27228526+delgado3d@users.noreply.github.com>

* add default check

* only add prefix if more then one region

* temp use api

* refactor to use openai api

* test

* remove unused import

* Prettier lint

* Fix test

* revert back to bedrock

* Tiny style fix for spacing of code blocks from edit message button

* try generate text normally

* prompt adjust

* add list style to prompt

* prompt adjust

* prompt adjust emphasise display query

* update prompts

* prompt adjust

* remove package

* prompt adjust

---------

Co-authored-by: Jordi Enric <jordi.err@gmail.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
Co-authored-by: divit <27228526+delgado3d@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2025-08-27 11:34:44 +07:00

123 lines
3.6 KiB
TypeScript

import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock'
import { LanguageModel } from 'ai'
import { createCredentialChain, fromNodeProviderChain } from '@aws-sdk/credential-providers'
import { CredentialsProviderError } from '@smithy/property-provider'
import { awsCredentialsProvider } from '@vercel/functions/oidc'
import { selectWeightedKey } from './util'
const credentialProvider = createCredentialChain(
// Vercel OIDC provider will be used for staging/production
vercelOidcProvider,
// AWS profile will be used for local development
fromNodeProviderChain({
profile: process.env.AWS_BEDROCK_PROFILE,
})
)
/**
* Creates a Vercel OIDC provider for AWS credentials.
*
* Wraps `awsCredentialsProvider` to properly handle errors
* so that it can be used in a credential chain.
*/
async function vercelOidcProvider() {
try {
return await awsCredentialsProvider({
roleArn: process.env.AWS_BEDROCK_ROLE_ARN!,
})()
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to create Vercel OIDC provider'
// Re-throw using the correct error type and `tryNextLink` option
throw new CredentialsProviderError(message, {
tryNextLink: true,
})
}
}
export async function checkAwsCredentials() {
try {
const credentials = await credentialProvider()
return !!credentials
} catch (error) {
return false
}
}
export const bedrockRegionMap = {
use1: 'us-east-1',
use2: 'us-east-2',
usw2: 'us-west-2',
euc1: 'eu-central-1',
} as const
export type BedrockRegion = keyof typeof bedrockRegionMap
export const regionPrefixMap: Record<BedrockRegion, string> = {
use1: 'us',
use2: 'us',
usw2: 'us',
euc1: 'eu',
}
export type BedrockModel = 'anthropic.claude-3-7-sonnet-20250219-v1:0' | 'openai.gpt-oss-120b-1:0'
export type RegionWeights = Record<BedrockRegion, number>
/**
* Weights for distributing requests across Bedrock regions.
* Weights are proportional to our rate limits per model per region.
*/
const modelRegionWeights: Record<BedrockModel, RegionWeights> = {
['anthropic.claude-3-7-sonnet-20250219-v1:0']: {
use1: 40,
use2: 10,
usw2: 10,
euc1: 10,
},
['openai.gpt-oss-120b-1:0']: {
use1: 0,
use2: 0,
usw2: 30,
euc1: 0,
},
}
/**
* Creates a Bedrock client that routes requests to different regions
* based on a routing key, with optional OpenAI support.
*
* Used to load balance requests across multiple regions depending on
* their capacities.
*/
export function createRoutedBedrock(routingKey?: string, useOpenAI = false) {
return async (
modelId: BedrockModel
): Promise<{ model: LanguageModel; supportsCachePoint: boolean }> => {
const regionWeights = modelRegionWeights[modelId]
// Select the Bedrock region based on the routing key and the model
const bedrockRegion = routingKey
? await selectWeightedKey(routingKey, regionWeights)
: // There's a few places where getModel is called without a routing key
// Will cause disproportionate load on use1 region
regionWeights['use1'] > 0
? 'use1'
: 'usw2'
const bedrock = createAmazonBedrock({
credentialProvider,
region: bedrockRegionMap[bedrockRegion],
})
// Cross-region models require the region prefix
const activeRegions = Object.values(regionWeights).filter((weight) => weight > 0).length
const modelName = activeRegions > 1 ? `${regionPrefixMap[bedrockRegion]}.${modelId}` : modelId
const model = bedrock(modelName)
const supportsCachePoint = modelId === 'anthropic.claude-3-7-sonnet-20250219-v1:0'
return { model, supportsCachePoint }
}
}