Post

GPTを利用したSlackスレッド要約ボット


はじめに

最近、ほとんどの会社でSlackが使われています。
私もSlackを利用しているのですが、Slackの内容を把握するのに多くの時間を費やしています。

例えば、私のメンションが追加されて「上記の内容をお願いします!」と連絡が来ることがあり、スレッド内のメッセージが100件以上の場合もあります。
また、休暇後に戻ってきたときに、把握しなければならないスレッドが多いと、1日が業務の把握だけで終わってしまうのは非常に残念だと感じました。

最近、OpenAIからGPT-4o-miniが発売されて、価格が安いし、スレッドの全内容を要約してくれるBotを作って、スレッドの把握時間を節約できると思いました!



APP仕様

img

簡単に、仕様をイメージでまとめてみました。

  1. 要約したいスレッドで、Botをメンション。
  2. Botが、動いていることがわかるように「まとめ中です...」というメッセージを非公開で表示。
  3. 要約が完了すると、自分だけが確認できる非公開の要約内容を受ける。
  4. 要約と同時に、非公開で共有ボタンを表示。
  5. 共有ボタンをクリックすると、要約内容をスレッドに共有。

追加事項
1.基本の要約プロンプトは、APPに内蔵し、Botをメンションするだけで要約。
2.メンション後に、追加のプロンプトを入力して、より効率的に使用可能にする。

例) @bot 英語で、@bot 一文で、@bot エンジニアが必要な作業だけ



技術スタック及びアーキテクチァー

  • 言語

    Python 3.8+

  • 主要ライブラリ

    slack_bolt : Slackアプリ開発のためのフレームワーク
    langchain : LLMとの相互作用のためのフレームワーク
    python-dotenv : 環境変数管理

  • API

    Slack API: Bot機能の実装とメッセージ処理
    OpenAI API: GPT-4o miniモデルを用いたテキスト要約


img

  • Slackイベントリスニング

    slack_boltライブラリを使用してSlackイベントを受信。
    メンション(@BotName)を通じて、Botを呼び出し。

  • スレッド内容抽出

    Slack APIを使用して、メンションされたスレッドの全体の会話内容を取得。
    User IDを実名に変換して、読みやすくする。

  • GPT-4o miniを利用した要約

    langchainライブラリで、OpenAIのGPT-4o miniモデルと連携。
    スレッド内容をGPT-4o miniに渡して要約を生成

  • カスタムプロンプト

    Userがメンションと共に、特定の指示を入力。
    基本要約プロンプトに、Userのプロンプトを追加して、柔軟な要約が可能。

  • 非同期処理

    要約中であることを知らせるメッセージを先に送信して、User体験を向上させる。

  • プライバシー考慮

    要約結果は、要請したUserのみに表示。
    共有ボタンを通じて、要約をスレッドに公開するオプションを提供。



主要コード説明

1
2
3
4
5
6
7
8
9
10
#==========================================
# 必要なモジュールをインポート
#==========================================
import os
from dotenv import load_dotenv
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
from slack_sdk import WebClient
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
  • 必要なモジュールをインポート

    dotenvを使用して、環境変数をロードし、Slack BoltSlack SDKを使用して、
    Slackイベントを処理します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#==========================================
# 初期化
#==========================================
# .envファイルから環境変数を読み込む
load_dotenv()

# Slackアプリケーションを初期化
app = App(token=os.getenv("SLACK_BOT_TOKEN"))
client = WebClient(token=os.getenv("SLACK_BOT_TOKEN"))

# OpenAI GPTモデルを初期化
chat = ChatOpenAI(temperature=0.7, max_tokens=2048, model_name="gpt-4o-mini")

# デフォルトの要約プロンプ
default_summary_prompt = "次の会話を日本語で要約してください"
  • 初期化

    環境変数をロードし、SlackアプリとOpenAI GPTモデルを初期化します。
    gpt-4o-miniを使用し、プロンプトを通じて基本的に日本語で要約を注文します。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#==========================================
# ユーティリティ関数
#==========================================
# ボットのユーザーIDを取得
def get_bot_user_id():
    try:
        response = client.auth_test()
        return response["user_id"]
    except Exception as e:
        print(f"ボットユーザーIDの取得に失敗しました。: {e}")
        return None

# ユーザーの実名を取得
def get_user_name(user_id):
    try:
        user_info = client.users_info(user=user_id)
        return user_info["user"]["real_name"]
    except Exception as e:
        print(f"ユーザー名の取得に失敗しました。: {e}")
        return user_id
  • get_bot_user_id

    Slack APIのauth_testメソッドを使用して、BotのUser IDを取得します。
    これは、Botがメンションされたメッセージで、自分を識別するために必要です。

  • get_user_name

    指定されたUser IDを使用して、Slack APIのusers_infoメソッドで、Userの実名を取得します。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#==========================================
# メインイベントハンドラ
#==========================================
# ボットがメンションされたときのイベントハンドラ
@app.event("app_mention")
def handle_mention(event, say):
    # スレッドのタイムスタンプを取得
    thread_ts = event.get("thread_ts", event["ts"])
    channel_id = event["channel"]
    user_id = event["user"]
    
    # カスタムプロンプトを抽出
    if BOT_USER_ID:
        custom_prompt = event["text"].split(f"<@{BOT_USER_ID}>")[1].strip()
    else:
        custom_prompt = event["text"].strip()
    
    # 要約プロンプトを設定
    summary_prompt = f"{default_summary_prompt} {custom_prompt}" if custom_prompt else default_summary_prompt
    
    # 要約中メッセージを送信(あなただけに表示されています)
    client.chat_postEphemeral(
        channel=channel_id,
        user=user_id,
        thread_ts=thread_ts,
        text="まとめ中です..."
    )
    
    # スレッドの会話を取得
    result = client.conversations_replies(channel=channel_id, ts=thread_ts)
    messages = result["messages"]
    
    # 会話を整形
    conversation = "\n".join([f"{get_user_name(msg['user'])}: {msg['text']}" for msg in messages if msg['user'] != BOT_USER_ID])
    
    # GPTモデルを使用して要約を生成
    summary = chat.invoke([HumanMessage(content=f"{summary_prompt}\n\n{conversation}")]).content
    
    # 要約結果を送信(あなただけに表示されています)
    client.chat_postEphemeral(
        channel=channel_id,
        user=user_id,
        thread_ts=thread_ts,
        text=f"【 概要結果 】\n{summary}"
    )
    
    # 共有ボタンを追加(あなただけに表示されています)
    client.chat_postEphemeral(
        channel=channel_id,
        user=user_id,
        thread_ts=thread_ts,
        text="要約を共有しますか?",
        blocks=[
            {
                "type": "actions",
                "elements": [
                    {
                        "type": "button",
                        "text": {"type": "plain_text", "text": "共有"},
                        "value": summary,
                        "action_id": "share_summary"
                    }
                ]
            }
        ]
    )
  • スレッドのタイムスタンプを取得

    thread_tsを取得して、現在のスレッドのタイムスタンプを確認します。

  • カスタムプロンプトを抽出

    メンションされたメッセージからボットのユーザーIDを基準にカスタムプロンプトを抽出します。

  • 要約プロンプトの設定

    デフォルトの要約プロンプトにカスタムプロンプトを追加して、最終的な要約プロンプトを設定します。

  • 要約中メッセージの送信

    要約作業が始まったことを知らせるメッセージをユーザーにエフェメラルメッセージで送信します。

  • 会話内容を取得

    対象スレッドの全ての会話内容をSlack APIを使って取得します。

  • 会話内容の整形

    会話内容をユーザー名とともに整形します。

  • GPTモデルを使った要約生成

    整形された会話内容をGPTモデルに渡して要約を生成します。

  • 要約結果の送信

    生成された要約結果をユーザーにエフェメラルメッセージで送信します。

  • 共有ボタンの追加

    ユーザーが要約を他の人と共有できるように共有ボタンを追加したメッセージを送信します。



使用例

image-20240804192950637 (テスト例文)

image-20240804193059730 (基本要約)

image-20240804193135132 (プロンプトを使用した例 1)

image-20240804193229542 (プロンプトを使用した例 2 or 共有ボタンをクリック)

image-20240804193301633 (プロンプトを使用した例 3)


Slack API

OpenAI API

Library

このポストは著作権者の CC BY-NC 4.0 ライセンスに従います。

© HAKU. Some rights reserved.