## 1.简介
ChatGPT 是目前非常热门的人工智能(AI)自然语言处理应用工具。它能够通过学习和理解人类的语言来进行对话,可广泛应用于客服聊天机器人、问答系统、虚拟个人助手等应用。它还被用于模仿人类生成多种格式的文本,包括对话,讲故事,新闻文章等。ChatGPT 因其能够理解自然语言,生成高质量,连贯的文本和有意义的响应而获得公众和研究界的赞誉褒奖。接下来我们将演示如何使用 Amazon Lambda 等[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)计算产品,以及 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 构建一个[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)的、低成本的 Web 应用程序作为你的个人 AI 助手。本项目中使用的所有服务都涵盖在亚马逊云科技提供的免费服务套餐中。用到的亚马逊云科技服务有:
* [Amazon API Gateway](https://www.amazonaws.cn/api-gateway/)
* [Amazon Lambda](https://www.amazonaws.cn/lambda/)
* [Amazon S3](https://www.amazonaws.cn/s3)
* [Amazon DynamoDB](https://www.amazonaws.cn/dynamodb)
你也可以在 <https://www.amazonaws.cn/free/> 查看免费套餐的详细信息。
## 2.整体架构
* 使用 **[Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail)** 存储桶托管前端客户端的 Html、JS、CSS 文件。
* 使用 **[Amazon API Gateway](https://aws.amazon.com/cn/api-gateway/?trk=cndc-detail)** 将前端请求从客户端路由到后端服务。
* 后端服务部署在 **Amazon Lambda** 之上,其中包括 API 鉴权功能,用户登录的功能,处理来自客户端的聊天会话的请求并调用 OpenAI SDK 以从 OpenAI 服务器获取响应文本返回给客户端。
* 创建一个 **[Amazon DynamoDB](https://aws.amazon.com/cn/dynamodb/?trk=cndc-detail)** 表来存储登陆用户名和密码,用于用户登录的基本授权。
![image.png](https://dev-media.amazoncloud.cn/bd80ab5b28904821a938d363dd7a24fc_image.png "image.png")
## 3.先决条件
* 首先你需要自行创建一个 OpenAI 帐户,或者使用已有 OpenAI 账户,并在后台生成一个 API 密钥。后面在使用 OpenAI 的 API 时需要传入这个密钥。
![image.png](https://dev-media.amazoncloud.cn/2a533eddf5d54e8292be40cd2d8800a5_image.png "image.png")
<!--StartFragment-->
* 亚马逊云科技的帐户。如果你的帐户可以享受亚马逊云科技提供的**免费套餐**,那么在免费套餐配额范围内的费用将为 0。
## 4.设置本地环境
* 安装 Nodejs(如果已经安装了,请跳过此步)
本次演示应用的前后端采用 Nodejs 开发,因此需要在本地环境中安装 [Nodejs](https://nodejs.org/en/download/),用于编译静态网页文件和 Amazon Lambda 函数的依赖包。
## 5.获取源代码并构建包
- 从 github 下载代码包到本地。
```
>git clone https\\://github.com/aws-samples/aws-serverless-openai-chatbot-demo.git
```
该项目文件夹结构为:
![image.png](https://dev-media.amazoncloud.cn/857a1299ce7c4c5ebad4af6eba139a6a_image.png "image.png")
server 文件夹包含后端 lambda 函数的代码。client 文件夹包含前端网页的代码。
* 分别转到 server 文件夹下的各个 lambda 函数文件夹,安装依赖项并打包制作 . zip 文件,以上传到 Amazon Lambda。例如,要制作 zip,则使用以下命令:
```
>cd server/lambda_login
>npm install
>zip -r lambda_login.zip .
```
* 本演示应用需要创建 3 个 Amazon Lambda 函数,所以总共需要创建 3 个 . zip 文件:
1. ***lambda_auth.zip***
2. ***lambda_login.zip***
3. ***lambda_chat.zip***
## 6.创建 Lambda 函数
### 6.1 创建一个 Lambda 函数来处理聊天会话
* 在亚马逊云科技 Lambda 控制台中,从头开始创建一个名为 ***openai-chat*** 的函数,选择 **Node.js** 作为运行时。(*备注:如果您使用带有 M1/M2 芯片的 Mac 在本地构建 NodeJS 依赖项,请记住选择“arm64”作为架构选项。*)
![image.png](https://dev-media.amazoncloud.cn/f5afb023b80b4719bd6f63c473c9543c_image.png "image.png")
* 将上一步创建的 ***lambda_chat.zip*** 上传到 Lambda 代码源。
![image.png](https://dev-media.amazoncloud.cn/d4305b67f6354352b40d89e6ffc694ed_image.png "image.png")
<!--StartFragment-->
* 在环境变量中,创建”***OPENAI_API_KEY***“的键,并将自己的 OpenAI API KEY 配置成值。
<!--EndFragment-->
<!--StartFragment-->
![](https://s3.cn-north-1.amazonaws.com.cn/awschinablog/build-your-own-chatgpt-using-serverless-products-such-as-amazon-lambda6.png)
<!--EndFragment-->
![image.png](https://dev-media.amazoncloud.cn/d26b08f210ff4f98a9176b05f16cdb40_image.png "image.png")
* OpenAI 的接口的响应时间往往会超过 3 秒,因此要请将这个 lambda 函数的超时设置更改为更大的值,**如1分钟**。
![image.png](https://dev-media.amazoncloud.cn/fe40cf6b924e47bab047303665ffb8ef_image.png "image.png")
### 6.2 创建一个 Lambda 函数,用于 Amazon API Gateway 请求鉴权
* 在亚马逊云科技 Lambda 控制台中,从头开始创建一个名为 ***chat-authorizer*** 的 Lambda 函数,选择 Node.js 作为运行时。
![image.png](https://dev-media.amazoncloud.cn/534090a76307424aa7c19b583373f286_image.png "image.png")
* 在环境变量中配置一个名为“***TOKEN_KEY***”的环境变量,自定义一个值,该值将作为 JWT 签名密钥。
![image.png](https://dev-media.amazoncloud.cn/5694b405255c4a078961897f2bfd68d1_image.png "image.png")
* 将之前创建的 ***lambda_auth.zip*** 文件上传到 Lambda 代码源(与创建 open-chat 步骤相同)。
### 6.3 创建一个 Lambda 函数来处理用户登录请求
* 在亚马逊云科技 Lambda 控制台中,从头开始创建一个名为 ***openai-login*** 的 lambda 函数,选择 Node.js 作为运行时。
![image.png](https://dev-media.amazoncloud.cn/71d24d15a5de4664bf354fec5d7aaba6_image.png "image.png")
* 添加 ***TOKEN_KEY*** 环境变量(与 chat-authorizer 相同):
![image.png](https://dev-media.amazoncloud.cn/8c7ca5d8ff9a450c882ea6bfe48ab512_image.png "image.png")
* 此函数将调用 DynamoDB 的 API 来验证用户名和密码,因此我们需要附加 ***[Amazon DynamoDB](https://aws.amazon.com/cn/dynamodb/?trk=cndc-detail)ReadOnlyAccess*** 策略或为此函数的执行角色创建访问 DynamoDB 的**内联策略**。
![image.png](https://dev-media.amazoncloud.cn/5faccba9e92241babe8856cebf0300b9_image.png "image.png")
* 将之前创建的 ***lambda_login.zip*** 文件上传到 Lambda 代码源(与创建 open-chat 步骤相同)。
## 7. 创建 API Gateway
### 7.1 创建一个名为“***chatbot***”的 HTTP API
![image.png](https://dev-media.amazoncloud.cn/e74e5d14f88c4ce78f559874dd6f4194_image.png "image.png")
### 7.2 创建两个 POST 方法的路由:**/chat,/login**
![image.png](https://dev-media.amazoncloud.cn/bbc3c750342f471bba2d6aa523df4052_image.png "image.png")
### 7.3 对于 /chat 路由,创建 Lambda 授权方,以及集成到 Lambda 函数
* 创建一个 Lambda 授权方,在 Lambda 函数字段中,选择你之前创建的”***chat-authorizer***“函数。
![image.png](https://dev-media.amazoncloud.cn/3e6b177940c8432ba30fa7509cf5a262_image.png "image.png")
* 创建并附加一个 Lambda 集成,集成目标是之前创建的***“openai-chat”***函数。
![image.png](https://dev-media.amazoncloud.cn/1d1d9e2fc71b4b748cdb275f09ce05d0_image.png "image.png")
### 7.4 对于 /login 路由,创建并附加一个 Lambda 集成,集成目标是之前创建的“*openai-login*”函数
![image.png](https://dev-media.amazoncloud.cn/0d2db18ad8b54115920a810fee771706_image.png "image.png")
### 7.5 设置 CORS 配置如下
![image.png](https://dev-media.amazoncloud.cn/26ce52df4cd048329438dfcc1701dac6_image.png "image.png")
## 8. 创建 DynamoDB 表
本演示应用使用 [Amazon DynamoDB](https://aws.amazon.com/cn/dynamodb/?trk=cndc-detail) 存储用户名和密码凭证。为了简化演示,暂未实现注册功能和密码加密存储功能,你可以直接将用户和明文密码添加到 Dynamo 的表中。或者你可以参考代码包中的 Amazon CLI。
* 登录并打开 [Amazon DynamoDB](https://aws.amazon.com/cn/dynamodb/?trk=cndc-detail) 控制台,创建一个表名 ***chat_user_info***,分区键名为 ***username***,字符串类型。
![image.png](https://dev-media.amazoncloud.cn/9158c418b6e84d03b0584e147ca07fd1_image.png "image.png")
* 将你的用户名和密码对添加到表中。添加一个字符串类型的新属性“***password***”,用于存放用户对应的密码。
![image.png](https://dev-media.amazoncloud.cn/2e966ec909ad484fbba168460349884e_image.png "image.png")
## 9. 部署 S3 托管网站
### 9.1 创建 S3 存储桶,并启用静态网站托管功能
*详情可参考:*[*https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html*](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html)
将存储桶配置为静态网站时,必须启用静态网站托管、配置索引文档并设置权限。
* 在 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 控制台上创建一个名为 **Bucket-name(请替换成自己的存储桶名称**)的 S3 存储桶。
<!---->
* 在“**属性**”选项卡中启用此存储桶的静态网站托管功能。在**索引文档**中,输入索引文档的文件名 `index.html`。
![image.png](https://dev-media.amazoncloud.cn/b28a2f9b07f0418ea4ff7dd583546ddf_image.png "image.png")
* 默认情况下,S3 存储桶会阻止公共访问。你需要在“**权限**”选项卡中更改设置。
![image.png](https://dev-media.amazoncloud.cn/3641cffaf1b04f6bb6c48c91865ebe71_image.png "image.png")
* 并将以下策略(请修改 bucket-name 为实际存储桶名称)添加到存储桶策略以允许能从 internet 访问。
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws-cn:s3:::Bucket-Name/*"
]
}
]
}
```
### 9.2 编译网站静态文件
* 在本地环境中,转到 client/src/commons 文件夹,将 `apigw.js` 的第一行更改为你创建的实际的 API gateway 端点。
![image.png](https://dev-media.amazoncloud.cn/22ede8bf81f746619432c734e122f771_image.png "image.png")
* 在 client 目录下,然后运行这些命令来编译静态网站的文件。
```
>cd client
>npm install
>npm run build
```
“npm run build”命令运行完成后,它将在 client 文件夹中生成一个名为“build”的文件夹。该文件夹包含了要部署到 [Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 网站的所有静态文件。
![image.png](https://dev-media.amazoncloud.cn/c5302b6421b94e218716778d941ac349_image.png "image.png")
你可以通过 S3 控制台将此文件夹上传到存储桶亚马逊云科技或使用 Amazon CLI,如下所示:
```
>aws s3 sync ./build/ s3://bucket-name/
```
* 完成所有步骤后,现在您可以在 PC /Mobile 浏览器中访问 S3 网站,并使用你预先设置在 DynamoDB 表中的用户名和密码来登录进入。[Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail) 静态托管网站的访问端点可以在“属性”选项卡中找到。
![image.png](https://dev-media.amazoncloud.cn/48539d8ed4fe4c3cb25b403030dcf0e2_image.png "image.png")
![image.png](https://dev-media.amazoncloud.cn/0f08d2bf6b0c40c686b3c33afb5d87e8_image.png "image.png")
**本篇作者**
![image.png](https://dev-media.amazoncloud.cn/4c94b94f6b9e42028b8f3ed07486c74b_image.png "image.png")
谢川
亚马逊云科技项目经理,负责云服务在中国的部署以及客户体验改进。曾在通信,电商,互联网等行业有多年的产品设计和开发经验,并且拥有多个AI应用方面的发明专利。
![image.png](https://dev-media.amazoncloud.cn/cfe217721f73485b94ed42d643c6b782_image.png "image.png")
关宇
亚马逊云科技项目经理,负责云服务在中国的部署以及客户体验改进。拥有多年产品设计和研发经验。