AWS CDK: AppSync GraphQL API for Amazon Bedrock

October 30th, 2023 325 Words

Based on invoking Amazon Bedrock with AWS Lambda and Amazon API Gateway, you can adapt the AWS Cloud Development Kit example code to use AWS AppSync and GraphQL for accessing Amazon Bedrock.

Of course, using AWS AppSync, a simple GraphQL Schema is needed; simply configure a new Query for sending prompts to Amazon Bedrock:

type Query {
  prompt: String!
}

The existing AWS Lambda function, based on the example for Amazon API Gateway, can be adjusted to support AWS AppSync and supportive types:

import { AppSyncResolverHandler } from 'aws-lambda'
import { sendPrompt } from '../scripts/invoke.ts'

export interface HandlerArgument {}
export type HandlerResult = string

export const handler: AppSyncResolverHandler<
  HandlerArgument,
  HandlerResult
> = async () => {
  const response = await sendPrompt("Please generate a funny Haiku about software engineering.")

  return response.data.text.trim()
}

Wrapping this up with the AWS Cloud Development Kit, your AWS CloudFormation stack includes all required AWS resources with this code:


import { App, Stack, StackProps } from 'aws-cdk-lib';
import { AuthorizationType, Definition, GraphqlApi, LambdaDataSource, MappingTemplate } from 'aws-cdk-lib/aws-appsync';
import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { Tracing } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import { join } from 'path';

export class Components extends Stack {
  constructor(scope: App, id: string, props?: StackProps) {
    super(scope, id, props)

    const func = new NodejsFunction(this, 'invoke', {
      entry: 'aws/functions/invoke.ts',
      handler: 'handler',
      initialPolicy: [
        new PolicyStatement({
          effect: Effect.ALLOW,
          actions: ['bedrock:InvokeModel'],
          resources: ['*']
        })
      ],
      tracing: Tracing.ACTIVE,
    })

    const schema = Definition.fromFile(join(__dirname, 'schema.graphql'))

    const api = new GraphqlApi(this, 'graphql', {
      name: 'example',
      definition: schema,
      authorizationConfig: {
        defaultAuthorization: {
          authorizationType: AuthorizationType.API_KEY,
        },
      },
      xrayEnabled: true,
    });

    const source = new LambdaDataSource(this, 'source', {
      api,
      lambdaFunction: func,
    })
    
    source.createResolver('resolver', {
      typeName: 'Query',
      fieldName: 'prompt',
      requestMappingTemplate: MappingTemplate.lambdaRequest(),
      responseMappingTemplate: MappingTemplate.lambdaResult(),
    });
  }
}

Next, you can use the browser console to access your API:

AppSync Browser Console and Amazon Bedrock prompt

Adding a custom prompt argument to your GraphQL query could be a next step.

Programming is easy
Debugging is hard
Coffee helps a lot

Enjoy! 🎉