22
10

More than 1 year has passed since last update.

【忙しい人向け】爆速で ChatGPT の Discord Bot を作ってみた

Last updated at Posted at 2023-04-28

概要

ChatGPT の Discord Bot を試しに作ってみたら数時間で完成したので、記事にしてみました。
以下のようにBotにメンションすると返事をしてくれます。

image.png

注意事項

  • お金が掛かります。
  • 筆者はDiscord Botを作るのが初めてです。
  • 普段 Python を書かないのでコードも雑です。
  • 本記事は忙しい人向けです。時間がある人は他の記事も参考にしましょう。

1. とりあえず Discord Bot を用意する

最速で Discord の Bot が作れる方法を発見しました。
以下の記事に従って、Discord Bot を用意します。

注意点がいくつかあります!

  • BOTの追加設定が必要
    • 1つ目の記事に従いBotを作成する際に、追加で設定が必要です。
    • DEVELOPER PORTAL の Bot の設定ページから MESSAGE CONTENT INTENT をオンにする必要があります。
      image.png
  • 課金が必要
    • 2つ目の記事の冒頭にも書いてありますが、Herokuの無料プランが廃止されたため、課金が必要です。
    • 筆者は一番安いプランの Eco dynos に登録しました。月5ドルです。

記事に従い /ping に対して pong が返ってきたら、次へ進みましょう。

image.png

2. OpenAI のアカウントを作成する

以下からアカウントを作成します。

特に詰まるポイントは無かったので説明は省きますが、困ったら「openai アカウント 作成」とかでググりましょう。

アカウントが作成できたら、以下から API key を作成します。

以下から API key が表示されていればOKです。

image.png

作成した API key は手順1で登録した Bot のトークンと同様に、Herokuに OPENAI_API_KEY という名前で登録しておきましょう。

アカウント作成時に無料クレジットが付与されるので、そのクレジットを消費しきるまでは無料です。
Usage から、使用量が確認できるので、定期的に確認しておきましょう。

クレジットを消費しきると止まると思うので、使い続けたい場合は課金しましょう。
1000トークンあたり0.002ドルなので、安いと思います。

3. Bot に対してメンションが来たら ChatGPT で返事をするようにする

ここからが本番です。手順1で作成したリポジトリの discordbot.py を編集していきます。

その前に、requirements.txt に pythonのパッケージ openai を追加します。

requirements.txt
  discord.py[voice]
+ openai

これで、デプロイ時に以下の OpenAI のパッケージがインストールされます。

最後に、OpenAI のパッケージを利用して、以下のように discordbot.py を編集します。

import discord
import traceback
from discord.ext import commands
from os import getenv
import openai

intents = discord.Intents.default()
intents.message_content = True

bot = commands.Bot(command_prefix='/', intents=intents)

messages = [
    {"role": "system", "content": "You are a helpful assistant. The AI assistant's name is AI Qiitan."},
    {"role": "user", "content": "こんにちは。あなたは誰ですか?"},
    {"role": "assistant", "content": "私は AI アシスタントの AI Qiitan です。なにかお手伝いできることはありますか?"}
]

@bot.event
async def on_command_error(ctx, error):
    orig_error = getattr(error, "original", error)
    error_msg = ''.join(traceback.TracebackException.from_exception(orig_error).format())
    await ctx.send(error_msg)

@bot.event
async def on_message(message):
    if message.author == bot.user:
        return
    if bot.user.id in [member.id for member in message.mentions]:
        print(message.content)
        print(message.content.split('>')[1].lstrip())
        messages.append({"role": "user", "content": message.content.split('>')[1].lstrip()})

        openai_api_key = getenv('OPENAI_API_KEY')
        openai.api_key = openai_api_key

        completion = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages
        )

        print(completion.choices[0].message.content)
        await message.channel.send(completion.choices[0].message.content)

token = getenv('DISCORD_BOT_TOKEN')
bot.run(token)

これで完成です!!

image.png

おまけ

上記の discordbot.py を少し解説します。

その前に、今回使用しているパッケージのリファレンスを紹介します。

discord.py

以下が discord.py 日本語のドキュメントです。困ったらここを読みましょう。

一番参考にしたのは、APIリファレンスのページです。
例として、下で出てくる on_message の引数 Message がどんなクラスで、何を持っているかを参照しました。

openai-python

リポジトリは以下です。

公式ドキュメントは英語ですが、何となく雰囲気で理解できます。

他には、今回使用している openai.ChatCompletion でググって出てきた例を参考にすれば実装できます。

discordbot.py 解説

以下のように on_message で、Discordのメッセージを処理します。

@bot.event
async def on_message(message):

以下で、メッセージのメンションがある場合のみ、処理を行うようにしています。

if bot.user.id in [member.id for member in message.mentions]:

message.content でメッセージを文字列で取得できますが、メンションが含まれる場合以下のようになっています。

<@123456789123456789> こんにちは

なので、以下のようにメンションより後ろの部分を取得しています。

message.content.split('>')[1].lstrip()

今回使用している API のopenai.ChatCompletion は、3つのロール(system, user, assistant)による会話に続く次のメッセージが返ってきます。今回は以下のように設定してみました。

system    : あなたはアシスタントです。なまえは AI Qiitan です。
user      : あなたは誰ですか?
assistant : 私は AI アシスタントの AI Qiitan です。
user      : (ここに Discord から取得したメッセージを入れる)
assistant : (ここを ChatGPT が生成する)

これを python で書くと以下のようになります。

messages = [
    {"role": "system", "content": "You are a helpful assistant. The AI assistant's name is AI Qiitan."},
    {"role": "user", "content": "こんにちは。あなたは誰ですか?"},
    {"role": "assistant", "content": "私は AI アシスタントの AI Qiitan です。なにかお手伝いできることはありますか?"}
]

messages.append({"role": "user", "content": message.content.split('>')[1].lstrip()})

そして、以下で ChatGPTが返したメッセージが取得できるので、これを Discord に投げています。

completion.choices[0].message.content

あとがき

きっかけは社内の Slack の ChatGPT API を使った bot でした。

社内でとても盛り上がっていたので、普段入り浸っているDiscordサーバーに導入したら盛り上がるのでは?と思い、作ってみました。

爆速で雑に作ったのでまだまだ改善の余地がありますが、こんな状態でもサーバーのメンバーが様々な質問をBotに投げかけており、めちゃくちゃ盛り上がりました。

22
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
10