はじめに
元記事をご覧でない方は、そちらを先にご覧いただくことをお勧めします。
詳しいソースコードはこちらです。
こちらは、Slack & ChatGPTのBotを作成する上での、実装方法や実装上あった問題などについて解説する記事となっております。
使用言語はTypeScriptです。AltJSの実質的王者です。今回はこいつに助けられましたが、苦しめられました。
Node.js + Dockerでデプロイするつもりで作成しました。Dockerでいくつかのツールをデプロイしている環境があるため、それに合わせています。 Cloudflare Wokersや、AWS Lambdaのような、サーバーレスで実行するようにもできますが、今回は割愛。
今回の開発は同期の 内山 くんと共同で行ったため、記事執筆も二人で行っております。
目次
プログラムの構造・使用ライブラリ
プログラムの使用ライブラリは、以下のようになっています。 いずれもnpmパッケージです。
パッケージ名 | 用途 | リンク |
---|---|---|
@slack/bolt | Slack API | @slack/bolt-npm |
openai | OpenAI API | openai-npm |
dotenv | 環境変数 | dotenv-npm |
後ほど触れますが、このBoltというのがかなりの曲者でした。以前Discord.jsでDiscordのボットを作成したことがあるのですが、それとは悪い意味でかなり違いました。
OpenAIのnpmパッケージは非常に使いやすく、動作も単純です。
dotenvは、環境変数などを内部で認識するために利用しています。
プログラムの依存関係を、dependency-cruiser
で可視化したものです。
プログラムの挙動が単純なためシンプルですが、utils内でもSlack Boltのインスタンスが必要なため、app.tsで独立させました。
file | 処理内容 |
---|---|
src/index.ts | Botの起動,イベント挙動の定義 |
src/app.ts | BoltのAppインスタンスの初期化 |
src/utils/index.ts | 会話履歴などの配列操作関数などを定義 |
src/utils/ai.ts | OpenAI API関連の関数 |
気をつけた点
今回TypeScriptを利用したので型についてです。
Slack Boltの型にはかなりの時間を費やしました。
実際、このようなissueが立っているくらいです。
Developer experience building Slack apps with Bolt using TypeScript #826
今回開発するに当たって、特に困った2個を紹介しようと思います。調べてもなかなか出て来なかったので、困ってる人もいるかと思います。
1つ目
app.message(/.*/, ({ message }) => {}
で取得したmessage
を型付けようと思いました。
なんとかGenericMessageEvent
という型を見つけることがでしました。
ですが、、
const msg: GenericMessageEvent = message;
これだとダメです。
const msg: GenericMessageEvent = message as GenericMessageEvent;
このようにしなければエラーを吐いてしまいます。
また、メッセージの型は複数あり、このGenericMessageEvent
にしておけば全てのメッセージを網羅してくれそうです。
詳しくはここらへんをご参照ください。
2つ目
続いて、本Botでは
app.client.conversations.replies()
を使用しています。これで返ってくる型がMessage[]
なんですが、Message
型ってなんやねん。
これはslack web apiのメソッドなので、試しにこのようにしてみました。
import { Message } from '@slack/web-api';
案の定、存在しないと怒られてしまいます。
正解はこうでした。ChatGPTに教えてもらいました。ChatGPTってやっぱりすごい。
import { Message } from '@slack/web-api/dist/response/ConversationsRepliesResponse';
こんなの誰がわかるねん
こんなのわかるわけないですね。最初、ソースコードからMessageを探し出してそのまま貼り付けていました。 ともあれ、それよりは全然いい形にすることができました。
まとめ
今回の開発で存在感のあるトピックに関して、それぞれまとめます。
TypeScript
今回の開発を振り返ると、やはりTypeScriptの偉大さに気づかされます。JavaScriptで同じプログラムを記述しようとすると、おそらく二倍ほど時間が掛かったのではないかと思います。 Slack Boltのところの、型が見つからない問題などもありますが、基本的にそのオブジェクトがどの状態なのか、どのプロパティ、メンバを持つのかが確定するのは素晴らしいです。
Slack Bolt
こいつには苦戦させられました。しかし、webhookでのイベント駆動方式が基本となっていて、discordなどwebsocketが基本のものとはかなり毛色が違うため、アプローチとしては面白かったです。 複雑なアプリケーションが書きたい方は、StackOverflowを読むと良いと思います。公式ドキュメント、リファレンスはあまり参考になりません。 Bolt自体はTypeScriptで書かれているようなので、さらに頑張って欲しいところです。
OpenAI API(GPT)
また、Boltはアレですが、OpenAI側のライブラリはかなり出来が良い印象でした。使い方が単純なため複雑なアプリケーションにも簡単に溶け込ませることができます。npm以外に、Pythonのpipなどにも同様のライブラリがあるようです。 使用言語に関してライブラリが大きな問題となりやすい中、複数言語に跨ってかなりできの良いライブラリがあるのは素晴らしいですね。