やったこと
slackにメンションをつけてChatGPTと対話できるようにしました。 チャンネル投稿を過去3個を取得して、会話が続けられるようになっています。
やることは大きく
- SlackのBolt設定
- こちらは前回の記事を参考。
- https://redpanda-page.vercel.app/Tech/20230319
- ChatGPTを呼び出す
- 今回はこちらを中心に書きます。
ChatGPT周りの用語整理
まずはChatGPTらについて抑えておきましょう。 ChatGPT, GPT-3, GPT-4など用語がたくさんあったので、公式ドキュメントや色んなサイトを比較しながら自分なりにまとめてみました。 まずopenAIについてですが、openAIはAIを研究する研究所でいろんなAPIを公開しています。例えば
- GPT API:自然言語生成モデルを使用して、文章や文章の継続を生成するAPIです。
- DALL-E API:画像生成モデルを使用して、文章から画像を生成するAPIです。
- Codex API:コード生成モデルを使用して、自然言語での説明からコードを生成するAPIです。
- CLIP API:テキストと画像を一緒に扱うことができるAPIで、画像から文章を生成することもできます。
その中でGPT APIについて深掘りします。
GPTの種類
GPT-3とGPT-3.5は言語モデルのサイズの差。
- GPT-3:自然言語を理解して生成できる訓練された言語モデル
- GPT-3.5:GPT-3から改善されたモデル
- gpt-3.5-turbo: 一番優れたGPT-3.5モデル今回利用するのはこちら
- GPT-4:GPT-3.5から改善されたモデル
(GPT-1,2もあります。)
ChatGPTとGPT-3.5の違い
ChatGPTはGPT-3.5アーキテクチャに基づいて訓練されたもので、チャットボットに特化したモデルのことです。
一度は使ったことがあるこのアプリケーションでChatGPTを無料で使えます。
gpt-3.5-turbo
3/1にChatGPTのAPIとしてgpt-3.5-turboモデルを発表されました。今回で使ってみるAPIでもこれを利用します。
値段は1,000tokenで$0.002。単語一つが1tokenと考えればいいと思います。
こちらのサイトでtokenの区切りがどうなるか試すことができます。
Open AIのTokenをもらう
Open AIにアカウント登録が必要です。
tokenをこちらでもらいます。一度しか表示されないので注意しましょう。
どれくらいtokenを使っているかは以下で確認できます。18$まで無料で利用可能です。
ソースコード
typescript, nodemon, eslintを利用しましたが、環境構築はここでは載せません。 まだローカルで立ち上げているため、今後どのサーバーに載せるかは考え中です。 process.envのところは各自copyしたtokenたちを入れます。
やってることは、slackのチャンネルにメンション付きで投稿があったときに、チャンネルのないの最近の3件のスレッドを取得し、メッセージを組み立ててChatGPTにapiを叩きます。 メッセージに入るのは
- systemメッセージ ChatGPTの役割を与えます。slack bot、優しい先生など色々指定できます。今回は固定しました。
{ role: "system", content: "slack bot" }
2. assistantメッセージ ChatGPTからの回答を入れます。 slackのスレッドを取得するときにbotからのスレッドはこちらに入ります。 これにより、前回の質問もうまいことChatGPTが参考してくれて対話が成り立つことになります。
{ role: "assistant", content: 以前のChatGPTからの回答 }
- userメッセージ ユーザーの質問を入れます。 slackのスレッドを取得するときにbotからではなくユーザーの質問のスレッドはこちらに入れています。
{ role: "user", content: ユーザーの質問 }
叩く部分はこうなっています。
const response = await openAIClient.createChatCompletion({ model: "gpt-3.5-turbo", messages: msg, top_p: 0.5, // 大きくなるほど、いろんな単語を選ぶようになる frequency_penalty: 0.5, // 同じ単語をもう一度使うかどうか。2に近いと繰り返しにくくなる });
全体のソースコード
import { App } from "@slack/bolt"; import { ChatCompletionRequestMessageRoleEnum, Configuration, OpenAIApi, } from "openai"; import * as dotenv from "dotenv"; import { ChatCompletionRequestMessage } from "openai/api"; dotenv.config(); const app = new App({ token: process.env.SLACK_BOT_TOKEN, signingSecret: process.env.SLACK_SIGNING_SECRET, socketMode: true, appToken: process.env.SLACK_APP_TOKEN, port: 3000, }); app.event("app_mention", async ({ event, client, say }) => { // channelで発言があった場合 const { channel, text } = event; try { // api setting const configuration = new Configuration({ apiKey: process.env.OPENAI_KEY, // openAIのAPIkey }); const openAIClient = new OpenAIApi(configuration); const CHAT_GPT_SYSTEM_PROMPT = `slack bot`; const msg: ChatCompletionRequestMessage[] = [ { role: ChatCompletionRequestMessageRoleEnum.System, content: CHAT_GPT_SYSTEM_PROMPT, }, ]; // channelにhistoryがある場合、3個取得 // 順番は thread idでsortすることで時間順に取得 const channelHistory = await client.conversations.history({ channel: channel, limit: 3, }); if (channelHistory.ok) { const prevMessages = channelHistory.messages .sort((a, b) => Number(a.ts) - Number(b.ts)) .map((m) => { const role = m.bot_id ? ChatCompletionRequestMessageRoleEnum.Assistant : ChatCompletionRequestMessageRoleEnum.User; return { role: role, content: m.text as string }; }); msg.push(...prevMessages); } else { msg.push({ role: ChatCompletionRequestMessageRoleEnum.User, content: text as string, }); } // Chat Completion API を呼び出す const response = await openAIClient.createChatCompletion({ model: "gpt-3.5-turbo", messages: msg, top_p: 0.5, // 大きくなるほど、いろんな単語を選ぶようになる frequency_penalty: 0.5, // 同じ単語をもう一度使うかどうか。2に近いと繰り返しにくくなる }); // APIから回答と、使ったtoken数をもらう const message = response.data.choices[0].message?.content || ""; const total_tokens = response.data.usage.total_tokens; // 回答をSlackに投稿する if (message) { await say(`${message} [total tokens: ${total_tokens}]`); } else { throw new Error("message is empty"); } } catch (e) { await say("壊れてしまいました。エラー!!!!!"); } }); (async () => { await app.start(); console.log("⚡️ Bolt app is running!"); })();
試した内容はこちら。
手元で簡単い試したかったので色々と足りないです。 必要最小限の機能しか入れてないので、今後時間があったら以下を入れたいですね。
- まともなエラー処理
- スレッドの時のイベント処理
- 遅延された時の回答
Ref
ChatGPT APIを活用したSlackbotを作成して、30分以内に会社内に有能な友達を作る
- 神の記事