This particular GPT Action provides an overview of how to build an AWS Lambda function. This documentation helps a user set up an OAuth-protected AWS Function to connect to a GPT Action, and to a sample application. This example uses AWS SAM (Serverless Application Model) in this example to set-up the AWS stack.
Value: Users can now leverage ChatGPT's capabilities to connect to an AWS Function. This enables you to connect to any services in AWS and run code/applications on this. This can in a few ways:
Example Use Cases:
We will leverage AWS Lambda services to create a middleware function. You can get familiar with this stack by visiting the following links:
Before you get started, make sure you have an AWS Console with access to create: Lambda Function, S3 Buckets, Application Stack, Cognito User Pool, Cognito User Pool App Clients, API Gateway, Lambda roles, CloudFormation stacks (this feels like a lot but creating those services is automated!).
To create an AWS Function you can use AWS SAM. An example of a SAM Template can be found here [0].
This template includes:
This code is purely informational to help you get started and doesn't require pre-existing AWS resources. We recommend to map existing user pools if you have any instead of creating new ones, as well as setting up your Lambda in a VPC that has access to other AWS Resources (if you need to leverage those). You can see an example of a set-up like this in the RedShift cookbook.
The Cognito Authorizer is key to make sure your function can only be called/accessed by authenticated users so make sure to set this up correctly with your environment.
[0]
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-middleware
AWS middleware function
Parameters:
CognitoUserPoolName:
Type: String
Default: MyCognitoUserPool
CognitoUserPoolClientName:
Type: String
Default: MyCognitoUserPoolClient
Resources:
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Ref CognitoUserPoolName
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
MyCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: !Ref MyCognitoUserPool
ClientName: !Ref CognitoUserPoolClientName
GenerateSecret: true
MiddlewareApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
AuthorizationScopes:
- openid
- email
- profile
UserPoolArn: !GetAtt MyCognitoUserPool.Arn
MiddlewareFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: aws-middleware/
Handler: app.lambda_handler
Runtime: python3.11
Timeout: 45
Architectures:
- x86_64
Events:
SqlStatement:
Type: Api
Properties:
Path: /my_route
Method: post
RestApiId: !Ref MiddlewareApi
Outputs:
MiddlewareApi:
Description: "API Gateway endpoint URL for Prod stage for SQL Statement function"
Value: !Sub "https://${MiddlewareApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/my_route"
MiddlewareFunction:
Description: "SQL Statement Lambda Function ARN"
Value: !GetAtt MiddlewareFunction.Arn
MiddlewareFunctionIamRole:
Description: "Implicit IAM Role created for SQL Statement function"
Value: !GetAtt MiddlewareFunctionRole.Arn
CognitoUserPoolArn:
Description: "ARN of the Cognito User Pool"
Value: !GetAtt MyCognitoUserPool.Arn
You can clone the openai-cookbook repository & take the sample python code & SAM template from the lambda-middleware
directory:
git clone https://github.com/pap-openai/lambda-middleware
cd lambda-middleware
To build & deploy your function, run the following commands from this directory
sam build
sam deploy --template-file template.yaml --stack-name aws-middleware --capabilities CAPABILITY_IAM
Once you have this deployed, you can go check out the application on AWS Lambda:
You can confirm that the function is not reachable unless authenticated by running a curl command without any authentication:
curl -d {} <middleware_api_output_url_from_deploy_command>
which should return {"message":"Unauthorized"}
.
Optional: do those steps only if you created a user pool and are not using an existing one
Let's create a user in the newly user pool. To do that, fetch the output of CognitoUserPoolArn in the deploy command, and get the value after the "/", which should be in the format of: your-region_xxxxx
.
aws cognito-idp admin-create-user \
--user-pool-id "your-region_xxxxx" \
--username johndoe@example.com \
--user-attributes Name=email,Value=johndoe@example.com \
--temporary-password "TempPassword123"
Let's now make sure we create a webpage/domain on which we can log-in. Go to AWS Cognito, select the newly created user pool & go to App Integration tab:
Create a Cognito Domain by clicking on "Domains" then "Create Cognito Domain"
Scroll down to App client list
on the App Integration page of your User Pool:
Select your app client and edit the Hosted UI:
And add a callback URL, Authorization Scheme and OAuth scope:
Note that you'll come back to this step when ChatGPT will generate a callback URL for the authentication of your action. The postman URL, should be used only for development purpose.
You can try this connection in Postman, under Authorization for your <api_url>
, copy/paste the value from AWS for the client_id, client_secret and the URL you set up for the auth domain, make sure to add openid
in the scope to get a valid access_token:
If you're now doing the request on Postman, using the access_token you just retrieve, you'll get a success JSON returned:
Now let's integrate this into ChatGPT.
Create an action and copy paste the following spec:
openapi: 3.1.0
info:
title: Success API
description: API that returns a success message.
version: 1.0.0
servers:
- url: https://3ho5n15aef.execute-api.us-east-1.amazonaws.com/Prod
description: Main production server
paths:
/my_route:
post:
operationId: postSuccess
summary: Returns a success message.
description: Endpoint to check the success status.
responses:
'200':
description: A JSON object indicating success.
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
example: true
If you try to test the action (you can click the "Test" Button), you'll see that you have a 401 as you're not authenticated.
Let's now add authentication in the action.
Click on Authentication > OAuth. We'll now need to fetch AWS Cognito's variables. Let's go on your User Pool > User Pool App Client. From there you can retrieve your client ID and client Secret.
Copy paste those values in ChatGPT. Now let's add the Token URLs.
From your User Pool you'll find the URL you've previously created for the hosted domain.
We'll take this URL and append AWS routes for OAuth.
<your_url>/oauth2/token
<your_url>/oauth2/authorize
Copy paste those in ChatGPT.
In scope, add openid and click on Save.
Now go back on your GPT (moving out of the action subview), and you'll see a callback URL provided by ChatGPT for the Authentication:
Get this URL and edit the hosted UI of your User Pool App client & save the changes:
You can now test this action again:
You will be redirected to AWS Cognito page, which you can log-in in using the credentials previously set-up.
If you now ask the GPT to run the same action, it will answer correctly as you're now authenticated and able to run this function!
You've now set-up an action in ChatGPT that can talk with your applications in AWS, in an authenticated way! This cookbook shows you how to create the Cognito Pool from scratch using username/password, though, we recommend to set-up Cognito based on your needs (for example by plugging your own IDP into Cognito).
Additionally, the function is not connected to any other services, which is the advantage of being able to communicate to an AWS Lambda function in a safe way. You can therefore tweak the code and AWS SAM template to fit your need. An example of a more complex function is Redshift, that follows those steps to create the function and authentication but has a different code/deployment.