Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
30d2087
fix IndexName -> index in otherwise unused query list resolver
atierian Sep 12, 2024
b2b2135
update snapshots in relational, searchable, and index transformers
atierian Sep 27, 2024
11de0e3
single item messages, replace assistantContent with associatedUserMes…
atierian Sep 27, 2024
06c295a
assistant mutation pipeline writes instead of updates
atierian Sep 27, 2024
c8d7500
update event payload for lambda history retrieval pattern
atierian Sep 27, 2024
b3a9e19
update test case for num resolver fns in list query pipeline
atierian Sep 27, 2024
1170798
remove straggler import statement
atierian Sep 27, 2024
019e01f
lint
atierian Oct 1, 2024
d35bd88
wip conversation-pipeline-resolver abstraction
atierian Oct 2, 2024
90d6131
wip pipeline defs
atierian Oct 15, 2024
b75b80d
wip add subscription pipeline definition
atierian Oct 15, 2024
a9df4e9
Merge branch 'main' into ai.conversation-consolidate-resolver-generation
atierian Oct 15, 2024
dbc52bf
fix use correct field and type names for resolvers
atierian Oct 15, 2024
175fa36
remove now unneeded files
atierian Oct 15, 2024
90afcb5
cleanup
atierian Oct 15, 2024
5162880
consolidate datasource and substitution helpers
atierian Oct 15, 2024
22e2b68
simplify pipeline resolver by using function rather than class
atierian Oct 16, 2024
a0062d0
move templates to a subdirectory
atierian Oct 16, 2024
f0e51d9
organize imports
atierian Oct 16, 2024
fc5d8fb
move definitions types to own file
atierian Oct 16, 2024
77da9b1
file orgnization hygiene
atierian Oct 16, 2024
2acdfc1
remove string template values
atierian Oct 16, 2024
8893a15
prettier
atierian Oct 16, 2024
ef784a5
Merge branch 'main' into ai.conversation-consolidate-resolver-generation
atierian Oct 21, 2024
288d076
move handler configuration into types file
atierian Oct 21, 2024
60683e7
file name and inline comments
atierian Oct 21, 2024
204019a
add MODEL_ID and SYSTEM_PROMPT substitutions
atierian Oct 21, 2024
5dc7752
cleanup
atierian Oct 21, 2024
5e7e0a6
remove unused helper in test case
atierian Oct 21, 2024
5f6712b
lint
atierian Oct 21, 2024
0e8eaee
drop unnecessary -p in mkdir script (windows)
atierian Oct 21, 2024
9c8c72c
update copy-js-resolver-templates script for windows compat
atierian Oct 21, 2024
aa252f7
single validation place
atierian Oct 21, 2024
ac1148f
add back existing functionName deprecation wording
atierian Oct 21, 2024
80948aa
extract api
atierian Oct 21, 2024
a3111dc
fix doc comment names
atierian Oct 22, 2024
0b84777
Error -> InvalidDirectiveError
atierian Oct 22, 2024
fb1f132
function -> const
atierian Oct 22, 2024
3c52969
export same names from resolver submodule
atierian Oct 22, 2024
61052fe
Merge branch 'main' into ai.conversation-consolidate-resolver-generation
atierian Oct 23, 2024
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
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ packages/amplify-graphql-api-construct-tests/amplify-e2e-reports
packages/amplify-graphql-api-construct/README.md
packages/amplify-graphql-api-construct/tsconfig.json
packages/amplify-graphql-conversation-transformer/src/__tests__/schemas/*.graphql
packages/amplify-graphql-conversation-transformer/src/resolvers/*.template.js
packages/amplify-graphql-conversation-transformer/src/resolvers/templates/*.template.js
packages/amplify-graphql-generation-transformer/src/resolvers/*.template.js
packages/amplify-data-construct/README.md
packages/amplify-data-construct/tsconfig.json
Expand Down
2 changes: 0 additions & 2 deletions packages/amplify-graphql-conversation-transformer/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ export class ConversationTransformer extends TransformerPluginBase {
generateResolvers: (ctx: TransformerContextProvider) => void;
// (undocumented)
prepare: (ctx: TransformerPrepareStepContextProvider) => void;
// (undocumented)
validate: () => void;
}

// (No @packageDocumentation comment for this package)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"build": "tsc && yarn copy-js-resolver-templates",
"watch": "tsc -w",
"clean": "rimraf ./lib",
"copy-js-resolver-templates": "cp ./src/resolvers/*.template.js ./lib/resolvers",
"copy-js-resolver-templates": "cd lib/resolvers && mkdir -p templates && cp ../../src/resolvers/templates/*.template.js templates",
"test": "jest",
"extract-api": "ts-node ../../scripts/extract-api.ts"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ export function request(ctx) {
const { args, request } = ctx;
const { graphqlApiEndpoint } = ctx.stash;


const selectionSet = 'id conversationId content { image { format source { bytes }} text toolUse { toolUseId name input } toolResult { status toolUseId content { json text image { format source { bytes }} document { format name source { bytes }} }}} role owner createdAt updatedAt';

const responseMutation = {
Expand All @@ -161,18 +160,18 @@ export function request(ctx) {
selectionSet,
};
const currentMessageId = ctx.stash.defaultValues.id;

const modelConfiguration = {
modelId: 'anthropic.claude-3-haiku-20240307-v1:0',
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",
inferenceConfiguration: {"temperature":0.5,"topP":0.9,"maxTokens":100},
};
modelId: "anthropic.claude-3-haiku-20240307-v1:0",
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",
inferenceConfiguration: {"temperature":0.5,"topP":0.9,"maxTokens":100},
};
Comment on lines +165 to +168
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes are from JSON.stringify(...) ('' --> "") and maintaining proper indentation.


const clientTools = args.toolConfiguration?.tools?.map((tool) => {
return { ...tool.toolSpec };
});
const toolsConfiguration = {
clientTools
};
const dataTools = undefined;
const toolsConfiguration = { dataTools, clientTools };
Comment on lines +173 to +174
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is expected if no tools are provided in the conversation directive. It was part of reworking the resolver function generation to stop constructed fragments of the JS resolver runtime code as strings within the transformer.


const messageHistoryQuery = {
getQueryName: 'getConversationMessagePirateChat',
Expand Down Expand Up @@ -373,7 +372,6 @@ export function request(ctx) {
const { args, request } = ctx;
const { graphqlApiEndpoint } = ctx.stash;

const toolDefinitions = {"tools":[{"name":"listTodos","description":"lists todos","inputSchema":{"json":{"type":"object","properties":{},"required":[]}},"graphqlRequestInputDescriptor":{"selectionSet":"items { content isDone id createdAt updatedAt owner } nextToken","propertyTypes":{},"queryName":"listTodos"}}]};
const selectionSet = 'id conversationId content { image { format source { bytes }} text toolUse { toolUseId name input } toolResult { status toolUseId content { json text image { format source { bytes }} document { format name source { bytes }} }}} role owner createdAt updatedAt';

const responseMutation = {
Expand All @@ -382,20 +380,18 @@ export function request(ctx) {
selectionSet,
};
const currentMessageId = ctx.stash.defaultValues.id;

const modelConfiguration = {
modelId: 'anthropic.claude-3-haiku-20240307-v1:0',
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",

};
modelId: "anthropic.claude-3-haiku-20240307-v1:0",
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",
inferenceConfiguration: undefined,
};

const clientTools = args.toolConfiguration?.tools?.map((tool) => {
return { ...tool.toolSpec };
});
const dataTools = toolDefinitions.tools;
const toolsConfiguration = {
dataTools,
clientTools,
};
const dataTools = [{"name":"listTodos","description":"lists todos","inputSchema":{"json":{"type":"object","properties":{},"required":[]}},"graphqlRequestInputDescriptor":{"selectionSet":"items { content isDone id createdAt updatedAt owner } nextToken","propertyTypes":{},"queryName":"listTodos"}}];
const toolsConfiguration = { dataTools, clientTools };

const messageHistoryQuery = {
getQueryName: 'getConversationMessagePirateChat',
Expand Down Expand Up @@ -596,7 +592,6 @@ export function request(ctx) {
const { args, request } = ctx;
const { graphqlApiEndpoint } = ctx.stash;

const toolDefinitions = {"tools":[{"name":"listCustomers","description":"Provides data about the customer sending a message","inputSchema":{"json":{"type":"object","properties":{},"required":[]}},"graphqlRequestInputDescriptor":{"selectionSet":"items { name email activeCart { products { name price } customerId id createdAt updatedAt owner } orderHistory { items { products { name price } customerId id createdAt updatedAt owner } nextToken } id createdAt updatedAt owner } nextToken","propertyTypes":{},"queryName":"listCustomers"}}]};
const selectionSet = 'id conversationId content { image { format source { bytes }} text toolUse { toolUseId name input } toolResult { status toolUseId content { json text image { format source { bytes }} document { format name source { bytes }} }}} role owner createdAt updatedAt';

const responseMutation = {
Expand All @@ -605,20 +600,18 @@ export function request(ctx) {
selectionSet,
};
const currentMessageId = ctx.stash.defaultValues.id;

const modelConfiguration = {
modelId: 'anthropic.claude-3-haiku-20240307-v1:0',
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",

};
modelId: "anthropic.claude-3-haiku-20240307-v1:0",
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",
inferenceConfiguration: undefined,
};

const clientTools = args.toolConfiguration?.tools?.map((tool) => {
return { ...tool.toolSpec };
});
const dataTools = toolDefinitions.tools;
const toolsConfiguration = {
dataTools,
clientTools,
};
const dataTools = [{"name":"listCustomers","description":"Provides data about the customer sending a message","inputSchema":{"json":{"type":"object","properties":{},"required":[]}},"graphqlRequestInputDescriptor":{"selectionSet":"items { name email activeCart { products { name price } customerId id createdAt updatedAt owner } orderHistory { items { products { name price } customerId id createdAt updatedAt owner } nextToken } id createdAt updatedAt owner } nextToken","propertyTypes":{},"queryName":"listCustomers"}}];
const toolsConfiguration = { dataTools, clientTools };

const messageHistoryQuery = {
getQueryName: 'getConversationMessagePirateChat',
Expand Down Expand Up @@ -819,7 +812,6 @@ export function request(ctx) {
const { args, request } = ctx;
const { graphqlApiEndpoint } = ctx.stash;

const toolDefinitions = {"tools":[{"name":"getTemperature","description":"does a thing","inputSchema":{"json":{"type":"object","properties":{"city":{"type":"string","description":"A UTF-8 character sequence."}},"required":["city"]}},"graphqlRequestInputDescriptor":{"selectionSet":"value unit","propertyTypes":{"city":"String!"},"queryName":"getTemperature"}},{"name":"plus","description":"does a different thing","inputSchema":{"json":{"type":"object","properties":{"a":{"type":"number","description":"A signed 32-bit integer value."},"b":{"type":"number","description":"A signed 32-bit integer value."}},"required":[]}},"graphqlRequestInputDescriptor":{"selectionSet":"","propertyTypes":{"a":"Int","b":"Int"},"queryName":"plus"}}]};
const selectionSet = 'id conversationId content { image { format source { bytes }} text toolUse { toolUseId name input } toolResult { status toolUseId content { json text image { format source { bytes }} document { format name source { bytes }} }}} role owner createdAt updatedAt';

const responseMutation = {
Expand All @@ -828,20 +820,18 @@ export function request(ctx) {
selectionSet,
};
const currentMessageId = ctx.stash.defaultValues.id;

const modelConfiguration = {
modelId: 'anthropic.claude-3-haiku-20240307-v1:0',
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",

};
modelId: "anthropic.claude-3-haiku-20240307-v1:0",
systemPrompt: "You are a helpful chatbot. Answer questions to the best of your ability.",
inferenceConfiguration: undefined,
};

const clientTools = args.toolConfiguration?.tools?.map((tool) => {
return { ...tool.toolSpec };
});
const dataTools = toolDefinitions.tools;
const toolsConfiguration = {
dataTools,
clientTools,
};
const dataTools = [{"name":"getTemperature","description":"does a thing","inputSchema":{"json":{"type":"object","properties":{"city":{"type":"string","description":"A UTF-8 character sequence."}},"required":["city"]}},"graphqlRequestInputDescriptor":{"selectionSet":"value unit","propertyTypes":{"city":"String!"},"queryName":"getTemperature"}},{"name":"plus","description":"does a different thing","inputSchema":{"json":{"type":"object","properties":{"a":{"type":"number","description":"A signed 32-bit integer value."},"b":{"type":"number","description":"A signed 32-bit integer value."}},"required":[]}},"graphqlRequestInputDescriptor":{"selectionSet":"","propertyTypes":{"a":"Int","b":"Int"},"queryName":"plus"}}];
const toolsConfiguration = { dataTools, clientTools };

const messageHistoryQuery = {
getQueryName: 'getConversationMessagePirateChat',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { AuthTransformer } from '@aws-amplify/graphql-auth-transformer';
import { GenerationTransformer } from '@aws-amplify/graphql-generation-transformer';
import { IndexTransformer, PrimaryKeyTransformer } from '@aws-amplify/graphql-index-transformer';
import { ModelTransformer } from '@aws-amplify/graphql-model-transformer';
import { BelongsToTransformer, HasManyTransformer, HasOneTransformer } from '@aws-amplify/graphql-relational-transformer';
import { validateModelSchema } from '@aws-amplify/graphql-transformer-core';
import { AppSyncAuthConfiguration, ModelDataSourceStrategy } from '@aws-amplify/graphql-transformer-interfaces';
import { DeploymentResources, testTransform, TransformManager } from '@aws-amplify/graphql-transformer-test-utils';
import { parse } from 'graphql';
import { ConversationTransformer } from '..';
import { BelongsToTransformer, HasManyTransformer, HasOneTransformer } from '@aws-amplify/graphql-relational-transformer';
import * as fs from 'fs-extra';
import * as path from 'path';
import { Code, Function, IFunction, Runtime } from 'aws-cdk-lib/aws-lambda';
import { GenerationTransformer } from '@aws-amplify/graphql-generation-transformer';
import * as fs from 'fs-extra';
import { parse } from 'graphql';
import { toUpper } from 'graphql-transformer-common';
import * as path from 'path';
import { ConversationTransformer } from '..';

const conversationSchemaTypes = fs.readFileSync(path.join(__dirname, 'schemas/conversation-schema-types.graphql'), 'utf8');

Expand Down Expand Up @@ -157,16 +157,6 @@ const getResolverResource = (mutationName: string, resources?: Record<string, an
return resources?.[resolverName];
};

const getResolverFnResource = (mutationName: string, resources: DeploymentResources): string => {
const resolverFnCode =
resources.rootStack.Resources &&
Object.entries(resources.rootStack.Resources).find(([key, _]) => key.startsWith(`Mutation${toUpper(mutationName)}DataResolverFn`))?.[1][
'Properties'
]['Code'];

return resolverFnCode;
};

const defaultAuthConfig: AppSyncAuthConfiguration = {
defaultAuthentication: {
authenticationType: 'AMAZON_COGNITO_USER_POOLS',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ConversationFieldHandler } from '../transformer-steps/conversation-field-handler';
import { DirectiveNode, FieldDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { InvalidDirectiveError } from '@aws-amplify/graphql-transformer-core';
import { TransformerSchemaVisitStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { DirectiveNode, FieldDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { ConversationFieldHandler } from '../transformer-steps/conversation-field-handler';

describe('ConversationFieldHandler', () => {
let handler: ConversationFieldHandler;
Expand Down Expand Up @@ -55,8 +55,8 @@ describe('ConversationFieldHandler', () => {
const config = handler.getDirectiveConfig(parent, field, directive, mockContext);

expect(config).toBeDefined();
expect(config.messageModel).toBeDefined();
expect(config.conversationModel).toBeDefined();
expect(config.message).toBeDefined();
expect(config.conversation).toBeDefined();
});

it('should throw an error if field type is not ConversationMessage', () => {
Expand All @@ -74,12 +74,10 @@ describe('ConversationFieldHandler', () => {
const field = createMockField('testField', 'ConversationMessage');
const directive = createMockDirective();

const config = handler.getDirectiveConfig(parent, field, directive, mockContext);
const { messageModel } = config.messageModel;
const { conversationModel } = config.conversationModel;
const { message, conversation } = handler.getDirectiveConfig(parent, field, directive, mockContext);

expect(messageModel.name.value).toBe('ConversationMessageTestField');
expect(conversationModel.name.value).toBe('ConversationTestField');
expect(message.model.name.value).toBe('ConversationMessageTestField');
expect(conversation.model.name.value).toBe('ConversationTestField');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { DataSourceProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { DirectiveNode, FieldDefinitionNode, InputObjectTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { ConversationModel } from './graphql-types/conversation-model';
import { MessageModel } from './graphql-types/message-model';
import { Tool } from './tools/process-tools';

/**
* Configuration for the Conversation Directive
*/
export type ConversationDirectiveConfiguration = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidating directive configuration relevant types here.

// From the GraphQL Schema
parent: ObjectTypeDefinitionNode;
field: FieldDefinitionNode;
directive: DirectiveNode;

// Raw Directive Input
aiModel: string;
systemPrompt: string;
inferenceConfiguration: ConversationInferenceConfiguration | undefined;
tools: ToolDefinition[];
/**
* Custom handler function name.
*
* @deprecated Replaced by 'handler'
*/
functionName: string | undefined;
handler: ConversationHandlerFunctionConfiguration | undefined;

// Generated within the Conversation Transformer
toolSpec: Tool[] | undefined;
conversation: ConversationModel;
message: MessageModel;
assistantResponseMutation: { field: FieldDefinitionNode; input: InputObjectTypeDefinitionNode };
assistantResponseSubscriptionField: FieldDefinitionNode;
dataSources: ConversationDirectiveDataSources;
};

/**
* Conversation Directive Handler Function Configuration
*/
export type ConversationHandlerFunctionConfiguration = {
functionName: string;
eventVersion: string;
};

/**
* Conversation Directive Inference Configuration
*/
export type ConversationInferenceConfiguration = {
maxTokens?: number;
temperature?: number;
topP?: number;
};

/**
* Conversation Directive Tool Definition
*/
export type ToolDefinition = {
name: string;
description: string;
};

/**
* Conversation Directive Data Sources
*/
export type ConversationDirectiveDataSources = {
lambdaFunctionDataSource: DataSourceProvider;
messageTableDataSource: DataSourceProvider;
conversationTableDataSource: DataSourceProvider;
};
Loading
Loading