Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion packages/@aws-cdk/aws-bedrock-alpha/bedrock/prompts/prompt.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Arn, ArnFormat, IResource, Lazy, Resource } from 'aws-cdk-lib/core';
import { Arn, ArnFormat, IResource, Lazy, Resource, ValidationError } from 'aws-cdk-lib/core';
import * as bedrock from 'aws-cdk-lib/aws-bedrock';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as kms from 'aws-cdk-lib/aws-kms';
Expand Down Expand Up @@ -287,6 +287,7 @@ export class Prompt extends PromptBase implements IPrompt {
// ------------------------------------------------------
// Validation
// ------------------------------------------------------
this.validatePromptDefault(props);
this.node.addValidation({ validate: () => this.validatePromptName() });
this.node.addValidation({ validate: () => this.validatePromptVariants() });
this.node.addValidation({ validate: () => this.validateDescription() });
Expand Down Expand Up @@ -378,6 +379,16 @@ export class Prompt extends PromptBase implements IPrompt {
return errors;
}

/**
* Validates that if the prompt has a default, it was also added to the variants array
* @param props - The properties set in the constructor
*/
private validatePromptDefault(props: PromptProps) {
if (props.defaultVariant && !props.variants?.includes(props.defaultVariant)) {
throw new ValidationError('The \'defaultVariant\' needs to be included in the \'variants\' array.', this);
}
}

/**
* Validates whether the description length is within the allowed limit.
* @returns Array of validation error messages, empty if valid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,32 +155,32 @@ describe('Prompt', () => {
});
});

test('validates prompt name pattern - invalid names', () => {
const invalidNames = [
'-invalid', // starts with hyphen
'invalid-', // ends with hyphen
'a'.repeat(101), // too long
'', // empty
'invalid name', // contains space
'invalid@name', // contains special character
];

invalidNames.forEach((name, index) => {
expect(() => {
new bedrock.Prompt(stack, `TestPrompt${index}`, {
promptName: name,
});
}).not.toThrow(); // Validation happens at synthesis time, not construction time
test.each([
['-invalid', 'starts with hyphen'],
['a'.repeat(101), 'too long'],
['', 'empty'],
['invalid name', 'contains space'],
['invalid@name', 'contains special character'],
])('validates prompt name pattern - %s (%s)', (invalidName, _description) => {
new bedrock.Prompt(stack, 'TestPrompt', {
promptName: invalidName,
});

expect(() => {
Template.fromStack(stack);
}).toThrow(/Valid characters are a-z, A-Z, 0-9, _ \(underscore\) and - \(hyphen\). Must not begin with a hyphen and must be 1-100 characters long/);
});

test('validates description length', () => {
new bedrock.Prompt(stack, 'TestPrompt', {
promptName: 'test-prompt',
description: 'a'.repeat(251), // too long
});

// Validation happens at synthesis time, not construction time
expect(() => {
new bedrock.Prompt(stack, 'TestPrompt', {
promptName: 'test-prompt',
description: 'a'.repeat(251), // too long
});
}).not.toThrow(); // Validation happens at synthesis time, not construction time
Template.fromStack(stack);
}).toThrow(/Description must be 200 characters or less/);
});

test('validates maximum number of variants', () => {
Expand All @@ -192,12 +192,15 @@ describe('Prompt', () => {
}),
);

new bedrock.Prompt(stack, 'TestPrompt', {
promptName: 'test-prompt',
variants,
});

// Validation happens at synthesis time, not construction time
expect(() => {
new bedrock.Prompt(stack, 'TestPrompt', {
promptName: 'test-prompt',
variants,
});
}).not.toThrow(); // Validation happens at synthesis time, not construction time
Template.fromStack(stack);
}).toThrow(/Too many variants specified/);
});

test('validates unique variant names', () => {
Expand All @@ -213,12 +216,30 @@ describe('Prompt', () => {
promptText: 'Text 2',
});

new bedrock.Prompt(stack, 'TestPrompt', {
promptName: 'test-prompt',
variants: [variant1, variant2],
});

// Validation happens at synthesis time, not construction time
expect(() => {
Template.fromStack(stack);
}).toThrow(/Duplicate variant names found/);
});

test('validates default variant is added to variants array', () => {
const defaultVariant = bedrock.PromptVariant.text({
variantName: 'default-variant',
model: foundationModel,
promptText: 'Text',
});

expect(() => {
new bedrock.Prompt(stack, 'TestPrompt', {
promptName: 'test-prompt',
variants: [variant1, variant2],
promptName: 'my-test-prompt',
defaultVariant: defaultVariant,
});
}).not.toThrow(); // Validation happens at synthesis time, not construction time
}).toThrow('The \'defaultVariant\' needs to be included in the \'variants\' array.');
});
});

Expand Down
Loading