Skip to content

Commit

Permalink
Merge branch 'main' into e2e/vigy/clear-env-issue
Browse files Browse the repository at this point in the history
  • Loading branch information
vigy02 committed Oct 10, 2024
2 parents 4047803 + faacd1b commit 2b312c4
Show file tree
Hide file tree
Showing 125 changed files with 5,252 additions and 1,129 deletions.
5 changes: 5 additions & 0 deletions .changeset/early-starfishes-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/ai-constructs': patch
---

Fix case where bedrock content blocks would be populated with 'null' instead of 'undefined.
5 changes: 5 additions & 0 deletions .changeset/modern-toys-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@aws-amplify/backend-deployer': patch
---

detect more generic CFN deployment failure errors
2 changes: 0 additions & 2 deletions .changeset/seven-rabbits-poke.md

This file was deleted.

1 change: 1 addition & 0 deletions .eslint_dictionary.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
"mysql",
"namespace",
"namespaces",
"netstat",
"nodejs",
"nodenext",
"nodir",
Expand Down
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Ignore artifacts:
.amplify
build
coverage
bin
Expand All @@ -10,6 +11,7 @@ verdaccio-cache
expected-cdk-out
.changeset/pre.json
concurrent_workspace_script_cache.json
packages/integration-tests/src/e2e-tests
scripts/components/api-changes-validator/test-resources/working-directory
/test-projects
testDir
testDir
1,098 changes: 814 additions & 284 deletions package-lock.json

Large diffs are not rendered by default.

62 changes: 46 additions & 16 deletions packages/ai-constructs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@

/// <reference types="node" />

import { AIConversationOutput } from '@aws-amplify/backend-output-schemas';
import { BackendOutputStorageStrategy } from '@aws-amplify/plugin-types';
import * as bedrock from '@aws-sdk/client-bedrock-runtime';
import { Construct } from 'constructs';
import { FunctionResources } from '@aws-amplify/plugin-types';
import * as jsonSchemaToTypeScript from 'json-schema-to-ts';
import { ResourceProvider } from '@aws-amplify/plugin-types';
import * as smithy from '@smithy/types';

declare namespace __export__conversation {
export {
ConversationHandlerFunction,
ConversationHandlerFunctionProps
ConversationHandlerFunctionProps,
ConversationTurnEventVersion
}
}
export { __export__conversation }
Expand All @@ -25,10 +28,12 @@ declare namespace __export__conversation__runtime {
ConversationMessage,
ConversationMessageContentBlock,
ConversationTurnEvent,
createExecutableTool,
ExecutableTool,
FromJSONSchema,
JSONSchema,
handleConversationTurnEvent,
ToolDefinition,
ToolExecutionInput,
ToolInputSchema,
ToolResultContentBlock
}
Expand All @@ -39,6 +44,8 @@ export { __export__conversation__runtime }
class ConversationHandlerFunction extends Construct implements ResourceProvider<FunctionResources> {
constructor(scope: Construct, id: string, props: ConversationHandlerFunctionProps);
// (undocumented)
static readonly eventVersion: ConversationTurnEventVersion;
// (undocumented)
resources: FunctionResources;
}

Expand All @@ -49,6 +56,7 @@ type ConversationHandlerFunctionProps = {
modelId: string;
region?: string;
}>;
outputStorageStrategy?: BackendOutputStorageStrategy<AIConversationOutput>;
};

// @public (undocumented)
Expand All @@ -64,6 +72,12 @@ type ConversationMessageContentBlock = bedrock.ContentBlock | {
bytes: string;
};
};
text?: never;
document?: never;
toolUse?: never;
toolResult?: never;
guardContent?: never;
$unknown?: never;
};

// @public (undocumented)
Expand All @@ -87,11 +101,16 @@ type ConversationTurnEvent = {
};
};
request: {
headers: {
authorization: string;
};
headers: Record<string, string>;
};
messages?: Array<ConversationMessage>;
messageHistoryQuery: {
getQueryName: string;
getQueryInputTypeName: string;
listQueryName: string;
listQueryInputTypeName: string;
listQueryLimit?: number;
};
messages: Array<ConversationMessage>;
toolsConfiguration?: {
dataTools?: Array<ToolDefinition & {
graphqlRequestInputDescriptor: {
Expand All @@ -105,27 +124,38 @@ type ConversationTurnEvent = {
};

// @public (undocumented)
type ExecutableTool = ToolDefinition & {
execute: (input: ToolExecutionInput | undefined) => Promise<ToolResultContentBlock>;
type ConversationTurnEventVersion = `1.${number}`;

// @public
const createExecutableTool: <TJSONSchema extends JSONSchema = JSONSchema, TToolInput = FromJSONSchema<TJSONSchema>>(name: string, description: string, inputSchema: ToolInputSchema<TJSONSchema>, handler: (input: TToolInput) => Promise<bedrock.ToolResultContentBlock>) => ExecutableTool<TJSONSchema, TToolInput>;

// @public (undocumented)
type ExecutableTool<TJSONSchema extends JSONSchema = JSONSchema, TToolInput = FromJSONSchema<TJSONSchema>> = ToolDefinition<TJSONSchema> & {
execute: (input: TToolInput) => Promise<ToolResultContentBlock>;
};

// @public (undocumented)
type FromJSONSchema<TJSONSchema extends JSONSchema> = jsonSchemaToTypeScript.FromSchema<TJSONSchema>;

// @public
const handleConversationTurnEvent: (event: ConversationTurnEvent, props?: {
tools?: Array<ExecutableTool>;
tools?: Array<ExecutableTool<JSONSchema, any>>;
}) => Promise<void>;

// @public (undocumented)
type ToolDefinition = {
type JSONSchema = jsonSchemaToTypeScript.JSONSchema;

// @public (undocumented)
type ToolDefinition<TJSONSchema extends JSONSchema = JSONSchema> = {
name: string;
description: string;
inputSchema: ToolInputSchema;
inputSchema: ToolInputSchema<TJSONSchema>;
};

// @public (undocumented)
type ToolExecutionInput = smithy.DocumentType;

// @public (undocumented)
type ToolInputSchema = bedrock.ToolInputSchema;
type ToolInputSchema<TJSONSchema extends JSONSchema> = {
json: TJSONSchema;
};

// @public (undocumented)
type ToolResultContentBlock = bedrock.ToolResultContentBlock;
Expand Down
29 changes: 29 additions & 0 deletions packages/ai-constructs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# @aws-amplify/ai-constructs

## 0.4.0

### Minor Changes

- 4781704: Add information about event version to conversation components
- 3a29d43: Pass user agent in conversation handler lambda

### Patch Changes

- 6e4a62f: Fix multi tool usage in single turn.

## 0.3.0

### Minor Changes

- 300a72d: Infer executable tool input type from input schema
- 0a5e51c: Stream conversation logs in sandbox

### Patch Changes

- Updated dependencies [0a5e51c]
- @aws-amplify/backend-output-schemas@1.3.0

## 0.2.0

### Minor Changes

- d0a90b1: Use message history instead of event payload for conversational route

## 0.1.4

### Patch Changes
Expand Down
11 changes: 9 additions & 2 deletions packages/ai-constructs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aws-amplify/ai-constructs",
"version": "0.1.4",
"version": "0.4.0",
"type": "commonjs",
"publishConfig": {
"access": "public"
Expand All @@ -26,9 +26,16 @@
},
"license": "Apache-2.0",
"dependencies": {
"@aws-amplify/backend-output-schemas": "^1.3.0",
"@aws-amplify/platform-core": "^1.1.0",
"@aws-amplify/plugin-types": "^1.0.1",
"@aws-sdk/client-bedrock-runtime": "^3.622.0",
"@smithy/types": "^3.3.0"
"@smithy/types": "^3.3.0",
"json-schema-to-ts": "^3.1.1"
},
"devDependencies": {
"@aws-amplify/backend-output-storage": "^1.1.2",
"typescript": "^5.0.0"
},
"peerDependencies": {
"aws-cdk-lib": "^2.152.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { App, Stack } from 'aws-cdk-lib';
import { ConversationHandlerFunction } from './conversation_handler_construct';
import { Template } from 'aws-cdk-lib/assertions';
import path from 'path';
import { StackMetadataBackendOutputStorageStrategy } from '@aws-amplify/backend-output-storage';

void describe('Conversation Handler Function construct', () => {
void it('creates handler with log group with JWT token redacting policy', () => {
Expand Down Expand Up @@ -140,6 +141,56 @@ void describe('Conversation Handler Function construct', () => {
});
});

void it('does not store output if output strategy is absent', () => {
const app = new App();
const stack = new Stack(app);
new ConversationHandlerFunction(stack, 'conversationHandler', {
models: [
{
modelId: 'testModelId',
},
],
outputStorageStrategy: undefined,
});
const template = Template.fromStack(stack);
const output = template.findOutputs(
'definedConversationHandlers'
).definedConversationHandlers;
assert.ok(!output);
});

void it('stores output if output strategy is present', () => {
const app = new App();
const stack = new Stack(app);
new ConversationHandlerFunction(stack, 'conversationHandler', {
models: [
{
modelId: 'testModelId',
},
],
outputStorageStrategy: new StackMetadataBackendOutputStorageStrategy(
stack
),
});
const template = Template.fromStack(stack);
const outputValue = template.findOutputs('definedConversationHandlers')
.definedConversationHandlers.Value;
assert.deepStrictEqual(outputValue, {
'Fn::Join': [
'',
[
'["',
{
/* eslint-disable spellcheck/spell-checker */
Ref: 'conversationHandlerconversationHandlerFunction45BC2E1F',
/* eslint-enable spellcheck/spell-checker */
},
'"]',
],
],
});
});

void it('throws if entry is not absolute', () => {
const app = new App();
const stack = new Stack(app);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { FunctionResources, ResourceProvider } from '@aws-amplify/plugin-types';
import { Duration, Stack } from 'aws-cdk-lib';
import {
BackendOutputStorageStrategy,
FunctionResources,
ResourceProvider,
} from '@aws-amplify/plugin-types';
import { Duration, Stack, Tags } from 'aws-cdk-lib';
import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { CfnFunction, Runtime as LambdaRuntime } from 'aws-cdk-lib/aws-lambda';
import {
CfnFunction,
Runtime as LambdaRuntime,
LoggingFormat,
} from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import {
CustomDataIdentifier,
Expand All @@ -11,6 +19,11 @@ import {
} from 'aws-cdk-lib/aws-logs';
import { Construct } from 'constructs';
import path from 'path';
import { TagName } from '@aws-amplify/platform-core';
import {
AIConversationOutput,
aiConversationOutputKey,
} from '@aws-amplify/backend-output-schemas';

const resourcesRoot = path.normalize(path.join(__dirname, 'runtime'));
const defaultHandlerFilePath = path.join(resourcesRoot, 'default_handler.js');
Expand All @@ -21,8 +34,17 @@ export type ConversationHandlerFunctionProps = {
modelId: string;
region?: string;
}>;
/**
* @internal
*/
outputStorageStrategy?: BackendOutputStorageStrategy<AIConversationOutput>;
};

// Event is a protocol between AppSync and Lambda handler. Therefore, X.Y subset of semver is enough.
// Typing this as 1.X so that major version changes are caught by compiler if consumer of this construct inspects
// event version.
export type ConversationTurnEventVersion = `1.${number}`;

/**
* Conversation Handler Function CDK construct.
* This construct deploys resources that integrate conversation routes
Expand All @@ -37,6 +59,7 @@ export class ConversationHandlerFunction
extends Construct
implements ResourceProvider<FunctionResources>
{
static readonly eventVersion: ConversationTurnEventVersion = '1.0';
resources: FunctionResources;

/**
Expand All @@ -53,6 +76,8 @@ export class ConversationHandlerFunction
throw new Error('Entry must be absolute path');
}

Tags.of(this).add(TagName.FRIENDLY_NAME, id);

const conversationHandler = new NodejsFunction(
this,
`conversationHandlerFunction`,
Expand All @@ -67,6 +92,7 @@ export class ConversationHandlerFunction
// For custom entry we do bundle SDK as we can't control version customer is coding against.
bundleAwsSDK: !!this.props.entry,
},
loggingFormat: LoggingFormat.JSON,
logGroup: new LogGroup(this, 'conversationHandlerFunctionLogGroup', {
retention: RetentionDays.INFINITE,
dataProtectionPolicy: new DataProtectionPolicy({
Expand Down Expand Up @@ -105,5 +131,23 @@ export class ConversationHandlerFunction
) as CfnFunction,
},
};

this.storeOutput(this.props.outputStorageStrategy);
}

/**
* Append conversation handler to defined functions.
*/
private storeOutput = (
outputStorageStrategy:
| BackendOutputStorageStrategy<AIConversationOutput>
| undefined
): void => {
outputStorageStrategy?.appendToBackendOutputList(aiConversationOutputKey, {
version: '1',
payload: {
definedConversationHandlers: this.resources.lambda.functionName,
},
});
};
}
Loading

0 comments on commit 2b312c4

Please sign in to comment.