はじめに
最近話題になっているChatGPTを使ってチャットボットを簡単に作れないかと思い試してみました。
チャットボットはCisco Webexのbotを使用し、ロジックはAWSのLambdaに記述しました。ChatGPTはAPIが用意されていないようなので、今回はGPT-3等のモデルが使えるOpenAIのAPIを使用しています。
OpenAIのAPIを使用するには、アカウントを作成しAPIキーを取得する必要があります。今回は初回に割り当てられる$18.00分のフリートライアルを使用します。
AWSの各リソースにはそれぞれ利用料金が発生します。
手順
- 開発環境の準備
- Bot logicの作成
- Cisco Webex Botの作成
- AWS Lambdaの準備
- AWS API Gatewayの準備
- CIsco Webex webhookの作成
開発環境の準備
AWSで開発環境として Cloud9 を準備します。
AWS Cloud9
マネジメントコンソールのCloud9の作成画面から Name を入力し、Environment type で New EC2 instance を選択します。
Instance type は t2.micro 、 Platform は Ubuntu Server 18.04 LTS を選択し、Create をクリックします。作成できれば、Open in Cloud9 からIDEを起動させます。
Bot logicの作成
AWS Lambdaには、Bot logicのコードそのものと関連するライブラリをzipでパッケージにしてデプロイします。
プロジェクトディレクトリを作成し、そこにライブラリをインストールしBot logicも配置します。今回はLambdaに対応しているpython3.9を使用するので、python3.9のコンテナ上でプロジェクトディレクトリを作成しライブラリをインストールした後、そのプロジェクトディレクトリをホストOSに docker cp
でコピーします。ホストOSでプロジェクトディレクトリにBot logicを作成し、ライブラリもまとめてzip化することでデプロイパッケージを作成します。
1. ライブラリのインストール
Cloud9のターミナルでpython3.9のコンテナを起動し、そのコンテナ上でプロジェクトディレクトリを作成、ライブラリをインストールします。ライブラリは openai 、 webexteamssdk を使用します。
openai: OpenAI APIへのアクセスを提供するライブラリ(ドキュメント)
webexteamssdk: Cisco webex APIへのアクセスを提供するライブラリ(ドキュメント)
cloud9 $ docker run -itd --name py3.9 python:3.9
py3.904279f704823ce0bd12d7e21e4cf81c603b4918c2c6b2205d258
cloud9 $ docker exec -it py3.9 bash
root@py3.9:/# cd
root@py3.9:~# mkdir webex_chatgpt #プロジェクトディレクトリの作成
root@py3.9:~# cd webex_chatgpt/
root@py3.9:~/webex_chatgpt# mkdir package #ライブラリをインストールするpackageディレクトリの作成
root@py3.9:~/webex_chatgpt# pip3 install --target ./package openai #openaiライブラリのインストール
Collecting openai
Downloading openai-0.25.0.tar.gz (44 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 44.9/44.9 KB 7.0 MB/s eta 0:00:00
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Collecting tqdm
Downloading tqdm-4.64.1-py2.py3-none-any.whl (78 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 78.5/78.5 KB 14.1 MB/s eta 0:00:00
(snip)
root@py3.9:~/webex_chatgpt# pip3 install --target ./package webexteamssdk #webexteamssdkライブラリのインストール
Collecting webexteamssdk
Downloading webexteamssdk-1.6.1-py3-none-any.whl (113 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 113.5/113.5 KB 12.6 MB/s eta 0:00:00
Collecting PyJWT
Downloading PyJWT-2.6.0-py3-none-any.whl (20 kB)
(snip)
root@py3.9:~/webex_chatgpt# exit
exit
cloud9 $ docker cp py3.9:/root/webex_chatgpt ./ #コンテナ上のプロジェクトディレクトリをホストOSへコピー
cloud9 $ cd webex_chatgpt/package/
cloud9:~/environment/webex_chatgpt/package $ zip -r ../my-deployment-package.zip . #ライブラリのzip化
adding: urllib3/ (stored 0%)
adding: urllib3/connection.py (deflated 71%)
adding: urllib3/connectionpool.py (deflated 73%)
(snip)
cloud9:~/environment/webex_chatgpt/package $ cd ../
cloud9:~/environment/webex_chatgpt $ touch lambda_function.py #Bot logicファイルを作成
2. Bot logic
Cloud9のIDEでlambda_function.pyというファイル名でBot logicを作成します。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import openai
import os
from webexteamssdk import WebexTeamsAPI, Webhook
MESSAGE_WEBHOOK_RESOURCE = "messages"
MESSAGE_WEBHOOK_EVENT = "created"
openai.api_key = os.environ["OPENAI_SECRET_KEY"]
def chatgpt(prompt, room, api):
response = openai.Completion.create(
model="text-davinci-003",
prompt=prompt,
temperature=0.6,
max_tokens=150,
top_p=1,
frequency_penalty=1,
presence_penalty=1
)
api.messages.create(
room.id,
markdown=response["choices"][0]["text"]
)
def respond_to_message(webhook, api, me):
room = api.rooms.get(webhook.data.roomId)
message = api.messages.get(webhook.data.id)
if message.personId == me.id:
return "OK"
else:
chatgpt(message.text, room, api)
return "OK"
def lambda_handler(event, context):
api = WebexTeamsAPI()
me = api.people.me()
webhook_obj = Webhook(event["body"])
if (webhook_obj.resource == MESSAGE_WEBHOOK_RESOURCE and webhook_obj.event == MESSAGE_WEBHOOK_EVENT):
respond_to_message(webhook_obj, api, me)
else:
print(f"IGNORING UNEXPECTED WEBHOOK:\n{webhook_obj}")
return "OK"
Bot logicファイルをzipパッケージに追加します。
cloud9:~/environment/webex_chatgpt $ zip -g my-deployment-package.zip lambda_function.py #Bot logicファイルをzipパッケージに追加
adding: lambda_function.py (deflated 55%)
Cisco Webex Botの作成
Bot logicが完成したので、Webex for Developersで Bot を作成します。
Webex for DevelopersでBotを作成します。Start Building Apps から作成画面へ移ります。
Bot を選択します。
Bot name 、Bot username を入力、Icon を選択し、Add Bot をクリックします。
Botが作成できれば、 Bot access token をコピーしておきます。
AWS Lambdaの準備
Bot logicの実行環境として Lambda を準備します。
1. AWS Lambda関数の作成
Lambda の 関数の作成 から関数を作成します。
一から作成 を選択し、関数名 を入力、ランタイム で Python 3.9 を選択します。
あとはデフォルト設定のまま 関数の作成 をおクリックします。
関数の作成が完了すれば、設定 タブ から 一般設定 の編集をクリックします。
タイムアウト を1分に伸ばします。
環境変数 にOpenAIのサイトにログインすれば取得できる OpenAIのAPIキー と、Bot作成時に取得した Bot access token を設定します。これらの値はBot logicのコードから環境変数を通して参照します。
OPENAI_SECRET_KEY: { OpenAIのAPIキー }
WEBEX_TEAMS_ACCESS_TOKEN: { Bot access token }
2. デプロイパッケージのアップロード
CLoud9のターミナルからawsコマンドでデプロイパッケージをLambdaへアップロードします。
cloud9:~/environment/webex_chatgpt $ aws configure set default.region ap-northeast-1 #デフォルトリージョンの設定
cloud9:~/environment/webex_chatgpt $ aws lambda update-function-code --function-name webex_bot --zip-file fileb://my-deployment-package.zip
{
"FunctionName": "webex_bot",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:************:function:webex_bot",
"Runtime": "python3.9",
"Role": "arn:aws:iam::************:role/service-role/webex_bot-role-q8fpg7c4",
"Handler": "lambda_function.lambda_handler",
"CodeSize": 43060227,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2022-12-07T00:36:00.000+0000",
"CodeSha256": "L4Gfp9QcYw+Avxgy0ofhhenTznkV6mpof9NIrokvPJs=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "7c584c75-77c7-4b86-a778-************",
"State": "Active",
"LastUpdateStatus": "InProgress",
"LastUpdateStatusReason": "The function is being created.",
"LastUpdateStatusReasonCode": "Creating",
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
}
}
AWS API Gatewayの準備
LambdaのAPIとして API Gateway を準備します。
API Gateway の 作成画面から REST API の構築を選択します。
プロトコルは REST 、APIの作成は 新しいAPI を選択、 API名 は任意の名前を入力し、 エンドポイントタイプ はリージョンを選択し、 APIの作成 をクリックします。
アクション から リソースの作成 をします。
リソース名 に message を入力し リソースの作成 をクリックします。
アクション から メソッドの作成 をします。
POST を選択します。
統合タイプ は Lambda関数 、 Lambdaプロキシ統合の使用 を有効化、 Lambdaリージョン は ap-northeast-1 、 Lambda関数 には作成したLambda関数の名前をそれぞれ設定します。
アクション から APIのデプロイ をします。
新しいステージ を選択し、任意の ステージ名 を入力します。今回は prod ステージを作成しました。
POST メソッドの 呼び出しURL をコピーしておきます。
CIsco Webex webhookの作成
Webex for Developersで webhook の準備します。
Webex for Developersにログインし、ドキュメントページの左ペインから APIs => Webex APIs => Messaging => Reference => Webhooks => POST Create a Webhook を選択します。
右ペインの Webhook 作成画面に下記のようにパラメータを入力し Run します。
- Authorization:
- Use personal access tokenを無効にし、Bot作成時にコピーしておいた Bot access tokenをペーストします。
- name:
- 任意のWebhook名を入力します。
- targetUrl:
- API Gateway作成時にコピーしておいたPOSTメソッドの呼び出しURLをペーストします。
- resource:
- messagesと入力します。
- event:
- createdと入力します。
実行
Webexで作成したBotに対してダイレクトメッセージを送ります。
答えが最適かどうかは置いておいて、ちゃんと返信してくれました。
まとめ
認証や、ヘッダー、ボディー、メソッドなどAPIアクセスのコードは少し煩雑になりがちですが、openaiや、webexteamssdkなどライブラリを使えばAPIアクセスのコードを非常に簡単にシンプルに作成することができました。どちらもわかりやすいドキュメントも用意されいてとても便利でした。
WebexのWebhookはアダプティブカードにも対応しているので使い道は無限大にあり、とても便利なツールとしてよく使わせてもらっています。