diff --git a/.gitignore b/.gitignore index ea31e4fd..8523c18e 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,6 @@ test/integ/chatprompt.integ.snapshot/manifest.json test/integ/chatprompt.integ.snapshot/**/manifest.json test/integ/chatprompt.integ.snapshot/tree.json test/integ/chatprompt.integ.snapshot/**/tree.json -test/integ/.tmp test/integ/inference-profiles.integ.snapshot/asset.* test/integ/inference-profiles.integ.snapshot/**/asset.* test/integ/inference-profiles.integ.snapshot/cdk.out @@ -73,6 +72,15 @@ test/integ/inference-profiles.integ.snapshot/manifest.json test/integ/inference-profiles.integ.snapshot/**/manifest.json test/integ/inference-profiles.integ.snapshot/tree.json test/integ/inference-profiles.integ.snapshot/**/tree.json +test/integ/.tmp +test/integ/prompt-router.integ.snapshot/asset.* +test/integ/prompt-router.integ.snapshot/**/asset.* +test/integ/prompt-router.integ.snapshot/cdk.out +test/integ/prompt-router.integ.snapshot/**/cdk.out +test/integ/prompt-router.integ.snapshot/manifest.json +test/integ/prompt-router.integ.snapshot/**/manifest.json +test/integ/prompt-router.integ.snapshot/tree.json +test/integ/prompt-router.integ.snapshot/**/tree.json test/patterns/gen-ai/aws-aoss-cw-dashboard/integ-tests/.tmp test/patterns/gen-ai/aws-aoss-cw-dashboard/integ-tests/aws-aoss-cw-dashboard.integ.snapshot/asset.* test/patterns/gen-ai/aws-aoss-cw-dashboard/integ-tests/aws-aoss-cw-dashboard.integ.snapshot/**/asset.* diff --git a/.npmignore b/.npmignore index 31b2a725..57b69c72 100644 --- a/.npmignore +++ b/.npmignore @@ -23,8 +23,9 @@ tsconfig.tsbuildinfo /.eslintrc.json !.jsii test/integ/chatprompt.integ.snapshot -test/integ/.tmp test/integ/inference-profiles.integ.snapshot +test/integ/.tmp +test/integ/prompt-router.integ.snapshot test/patterns/gen-ai/aws-aoss-cw-dashboard/integ-tests/.tmp test/patterns/gen-ai/aws-aoss-cw-dashboard/integ-tests/aws-aoss-cw-dashboard.integ.snapshot test/patterns/gen-ai/aws-llama-index-data-loader/integ-tests/.tmp diff --git a/.projen/deps.json b/.projen/deps.json index c4696be7..62ba1744 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -6,7 +6,7 @@ }, { "name": "@aws-cdk/integ-tests-alpha", - "version": "2.174.0-alpha.0", + "version": "2.174.1-alpha.0", "type": "build" }, { @@ -137,7 +137,7 @@ }, { "name": "aws-cdk-lib", - "version": "^2.174.0", + "version": "^2.174.1", "type": "peer" }, { diff --git a/.projen/tasks.json b/.projen/tasks.json index 014f8c5e..e26498b7 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -416,6 +416,69 @@ } ] }, + "integ:prompt-router:assert": { + "name": "integ:prompt-router:assert", + "description": "assert the snapshot of integration test 'prompt-router'", + "steps": [ + { + "exec": "[ -d \"test/integ/prompt-router.integ.snapshot\" ] || (echo \"No snapshot available for integration test 'prompt-router'. Run 'projen integ:prompt-router:deploy' to capture.\" && exit 1)" + }, + { + "exec": "cdk synth --app \"ts-node -P tsconfig.dev.json test/integ/prompt-router.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata -o test/integ/.tmp/prompt-router.integ/assert.cdk.out > /dev/null" + }, + { + "exec": "diff -r -x asset.* -x cdk.out -x manifest.json -x tree.json test/integ/prompt-router.integ.snapshot/ test/integ/.tmp/prompt-router.integ/assert.cdk.out/" + } + ] + }, + "integ:prompt-router:deploy": { + "name": "integ:prompt-router:deploy", + "description": "deploy integration test 'prompt-router' and capture snapshot", + "steps": [ + { + "exec": "rm -fr test/integ/.tmp/prompt-router.integ/deploy.cdk.out" + }, + { + "exec": "cdk deploy --app \"ts-node -P tsconfig.dev.json test/integ/prompt-router.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata '**' --require-approval=never -o test/integ/.tmp/prompt-router.integ/deploy.cdk.out" + }, + { + "exec": "rm -fr test/integ/prompt-router.integ.snapshot" + }, + { + "exec": "mv test/integ/.tmp/prompt-router.integ/deploy.cdk.out test/integ/prompt-router.integ.snapshot" + }, + { + "spawn": "integ:prompt-router:destroy" + } + ] + }, + "integ:prompt-router:destroy": { + "name": "integ:prompt-router:destroy", + "description": "destroy integration test 'prompt-router'", + "steps": [ + { + "exec": "cdk destroy --app test/integ/prompt-router.integ.snapshot '**' --no-version-reporting" + } + ] + }, + "integ:prompt-router:snapshot": { + "name": "integ:prompt-router:snapshot", + "description": "update snapshot for integration test \"prompt-router\"", + "steps": [ + { + "exec": "cdk synth --app \"ts-node -P tsconfig.dev.json test/integ/prompt-router.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata -o test/integ/prompt-router.integ.snapshot > /dev/null" + } + ] + }, + "integ:prompt-router:watch": { + "name": "integ:prompt-router:watch", + "description": "watch integration test 'prompt-router' (without updating snapshots)", + "steps": [ + { + "exec": "cdk watch --app \"ts-node -P tsconfig.dev.json test/integ/prompt-router.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata '**' -o test/integ/.tmp/prompt-router.integ/deploy.cdk.out" + } + ] + }, "integ:snapshot-all": { "name": "integ:snapshot-all", "description": "update snapshot for all integration tests", @@ -426,6 +489,9 @@ { "spawn": "integ:inference-profiles:snapshot" }, + { + "spawn": "integ:prompt-router:snapshot" + }, { "spawn": "integ:aws-aoss-cw-dashboard:snapshot" }, @@ -565,6 +631,9 @@ { "spawn": "integ:inference-profiles:assert" }, + { + "spawn": "integ:prompt-router:assert" + }, { "spawn": "integ:aws-aoss-cw-dashboard:assert" }, diff --git a/.projenrc.ts b/.projenrc.ts index 4bb9d1aa..fa66d034 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -29,7 +29,7 @@ import { const GITHUB_USER = 'awslabs'; const PUBLICATION_NAMESPACE = 'cdklabs'; const PROJECT_NAME = 'generative-ai-cdk-constructs'; -const CDK_VERSION: string = '2.174.0'; +const CDK_VERSION: string = '2.174.1'; function camelCaseIt(input: string): string { // Hypens and dashes to spaces and then CamelCase... diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bbafe9e..ddb105b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -# CDK Generative AI Constructs V0.1.289 (2025-01-08) +# CDK Generative AI Constructs V0.1.290 (2025-01-08) + +Based on CDK library version 2.174.1 + +# CDK Generative AI Constructs V0.1.289 (2025-01-06) Based on CDK library version 2.174.0 diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index e6e43fb9..323f9931 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -16,7 +16,7 @@ Default output format [None]: json ``` - [Node](https://nodejs.org/en) >= v20.9.0 -- [AWS CDK](https://github.com/aws/aws-cdk/releases/tag/v2.174.0) >= 2.174.0 +- [AWS CDK](https://github.com/aws/aws-cdk/releases/tag/v2.174.1) >= 2.174.1 - [Python](https://www.python.org/downloads/) >=3.9 - [Projen](https://github.com/projen/projen) >= 0.78.8 - [Yarn](https://classic.yarnpkg.com/lang/en/docs/cli/install/) >= 1.22.19 diff --git a/apidocs/namespaces/bedrock/README.md b/apidocs/namespaces/bedrock/README.md index 59734f9a..b728c798 100644 --- a/apidocs/namespaces/bedrock/README.md +++ b/apidocs/namespaces/bedrock/README.md @@ -52,6 +52,7 @@ - [DataSource](classes/DataSource.md) - [DataSourceBase](classes/DataSourceBase.md) - [DataSourceNew](classes/DataSourceNew.md) +- [DefaultPromptRouterIdentifier](classes/DefaultPromptRouterIdentifier.md) - [Guardrail](classes/Guardrail.md) - [GuardrailBase](classes/GuardrailBase.md) - [InferenceProfileBase](classes/InferenceProfileBase.md) @@ -60,6 +61,7 @@ - [ParsingStategy](classes/ParsingStategy.md) - [Prompt](classes/Prompt.md) - [PromptBase](classes/PromptBase.md) +- [PromptRouter](classes/PromptRouter.md) - [PromptVariant](classes/PromptVariant.md) - [PromptVersion](classes/PromptVersion.md) - [S3ApiSchema](classes/S3ApiSchema.md) @@ -106,6 +108,7 @@ - [IKnowledgeBase](interfaces/IKnowledgeBase.md) - [InferenceConfiguration](interfaces/InferenceConfiguration.md) - [IPrompt](interfaces/IPrompt.md) +- [IPromptRouter](interfaces/IPromptRouter.md) - [KnowledgeBaseAttributes](interfaces/KnowledgeBaseAttributes.md) - [KnowledgeBaseProps](interfaces/KnowledgeBaseProps.md) - [LambdaCustomTransformationProps](interfaces/LambdaCustomTransformationProps.md) @@ -114,6 +117,7 @@ - [PromptConfiguration](interfaces/PromptConfiguration.md) - [PromptOverrideConfiguration](interfaces/PromptOverrideConfiguration.md) - [PromptProps](interfaces/PromptProps.md) +- [PromptRouterProps](interfaces/PromptRouterProps.md) - [PromptVersionProps](interfaces/PromptVersionProps.md) - [RegexFilter](interfaces/RegexFilter.md) - [S3DataSourceAssociationProps](interfaces/S3DataSourceAssociationProps.md) @@ -130,6 +134,10 @@ - [WebCrawlerDataSourceAssociationProps](interfaces/WebCrawlerDataSourceAssociationProps.md) - [WebCrawlerDataSourceProps](interfaces/WebCrawlerDataSourceProps.md) +## Variables + +- [REGION\_TO\_GEO\_AREA](variables/REGION_TO_GEO_AREA.md) + ## Functions - [validateInferenceConfiguration](functions/validateInferenceConfiguration.md) diff --git a/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md b/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md index 3f75ab84..f8273a75 100644 --- a/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md +++ b/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md @@ -197,9 +197,15 @@ The ARN of the Bedrock invokable abstraction. *** -### META\_LLAMA\_3\_2\_11B\_INSTRUCT\_V1 +### META\_LLAMA\_3\_1\_70B\_INSTRUCT\_V1 -> `readonly` `static` **META\_LLAMA\_3\_2\_11B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) +> `readonly` `static` **META\_LLAMA\_3\_1\_70B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) + +*** + +### META\_LLAMA\_3\_1\_8B\_INSTRUCT\_V1 + +> `readonly` `static` **META\_LLAMA\_3\_1\_8B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) ************************************************************************* META @@ -207,6 +213,12 @@ The ARN of the Bedrock invokable abstraction. *** +### META\_LLAMA\_3\_2\_11B\_INSTRUCT\_V1 + +> `readonly` `static` **META\_LLAMA\_3\_2\_11B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) + +*** + ### META\_LLAMA\_3\_2\_1B\_INSTRUCT\_V1 > `readonly` `static` **META\_LLAMA\_3\_2\_1B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) diff --git a/apidocs/namespaces/bedrock/classes/DefaultPromptRouterIdentifier.md b/apidocs/namespaces/bedrock/classes/DefaultPromptRouterIdentifier.md new file mode 100644 index 00000000..c81ff529 --- /dev/null +++ b/apidocs/namespaces/bedrock/classes/DefaultPromptRouterIdentifier.md @@ -0,0 +1,37 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / DefaultPromptRouterIdentifier + +# Class: DefaultPromptRouterIdentifier + +Represents identifiers for default prompt routers in Bedrock + +## Properties + +### promptRouterId + +> `readonly` **promptRouterId**: `string` + +*** + +### routingModels + +> `readonly` **routingModels**: [`BedrockFoundationModel`](BedrockFoundationModel.md)[] + +*** + +### ANTHROPIC\_CLAUDE\_V1 + +> `readonly` `static` **ANTHROPIC\_CLAUDE\_V1**: [`DefaultPromptRouterIdentifier`](DefaultPromptRouterIdentifier.md) + +Anthropic Claude V1 router configuration + +*** + +### META\_LLAMA\_3\_1 + +> `readonly` `static` **META\_LLAMA\_3\_1**: [`DefaultPromptRouterIdentifier`](DefaultPromptRouterIdentifier.md) + +Meta Llama 3.1 router configuration diff --git a/apidocs/namespaces/bedrock/classes/PromptRouter.md b/apidocs/namespaces/bedrock/classes/PromptRouter.md new file mode 100644 index 00000000..1d5969b8 --- /dev/null +++ b/apidocs/namespaces/bedrock/classes/PromptRouter.md @@ -0,0 +1,126 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / PromptRouter + +# Class: PromptRouter + +Represents an Amazon Bedrock abstraction on which you can +run the `Invoke` API. This can be a Foundational Model, +a Custom Model, or an Inference Profile. + +## Implements + +- [`IInvokable`](../interfaces/IInvokable.md) +- [`IPromptRouter`](../interfaces/IPromptRouter.md) + +## Constructors + +### new PromptRouter() + +> **new PromptRouter**(`props`, `region`): [`PromptRouter`](PromptRouter.md) + +#### Parameters + +##### props + +[`PromptRouterProps`](../interfaces/PromptRouterProps.md) + +##### region + +`string` + +#### Returns + +[`PromptRouter`](PromptRouter.md) + +## Properties + +### invokableArn + +> `readonly` **invokableArn**: `string` + +The ARN of the Bedrock invokable abstraction. + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`invokableArn`](../interfaces/IInvokable.md#invokablearn) + +*** + +### promptRouterArn + +> `readonly` **promptRouterArn**: `string` + +The ARN of the prompt router. + +#### Implementation of + +[`IPromptRouter`](../interfaces/IPromptRouter.md).[`promptRouterArn`](../interfaces/IPromptRouter.md#promptrouterarn) + +*** + +### promptRouterId + +> `readonly` **promptRouterId**: `string` + +The Id of the prompt router. + +#### Implementation of + +[`IPromptRouter`](../interfaces/IPromptRouter.md).[`promptRouterId`](../interfaces/IPromptRouter.md#promptrouterid) + +*** + +### routingEndpoints + +> `readonly` **routingEndpoints**: [`IInvokable`](../interfaces/IInvokable.md)[] + +The foundation models / profiles this router will route to. + +#### Implementation of + +[`IPromptRouter`](../interfaces/IPromptRouter.md).[`routingEndpoints`](../interfaces/IPromptRouter.md#routingendpoints) + +## Methods + +### grantInvoke() + +> **grantInvoke**(`grantee`): `Grant` + +Gives the appropriate policies to invoke and use the invokable abstraction. + +#### Parameters + +##### grantee + +`IGrantable` + +#### Returns + +`Grant` + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`grantInvoke`](../interfaces/IInvokable.md#grantinvoke) + +*** + +### fromDefaultId() + +> `static` **fromDefaultId**(`defaultRouter`, `region`): [`PromptRouter`](PromptRouter.md) + +#### Parameters + +##### defaultRouter + +[`DefaultPromptRouterIdentifier`](DefaultPromptRouterIdentifier.md) + +##### region + +`string` + +#### Returns + +[`PromptRouter`](PromptRouter.md) diff --git a/apidocs/namespaces/bedrock/interfaces/IPromptRouter.md b/apidocs/namespaces/bedrock/interfaces/IPromptRouter.md new file mode 100644 index 00000000..89079771 --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/IPromptRouter.md @@ -0,0 +1,31 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / IPromptRouter + +# Interface: IPromptRouter + +## Properties + +### promptRouterArn + +> `readonly` **promptRouterArn**: `string` + +The ARN of the prompt router. + +*** + +### promptRouterId + +> `readonly` **promptRouterId**: `string` + +The Id of the prompt router. + +*** + +### routingEndpoints + +> `readonly` **routingEndpoints**: [`IInvokable`](IInvokable.md)[] + +The foundation models / profiles this router will route to. diff --git a/apidocs/namespaces/bedrock/interfaces/PromptRouterProps.md b/apidocs/namespaces/bedrock/interfaces/PromptRouterProps.md new file mode 100644 index 00000000..15735089 --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/PromptRouterProps.md @@ -0,0 +1,23 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / PromptRouterProps + +# Interface: PromptRouterProps + +## Properties + +### promptRouterId + +> `readonly` **promptRouterId**: `string` + +Prompt Router Id + +*** + +### routingModels + +> `readonly` **routingModels**: [`BedrockFoundationModel`](../classes/BedrockFoundationModel.md)[] + +The foundation models this router will route to. diff --git a/apidocs/namespaces/bedrock/variables/REGION_TO_GEO_AREA.md b/apidocs/namespaces/bedrock/variables/REGION_TO_GEO_AREA.md new file mode 100644 index 00000000..af9ea099 --- /dev/null +++ b/apidocs/namespaces/bedrock/variables/REGION_TO_GEO_AREA.md @@ -0,0 +1,13 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / REGION\_TO\_GEO\_AREA + +# Variable: REGION\_TO\_GEO\_AREA + +> `const` **REGION\_TO\_GEO\_AREA**: `object` + +## Index Signature + +\[`key`: `string`\]: [`CrossRegionInferenceProfileRegion`](../enumerations/CrossRegionInferenceProfileRegion.md) diff --git a/package.json b/package.json index 3e295790..ebc6bfee 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,11 @@ "integ:inference-profiles:destroy": "npx projen integ:inference-profiles:destroy", "integ:inference-profiles:snapshot": "npx projen integ:inference-profiles:snapshot", "integ:inference-profiles:watch": "npx projen integ:inference-profiles:watch", + "integ:prompt-router:assert": "npx projen integ:prompt-router:assert", + "integ:prompt-router:deploy": "npx projen integ:prompt-router:deploy", + "integ:prompt-router:destroy": "npx projen integ:prompt-router:destroy", + "integ:prompt-router:snapshot": "npx projen integ:prompt-router:snapshot", + "integ:prompt-router:watch": "npx projen integ:prompt-router:watch", "integ:snapshot-all": "npx projen integ:snapshot-all", "package": "npx projen package", "package-all": "npx projen package-all", @@ -64,7 +69,7 @@ }, "devDependencies": { "@aws-cdk/assert": "^2.68.0", - "@aws-cdk/integ-tests-alpha": "2.174.0-alpha.0", + "@aws-cdk/integ-tests-alpha": "2.174.1-alpha.0", "@commitlint/config-conventional": "^18.6.3", "@mrgrain/jsii-struct-builder": "^0.7.43", "@types/jest": "^29.5.14", @@ -72,7 +77,7 @@ "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", "aws-cdk": "^2", - "aws-cdk-lib": "2.174.0", + "aws-cdk-lib": "2.174.1", "aws-sdk-mock": "^5.9.0", "commitlint": "^18.6.1", "constructs": "10.3.0", @@ -97,7 +102,7 @@ "typescript": "^5.7.2" }, "peerDependencies": { - "aws-cdk-lib": "^2.174.0", + "aws-cdk-lib": "^2.174.1", "constructs": "^10.3.0" }, "dependencies": { diff --git a/src/cdk-lib/bedrock/README.md b/src/cdk-lib/bedrock/README.md index 56a992da..b3d0780d 100644 --- a/src/cdk-lib/bedrock/README.md +++ b/src/cdk-lib/bedrock/README.md @@ -1359,6 +1359,44 @@ const variant2 = PromptVariant.text({ prompt1.addVariant(variant2); ``` +### Prompt routing + +Amazon Bedrock intelligent prompt routing provides a single serverless endpoint for efficiently routing requests between different foundational models within the same model family. +It can help you optimize for response quality and cost. They offer a comprehensive solution for managing multiple AI models through a single serverless endpoint, +simplifying the process for you. Intelligent prompt routing predicts the performance of each model for each request, and dynamically routes each request to the model +that it predicts is most likely to give the desired response at the lowest cost. +More information about prompt routing in the [documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-routing.html) + +**TypeScript** + +```ts +const variant = PromptVariant.text({ + variantName: 'variant1', + promptText: 'What is the capital of France?', + model: PromptRouter.fromDefaultId(DefaultPromptRouterIdentifier.ANTHROPIC_CLAUDE_V1, region), +}); + +new Prompt(stack, 'Prompt', { + promptName: 'prompt-router-test', + variants: [variant], +}); +``` + +**Python** + +```py +variant = bedrock.PromptVariant.text( + variant_name='variant1', + prompt_text='What is the capital of France?', + model=bedrock.PromptRouter.from_default_id(bedrock.DefaultPromptRouterIdentifier.ANTHROPIC_CLAUDE_V1, region), +) + +bedrock.Prompt(self, 'Prompt', + prompt_name='prompt-router-test', + variants=[variant], +) +``` + ### Prompt Version A prompt version is a snapshot of a prompt at a specific point in time that you diff --git a/src/cdk-lib/bedrock/index.ts b/src/cdk-lib/bedrock/index.ts index 74183ead..8281a2e6 100644 --- a/src/cdk-lib/bedrock/index.ts +++ b/src/cdk-lib/bedrock/index.ts @@ -31,6 +31,7 @@ export * from './data-sources/sharepoint-data-source'; export * from './data-sources/confluence-data-source'; export * from './data-sources/salesforce-data-source'; export * from './data-sources/s3-data-source'; -export * from './inference-profiles/application-inference-profile'; export * from './inference-profiles/common'; +export * from './inference-profiles/default-prompt-routers'; export * from './inference-profiles/cross-region-inference-profile'; +export * from './inference-profiles/application-inference-profile'; diff --git a/src/cdk-lib/bedrock/inference-profiles/cross-region-inference-profile.ts b/src/cdk-lib/bedrock/inference-profiles/cross-region-inference-profile.ts index 598d82a3..add035b6 100644 --- a/src/cdk-lib/bedrock/inference-profiles/cross-region-inference-profile.ts +++ b/src/cdk-lib/bedrock/inference-profiles/cross-region-inference-profile.ts @@ -44,6 +44,25 @@ export enum CrossRegionInferenceProfileRegion { APAC = 'apac', } +export const REGION_TO_GEO_AREA: { [key: string]: CrossRegionInferenceProfileRegion } = { + // US Regions + 'us-east-1': CrossRegionInferenceProfileRegion.US, // N. Virginia + 'us-east-2': CrossRegionInferenceProfileRegion.US, // Ohio + 'us-west-2': CrossRegionInferenceProfileRegion.US, // Oregon + + // EU Regions + 'eu-central-1': CrossRegionInferenceProfileRegion.EU, // Frankfurt + 'eu-west-1': CrossRegionInferenceProfileRegion.EU, // Ireland + 'eu-west-3': CrossRegionInferenceProfileRegion.EU, // Paris + + // APAC Regions + 'ap-northeast-1': CrossRegionInferenceProfileRegion.APAC, // Tokyo + 'ap-northeast-2': CrossRegionInferenceProfileRegion.APAC, // Seoul + 'ap-south-1': CrossRegionInferenceProfileRegion.APAC, // Mumbai + 'ap-southeast-1': CrossRegionInferenceProfileRegion.APAC, // Singapore + 'ap-southeast-2': CrossRegionInferenceProfileRegion.APAC, // Sydney +}; + /****************************************************************************** * PROPS FOR NEW CONSTRUCT *****************************************************************************/ diff --git a/src/cdk-lib/bedrock/inference-profiles/default-prompt-routers.ts b/src/cdk-lib/bedrock/inference-profiles/default-prompt-routers.ts new file mode 100644 index 00000000..43a6ea0e --- /dev/null +++ b/src/cdk-lib/bedrock/inference-profiles/default-prompt-routers.ts @@ -0,0 +1,124 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance + * with the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import { Arn, ArnFormat, Aws } from 'aws-cdk-lib'; +import { IGrantable, Grant } from 'aws-cdk-lib/aws-iam'; +import { + CrossRegionInferenceProfile, + REGION_TO_GEO_AREA, +} from './../inference-profiles/cross-region-inference-profile'; +import { BedrockFoundationModel, IInvokable } from './../models'; + +export interface IPromptRouter { + /** + * The ARN of the prompt router. + */ + readonly promptRouterArn: string; + /** + * The Id of the prompt router. + */ + readonly promptRouterId: string; + /** + * The foundation models / profiles this router will route to. + */ + readonly routingEndpoints: IInvokable[]; +} + +export interface PromptRouterProps { + /** + * Prompt Router Id + */ + readonly promptRouterId: string; + /** + * The foundation models this router will route to. + */ + readonly routingModels: BedrockFoundationModel[]; +} + +/** + * Represents identifiers for default prompt routers in Bedrock + */ +export class DefaultPromptRouterIdentifier { + /** + * Anthropic Claude V1 router configuration + */ + public static readonly ANTHROPIC_CLAUDE_V1 = new DefaultPromptRouterIdentifier({ + promptRouterId: 'anthropic.claude:1', + routingModels: [ + BedrockFoundationModel.ANTHROPIC_CLAUDE_HAIKU_V1_0, + BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V1_0, + ], + }); + + /** + * Meta Llama 3.1 router configuration + */ + public static readonly META_LLAMA_3_1 = new DefaultPromptRouterIdentifier({ + promptRouterId: 'meta.llama:1', + routingModels: [ + BedrockFoundationModel.META_LLAMA_3_1_8B_INSTRUCT_V1, + BedrockFoundationModel.META_LLAMA_3_1_70B_INSTRUCT_V1, + ], + }); + + public readonly promptRouterId: string; + public readonly routingModels: BedrockFoundationModel[]; + private constructor(props: PromptRouterProps) { + (this.promptRouterId = props.promptRouterId), (this.routingModels = props.routingModels); + } +} + +export class PromptRouter implements IInvokable, IPromptRouter { + public static fromDefaultId(defaultRouter: DefaultPromptRouterIdentifier, region: string) { + return new PromptRouter(defaultRouter, region); + } + public readonly promptRouterArn: string; + public readonly promptRouterId: string; + public readonly invokableArn: string; + public readonly routingEndpoints: IInvokable[]; + + constructor(props: PromptRouterProps, region: string) { + this.promptRouterId = props.promptRouterId; + this.promptRouterArn = Arn.format({ + partition: Aws.PARTITION, + service: 'bedrock', + region: region, + account: Aws.ACCOUNT_ID, + resource: 'default-prompt-router', + resourceName: this.promptRouterId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + // needed to implement IInvokable + this.invokableArn = this.promptRouterArn; + + // build inference profiles from routing endpoints + this.routingEndpoints = props.routingModels.flatMap(model => { + return CrossRegionInferenceProfile.fromConfig({ + model: model, + geoRegion: REGION_TO_GEO_AREA[region], + }); + }); + } + + grantInvoke(grantee: IGrantable): Grant { + // Grant invoke on every model of the router + this.routingEndpoints.forEach(model => { + model.grantInvoke(grantee); + }); + // Grant invoke to the prompt router + return Grant.addToPrincipal({ + grantee, + actions: ['bedrock:GetPromptRouter', 'bedrock:InvokeModel'], + resourceArns: [this.promptRouterArn], + }); + } +} diff --git a/src/cdk-lib/bedrock/models.ts b/src/cdk-lib/bedrock/models.ts index 1d39947f..fb350049 100644 --- a/src/cdk-lib/bedrock/models.ts +++ b/src/cdk-lib/bedrock/models.ts @@ -76,17 +76,20 @@ export class BedrockFoundationModel implements IInvokable { supportsAgents: true, }); - public static readonly AMAZON_NOVA_MICRO_V1 = new BedrockFoundationModel('amazon.nova-micro-v1:0', - { supportsAgents: true, supportsCrossRegion: true }, - ); + public static readonly AMAZON_NOVA_MICRO_V1 = new BedrockFoundationModel('amazon.nova-micro-v1:0', { + supportsAgents: true, + supportsCrossRegion: true, + }); - public static readonly AMAZON_NOVA_LITE_V1 = new BedrockFoundationModel('amazon.nova-lite-v1:0', - { supportsAgents: true, supportsCrossRegion: true }, - ); + public static readonly AMAZON_NOVA_LITE_V1 = new BedrockFoundationModel('amazon.nova-lite-v1:0', { + supportsAgents: true, + supportsCrossRegion: true, + }); - public static readonly AMAZON_NOVA_PRO_V1 = new BedrockFoundationModel('amazon.nova-pro-v1:0', - { supportsAgents: true, supportsCrossRegion: true }, - ); + public static readonly AMAZON_NOVA_PRO_V1 = new BedrockFoundationModel('amazon.nova-pro-v1:0', { + supportsAgents: true, + supportsCrossRegion: true, + }); public static readonly TITAN_EMBED_TEXT_V1 = new BedrockFoundationModel('amazon.titan-embed-text-v1', { supportsKnowledgeBase: true, @@ -168,6 +171,17 @@ export class BedrockFoundationModel implements IInvokable { /**************************************************************************** * META ***************************************************************************/ + public static readonly META_LLAMA_3_1_8B_INSTRUCT_V1 = new BedrockFoundationModel('meta.llama3-1-8b-instruct-v1:0', { + supportsCrossRegion: true, + }); + + public static readonly META_LLAMA_3_1_70B_INSTRUCT_V1 = new BedrockFoundationModel( + 'meta.llama3-1-70b-instruct-v1:0', + { + supportsCrossRegion: true, + }, + ); + public static readonly META_LLAMA_3_2_11B_INSTRUCT_V1 = new BedrockFoundationModel( 'meta.llama3-2-11b-instruct-v1:0', { diff --git a/test/integ/prompt-router.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json b/test/integ/prompt-router.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json new file mode 100644 index 00000000..79bdb016 --- /dev/null +++ b/test/integ/prompt-router.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json @@ -0,0 +1,19 @@ +{ + "version": "39.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "ServiceTestDefaultTestDeployAssertE49B1ECE.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/test/integ/prompt-router.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.template.json b/test/integ/prompt-router.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.template.json new file mode 100644 index 00000000..ad9d0fb7 --- /dev/null +++ b/test/integ/prompt-router.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/test/integ/prompt-router.integ.snapshot/aws-cdk-bedrock-prompt-router-integ-test.assets.json b/test/integ/prompt-router.integ.snapshot/aws-cdk-bedrock-prompt-router-integ-test.assets.json new file mode 100644 index 00000000..8703900b --- /dev/null +++ b/test/integ/prompt-router.integ.snapshot/aws-cdk-bedrock-prompt-router-integ-test.assets.json @@ -0,0 +1,20 @@ +{ + "version": "39.0.0", + "files": { + "d234028c8a2b4e7ef7c530e7abc3de36d8f1325a26b3ef033f98d37f8b627ad9": { + "source": { + "path": "aws-cdk-bedrock-prompt-router-integ-test.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-us-east-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", + "objectKey": "d234028c8a2b4e7ef7c530e7abc3de36d8f1325a26b3ef033f98d37f8b627ad9.json", + "region": "us-east-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/test/integ/prompt-router.integ.snapshot/aws-cdk-bedrock-prompt-router-integ-test.template.json b/test/integ/prompt-router.integ.snapshot/aws-cdk-bedrock-prompt-router-integ-test.template.json new file mode 100644 index 00000000..1855bba3 --- /dev/null +++ b/test/integ/prompt-router.integ.snapshot/aws-cdk-bedrock-prompt-router-integ-test.template.json @@ -0,0 +1,74 @@ +{ + "Resources": { + "PromptAD8A4FD3": { + "Type": "AWS::Bedrock::Prompt", + "Properties": { + "Name": "prompt-router-test", + "Variants": [ + { + "InferenceConfiguration": { + "Text": {} + }, + "ModelId": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:us-east-1:", + { + "Ref": "AWS::AccountId" + }, + ":default-prompt-router/anthropic.claude:1" + ] + ] + }, + "Name": "variant1", + "TemplateConfiguration": { + "Text": { + "Text": "What is the capital of France?" + } + }, + "TemplateType": "TEXT" + } + ] + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/test/integ/prompt-router.integ.snapshot/integ.json b/test/integ/prompt-router.integ.snapshot/integ.json new file mode 100644 index 00000000..06e2a72a --- /dev/null +++ b/test/integ/prompt-router.integ.snapshot/integ.json @@ -0,0 +1,19 @@ +{ + "version": "39.0.0", + "testCases": { + "ServiceTest/DefaultTest": { + "stacks": [ + "aws-cdk-bedrock-prompt-router-integ-test" + ], + "cdkCommandOptions": { + "destroy": { + "args": { + "force": true + } + } + }, + "assertionStack": "ServiceTest/DefaultTest/DeployAssert", + "assertionStackName": "ServiceTestDefaultTestDeployAssertE49B1ECE" + } + } +} \ No newline at end of file diff --git a/test/integ/prompt-router.integ.ts b/test/integ/prompt-router.integ.ts new file mode 100644 index 00000000..5345933c --- /dev/null +++ b/test/integ/prompt-router.integ.ts @@ -0,0 +1,47 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance + * with the License. A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES + * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions + * and limitations under the License. + */ +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import { DefaultPromptRouterIdentifier, Prompt, PromptRouter, PromptVariant } from '../../src/cdk-lib/bedrock'; + +const app = new cdk.App(); +const region = 'us-east-1'; +const stack = new cdk.Stack(app, 'aws-cdk-bedrock-prompt-router-integ-test', { + env: { + region, + }, +}); + +const variant = PromptVariant.text({ + variantName: 'variant1', + promptText: 'What is the capital of France?', + model: PromptRouter.fromDefaultId(DefaultPromptRouterIdentifier.ANTHROPIC_CLAUDE_V1, region), +}); + +new Prompt(stack, 'Prompt', { + promptName: 'prompt-router-test', + variants: [variant], +}); + +new integ.IntegTest(app, 'ServiceTest', { + testCases: [stack], + cdkCommandOptions: { + destroy: { + args: { + force: true, + }, + }, + }, +}); + +app.synth(); diff --git a/yarn.lock b/yarn.lock index 4f0d27b2..c29a5754 100644 --- a/yarn.lock +++ b/yarn.lock @@ -60,10 +60,10 @@ string-width "^4.2.3" table "^6.8.1" -"@aws-cdk/integ-tests-alpha@2.174.0-alpha.0": - version "2.174.0-alpha.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.174.0-alpha.0.tgz#9c55e4dc9c09ced3bf4a61573bab05a2b8caaaff" - integrity sha512-+Z0qNhVl41PL0ZJJB8lO3+Fxe6yQ2gsjS0IarsRx8WOWYdRypsjXQx+/mUwVC7nwC9+dKYrfBj7RcP9GvI4z4A== +"@aws-cdk/integ-tests-alpha@2.174.1-alpha.0": + version "2.174.1-alpha.0" + resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.174.1-alpha.0.tgz#c1bde5f4d0a97f1c275fa4ab8fadac2a6961d99c" + integrity sha512-+w6UGfZRUKonyt0SEBzgliwxux53336Yg9CYu3CCwZl/FWjdJnxZlZI+RBlEPRGMvCb6Eoc6fYiMdx/npDlK+Q== "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": version "7.26.2" @@ -1408,10 +1408,10 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -aws-cdk-lib@2.174.0: - version "2.174.0" - resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.174.0.tgz#d43ad7ed927ba9c4badff1c141b1583baca19f9f" - integrity sha512-OHBJcsg0i4KftWVeUzw1AkG7onZWNNM/DH7NQnbDOs0Ap716VvtcTUubUpeFrazDWe9Opfn1essTjv6gaVyHBw== +aws-cdk-lib@2.174.1: + version "2.174.1" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.174.1.tgz#adfce6a1531eef679e1bac9ac277f04976f2f4b2" + integrity sha512-4WRd1Qyf+BKIMwEDQdpU+h3daDTTH9nCcEBUUxQnpuswdMUwvjjIkmWmGMnXNZK7PU/715gJK9XCSBaphb3M8g== dependencies: "@aws-cdk/asset-awscli-v1" "^2.2.208" "@aws-cdk/asset-kubectl-v20" "^2.1.3"