🤖

ChatGPTが応えてくれるSlackのbot作ったけどまじ簡単

2023/03/14に公開

ChatGPTが応えてくれるSlackのbot作ったけどまじ簡単

ChatGPT.もともとOpen AIからAPIが提供されていたけどReference読んでも使うのめっちゃ難しかったけど,今回簡単に使えるAPIがリリースされたので使ってみた.まじ簡単🤩

https://platform.openai.com/docs/api-reference/chat/create

使った技術

TypeScript, Node.js, Bolt(SlackのイベントをListenしてくれるSDK)

TypeScriptじゃなくても平気です.

また,今回の記事ではSlackのbotってそもそもどうやって実装するのか?みたいなことは割愛します🙇‍♂️

作ったもの

こんな感じでメンションをつけたらスレッド内で回答してくれて,スレッド内の会話は記憶するようにしました.

実装

ChatGPTのAPIの実装箇所

import axios from 'axios';
import dotenv from 'dotenv';
dotenv.config();

export const postChat = async (
  messages: { role: string; content: string }[],
) => {
  const response = await axios.post(
    'https://api.openai.com/v1/chat/completions',
    {
      model: 'gpt-3.5-turbo',
      messages,
    }, // body
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
      },
    },
  );

  if (!response.data) return 'No response from OpenAI API';

  return response.data.choices[0].message.content;
};

node18からfetchが使用できますが,axiosを使いました.こんな感じでエンドポイントとBearer Tokenだけで実装できちゃう.

request bodyもとてもシンプルです.

{ role: string; content: string }のroleにはuserassistantが来ます.

これを配列で受け付けているので,会話の配列を渡せば過去の会話も含めた回答をしてくれるわけです.

BoltのListener部分

app.event('app_mention', async ({ event, client, say }) => {
  const channelId = event.channel;
  if (channelId !== askBotChannelId) return;
  try {
    /* 応答があったスレッドの内容を取得 */
    const replies = await client.conversations.replies({
      channel: channelId,
      ts: event.thread_ts || event.ts,
    });

    if (!replies.messages) {
      await say(
        '[ERROR]:\nスレッドが見つかりませんでした。\n管理者に連絡してください。',
      );

      return;
    }

    /* スレッドの内容をGTPに送信 */
    const threadMessages = replies.messages.map((message) => {
      return {
        role: message.user === botUserId ? 'assistant' : 'user',
        content: (message.text || '').replace(`<@${botUserId}>`, ''),
      };
    });
    const gptAnswerText = await postChat(threadMessages);

    /* スレッドに返信 */
    await say({
      text: gptAnswerText,
      thread_ts: event.ts,
    });
  } catch (error) {
    console.error(error);
  }
});

トリガーはapp_mentionにしました.特定のチャンネル内でbotに対してメンションしたときにのみ応答します.こうすることで,いちいち反応しなくなるし,botの回答に対してスレッド内で気軽に他の人と話ができるので良さげです.

トリガー後にまず,スレッド内の投稿一覧を取得する必要があります.これはSlackのweb clientにあるconversations.repliesを使用して取得できます.

ここで取得したメッセージを整形してChatGPTのAPIに投げれば回答が帰ってくるという感じです.

おわり

というわけで,1〜2時間くらいでサクッとChatGPTが回答するSlackのbotを作ることができました🎉

スレッドの要約もこの実装を応用すれば簡単にできるでしょう.急に50件の返信とかなっているスレッドに召喚されたときはぜひともChatGPTに要約させたいですね😇

また,APIにはstreamというparameterがあり,これをtrueにすることで,回答の進行状況をストリーミングできるようなので,いずれやってみたいです!

Discussion