メインコンテンツへスキップ
見出し画像

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)

    宣伝

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


    あなたへのおすすめ