|
| 1 | +# AI Chat Application using AWS AppSync (WebSockets), AWS Lambda, and Amazon Bedrock. |
| 2 | + |
| 3 | +This AI chat application works through a simple request-response flow. A client sends a GraphQL mutation to the AWS AppSync API endpoint. AWS AppSync then routes the request to the AWS Lambda function via the configured data source and resolver. The AWS Lambda function receives the user's input message, then constructs a properly formatted request for Amazon Bedrock's Claude model (including the Anthropic API version, token limit, and user message). This is then sent to Amazon Bedrock using the AWS SDK, waits for the AI response, and returns the generated text back to AWS AppSync. AWS AppSync then delivers this response to the client, while the subscription feature enables real-time notifications to connected clients when new responses are available, creating an interactive chat experience where users can send messages and receive AI-generated replies in real-time. |
| 4 | + |
| 5 | + |
| 6 | +Learn more about this pattern at [Serverless Land Patterns](https://serverlessland.com/patterns/appsync-ws-lambda-bedrock-sam) |
| 7 | + |
| 8 | +Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. |
| 9 | + |
| 10 | +## Prerequisites |
| 11 | + |
| 12 | +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. |
| 13 | +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured |
| 14 | +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) |
| 15 | +* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed |
| 16 | +* [NOTE! Manage Access to Amazon Bedrock Foundation Models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) |
| 17 | + |
| 18 | + |
| 19 | +## Deployment Instructions |
| 20 | +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: |
| 21 | + ``` |
| 22 | + git clone https://github.com/aws-samples/serverless-patterns |
| 23 | + ``` |
| 24 | +2. Change directory to the pattern directory: |
| 25 | + ``` |
| 26 | + cd appsync-ws-lambda-bedrock-sam |
| 27 | + ``` |
| 28 | +3. Install dependencies |
| 29 | + ``` |
| 30 | + cd src && npm install && cd .. |
| 31 | + ``` |
| 32 | +4. From the command line, use AWS SAM build to prepare an application for subsequent steps in the developer workflow, such as local testing or deploying to the AWS Cloud: |
| 33 | + ``` |
| 34 | + sam build |
| 35 | + ``` |
| 36 | +5. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file: |
| 37 | + ``` |
| 38 | + sam deploy --guided |
| 39 | + ``` |
| 40 | +6. During the prompts: |
| 41 | + * Enter a stack name |
| 42 | + * Enter the desired AWS Region |
| 43 | + * Enter the desired ModelId |
| 44 | + * Enter the desired BedrockRegion |
| 45 | + * Allow SAM to create roles with the required permissions if needed. |
| 46 | +
|
| 47 | +7. Note the outputs **GraphQLAPIURL** and **GraphQLAPIKey** from the SAM deployment process. |
| 48 | +These contain the resource names and/or ARNs which are used for testing. |
| 49 | +
|
| 50 | +
|
| 51 | +## Architecture |
| 52 | + |
| 53 | +
|
| 54 | +
|
| 55 | +## How it Works |
| 56 | +Client Request Flow: |
| 57 | +1. Client sends a GraphQL mutation invokeModel(input: "user message") to the AppSync API endpoint using the provided API key. |
| 58 | +2. AppSync receives the mutation and routes it through the InvokeModelResolver to the LambdaDataSource. |
| 59 | +3. The resolver triggers the Lambda function, passing the user's input as event.arguments.input. |
| 60 | +
|
| 61 | +Lambda Processing: |
| 62 | +
|
| 63 | +4. Lambda function receives the event and extracts the user message from event.arguments.input. |
| 64 | +5. Creates a Bedrock request payload with Claude's required format: anthropic_version, max_tokens (1000), and the user message in a messages array. |
| 65 | +6. Uses BedrockRuntimeClient to send an InvokeModelCommand to the specified Claude model. |
| 66 | +7. Waits synchronously for Bedrock's response, then parses the JSON response and extracts the AI-generated text from result.content[0].text. |
| 67 | +
|
| 68 | +Response Delivery: |
| 69 | +
|
| 70 | +8. Lambda returns the AI text response to AppSync. |
| 71 | +9. AppSync delivers the response back to the client through the GraphQL mutation response. |
| 72 | +10. Clients subscribed to onModelResponse receive real-time notifications of new AI responses via WebSocket connections. |
| 73 | +
|
| 74 | +The architecture uses AppSync's built-in WebSocket capabilities for real-time subscriptions, eliminating the need for manual connection management. |
| 75 | +
|
| 76 | +## Testing |
| 77 | +
|
| 78 | +### Interactive Web Interface |
| 79 | +``` |
| 80 | +To use the test interface: |
| 81 | +1. Deploy the application using SAM |
| 82 | +2. Copy the GraphQLAPIURL Value and GraphQLAPIKey Value from the deployment outputs |
| 83 | +3. Open 'test.html' |
| 84 | +4. Update the 'API_URL' variable with your GraphQLAPIURL |
| 85 | +5. Update the 'API_KEY' variable with your GraphQLAPIKey |
| 86 | +6. Save 'test.html' |
| 87 | +7. Open the HTML file in a browser |
| 88 | +8. Click "Connect" to establish a WebSocket connection |
| 89 | +9. Type your message and click "Send" |
| 90 | +``` |
| 91 | +
|
| 92 | +### AWS AppSync Console |
| 93 | +* Go to AWS AppSync console → Your API → Queries |
| 94 | +* Use the built-in GraphQL explorer |
| 95 | +* Run this mutation: |
| 96 | +```bash |
| 97 | +mutation { |
| 98 | + invokeModel(input: "What is AWS Lambda?") |
| 99 | +} |
| 100 | +``` |
| 101 | + |
| 102 | +### Terminal using curl |
| 103 | +```bash |
| 104 | +curl -X POST \ |
| 105 | + -H "Content-Type: application/json" \ |
| 106 | + -H "x-api-key: YOUR_API_KEY" \ |
| 107 | + -d '{"query": "mutation { invokeModel(input: \"What is AWS Lambda?\") }"}' \ |
| 108 | + YOUR_GRAPHQL_API_URL |
| 109 | +``` |
| 110 | + |
| 111 | +## Cleanup |
| 112 | +1. Delete the stack |
| 113 | + ```bash |
| 114 | + sam delete |
| 115 | + ``` |
| 116 | +2. Confirm the stack has been deleted |
| 117 | + ```bash |
| 118 | + aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus" |
| 119 | + ``` |
| 120 | +---- |
| 121 | +Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 122 | + |
| 123 | +SPDX-License-Identifier: MIT-0 |
0 commit comments