見出し画像

gpt-3.5-turboを使ったslack bot を作ってみた

ファインディ株式会社、アルゴリズム企画開発チームの山家です。
OpenAIが出しているAPI(gpt-3.5-turbo)を使用してslack bot を作成しました。


作ったもの

スレッドの内容を理解しながら返信してくれるChatGPTライクなslack botを作成しました。
pythonで書いてる方が少なかったので、記事にしてみました。

かわいい

OpenAIのkey取得

OpenAIのAPI keysを開く
+ create new secret key を押してkeyを発行する。

Slack Botを作成する

Basic InformationのApp-Level Tokensでwriteを追加し、xapp~~から始まるtokenをコピーしておきます。(後で使います。)

https://api.slack.com/apps へアクセスしてAppを作成する
Bolt for PythonでSocketModeを使用するため、slack app ページでSocket Mode をenableにする

Event Subscriptionsをenableにして、トリガーを作成する。
今回は、app_mentionとmessage.imを設定しています。

参考記事)


コード

Boltフレームワークを使用します。(Bolt 入門ガイド
以下を環境変数でexportしておきます

export SLACK_BOT_TOKEN=xoxb-hogehoge
export SLACK_APP_TOKEN=xapp-fugafuga()
export SLACK_BOT_ID=@PIYOPIYO
export OPENAI_DEFAULT_MESSAGE=Let's think step by step.
export OPENAI_API_KEY=foofoo

以下のコードをmain.pyに保存する

import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
import openai

# 環境変数からトークンを読み込む
app = App(token=os.environ["SLACK_BOT_TOKEN"])
openai.api_key = os.environ["OPENAI_API_KEY"]
system_message = os.environ["OPENAI_DEFAULT_MESSAGE"]
slack_bot_id = os.environ["SLACK_BOT_ID"]

# direct messageを送付した場合のイベントはmessage、チャンネルでメンションした場合はapp_mentionをトリガーしている。
@app.event("message")
@app.event("app_mention")
def gpt_reply(event, say):
    # ecent[text]には、メンションが含まれているので、メンションを削除する
    input_message = remove_slack_id_from_text(event["text"], slack_bot_id)
    channel = event["channel"]
    user_slack_id = event["user"]
    # メッセージを取得する
    messages = [
        {"role": "system", "content": system_message},
        {"role": "user", "content": input_message},
    ]
    thread_ts = event["ts"]
    # スレッドにメッセージがある場合は、メッセージを取得する
    if "thread_ts" in event:
        thread_ts = event["thread_ts"]
        thread_messages_response = app.client.conversations_replies(
            channel=channel, ts=thread_ts
        )
        for i in thread_messages_response["messages"]:
            # メッセージがBotの場合は、Botの発言をmessagesに追加する
            if i["user"] == slack_bot_id:
                messages.append(
                    {
                        "role": "assistant",
                        "content": remove_slack_id_from_text(i["text"], slack_bot_id),
                    }
                )
            # メッセージがユーザーの場合は、ユーザーの発言をmessagesに追加する
            elif i["user"] == user_slack_id:
                messages.append(
                    {
                        "role": "user",
                        "content": remove_slack_id_from_text(i["text"], user_slack_id),
                    }
                )
    print("User:" + input_message)
    # OpenAIのChat APIを使用してChatGPTからの返答を取得する
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages,
    )
    text = response["choices"][0]["message"]["content"]
    if text != "":
        print("ChatGPT:" + text)
        say(text=text, thread_ts=thread_ts, channel=channel)
    else:
        print("ChatGPT:" + "No response from OpenAI API")
        say(text="No response from OpenAI API", thread_ts=thread_ts, channel=channel)
    thread_ts = app.client.conversations_replies(channel=channel, ts=thread_ts)[
        "messages"
    ][0]["thread_ts"]


def remove_slack_id_from_text(text, slack_id):
    return text.replace(f"<@{slack_id}>", "")


# Socket Modeハンドラーを作成し、Slack APIを起動する
if __name__ == "__main__":
    handler = SocketModeHandler(
        app,
        os.environ["SLACK_APP_TOKEN"],
    )
    handler.start()
python main.py

を実行する

社内では、GKEを使用して常時起動するようにしています。

のびしろ

tokenが上限を超える際にエラーが出ないです。(気が向いたら修正します)
スレッドの内容を全て渡している為、gpt_botとのやり取り以外のメッセージも考慮されてしまいます。

まとめ

社内でslackbotを展開したところ、わからない単語を調べたり、slackのコミュニケーション活性化に繋がっているようでうれしかったです。

現在、事業領域的にもセンシティブな情報を扱うので、OpenAIのAPIにはセンシティブな情報をいれないようにしており、LLMの内製化を進めてます。(内製の知見ある人いたら教えて下さいw)

宣伝

一緒に働く人も募集してます!ぜひ!


いいなと思ったら応援しよう!