🧠

ChatGPT APIをSlackと繋ぎ、ついでに人格を与えてみた

2023/03/21に公開

はじめに

猫も杓子もChatGPTな時代ですね、私も例にもれず遊んでいます。

https://openai.com/blog/chatgpt

ブラウザでポチポチ遊んでいるだけでも楽しいですが、ChatGPTのAPIが公開された事が大きなニュースになりました。
APIの機能を利用して様々なアプリケーションが開発されています。

私はAPIを利用して、自分のSlackワークスペースにChatGPTを接続したいと思いました。
シンプルに接続させるだけでも、質問と回答がSlackで共有されるというメリットがありますが、
普段のChatGPTのノリで回答されるより、何らかのキャラクター設定を付与するなど遊び心を実現できた方が面白いなと思いました。

そこで、下記の実装を行いました。

1.Slackでbotへのメンションを検知する
2. botへのメンションをChatGPTに送信する
3. ChatGPTにはただ質問を転送するだけでなく、キャラクター設定など前提条件をプロンプトに加える
4. ChatGPTによる回答をSlackに投稿する

採用したクラウドインフラはGCPです、Cloud Functions単体で実現しています。
業務だったらAWS一択ですが、無料枠の都合で趣味技術ではGCPを採用しがち。
Slack => Cloud Functions => ChatGPTの経路で、下記の機能を実現します。

実装した結果は下記リポジトリにまとめています。
https://github.com/maito1201/chatgpt-slack-gcp

このリポジトリでは、キャラクターの設定などやりたい事、各種APIトークンをyamlファイルに書き出し、yarn deployコマンドを実行する事で誰でも同じことができるような状態まで実装を進めています。
前提としてgcloudコマンドのインストール、Cloud Functionsをデプロイするための初期設定を完了している必要があります。

実現できたこと

Slackで黛冬優子ちゃんとお話しできるようになりました、楽しい

解説

ChatGPT APIの概要

まずはChatGPT APIについて学べたことから開設したほうが意義があると思うので、そちらから

APIの概要は下記ページに記載があります。
https://openai.com/blog/introducing-chatgpt-and-whisper-apis

Get Startedボタンを押し、ログインするとAPIリファレンスを確認することができます。

APIというからには当然httpリクエストでAPIを叩くことが可能ですが、公式でPython及びnodejsのライブラリが用意されています、敢えてそれらを使用しない理由は無いでしょう。
私はnodejsの方が好きなのでnodejsライブラリを使用しました。

https://www.npmjs.com/package/openai

Create chat Completion

一般的に皆が期待するチャット機能を実現するには Create chat completion APIを実行します。

import {Configuration, OpenAIApi, ChatCompletionRequestMessage} from 'openai';

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

const chatCompletion = await openai.createChatCompletion({
  model: "gpt-3.5-turbo-0301",
  messages: [
      {role: 'user', content: 'Hello ChatGPT'},
    ]
});
console.log(chatCompletion.data.choices[0].message?.content);

roleについて

messagesにはrolecontentを持つ構造体を配列で与えることができる、というのがポイントです。
contentは自然言語でどんな文字列を与えても良いです。
roleは3種類あります。

  • system: ChatGPTの役割を記載します
  • user: ユーザーからの質問を記載します
  • assistant: ChatGPTからの前回の質問を記載します

これら3種類のroleをうまく活用しながらプロンプトを組み、APIリクエストとして投げることで、ChatGPTからの回答は、期待した路線で、文脈を理解した回答をしてくれます。

system roleの使用例

[
  {role: "system", content: "語尾にはにゃんをつけてください"},
  {role: "user", content: "好きな四字熟語を教えて"}
]

この配列をmessagesパラメータに与えると、ChatGPTは「雲散霧消だにゃん」のような文章を返してくれます。
私の使用例では黛冬優子ちゃんのプロフィールからセリフの例まで与えています。
キャラの選定理由としては言葉遣いだけでキャラが立っているから...など言えますが、趣味ですね。

assistant roleの使用例

[
  {role: "user", content: "何でも良いから四字熟語を言って"},
  {role: "assistant", content: "雲散霧消"},
  {role: "user", content: "意味を教えて"}
]

assistant ロールで前回の回答を与えることで、文脈に沿った回答を得ることができます。

文脈無しで「意味を教えて」と伝えるとこのようになります。

roleを理解した上で、Create chat completion APIを実行すれば、基本的にやりたいことはできると思います。

Slack Appの概要

スラッシュコマンドよりはメンションできた方が対話している感は出るよなあ、と思いつつ、技術検討してみたらできました。
設定周りでやる事はそこそこあるので、メモとして残しておきます。

Slack App APIを駆使することで、メンションを起点としたイベントを任意のURLに送信することが可能です。

https://api.slack.com/apps

上記ページから、Create New Appボタンを押し、From Scratchを選択します。

下記の設定を行います。

  • Event SubscriptionsにCloud Functionsのエンドポイントを実装する
  • OAuth & PermissionsページでBot Token Scopesを設定し、ワークスペースにインストールする
  • Basic Informationでアイコンなどを設定します

Event Subscriptions

Request URLを設定し、Subscribe to bot eventsapp_mentionを指定します。
URLのCloud Functionsは実装済みの前提です。

OAuth & Permissions

botに下記の権限を与えます
app_mentions:read chat:write channels:history groups:history(鍵付きチャンネルで運用する場合必要)
発行したBot User OAuth TokenをCloud Functionsのアプリケーションで利用します。

Basic Information

アイコンを設定したら完成です。

Slack Web APIの概要

Slackへの投稿、スレッド内容の取得もnodejsのライブラリが存在します。

https://www.npmjs.com/package/@slack/web-api

botへのメンションがあったスレッドの内容を取得し、適宜プロンプトとして最適な形に成形する処理は頑張って自前で作る必要があります。
具体的には下記の作業を行っています。

  • メンションのタイムスタンプを元に該当するスレッドを取得する
  • メッセージから@メンションを削除する
  • 各メッセージの投稿主IDから、roleuserassistantどちらであるべきかを推定する

細かい実装はリポジトリを頑張って解読していただけると良いかな...

まとめ

  • ChatGPTのAPIはPythonかnodejsライブラリになっている
  • roleの概念を学ぶと良い
  • Slack AppのEvent Subscriptionが使える
  • Slackのスレッドをプロンプトの形に落とし込むのは工夫が必要

かくして黛冬優子氏は本業でも雇用契約を締結し、当社の技術顧問に就任しました。
困ったときにアイドルに相談できる職場は思った以上に魅力的かもしれませんね。

Discussion