ご機嫌よう、世界
なんかもう最近は猫も杓子もChatGPTじゃないですか?
僕みたいに自然言語処理をかじっていると、社内外問わずいろんな人から「ChatGPT、どうっすか」と まるで宗右衛門町の客引きのように 声をかけられます
どうもこうも、それはそれでしょう、そもそもあの子のベースになっているGPT-3.5は単純にパラメータ数がry
ChatGPTのAPIがついにオープンになったのでSlack botを早速導入する
どうもCTO室AI推進部とグループ会社HiTTOで 二股 兼務中の@ken11です。
いや今回の話は非常にシンプルで掲題の通りなんですが、冗談抜きで社内外問わずChatGPTに対する強い興味と関心のお声を頂戴しており、せっかくなのでAPIが使えるようになったならみんなに伝わりやすい使い方をしてみましょうね、そうだよねハム太郎ってことでSlack botをつくりました
すなわちもう一人の自分、ペルソナを召喚しました()
こういうのは話題性があるうちにやるのが大事なのでね、機能性よりスピード重視です!
僕は午前4時頃に「そろそろオフトゥンへGOの時間だなも…ねむねむ…(おもむろにYouTubeで新兎わいちゃんを見始める ※ここ重要)」というナイトルーティン(死語)をし始めた頃にOpenAIから「APIあけたーーーー」ってメールが配信されていることに気づき、「おいおいおいおい今夜は寝かさねえってか?」とオフトゥンからエクソダス、botを作り始めたのでした(いい話だ)
おいしいChatGPTなSlack botのつくりかた
とりあえず今回のbotの構成について、マジでシンプルにこんな感じでつくります
Slack bot ⇔ API Gateway ⇔ Lambda
ほんと、それ以上でも以下でもないです、おもちゃですから
※おもちゃとはいえAWS使ってるのでしっかりお金はかかります!また、ChatGPT APIは最初は無料分でまかなえると思いますが、そのうち課金しないと動かなくなります!
Lambdaを用意する
なにはともかくChatGPT APIを使うLambdaをつくりましょう
OpenAIのユーザ登録をして、とりあえずAPIキーを取得します
そしてOpenAIを使うにはライブラリを利用するのが楽なので、Lambdaのlayerを生成します
あ、今回僕はPythonでやってます
$ mkdir python $ pip install openai -t ./python $ zip -r9 layer.zip python
そしてレイヤーメニューからレイヤーを作成します
先ほど作成した layer.zip
をアップロードし、適当な名前をつけて作成します
続けて、とりあえずLambda関数を「一から作成」で作成します
ランタイムはPython3.9にします
最下部の レイヤーの追加
から先ほど作成したレイヤーを追加します
これでLambda関数内で openai
のライブラリが使用できるようになりました
続いて、環境変数の設定をします
設定の環境変数を選択し、ここでは OPENAI_API_KEY
という名前で、OpenAIのAPIキーをセットしておきます
また、Lambdaのタイムアウト時間は適宜延ばしておくとよいと思います(デフォルト3秒は結構厳しい、とはいえそもそもSlack側が3秒でタイムアウトするから別にいいのかもしれない)
最後に、Lambda関数のコードを書きます
import os import openai import json import hmac import hashlib import datetime from urllib.parse import parse_qs openai.api_key = os.getenv("OPENAI_API_KEY") secret = os.environ['SLACK_API_SIGNING_SECRET'] def verify(headers, body): try: signature = headers["X-Slack-Signature"] request_ts = int(headers["X-Slack-Request-Timestamp"]) now_ts = int(datetime.datetime.now().timestamp()) message = "v0:{}:{}".format(headers["X-Slack-Request-Timestamp"], body) expected = "v0={}".format(hmac.new( bytes(secret, 'UTF-8'), bytes(message, 'UTF-8'), hashlib.sha256).hexdigest()) except Exception: return False else: if (abs(request_ts - now_ts) > (60 * 5) or not hmac.compare_digest(expected, signature)): return False return True def lambda_handler(event, context): if verify(event['headers'], event['body']): params = parse_qs(event['body']) text = params['text'][0] response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are a mad scientist."}, {"role": "user", "content": text} ] ) payload = { "response_type": "in_channel", "text": response["choices"][0]["message"]["content"] } return { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": json.dumps(payload) } else: return {"statusCode": 400}
以下、ポイントです。
- 一応Slackからのリクエストなのか検証しています、環境変数に
SLACK_API_SIGNING_SECRET
を設定してごにょごにょ - API GWからきたリクエスト内容は、
parse_qs
でevent['body']
をパースすることで取得できます - 今回新たに開放された
openai.ChatCompletion.create
を使ってChatGPTを呼び出しています。messages
オプションでまずsystem
というroleを使ってassistant
(実際に回答してくるbot)のキャラクターを指定することができます。僕はマッドサイエンティストにしておきました() また、ここに過去のuserとassistantのやりとりを設定することで会話の流れをつくれるわけですが、今回は過去のログを記憶させるのが面倒だったので実施していません。その他、ドキュメントのこの辺に詳細は書かれています。 - ChatGPTのレスポンスはjsonで、回答だけ取りたい場合は
["choices"][0]["message"]["content"]
で十分です payload
内response_type
はSlack側の仕様で、これを指定しないとスラッシュコマンドを利用したユーザにしか返信が見えなくなってしまいます。みんなで盛り上がるためにはみんなに見えるようにしよう!()
これでひとまずLambda関数はできました
API Gatewayを用意する
続いてAPI Gatewayを作成します
まず、APIの作成からRESTを選択して作成します
次に、アクションメニュー内のメソッドの作成を選び、POSTメソッドを作成します
作成済みのLambda関数を選び、プロキシ統合にしておきます
最後に、エンドポイントをデプロイします
これでもうAPI Gatewayはリクエストを受け付けている状態になります。
呼び出し用のURLが発行されるので、ここにリクエストするとLambdaが実行され、レスポンスが返ってくる次第です
このURLにめちゃくちゃリクエストされるとお金がBackwardする可能性があるので、URLの取り扱いは慎重に
Slack botをつくる
最後に、Slack botをつくります
ここの CreateNewApp
から作成を開始します
名前を適当につけて作成したら左のメニューにあるSlash Commandsを選びます
Create New Command
を選択し
こんな感じで設定してあげます
URLに先ほどのAPI GatewayのURLを入れてあげるだけで、あとはお好みでどうぞ
また、Signing SecretをLambdaで検証しているので、Lambdaの SLACK_API_SIGNING_SECRET
に設定するのをお忘れなきよう
最後に、左側のメニューの Install App
でbotを使いたいワークスペースにインストールしたら完了です
これでもう、Slack上でいつでもどこでも呼び出せます
都合のいい存在ですね
注意点
いくつか注意というか補足があります。
- 会話の記憶は実装しなかったので、そこはまだ楽しめないですごめんなさい
- API GatewayもLambdaもお金かかります、セキュリティ的にいい状態ではないので、リクエストが大量にきて泣かないよう気をつけてください。マジでお金がBackwardします
- 緩和策として、API Gatewayには使用量プランというオプションがあり、クオータ制限等かけられるので心配ならどうぞ(ここでは詳しい話はしません)
- Slackのスラッシュコマンドは3秒以内にレスポンスを返さないといけないという厳しい制限があります。Lambdaのコールドスタート、ChatGPT APIからのレスポンス等、3秒は結構厳しくなる場面もあるので、タイムアウトしがちなのはご愛嬌です。わざわざ非同期にするほどのものでもないしな……
最後に
というわけで、午前4時から爆速でSlack botをつくりあげ、寝て起きたらみんなが非常に楽しそうに使ってくれていたのでほっこりしました
これで僕が寝ている間もみんなSlack芸楽しめるね…( ˘ω˘ )
あ、ちなみにbotの名前は自分の分身として ken111
にしました、Vault111から来たアイツみたいな感じになりましたね()
以上、早速ChatGPT APIを使って遊び倒した話でした!
マネーフォワードってわりと真面目な会社だと思ってますか?
マネーフォワードには僕みたいに一日中Slack芸をして「ホントは仕事してないんでしょう?」と言われるtimes芸人が、実際には多数在籍しています!!(※個人調べ)
僕個人は一緒にSlack芸をしてtimes芸人になってくれる方を募集してます!