PC のターミナルや、Google Colab や Jupyter のノートブックで、GPT-3.5-turbo と対話するのもそれはそれで楽しいですが、やはり使いやすいフロント実装があった方が便利です。
自分用の場合はもちろん、社内向けは顧客向けにデモや PoC (Proof of Concept)を実現するときにも GUI は必要ですね。
そんな中で、非常に実装が簡単なのが Slack Bot なので、今回は Slack Bot を、手元の PC で動作させてみます。手元 PC にあればどのサーバーに deploy するかといったことも考えなくてすみますし、デモを提供したときに token を使われすぎないように素早くシャットダウンできる点が便利です。
Slack の API を準備する
新しいアプリを作成する
上記 URL にアクセスし、Create App ボタンをクリックして新しいアプリを作成します。
ワークスペースと、アプリの名称を決定します。
権限を設定する
左メニューの OAuth & Permissions から権限を設定します。
右Pane 中程の、 Add an OAuth Scope ボタンから OAuth Scope を追加します。今回は、 app_mentions:read と chat:write だけを許可します。メンション以外のメッセージも処理したい場合は適切な権限を追加します。
アプリをインストールする
左メニューのInstall App からアプリをワークスペースにインストールします。さらに、OAuth Token が表示されるので、それをコピーして控えておきます(xoxb-で始まる文字列)。
Socket Mode を有効にする
今回はSocket Mode で動作させるので、左メニューの Socket Mode を選択します。続いて、 Enable Socket Mode をオンにします。
App Level Token を取得する
左メニューの Basic Information から App-Level Tokens を表示し、Generate Token and Scopes ボタンをクリックして、App Token を作成します。
connections:write Scope を追加して、「Generate」ボタンをクリックしてApp Token を生成します。
xapp-で始まるTokenが表示されるので、これも控えておきます。
Python に必要なライブラリをインストールする
py -m pip install slack-sdk slack-bolt
として、slack BOT 開発用のライブラリをインストールします。
ここまでで、ようやく slack BOT 開発の準備が整いました(コードを書くより、 OAuth Token の準備の方が大変です)。
簡単な Slack BOT に GPT-3.5-turbo を繋げてみる
import と キーの設定
# slack bolt
from slack_bolt import App
# socket mode での動作
from slack_bolt.adapter.socket_mode import SocketModeHandler
# GPT-3.5-turbo
from langchain.chat_models import ChatOpenAI
from langchain import LLMChain
from langchain.prompts.chat import (
ChatPromptTemplate,
# System メッセージテンプレート
SystemMessagePromptTemplate,
# assistant メッセージテンプレート
AIMessagePromptTemplate,
# user メッセージテンプレート
HumanMessagePromptTemplate,
)
from langchain.schema import (
# それぞれ GPT-3.5-turbo API の assistant, user, system role に対応
AIMessage,
HumanMessage,
SystemMessage
)
# env に読み込ませるAPIキーの類
import key
# 環境変数にAPIキーを設定
import os
os.environ["OPENAI_API_KEY"] = key.OPEN_API_KEY
SLACK_APP_TOKEN = key.SLACK_APP_TOKEN # "xapp-XXXXXXXXXXXX"
SLACK_BOT_TOKEN = key.SLACK_BOT_TOKEN # "xoxb-XXXXXXXXXXXX"
Slack Bot 用に slack_boltのApp, SocketModeHandler を importします。
GPT-3.5-turbo 用には、ChatModelの他、LLMChain と Prompt だけを import します。
Slack 用には先ほど取得してきた APP_TOKEN と BOT_TOKEN をセットします。GPT-3.5-turbo 用には、OPEN_API_KEYを設定します。
オブジェクトの作成
# Slack Bot の作成
app = App(token=SLACK_BOT_TOKEN)
# モデル作成
llm = ChatOpenAI(temperature=0)
# 日本語で ChatGPT っぽく丁寧に説明させる
system_message_prompt = SystemMessagePromptTemplate.from_template("You are an assistant who thinks step by step and includes a thought path in your response. Your answers are in Japanese.")
# ユーザーからの入力
human_template="{text}"
# User role のテンプレートに
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
# ひとつのChatTemplateに
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
chat_prompt.input_variables = ['text']
# カスタムプロンプトを入れてchain 化
chain = LLMChain(llm=llm, prompt=chat_prompt)
Slack Bot は、AppのコンストラクタにBOT TOKENを与えて実体化させます。
GPT-3.5-turbo では、 temperatureを設定して言語モデルを実体化させ、続いて Promptのテンプレートを作成し、まとめて LLMChain に入れて使いやすくパッケージにします。
BOT の動作部分
# メンションされた時
@app.event("app_mention")
def command_handler(body, say):
# メンションの内容を取得
text = body['event']['text']
# LLMを動作させてチャンネルで発言
say(chain.run(text=text))
if __name__ == "__main__":
# Socket で起動
handler = SocketModeHandler(app, SLACK_APP_TOKEN)
handler.start()
今回はメンションにのみ反応させるので、 @app.event(“app_mention”) のみイベント設定を指定しています。
イベントの処理については、ユーザーからのメンションの内容を受け取り、それに対する応答を LLM に作成させ、 say メソッドで反応させています。
LLM の実行が完了するには少し時間がかかるので、先にメッセージを送信するといった処理をしてもいいでしょう。
main部分については、 SocketModeHandler に bot のインスタンスである app と、 APP_TOKEN を与えて作成し、startメソッドで起動します。
作成した Python ファイルを起動すると、
Bolt app is running!
というメッセージが表示され、Bot が起動状態になります。この Bot はこちらからconnection を張りに行っているので、ネットワークの特別な設定などなしで動作します。
後は、Botを使用したいチャネルに invite するか、アプリを追加し、メンションをすることで動作します。
問題なく動作しますが、時刻を確認してもらえれば分かるように、応答までに1分経過しています。開発者本人は、ローカルで何度も時間がかかるところを見ているので問題ないと思いますが、一般ユーザー向けにローンチする場合は、心配にならないようになんらかのメッセージを表示した方がよさそうです。
まとめ
- Slack BOT の開発は、 Scope を設定してOAuth発行するので、初期設定が面倒臭い(セキュリティのためなのですが……)
- 開発は、Python で Bolt を使う限りでは非常に楽(初期設定よりずっと楽)
- SocketModeだと手元のPCで気軽に動作確認が出来て便利
- LLM の応答には時間がかかるので、何らかのメッセージ表示などを行った方がいい。