2024年8月9日

GPT Actions 库 - AWS 中间件

这个特定的GPT Action提供了如何构建AWS Lambda函数的概述。本文档帮助用户设置一个受OAuth保护的AWS函数,以连接到GPT Action和示例应用程序。本示例使用AWS SAM(无服务器应用模型)来设置AWS堆栈。

价值: 用户现在可以利用ChatGPT的功能连接到AWS函数。这使您能够连接到AWS中的任何服务并在此运行代码/应用程序。这可以通过以下几种方式实现:

  • 访问第三方服务,如AWS Redshift、AWS DynamoDB、AWS S3等更多服务!
  • 允许对来自API的文本响应进行预处理(克服上下文限制,添加上下文或元数据作为示例)。
  • 支持返回文件而非从第三方API获取文本。这对于展示用于数据分析的CSV文件,或返回PDF文件让ChatGPT将其视为上传文件处理非常有用。

示例用例:

  • 用户需要在Redshift中查询数据,但需要一个位于ChatGPT和Redshift之间的中间件应用来返回文件(用于确保数据分析准确性以及处理大量数据)
  • 用户已在AWS函数中构建了多个步骤,需要通过ChatGPT来启动该流程。

在开始之前,请确保您拥有一个AWS控制台,并具备创建以下资源的权限:Lambda函数、S3存储桶、应用堆栈、Cognito用户池、Cognito用户池应用客户端、API网关、Lambda角色、CloudFormation堆栈(虽然看起来很多,但这些服务的创建都是自动化的!)。

要创建AWS函数,您可以使用AWS SAM。一个SAM模板的示例可以在这里 [0]找到。

此模板包含:

  • 用户池和用户池客户端,用于OAuth
  • 一个Cognito授权器,确保该功能只能由经过身份验证的用户调用
  • 将Lambda函数映射到现有VPC(可用于连接其他AWS服务)
  • 具有可动态设置的参数(例如:凭证/变量)
  • 一个API网关,将HTTP路由映射到函数

这段代码仅供信息参考,帮助您入门,不需要预先拥有AWS资源。我们建议如果您已有用户池,请映射现有用户池而非创建新的,同时将Lambda设置在可访问其他AWS资源的VPC中(如需利用这些资源)。您可以在RedShift食谱中查看此类设置的示例。

Cognito授权器是确保您的函数只能被已认证用户调用/访问的关键,因此请确保根据您的环境正确设置它。

[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

你可以克隆openai-cookbook仓库并从lambda-middleware目录获取示例Python代码和SAM模板:

git clone https://github.com/pap-openai/lambda-middleware
cd lambda-middleware

要构建并部署您的函数,请在此目录下运行以下命令

sam build
sam deploy --template-file template.yaml --stack-name aws-middleware --capabilities CAPABILITY_IAM

部署完成后,您可以在AWS Lambda上查看应用程序:

../../../images/aws_lambda_1.png

您可以通过运行未经身份验证的curl命令来确认该功能在未认证状态下不可访问:

curl -d {} <middleware_api_output_url_from_deploy_command>

应该返回 {"message":"Unauthorized"}

可选:仅当您创建了用户池且未使用现有用户池时执行这些步骤

让我们在新创建的用户池中创建一个用户。为此,请获取部署命令中CognitoUserPoolArn的输出,并提取"/"后面的值,其格式应为: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"

现在让我们确保创建一个可以登录的网页/域名。前往AWS Cognito,选择新创建的用户池并进入应用集成选项卡:

../../../images/aws_lambda_3.png

点击"域名"然后"创建Cognito域名"来创建Cognito域名

../../../images/aws_lambda_8.png

向下滚动到用户池的应用集成页面上的App client list

../../../images/aws_lambda_9.png

选择您的应用客户端并编辑托管用户界面:

../../../images/aws_lambda_10.png

并添加回调URL、授权方案和OAuth范围:

../../../images/aws_lambda_11.png

请注意,当ChatGPT为你的操作认证生成回调URL时,你需要回到这一步。Postman URL仅应用于开发目的。

你可以在Postman中尝试此连接,在的授权部分,从AWS复制/粘贴client_id、client_secret的值以及你为认证域设置的URL,确保在scope中添加openid以获取有效的access_token:

../../../images/aws_lambda_12.png

../../../images/aws_lambda_13.png

如果你现在正在Postman上发起请求,使用你刚刚获取的access_token,将会返回一个成功的JSON响应:

../../../images/aws_lambda_14.png

现在让我们将这个集成到ChatGPT中。

创建一个动作并复制粘贴以下规范:

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

如果您尝试测试该操作(可以点击"Test"按钮),您会看到由于未通过身份验证而返回401错误。

现在让我们在操作中添加身份验证。

点击认证 > OAuth。 我们现在需要获取AWS Cognito的变量。请进入您的用户池 > 用户池应用客户端。在那里您可以获取您的客户端ID和客户端密钥。

../../../images/aws_lambda_15.png

将这些值复制粘贴到ChatGPT中。现在让我们添加Token URL。

在您的用户池中,您将找到之前为托管域名创建的URL。

../../../images/aws_lambda_16.png

我们将获取此URL并附加AWS routes for OAuth

  • token: /oauth2/token
  • 授权: /oauth2/authorize

将这些内容复制粘贴到ChatGPT中。

在范围内,添加openid并点击保存。

现在回到你的GPT(退出操作子视图),你会看到ChatGPT为认证提供的回调URL:

../../../images/aws_lambda_17.png

获取此URL并编辑您用户池应用客户端的托管UI界面,然后保存更改:

../../../images/aws_lambda_18.png

你现在可以再次测试这个操作:

../../../images/aws_lambda_19.png

您将被重定向到AWS Cognito页面,可以使用之前设置的凭据登录。

如果你现在让GPT执行相同的操作,它会正确回答,因为你现在已经通过身份验证,可以运行这个函数了!

../../../images/aws_lambda_20.png

您现在已经设置了一个ChatGPT中的动作,可以通过认证方式与您的AWS应用程序进行对话!本指南向您展示了如何从头开始使用用户名/密码创建Cognito池,不过我们建议根据您的需求来设置Cognito(例如通过将您自己的IDP接入Cognito)。

此外,该函数未连接任何其他服务,其优势在于能够以安全的方式与AWS Lambda函数通信。因此,您可以根据需要调整代码和AWS SAM模板。更复杂函数的示例是Redshift,它遵循相同的步骤来创建函数和身份验证,但具有不同的代码/部署方式。