KINTO Tech Blog
General

ChatGPTにSlackカスタム絵文字を作ってもらった

Cover Image for ChatGPTにSlackカスタム絵文字を作ってもらった

はじめに

こんにちは。分析グループでデータエンジニアをしている小池です。Slackって便利ですよね。こいつは突然何を言い出すのか。そう思ったかたも多いかもしれません。しかし、安心してください。Slackが便利であることはまぎれもない事実です。そして、その中でも絵文字リアクションは群を抜いて便利だとわたしは思います。そもそも絵文字リアクションが何者かわかりますか。少していねいに説明してみますね。次の画像をご覧ください。
Slack絵文字リアクション
これはわたしが自分のtimesチャンネルでぼやいたものです。白く囲んだ部分を見ると、ぽこぽこと泡のようなものがあることがわかると思います。これがまさしく絵文字リアクションです。「🥲」という絵文字の横に「1」とありますが、これは1人が「🥲」絵文字のリアクションをしたことを表しています。この数字が多ければ多いほどうれしいですね。また、ほかに「どんまい」という絵文字があります。これはSlackに標準搭載されているわけでなく、ユーザが追加した「カスタム絵文字[1]」というものです。今回は、ChatGPTの力を借りてカスタム絵文字の追加を行ってみます。

背景

そもそも、なぜカスタム絵文字を追加したくなったのかを説明しましょう。わたしの所属している分析グループは、東京、名古屋、大阪の3拠点に分かれて業務を行っています。これは、常時フルリモート状態になっているメンバーがいるということです。東京は東京、名古屋は名古屋、大阪は大阪でオフラインのコミュニケーションが行われることもあるため、全員が自宅からリモートワークをしている状態よりも情報の格差が生じてしまっているかもしれません。こういった事象をなくすべく、テキストコミュニケーションツールであるSlackにもっと力を入れるべきなのではないかと考えました。そして、その手段としてカスタム絵文字の追加を思いついたというわけです。

Slackカスタム絵文字の作成

それでは、さっそくカスタム絵文字を追加していきましょう。以下のような手順で進めていこうと思います。

  1. リアクションに使われた絵文字の利用回数の集計
  2. 1で集計した絵文字を感情別にグループ分け
  3. 2で作成したグループをもとにChatGPTで単語を生成
  4. 3で生成した単語を選定し、絵文字作成ツールで画像にしてSlackへ登録

絵文字の利用回数の集計

カスタム絵文字を追加するといっても、どんなものを追加すればよいのかいきなりはわかりませんね。そこで、まずは日ごろからどのような絵文字が使われているのかをリサーチするところから始めてみます。具体的には、チャンネルと期間をしぼり、それらの投稿の中でなされた絵文字リアクションとその回数を調べて傾向をつかんでみようと思います。

はじめに、SlackのAppを作成して、以下のように権限を設定し(必要そうなものをなんとなく追加したため、過剰な権限になっているかもしれません)、トークンを発行します。
Slackbotの権限

作成したAppをPythonから呼び出して次のように集計作業を行います。

import datetime
import pprint
import time
import yaml
from slack_sdk.web import WebClient


def main():
    get_and_save_messages()
    reaction_counts = get_reaction_counts()
    pprint.pprint(sorted(reaction_counts.items(), key=lambda x: x[1], reverse=True))


def get_and_save_messages():
    SLACK_API_TOKEN = "SLACK_API_TOKEN"
    client = WebClient(token=SLACK_API_TOKEN)
    target_channel_id_to_name = {
        "id0": "#name0",
        "id1": "#name1",
        "id2": "#name2",
        "id3": "#name3",
        "id4": "#name4",
    }

    unix_times = get_unix_times()
    messages = get_messages_in_channels(client, list(target_channel_id_to_name.keys()), unix_times)
    with open("messages.yaml", "w") as f:
        yaml.dump(messages, f, allow_unicode=True)


def get_messages_in_channels(client, channel_ids, unix_times):
    merged_messages = []
    for channel_id in channel_ids:
        for unix_time_pair in unix_times:
            merged_messages += client.conversations_history(
                channel=channel_id,
                include_all_metadata=False,
                latest=str(unix_time_pair[0]),
                limit=100000,
                oldest=str(unix_time_pair[1])
            )["messages"]
    return merged_messages


def get_unix_times():
    unix_times = []
    today = datetime.date.today()
    start = 1
    end = 15
    for _ in range(24):
        start_date = today - datetime.timedelta(days=start)
        end_date = today - datetime.timedelta(days=end)
        start_unixtime = int(time.mktime(start_date.timetuple()))
        end_unixtime = int(time.mktime(end_date.timetuple()))
        unix_times.append((start_unixtime, end_unixtime))
        start = end + 1
        end = start + 14
    return unix_times


def get_reaction_counts():
    with open("messages.yaml", "r") as f:
        messages = yaml.safe_load(f)

    reaction_counts = dict()
    for message in messages:
        if "reactions" in message:
            for reaction in message["reactions"]:
                reaction_counts[reaction["name"]] = reaction_counts.get(reaction["name"], 0) + reaction["count"]
    return reaction_counts


if __name__ == "__main__":
    main()

ソースコードについてかんたんに説明しましょう。
main()では各工程ごとの関数を呼び出すようになっています。get_save_and_messages()はSlackからメッセージを取得してファイルに保存する関数です。なお、SLACK_API_TOKENtarget_channel_id_to_nameは伏せてあります。メッセージが多すぎると一度に取得できない場合があるためget_unix_times()で期間を分割したものをリストで返し、メッセージを小分けに取得するようにしています。メッセージ取得が終わったらget_reaction_counts()で絵文字リアクションの回数を集計します。その後、回数が多い順にソートして表示して終了です。

実行結果を次に示します。たとえば、('man-gesturing-ok', 248)は、man-gesturing-okという絵文字が248回リアクションされたことを表しています。また、この実行結果にはデフォルトの絵文字はもちろん、手作りのものや社外のかた[2]が作成したものも含まれています。

('man-gesturing-ok', 248),
('eyes', 248),
('arigatougozai', 199),
('承知しました', 64),
('+1', 49),
('thinking_face', 43),
('yorosikuonegaisimasu', 26),
('arigatougozaimasu', 17),
('tada', 15),
('素敵', 14),
('arigato', 13),
('do_ne', 13),
('man-gesturing-no', 11),
('scream', 10),
('kakuninshimasu', 10),
('承知2', 9),
('woman-bowing', 9),
('sob', 8),
('ok', 8),
('faito', 8),
('kami_bl', 7),
('done_hiragana', 7),
('desune', 7),
('naruhodo', 7),
('ok_hand', 7),
('sugoi', 7),
('tasukaru', 7),
('pray_mochimochi', 7),
('done-payment', 6),
('hai-', 6),
('nanto', 6),
('yokata', 6),
('mumondai', 6),
('tashi-crab', 5),
('muscle', 5),
('oh', 5),
('sasuga2', 5),
('uooo', 5),

絵文字のグループ分け

先ほど集計した状態のままだとまだ解像度が低いため、絵文字を感情表現の種類ごとにグループ分けして特徴をつかんでみます。なお、グループ分け方法は独自で考えたものにしました(調べてみると心理学者が考案した感情の区分けがあるようでしたが、仰々しすぎて今回にはそぐわないと判断しました)。

報連相のために行われるものと感情表現のために行われるものに二分され、そこからさらに分かれていくといった構造になっていると考えました。それを次に示します。

- 報連相
  - 報告
  - チェック
  - お願い
- 感情表現
  - 共感
  - 褒め
  - 感謝
  - 応援
  - 慰め
- その他

この区分けを先ほどの集計結果に適用してみます。
絵文字グルーピング

まじまじとご覧になったかたはわかると思いますが、どこにあてはまるかわからないものはほとんどフィーリングで適当に分けました...🤫
ですが、まずまず納得感のあるグループ分けができたのではないかと思います。

ChatGPTを用いた絵文字生成

絵文字のグループ分けに続いて、それぞれの感情表現の種類ごとに絵文字を生成してみようと思います。また、手段として今はやりのChatGPTを使ってみます。使用したモデルはGPT-4で、プラグインやウェブブラウジング機能は使いませんでした。使用したプロンプトは次のとおりです。

Slackのカスタム絵文字を作りたいです。下記についてそれぞれ10こずつあげてください。
また、ひらがな、カタカナ、漢字のいずれかで4~6文字に収めるよう努力してください。
- メッセージを送ってきた相手に共感を示せるもの(例 : :たしかに:、:ですね:)
- メッセージを送ってきた相手を褒められるもの(例 : :すてき:、:神:、:すごい:)
- メッセージを送ってきた相手に感謝を示せるもの(例 : :ありがと:、:たすかる:)
- メッセージを送ってきた相手を応援できるもの(例 : :ファイト:、:ウオオオ:)
- メッセージを送ってきた相手を慰められるもの(例 : :oh:、:なんと:)

実行結果は次のとおりです。

カスタム絵文字の提案です。ひらがな、カタカナ、漢字のいずれかで4~6文字に収めるよう努力しました。
メッセージを送ってきた相手に共感を示せるもの:
:わかるよ: (wakaru yo)
:同感: (doukan)
:納得: (nattoku)
:うんうん: (un un)
:それそれ: (sore sore)
:言いたい: (iitai)
:共感: (kyoukan)
:感じる: (kanjiru)
:ごもっとも: (gomottomo)
:思いやり: (omoiyari)

メッセージを送ってきた相手を褒められるもの:
:すごいね: (sugoi ne)
:天才: (tensai)
:凄い: (sugoi)
:かっこいい: (kakkoii)
:素敵: (suteki)
:美しい: (utsukushii)
:完璧: (kanpeki)
:尊敬: (sonkei)
:称賛: (shousan)
:輝いてる: (kagayaiteru)

メッセージを送ってきた相手に感謝を示せるもの:
:ありがとう: (arigatou)
:感謝: (kansha)
:感謝してる: (kansha shiteru)
:ありがとうね: (arigatou ne)
:ありがとー: (arigatou-)
:助かった: (tasukatta)
:感謝の気持ち: (kansha no kimochi)
:恩返し: (ongaesha)
:お礼: (orei)
:感激: (kangeki)

メッセージを送ってきた相手を応援できるもの:
:がんばって: (ganbatte)
:ファイト: (faito)
:頑張れ: (ganbare)
:応援する: (ouen suru)
:力になる: (chikara ni naru)
:一緒にがんばろう: (issho ni ganbarou)
:がんばりましょう: (ganbarimashou)
:エールを送る: (eeru wo okuru)
:成功を祈る: (seikou wo inoru)
:自信を持って: (jishin wo motte)

メッセージを送ってきた相手を慰められるもの:
:大丈夫: (daijoubu)
:頑張れ: (ganbare)
:気にしないで: (ki ni shinaide)
:がんばったね: (ganbatta ne)
:辛いね: (tsurai ne)
:つらいよね: (tsurai yo ne)
:明日は新しい日: (ashita wa atarashii hi)
:落ち込まないで: (ochikomanaide)
:前向きに: (zenmuki ni)
:頑張ってるね: (ganbatteru ne)

Slackで使うには明らかに不自然なものもありますが、なかなかよさそうです。

絵文字の選定とSlackへの登録

先ほどChatGPTに生成させた絵文字から使い勝手のよさそうなものを選んでみるとともに、すでにSlackワークスペースに登録されている絵文字を省いてみます。

- 共感
  - :wakaruyo:
  - :doukan:
  - :gomottomo:
- 褒め
  - :sugoine:
- 感謝
  - :kangeki:
- 応援
- 慰め
  - :kinishinaide:

こんな感じになりました。
最後にこれらを絵文字作成ツール[3]で画像にし、Slackに登録して完了です。
登録した絵文字

うーん、いい眺め!

おわりに

いかがでしたか。これでSlackでのコミュニケーションが活発になること間違いなし...とはいかず、追加した絵文字を率先して使って組織に浸透させていく作業が重要になってくると思います。また、今回は感情表現の種類ごとにまんべんなくカスタム絵文字を追加しましたが、足りていないところを集中的に作るというアプローチもできそうです。あなたの組織のSlackワークスペースでもやってみてくださいね!

脚注
  1. Slackカスタム絵文字 ↩︎

  2. ¥0 – SmartHR Store ↩︎

  3. 絵文字ジェネレーター ↩︎

Facebook

関連記事 | Related Posts

We are hiring!

【データサイエンティスト(リーダークラス)】分析G/東京・名古屋

分析グループについてKINTOにおいて開発系部門発足時から設置されているチームであり、それほど経営としても注力しているポジションです。決まっていること、分かっていることの方が少ないぐらいですので、常に「なぜ」を考えながら、未知を楽しめるメンバーが集まっております。

【データエンジニア】分析G/名古屋・大阪

分析グループについてKINTOにおいて開発系部門発足時から設置されているチームであり、それほど経営としても注力しているポジションです。決まっていること、分かっていることの方が少ないぐらいですので、常に「なぜ」を考えながら、未知を楽しめるメンバーが集まっております。