diff --git a/.projen/deps.json b/.projen/deps.json index 3f8d7c3b..4cabc13b 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -6,7 +6,7 @@ }, { "name": "@aws-cdk/integ-tests-alpha", - "version": "^2.154.1-alpha.0", + "version": "^2.155.0-alpha.0", "type": "build" }, { @@ -137,7 +137,7 @@ }, { "name": "aws-cdk-lib", - "version": "^2.154.1", + "version": "^2.155.0", "type": "peer" }, { diff --git a/.projenrc.ts b/.projenrc.ts index 3bfe4d8a..be699d8a 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.154.1'; +const CDK_VERSION: string = '2.155.0'; function camelCaseIt(input: string): string { // Hypens and dashes to spaces and then CamelCase... diff --git a/package.json b/package.json index bc4d6544..992bdb18 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@aws-cdk/assert": "^2.68.0", - "@aws-cdk/integ-tests-alpha": "^2.154.1-alpha.0", + "@aws-cdk/integ-tests-alpha": "^2.155.0-alpha.0", "@commitlint/config-conventional": "^18.6.3", "@mrgrain/jsii-struct-builder": "^0.7.42", "@types/jest": "^29.5.12", @@ -57,7 +57,7 @@ "@typescript-eslint/eslint-plugin": "^7", "@typescript-eslint/parser": "^7", "aws-cdk": "^2", - "aws-cdk-lib": "2.154.1", + "aws-cdk-lib": "2.155.0", "aws-sdk-mock": "^5.9.0", "commitlint": "^18.6.1", "constructs": "10.3.0", @@ -82,7 +82,7 @@ "typescript": "^5.5.4" }, "peerDependencies": { - "aws-cdk-lib": "^2.154.1", + "aws-cdk-lib": "^2.155.0", "constructs": "^10.3.0" }, "dependencies": { diff --git a/src/cdk-lib/bedrock/data-sources/base-data-source.ts b/src/cdk-lib/bedrock/data-sources/base-data-source.ts index 7124d6eb..6f25b353 100644 --- a/src/cdk-lib/bedrock/data-sources/base-data-source.ts +++ b/src/cdk-lib/bedrock/data-sources/base-data-source.ts @@ -21,41 +21,58 @@ import { CustomTransformation } from './custom-transformation'; import { ParsingStategy } from './parsing'; +/** + * Specifies the policy for handling data when a data source resource is deleted. + * This policy affects the vector embeddings created from the data source. + */ export enum DataDeletionPolicy { /** - * Deletes the data source and its associated resources. + * Deletes all vector embeddings derived from the data source upon deletion + * of a data source resource. */ DELETE = 'DELETE', + /** - * Retains the data source and its associated resources. + * Retains all vector embeddings derived from the data source even after + * deletion of a data source resource. */ RETAIN = 'RETAIN' } + + +/** + * Represents the types of data sources that can be associated to an Knowledge Base. + */ export enum DataSourceType { /** - * Connects to an Amazon S3 Bucket. + * Amazon S3 Bucket data source. */ S3 = 'S3', + /** - * Connects to a Confluence Cloud Instance. + * Confluence Cloud Instance data source. */ CONFLUENCE = 'CONFLUENCE', + /** - * Connects to a Salesforce instance. + * Salesforce instance data source. */ SALESFORCE = 'SALESFORCE', + /** - * Connects to a Microsoft SharePoint instance. + * Microsoft SharePoint instance data source. */ SHAREPOINT = 'SHAREPOINT', + /** - * Leverages a Web page crawler that extracts content from public web pages - * which you are authorized to crawl. + * Web Crawler data source. + * Extracts content from authorized public web pages using a crawler. */ WEB_CRAWLER = 'WEB' } + /** * Specifies interface for resources created with CDK or imported into CDK. */ @@ -91,24 +108,28 @@ export interface DataSourceAssociationProps { * @default - A new name will be generated. */ readonly dataSourceName?: string; + /** * A description of the data source. * * @default - No description is provided. */ readonly description?: string; + /** * The KMS key to use to encrypt the data source. * * @default - Service owned and managed key. */ readonly kmsKey?: kms.IKey; + /** * The data deletion policy to apply to the data source. * - * @default DataDeletionPolicy.DELETE + * @default - Sets the data deletion policy to the default of the data source type. */ readonly dataDeletionPolicy?: DataDeletionPolicy; + /** * The chunking stategy to use for splitting your documents or content. * The chunks are then converted to embeddings and written to the vector @@ -117,12 +138,14 @@ export interface DataSourceAssociationProps { * @default ChunkingStrategy.DEFAULT */ readonly chunkingStrategy?: ChunkingStrategy; + /** * The parsing strategy to use. * * @default - No Parsing Stategy is used. */ readonly parsingStrategy?: ParsingStategy; + /** * The custom transformation strategy to use. * @@ -153,8 +176,30 @@ export abstract class DataSourceNew extends DataSourceBase { * The knowledge base associated with the data source. */ public abstract readonly knowledgeBase: KnowledgeBase; - - // Common methods only for new data sources go here + /** + * The KMS key to use to encrypt the data source. + */ + public abstract readonly kmsKey?: kms.IKey; + + // ------------------------------------------------------ + // Common methods for ALL NEW data sources + // ------------------------------------------------------ + public formatCfnCommonProps(props: DataSourceAssociationProps) { + return { + dataDeletionPolicy: props.dataDeletionPolicy, + description: props.description, + name: this.dataSourceName, + serverSideEncryptionConfiguration: props.kmsKey ? { + kmsKeyArn: props.kmsKey.keyArn, + } : undefined, + vectorIngestionConfiguration: (props.chunkingStrategy || props.parsingStrategy || props.customTransformation) ? { + chunkingConfiguration: props.chunkingStrategy?.configuration, + parsingConfiguration: props.parsingStrategy?.configuration, + customTransformationConfiguration: props.customTransformation?.configuration, + } : undefined, + + } + } } diff --git a/src/cdk-lib/bedrock/data-sources/confluence-data-source.ts b/src/cdk-lib/bedrock/data-sources/confluence-data-source.ts index 79dfdd2a..ac326f04 100644 --- a/src/cdk-lib/bedrock/data-sources/confluence-data-source.ts +++ b/src/cdk-lib/bedrock/data-sources/confluence-data-source.ts @@ -16,46 +16,84 @@ import { ISecret } from 'aws-cdk-lib/aws-secretsmanager'; import { Construct } from 'constructs'; import { KnowledgeBase } from './../knowledge-base'; -import { DataDeletionPolicy, DataSourceAssociationProps, DataSourceNew, DataSourceType } from './base-data-source'; +import { DataSourceAssociationProps, DataSourceNew, DataSourceType } from './base-data-source'; import { generatePhysicalNameV2 } from '../../../common/helpers/utils'; - +/** + * The different authentication types available to connect to your Confluence instance. + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/confluence-data-source-connector.html#configuration-confluence-connector + */ export enum ConfluenceDataSourceAuthType { /** * Your secret authentication credentials in AWS Secrets Manager should include: - * `confluenceAppKey`, `confluenceAppSecret`, `confluenceAccessToken`, `confluenceRefreshToken`. + * - `confluenceAppKey` + * - `confluenceAppSecret` + * - `confluenceAccessToken` + * - `confluenceRefreshToken` */ OAUTH2_CLIENT_CREDENTIALS = 'OAUTH2_CLIENT_CREDENTIALS', /** * Your secret authentication credentials in AWS Secrets Manager should include: - * `username` and `password` (API token). + * - `username` (email of admin account) + * - `password` (API token) */ - BASIC = 'BASIC' + BASIC = 'BASIC', } +/** + * Represents the different types of content objects in Confluence that can be + * crawled by the data source. + */ export enum ConfluenceObjectType { SPACE = 'Space', PAGE = 'Page', BLOG = 'Blog', + COMMENT = 'Comment', ATTACHMENT = 'Attachment', - COMMENT = 'Comment' } +/** + * Defines filters for crawling Confluence content. + * These filters allow you to include or exclude specific content based on object types and patterns. + * + * - For Spaces: Use the unique space key + * - For Pages: Use the main page title + * - For Blogs: Use the main blog title + * - For Comments: Use "Re: Page/Blog Title" + * - For Attachments: Use the filename with extension + * @remarks + * - You can specify inclusion and exclusion patterns using regular expressions. + * - If both inclusion and exclusion patterns match a document, the exclusion takes precedence. + * + * @example + * To exclude PDF files with "private" in the filename: + * ```ts + * { + * objectType: ConfluenceObjectType.ATTACHMENT, + * excludePatterns: [".*private.*\\.pdf"] + * } + * ``` + */ export interface ConfluenceCrawlingFilters { /** - * Include object types. + * The type of Confluence object to apply the filters to. */ readonly objectType: ConfluenceObjectType; + /** - * Include patterns. + * Regular expression patterns to include content. + * If specified, only content matching these patterns will be crawled. */ readonly includePatterns?: string[]; + /** - * Exclude paths. + * Regular expression patterns to exclude content. + * Content matching these patterns will not be crawled, even if it matches an include pattern. */ readonly excludePatterns?: string[]; } + /** * Interface to add a new data source to an existing KB. */ @@ -64,7 +102,7 @@ export interface ConfluenceDataSourceAssociationProps extends DataSourceAssociat * The Confluence host URL or instance URL. * @example https://example.atlassian.net */ - readonly endpoint: string; + readonly confluenceUrl: string; /** * The AWS Secrets Manager secret that stores your authentication credentials * for your Confluence instance URL. Secret must start with "AmazonBedrock-". @@ -100,6 +138,9 @@ export interface ConfluenceDataSourceProps extends ConfluenceDataSourceAssociati * @see https://docs.aws.amazon.com/bedrock/latest/userguide/confluence-data-source-connector.html */ export class ConfluenceDataSource extends DataSourceNew { + // ------------------------------------------------------ + // Common attributes for all new data sources + // ------------------------------------------------------ /** * The unique identifier of the data source. * @example 'JHUEVXUZMU' @@ -117,18 +158,24 @@ export class ConfluenceDataSource extends DataSourceNew { * The knowledge base associated with the data source. */ public readonly knowledgeBase: KnowledgeBase; + /** + * The KMS key to use to encrypt the data source. + */ + public readonly kmsKey?: IKey; + // ------------------------------------------------------ + // Unique to this class + // ------------------------------------------------------ /** * The Confluence host URL or instance URL. */ - public readonly endpoint: string; + public readonly confluenceUrl: string; /** * The AWS Secrets Manager secret that stores your authentication credentials. */ public readonly authSecret: ISecret; - /** - * The KMS key to use to encrypt the data source. - */ - public readonly kmsKey?: IKey; + // ------------------------------------------------------ + // Unique to this class + // ------------------------------------------------------ /** * The Data Source cfn resource. */ @@ -137,26 +184,28 @@ export class ConfluenceDataSource extends DataSourceNew { constructor(scope: Construct, id: string, props: ConfluenceDataSourceProps) { super(scope, id); - // Assign attributes + // Assign common attributes this.knowledgeBase = props.knowledgeBase; this.dataSourceType = DataSourceType.CONFLUENCE; - this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'sfdc-datasource', { maxLength: 40, lower: true, separator: '-' });; - this.endpoint = props.endpoint; - this.authSecret = props.authSecret; + this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'confluence-ds', { maxLength: 40, lower: true, separator: '-' }); this.kmsKey = props.kmsKey; + // Assign unique attributes + this.confluenceUrl = props.confluenceUrl; + this.authSecret = props.authSecret; - // L1 instantiation + // ------------------------------------------------------ + // L1 Instantiation + // ------------------------------------------------------ this.__resource = new CfnDataSource(this, 'DataSource', { + ...this.formatCfnCommonProps(props), knowledgeBaseId: this.knowledgeBase.knowledgeBaseId, - name: this.dataSourceName, - dataDeletionPolicy: props.dataDeletionPolicy ?? DataDeletionPolicy.DELETE, dataSourceConfiguration: { type: this.dataSourceType, confluenceConfiguration: { sourceConfiguration: { authType: props.authType ?? ConfluenceDataSourceAuthType.OAUTH2_CLIENT_CREDENTIALS, credentialsSecretArn: this.authSecret.secretArn, - hostUrl: this.endpoint, + hostUrl: this.confluenceUrl, hostType: 'SAAS', }, crawlerConfiguration: @@ -173,20 +222,10 @@ export class ConfluenceDataSource extends DataSourceNew { }, }) : undefined, }, - }, - vectorIngestionConfiguration: (props.chunkingStrategy || props.parsingStrategy || props.customTransformation) ? { - chunkingConfiguration: props.chunkingStrategy?.configuration, - parsingConfiguration: props.parsingStrategy?.configuration, - customTransformationConfiguration: props.customTransformation?.configuration, - } : undefined, - serverSideEncryptionConfiguration: this.kmsKey ? { - kmsKeyArn: this.kmsKey.keyArn, - } : undefined, - + } }); this.dataSourceId = this.__resource.attrDataSourceId; - } } \ No newline at end of file diff --git a/src/cdk-lib/bedrock/data-sources/s3-data-source.ts b/src/cdk-lib/bedrock/data-sources/s3-data-source.ts index 53081a3c..ab7f4ebb 100644 --- a/src/cdk-lib/bedrock/data-sources/s3-data-source.ts +++ b/src/cdk-lib/bedrock/data-sources/s3-data-source.ts @@ -90,7 +90,7 @@ export class S3DataSource extends DataSourceNew { // Assign attributes this.knowledgeBase = props.knowledgeBase; this.dataSourceType = DataSourceType.S3; - this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 's3-datasource', { maxLength: 40, lower: true, separator: '-' });; + this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 's3-ds', { maxLength: 40, lower: true, separator: '-' });; this.bucket = props.bucket; this.kmsKey = props.kmsKey; diff --git a/src/cdk-lib/bedrock/data-sources/salesforce-data-source.ts b/src/cdk-lib/bedrock/data-sources/salesforce-data-source.ts index cd6031a3..b7d2cc08 100644 --- a/src/cdk-lib/bedrock/data-sources/salesforce-data-source.ts +++ b/src/cdk-lib/bedrock/data-sources/salesforce-data-source.ts @@ -145,7 +145,7 @@ export class SalesforceDataSource extends DataSourceNew { // Assign attributes this.knowledgeBase = props.knowledgeBase; this.dataSourceType = DataSourceType.SALESFORCE; - this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'sfdc-datasource', { maxLength: 40, lower: true, separator: '-' });; + this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'sfdc-ds', { maxLength: 40, lower: true, separator: '-' });; this.endpoint = props.endpoint; this.authSecret = props.authSecret; this.kmsKey = props.kmsKey; diff --git a/src/cdk-lib/bedrock/data-sources/sharepoint-data-source.ts b/src/cdk-lib/bedrock/data-sources/sharepoint-data-source.ts index fca5e8e6..0bac4d06 100644 --- a/src/cdk-lib/bedrock/data-sources/sharepoint-data-source.ts +++ b/src/cdk-lib/bedrock/data-sources/sharepoint-data-source.ts @@ -140,7 +140,7 @@ export class SharepointDataSource extends DataSourceNew { // Assign attributes this.knowledgeBase = props.knowledgeBase; this.dataSourceType = DataSourceType.SHAREPOINT; - this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'sfdc-datasource', { maxLength: 40, lower: true, separator: '-' });; + this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'sharepoint-ds', { maxLength: 40, lower: true, separator: '-' });; this.siteUrls = props.siteUrls; this.domain = props.domain; this.authSecret = props.authSecret; diff --git a/src/cdk-lib/bedrock/data-sources/web-crawler-data-source.ts b/src/cdk-lib/bedrock/data-sources/web-crawler-data-source.ts index 31392347..97d88a45 100644 --- a/src/cdk-lib/bedrock/data-sources/web-crawler-data-source.ts +++ b/src/cdk-lib/bedrock/data-sources/web-crawler-data-source.ts @@ -124,7 +124,7 @@ export class WebCrawlerDataSource extends DataSourceNew { // Assign attributes this.knowledgeBase = props.knowledgeBase; this.dataSourceType = DataSourceType.WEB_CRAWLER; - this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'crawler-datasource', { maxLength: 40, lower: true, separator: '-' });; + this.dataSourceName = props.dataSourceName ?? generatePhysicalNameV2(this, 'crawler-ds', { maxLength: 40, lower: true, separator: '-' });; this.kmsKey = props.kmsKey; this.crawlingRate = props.crawlingRate ?? 300; diff --git a/src/cdk-lib/bedrock/knowledge-base.ts b/src/cdk-lib/bedrock/knowledge-base.ts index 2b7369b3..607e3854 100644 --- a/src/cdk-lib/bedrock/knowledge-base.ts +++ b/src/cdk-lib/bedrock/knowledge-base.ts @@ -666,7 +666,7 @@ export class KnowledgeBase extends Construct { }); } public addConfluenceDataSource(props: ConfluenceDataSourceAssociationProps): ConfluenceDataSource { - const url = new URL(props.endpoint); + const url = new URL(props.confluenceUrl); return new ConfluenceDataSource(this, `cf-${url.hostname.replace('.', '-')}`, { knowledgeBase: this, ...props, }); diff --git a/src/cdk-lib/opensearch-vectorindex/vector-index.ts b/src/cdk-lib/opensearch-vectorindex/vector-index.ts index 1da64e71..6605e119 100644 --- a/src/cdk-lib/opensearch-vectorindex/vector-index.ts +++ b/src/cdk-lib/opensearch-vectorindex/vector-index.ts @@ -237,13 +237,12 @@ export class VectorIndex extends cdk.Resource { const vectorIndex = new cdk.CustomResource(this, 'VectorIndex', { serviceToken: crProvider.serviceToken, properties: { - Endpoint: `${props.collection.collectionId}.${ - cdk.Stack.of(this).region + Endpoint: `${props.collection.collectionId}.${cdk.Stack.of(this).region }.aoss.amazonaws.com`, IndexName: props.indexName, VectorField: props.vectorField, Dimensions: props.vectorDimensions, - MetadataManagement: props.mappings.map((m) => { + MetadataManagement: props.mappings.map((m: MetadataManagementFieldProps) => { return { MappingField: m.mappingField, DataType: m.dataType, diff --git a/test/cdk-lib/bedrock/data-sources/crawler-data-source.test.ts b/test/cdk-lib/bedrock/data-sources/crawler-data-source.test.ts new file mode 100644 index 00000000..4c3c1865 --- /dev/null +++ b/test/cdk-lib/bedrock/data-sources/crawler-data-source.test.ts @@ -0,0 +1,97 @@ +/** + * 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 { App, Stack } from 'aws-cdk-lib'; +import { Match, Template } from 'aws-cdk-lib/assertions'; +import { IKey, Key } from 'aws-cdk-lib/aws-kms'; +import { Secret } from 'aws-cdk-lib/aws-secretsmanager'; +import * as bedrock from '../../../../src/cdk-lib/bedrock'; + + +describe('S3 Data Source', () => { + let stack: Stack; + let kb: bedrock.KnowledgeBase; + let key: IKey; + + beforeEach(() => { + const app = new App(); + stack = new Stack(app, 'TestStack'); + kb = new bedrock.KnowledgeBase(stack, 'KB', { + embeddingsModel: bedrock.BedrockFoundationModel.TITAN_EMBED_TEXT_V1, + }); + const sampleKeyArn = 'arn:aws:kms:eu-central-1:123456789012:key/06484191-7d55-49fb-9be7-0baaf7fe8418'; + key = Key.fromKeyArn(stack, 'TestKey', sampleKeyArn); + + }); + + test('Basic Web Crawler', () => { + new bedrock.WebCrawlerDataSource(stack, 'TestDataSource', { + knowledgeBase: kb, + dataSourceName: 'TestDataSource', + sourceUrls: ['https://example.com'], + crawlingScope: bedrock.CrawlingScope.SUBDOMAINS, + kmsKey: key, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { + Name: 'TestDataSource', + ServerSideEncryptionConfiguration: { + KmsKeyArn: 'arn:aws:kms:eu-central-1:123456789012:key/06484191-7d55-49fb-9be7-0baaf7fe8418', + }, + DataSourceConfiguration: { + Type: 'WEB', + WebConfiguration: { + CrawlerConfiguration: { + CrawlerLimits: { + RateLimit: "300" + }, + Scope: 'SUBDOMAINS', + ExclusionFilters: Match.absent(), + InclusionFilters: Match.absent(), + }, + SourceConfiguration: { + UrlConfiguration: { + SeedUrls: [{ + Url: 'https://example.com', + }], + }, + }, + }, + }, + }); + }); + + test('Basic Confluence Setup', () => { + new bedrock.ConfluenceDataSource(stack, 'TestDataSource', { + knowledgeBase: kb, + dataSourceName: 'TestDataSource', + confluenceUrl: 'https://example.atlassian.net', + authSecret: new Secret(stack, 'TestSecret'), + kmsKey: key, + }); + + console.log(Template.fromStack(stack)); + Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { + Name: 'TestDataSource', + ServerSideEncryptionConfiguration: { + KmsKeyArn: 'arn:aws:kms:eu-central-1:123456789012:key/06484191-7d55-49fb-9be7-0baaf7fe8418', + }, + DataSourceConfiguration: { + Type: 'CONFLUENCE', + ConfluenceConfiguration: Match.anyValue(), + + }, + }); + + }); +}); \ No newline at end of file diff --git a/test/cdk-lib/bedrock/s3-data-source.test.ts b/test/cdk-lib/bedrock/data-sources/s3-data-sorce.ts similarity index 93% rename from test/cdk-lib/bedrock/s3-data-source.test.ts rename to test/cdk-lib/bedrock/data-sources/s3-data-sorce.ts index 1ce792a1..9cc92c54 100644 --- a/test/cdk-lib/bedrock/s3-data-source.test.ts +++ b/test/cdk-lib/bedrock/data-sources/s3-data-sorce.ts @@ -16,21 +16,8 @@ import { Template } from 'aws-cdk-lib/assertions'; import { FoundationModel, FoundationModelIdentifier } from 'aws-cdk-lib/aws-bedrock'; import * as s3 from 'aws-cdk-lib/aws-s3'; import { AwsSolutionsChecks } from 'cdk-nag'; -import * as bedrock from '../../../src/cdk-lib/bedrock'; - - -// mock lambda.Code.fromDockerBuild() -jest.mock('aws-cdk-lib/aws-lambda', () => { - const actualLambda = jest.requireActual('aws-cdk-lib/aws-lambda'); - return { - ...actualLambda, - Code: { - ...actualLambda.Code, - fromDockerBuild: jest.fn(() => actualLambda.Code.fromInline('mockCode')), - fromAsset: jest.fn(() => actualLambda.Code.fromInline('mockCode')), - }, - }; -}); +import * as bedrock from '../../../../src/cdk-lib/bedrock'; + describe('S3 Data Source', () => { let stack: cdk.Stack; @@ -43,7 +30,7 @@ describe('S3 Data Source', () => { stack = new cdk.Stack(app, 'TestStack'); bucket = new s3.Bucket(stack, 'TestBucket'); kb = new bedrock.KnowledgeBase(stack, 'KB', { - embeddingsModel: bedrock.BedrockFoundationModel.TITAN_EMBED_TEXT_V1, + embeddingsModel: bedrock.BedrockFoundationModel.TITAN_EMBED_TEXT_V2_1024, }); }); @@ -56,7 +43,6 @@ describe('S3 Data Source', () => { }); Template.fromStack(stack).hasResourceProperties('AWS::Bedrock::DataSource', { - VectorIngestionConfiguration: { ChunkingConfiguration: { diff --git a/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/cdk.out b/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/cdk.out new file mode 100644 index 00000000..4efaa16f --- /dev/null +++ b/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.24"} \ No newline at end of file diff --git a/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/manifest.json b/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/manifest.json new file mode 100644 index 00000000..6197ac07 --- /dev/null +++ b/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/manifest.json @@ -0,0 +1,125 @@ +{ + "version": "36.0.24", + "artifacts": { + "aws-cdk-bedrock-prompts-integ-test.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-bedrock-prompts-integ-test.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-bedrock-prompts-integ-test": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-bedrock-prompts-integ-test.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a62e4ef5218c29945707c2451e0d55ee6bc68d08ffb4082a738b0aa950adfa5c.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-bedrock-prompts-integ-test.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-bedrock-prompts-integ-test.assets" + ], + "metadata": { + "/aws-cdk-bedrock-prompts-integ-test/cmk/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "cmk01DE03DA" + } + ], + "/aws-cdk-bedrock-prompts-integ-test/prompt1/Prompt": [ + { + "type": "aws:cdk:logicalId", + "data": "prompt1Prompt7E73129C" + } + ], + "/aws-cdk-bedrock-prompts-integ-test/prompt1/PromptVersion-my first version": [ + { + "type": "aws:cdk:logicalId", + "data": "prompt1PromptVersionmyfirstversionCC6C6F93" + } + ], + "/aws-cdk-bedrock-prompts-integ-test/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-bedrock-prompts-integ-test/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-bedrock-prompts-integ-test" + }, + "ServiceTestDefaultTestDeployAssertE49B1ECE.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ServiceTestDefaultTestDeployAssertE49B1ECE.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ServiceTestDefaultTestDeployAssertE49B1ECE": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ServiceTestDefaultTestDeployAssertE49B1ECE.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ServiceTestDefaultTestDeployAssertE49B1ECE.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ServiceTestDefaultTestDeployAssertE49B1ECE.assets" + ], + "metadata": { + "/ServiceTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ServiceTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ServiceTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/tree.json b/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/tree.json new file mode 100644 index 00000000..19ef1889 --- /dev/null +++ b/test/cdk-lib/bedrock/integ-tests/prompts.integ.snapshot/tree.json @@ -0,0 +1,282 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-bedrock-prompts-integ-test": { + "id": "aws-cdk-bedrock-prompts-integ-test", + "path": "aws-cdk-bedrock-prompts-integ-test", + "children": { + "cmk": { + "id": "cmk", + "path": "aws-cdk-bedrock-prompts-integ-test/cmk", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-bedrock-prompts-integ-test/cmk/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.CfnKey", + "version": "2.154.1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kms.Key", + "version": "2.154.1" + } + }, + "prompt1": { + "id": "prompt1", + "path": "aws-cdk-bedrock-prompts-integ-test/prompt1", + "children": { + "Prompt": { + "id": "Prompt", + "path": "aws-cdk-bedrock-prompts-integ-test/prompt1/Prompt", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Bedrock::Prompt", + "aws:cdk:cloudformation:props": { + "customerEncryptionKeyArn": { + "Fn::GetAtt": [ + "cmk01DE03DA", + "Arn" + ] + }, + "defaultVariant": "variant1", + "description": "my first prompt", + "name": "prompt1", + "variants": [ + { + "name": "variant1", + "templateType": "TEXT", + "modelId": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + "::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + }, + "inferenceConfiguration": { + "text": { + "temperature": 1, + "topP": 0.999, + "maxTokens": 2000, + "topK": 250 + } + }, + "templateConfiguration": { + "text": { + "inputVariables": [ + { + "name": "topic" + } + ], + "text": "This is my first text prompt. Please summarize our conversation on: {{topic}}." + } + } + }, + { + "name": "variant2", + "templateType": "TEXT", + "modelId": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":bedrock:", + { + "Ref": "AWS::Region" + }, + "::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" + ] + ] + }, + "inferenceConfiguration": { + "text": { + "temperature": 0.5, + "topP": 0.999, + "maxTokens": 2000, + "topK": 250 + } + }, + "templateConfiguration": { + "text": { + "inputVariables": [ + { + "name": "topic" + } + ], + "text": "This is my second text prompt. Please summarize our conversation on: {{topic}}." + } + } + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_bedrock.CfnPrompt", + "version": "2.154.1" + } + }, + "PromptVersion-my first version": { + "id": "PromptVersion-my first version", + "path": "aws-cdk-bedrock-prompts-integ-test/prompt1/PromptVersion-my first version", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Bedrock::PromptVersion", + "aws:cdk:cloudformation:props": { + "description": "my first version", + "promptArn": { + "Fn::GetAtt": [ + "prompt1Prompt7E73129C", + "Arn" + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_bedrock.CfnPromptVersion", + "version": "2.154.1" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-bedrock-prompts-integ-test/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.154.1" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-bedrock-prompts-integ-test/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "2.154.1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "2.154.1" + } + }, + "ServiceTest": { + "id": "ServiceTest", + "path": "ServiceTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "ServiceTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "ServiceTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "ServiceTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ServiceTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "2.154.1" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ServiceTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "2.154.1" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "2.154.1" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "2.154.1-alpha.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "2.154.1-alpha.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "2.154.1" + } + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index fe77c19f..5fa56358 100644 --- a/yarn.lock +++ b/yarn.lock @@ -60,10 +60,10 @@ string-width "^4.2.3" table "^6.8.1" -"@aws-cdk/integ-tests-alpha@^2.154.1-alpha.0": - version "2.154.1-alpha.0" - resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.154.1-alpha.0.tgz#d98e60ceb7fa26e9404a3b208a02f8ee89c4be2e" - integrity sha512-jw1jlTKWhxRlgrtCIjZf2n+B7dAwv6BFRJWi9S6/ijo/GzysnX1eE5uMMDA1mu6LPdr271qcj5pRCP13FCgqIQ== +"@aws-cdk/integ-tests-alpha@^2.155.0-alpha.0": + version "2.155.0-alpha.0" + resolved "https://registry.yarnpkg.com/@aws-cdk/integ-tests-alpha/-/integ-tests-alpha-2.155.0-alpha.0.tgz#5716b068511420ee5f393be37adf7c31948a27a6" + integrity sha512-brwoJNQrEwZVlrdplpoUWHyXOqkjgUt3hiYLQLk6xcYc79PxGBJ8uARPe0ZGQcQscAz2qGmQsjl4okRGqfTyKg== "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7": version "7.24.7" @@ -1406,10 +1406,10 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -aws-cdk-lib@2.154.1: - version "2.154.1" - resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.154.1.tgz#92888bca6b196ab3ae27adad43e85a14fa81f9c4" - integrity sha512-XV04/XyNKJ2yyMfYsiSmWx+rIKwTrcrd87p61t4xhE240Iy6Y6LxXVdvkNEOjjbeXVmOUQ7JBG9cW1BeeFiDgg== +aws-cdk-lib@2.155.0: + version "2.155.0" + resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.155.0.tgz#73abc753bf5dc9b5abe7e71aff254b386786a455" + integrity sha512-QGzDhLldBXsyOUmhgtZ98PiOUS2g1Mb5MO08FiOvQn3+KSyJjQdq0GoyxtDpCNGLaWmIfcyrtB9aDhod38fl9g== dependencies: "@aws-cdk/asset-awscli-v1" "^2.2.202" "@aws-cdk/asset-kubectl-v20" "^2.1.2"