RustでChatGPTを利用したDiscord Bot作った
ChatGPTを気軽に使えるようにするべく、ChatGPTを利用したDiscord Botを作りました。
Rust(serenity)で開発して、shuttleへデプロイし、常時稼働させています。
ソースコード
Botの大まかな動作
便宜上、今回作成したBotの名前を@chatgpt-bot
とします。
-
@chatgpt-bot
へメンションすると、そのメンションの内容と最新の100件のメッセージを取得します。 - それらを指定されている形式に変換して、OpenAIのAPIへPOSTします
- APIのレスポンスをBotがメンションをしてきたユーザーに返します。
ここではメンションとしましたが、 スラッシュコマンドでも良いです。
利用したもの
言語としてはRustを用いて、Discord API用のクレートであるserenityを利用しました。
デプロイ先にはshuttleを利用しました。
実装
プロジェクト作成
shuttleではserenityがサポートされているので下記のコマンドでserenity用のプロジェクトが作成ができます。
cargo shuttle init --serenity
詳細なDiscord Botの設定などは省きます。下記を参考にしてください。
コード
コードは公開しているので、ポイントのみ解説します。
トークンやAPIキーの扱い
Shuttleでは.env
ではなくSecrets.toml
に環境変数などの機密情報を記載して利用します。
そのため、ShuttleのBlogにもあるようにasync fn serenity
で環境変数を取得した後、gpt_token
でBot構造体に所有させることにしています。
struct Bot {
gpt_token: String,
client: reqwest::Client,
}
...
#[shuttle_service::main]
async fn serenity(
#[shuttle_secrets::Secrets] secret_store: SecretStore,
) -> shuttle_service::ShuttleSerenity {
// Secrets.tomlからトークンを取得する
let discord_token = secret_store
.get("DISCORD_TOKEN")
.context("'DISCORD_TOKEN' was not found")?;
let gpt_token = secret_store
.get("CHATGPT_TOKEN")
.context("'CHATGPT_TOKEN' was not found")?;
let client = get_client(&discord_token, &gpt_token).await;
Ok(client)
}
pub async fn get_client(discord_token: &str, gpt_token: &str) -> serenity::Client {
let intents = GatewayIntents::GUILD_MESSAGES
| GatewayIntents::DIRECT_MESSAGES
| GatewayIntents::MESSAGE_CONTENT;
serenity::Client::builder(discord_token, intents)
.event_handler(Bot {
gpt_token: gpt_token.to_owned(),
client: reqwest::Client::new(),
})
.await
.expect("Err creating client")
}
文脈に沿った会話をできるようにする
会話の文脈に沿った会話をできるようにするため、最新100件を取得したAPIへ送信することにしました。messagesパラメーターの形式に変換しています。
取得した100件に対して、繰り返して処理を行い、チャンネルで実行すると関係ないメッセージも含まれてしまうので、聞きたい話題ごとにスレッドを立てて、会話することをお勧めします。
botが動いているか分かりやすくする
start_typing
で〇〇が入力中...
と表示することができます。Botが動いているのか、エラーで押しているのかわかりやすくなります。
shuttleでDiscord Botを常時稼働させる
現時点でリリースノートにしか書かれていないのですが、30分アクセスがないとアプリケーションはスリープするようになったため、project作成時に--idle-minutes
オプションでスリープしないように設定します。
shuttle project new --idle-minutes 0
感想
コードを書くにあたり、ChatGPTにRustを教えてもらいながら実装を進めました。
Rustほぼ初心者でも開発できました。
参考
Discussion