🤖

コミュニケーションを爆速化させるにはSlackとPythonを使え!

に公開

はじめに

こんにちは!データサイエンティストをしているTakoです🐙
突然ですが、「ここの業務プロセス改善したいな・・・」と感じたとき
どのような手順を踏んでタスク化するかの検討まで持っていきますか?
誰かに話したきりやチャットツールに投稿したきりになっていませんか?

その場では色々と話したが結局どこにも残していなくて
タスク化されずに忘れ去られてしまってはいないでしょうか?

日々感じていることはあって、Slack等のチャットツールに投稿したりするが、
流れてしまって結局議論(タスク化)するときには忘れてしまっている・・・。
そのようなことを防ぐためにSlack, Python, ローカルLLMを使って
忘却の彼方にいかせず、議論をいつでもできるようなアプリを作成したのでご紹介します!

モチベーション

課題を感じるたびにタスク化をするとなると、「これってタスクにするほどかな?」や
「タスクチケットを切るのが面倒だな」と心理的ハードルが高くなると感じました。
上記のハードルから、Slackで気軽にチームの課題を話していこうという方針になりました。
「気軽に課題をみんなに共有できて、タスク化を検討できるようにしたい!」

Slackの議論、流れて消えてない?ローカルLLM(Ollama)とスプレッドシートで作る「自動要約・蓄積」パイプライン

いざSlackで課題の共有をしだすと、気軽さから課題の共有自体は多くなりましたが、
「あの議論、結局どうなったんだっけ?」と探したりする必要があり
タスク化を検討する際の余計な作業が増えてしまいました。。。(気軽な会話の代償・・・)

そこで、Slackのスレッド全文をローカルLLM(Ollama)に投げて要約し、
Googleスプレッドシートに「課題」として自動蓄積する仕組み
を構築しました。

アプリ化してSlackにインストールすることで、
過去ログの一括解析から、Socket Modeによるリアルタイム監視まで対応できます。
どういったロジックで作成したかを説明していきます。

全体構成とワークフロー

今回のシステムは、「過去ログのバッチ処理」「新着メッセージのリアルタイム処理」 の2系統で動いています。

技術スタック

  • 言語: Python
  • Slack SDK: Slack Bolt (Socket Mode)
  • LLM: Ollama (ローカル実行)
  • DB: Google Sheets (gspread)
  • キャッシュ: ローカルJSONファイル

処理フロー

実際にどのようなプロセスでSlackに投稿した内容が処理されるかを図で書いてみました。

このようなフローでプログラムは動きます。
やっていることは単純で、メッセージが新しく書かれたらそのスレッドのすべてのメッセージ(返信含む)をSlackから取得しLLMに投げるだけです。
スプレッドシートで要約は管理しているので、既に要約済みの場合は最新の返信を含んだ要約に上書き更新します。
また、基本のフローは検知したときにはじまりますが、任意の過去スレッドにさかのぼって要約することも可能にしています。

下記の設定も必須になってきますので後程説明します。

  1. 自作アプリをSlackにインストール ← Pytnonとslackを繋ぐ
  2. Ollama(ローカルLLM)をPCにインストール
  3. サービスアカウントの発行

ちなみにスプレッドシートでのデータ収集は下記のようにしています↓
https://docs.google.com/spreadsheets/d/1BFhM-WIibBXf8-a1fJXwd1LeoKvLM1IDabyiuJLQ9dM/edit?usp=sharing

環境構築

この3つができるように環境構築をしていきます!

  1. 自作アプリをSlackにインストール ← アプリとSlackを繋ぐ
  2. Ollama(ローカルLLM)をPCにインストール
  3. サービスアカウントの発行

自作アプリをSlackにインストール

Slackの投稿を検知してアプリ側で投稿された内容等を取得するには
Slackにアプリをインストールするのとメッセージを読み書きするための権限が必要になります。

  1. まずはSlack Marketplaceに飛び、アプリを追加したいワークスペースを選びます。

  2. その次に上部のタブの「構築」を押下すると、自作アプリの一覧が表示されます

  3. 「Create New App」を押下して、「From scratch」を選択します
    a. アプリ名は何でもOKでワークスペースはインストールする場所にしてください
    こんな画面までいけたらOKです!

  4. 「Socket Mode」タブを選択し、Enable Socket ModeをON(緑になったらOK)にします。Token名は何でもOKです。」

※この時に作成されるTokenは必要になりますので、必ず保存してください。xapp- から始まります。

Socket Mode(ソケットモード)は、一言で言うと「外部からアクセスできない環境(自分のPCや社内サーバー)からでも Slackの通知をリアルタイムに受け取れる仕組み」 のことです。

  1. 「Event Subscriptions」タブを選択し、Enable EventsをON(緑になったらOK)にします

メッセージの新規投稿、返信を検知するために必要になります。

  1. 「OAuth & Permissions」タブを選択し、Scopesからアプリの権限を設定します
    a. ここら辺があれば大丈夫です
    b. channels:history
    c. chat:write
    d. groups:history
    e. reactions:write
    f. users:read
    g. app_mentions:read
    h. すべてのScopeの追加完了後にOAuth Tokensのところで Install to [workspce]をします

アプリがどこまでSlackを操作できるかを決める権限設定になります。
※Bot User OAuth Tokenのxoxb- から始まるTokenを保存してください。

再掲
この時に2つのTokenは必ず取得してください(アプリの処理に必要になります)。

  • 「Socket Mode」タブ:xapp-XXXXXX.....から始まるやつ
  • 「OAuth & Permissions」タブ:xoxb-XXXX...から始まるやつ

あとはインストールしたアプリを好きなチャンネルに「インテグレーション」から追加します!
これでSlack側の下準備は完了です!

Ollama(ローカルLLM)をPCにインストール

Ollama(オラマ)は、ChatGPTのような高性能なAI(大規模言語モデル:LLM)を、クラウドを介さず「自分のPC(ローカル環境)で直接動かす」 ためのツールです。

Ollamaの特徴

  • 情報を外部に出ることがない(ローカルLLM)
  • 自PCをAIサーバーにできる
    • Postすることでプロンプトを投げることができる
  • 色々なLLMを試すことができる
    • PCのスペック、用途に合わせてモデルをすぐに変更できる

手順はめちゃくちゃ簡単です。

  1. Ollama公式サイトからインストール
  2. インストール完了後に ollama run gemma2 <- ここは任意のモデル をしてモデルのインストール
    a. モデル一覧

モデルのインストールが完了して会話画面になれば準備完了です!
http://localhost:11434/api/generate ← ここにAIサーバーが立ち上がっています。

サービスアカウントの発行

これはめちゃくちゃ簡単なのと記事がいっぱいあるので、記事のリンクだけ張っておきます。
参照↓
https://dream-yt.github.io/post/spreadsheet-via-service-account/

環境構築は簡単ですね!あとは自分の理想の処理が実現できるようにコードをひたすら書きます。
全部は説明できないので、頑張った部分だけ説明していきます。

工夫ポイント

ユーザー名のキャッシュ

メッセージには「ユーザーID」しか含まれていません。毎回APIで名前を引きに行くと遅いため、user_cache.json に保存。未登録のユーザーのみ取得しに行く仕組みです。

処理済みIDの管理

過去ログを解析する際、すでに要約済みのスレッドを二度処理しないよう、processed_ids.json でThread IDをキーで最新の返信ID(latest_reply)を値として管理しています。
これで「差分がある場合に要約する」ことが可能になります。

2. LLMの「脳」をローカルで動かす(Ollama)

要約にはローカルLLMの Ollama を使用しました。
外部にデータを出さないため、機密性の高い議論も安心して扱えます。
とりあえず無料で試すことが可能になりました。

厳格なJSON出力

LLMの出力をプログラムで扱いやすくするため、システムプロンプトで出力を厳格に指定しています。

System Prompt: 「出力は必ず以下のJSON形式のみとしてください: {"summary": "...", "category": "...", "tech": "..."}

これにより、json.loads() でそのままスプレッドシートに流し込める辞書データとして受け取れます。

3. スプレッドシートへの保存ロジック

単に追記(Append)するだけではなく、 「更新(Update)」 にも対応させているのがポイントです。

  1. 検索: Thread IDをキーに、シート内の既存データを検索。
  2. 分岐:
    • 既にあれば、その行を最新の要約で上書き。
    • なければ、新しい行として末尾に追加。

これにより、議論が続いているスレッドの要約も、常に最新の状態に保たれます。

4. リアルタイム監視(Socket Mode)

過去ログの解析が終わったら、SocketModeHandler で待機状態に入ります。

  • 新しいメッセージが投稿される
  • 自動でスレッドを特定し、数分おきに要約を更新
  • 処理が完了したら、Slack側にリアクション(🤖)を付けて、正常に記録されたことを可視化

デモ

実際に動かしてみた動画です。
最初に過去のスレッドの要約を開始して、その次にリアルタイム監視を開始します。

https://youtu.be/JRMOZdnZsCw

実運用では

実運用では下記は気を付けたほうがよさそうです。

  • JSONパースエラー対策: LLMがJSONで返さない可能性があるので防止策を考える
  • スプレッドシートの書き込み制限: 今は1行ずつなのでまとめてアペンドする
  • 環境変数の分離: トークン類はpyファイルに直が気しない

しっかり考えないとですね。

まとめ

Slackに課題を投稿する楽さを維持したまま、課題の蓄積が可能になりました。
個人的に要約も素晴らしいが、タスク化を検討するときにはカテゴライズが役に立つのではと思っています。

アプリを作成していて思ったのですが、ローカルLLMを使って過去のスレッドをさかのぼって特定のキーワードについて話していることを要約するようなアプリも役に立ちそうだなと思いました。

「技術的負債」や「不具合報告」といったカテゴリ分けをLLMに任せることで
後からのチームの課題の分析も格段に楽になればいいな~。

Discussion