はじめに
最近ChatGPTが流行ってますよね。
筆者も論文の要約や検索、英語翻訳などに利用させていただいております。
そんなChatGPTのAPIが2023/3/1に一般公開されたとのことで、Slackから簡単に利用できるようにしたい!!ということでAWSの勉強も兼ねて実装してみました。
備忘録的に記事を書いてみます!
今回のシステムの簡単なアーキテクチャ図はこちらになります!!

実際に遊んでみるとこんな感じです笑

実装
早速ですが、実装について説明していきます。
ステップとしては以下の3つです。
1. OpenAIのAPIキーの取得
2. SlackAppの作成
3. SlackAppの機能実装(AWS)
1. OpenAIのAPIキーの取得
これがないとChatGPT APIが利用できません。
ということで、OpenAIにアクセスして、アカウントを作成しましょう。
作成が完了したら、右上のPersonalからView API keysをクリックします。

その後Create new secret keyをクリックして、API keyを作成します。(この際に生成されたkeyは一度しか見れないので、忘れないようにどこかにメモしておきましょう!!)

OpenAIのAPIキーについてはこれで完了です!!
2. SlackAppの作成
次はSlack上でユーザからのメッセージを受け取り、ChatGPTに流すためのSlack Appを作成します。
ここでは、Slack Appの作成のみにとどめ、具体的な機能実装については3.で説明します。
Slack Appsにアクセスし、Create New Appをクリックします。
その後、From scratchを選択します。
名前やWorkspaceに関しては自由に設定してください。

Webhook URLの作成
アプリの作成が完了したら、外部サービスからSlackにメッセージを送信するためのWebhook URLを作成します。
Add New Webhook to Workspaceをクリックし、メッセージを送信するチャンネルを選択します。
作成された、URLはアプリの機能実装で利用するのでメモしておきましょう!!

Event Subscriptionsの設定
Slackでは、ユーザのメッセージ送信などのイベントを受け取るために予めSubscribeするイベントを登録しておく必要があります。
以下の画像のように、ボットが追加されているチャンネルのメッセージ送信イベントを受け取るためにmessage.channelsイベントを登録するのですが、この操作を行うためにはイベントを送信するLambda関数の機能が必要となるため、後回しにします。

Slack Appをチャンネルに追加
作成したSlack Appをメッセージを送受信するためのチャンネルに追加しましょう。
Slackの追加したいチャンネルを開き左上にあるチャンネル名をクリックすると以下のような画面が出てきます。
そこでIntegrationsタブに移動し、AppsのAdd appsから作成したSlack Appを選択することでチャンネルに追加できます。
これをしていないと、Slack Appがメッセージを受信できないのでメッセージを送信しても何も反応してくれなくなります。

とりあえず、これでSlack Appの作成は完了です。
3. Slack Appの機能実装
ここから、Slack Appの機能実装に入っていきます!!
今回はAWS LambdaとAPI gateway、Cloud9を利用していきます。
参考にした記事は、AWSを使ったslackチャットbotの構築とCisco WebexとAWS LambdaでOpenAI GPT-3のチャットボットを作るになります。
AWS Cloud9
まずはAWS Cloud9を使って、AWS Lambdaにデプロイするためのzipファイルを作成します。
pythonのopenaiライブラリのような標準ライブラリ以外を用いたい場合はAWS Lambdaでpipを使うことができないため、ファイルアップロード機能を用いる必要があります。
【AWS】Lambda上のPythonで外部ライブラリを使用する方法のように様々な方法でアップロードは可能ですが、今回はコマンド一つでアップロード可能ということで、AWS Cloud9を利用しました。
AWS Cloud9の作成
AWSのCloud9の画面に行き、Create environmentをクリックすると、以下のような画面に遷移します。
適当な名前を入力し、createをクリックします。(その他の設定に関してはデフォルトのままでいいと思います。)

作成後は、インスタンスが立ち上がるまでに少し時間がかかると思います。
作成が完了し、EnvironmentsページからCloud9 IDEを開くためにOpenをクリックすると以下のような画面が出力されます。

ライブラリのインストール
openaiをインストールします。
まず、python3.9のコンテナを起動し、そのコンテナ上でプロジェクトディレクトリの作成、ライブラリのインストールを行います。
Cloud9 IDEのコンソール上で以下のコマンドを入力します。
# コンテナ作成
$ docker run -itd --name py3.9 python:3.9
# コンテナに入る
$ docker exec -it py3.9 bash
# ------コンテナ内------
$ cd
$ mkdir slack_chatgpt # プロジェクトディレクトリの作成
$ cd slack_chatgpt/
$ mkdir package #ライブラリをインストールするpackageディレクトリの作成
$ pip3 install --target ./package openai #openaiライブラリのインストール
$ exit #コンテナから出る
# ------コンテナ内------
$ docker cp py3.9:/root/slack_chatgpt ./ #コンテナ上のプロジェクトディレクトリをホストOSへコピー
$ cd slack_chatgpt/package/
$ zip -r ../my-deployment-package.zip . #ライブラリのzip化
$ cd ../
$ touch lambda_function.py #SlackAppの機能を実装するためのファイルを作成
Slack Appの機能を実装するpythonファイルの作成
ソースコードは以下の通りです。
基本的には、Slackメッセージの最初でSlack Appがメンションされているメッセージに対して、ChatGPTを用いた回答を返信するという機能となっています。
Slackからのリクエスト形式やChatGPTからのレスポンス形式を参考に実装しています。
import json
import urllib.request
import ssl
import logging
import openai
import os
openai.api_key = os.environ["OPENAI_API_KEY"]
# CloudwatchLogsのログ記憶ライブラリの使用
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
# CloudwatchLogsで詳細なログを取得
logging.info(json.dumps(event))
# Slack Events APIの再送回避(参考URL:https://dev.classmethod.jp/articles/slack-resend-matome/)
if "x-slack-retry-num" in event["headers"]:
return {"statusCode": 200}
# メッセージイベントのbodyを取得
body = json.loads(event["body"])
msg = ""
# Event Subscriptionsのチャレンジステータスを返す
if "challenge" in body:
return {
"statusCode": 200,
"body": body["challenge"],
"headers": {
"content-type": "text/plain"
}
}
elif "user" == body["event"]["blocks"][0]["elements"][0]["elements"][0]["type"]:
if os.environ["SLACK_APP_ID"] == body["event"]["blocks"][0]["elements"][0]["elements"][0]["user_id"]:
# メッセージの最初でSlackAppがメンションされていた場合
for block in body["event"]["blocks"]:
for elements in block["elements"]:
for element in elements["elements"]:
if element["type"] == "text":
# Slackのテキストやコードブロックなどを一つのmsgとして変数に格納
msg += element["text"]
# ChatGPTにリクエストを送信
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": msg}
]
)
logging.info(completion)
# ChatGPTからの返答をmsgに格納
return_msg = completion["choices"][0]["message"]["content"]
else:
return
# リクエストヘッダをJSONにする。
req_headers = {
"Content-Type": "application/json",
}
# JSONにメッセージをつめる。
req_json_slack = {
"text": return_msg
}
#リクエストを生成してSlackへ投げる。
req_slack = urllib.request.Request(os.environ["WEBHOOK_URL"], json.dumps(req_json_slack).encode(), req_headers)
urllib.request.urlopen(req_slack)
ファイル作成が完了したら、zipパッケージにlambda_function.pyを追加します。
$ zip -g my-deployment-package.zip lambda_function.py
このあとはLambdaの作業に移りますが、Cloud9からzipファイルのLambdaへのアップロードを行うのでCloud9 IDEは開いたままが良いと思います。
AWS Lambda
AWS Lambdaの作成
AWSのLambdaのページに行き、関数の作成を選択すると以下のような画面が出てきます。
適当な関数名とランタイムをpython3.9に設定して、関数の作成をクリックします。

#### 環境変数の設定
lambda_function.pyで使用している環境変数の設定を行います。
作成したLamdaの設定タブに移動して、編集ボタンをクリックして、設定を行います。
キーのOPENAI_API_KEYとWEBHOOK_URLはそれぞれ1. OpenAIのAPIキーの取得とWebhook URLの作成で作成したものを設定します。
SLACK_APP_IDは以下の画像のような画面がSlack上で作成したアプリをクリックすることで表示されるのでMember IDをコピーして設定します。

設定が完了すると以下のような画面になります。

ファイルのアップロード
ここで先程Cloud9で作成した、zipファイルをLambdaにアップロードします。
Cloud9のコンソールで以下のコマンドを入力します。(FunctionNameは自信がLambda作成時に設定した名前に置き換えてください)
aws lambda update-function-code --function-name <FunctionName> --zip-file fileb://my-deployment-package.zip
AWS API Gateway
AWSのAPI Gatewayのページに行き、APIを作成をクリックします。
以下のような画面に遷移するのでHTTP APIの構築をクリックします。

次の画面で統合を追加をクリックすると以下のような画面になるので、先程作成したLambda関数を選択します。
API名は適当なものをつけてください。

次のルートを設定ではデフォルトのままで良いですが、リソースパスは後々必要となるので覚えておいてください。

Step3のステージを定義はデフォルトのままで良いので、Step4で作成をクリックすると完了です。
Event Subscriptionsの設定
ここで、Event Subscriptionsの設定で後回しにしていた設定を行います。
Event Subscriptionsのページに行き、Enable Eventsをonにすると以下のような画面になると思います。

ここで、Request URLに下記のAPI GatewayでURLを呼び出すのURLにAWS API Gatewayでのリソースパスを追加したURLを入力します。
入力後、Verifiedと緑の文字が表示されると認証成功です。
url verificationに関して詳しく知りたい方はどうぞ

成功後は、Subscribe to bot eventsタブからAdd Bot User Eventをクリックし、message.channelsを選択し、画面下部のSave Changesをクリックし、アプリのワークスペースへの再インストールを行います。
動作確認
皆様、お疲れさまでした。(筆者も書いてて疲れました笑)
また、ここまで、お読みいただき誠にありがとうございます!!
では、実装したSlackAPPを利用してみましょう!
メッセージの最初で作成したアプリをメンションして、メッセージを送信すると回答が返ってきます!!!(作成する前に聞いてみるべきでしたね...)

おわりに
今回、「ChatGPT APIを使いたい!」、「だったら普段から作りなれているSlack Appで作ってみるか!!」、「どうせならあまり使ったことないAWSで実装してみるか!!!」と思いつきで始め、なんとなくまとめてみたくなって筆をとった次第です笑
読みにくい、または分かりづらい、記事通りに実装したのに動かない、もっとこうした方が良い等がございましたらコメントいただけますとできる範囲で対応、修正していきたいと思います!
最後に、煽りスキルの高いChatGPTさんとの会話を載せて示させていただきます。
お付き合いいただき誠にありがとうございました![]()
