diff --git a/.gitignore b/.gitignore index 249ee8ac..b22a12e5 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,15 @@ junit.xml !/.eslintrc.json .jsii tsconfig.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 +test/integ/inference-profiles.integ.snapshot/**/cdk.out +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/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 1f169094..19d6a6b9 100644 --- a/.npmignore +++ b/.npmignore @@ -22,6 +22,8 @@ dist tsconfig.tsbuildinfo /.eslintrc.json !.jsii +test/integ/.tmp +test/integ/inference-profiles.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 cb07eb71..f367a4fe 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -6,7 +6,7 @@ }, { "name": "@aws-cdk/integ-tests-alpha", - "version": "2.162.1-alpha.0", + "version": "2.166.0-alpha.0", "type": "build" }, { @@ -137,7 +137,7 @@ }, { "name": "aws-cdk-lib", - "version": "^2.162.1", + "version": "^2.166.0", "type": "peer" }, { diff --git a/.projen/tasks.json b/.projen/tasks.json index 7c3f7357..5b1a35db 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -290,10 +290,76 @@ } ] }, + "integ:inference-profiles:assert": { + "name": "integ:inference-profiles:assert", + "description": "assert the snapshot of integration test 'inference-profiles'", + "steps": [ + { + "exec": "[ -d \"test/integ/inference-profiles.integ.snapshot\" ] || (echo \"No snapshot available for integration test 'inference-profiles'. Run 'projen integ:inference-profiles:deploy' to capture.\" && exit 1)" + }, + { + "exec": "cdk synth --app \"ts-node -P tsconfig.dev.json test/integ/inference-profiles.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata -o test/integ/.tmp/inference-profiles.integ/assert.cdk.out > /dev/null" + }, + { + "exec": "diff -r -x asset.* -x cdk.out -x manifest.json -x tree.json test/integ/inference-profiles.integ.snapshot/ test/integ/.tmp/inference-profiles.integ/assert.cdk.out/" + } + ] + }, + "integ:inference-profiles:deploy": { + "name": "integ:inference-profiles:deploy", + "description": "deploy integration test 'inference-profiles' and capture snapshot", + "steps": [ + { + "exec": "rm -fr test/integ/.tmp/inference-profiles.integ/deploy.cdk.out" + }, + { + "exec": "cdk deploy --app \"ts-node -P tsconfig.dev.json test/integ/inference-profiles.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata '**' --require-approval=never -o test/integ/.tmp/inference-profiles.integ/deploy.cdk.out" + }, + { + "exec": "rm -fr test/integ/inference-profiles.integ.snapshot" + }, + { + "exec": "mv test/integ/.tmp/inference-profiles.integ/deploy.cdk.out test/integ/inference-profiles.integ.snapshot" + }, + { + "spawn": "integ:inference-profiles:destroy" + } + ] + }, + "integ:inference-profiles:destroy": { + "name": "integ:inference-profiles:destroy", + "description": "destroy integration test 'inference-profiles'", + "steps": [ + { + "exec": "cdk destroy --app test/integ/inference-profiles.integ.snapshot '**' --no-version-reporting" + } + ] + }, + "integ:inference-profiles:snapshot": { + "name": "integ:inference-profiles:snapshot", + "description": "update snapshot for integration test \"inference-profiles\"", + "steps": [ + { + "exec": "cdk synth --app \"ts-node -P tsconfig.dev.json test/integ/inference-profiles.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata -o test/integ/inference-profiles.integ.snapshot > /dev/null" + } + ] + }, + "integ:inference-profiles:watch": { + "name": "integ:inference-profiles:watch", + "description": "watch integration test 'inference-profiles' (without updating snapshots)", + "steps": [ + { + "exec": "cdk watch --app \"ts-node -P tsconfig.dev.json test/integ/inference-profiles.integ.ts\" --no-notices --no-version-reporting --no-asset-metadata --no-path-metadata '**' -o test/integ/.tmp/inference-profiles.integ/deploy.cdk.out" + } + ] + }, "integ:snapshot-all": { "name": "integ:snapshot-all", "description": "update snapshot for all integration tests", "steps": [ + { + "spawn": "integ:inference-profiles:snapshot" + }, { "spawn": "integ:aws-aoss-cw-dashboard:snapshot" }, @@ -427,6 +493,9 @@ { "spawn": "eslint" }, + { + "spawn": "integ:inference-profiles:assert" + }, { "spawn": "integ:aws-aoss-cw-dashboard:assert" }, diff --git a/.projenrc.ts b/.projenrc.ts index 475791c3..7ea95a39 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -30,7 +30,7 @@ import { const GITHUB_USER = 'awslabs'; const PUBLICATION_NAMESPACE = 'cdklabs'; const PROJECT_NAME = 'generative-ai-cdk-constructs'; -const CDK_VERSION: string = '2.162.1'; +const CDK_VERSION: string = '2.166.0'; function camelCaseIt(input: string): string { // Hypens and dashes to spaces and then CamelCase... diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c9900ec..ed629d71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# CDK Generative AI Constructs V0.1.283 (2024-11-20) + +Based on CDK library version 2.166.0 + # CDK Generative AI Constructs V0.1.273 (2024-10-15) Based on CDK library version 2.162.1 diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index da9ab0bc..9118b64b 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.162.1) >= 2.162.1 +- [AWS CDK](https://github.com/aws/aws-cdk/releases/tag/v2.166.0) >= 2.166.0 - [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/interfaces/DockerLambdaCustomProps.md b/apidocs/interfaces/DockerLambdaCustomProps.md index eb99f594..51aa9785 100644 --- a/apidocs/interfaces/DockerLambdaCustomProps.md +++ b/apidocs/interfaces/DockerLambdaCustomProps.md @@ -594,7 +594,7 @@ stable > `readonly` `optional` **recursiveLoop**: `RecursiveLoop` Sets the Recursive Loop Protection for Lambda Function. -It lets Lambda detect and terminate unintended recusrive loops. +It lets Lambda detect and terminate unintended recursive loops. #### Default diff --git a/apidocs/namespaces/bedrock/README.md b/apidocs/namespaces/bedrock/README.md index 8d094266..15d762e8 100644 --- a/apidocs/namespaces/bedrock/README.md +++ b/apidocs/namespaces/bedrock/README.md @@ -20,9 +20,11 @@ - [ContentFilterType](enumerations/ContentFilterType.md) - [ContextualGroundingFilterType](enumerations/ContextualGroundingFilterType.md) - [CrawlingScope](enumerations/CrawlingScope.md) +- [CrossRegionInferenceProfileRegion](enumerations/CrossRegionInferenceProfileRegion.md) - [DataDeletionPolicy](enumerations/DataDeletionPolicy.md) - [DataSourceType](enumerations/DataSourceType.md) - [GuardrailAction](enumerations/GuardrailAction.md) +- [InferenceProfileType](enumerations/InferenceProfileType.md) - [ManagedWordFilterType](enumerations/ManagedWordFilterType.md) - [ParserMode](enumerations/ParserMode.md) - [PromptCreationMode](enumerations/PromptCreationMode.md) @@ -41,15 +43,18 @@ - [AgentActionGroup](classes/AgentActionGroup.md) - [AgentAlias](classes/AgentAlias.md) - [ApiSchema](classes/ApiSchema.md) +- [ApplicationInferenceProfile](classes/ApplicationInferenceProfile.md) - [BedrockFoundationModel](classes/BedrockFoundationModel.md) - [ChunkingStrategy](classes/ChunkingStrategy.md) - [ConfluenceDataSource](classes/ConfluenceDataSource.md) +- [CrossRegionInferenceProfile](classes/CrossRegionInferenceProfile.md) - [CustomTransformation](classes/CustomTransformation.md) - [DataSource](classes/DataSource.md) - [DataSourceBase](classes/DataSourceBase.md) - [DataSourceNew](classes/DataSourceNew.md) - [Guardrail](classes/Guardrail.md) - [GuardrailBase](classes/GuardrailBase.md) +- [InferenceProfileBase](classes/InferenceProfileBase.md) - [InlineApiSchema](classes/InlineApiSchema.md) - [KnowledgeBase](classes/KnowledgeBase.md) - [ParsingStategy](classes/ParsingStategy.md) @@ -72,6 +77,8 @@ - [AgentAliasProps](interfaces/AgentAliasProps.md) - [AgentProps](interfaces/AgentProps.md) - [ApiSchemaConfig](interfaces/ApiSchemaConfig.md) +- [ApplicationInferenceProfileAttributes](interfaces/ApplicationInferenceProfileAttributes.md) +- [ApplicationInferenceProfileProps](interfaces/ApplicationInferenceProfileProps.md) - [BedrockFoundationModelProps](interfaces/BedrockFoundationModelProps.md) - [CommonPromptVariantProps](interfaces/CommonPromptVariantProps.md) - [ConfluenceCrawlingFilters](interfaces/ConfluenceCrawlingFilters.md) @@ -80,6 +87,7 @@ - [ContentFilter](interfaces/ContentFilter.md) - [ContextualGroundingFilter](interfaces/ContextualGroundingFilter.md) - [CrawlingFilters](interfaces/CrawlingFilters.md) +- [CrossRegionInferenceProfileProps](interfaces/CrossRegionInferenceProfileProps.md) - [CustomTopicProps](interfaces/CustomTopicProps.md) - [DataSourceAssociationProps](interfaces/DataSourceAssociationProps.md) - [FoundationModelParsingStategyProps](interfaces/FoundationModelParsingStategyProps.md) @@ -90,6 +98,8 @@ - [IAgentAlias](interfaces/IAgentAlias.md) - [IDataSource](interfaces/IDataSource.md) - [IGuardrail](interfaces/IGuardrail.md) +- [IInferenceProfile](interfaces/IInferenceProfile.md) +- [IInvokable](interfaces/IInvokable.md) - [IKnowledgeBase](interfaces/IKnowledgeBase.md) - [InferenceConfiguration](interfaces/InferenceConfiguration.md) - [IPrompt](interfaces/IPrompt.md) diff --git a/apidocs/namespaces/bedrock/classes/Agent.md b/apidocs/namespaces/bedrock/classes/Agent.md index 06d7c899..c62d2c26 100644 --- a/apidocs/namespaces/bedrock/classes/Agent.md +++ b/apidocs/namespaces/bedrock/classes/Agent.md @@ -92,6 +92,14 @@ The name for the agent alias. *** +### foundationModel + +> `readonly` **foundationModel**: [`IInvokable`](../interfaces/IInvokable.md) + +The model used by the agent. + +*** + ### knowledgeBases > **knowledgeBases**: `AgentKnowledgeBaseProperty`[] = `[]` diff --git a/apidocs/namespaces/bedrock/classes/ApplicationInferenceProfile.md b/apidocs/namespaces/bedrock/classes/ApplicationInferenceProfile.md new file mode 100644 index 00000000..9fb34b4f --- /dev/null +++ b/apidocs/namespaces/bedrock/classes/ApplicationInferenceProfile.md @@ -0,0 +1,501 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / ApplicationInferenceProfile + +# Class: ApplicationInferenceProfile + +Class to create a ApplicationInferenceProfile with CDK. +These are inference profiles created by users (user defined). +This helps to track costs and model usage. + +## Resource + +AWS::Bedrock::ApplicationInferenceProfile + +## See + +https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html + +## Extends + +- [`InferenceProfileBase`](InferenceProfileBase.md) + +## Implements + +- [`IInvokable`](../interfaces/IInvokable.md) + +## Constructors + +### new ApplicationInferenceProfile() + +> **new ApplicationInferenceProfile**(`scope`, `id`, `props`): [`ApplicationInferenceProfile`](ApplicationInferenceProfile.md) + +#### Parameters + +• **scope**: `Construct` + +• **id**: `string` + +• **props**: [`ApplicationInferenceProfileProps`](../interfaces/ApplicationInferenceProfileProps.md) + +#### Returns + +[`ApplicationInferenceProfile`](ApplicationInferenceProfile.md) + +#### Overrides + +[`InferenceProfileBase`](InferenceProfileBase.md).[`constructor`](InferenceProfileBase.md#constructors) + +## Properties + +### createdAt + +> `readonly` **createdAt**: `string` + +Time Stamp for ApplicationInferenceProfile creation. + +*** + +### env + +> `readonly` **env**: `ResourceEnvironment` + +The environment this resource belongs to. +For resources that are created and managed by the CDK +(generally, those created by creating new class instances like Role, Bucket, etc.), +this is always the same as the environment of the stack they belong to; +however, for imported resources +(those obtained from static methods like fromRoleArn, fromBucketName, etc.), +that might be different than the stack they were imported into. + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`env`](InferenceProfileBase.md#env) + +*** + +### inferenceProfileArn + +> `readonly` **inferenceProfileArn**: `string` + +The ARN of the application application inference profile. + +#### Overrides + +[`InferenceProfileBase`](InferenceProfileBase.md).[`inferenceProfileArn`](InferenceProfileBase.md#inferenceprofilearn) + +*** + +### inferenceProfileId + +> `readonly` **inferenceProfileId**: `string` + +The unique identifier of the application inference profile. + +#### Overrides + +[`InferenceProfileBase`](InferenceProfileBase.md).[`inferenceProfileId`](InferenceProfileBase.md#inferenceprofileid) + +*** + +### inferenceProfileModel + +> `readonly` **inferenceProfileModel**: [`IInvokable`](../interfaces/IInvokable.md) + +The underlying model/cross-region model used by the application inference profile. + +*** + +### inferenceProfileName + +> `readonly` **inferenceProfileName**: `string` + +The name of the application inference profile. + +*** + +### invokableArn + +> `readonly` **invokableArn**: `string` + +This equals to the inferenceProfileArn property, useful just to implement IInvokable interface. + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`invokableArn`](../interfaces/IInvokable.md#invokablearn) + +*** + +### node + +> `readonly` **node**: `Node` + +The tree node. + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`node`](InferenceProfileBase.md#node) + +*** + +### physicalName + +> `protected` `readonly` **physicalName**: `string` + +Returns a string-encoded token that resolves to the physical name that +should be passed to the CloudFormation resource. + +This value will resolve to one of the following: +- a concrete value (e.g. `"my-awesome-bucket"`) +- `undefined`, when a name should be generated by CloudFormation +- a concrete name generated automatically during synthesis, in + cross-environment scenarios. + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`physicalName`](InferenceProfileBase.md#physicalname) + +*** + +### stack + +> `readonly` **stack**: `Stack` + +The stack in which this resource is defined. + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`stack`](InferenceProfileBase.md#stack) + +*** + +### status + +> `readonly` **status**: `string` + +The status of the application inference profile. ACTIVE means that the inference profile is ready to be used. + +*** + +### type + +> `readonly` **type**: [`InferenceProfileType`](../enumerations/InferenceProfileType.md) + +The type of the inference profile. The following types are possible: +SYSTEM_DEFINED – The inference profile is defined by Amazon Bedrock. +You can route inference requests across regions with these inference profiles. +APPLICATION – The inference profile was created by a user. +This type of inference profile can track metrics and costs when invoking the model in it. +The inference profile may route requests to one or multiple regions. + +#### Overrides + +[`InferenceProfileBase`](InferenceProfileBase.md).[`type`](InferenceProfileBase.md#type) + +*** + +### updatedAt + +> `readonly` **updatedAt**: `string` + +Time Stamp for ApplicationInferenceProfile update. + +## Methods + +### \_enableCrossEnvironment() + +> **\_enableCrossEnvironment**(): `void` + +**`Internal`** + +Called when this resource is referenced across environments +(account/region) to order to request that a physical name will be generated +for this resource during synthesis, so the resource can be referenced +through its absolute name/arn. + +#### Returns + +`void` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`_enableCrossEnvironment`](InferenceProfileBase.md#_enablecrossenvironment) + +*** + +### applyRemovalPolicy() + +> **applyRemovalPolicy**(`policy`): `void` + +Apply the given removal policy to this resource + +The Removal Policy controls what happens to this resource when it stops +being managed by CloudFormation, either because you've removed it from the +CDK application or because you've made a change that requires the resource +to be replaced. + +The resource can be deleted (`RemovalPolicy.DESTROY`), or left in your AWS +account for data recovery and cleanup later (`RemovalPolicy.RETAIN`). + +#### Parameters + +• **policy**: `RemovalPolicy` + +#### Returns + +`void` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`applyRemovalPolicy`](InferenceProfileBase.md#applyremovalpolicy) + +*** + +### generatePhysicalName() + +> `protected` **generatePhysicalName**(): `string` + +#### Returns + +`string` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`generatePhysicalName`](InferenceProfileBase.md#generatephysicalname) + +*** + +### getResourceArnAttribute() + +> `protected` **getResourceArnAttribute**(`arnAttr`, `arnComponents`): `string` + +Returns an environment-sensitive token that should be used for the +resource's "ARN" attribute (e.g. `bucket.bucketArn`). + +Normally, this token will resolve to `arnAttr`, but if the resource is +referenced across environments, `arnComponents` will be used to synthesize +a concrete ARN with the resource's physical name. Make sure to reference +`this.physicalName` in `arnComponents`. + +#### Parameters + +• **arnAttr**: `string` + +The CFN attribute which resolves to the ARN of the resource. +Commonly it will be called "Arn" (e.g. `resource.attrArn`), but sometimes +it's the CFN resource's `ref`. + +• **arnComponents**: `ArnComponents` + +The format of the ARN of this resource. You must +reference `this.physicalName` somewhere within the ARN in order for +cross-environment references to work. + +#### Returns + +`string` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`getResourceArnAttribute`](InferenceProfileBase.md#getresourcearnattribute) + +*** + +### getResourceNameAttribute() + +> `protected` **getResourceNameAttribute**(`nameAttr`): `string` + +Returns an environment-sensitive token that should be used for the +resource's "name" attribute (e.g. `bucket.bucketName`). + +Normally, this token will resolve to `nameAttr`, but if the resource is +referenced across environments, it will be resolved to `this.physicalName`, +which will be a concrete name. + +#### Parameters + +• **nameAttr**: `string` + +The CFN attribute which resolves to the resource's name. +Commonly this is the resource's `ref`. + +#### Returns + +`string` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`getResourceNameAttribute`](InferenceProfileBase.md#getresourcenameattribute) + +*** + +### grantInvoke() + +> **grantInvoke**(`grantee`): `Grant` + +Gives the appropriate policies to invoke and use the application inference profile. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`grantInvoke`](../interfaces/IInvokable.md#grantinvoke) + +*** + +### grantProfileUsage() + +> **grantProfileUsage**(`grantee`): `Grant` + +Grants appropriate permissions to use the application inference profile (AIP). +Does not grant permissions to use the model/cross-region profile in the AIP. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +#### Overrides + +[`InferenceProfileBase`](InferenceProfileBase.md).[`grantProfileUsage`](InferenceProfileBase.md#grantprofileusage) + +*** + +### toString() + +> **toString**(): `string` + +Returns a string representation of this construct. + +#### Returns + +`string` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`toString`](InferenceProfileBase.md#tostring) + +*** + +### fromApplicationInferenceProfileAttributes() + +> `static` **fromApplicationInferenceProfileAttributes**(`scope`, `id`, `attrs`): [`IInferenceProfile`](../interfaces/IInferenceProfile.md) + +Import a ApplicationInferenceProfile given its attributes + +#### Parameters + +• **scope**: `Construct` + +• **id**: `string` + +• **attrs**: [`ApplicationInferenceProfileAttributes`](../interfaces/ApplicationInferenceProfileAttributes.md) + +#### Returns + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md) + +*** + +### fromCfnApplicationInferenceProfile() + +> `static` **fromCfnApplicationInferenceProfile**(`CfnApplicationInferenceProfile`): [`IInferenceProfile`](../interfaces/IInferenceProfile.md) + +Import a low-level L1 Cfn ApplicationInferenceProfile + +#### Parameters + +• **CfnApplicationInferenceProfile**: `CfnApplicationInferenceProfile` + +#### Returns + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md) + +*** + +### isConstruct() + +> `static` **isConstruct**(`x`): `x is Construct` + +Checks if `x` is a construct. + +Use this method instead of `instanceof` to properly detect `Construct` +instances, even when the construct library is symlinked. + +Explanation: in JavaScript, multiple copies of the `constructs` library on +disk are seen as independent, completely different libraries. As a +consequence, the class `Construct` in each copy of the `constructs` library +is seen as a different class, and an instance of one class will not test as +`instanceof` the other class. `npm install` will not create installations +like this, but users may manually symlink construct libraries together or +use a monorepo tool: in those cases, multiple copies of the `constructs` +library can be accidentally installed, and `instanceof` will behave +unpredictably. It is safest to avoid using `instanceof`, and using +this type-testing method instead. + +#### Parameters + +• **x**: `any` + +Any object + +#### Returns + +`x is Construct` + +true if `x` is an object created from a class which extends `Construct`. + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`isConstruct`](InferenceProfileBase.md#isconstruct) + +*** + +### isOwnedResource() + +> `static` **isOwnedResource**(`construct`): `boolean` + +Returns true if the construct was created by CDK, and false otherwise + +#### Parameters + +• **construct**: `IConstruct` + +#### Returns + +`boolean` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`isOwnedResource`](InferenceProfileBase.md#isownedresource) + +*** + +### isResource() + +> `static` **isResource**(`construct`): `construct is Resource` + +Check whether the given construct is a Resource + +#### Parameters + +• **construct**: `IConstruct` + +#### Returns + +`construct is Resource` + +#### Inherited from + +[`InferenceProfileBase`](InferenceProfileBase.md).[`isResource`](InferenceProfileBase.md#isresource) diff --git a/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md b/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md index e6349025..f272f044 100644 --- a/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md +++ b/apidocs/namespaces/bedrock/classes/BedrockFoundationModel.md @@ -11,6 +11,10 @@ Bedrock models. If you need to use a model name that doesn't exist as a static member, you can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationModel('my-model')`. +## Implements + +- [`IInvokable`](../interfaces/IInvokable.md) + ## Constructors ### new BedrockFoundationModel() @@ -29,10 +33,32 @@ can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationMo ## Properties +### invokableArn + +> `readonly` **invokableArn**: `string` + +The ARN of the Bedrock invokable abstraction. + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`invokableArn`](../interfaces/IInvokable.md#invokablearn) + +*** + +### modelArn + +> `readonly` **modelArn**: `string` + +*** + ### modelId > `readonly` **modelId**: `string` +************************************************************************* + Constructor +************************************************************************* + *** ### supportsAgents @@ -41,6 +67,12 @@ can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationMo *** +### supportsCrossRegion + +> `readonly` **supportsCrossRegion**: `boolean` + +*** + ### supportsKnowledgeBase > `readonly` **supportsKnowledgeBase**: `boolean` @@ -63,6 +95,10 @@ can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationMo > `readonly` `static` **AMAZON\_TITAN\_TEXT\_EXPRESS\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) +************************************************************************* + AMAZON +************************************************************************* + *** ### ANTHROPIC\_CLAUDE\_3\_5\_HAIKU\_V1\_0 @@ -81,6 +117,10 @@ can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationMo > `readonly` `static` **ANTHROPIC\_CLAUDE\_3\_5\_SONNET\_V2\_0**: [`BedrockFoundationModel`](BedrockFoundationModel.md) +************************************************************************* + ANTHROPIC +************************************************************************* + *** ### ANTHROPIC\_CLAUDE\_HAIKU\_V1\_0 @@ -123,6 +163,10 @@ can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationMo > `readonly` `static` **COHERE\_EMBED\_ENGLISH\_V3**: [`BedrockFoundationModel`](BedrockFoundationModel.md) +************************************************************************* + COHERE +************************************************************************* + *** ### COHERE\_EMBED\_MULTILINGUAL\_V3 @@ -131,6 +175,28 @@ can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationMo *** +### META\_LLAMA\_3\_2\_11B\_INSTRUCT\_V1 + +> `readonly` `static` **META\_LLAMA\_3\_2\_11B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) + +************************************************************************* + META +************************************************************************* + +*** + +### META\_LLAMA\_3\_2\_1B\_INSTRUCT\_V1 + +> `readonly` `static` **META\_LLAMA\_3\_2\_1B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) + +*** + +### META\_LLAMA\_3\_2\_3B\_INSTRUCT\_V1 + +> `readonly` `static` **META\_LLAMA\_3\_2\_3B\_INSTRUCT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) + +*** + ### TITAN\_EMBED\_TEXT\_V1 > `readonly` `static` **TITAN\_EMBED\_TEXT\_V1**: [`BedrockFoundationModel`](BedrockFoundationModel.md) @@ -186,10 +252,80 @@ Returns the ARN of the foundation model in the following format: *** +### grantInvoke() + +> **grantInvoke**(`grantee`): `Grant` + +Gives the appropriate policies to invoke and use the Foundation Model in the stack region. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`grantInvoke`](../interfaces/IInvokable.md#grantinvoke) + +*** + +### grantInvokeAllRegions() + +> **grantInvokeAllRegions**(`grantee`): `Grant` + +Gives the appropriate policies to invoke and use the Foundation Model in all regions. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +*** + ### toString() > **toString**(): `string` +Returns a string representation of an object. + #### Returns `string` + +*** + +### fromCdkFoundationModel() + +> `static` **fromCdkFoundationModel**(`modelId`, `props`): [`BedrockFoundationModel`](BedrockFoundationModel.md) + +#### Parameters + +• **modelId**: `FoundationModel` + +• **props**: [`BedrockFoundationModelProps`](../interfaces/BedrockFoundationModelProps.md) = `{}` + +#### Returns + +[`BedrockFoundationModel`](BedrockFoundationModel.md) + +*** + +### fromCdkFoundationModelId() + +> `static` **fromCdkFoundationModelId**(`modelId`, `props`): [`BedrockFoundationModel`](BedrockFoundationModel.md) + +#### Parameters + +• **modelId**: `FoundationModelIdentifier` + +• **props**: [`BedrockFoundationModelProps`](../interfaces/BedrockFoundationModelProps.md) = `{}` + +#### Returns + +[`BedrockFoundationModel`](BedrockFoundationModel.md) diff --git a/apidocs/namespaces/bedrock/classes/CrossRegionInferenceProfile.md b/apidocs/namespaces/bedrock/classes/CrossRegionInferenceProfile.md new file mode 100644 index 00000000..b798ee90 --- /dev/null +++ b/apidocs/namespaces/bedrock/classes/CrossRegionInferenceProfile.md @@ -0,0 +1,144 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / CrossRegionInferenceProfile + +# Class: CrossRegionInferenceProfile + +Cross-region inference enables you to seamlessly manage unplanned traffic +bursts by utilizing compute across different AWS Regions. With cross-region +inference, you can distribute traffic across multiple AWS Regions, enabling +higher throughput and enhanced resilience during periods of peak demands. + +## See + +https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html + +## Implements + +- [`IInvokable`](../interfaces/IInvokable.md) +- [`IInferenceProfile`](../interfaces/IInferenceProfile.md) + +## Properties + +### inferenceProfileArn + +> `readonly` **inferenceProfileArn**: `string` + +#### Example + +```ts +'arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0' +``` + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`inferenceProfileArn`](../interfaces/IInferenceProfile.md#inferenceprofilearn) + +*** + +### inferenceProfileId + +> `readonly` **inferenceProfileId**: `string` + +#### Example + +```ts +'us.anthropic.claude-3-5-sonnet-20240620-v1:0' +``` + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`inferenceProfileId`](../interfaces/IInferenceProfile.md#inferenceprofileid) + +*** + +### inferenceProfileModel + +> `readonly` **inferenceProfileModel**: [`BedrockFoundationModel`](BedrockFoundationModel.md) + +The underlying model supporting cross-region inference. + +*** + +### invokableArn + +> `readonly` **invokableArn**: `string` + +This equals to the inferenceProfileArn property, useful just to implement IInvokable interface + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`invokableArn`](../interfaces/IInvokable.md#invokablearn) + +*** + +### type + +> `readonly` **type**: [`InferenceProfileType`](../enumerations/InferenceProfileType.md) + +#### Example + +```ts +InferenceProfileType.SYSTEM_DEFINED +``` + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`type`](../interfaces/IInferenceProfile.md#type) + +## Methods + +### grantInvoke() + +> **grantInvoke**(`grantee`): `Grant` + +Gives the appropriate policies to invoke and use the Foundation Model. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +#### Implementation of + +[`IInvokable`](../interfaces/IInvokable.md).[`grantInvoke`](../interfaces/IInvokable.md#grantinvoke) + +*** + +### grantProfileUsage() + +> **grantProfileUsage**(`grantee`): `Grant` + +Grants appropriate permissions to use the cross-region inference profile. +Does not grant permissions to use the model in the profile. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`grantProfileUsage`](../interfaces/IInferenceProfile.md#grantprofileusage) + +*** + +### fromConfig() + +> `static` **fromConfig**(`config`): [`CrossRegionInferenceProfile`](CrossRegionInferenceProfile.md) + +#### Parameters + +• **config**: [`CrossRegionInferenceProfileProps`](../interfaces/CrossRegionInferenceProfileProps.md) + +#### Returns + +[`CrossRegionInferenceProfile`](CrossRegionInferenceProfile.md) diff --git a/apidocs/namespaces/bedrock/classes/InferenceProfileBase.md b/apidocs/namespaces/bedrock/classes/InferenceProfileBase.md new file mode 100644 index 00000000..d4076e27 --- /dev/null +++ b/apidocs/namespaces/bedrock/classes/InferenceProfileBase.md @@ -0,0 +1,400 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / InferenceProfileBase + +# Class: `abstract` InferenceProfileBase + +Abstract base class for a ApplicationInferenceProfile. +Contains methods and attributes valid for ApplicationInferenceProfiles either created with CDK or imported. + +## Extends + +- `Resource` + +## Extended by + +- [`ApplicationInferenceProfile`](ApplicationInferenceProfile.md) + +## Implements + +- [`IInferenceProfile`](../interfaces/IInferenceProfile.md) +- `IResource` + +## Constructors + +### new InferenceProfileBase() + +> **new InferenceProfileBase**(`scope`, `id`, `props`?): [`InferenceProfileBase`](InferenceProfileBase.md) + +#### Parameters + +• **scope**: `Construct` + +• **id**: `string` + +• **props?**: `ResourceProps` + +#### Returns + +[`InferenceProfileBase`](InferenceProfileBase.md) + +#### Inherited from + +`Resource.constructor` + +## Properties + +### env + +> `readonly` **env**: `ResourceEnvironment` + +The environment this resource belongs to. +For resources that are created and managed by the CDK +(generally, those created by creating new class instances like Role, Bucket, etc.), +this is always the same as the environment of the stack they belong to; +however, for imported resources +(those obtained from static methods like fromRoleArn, fromBucketName, etc.), +that might be different than the stack they were imported into. + +#### Implementation of + +`IResource.env` + +#### Inherited from + +`Resource.env` + +*** + +### inferenceProfileArn + +> `abstract` `readonly` **inferenceProfileArn**: `string` + +The ARN of the application inference profile. + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`inferenceProfileArn`](../interfaces/IInferenceProfile.md#inferenceprofilearn) + +*** + +### inferenceProfileId + +> `abstract` `readonly` **inferenceProfileId**: `string` + +The unique identifier of the inference profile. + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`inferenceProfileId`](../interfaces/IInferenceProfile.md#inferenceprofileid) + +*** + +### node + +> `readonly` **node**: `Node` + +The tree node. + +#### Implementation of + +`IResource.node` + +#### Inherited from + +`Resource.node` + +*** + +### physicalName + +> `protected` `readonly` **physicalName**: `string` + +Returns a string-encoded token that resolves to the physical name that +should be passed to the CloudFormation resource. + +This value will resolve to one of the following: +- a concrete value (e.g. `"my-awesome-bucket"`) +- `undefined`, when a name should be generated by CloudFormation +- a concrete name generated automatically during synthesis, in + cross-environment scenarios. + +#### Inherited from + +`Resource.physicalName` + +*** + +### stack + +> `readonly` **stack**: `Stack` + +The stack in which this resource is defined. + +#### Implementation of + +`IResource.stack` + +#### Inherited from + +`Resource.stack` + +*** + +### type + +> `abstract` `readonly` **type**: [`InferenceProfileType`](../enumerations/InferenceProfileType.md) + +The ID or Amazon Resource Name (ARN) of the inference profile. + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`type`](../interfaces/IInferenceProfile.md#type) + +## Methods + +### \_enableCrossEnvironment() + +> **\_enableCrossEnvironment**(): `void` + +**`Internal`** + +Called when this resource is referenced across environments +(account/region) to order to request that a physical name will be generated +for this resource during synthesis, so the resource can be referenced +through its absolute name/arn. + +#### Returns + +`void` + +#### Inherited from + +`Resource._enableCrossEnvironment` + +*** + +### applyRemovalPolicy() + +> **applyRemovalPolicy**(`policy`): `void` + +Apply the given removal policy to this resource + +The Removal Policy controls what happens to this resource when it stops +being managed by CloudFormation, either because you've removed it from the +CDK application or because you've made a change that requires the resource +to be replaced. + +The resource can be deleted (`RemovalPolicy.DESTROY`), or left in your AWS +account for data recovery and cleanup later (`RemovalPolicy.RETAIN`). + +#### Parameters + +• **policy**: `RemovalPolicy` + +#### Returns + +`void` + +#### Implementation of + +`IResource.applyRemovalPolicy` + +#### Inherited from + +`Resource.applyRemovalPolicy` + +*** + +### generatePhysicalName() + +> `protected` **generatePhysicalName**(): `string` + +#### Returns + +`string` + +#### Inherited from + +`Resource.generatePhysicalName` + +*** + +### getResourceArnAttribute() + +> `protected` **getResourceArnAttribute**(`arnAttr`, `arnComponents`): `string` + +Returns an environment-sensitive token that should be used for the +resource's "ARN" attribute (e.g. `bucket.bucketArn`). + +Normally, this token will resolve to `arnAttr`, but if the resource is +referenced across environments, `arnComponents` will be used to synthesize +a concrete ARN with the resource's physical name. Make sure to reference +`this.physicalName` in `arnComponents`. + +#### Parameters + +• **arnAttr**: `string` + +The CFN attribute which resolves to the ARN of the resource. +Commonly it will be called "Arn" (e.g. `resource.attrArn`), but sometimes +it's the CFN resource's `ref`. + +• **arnComponents**: `ArnComponents` + +The format of the ARN of this resource. You must +reference `this.physicalName` somewhere within the ARN in order for +cross-environment references to work. + +#### Returns + +`string` + +#### Inherited from + +`Resource.getResourceArnAttribute` + +*** + +### getResourceNameAttribute() + +> `protected` **getResourceNameAttribute**(`nameAttr`): `string` + +Returns an environment-sensitive token that should be used for the +resource's "name" attribute (e.g. `bucket.bucketName`). + +Normally, this token will resolve to `nameAttr`, but if the resource is +referenced across environments, it will be resolved to `this.physicalName`, +which will be a concrete name. + +#### Parameters + +• **nameAttr**: `string` + +The CFN attribute which resolves to the resource's name. +Commonly this is the resource's `ref`. + +#### Returns + +`string` + +#### Inherited from + +`Resource.getResourceNameAttribute` + +*** + +### grantProfileUsage() + +> **grantProfileUsage**(`grantee`): `Grant` + +Grants appropriate permissions to use the cross-region inference profile. +Does not grant permissions to use the model in the profile. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` + +#### Implementation of + +[`IInferenceProfile`](../interfaces/IInferenceProfile.md).[`grantProfileUsage`](../interfaces/IInferenceProfile.md#grantprofileusage) + +*** + +### toString() + +> **toString**(): `string` + +Returns a string representation of this construct. + +#### Returns + +`string` + +#### Inherited from + +`Resource.toString` + +*** + +### isConstruct() + +> `static` **isConstruct**(`x`): `x is Construct` + +Checks if `x` is a construct. + +Use this method instead of `instanceof` to properly detect `Construct` +instances, even when the construct library is symlinked. + +Explanation: in JavaScript, multiple copies of the `constructs` library on +disk are seen as independent, completely different libraries. As a +consequence, the class `Construct` in each copy of the `constructs` library +is seen as a different class, and an instance of one class will not test as +`instanceof` the other class. `npm install` will not create installations +like this, but users may manually symlink construct libraries together or +use a monorepo tool: in those cases, multiple copies of the `constructs` +library can be accidentally installed, and `instanceof` will behave +unpredictably. It is safest to avoid using `instanceof`, and using +this type-testing method instead. + +#### Parameters + +• **x**: `any` + +Any object + +#### Returns + +`x is Construct` + +true if `x` is an object created from a class which extends `Construct`. + +#### Inherited from + +`Resource.isConstruct` + +*** + +### isOwnedResource() + +> `static` **isOwnedResource**(`construct`): `boolean` + +Returns true if the construct was created by CDK, and false otherwise + +#### Parameters + +• **construct**: `IConstruct` + +#### Returns + +`boolean` + +#### Inherited from + +`Resource.isOwnedResource` + +*** + +### isResource() + +> `static` **isResource**(`construct`): `construct is Resource` + +Check whether the given construct is a Resource + +#### Parameters + +• **construct**: `IConstruct` + +#### Returns + +`construct is Resource` + +#### Inherited from + +`Resource.isResource` diff --git a/apidocs/namespaces/bedrock/classes/PromptVariant.md b/apidocs/namespaces/bedrock/classes/PromptVariant.md index 312882ea..c89038c4 100644 --- a/apidocs/namespaces/bedrock/classes/PromptVariant.md +++ b/apidocs/namespaces/bedrock/classes/PromptVariant.md @@ -46,9 +46,9 @@ The name of the prompt variant. *** -### templateConfiguration? +### templateConfiguration -> `abstract` `optional` **templateConfiguration**: `PromptTemplateConfigurationProperty` +> `abstract` **templateConfiguration**: `PromptTemplateConfigurationProperty` The template configuration. diff --git a/apidocs/namespaces/bedrock/enumerations/CrossRegionInferenceProfileRegion.md b/apidocs/namespaces/bedrock/enumerations/CrossRegionInferenceProfileRegion.md new file mode 100644 index 00000000..e3cc6225 --- /dev/null +++ b/apidocs/namespaces/bedrock/enumerations/CrossRegionInferenceProfileRegion.md @@ -0,0 +1,45 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / CrossRegionInferenceProfileRegion + +# Enumeration: CrossRegionInferenceProfileRegion + +## Enumeration Members + +### APAC + +> **APAC**: `"apac"` + +Cross-region Inference Identifier for the Asia-Pacific area. +According to the model chosen, this might include: +- Tokyo (`ap-northeast-1`) +- Seoul (`ap-northeast-2`) +- Mumbai (`ap-south-1`) +- Singapore (`ap-southeast-1`) +- Sydney (`ap-southeast-2`) + +*** + +### EU + +> **EU**: `"eu"` + +Cross-region Inference Identifier for the European area. +According to the model chosen, this might include: +- Frankfurt (`eu-central-1`) +- Ireland (`eu-west-1`) +- Paris (`eu-west-3`) + +*** + +### US + +> **US**: `"us"` + +Cross-region Inference Identifier for the United States area. +According to the model chosen, this might include: +- N. Virginia (`us-east-1`) +- Oregon (`us-west-2`) +- Ohio (`us-east-2`) diff --git a/apidocs/namespaces/bedrock/enumerations/InferenceProfileType.md b/apidocs/namespaces/bedrock/enumerations/InferenceProfileType.md new file mode 100644 index 00000000..cabcc6e3 --- /dev/null +++ b/apidocs/namespaces/bedrock/enumerations/InferenceProfileType.md @@ -0,0 +1,27 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / InferenceProfileType + +# Enumeration: InferenceProfileType + +These are the values used by the API when using aws bedrock get-inference-profile --inference-profile-identifier XXXXXXX + +## Enumeration Members + +### APPLICATION + +> **APPLICATION**: `"APPLICATION"` + +An inference profile that is user-created. These are profiles that help +you track costs or metrics. + +*** + +### SYSTEM\_DEFINED + +> **SYSTEM\_DEFINED**: `"SYSTEM_DEFINED"` + +An inference profile that is created by AWS. These are profiles such as cross-region +which help you distributed traffic across a geographic region. diff --git a/apidocs/namespaces/bedrock/interfaces/AgentProps.md b/apidocs/namespaces/bedrock/interfaces/AgentProps.md index ddb5b92f..3077c935 100644 --- a/apidocs/namespaces/bedrock/interfaces/AgentProps.md +++ b/apidocs/namespaces/bedrock/interfaces/AgentProps.md @@ -93,7 +93,7 @@ allows the Bedrock service to assume the role. ### foundationModel -> `readonly` **foundationModel**: [`BedrockFoundationModel`](../classes/BedrockFoundationModel.md) +> `readonly` **foundationModel**: [`IInvokable`](IInvokable.md) The Bedrock text foundation model for the agent to use. diff --git a/apidocs/namespaces/bedrock/interfaces/ApplicationInferenceProfileAttributes.md b/apidocs/namespaces/bedrock/interfaces/ApplicationInferenceProfileAttributes.md new file mode 100644 index 00000000..12924b93 --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/ApplicationInferenceProfileAttributes.md @@ -0,0 +1,27 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / ApplicationInferenceProfileAttributes + +# Interface: ApplicationInferenceProfileAttributes + +*************************************************************************** + ATTRS FOR IMPORTED CONSTRUCT +*************************************************************************** + +## Properties + +### inferenceProfileArn + +> `readonly` **inferenceProfileArn**: `string` + +The ARN of the application inference profile. + +*** + +### inferenceProfileIdentifier + +> `readonly` **inferenceProfileIdentifier**: `string` + +The ID or Amazon Resource Name (ARN) of the inference profile. diff --git a/apidocs/namespaces/bedrock/interfaces/ApplicationInferenceProfileProps.md b/apidocs/namespaces/bedrock/interfaces/ApplicationInferenceProfileProps.md new file mode 100644 index 00000000..8f3af826 --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/ApplicationInferenceProfileProps.md @@ -0,0 +1,56 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / ApplicationInferenceProfileProps + +# Interface: ApplicationInferenceProfileProps + +Properties for creating a ApplicationInferenceProfile. + +## Properties + +### description? + +> `readonly` `optional` **description**: `string` + +Description of the inference profile. + +#### See + +http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-bedrock-applicationinferenceprofile.html#cfn-bedrock-applicationinferenceprofile-description + +*** + +### inferenceProfileName + +> `readonly` **inferenceProfileName**: `string` + +The name of the inference profile. + +#### See + +http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-bedrock-applicationinferenceprofile.html#cfn-bedrock-applicationinferenceprofile-inferenceprofilename + +*** + +### modelSource + +> `readonly` **modelSource**: [`IInvokable`](IInvokable.md) + +To create an application inference profile for one Region, specify a foundation model. +Usage and costs for requests made to that Region with that model will be tracked. + +To create an application inference profile for multiple Regions, +specify a cross region (system-defined) inference profile. +The inference profile will route requests to the Regions defined in +the cross region (system-defined) inference profile that you choose. +Usage and costs for requests made to the Regions in the inference profile will be tracked. + +*** + +### tags? + +> `readonly` `optional` **tags**: `CfnTag`[] + +A list of tags associated with the inference profile. diff --git a/apidocs/namespaces/bedrock/interfaces/BedrockFoundationModelProps.md b/apidocs/namespaces/bedrock/interfaces/BedrockFoundationModelProps.md index d9e537fb..d53e5622 100644 --- a/apidocs/namespaces/bedrock/interfaces/BedrockFoundationModelProps.md +++ b/apidocs/namespaces/bedrock/interfaces/BedrockFoundationModelProps.md @@ -22,6 +22,20 @@ Bedrock Agents can use this model. *** +### supportsCrossRegion? + +> `readonly` `optional` **supportsCrossRegion**: `boolean` + +Can be used with a Cross-Region Inference Profile + +#### Default + +```ts +- false +``` + +*** + ### supportsKnowledgeBase? > `readonly` `optional` **supportsKnowledgeBase**: `boolean` diff --git a/apidocs/namespaces/bedrock/interfaces/CommonPromptVariantProps.md b/apidocs/namespaces/bedrock/interfaces/CommonPromptVariantProps.md index 0039566c..6ca83574 100644 --- a/apidocs/namespaces/bedrock/interfaces/CommonPromptVariantProps.md +++ b/apidocs/namespaces/bedrock/interfaces/CommonPromptVariantProps.md @@ -14,7 +14,7 @@ ### model -> `readonly` **model**: `IModel` +> `readonly` **model**: [`IInvokable`](IInvokable.md) The model which is used to run the prompt. The model could be a foundation model, a custom model, or a provisioned model. diff --git a/apidocs/namespaces/bedrock/interfaces/CrossRegionInferenceProfileProps.md b/apidocs/namespaces/bedrock/interfaces/CrossRegionInferenceProfileProps.md new file mode 100644 index 00000000..27bab6a1 --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/CrossRegionInferenceProfileProps.md @@ -0,0 +1,32 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / CrossRegionInferenceProfileProps + +# Interface: CrossRegionInferenceProfileProps + +*************************************************************************** + PROPS FOR NEW CONSTRUCT +*************************************************************************** + +## Properties + +### geoRegion + +> `readonly` **geoRegion**: [`CrossRegionInferenceProfileRegion`](../enumerations/CrossRegionInferenceProfileRegion.md) + +The geographic region where the traffic is going to be distributed. Routing +factors in user traffic, demand and utilization of resources. + +*** + +### model + +> `readonly` **model**: [`BedrockFoundationModel`](../classes/BedrockFoundationModel.md) + +A model supporting cross-region inference. + +#### See + +https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference-support.html diff --git a/apidocs/namespaces/bedrock/interfaces/FoundationModelParsingStategyProps.md b/apidocs/namespaces/bedrock/interfaces/FoundationModelParsingStategyProps.md index 1a57624c..c3d39f98 100644 --- a/apidocs/namespaces/bedrock/interfaces/FoundationModelParsingStategyProps.md +++ b/apidocs/namespaces/bedrock/interfaces/FoundationModelParsingStategyProps.md @@ -12,7 +12,7 @@ Properties for configuring a Foundation Model parsing strategy. ### parsingModel -> `readonly` **parsingModel**: `IModel` +> `readonly` **parsingModel**: [`IInvokable`](IInvokable.md) The Foundation Model to use for parsing non-textual information. Currently supported models are Claude 3 Sonnet and Claude 3 Haiku. diff --git a/apidocs/namespaces/bedrock/interfaces/IInferenceProfile.md b/apidocs/namespaces/bedrock/interfaces/IInferenceProfile.md new file mode 100644 index 00000000..bf57e911 --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/IInferenceProfile.md @@ -0,0 +1,49 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / IInferenceProfile + +# Interface: IInferenceProfile + +Represents a ApplicationInferenceProfile, either created with CDK or imported. + +## Properties + +### inferenceProfileArn + +> `readonly` **inferenceProfileArn**: `string` + +The ARN of the application inference profile. + +*** + +### inferenceProfileId + +> `readonly` **inferenceProfileId**: `string` + +The unique identifier of the inference profile. + +*** + +### type + +> `readonly` **type**: [`InferenceProfileType`](../enumerations/InferenceProfileType.md) + +The type of inference profile. + +## Methods + +### grantProfileUsage() + +> **grantProfileUsage**(`grantee`): `Grant` + +Grants appropriate permissions to use the inference profile. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` diff --git a/apidocs/namespaces/bedrock/interfaces/IInvokable.md b/apidocs/namespaces/bedrock/interfaces/IInvokable.md new file mode 100644 index 00000000..392f43ca --- /dev/null +++ b/apidocs/namespaces/bedrock/interfaces/IInvokable.md @@ -0,0 +1,35 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../README.md) • **Docs** + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../README.md) / [bedrock](../README.md) / IInvokable + +# Interface: IInvokable + +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. + +## Properties + +### invokableArn + +> `readonly` **invokableArn**: `string` + +The ARN of the Bedrock invokable abstraction. + +## Methods + +### grantInvoke() + +> **grantInvoke**(`grantee`): `Grant` + +Gives the appropriate policies to invoke and use the invokable abstraction. + +#### Parameters + +• **grantee**: `IGrantable` + +#### Returns + +`Grant` diff --git a/apidocs/namespaces/bedrock/interfaces/TextPromptVariantProps.md b/apidocs/namespaces/bedrock/interfaces/TextPromptVariantProps.md index b3b6f8e2..0a2d2f28 100644 --- a/apidocs/namespaces/bedrock/interfaces/TextPromptVariantProps.md +++ b/apidocs/namespaces/bedrock/interfaces/TextPromptVariantProps.md @@ -22,7 +22,7 @@ Inference configuration for the Text Prompt ### model -> `readonly` **model**: `IModel` +> `readonly` **model**: [`IInvokable`](IInvokable.md) The model which is used to run the prompt. The model could be a foundation model, a custom model, or a provisioned model. diff --git a/package.json b/package.json index a8047a5b..76a3dfdc 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,11 @@ "integ:aws-llama-index-data-loader:destroy": "npx projen integ:aws-llama-index-data-loader:destroy", "integ:aws-llama-index-data-loader:snapshot": "npx projen integ:aws-llama-index-data-loader:snapshot", "integ:aws-llama-index-data-loader:watch": "npx projen integ:aws-llama-index-data-loader:watch", + "integ:inference-profiles:assert": "npx projen integ:inference-profiles:assert", + "integ:inference-profiles:deploy": "npx projen integ:inference-profiles:deploy", + "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:snapshot-all": "npx projen integ:snapshot-all", "package": "npx projen package", "package-all": "npx projen package-all", @@ -54,7 +59,7 @@ }, "devDependencies": { "@aws-cdk/assert": "^2.68.0", - "@aws-cdk/integ-tests-alpha": "2.162.1-alpha.0", + "@aws-cdk/integ-tests-alpha": "2.166.0-alpha.0", "@commitlint/config-conventional": "^18.6.3", "@mrgrain/jsii-struct-builder": "^0.7.43", "@types/jest": "^29.5.14", @@ -62,7 +67,7 @@ "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", "aws-cdk": "^2", - "aws-cdk-lib": "2.162.1", + "aws-cdk-lib": "2.166.0", "aws-sdk-mock": "^5.9.0", "commitlint": "^18.6.1", "constructs": "10.3.0", @@ -87,7 +92,7 @@ "typescript": "^5.6.3" }, "peerDependencies": { - "aws-cdk-lib": "^2.162.1", + "aws-cdk-lib": "^2.166.0", "constructs": "^10.3.0" }, "dependencies": { diff --git a/src/cdk-lib/bedrock/README.md b/src/cdk-lib/bedrock/README.md index 34ac28a3..6c52eb1e 100644 --- a/src/cdk-lib/bedrock/README.md +++ b/src/cdk-lib/bedrock/README.md @@ -28,6 +28,9 @@ This construct library includes CloudFormation L1 resources to deploy Bedrock fe - [API](#api) - [Knowledge Bases](#knowledge-bases) - [Agents](#agents) +- [Guardrails](#bedrock-guardrails) +- [Prompt management](#prompt-management) +- [Application inference profile](#application-inference-profile) ## API @@ -404,7 +407,7 @@ kb.addS3DataSource({ bucket, chunkingStrategy: ChunkingStrategy.SEMANTIC, parsingStrategy: ParsingStategy.foundationModel({ - model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0.asIModel(stack), + model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, }), }); @@ -725,7 +728,7 @@ two parsing strategies: ```ts bedrock.ParsingStategy.foundationModel({ - model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0.asIModel(stack), + model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, }); ``` @@ -733,7 +736,7 @@ two parsing strategies: ```python bedrock.ParsingStategy.foundation_model( - parsing_model=BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0.as_i_model(self) + parsing_model=BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0 ) ``` @@ -780,7 +783,7 @@ const agent = new bedrock.Agent(this, "Agent", { instruction: "You are a helpful and friendly agent that answers questions about literature.", }); -agent.addKnowledgeBase([kb]); +agent.addKnowledgeBase(kb); ``` Python @@ -795,6 +798,39 @@ agent = bedrock.Agent( agent.add_knowledge_base(kb); ``` +You can also use system defined inference profiles to enable cross region inference requests for supported models. For instance: + +TypeScript + +```ts +const cris = bedrock.CrossRegionInferenceProfile.fromConfig({ + geoRegion: bedrock.CrossRegionInferenceProfileRegion.US, + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V1_0, +}); + +const agent = new bedrock.Agent(this, 'Agent', { + foundationModel: cris, + instruction: 'You are a helpful and friendly agent that answers questions about agriculture.' +}); + +``` +Python +```python +cris = bedrock.CrossRegionInferenceProfile.from_config( + geo_region= bedrock.CrossRegionInferenceProfileRegion.US, + model= bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V1_0 +) + +agent = bedrock.Agent( + self, + "Agent", + foundation_model=cris, + instruction="You are a helpful and friendly agent that answers questions about agriculture.", +) +``` + +For more information on cross region inference, please refer to [System defined inference profiles](#system-defined-inference-profiles) + ### Action Groups An action group defines functions your agent can call. The functions are Lambda functions. The action group uses an OpenAPI schema to tell the agent what your functions do and how to call them. @@ -1016,7 +1052,7 @@ alias = bedrock.AgentAlias(self, 'ProdAlias', ) ``` -### Bedrock Guardrails +## Bedrock Guardrails Amazon Bedrock's Guardrails feature enables you to implement robust governance and control mechanisms for your generative AI applications, ensuring alignment with your specific use cases and responsible AI policies. Guardrails empowers you to create multiple tailored policy configurations, each designed to address the unique requirements and constraints of different use cases. These policy configurations can then be seamlessly applied across multiple foundation models (FMs) and Agents, ensuring a consistent user experience and standardizing safety, security, and privacy controls throughout your generative AI ecosystem. @@ -1216,7 +1252,7 @@ Example of `Prompt`: ```ts const cmk = new kms.Key(this, "cmk", {}); -const claudeModel = BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0.asIModel(this); +const claudeModel = BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0; const variant1 = PromptVariant.text({ variantName: "variant1", @@ -1227,7 +1263,6 @@ const variant1 = PromptVariant.text({ temperature: 1.0, topP: 0.999, maxTokens: 2000, - topK: 250, }, }); @@ -1264,7 +1299,6 @@ const variant2 = PromptVariant.text({ temperature: 0.5, topP: 0.999, maxTokens: 2000, - topK: 250, }, }); @@ -1294,3 +1328,143 @@ or alternatively: ```ts prompt1.createVersion("my first version"); ``` + +## System defined inference profiles + +You can build a CrossRegionInferenceProfile using a system defined inference profile. The inference profile will route requests to the Regions defined in the cross region (system-defined) inference profile that you choose. You can find the system defined inference profiles by navigating to your console (Amazon Bedrock -> Cross-region inference) or programmatically, for instance using [boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock/client/list_inference_profiles.html). + +Before using creating a CrossRegionInferenceProfile, ensure that you have access to the models and regions defined in the inference profiles. For instance, if you see the system defined inference profile "us.anthropic.claude-3-5-sonnet-20241022-v2:0" defined in your region, the table mentions that inference requests will be routed to US East (Virginia) us-east-1, US East (Ohio) us-east-2 and US West (Oregon) us-west-2. Thus, you need to have model access enabled in those regions for the model ```anthropic.claude-3-5-sonnet-20241022-v2:0```. You can then create the CrossRegionInferenceProfile as follows: + +TypeScript + +```ts +const cris = bedrock.CrossRegionInferenceProfile.fromConfig({ + geoRegion: bedrock.CrossRegionInferenceProfileRegion.US, + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0 +}); +``` + +Python + +```python +cris = bedrock.CrossRegionInferenceProfile.from_config( + geo_region= bedrock.CrossRegionInferenceProfileRegion.US, + model= bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0 +) +``` + +## Application inference profile + +You can create an application inference profile with one or more Regions to track usage and costs when invoking a model. + +To create an application inference profile for one Region, specify a foundation model. Usage and costs for requests made to that Region with that model will be tracked. + +To create an application inference profile for multiple Regions, specify a cross region (system-defined) inference profile. The inference profile will route requests to the Regions defined in the cross region (system-defined) inference profile that you choose. Usage and costs for requests made to the Regions in the inference profile will be tracked. You can find the system defined inference profiles by navigating to your console (Amazon Bedrock -> Cross-region inference) or programmatically, for instance using [boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock/client/list_inference_profiles.html): +``` +bedrock = session.client("bedrock", region_name="us-east-1") +bedrock.list_inference_profiles(typeEquals='SYSTEM_DEFINED') +``` + +Before using application inference profiles, ensure that: +- You have appropriate IAM permissions +- You have access to the models and regions defined in the inference profiles +- Ensure proper configuration of the required API permissions for inference profile-related actions + +Specifically the role you are assuming needs to have permissions for following actions in the IAM policy +``` +"Action": [ + "bedrock:GetInferenceProfile", + "bedrock:ListInferenceProfiles", + "bedrock:DeleteInferenceProfile" + "bedrock:TagResource", + "bedrock:UntagResource", + "bedrock:ListTagsForResource" + ] +``` +You can restrict to specific resources by applying "Resources" tag in the IAM policy. +``` +"Resource": ["arn:aws:bedrock:*:*:application-inference-profile/*"] +``` + +TypeScript + +```ts +// Create an application inference profile for one Region +// You can use the 'bedrock.BedrockFoundationModel' or pass the arn as a string +const appInfProfile1 = new ApplicationInferenceProfile(this, 'myapplicationprofile', { + inferenceProfileName: 'claude 3 sonnet v1', + modelSource: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + tags: [{key: 'test', value: 'test'}] +}); + +// To create an application inference profile across regions, specify the cross region inference profile +const cris = bedrock.CrossRegionInferenceProfile.fromConfig({ + geoRegion: bedrock.CrossRegionInferenceProfileRegion.US, + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0 +}); + +const appInfProfile2 = new ApplicationInferenceProfile(this, 'myapplicationprofile2', { + inferenceProfileName: 'claude 3 sonnet v1', + modelSource: cris +}); + +// Import a Cfn L1 construct created application inference profile +const cfnapp = new CfnApplicationInferenceProfile(this, 'mytestaip3', { + inferenceProfileName: 'mytest', + modelSource: { + copyFrom: 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0', + }, +}); + +const appInfProfile3 = bedrock.ApplicationInferenceProfile.fromCfnApplicationInferenceProfile(cfnapp); + +// Import an inference profile through attributes +const appInfProfile4 = bedrock.ApplicationInferenceProfile.fromApplicationInferenceProfileAttributes(this, 'TestAIP', { + inferenceProfileArn: 'arn:aws:bedrock:us-east-1:XXXXX:application-inference-profile/ID', + inferenceProfileIdentifier: 'arn:aws:bedrock:us-east-1:XXXXXXX:application-inference-profile/ID', +}); + +``` + +Python + +```python + +# Create an application inference profile for one Region +# You can use the 'bedrock.BedrockFoundationModel' or pass the arn as a string +appInfProfile1 = bedrock.ApplicationInferenceProfile(self, 'myapplicationprofile', + inference_profile_name='claude 3 sonnet v1', + model_source=bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + tags=[CfnTag( + key="key", + value="value" + )] +) + +# To create an application inference profile across regions, specify the cross region inference profile +cris = bedrock.CrossRegionInferenceProfile.from_config( + geo_region= bedrock.CrossRegionInferenceProfileRegion.US, + model= bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0 +) + +appInfProfile2 = bedrock.ApplicationInferenceProfile(self, 'myapplicationprofile2', + inference_profile_name='claude 35 sonnet v2', + model_source=cris +) + +# Import an inference profile through attributes +appInfProfile3 = bedrock.ApplicationInferenceProfile.from_application_inference_profile_attributes(self, 'TestAIP', + inference_profile_arn='arn:aws:bedrock:us-east-1:XXXXX:application-inference-profile/ID', + inference_profile_identifier='arn:aws:bedrock:us-east-1:XXXXXXX:application-inference-profile/ID', +) + +# Import a Cfn L1 construct created application inference profile +cfnaip = CfnApplicationInferenceProfile(this, 'mytestaip4', + inference_profile_name='mytest', + model_source= CfnApplicationInferenceProfile.InferenceProfileModelSourceProperty( + copy_from='arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0' + ), +) + +appInfProfile4 = bedrock.ApplicationInferenceProfile.from_cfn_application_inference_profile(cfnaip); +``` \ No newline at end of file diff --git a/src/cdk-lib/bedrock/agent.ts b/src/cdk-lib/bedrock/agent.ts index 9b6595b9..8036767f 100644 --- a/src/cdk-lib/bedrock/agent.ts +++ b/src/cdk-lib/bedrock/agent.ts @@ -21,7 +21,7 @@ import { AgentActionGroup } from './agent-action-group'; import { AgentAlias } from './agent-alias'; import { IGuardrail } from './guardrails/guardrails'; import { KnowledgeBase } from './knowledge-base'; -import { BedrockFoundationModel } from './models'; +import { IInvokable } from './models'; import { generatePhysicalNameV2 } from '../../common/helpers/utils'; /** @@ -212,7 +212,7 @@ export interface AgentProps { /** * The Bedrock text foundation model for the agent to use. */ - readonly foundationModel: BedrockFoundationModel; + readonly foundationModel: IInvokable; /** * The name of the agent. * @@ -340,6 +340,10 @@ export class Agent extends Construct { * The IAM role for the agent. */ public readonly role: iam.Role; + /** + * The model used by the agent. + */ + public readonly foundationModel: IInvokable; /** * The unique identifier of the agent. */ @@ -390,8 +394,7 @@ export class Agent extends Construct { super(scope, id); validatePromptOverrideConfiguration(props.promptOverrideConfiguration); - validateModel(props.foundationModel); - + this.foundationModel = props.foundationModel; this.name = props.name ?? generatePhysicalNameV2(this, 'bedrock-agent', { maxLength: 32, lower: true, separator: '-' }); @@ -422,22 +425,14 @@ export class Agent extends Construct { }, }), ); - - new iam.Policy(this, 'AgentFMPolicy', { - roles: [this.role], - statements: [ - new iam.PolicyStatement({ - actions: ['bedrock:InvokeModel'], - resources: [props.foundationModel.asArn(this)], - }), - ], - }); } + this.foundationModel.grantInvoke(this.role); + const agent = new bedrock.CfnAgent(this, 'Agent', { agentName: this.name, - foundationModel: String(props.foundationModel), + foundationModel: props.foundationModel.invokableArn, instruction: props.instruction, description: props.description, idleSessionTtlInSeconds: props.idleSessionTTL?.toSeconds(), @@ -596,17 +591,6 @@ export class Agent extends Construct { } } -/** - * Validate that Bedrock Agents can use the selected model. - * - * @internal This is an internal core function and should not be called directly. - */ -function validateModel(foundationModel: BedrockFoundationModel) { - if (!foundationModel.supportsAgents) { - throw new Error(`The model ${foundationModel} is not supported by Bedrock Agents.`); - } -} - /** * Validate the inferenceConfiguration of a prompt override. * diff --git a/src/cdk-lib/bedrock/data-sources/parsing.ts b/src/cdk-lib/bedrock/data-sources/parsing.ts index 1599382e..068909c2 100644 --- a/src/cdk-lib/bedrock/data-sources/parsing.ts +++ b/src/cdk-lib/bedrock/data-sources/parsing.ts @@ -11,9 +11,10 @@ * and limitations under the License. */ -import { CfnDataSource, IModel } from 'aws-cdk-lib/aws-bedrock'; +import { CfnDataSource } from 'aws-cdk-lib/aws-bedrock'; import { PolicyStatement } from 'aws-cdk-lib/aws-iam'; import { DEFAULT_PARSING_PROMPT } from './default-parsing-prompt'; +import { IInvokable } from '../models'; /** * Enum representing the types of parsing strategies available for Amazon Bedrock Knowledge Bases. @@ -22,7 +23,7 @@ enum ParsingStategyType { /** * Uses a Bedrock Foundation Model for advanced parsing of non-textual information from documents. */ - FOUNDATION_MODEL = 'BEDROCK_FOUNDATION_MODEL' + FOUNDATION_MODEL = 'BEDROCK_FOUNDATION_MODEL', } /** @@ -33,7 +34,7 @@ export interface FoundationModelParsingStategyProps { * The Foundation Model to use for parsing non-textual information. * Currently supported models are Claude 3 Sonnet and Claude 3 Haiku. */ - readonly parsingModel: IModel; + readonly parsingModel: IInvokable; /** * Custom prompt to instruct the parser on how to interpret the document. @@ -41,7 +42,6 @@ export interface FoundationModelParsingStategyProps { * @default - Uses the default instruction prompt as provided in the AWS Console. */ readonly parsingPrompt?: string; - } /** @@ -49,7 +49,6 @@ export interface FoundationModelParsingStategyProps { * @see https://docs.aws.amazon.com/bedrock/latest/userguide/kb-chunking-parsing.html#kb-advanced-parsing */ export abstract class ParsingStategy { - // ------------------------------------------------------ // FM Parsing Strategy // ------------------------------------------------------ @@ -65,7 +64,7 @@ export abstract class ParsingStategy { /** The CloudFormation property representation of this configuration */ public readonly configuration = { bedrockFoundationModelConfiguration: { - modelArn: props.parsingModel.modelArn, + modelArn: props.parsingModel.invokableArn, parsingPrompt: { parsingPromptText: props.parsingPrompt ?? DEFAULT_PARSING_PROMPT, }, @@ -74,12 +73,14 @@ export abstract class ParsingStategy { }; public generatePolicyStatements(): PolicyStatement[] { - return [new PolicyStatement({ - actions: ['bedrock:InvokeModel'], - resources: [props.parsingModel.modelArn], - })]; + return [ + new PolicyStatement({ + actions: ['bedrock:InvokeModel'], + resources: [props.parsingModel.invokableArn], + }), + ]; } - }; + } return new FoundationModelTransformation(); } @@ -90,7 +91,4 @@ export abstract class ParsingStategy { public abstract configuration: CfnDataSource.ParsingConfigurationProperty; public abstract generatePolicyStatements(): PolicyStatement[]; - - } - diff --git a/src/cdk-lib/bedrock/index.ts b/src/cdk-lib/bedrock/index.ts index 721a97e1..a97272e5 100644 --- a/src/cdk-lib/bedrock/index.ts +++ b/src/cdk-lib/bedrock/index.ts @@ -30,3 +30,6 @@ 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/cross-region-inference-profile'; diff --git a/src/cdk-lib/bedrock/inference-profiles/application-inference-profile.ts b/src/cdk-lib/bedrock/inference-profiles/application-inference-profile.ts new file mode 100644 index 00000000..0cdc1d16 --- /dev/null +++ b/src/cdk-lib/bedrock/inference-profiles/application-inference-profile.ts @@ -0,0 +1,208 @@ +/** + * 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 { CfnTag, Arn, ArnFormat } from 'aws-cdk-lib'; +import * as bedrock from 'aws-cdk-lib/aws-bedrock'; +import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam'; +import { Construct } from 'constructs'; +import { IInferenceProfile, InferenceProfileBase, InferenceProfileType } from './common'; +import { IInvokable } from '../models'; + +/****************************************************************************** + * PROPS FOR NEW CONSTRUCT + *****************************************************************************/ +/** + * Properties for creating a ApplicationInferenceProfile. + */ +export interface ApplicationInferenceProfileProps { + /** + * Description of the inference profile. + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-bedrock-applicationinferenceprofile.html#cfn-bedrock-applicationinferenceprofile-description + */ + readonly description?: string; + /** + * The name of the inference profile. + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-bedrock-applicationinferenceprofile.html#cfn-bedrock-applicationinferenceprofile-inferenceprofilename + */ + readonly inferenceProfileName: string; + /** + * To create an application inference profile for one Region, specify a foundation model. + * Usage and costs for requests made to that Region with that model will be tracked. + * + * To create an application inference profile for multiple Regions, + * specify a cross region (system-defined) inference profile. + * The inference profile will route requests to the Regions defined in + * the cross region (system-defined) inference profile that you choose. + * Usage and costs for requests made to the Regions in the inference profile will be tracked. + */ + readonly modelSource: IInvokable; + /** + * A list of tags associated with the inference profile. + * */ + readonly tags?: Array; +} + +/****************************************************************************** + * ATTRS FOR IMPORTED CONSTRUCT + *****************************************************************************/ +export interface ApplicationInferenceProfileAttributes { + /** + * The ARN of the application inference profile. + */ + readonly inferenceProfileArn: string; + /** + * The ID or Amazon Resource Name (ARN) of the inference profile. + */ + readonly inferenceProfileIdentifier: string; +} + +/****************************************************************************** + * NEW CONSTRUCT DEFINITION + *****************************************************************************/ +/** + * Class to create a ApplicationInferenceProfile with CDK. + * These are inference profiles created by users (user defined). + * This helps to track costs and model usage. + * @resource AWS::Bedrock::ApplicationInferenceProfile + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html + */ +export class ApplicationInferenceProfile extends InferenceProfileBase implements IInvokable { + /** + * Import a ApplicationInferenceProfile given its attributes + */ + public static fromApplicationInferenceProfileAttributes( + scope: Construct, + id: string, + attrs: ApplicationInferenceProfileAttributes, + ): IInferenceProfile { + class Import extends InferenceProfileBase { + public readonly inferenceProfileArn = attrs.inferenceProfileArn; + public readonly inferenceProfileId = Arn.split(attrs.inferenceProfileArn, ArnFormat.SLASH_RESOURCE_NAME) + .resourceName!; + public readonly type = InferenceProfileType.APPLICATION; + } + + return new Import(scope, id); + } + /** + * Import a low-level L1 Cfn ApplicationInferenceProfile + */ + public static fromCfnApplicationInferenceProfile( + CfnApplicationInferenceProfile: bedrock.CfnApplicationInferenceProfile, + ): IInferenceProfile { + return new (class extends InferenceProfileBase { + public readonly inferenceProfileArn = CfnApplicationInferenceProfile.attrInferenceProfileArn; + public readonly inferenceProfileId = CfnApplicationInferenceProfile.attrInferenceProfileId; + public readonly type = InferenceProfileType.APPLICATION; + })(CfnApplicationInferenceProfile, '@FromCfnApplicationInferenceProfile'); + } + /** + * The name of the application inference profile. + */ + public readonly inferenceProfileName: string; + /** + * The ARN of the application application inference profile. + */ + public readonly inferenceProfileArn: string; + /** + * The unique identifier of the application inference profile. + */ + public readonly inferenceProfileId: string; + /** + * The underlying model/cross-region model used by the application inference profile. + */ + public readonly inferenceProfileModel: IInvokable; + /** + * The status of the application inference profile. ACTIVE means that the inference profile is ready to be used. + */ + public readonly status: string; + /** + * The type of the inference profile. The following types are possible: + * SYSTEM_DEFINED – The inference profile is defined by Amazon Bedrock. + * You can route inference requests across regions with these inference profiles. + * APPLICATION – The inference profile was created by a user. + * This type of inference profile can track metrics and costs when invoking the model in it. + * The inference profile may route requests to one or multiple regions. + */ + public readonly type: InferenceProfileType; + /** + * Time Stamp for ApplicationInferenceProfile creation. + */ + public readonly createdAt: string; + /** + * Time Stamp for ApplicationInferenceProfile update. + */ + public readonly updatedAt: string; + /** + * This equals to the inferenceProfileArn property, useful just to implement IInvokable interface. + */ + public readonly invokableArn: string; + /** + * Instance of CfnApplicationInferenceProfile. + */ + private readonly _resource: bedrock.CfnApplicationInferenceProfile; + + constructor(scope: Construct, id: string, props: ApplicationInferenceProfileProps) { + super(scope, id); + + this.inferenceProfileModel = props.modelSource; + this.inferenceProfileName = props.inferenceProfileName; + this.type = InferenceProfileType.APPLICATION; + + // L1 instantiation + this._resource = new bedrock.CfnApplicationInferenceProfile(this, id, { + description: props.description, + inferenceProfileName: props.inferenceProfileName, + modelSource: { + copyFrom: props.modelSource.invokableArn, + }, + tags: props.tags, + }); + + // build attributes + this.inferenceProfileArn = this._resource.attrInferenceProfileArn; + this.inferenceProfileId = this._resource.attrInferenceProfileId; + this.status = this._resource.attrStatus; + this.type = this._resource.attrType as InferenceProfileType; + this.createdAt = this._resource.attrCreatedAt; + this.updatedAt = this._resource.attrUpdatedAt; + + // Needed to Implement IInvokable + this.invokableArn = this.inferenceProfileArn; + } + + /** + * Gives the appropriate policies to invoke and use the application inference profile. + */ + public grantInvoke(grantee: IGrantable): Grant { + // This method ensures the appropriate permissions are given + // to use either the inference profile or the vanilla FM + this.inferenceProfileModel.grantInvoke(grantee); + + // plus we add permissions to now invoke the application inference profile itself. + + return this.grantProfileUsage(grantee); + } + + /** + * Grants appropriate permissions to use the application inference profile (AIP). + * Does not grant permissions to use the model/cross-region profile in the AIP. + */ + grantProfileUsage(grantee: IGrantable): Grant { + const grant = Grant.addToPrincipal({ + grantee: grantee, + actions: ['bedrock:GetInferenceProfile', 'bedrock:InvokeModel'], + resourceArns: [this.inferenceProfileArn], + }); + return grant; + } +} diff --git a/src/cdk-lib/bedrock/inference-profiles/common.ts b/src/cdk-lib/bedrock/inference-profiles/common.ts new file mode 100644 index 00000000..f366a371 --- /dev/null +++ b/src/cdk-lib/bedrock/inference-profiles/common.ts @@ -0,0 +1,87 @@ +/** + * 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 { IResource, Resource } from 'aws-cdk-lib'; +import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam'; + +/** These are the values used by the API when using aws bedrock get-inference-profile --inference-profile-identifier XXXXXXX */ +export enum InferenceProfileType { + /** + * An inference profile that is created by AWS. These are profiles such as cross-region + * which help you distributed traffic across a geographic region. + */ + SYSTEM_DEFINED = 'SYSTEM_DEFINED', + /** + * An inference profile that is user-created. These are profiles that help + * you track costs or metrics. + */ + APPLICATION = 'APPLICATION', +} + +/****************************************************************************** + * COMMON + *****************************************************************************/ +/** + * Represents a ApplicationInferenceProfile, either created with CDK or imported. + */ +export interface IInferenceProfile { + /** + * The ARN of the application inference profile. + */ + readonly inferenceProfileArn: string; + /** + * The unique identifier of the inference profile. + */ + readonly inferenceProfileId: string; + /** + * The type of inference profile. + */ + readonly type: InferenceProfileType; + + /** + * Grants appropriate permissions to use the inference profile. + */ + grantProfileUsage(grantee: IGrantable): Grant; +} + +/** + * Abstract base class for a ApplicationInferenceProfile. + * Contains methods and attributes valid for ApplicationInferenceProfiles either created with CDK or imported. + */ +export abstract class InferenceProfileBase extends Resource implements IInferenceProfile, IResource { + /** + * The ARN of the application inference profile. + */ + public abstract readonly inferenceProfileArn: string; + /** + * The unique identifier of the inference profile. + */ + public abstract readonly inferenceProfileId: string; + /** + * The ID or Amazon Resource Name (ARN) of the inference profile. + */ + public abstract readonly type: InferenceProfileType; + + /** + * Grants appropriate permissions to use the cross-region inference profile. + * Does not grant permissions to use the model in the profile. + */ + grantProfileUsage(grantee: IGrantable): Grant { + const grant = Grant.addToPrincipal({ + grantee: grantee, + actions: ['bedrock:GetInferenceProfile', 'bedrock:ListInferenceProfiles'], + resourceArns: [this.inferenceProfileArn], + scope: this, + }); + return grant; + } +} 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 new file mode 100644 index 00000000..598d82a3 --- /dev/null +++ b/src/cdk-lib/bedrock/inference-profiles/cross-region-inference-profile.ts @@ -0,0 +1,139 @@ +/** + * 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 { Grant, IGrantable } from 'aws-cdk-lib/aws-iam'; +import { BedrockFoundationModel, IInvokable } from '../models'; +import { IInferenceProfile, InferenceProfileType } from './common'; + +export enum CrossRegionInferenceProfileRegion { + /** + * Cross-region Inference Identifier for the European area. + * According to the model chosen, this might include: + * - Frankfurt (`eu-central-1`) + * - Ireland (`eu-west-1`) + * - Paris (`eu-west-3`) + */ + EU = 'eu', + /** + * Cross-region Inference Identifier for the United States area. + * According to the model chosen, this might include: + * - N. Virginia (`us-east-1`) + * - Oregon (`us-west-2`) + * - Ohio (`us-east-2`) + */ + US = 'us', + /** + * Cross-region Inference Identifier for the Asia-Pacific area. + * According to the model chosen, this might include: + * - Tokyo (`ap-northeast-1`) + * - Seoul (`ap-northeast-2`) + * - Mumbai (`ap-south-1`) + * - Singapore (`ap-southeast-1`) + * - Sydney (`ap-southeast-2`) + */ + APAC = 'apac', +} + +/****************************************************************************** + * PROPS FOR NEW CONSTRUCT + *****************************************************************************/ +export interface CrossRegionInferenceProfileProps { + /** + * The geographic region where the traffic is going to be distributed. Routing + * factors in user traffic, demand and utilization of resources. + */ + readonly geoRegion: CrossRegionInferenceProfileRegion; + /** + * A model supporting cross-region inference. + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference-support.html + */ + readonly model: BedrockFoundationModel; +} + +/****************************************************************************** + * NEW CONSTRUCT DEFINITION + *****************************************************************************/ +/** + * Cross-region inference enables you to seamlessly manage unplanned traffic + * bursts by utilizing compute across different AWS Regions. With cross-region + * inference, you can distribute traffic across multiple AWS Regions, enabling + * higher throughput and enhanced resilience during periods of peak demands. + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html + */ +export class CrossRegionInferenceProfile implements IInvokable, IInferenceProfile { + public static fromConfig(config: CrossRegionInferenceProfileProps): CrossRegionInferenceProfile { + return new CrossRegionInferenceProfile(config); + } + /** + * @example 'us.anthropic.claude-3-5-sonnet-20240620-v1:0' + */ + public readonly inferenceProfileId: string; + /** + * @example 'arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-3-5-sonnet-20240620-v1:0' + */ + public readonly inferenceProfileArn: string; + /** + * @example InferenceProfileType.SYSTEM_DEFINED + */ + public readonly type: InferenceProfileType; + /** + * The underlying model supporting cross-region inference. + */ + public readonly inferenceProfileModel: BedrockFoundationModel; + /** This equals to the inferenceProfileArn property, useful just to implement IInvokable interface*/ + public readonly invokableArn: string; + + private constructor(props: CrossRegionInferenceProfileProps) { + if (!props.model.supportsCrossRegion) { + throw new Error(`Model ${props.model.modelId} does not support cross-region inference`); + } + this.type = InferenceProfileType.SYSTEM_DEFINED; + this.inferenceProfileModel = props.model; + this.inferenceProfileId = `${props.geoRegion}.${props.model.modelId}`; + this.inferenceProfileArn = Arn.format({ + partition: Aws.PARTITION, + service: 'bedrock', + account: Aws.ACCOUNT_ID, + region: Aws.REGION, + resource: 'inference-profile', + resourceName: this.inferenceProfileId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + // Needed to Implement IInvokable + this.invokableArn = this.inferenceProfileArn; + } + + /** + * Gives the appropriate policies to invoke and use the Foundation Model. + */ + public grantInvoke(grantee: IGrantable): Grant { + // for CRIS, we need to provide permissions to invoke the model in all regions + // where the inference profile can route requests + this.inferenceProfileModel.grantInvokeAllRegions(grantee); + // and we need to provide permissions to invoke the inference profile itself + return this.grantProfileUsage(grantee); + } + + /** + * Grants appropriate permissions to use the cross-region inference profile. + * Does not grant permissions to use the model in the profile. + */ + grantProfileUsage(grantee: IGrantable): Grant { + const grant = Grant.addToPrincipal({ + grantee: grantee, + actions: ['bedrock:GetInferenceProfile', 'bedrock:InvokeModel'], + resourceArns: [this.inferenceProfileArn], + }); + return grant; + } +} diff --git a/src/cdk-lib/bedrock/models.ts b/src/cdk-lib/bedrock/models.ts index bc8add0f..09a3db2c 100644 --- a/src/cdk-lib/bedrock/models.ts +++ b/src/cdk-lib/bedrock/models.ts @@ -11,11 +11,28 @@ * and limitations under the License. */ - -import { Stack } from 'aws-cdk-lib'; -import { IModel } from 'aws-cdk-lib/aws-bedrock'; +import { Arn, ArnFormat, Aws } from 'aws-cdk-lib'; +import { IModel, FoundationModel, FoundationModelIdentifier } from 'aws-cdk-lib/aws-bedrock'; +import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam'; import { IConstruct } from 'constructs'; +/** + * 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. + */ +export interface IInvokable { + /** + * The ARN of the Bedrock invokable abstraction. + */ + readonly invokableArn: string; + + /** + * Gives the appropriate policies to invoke and use the invokable abstraction. + */ + grantInvoke(grantee: IGrantable): Grant; +} + export interface BedrockFoundationModelProps { /** * Bedrock Agents can use this model. @@ -29,6 +46,11 @@ export interface BedrockFoundationModelProps { * @default - false */ readonly supportsKnowledgeBase?: boolean; + /** + * Can be used with a Cross-Region Inference Profile + * @default - false + */ + readonly supportsCrossRegion?: boolean; /** * Embedding models have different vector dimensions. * Only applicable for embedding models. @@ -42,82 +64,149 @@ export interface BedrockFoundationModelProps { * If you need to use a model name that doesn't exist as a static member, you * can instantiate a `BedrockFoundationModel` object, e.g: `new BedrockFoundationModel('my-model')`. */ -export class BedrockFoundationModel { - public static readonly ANTHROPIC_CLAUDE_V2 = new BedrockFoundationModel( - 'anthropic.claude-v2', - { supportsAgents: true }, - ); - public static readonly ANTHROPIC_CLAUDE_V2_1 = new BedrockFoundationModel( - 'anthropic.claude-v2:1', - { supportsAgents: true }, - ); - public static readonly ANTHROPIC_CLAUDE_INSTANT_V1_2 = new BedrockFoundationModel( - 'anthropic.claude-instant-v1', - { supportsAgents: true }, - ); - public static readonly AMAZON_TITAN_TEXT_EXPRESS_V1 = new BedrockFoundationModel( - 'amazon.titan-text-express-v1', - { supportsAgents: true }, - ); - public static readonly ANTHROPIC_CLAUDE_3_5_HAIKU_V1_0 = new BedrockFoundationModel( - 'anthropic.claude-3-5-haiku-20241022-v1:0', - { supportsAgents: true }, - ); +export class BedrockFoundationModel implements IInvokable { + /**************************************************************************** + * AMAZON + ***************************************************************************/ + public static readonly AMAZON_TITAN_TEXT_EXPRESS_V1 = new BedrockFoundationModel('amazon.titan-text-express-v1', { + supportsAgents: true, + }); + + public static readonly AMAZON_TITAN_PREMIER_V1_0 = new BedrockFoundationModel('amazon.titan-text-premier-v1:0', { + supportsAgents: true, + }); + + public static readonly TITAN_EMBED_TEXT_V1 = new BedrockFoundationModel('amazon.titan-embed-text-v1', { + supportsKnowledgeBase: true, + vectorDimensions: 1536, + }); + + public static readonly TITAN_EMBED_TEXT_V2_1024 = new BedrockFoundationModel('amazon.titan-embed-text-v2:0', { + supportsKnowledgeBase: true, + vectorDimensions: 1024, + }); + + public static readonly TITAN_EMBED_TEXT_V2_512 = new BedrockFoundationModel('amazon.titan-embed-text-v2:0', { + supportsKnowledgeBase: true, + vectorDimensions: 512, + }); + + public static readonly TITAN_EMBED_TEXT_V2_256 = new BedrockFoundationModel('amazon.titan-embed-text-v2:0', { + supportsKnowledgeBase: true, + vectorDimensions: 256, + }); + /**************************************************************************** + * ANTHROPIC + ***************************************************************************/ public static readonly ANTHROPIC_CLAUDE_3_5_SONNET_V2_0 = new BedrockFoundationModel( 'anthropic.claude-3-5-sonnet-20241022-v2:0', - { supportsAgents: true }, + { supportsAgents: true, supportsCrossRegion: true }, ); + public static readonly ANTHROPIC_CLAUDE_3_5_SONNET_V1_0 = new BedrockFoundationModel( 'anthropic.claude-3-5-sonnet-20240620-v1:0', - { supportsAgents: true }, + { supportsAgents: true, supportsCrossRegion: true }, ); + + public static readonly ANTHROPIC_CLAUDE_3_5_HAIKU_V1_0 = new BedrockFoundationModel( + 'anthropic.claude-3-5-haiku-20241022-v1:0', + { supportsAgents: true, supportsCrossRegion: true }, + ); + public static readonly ANTHROPIC_CLAUDE_OPUS_V1_0 = new BedrockFoundationModel( 'anthropic.claude-3-opus-20240229-v1:0', { supportsAgents: true }, ); + public static readonly ANTHROPIC_CLAUDE_SONNET_V1_0 = new BedrockFoundationModel( 'anthropic.claude-3-sonnet-20240229-v1:0', - { supportsAgents: true }, + { supportsAgents: true, supportsCrossRegion: true }, ); + public static readonly ANTHROPIC_CLAUDE_HAIKU_V1_0 = new BedrockFoundationModel( 'anthropic.claude-3-haiku-20240307-v1:0', - { supportsAgents: true }, - ); - public static readonly AMAZON_TITAN_PREMIER_V1_0 = new BedrockFoundationModel( - 'amazon.titan-text-premier-v1:0', - { supportsAgents: true }, + { supportsAgents: true, supportsCrossRegion: true }, ); - public static readonly TITAN_EMBED_TEXT_V1 = new BedrockFoundationModel( - 'amazon.titan-embed-text-v1', - { supportsKnowledgeBase: true, vectorDimensions: 1536 }, - ); - public static readonly TITAN_EMBED_TEXT_V2_1024 = new BedrockFoundationModel( - 'amazon.titan-embed-text-v2:0', - { supportsKnowledgeBase: true, vectorDimensions: 1024 }, - ); - public static readonly TITAN_EMBED_TEXT_V2_512 = new BedrockFoundationModel( - 'amazon.titan-embed-text-v2:0', - { supportsKnowledgeBase: true, vectorDimensions: 512 }, - ); - public static readonly TITAN_EMBED_TEXT_V2_256 = new BedrockFoundationModel( - 'amazon.titan-embed-text-v2:0', - { supportsKnowledgeBase: true, vectorDimensions: 256 }, - ); - public static readonly COHERE_EMBED_ENGLISH_V3 = new BedrockFoundationModel( - 'cohere.embed-english-v3', - { supportsKnowledgeBase: true, vectorDimensions: 1024 }, - ); - public static readonly COHERE_EMBED_MULTILINGUAL_V3 = new BedrockFoundationModel( - 'cohere.embed-multilingual-v3', - { supportsKnowledgeBase: true, vectorDimensions: 1024 }, + + public static readonly ANTHROPIC_CLAUDE_V2_1 = new BedrockFoundationModel('anthropic.claude-v2:1', { + supportsAgents: true, + }); + + public static readonly ANTHROPIC_CLAUDE_V2 = new BedrockFoundationModel('anthropic.claude-v2', { + supportsAgents: true, + }); + + public static readonly ANTHROPIC_CLAUDE_INSTANT_V1_2 = new BedrockFoundationModel('anthropic.claude-instant-v1', { + supportsAgents: true, + }); + + /**************************************************************************** + * COHERE + ***************************************************************************/ + public static readonly COHERE_EMBED_ENGLISH_V3 = new BedrockFoundationModel('cohere.embed-english-v3', { + supportsKnowledgeBase: true, + vectorDimensions: 1024, + }); + + public static readonly COHERE_EMBED_MULTILINGUAL_V3 = new BedrockFoundationModel('cohere.embed-multilingual-v3', { + supportsKnowledgeBase: true, + vectorDimensions: 1024, + }); + + /**************************************************************************** + * META + ***************************************************************************/ + public static readonly META_LLAMA_3_2_11B_INSTRUCT_V1 = new BedrockFoundationModel( + 'meta.llama3-2-11b-instruct-v1:0', + { + supportsCrossRegion: true, + }, ); + public static readonly META_LLAMA_3_2_3B_INSTRUCT_V1 = new BedrockFoundationModel('meta.llama3-2-3b-instruct-v1:0', { + supportsCrossRegion: true, + }); + + public static readonly META_LLAMA_3_2_1B_INSTRUCT_V1 = new BedrockFoundationModel('meta.llama3-2-1b-instruct-v1:0', { + supportsCrossRegion: true, + }); + + public static fromCdkFoundationModelId( + modelId: FoundationModelIdentifier, + props: BedrockFoundationModelProps = {}, + ): BedrockFoundationModel { + return new BedrockFoundationModel(modelId.modelId, props); + } + public static fromCdkFoundationModel( + modelId: FoundationModel, + props: BedrockFoundationModelProps = {}, + ): BedrockFoundationModel { + return new BedrockFoundationModel(modelId.modelId, props); + } + + /**************************************************************************** + * Constructor + ***************************************************************************/ public readonly modelId: string; + public readonly modelArn: string; + public readonly invokableArn: string; public readonly supportsAgents: boolean; + public readonly supportsCrossRegion: boolean; public readonly vectorDimensions?: number; public readonly supportsKnowledgeBase: boolean; constructor(value: string, props: BedrockFoundationModelProps = {}) { this.modelId = value; + this.modelArn = Arn.format({ + partition: Aws.PARTITION, + service: 'bedrock', + region: Aws.REGION, + account: '', + resource: 'foundation-model', + resourceName: this.modelId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + this.invokableArn = this.modelArn; + this.supportsCrossRegion = props.supportsCrossRegion ?? false; this.supportsAgents = props.supportsAgents ?? false; this.vectorDimensions = props.vectorDimensions; this.supportsKnowledgeBase = props.supportsKnowledgeBase ?? false; @@ -132,11 +221,47 @@ export class BedrockFoundationModel { * `arn:${Partition}:bedrock:${Region}::foundation-model/${ResourceId}` */ asArn(construct: IConstruct): string { - const region = Stack.of(construct).region; - return `arn:aws:bedrock:${region}::foundation-model/${this.modelId}`; + if (construct) { + } + return this.modelArn; } asIModel(construct: IConstruct): IModel { - return { modelArn: this.asArn(construct) }; + if (construct) { + } + return this; + } + + /** + * Gives the appropriate policies to invoke and use the Foundation Model in the stack region. + */ + public grantInvoke(grantee: IGrantable): Grant { + const grant = Grant.addToPrincipal({ + grantee: grantee, + actions: ['bedrock:InvokeModel'], + resourceArns: [this.invokableArn], + }); + return grant; + } + + /** + * Gives the appropriate policies to invoke and use the Foundation Model in all regions. + */ + public grantInvokeAllRegions(grantee: IGrantable): Grant { + const invokableArn = Arn.format({ + partition: Aws.PARTITION, + service: 'bedrock', + region: '*', + account: '', + resource: 'foundation-model', + resourceName: this.modelId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + + return Grant.addToPrincipal({ + grantee: grantee, + actions: ['bedrock:InvokeModel'], + resourceArns: [invokableArn], + }); } } diff --git a/src/cdk-lib/bedrock/prompts/prompt.ts b/src/cdk-lib/bedrock/prompts/prompt.ts index 754e88a2..1a9b2a3e 100644 --- a/src/cdk-lib/bedrock/prompts/prompt.ts +++ b/src/cdk-lib/bedrock/prompts/prompt.ts @@ -12,11 +12,11 @@ */ import { Arn, ArnFormat, aws_kms as kms, Lazy, aws_bedrock as bedrock, Resource } from 'aws-cdk-lib'; -import { IModel } from 'aws-cdk-lib/aws-bedrock'; import { Grant, IGrantable } from 'aws-cdk-lib/aws-iam'; import { IKey } from 'aws-cdk-lib/aws-kms'; import { md5hash } from 'aws-cdk-lib/core/lib/helpers-internal'; import { Construct } from 'constructs'; +import { IInvokable } from '../models'; export enum PromptTemplateType { TEXT = 'TEXT', @@ -31,7 +31,7 @@ export interface CommonPromptVariantProps { * The model which is used to run the prompt. The model could be a foundation * model, a custom model, or a provisioned model. */ - readonly model: IModel; + readonly model: IInvokable; } export interface TextPromptVariantProps extends CommonPromptVariantProps { @@ -66,7 +66,7 @@ export abstract class PromptVariant { return { name: props.variantName, templateType: PromptTemplateType.TEXT, - modelId: props.model.modelArn, + modelId: props.model.invokableArn, inferenceConfiguration: { text: { ...props.inferenceConfiguration }, }, @@ -102,7 +102,7 @@ export abstract class PromptVariant { /** * The template configuration. */ - public abstract templateConfiguration?: bedrock.CfnPrompt.PromptTemplateConfigurationProperty; + public abstract templateConfiguration: bedrock.CfnPrompt.PromptTemplateConfigurationProperty; // ------------------------------------------------------ // Constructor diff --git a/src/common/props/DockerLambdaCustomProps.ts b/src/common/props/DockerLambdaCustomProps.ts index dff6c541..2523169a 100644 --- a/src/common/props/DockerLambdaCustomProps.ts +++ b/src/common/props/DockerLambdaCustomProps.ts @@ -48,7 +48,7 @@ export interface DockerLambdaCustomProps { readonly reservedConcurrentExecutions?: number; /** * Sets the Recursive Loop Protection for Lambda Function. - * It lets Lambda detect and terminate unintended recusrive loops. + * It lets Lambda detect and terminate unintended recursive loops. * @default RecursiveLoop.Terminate * @stability stable */ diff --git a/test/cdk-lib/bedrock/agent.test.ts b/test/cdk-lib/bedrock/agent.test.ts index 6bde743c..fe967422 100644 --- a/test/cdk-lib/bedrock/agent.test.ts +++ b/test/cdk-lib/bedrock/agent.test.ts @@ -16,7 +16,7 @@ import { Annotations, Match, Template } from 'aws-cdk-lib/assertions'; import { Key } from 'aws-cdk-lib/aws-kms'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as s3 from 'aws-cdk-lib/aws-s3'; -import { NagSuppressions } from 'cdk-nag'; +import { NagSuppressions, AwsSolutionsChecks } from 'cdk-nag'; import * as bedrock from '../../../src/cdk-lib/bedrock'; import * as foundationModels from '../../../src/cdk-lib/bedrock/models'; @@ -158,7 +158,18 @@ describe('Agent with guardrails through addGuardrail', () => { KnowledgeBaseConfiguration: { Type: 'VECTOR', VectorKnowledgeBaseConfiguration: { - EmbeddingModelArn: 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1', + EmbeddingModelArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/amazon.titan-embed-text-v1', + ], + ], + }, }, }, }); @@ -183,7 +194,18 @@ describe('Agent with guardrails through addGuardrail', () => { test('Agent is created', () => { Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::Agent', { - FoundationModel: 'anthropic.claude-v2:1', + FoundationModel: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/anthropic.claude-v2:1', + ], + ], + }, Instruction: 'You provide support for developers working with CDK constructs.', IdleSessionTTLInSeconds: 1800, PromptOverrideConfiguration: { @@ -417,7 +439,18 @@ describe('Agent with guardrails through constructor', () => { KnowledgeBaseConfiguration: { Type: 'VECTOR', VectorKnowledgeBaseConfiguration: { - EmbeddingModelArn: 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1', + EmbeddingModelArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/amazon.titan-embed-text-v1', + ], + ], + }, }, }, }); @@ -442,7 +475,18 @@ describe('Agent with guardrails through constructor', () => { test('Agent is created', () => { Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::Agent', { - FoundationModel: 'anthropic.claude-v2:1', + FoundationModel: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/anthropic.claude-v2:1', + ], + ], + }, Instruction: 'You provide support for developers working with CDK constructs.', IdleSessionTTLInSeconds: 1800, PromptOverrideConfiguration: { @@ -655,7 +699,22 @@ describe('Agent without guardrails', () => { KnowledgeBaseConfiguration: { Type: 'VECTOR', VectorKnowledgeBaseConfiguration: { - EmbeddingModelArn: 'arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1', + EmbeddingModelArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':bedrock:', + { + Ref: 'AWS::Region', + }, + '::foundation-model/amazon.titan-embed-text-v1', + ], + ], + }, }, }, }); @@ -680,7 +739,18 @@ describe('Agent without guardrails', () => { test('Agent is created', () => { Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::Agent', { - FoundationModel: 'anthropic.claude-v2:1', + FoundationModel: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/anthropic.claude-v2:1', + ], + ], + }, Instruction: 'You provide support for developers working with CDK constructs.', IdleSessionTTLInSeconds: 1800, PromptOverrideConfiguration: { @@ -806,3 +876,52 @@ describe('Imports', () => { expect(agentAlias.aliasArn).toEqual('arn:aws:bedrock:us-east-1:123456789012:agent-alias/DNCJJYQKSU/TCLCITFZTN'); }); }); + +describe('Agent with CRIS', () => { + let app: cdk.App; + let stack: cdk.Stack; + + beforeEach(() => { + app = new cdk.App(); + cdk.Aspects.of(app).add(new AwsSolutionsChecks()); + stack = new cdk.Stack(app, 'TestStack'); + + const cris = bedrock.CrossRegionInferenceProfile.fromConfig({ + geoRegion: bedrock.CrossRegionInferenceProfileRegion.US, + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_HAIKU_V1_0, + }); + + new bedrock.Agent(stack, 'Agent', { + foundationModel: cris, + instruction: 'You provide support for developers working with CDK constructs.', + enableUserInput: true, + }); + }); + + test('Foundation model', () => { + // GIVEN + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::Agent', { + FoundationModel: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':bedrock:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0', + ], + ], + }, + Instruction: 'You provide support for developers working with CDK constructs.', + }); + }); +}); diff --git a/test/cdk-lib/bedrock/data-sources/s3-data-source.test.ts b/test/cdk-lib/bedrock/data-sources/s3-data-source.test.ts index 77490680..6161f056 100644 --- a/test/cdk-lib/bedrock/data-sources/s3-data-source.test.ts +++ b/test/cdk-lib/bedrock/data-sources/s3-data-source.test.ts @@ -13,7 +13,6 @@ import * as cdk from 'aws-cdk-lib'; import { Template, Match } from 'aws-cdk-lib/assertions'; -import { FoundationModel, FoundationModelIdentifier } from 'aws-cdk-lib/aws-bedrock'; import { Code, Function, Runtime } from 'aws-cdk-lib/aws-lambda'; import * as s3 from 'aws-cdk-lib/aws-s3'; import { AwsSolutionsChecks } from 'cdk-nag'; @@ -41,7 +40,6 @@ describe('S3 Data Source', () => { dataSourceName: 'TestDataSource', }); - Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { KnowledgeBaseId: { 'Fn::GetAtt': [Match.anyValue(), 'KnowledgeBaseId'], @@ -66,8 +64,7 @@ describe('S3 Data Source', () => { }); Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { - VectorIngestionConfiguration: - { + VectorIngestionConfiguration: { ChunkingConfiguration: { ChunkingStrategy: 'FIXED_SIZE', FixedSizeChunkingConfiguration: { @@ -91,9 +88,7 @@ describe('S3 Data Source', () => { }); Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { - - VectorIngestionConfiguration: - { + VectorIngestionConfiguration: { ChunkingConfiguration: { ChunkingStrategy: 'FIXED_SIZE', FixedSizeChunkingConfiguration: { @@ -114,10 +109,8 @@ describe('S3 Data Source', () => { }); Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { - VectorIngestionConfiguration: - { - ChunkingConfiguration: - { ChunkingStrategy: 'NONE' }, + VectorIngestionConfiguration: { + ChunkingConfiguration: { ChunkingStrategy: 'NONE' }, }, }); }); @@ -228,9 +221,7 @@ describe('S3 Data Source', () => { knowledgeBase: kb, dataSourceName: 'TestDataSource', parsingStrategy: bedrock.ParsingStategy.foundationModel({ - parsingModel: FoundationModel.fromFoundationModelId(stack, 'model', - FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_SONNET_20240229_V1_0, - ), + parsingModel: foundationModels.BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, }), }); @@ -273,16 +264,18 @@ describe('S3 Data Source', () => { Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { VectorIngestionConfiguration: { CustomTransformationConfiguration: { - Transformations: [{ - StepToApply: 'POST_CHUNKING', - TransformationFunction: { - TransformationLambdaConfiguration: { - LambdaArn: { - 'Fn::GetAtt': [Match.anyValue(), 'Arn'], + Transformations: [ + { + StepToApply: 'POST_CHUNKING', + TransformationFunction: { + TransformationLambdaConfiguration: { + LambdaArn: { + 'Fn::GetAtt': [Match.anyValue(), 'Arn'], + }, }, }, }, - }], + ], IntermediateStorage: { S3Location: { URI: Match.anyValue(), @@ -291,8 +284,5 @@ describe('S3 Data Source', () => { }, }, }); - }); - - -}); \ No newline at end of file +}); diff --git a/test/cdk-lib/bedrock/inference-profile.test.ts b/test/cdk-lib/bedrock/inference-profile.test.ts new file mode 100644 index 00000000..00880546 --- /dev/null +++ b/test/cdk-lib/bedrock/inference-profile.test.ts @@ -0,0 +1,253 @@ +/** + * 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 cdk from 'aws-cdk-lib'; +import { Match, Template } from 'aws-cdk-lib/assertions'; +import { CfnApplicationInferenceProfile } from 'aws-cdk-lib/aws-bedrock'; +import { AwsSolutionsChecks } from 'cdk-nag'; +import * as bedrock from '../../../src/cdk-lib/bedrock'; + +describe('CDK-Created-Cross-Region-Inference-Profile', () => { + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App(); + cdk.Aspects.of(app).add(new AwsSolutionsChecks()); + stack = new cdk.Stack(app, 'TestStack'); + }); + + /*test('Basic Creation', () => { + const cris = bedrock.CrossRegionInferenceProfile.fromConfig({ + geoRegion: bedrock.CrossRegionInferenceProfileRegion.EU, + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + }); + + expect(cris.inferenceProfileArn).toBe('cew2pa5r8hog'); + });*/ + + test('Basic Creation with a system defined inference profile', () => { + new bedrock.ApplicationInferenceProfile(stack, 'TestAIPSystem', { + inferenceProfileName: 'TestAIPSystem', + modelSource: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::ApplicationInferenceProfile', { + InferenceProfileName: 'TestAIPSystem', + Description: Match.absent(), + ModelSource: { + CopyFrom: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0', + ], + ], + }, + }, + }); + }); + + test('Basic Creation', () => { + new bedrock.ApplicationInferenceProfile(stack, 'TestAIPSystem', { + inferenceProfileName: 'TestAIPSystem', + modelSource: bedrock.CrossRegionInferenceProfile.fromConfig({ + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0, + geoRegion: bedrock.CrossRegionInferenceProfileRegion.EU, + }), + tags: [{ key: 'project', value: 'test' }], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::ApplicationInferenceProfile', { + InferenceProfileName: 'TestAIPSystem', + Description: Match.absent(), + ModelSource: { + CopyFrom: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':bedrock:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':inference-profile/eu.anthropic.claude-3-5-sonnet-20241022-v2:0', + ], + ], + }, + }, + }); + }); +}); + +describe('CDK-Created-Application-Inference-Profile', () => { + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App(); + cdk.Aspects.of(app).add(new AwsSolutionsChecks()); + stack = new cdk.Stack(app, 'TestStack'); + }); + + test('Basic Creation with a foundation model', () => { + new bedrock.ApplicationInferenceProfile(stack, 'TestAIP', { + inferenceProfileName: 'TestAIP', + description: 'This is a test application inf profile', + modelSource: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + tags: [{ key: 'test-key', value: 'test-value' }], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::ApplicationInferenceProfile', { + InferenceProfileName: 'TestAIP', + Description: 'This is a test application inf profile', + ModelSource: { + CopyFrom: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':bedrock:', + { + Ref: 'AWS::Region', + }, + '::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0', + ], + ], + }, + }, + Tags: [ + { + Key: 'test-key', + Value: 'test-value', + }, + ], + }); + }); + + test('Basic Creation with a system defined inference profile', () => { + new bedrock.ApplicationInferenceProfile(stack, 'TestAIPSystem', { + inferenceProfileName: 'TestAIPSystem', + modelSource: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::ApplicationInferenceProfile', { + InferenceProfileName: 'TestAIPSystem', + Description: Match.absent(), + ModelSource: { + CopyFrom: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':bedrock:', + { Ref: 'AWS::Region' }, + '::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0', + ], + ], + }, + }, + }); + }); + + test('Basic Creation', () => { + new bedrock.ApplicationInferenceProfile(stack, 'TestAIPSystem', { + inferenceProfileName: 'TestAIPSystem', + modelSource: bedrock.CrossRegionInferenceProfile.fromConfig({ + model: bedrock.BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0, + geoRegion: bedrock.CrossRegionInferenceProfileRegion.EU, + }), + tags: [{ key: 'project', value: 'test' }], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::ApplicationInferenceProfile', { + InferenceProfileName: 'TestAIPSystem', + Description: Match.absent(), + ModelSource: { + CopyFrom: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':bedrock:', + { + Ref: 'AWS::Region', + }, + ':', + { + Ref: 'AWS::AccountId', + }, + ':inference-profile/eu.anthropic.claude-3-5-sonnet-20241022-v2:0', + ], + ], + }, + }, + }); + }); +}); + +describe('Imported-ApplicationInferenceProfile', () => { + let stack: cdk.Stack; + + beforeEach(() => { + const app = new cdk.App(); + cdk.Aspects.of(app).add(new AwsSolutionsChecks()); + stack = new cdk.Stack(app, 'TestStack2', { + env: { + account: '123456789012', + region: 'us-east-1', + }, + }); + }); + + test('Basic Import - from attributes', () => { + const aip = bedrock.ApplicationInferenceProfile.fromApplicationInferenceProfileAttributes(stack, 'TestAIP', { + inferenceProfileArn: 'arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/cew2pa5r8hog', + inferenceProfileIdentifier: 'arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/cew2pa5r8hog', + }); + + expect(aip.inferenceProfileArn).toBe( + 'arn:aws:bedrock:us-east-1:123456789012:application-inference-profile/cew2pa5r8hog', + ); + expect(aip.inferenceProfileId).toBe('cew2pa5r8hog'); + }); + + test('Basic Import - from cfn', () => { + const cfnapp = new CfnApplicationInferenceProfile(stack, 'mytest', { + inferenceProfileName: 'mytest', + modelSource: { + copyFrom: 'arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0', + }, + }); + + const aip2 = bedrock.ApplicationInferenceProfile.fromCfnApplicationInferenceProfile(cfnapp); + + expect(aip2.inferenceProfileArn).toBe(cfnapp.attrInferenceProfileArn); + expect(aip2.inferenceProfileId).toBe(cfnapp.attrInferenceProfileId); + }); +}); diff --git a/test/cdk-lib/bedrock/models.test.ts b/test/cdk-lib/bedrock/models.test.ts index eda508af..9286ffe1 100644 --- a/test/cdk-lib/bedrock/models.test.ts +++ b/test/cdk-lib/bedrock/models.test.ts @@ -22,7 +22,7 @@ describe('BedrockFoundationModel', () => { .toBe('amazon.titan-embed-text-v1'); }); - test('returns ARN', () => { + test('returns ARN from BedrockFoundationModel', () => { const app = new cdk.App(); cdk.Aspects.of(app).add(new AwsSolutionsChecks()); const stack = new cdk.Stack(app, 'test-stack', { @@ -31,9 +31,52 @@ describe('BedrockFoundationModel', () => { region: 'us-east-1', }, }); - const construct = new Construct(stack, 'test-construct'); - expect(BedrockFoundationModel.TITAN_EMBED_TEXT_V1.asArn(construct)) - .toBe('arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1'); + new Construct(stack, 'test-construct'); + + expect(BedrockFoundationModel.TITAN_EMBED_TEXT_V1.invokableArn).toMatch( + /^arn:\${Token\[AWS\.Partition\.\d+\]}:bedrock:\${Token\[AWS\.Region\.\d+\]}::foundation-model\/amazon\.titan-embed-text-v1$/, + ); + + }); + + test('returns ARN fromCdkFoundationModelId', () => { + const app = new cdk.App(); + cdk.Aspects.of(app).add(new AwsSolutionsChecks()); + const stack = new cdk.Stack(app, 'test-stack', { + env: { + account: '123456789012', + region: 'us-east-1', + }, + }); + new Construct(stack, 'test-construct'); + + expect(BedrockFoundationModel.fromCdkFoundationModelId( + cdk.aws_bedrock.FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_5_SONNET_20241022_V2_0, + ).invokableArn).toMatch( + /^arn:\${Token\[AWS\.Partition\.\d+\]}:bedrock:\${Token\[AWS\.Region\.\d+\]}::foundation-model\/anthropic\.claude-3-5-sonnet-20241022-v2:0$/, + ); + + }); + + test('returns ARN fromCdkFoundationModel', () => { + const app = new cdk.App(); + cdk.Aspects.of(app).add(new AwsSolutionsChecks()); + const stack = new cdk.Stack(app, 'test-stack', { + env: { + account: '123456789012', + region: 'us-east-1', + }, + }); + new Construct(stack, 'test-construct'); + + expect(BedrockFoundationModel.fromCdkFoundationModelId( + cdk.aws_bedrock.FoundationModel.fromFoundationModelId( + stack, + 'mymodel', + cdk.aws_bedrock.FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_5_SONNET_20241022_V2_0, + )).invokableArn).toMatch( + /^arn:\${Token\[AWS\.Partition\.\d+\]}:bedrock:\${Token\[AWS\.Region\.\d+\]}::foundation-model\/anthropic\.claude-3-5-sonnet-20241022-v2:0$/, + ); }); }); diff --git a/test/cdk-lib/bedrock/prompts.test.ts b/test/cdk-lib/bedrock/prompts.test.ts index 16fcae64..3b55c44f 100644 --- a/test/cdk-lib/bedrock/prompts.test.ts +++ b/test/cdk-lib/bedrock/prompts.test.ts @@ -16,6 +16,7 @@ import { expect as cdkExpect, haveResource, haveResourceLike } from '@aws-cdk/as import * as cdk from 'aws-cdk-lib'; import { aws_bedrock as cdk_bedrock } from 'aws-cdk-lib'; import * as kms from 'aws-cdk-lib/aws-kms'; +import { BedrockFoundationModel, CrossRegionInferenceProfile, CrossRegionInferenceProfileRegion } from '../../../src/cdk-lib/bedrock'; import { Prompt, PromptVariant } from '../../../src/cdk-lib/bedrock/prompts/prompt'; describe('Prompt', () => { @@ -49,13 +50,11 @@ describe('Prompt', () => { }); // -------------------------------------------------------------------------- - test('creates a Prompt with one variant', () => { + test('creates a Prompt with one variant - fromCdkFoundationModelId', () => { // GIVEN const variant1 = PromptVariant.text({ variantName: 'variant1', - model: cdk_bedrock.FoundationModel.fromFoundationModelId( - stack, - 'model1', + model: BedrockFoundationModel.fromCdkFoundationModelId( cdk_bedrock.FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_SONNET_20240229_V1_0, ), promptVariables: ['topic'], @@ -64,7 +63,6 @@ describe('Prompt', () => { temperature: 1.0, topP: 0.999, maxTokens: 2000, - topK: 250, }, }); @@ -87,7 +85,111 @@ describe('Prompt', () => { Text: { MaxTokens: 2000, Temperature: 1, - TopK: 250, + TopP: 0.999, + }, + }, + Name: 'variant1', + TemplateConfiguration: { + Text: { + InputVariables: [{ Name: 'topic' }], + Text: 'This is my first text prompt. Please summarize our conversation on {{topic}}.', + }, + }, + TemplateType: 'TEXT', + }, + ], + }), + ); + }); + + test('creates a Prompt with one variant - BedrockFoundationModel', () => { + // GIVEN + const variant1 = PromptVariant.text({ + variantName: 'variant1', + model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + promptVariables: ['topic'], + promptText: 'This is my first text prompt. Please summarize our conversation on {{topic}}.', + inferenceConfiguration: { + temperature: 1.0, + topP: 0.999, + maxTokens: 2000, + }, + }); + + new Prompt(stack, 'prompt1', { + promptName: 'prompt1', + description: 'my prompt', + defaultVariant: variant1, + variants: [variant1], + }); + // WHEN & THEN + + cdkExpect(stack).to( + haveResourceLike('AWS::Bedrock::Prompt', { + Name: 'prompt1', + Description: 'my prompt', + DefaultVariant: 'variant1', + Variants: [ + { + InferenceConfiguration: { + Text: { + MaxTokens: 2000, + Temperature: 1, + TopP: 0.999, + }, + }, + Name: 'variant1', + TemplateConfiguration: { + Text: { + InputVariables: [{ Name: 'topic' }], + Text: 'This is my first text prompt. Please summarize our conversation on {{topic}}.', + }, + }, + TemplateType: 'TEXT', + }, + ], + }), + ); + }); + + test('creates a Prompt with one variant - CRIS', () => { + // GIVEN + const cris = CrossRegionInferenceProfile.fromConfig({ + geoRegion: CrossRegionInferenceProfileRegion.US, + model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + }); + + const variant1 = PromptVariant.text({ + variantName: 'variant1', + model: cris, + promptVariables: ['topic'], + promptText: 'This is my first text prompt. Please summarize our conversation on {{topic}}.', + inferenceConfiguration: { + temperature: 1.0, + topP: 0.999, + maxTokens: 2000, + }, + }); + + new Prompt(stack, 'prompt1', { + promptName: 'prompt1', + description: 'my prompt', + defaultVariant: variant1, + variants: [variant1], + }); + // WHEN & THEN + + cdkExpect(stack).to( + haveResourceLike('AWS::Bedrock::Prompt', { + Name: 'prompt1', + Description: 'my prompt', + DefaultVariant: 'variant1', + Variants: [ + { + InferenceConfiguration: { + Text: { + MaxTokens: 2000, + Temperature: 1, TopP: 0.999, }, }, @@ -146,9 +248,7 @@ describe('Prompt', () => { const variants = [1, 2, 3, 4].map((id) => PromptVariant.text({ variantName: `variant${id}`, - model: cdk_bedrock.FoundationModel.fromFoundationModelId( - stack, - `model${id}`, + model: BedrockFoundationModel.fromCdkFoundationModelId( cdk_bedrock.FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_SONNET_20240229_V1_0, ), promptVariables: ['topic'], @@ -157,7 +257,6 @@ describe('Prompt', () => { temperature: 1.0, topP: 0.999, maxTokens: 2000, - topK: 250, }, }), ); diff --git a/test/integ/inference-profiles.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json b/test/integ/inference-profiles.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json new file mode 100644 index 00000000..4adbb7de --- /dev/null +++ b/test/integ/inference-profiles.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "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/inference-profiles.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.template.json b/test/integ/inference-profiles.integ.snapshot/ServiceTestDefaultTestDeployAssertE49B1ECE.template.json new file mode 100644 index 00000000..ad9d0fb7 --- /dev/null +++ b/test/integ/inference-profiles.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/inference-profiles.integ.snapshot/aws-cdk-bedrock-guardrails-integ-test.assets.json b/test/integ/inference-profiles.integ.snapshot/aws-cdk-bedrock-guardrails-integ-test.assets.json new file mode 100644 index 00000000..d9732249 --- /dev/null +++ b/test/integ/inference-profiles.integ.snapshot/aws-cdk-bedrock-guardrails-integ-test.assets.json @@ -0,0 +1,20 @@ +{ + "version": "38.0.1", + "files": { + "91dac6b16ba4df2701f08f5f6d386e6409d930f45d5e0c62fdcaad8a37cc69b0": { + "source": { + "path": "aws-cdk-bedrock-guardrails-integ-test.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-eu-central-1": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-eu-central-1", + "objectKey": "91dac6b16ba4df2701f08f5f6d386e6409d930f45d5e0c62fdcaad8a37cc69b0.json", + "region": "eu-central-1", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-eu-central-1" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/test/integ/inference-profiles.integ.snapshot/aws-cdk-bedrock-guardrails-integ-test.template.json b/test/integ/inference-profiles.integ.snapshot/aws-cdk-bedrock-guardrails-integ-test.template.json new file mode 100644 index 00000000..018bab7e --- /dev/null +++ b/test/integ/inference-profiles.integ.snapshot/aws-cdk-bedrock-guardrails-integ-test.template.json @@ -0,0 +1,497 @@ +{ + "Resources": { + "TestAgentsimpleRole3DF8CB4B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "bedrock.amazonaws.com" + } + }, + { + "Action": "sts:AssumeRole", + "Condition": { + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + }, + "ArnLike": { + "aws:SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:eu-central-1:", + { + "Ref": "AWS::AccountId" + }, + ":agent/*" + ] + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "bedrock.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "RoleName": "AmazonBedrockExecutionRoleForAgents_awscdkbedrgentsimpleCE146514" + } + }, + "TestAgentsimpleRoleDefaultPolicy585202B2": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "bedrock:InvokeModel", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + "::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "TestAgentsimpleRoleDefaultPolicy585202B2", + "Roles": [ + { + "Ref": "TestAgentsimpleRole3DF8CB4B" + } + ] + } + }, + "TestAgentsimpleAgentAACF0DC1": { + "Type": "AWS::Bedrock::Agent", + "Properties": { + "ActionGroups": [ + { + "ActionGroupName": "UserInputAction", + "ActionGroupState": "DISABLED", + "ParentActionGroupSignature": "AMAZON.UserInput", + "SkipResourceInUseCheckOnDelete": false + } + ], + "AgentName": "test-agent-simple", + "AgentResourceRoleArn": { + "Fn::GetAtt": [ + "TestAgentsimpleRole3DF8CB4B", + "Arn" + ] + }, + "Description": "test-description", + "FoundationModel": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + "::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + }, + "Instruction": "You are a test bot that needs to be very gentle and useful to the user" + } + }, + "TestAgentcrisRole15797E3B": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "bedrock.amazonaws.com" + } + }, + { + "Action": "sts:AssumeRole", + "Condition": { + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + }, + "ArnLike": { + "aws:SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:eu-central-1:", + { + "Ref": "AWS::AccountId" + }, + ":agent/*" + ] + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "bedrock.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "RoleName": "AmazonBedrockExecutionRoleForAgents_awscdkbedrtAgentcrisF7C16C4F" + } + }, + "TestAgentcrisRoleDefaultPolicy6C083E13": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "bedrock:InvokeModel", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:*::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + } + }, + { + "Action": [ + "bedrock:GetInferenceProfile", + "bedrock:InvokeModel" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":inference-profile/eu.anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "TestAgentcrisRoleDefaultPolicy6C083E13", + "Roles": [ + { + "Ref": "TestAgentcrisRole15797E3B" + } + ] + } + }, + "TestAgentcrisAgent395215F9": { + "Type": "AWS::Bedrock::Agent", + "Properties": { + "ActionGroups": [ + { + "ActionGroupName": "UserInputAction", + "ActionGroupState": "DISABLED", + "ParentActionGroupSignature": "AMAZON.UserInput", + "SkipResourceInUseCheckOnDelete": false + } + ], + "AgentName": "test-agent-cris", + "AgentResourceRoleArn": { + "Fn::GetAtt": [ + "TestAgentcrisRole15797E3B", + "Arn" + ] + }, + "Description": "test-description", + "FoundationModel": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":inference-profile/eu.anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + }, + "Instruction": "You are a test bot that needs to be very gentle and useful to the user" + } + }, + "TestAppProfile97C615D8": { + "Type": "AWS::Bedrock::ApplicationInferenceProfile", + "Properties": { + "InferenceProfileName": "my-app-inf-profile", + "ModelSource": { + "CopyFrom": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":inference-profile/eu.anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + } + }, + "Tags": [ + { + "Key": "projectId", + "Value": "supplyUSXRC28" + } + ] + } + }, + "TestAgentaipRole6321FCB1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "bedrock.amazonaws.com" + } + }, + { + "Action": "sts:AssumeRole", + "Condition": { + "StringEquals": { + "aws:SourceAccount": { + "Ref": "AWS::AccountId" + } + }, + "ArnLike": { + "aws:SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:eu-central-1:", + { + "Ref": "AWS::AccountId" + }, + ":agent/*" + ] + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "bedrock.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "RoleName": "AmazonBedrockExecutionRoleForAgents_awscdkbedrstAgentaipB2FE765E" + } + }, + "TestAgentaipRoleDefaultPolicyD4F0F0D5": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "bedrock:InvokeModel", + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:*::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + } + }, + { + "Action": [ + "bedrock:GetInferenceProfile", + "bedrock:InvokeModel" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":inference-profile/eu.anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + } + }, + { + "Action": [ + "bedrock:GetInferenceProfile", + "bedrock:InvokeModel" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TestAppProfile97C615D8", + "InferenceProfileArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "TestAgentaipRoleDefaultPolicyD4F0F0D5", + "Roles": [ + { + "Ref": "TestAgentaipRole6321FCB1" + } + ] + } + }, + "TestAgentaipAgent6B2B1F92": { + "Type": "AWS::Bedrock::Agent", + "Properties": { + "ActionGroups": [ + { + "ActionGroupName": "UserInputAction", + "ActionGroupState": "DISABLED", + "ParentActionGroupSignature": "AMAZON.UserInput", + "SkipResourceInUseCheckOnDelete": false + } + ], + "AgentName": "test-agent-aip", + "AgentResourceRoleArn": { + "Fn::GetAtt": [ + "TestAgentaipRole6321FCB1", + "Arn" + ] + }, + "Description": "test-description", + "FoundationModel": { + "Fn::GetAtt": [ + "TestAppProfile97C615D8", + "InferenceProfileArn" + ] + }, + "Instruction": "You are a test bot that needs to be very gentle and useful to the user" + } + } + }, + "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/inference-profiles.integ.snapshot/integ.json b/test/integ/inference-profiles.integ.snapshot/integ.json new file mode 100644 index 00000000..48d7dfb3 --- /dev/null +++ b/test/integ/inference-profiles.integ.snapshot/integ.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "testCases": { + "ServiceTest/DefaultTest": { + "stacks": [ + "aws-cdk-bedrock-guardrails-integ-test" + ], + "cdkCommandOptions": { + "destroy": { + "args": { + "force": true + } + } + }, + "assertionStack": "ServiceTest/DefaultTest/DeployAssert", + "assertionStackName": "ServiceTestDefaultTestDeployAssertE49B1ECE" + } + } +} \ No newline at end of file diff --git a/test/integ/inference-profiles.integ.ts b/test/integ/inference-profiles.integ.ts new file mode 100644 index 00000000..5962bee5 --- /dev/null +++ b/test/integ/inference-profiles.integ.ts @@ -0,0 +1,72 @@ +/** + * 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 { + Agent, + ApplicationInferenceProfile, + BedrockFoundationModel, + CrossRegionInferenceProfile, + CrossRegionInferenceProfileRegion, +} from '../../src/cdk-lib/bedrock'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-bedrock-guardrails-integ-test', { + env: { + region: 'eu-central-1', + }, +}); +new Agent(stack, 'TestAgent-simple', { + instruction: 'You are a test bot that needs to be very gentle and useful to the user', + foundationModel: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + name: 'test-agent-simple', + description: 'test-description', +}); + +new Agent(stack, 'TestAgent-cris', { + instruction: 'You are a test bot that needs to be very gentle and useful to the user', + foundationModel: CrossRegionInferenceProfile.fromConfig({ + geoRegion: CrossRegionInferenceProfileRegion.EU, + model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + }), + name: 'test-agent-cris', + description: 'test-description', +}); + +const aip = new ApplicationInferenceProfile(stack, 'TestAppProfile', { + inferenceProfileName: 'my-app-inf-profile', + tags: [{ key: 'projectId', value: 'supplyUSXRC28' }], + modelSource: CrossRegionInferenceProfile.fromConfig({ + geoRegion: CrossRegionInferenceProfileRegion.EU, + model: BedrockFoundationModel.ANTHROPIC_CLAUDE_SONNET_V1_0, + }), +}); + +new Agent(stack, 'TestAgent-aip', { + instruction: 'You are a test bot that needs to be very gentle and useful to the user', + foundationModel: aip, + name: 'test-agent-aip', + description: 'test-description', +}); +new integ.IntegTest(app, 'ServiceTest', { + testCases: [stack], + cdkCommandOptions: { + destroy: { + args: { + force: true, + }, + }, + }, +}); + +app.synth(); diff --git a/yarn.lock b/yarn.lock index 5a42b54c..b5b45c79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,12 +17,12 @@ dependencies: "@aws-cdk/cloudformation-diff" "2.68.0" -"@aws-cdk/asset-awscli-v1@^2.2.202": - version "2.2.212" - resolved "https://registry.yarnpkg.com/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.212.tgz#dd93cdd383d9b97a8dfeac32c08d9d68488cda38" - integrity sha512-7WqbnWUkBBcAzEdfRrpz6sCOheUPf4JEUdGvzJ4EEufXeT7v7nRbRmTvUBbQ+OQlCv9UrVj9XuFxKPjkvneGMQ== +"@aws-cdk/asset-awscli-v1@^2.2.208": + version "2.2.211" + resolved "https://registry.yarnpkg.com/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.211.tgz#e33c1bab8e45ea3e4100fff1a0f4430a3ba2164d" + integrity sha512-56G1FYTiKyec3bEfEI/5UcU0XPnaGUlaDDH7OYClyvqss0HlnmoSulHK2gwai2PGAD1Nk+scPrdfH/MVAkSKuw== -"@aws-cdk/asset-kubectl-v20@^2.1.2": +"@aws-cdk/asset-kubectl-v20@^2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.3.tgz#80e09004be173995e91614e34d947da11dd9ff4d" integrity sha512-cDG1w3ieM6eOT9mTefRuTypk95+oyD7P5X/wRltwmYxU7nZc3+076YEVS6vrjDKr3ADYbfn0lDKpfB1FBtO9CQ== @@ -40,7 +40,7 @@ fs-extra "^9.1.0" md5 "^2.3.0" -"@aws-cdk/cloud-assembly-schema@^38.0.0": +"@aws-cdk/cloud-assembly-schema@^38.0.1": version "38.0.1" resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-38.0.1.tgz#cdf4684ae8778459e039cd44082ea644a3504ca9" integrity sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w== @@ -60,10 +60,10 @@ string-width "^4.2.3" table "^6.8.1" -"@aws-cdk/integ-tests-alpha@2.162.1-alpha.0": - version "2.162.1-alpha.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.162.1-alpha.0.tgz#576d1d8a0c88f25b683e319ec3e3b7ce94bf08c3" - integrity sha512-Y004DY4MEO/HtHIYvsGhS0T29RGiBjIguN37casoh8rosTXKVDDUKBBiXsF6d11qEAoQJfVKrRnHpj9LYcNWtQ== +"@aws-cdk/integ-tests-alpha@2.166.0-alpha.0": + version "2.166.0-alpha.0" + resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.166.0-alpha.0.tgz#fc82a90c422cd0ff90ee4b3f72026b6eb900cd1b" + integrity sha512-ksM64XQP0FzzGxmVFQQDF8JIJKJpcfUoFWTvRghDMDNq8IBi/KsP4/gXpHDyl4jtS58EPOMBpsy0SRCFyOCVvw== "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": version "7.26.2" @@ -1428,15 +1428,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -aws-cdk-lib@2.162.1: - version "2.162.1" - resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.162.1.tgz#06454f1302a345dbd2a1866b0f170adbc93b1664" - integrity sha512-XiZLVE5ISNajNNmLye8l5w4EGqm6/d8C8shw63QwxaRVYdHl5e+EAaUEmZJpWc4sYtY/sS+GHOfhoKFLjha2rg== +aws-cdk-lib@2.166.0: + version "2.166.0" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.166.0.tgz#279343451cc9391d52d77121e2a3feb2c756e3be" + integrity sha512-FAsIz/CpczbMrcShgvTWNp3kcGN6IDojJWNLqHioTRsTekcyN3OPmKvQJXUNWL0fnhTd8biFXC2esg6kM19xZw== dependencies: - "@aws-cdk/asset-awscli-v1" "^2.2.202" - "@aws-cdk/asset-kubectl-v20" "^2.1.2" + "@aws-cdk/asset-awscli-v1" "^2.2.208" + "@aws-cdk/asset-kubectl-v20" "^2.1.3" "@aws-cdk/asset-node-proxy-agent-v6" "^2.1.0" - "@aws-cdk/cloud-assembly-schema" "^38.0.0" + "@aws-cdk/cloud-assembly-schema" "^38.0.1" "@balena/dockerignore" "^1.0.2" case "1.6.3" fs-extra "^11.2.0"