Skip to content

Commit ef890d6

Browse files
authored
feat(eula): expose the eula property for SageMaker JumpStart model deployment (#257)
* chore(deps): upgrade cdk to 2.122.0 * chore(construct): expose new accepteula property * chore(eula): fail synth if eula not explicitly set to true * chore(doc): update related documentation * chore(test): add test to cover eula acceptance set to false * fix(commitlint): downgrade commitlint as issue with latest version * chore(commitlint): upgrade version * chore(sg): verify if model requires eula acceptance
1 parent fd6dc16 commit ef890d6

15 files changed

+119
-10
lines changed

.projen/deps.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.projenrc.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
const GITHUB_USER = 'awslabs';
3030
const PUBLICATION_NAMESPACE = 'cdklabs';
3131
const PROJECT_NAME = 'generative-ai-cdk-constructs';
32-
const CDK_VERSION: string = '2.116.0';
32+
const CDK_VERSION: string = '2.122.0';
3333

3434
const project = new awscdk.AwsCdkConstructLibrary({
3535
author: 'Amazon Web Services - Prototyping and Cloud Engineering',

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# CDK Generative AI Constructs V0.1.60 (2024-02-13)
2+
3+
Based on CDK library version 2.122.0
4+
15
# CDK Generative AI Constructs V0.1.35 (2024-01-24)
26

37
Based on CDK library version 2.116.0

DEVELOPER_GUIDE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Default output format [None]: json
1616
```
1717

1818
- [Node](https://nodejs.org/en) >= v20.9.0
19-
- [AWS CDK](https://github.com/aws/aws-cdk/releases/tag/v2.102.0) >= 2.114.0
19+
- [AWS CDK](https://github.com/aws/aws-cdk/releases/tag/v2.122.0) >= 2.122.0
2020
- [Python](https://www.python.org/downloads/) >=3.9
2121
- [Projen](https://github.com/projen/projen) >= 0.78.8
2222
- [Yarn](https://classic.yarnpkg.com/lang/en/docs/cli/install/) >= 1.22.19

apidocs/classes/JumpStartSageMakerEndpoint.md

+7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ The JumpStartSageMakerEndpoint class.
2020

2121
### Properties
2222

23+
- [acceptEula](JumpStartSageMakerEndpoint.md#accepteula)
2324
- [cfnEndpoint](JumpStartSageMakerEndpoint.md#cfnendpoint)
2425
- [cfnEndpointConfig](JumpStartSageMakerEndpoint.md#cfnendpointconfig)
2526
- [cfnModel](JumpStartSageMakerEndpoint.md#cfnmodel)
@@ -71,6 +72,12 @@ The JumpStartSageMakerEndpoint class.
7172

7273
## Properties
7374

75+
### acceptEula
76+
77+
`Private` `Readonly` **acceptEula**: `boolean`
78+
79+
___
80+
7481
### cfnEndpoint
7582

7683
`Readonly` **cfnEndpoint**: `CfnEndpoint`

apidocs/interfaces/IJumpStartModelSpec.md

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- [modelId](IJumpStartModelSpec.md#modelid)
1616
- [modelPackageArns](IJumpStartModelSpec.md#modelpackagearns)
1717
- [prepackedArtifactKey](IJumpStartModelSpec.md#prepackedartifactkey)
18+
- [requiresEula](IJumpStartModelSpec.md#requireseula)
1819
- [version](IJumpStartModelSpec.md#version)
1920

2021
## Properties
@@ -81,6 +82,12 @@ ___
8182

8283
___
8384

85+
### requiresEula
86+
87+
**requiresEula**: `boolean`
88+
89+
___
90+
8491
### version
8592

8693
**version**: `string`

apidocs/interfaces/JumpStartSageMakerEndpointProps.md

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
### Properties
88

9+
- [acceptEula](JumpStartSageMakerEndpointProps.md#accepteula)
910
- [endpointName](JumpStartSageMakerEndpointProps.md#endpointname)
1011
- [environment](JumpStartSageMakerEndpointProps.md#environment)
1112
- [instanceCount](JumpStartSageMakerEndpointProps.md#instancecount)
@@ -17,6 +18,12 @@
1718

1819
## Properties
1920

21+
### acceptEula
22+
23+
`Optional` `Readonly` **acceptEula**: `boolean`
24+
25+
___
26+
2027
### endpointName
2128

2229
`Optional` `Readonly` **endpointName**: `string`

package.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/patterns/gen-ai/aws-model-deployment-sagemaker/README_jumpstart.md

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import { JumpStartSageMakerEndpoint, JumpStartModel, SageMakerInstanceType } fro
5656
// Deploy a model from SageMaker Foundation Models or SageMaker JumpStart
5757
new JumpStartSageMakerEndpoint(this, 'LLAMA2', {
5858
model: JumpStartModel.META_TEXTGENERATION_LLAMA_2_7B_F_2_0_2,
59+
acceptEula: true,
5960
instanceType: SageMakerInstanceType.ML_G5_2XLARGE,
6061
});
6162
```
@@ -73,6 +74,7 @@ JumpStartSageMakerEndpoint(
7374
self,
7475
'LLAMA2',
7576
model=JumpStartModel.META_TEXTGENERATION_LLAMA_2_7_B_F_2_0_2,
77+
accept_eula=True,
7678
instance_type=SageMakerInstanceType.ML_G5_2_XLARGE,
7779
)
7880
```
@@ -97,6 +99,7 @@ Parameters
9799
|:-------------|:----------------|-----------------|-----------------|
98100
| model | JumpStartModel | ![Required](https://img.shields.io/badge/required-ff0000) | The model to deploy |
99101
| endpointName | string| ![Optional](https://img.shields.io/badge/optional-4169E1) | Name of the SageMaker endpoint created by the construct |
102+
| acceptEula | boolean| ![Optional](https://img.shields.io/badge/optional-4169E1) | Specifies agreement to the model end-user license agreement (EULA). The AcceptEula value must be explicitly defined as True in order to accept the EULA that the model requires. The user is responsible for reviewing and complying with any applicable license terms and making sure they are acceptable for their use case before downloading or using a model. |
100103
| instanceType | SageMakerInstanceType | ![Optional](https://img.shields.io/badge/optional-4169E1) | The ML compute instance type. If not provided, the default instance type will be used. This value is available in the [models spec](./jumpstart-model.ts) |
101104
| instanceCount | Integer | ![Optional](https://img.shields.io/badge/optional-4169E1) | Number of instances to launch initially |
102105
| role | [iam.Role](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.Role.html) | ![Optional](https://img.shields.io/badge/optional-4169E1) | The IAM role that SageMaker can assume to access model artifacts and docker image for deployment on ML compute instances or for batch transform jobs. If not provided, this construct will create a new role with Full access to SageMaker.|

src/patterns/gen-ai/aws-model-deployment-sagemaker/code-generation/generate-jumpstart-models.ts

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ interface JumpStartModelSpec {
3434
hosting_artifact_key?: string;
3535
hosting_script_key?: string;
3636
hosting_prepacked_artifact_key?: string;
37+
hosting_eula_key?: string;
3738
inference_environment_variables: {
3839
name: string;
3940
type: string;
@@ -114,6 +115,7 @@ export async function download_data() {
114115
hosting_prepacked_artifact_key,
115116
inference_environment_variables,
116117
hosting_instance_type_variants,
118+
hosting_eula_key,
117119
} = modelSpec;
118120

119121
const allowedFramework = ALLOWED_FRAMEWORKS.includes(hosting_ecr_specs.framework);
@@ -149,6 +151,7 @@ export async function download_data() {
149151
hosting_prepacked_artifact_key,
150152
inference_environment_variables,
151153
hosting_instance_type_variants,
154+
hosting_eula_key,
152155
};
153156
}
154157
}
@@ -180,6 +183,7 @@ function generateCode() {
180183
environment[env.name] = env.default;
181184
}
182185

186+
const hosting_eula_key = specSource.hosting_eula_key;
183187
const instanceVariants = specSource.hosting_instance_type_variants?.variants;
184188
const instanceAliases = specSource.hosting_instance_type_variants?.regional_aliases;
185189
let instanceVariantsArr: any[] | undefined;
@@ -220,6 +224,7 @@ function generateCode() {
220224
environment,
221225
instanceAliases: instanceAliasesArr,
222226
instanceVariants: instanceVariantsArr,
227+
requiresEula: hosting_eula_key,
223228
};
224229

225230
if (spec.modelPackageArns) {
@@ -269,6 +274,7 @@ export interface IJumpStartModelSpec {
269274
environment: { [key: string]: string | number | boolean };
270275
instanceAliases?: IInstanceAliase[];
271276
instanceVariants?: IInstanceValiant[];
277+
requiresEula: boolean;
272278
}
273279
274280
export class JumpStartModel {

src/patterns/gen-ai/aws-model-deployment-sagemaker/jumpstart-model.ts

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export interface IJumpStartModelSpec {
3535
environment: { [key: string]: string | number | boolean };
3636
instanceAliases?: IInstanceAliase[];
3737
instanceVariants?: IInstanceValiant[];
38+
requiresEula: boolean;
3839
}
3940

4041
export class JumpStartModel {

src/patterns/gen-ai/aws-model-deployment-sagemaker/jumpstart-models.json

+1-1
Large diffs are not rendered by default.

src/patterns/gen-ai/aws-model-deployment-sagemaker/jumpstart-sagemaker-endpoint.ts

+14
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface JumpStartSageMakerEndpointProps {
2828
readonly vpcConfig?: sagemaker.CfnModel.VpcConfigProperty | undefined;
2929
readonly environment?: { [key: string]: string };
3030
readonly startupHealthCheckTimeoutInSeconds?: number;
31+
readonly acceptEula?: boolean;
3132
}
3233

3334
/**
@@ -45,6 +46,7 @@ export class JumpStartSageMakerEndpoint extends SageMakerEndpointBase {
4546
public readonly instanceCount: number;
4647
public readonly role: iam.Role;
4748

49+
private readonly acceptEula: boolean;
4850
private readonly region: string;
4951
private readonly spec: IJumpStartModelSpec;
5052
private readonly startupHealthCheckTimeoutInSeconds: number;
@@ -56,12 +58,21 @@ export class JumpStartSageMakerEndpoint extends SageMakerEndpointBase {
5658
this.model = props.model;
5759
this.instanceType = props.instanceType;
5860
this.instanceCount = Math.max(1, props.instanceCount ?? 1);
61+
this.acceptEula = props.acceptEula ?? false;
62+
5963
this.role = props.role ?? this.createSageMakerRole();
6064
this.grantPrincipal = this.role;
6165

6266
this.startupHealthCheckTimeoutInSeconds = props.startupHealthCheckTimeoutInSeconds ?? 600;
6367
this.environment = props.environment;
6468
this.spec = this.model.bind();
69+
70+
if (!this.acceptEula && this.spec.requiresEula) {
71+
throw new Error(
72+
'The AcceptEula value must be explicitly defined as True in order to accept the EULA for the model '+this.spec.modelId+'. You are responsible for reviewing and complying with any applicable license terms and making sure they are acceptable for your use case before downloading or using a model.',
73+
);
74+
}
75+
6576
this.region = Stack.of(this).region;
6677

6778
if (Token.isUnresolved(this.region)) {
@@ -211,6 +222,9 @@ export class JumpStartSageMakerEndpoint extends SageMakerEndpointBase {
211222
compressionType: 'None',
212223
s3DataType: 'S3Prefix',
213224
s3Uri: modelArtifactUrl,
225+
modelAccessConfig: {
226+
acceptEula: this.acceptEula,
227+
},
214228
},
215229
},
216230
environment,

test/patterns/gen-ai/aws-model-deployment-sagemaker/aws-model-deployment-sagemaker.test.ts

+60
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ describe('JumpStartSageMakerEndpoint construct', () => {
3939

4040
JmpStrtTestConstruct = new JumpStartSageMakerEndpoint(JmpStrtTestStack, 'test', {
4141
model: JumpStartModel.META_TEXTGENERATION_LLAMA_2_7B_F_2_0_2,
42+
acceptEula: true,
4243
instanceType: SageMakerInstanceType.ML_G5_2XLARGE,
4344
});
4445
JmpStrtTestTemplate = Template.fromStack(JmpStrtTestStack);
@@ -90,6 +91,64 @@ describe('JumpStartSageMakerEndpoint construct', () => {
9091
});
9192
});
9293

94+
describe('JumpStartSageMakerEndpoint eula validation', () => {
95+
96+
let JmpStrtTestStack: cdk.Stack;
97+
98+
afterAll(() => {
99+
console.log('Test completed');
100+
});
101+
102+
beforeAll(() => {
103+
104+
JmpStrtTestStack = new cdk.Stack(undefined, undefined, {
105+
env: { account: cdk.Aws.ACCOUNT_ID, region: 'us-east-1' },
106+
});
107+
108+
});
109+
110+
test('SageMaker endpoint fails to synth', () => {
111+
112+
//wrapping code in a function, otherwise the error will not be caught and the assertion will fail.
113+
const t = () => {
114+
new JumpStartSageMakerEndpoint(JmpStrtTestStack, 'test', {
115+
model: JumpStartModel.META_TEXTGENERATION_LLAMA_2_7B_F_2_0_2,
116+
acceptEula: false, // should fail synth
117+
instanceType: SageMakerInstanceType.ML_G5_2XLARGE,
118+
});
119+
};
120+
121+
expect(t).toThrow('The AcceptEula value must be explicitly defined as True in order to accept the EULA for the model meta-textgeneration-llama-2-7b-f. You are responsible for reviewing and complying with any applicable license terms and making sure they are acceptable for your use case before downloading or using a model.');
122+
});
123+
124+
test('SageMaker endpoint succeeds to synth', () => {
125+
126+
//wrapping code in a function, otherwise the error will not be caught and the assertion will fail.
127+
const t = () => {
128+
new JumpStartSageMakerEndpoint(JmpStrtTestStack, 'test2', {
129+
model: JumpStartModel.META_TEXTGENERATION_LLAMA_2_7B_F_2_0_2,
130+
acceptEula: true, // should succeed synth
131+
instanceType: SageMakerInstanceType.ML_G5_2XLARGE,
132+
});
133+
};
134+
135+
expect(t).not.toThrow();
136+
});
137+
138+
test('SageMaker endpoint doesnt require eula succeeds to synth', () => {
139+
140+
//wrapping code in a function, otherwise the error will not be caught and the assertion will fail.
141+
const t = () => {
142+
new JumpStartSageMakerEndpoint(JmpStrtTestStack, 'test3', {
143+
model: JumpStartModel.MODEL_DEPTH2IMG_STABLE_DIFFUSION_V1_5_CONTROLNET_1_0_0, // eula not defined
144+
instanceType: SageMakerInstanceType.ML_G5_2XLARGE,
145+
});
146+
};
147+
148+
expect(t).not.toThrow();
149+
});
150+
});
151+
93152
describe('JumpStartSageMakerEndpoint VPC construct', () => {
94153

95154
let JmpStrtTestTemplate: Template;
@@ -140,6 +199,7 @@ describe('JumpStartSageMakerEndpoint VPC construct', () => {
140199
JmpStrtTestConstruct = new JumpStartSageMakerEndpoint(JmpStrtTestStack, 'test', {
141200
model: JumpStartModel.META_TEXTGENERATION_LLAMA_2_7B_F_2_0_2,
142201
instanceType: SageMakerInstanceType.ML_G5_2XLARGE,
202+
acceptEula: true,
143203
vpcConfig: {
144204
securityGroupIds: securityGroups.map(s => s.securityGroupId),
145205
subnets: vpc.privateSubnets.map((subnet) => subnet.subnetId),

yarn.lock

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)