9
14

More than 1 year has passed since last update.

ChatGPT APIを使ったDiscord返答ボットの作成【初心者向け】

Posted at

この記事では質問をしたら以下のように自動で返答をしてくれるDiscordのBotを作成します。
image.png

概要

3月1日、遂にOpenAIが「ChatGPT」のAPIを提供開始ました。
これは言語モデル、gpt-3.5-turboを搭載しており、価格は$0.002/1000tokensとなっています。以前の言語モデル、Davinciと比較すると、1000トークンあたりの価格が1/10となっていてよりリーズナブルになっています。
トークンの計算は、英語の場合1単語あたり1トークンですが、日本語の場合は複雑になっています。
日本語のトークンの数が知りたい場合、OpenAIのプレイグラウンドで確認することができます。
例えば、「This is a pen」だと4トークン、「これはペンです」だと8トークンとなっています。

対象読者

  • JavaScriptをある程度理解している人
  • VScodeをあらかじめインストールしている人
  • これからDiscord botを開発する人

開発環境

MacOS Ventura(v13.2.1)
VScode(v1.76)
Node.js(v18.14.0)
npm(v9.3.1)

環境の作成

  • 任意の場所にコードを入れるファイルを作成します
    私の場合、書類フォルダの中に"Discord_gptchat"という名前のフォルダを作成しました。(名前はなんでも可)
  • VScodeを開き、作ったフォルダを読み込みます。
  • package.jsonの作成
    以下のコマンドをターミナルで実行します。
npm init

色々とオプションを聞かれるので次のようにしてください。("は入力しない)

{
  "name": "bot",
  "version": "1.0.0",
  "description": "",",
  "main": "bot/index.js,",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": ",
  "license": "ISC"
}


Is this OK? (yes) y
  • Discoed.js,dotenv,openaiをインストール
    以下のコマンドをターミナルで実行します
npm install discord.js dotenv openai

discord.jsはDiscordのライブラリ
dotenvは.envを読み込めるようになるモジュール
openaiはOpenAIのライブラリ
となっています。
完了するとこのようなファイル構成になっています。
pakeg.png
botというフォルダを一番外のフォルダ内に作成した後、index.jsというファイルをbotの中に作成します。
bit.png
そして、下記のコマンドで.envファイルを作成します。

touch .env

最終的には以下のようなファイル構造になります。
saisixyu.png

各種トークンの取得

discordのトークン取得

  • Discordの開発者ポータルにアクセスし、Discordのアカウントでログインします。
  • New Applicationを選択ます。
    image.png
  • 任意の名前を入力し、チェックマークをクリックしCreateボタンをクリックします。
    image.png
  • 画面左側のメニューバーでBotを選択した後、Add botをクリックします。
    image.png
  • するとこのような画面になります
    image.png
  • 下にスクロールし、以下のように設定し、セーブしてください
    image.png
  • 最後に一番上まで戻り、View Tokenを押しトークンを取得してください。(後で使用するのでどこかにメモしておいてください)
    image.png

OpenAIのAPIキー取得

以下のサイトにアクセスし、アカウントが既にある場合はログイン、無い場合は新規作成をし、secret keyを取得してください。

.envファイルの編集

以下のように書いてください。

OPENAI_API_KEY=取得したOpenAIのシークレットキー
BOT_TOKEN=取得したDiscord botのトークン

コードの作成

以下のコードを先ほど作ったindex.jsに保存します。

// dotenvを使って、環境変数を読み込む
require("dotenv").config();

// 必要なモジュールを読み込む
var fs = require("fs");
const { Client, GatewayIntentBits } = require("discord.js");
const Discord = require("discord.js");

// Discordクライアントを初期化する
const client = new Discord.Client({
  intents: Object.values(Discord.IntentsBitField.Flags),
});

// OpenAIのAPIキーを設定する
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

// Discordクライアントが起動すると、一度だけ呼び出される関数を定義する
client.once("ready", () => {
  console.log(`${client.user.tag} Ready`);
});

// Discordクライアントが起動すると、一度だけ呼び出される関数を定義する
client.on("ready", async () => {
  // コマンドを定義する
  const chat = [
    {
      name: "gpt",
      description: "質問したら答えが返ってきます",
      options: [
        {
          type: 3,
          name: "質問",
          description: "質問したい文を入れてください",
          required: true,
        },
      ],
    },
  ];

  // コマンドを登録する
  await client.application.commands.set(chat);
});

// インタラクション(コマンド)が作成されたときに呼び出される関数を定義する
client.on("interactionCreate", async (interaction) => {
  // インタラクションがコマンドでなければ、何もしない
  if (!interaction.isCommand()) return;

  // インタラクションがどのコマンドかを取得する
  const command = interaction.commandName;

  // gptコマンドが呼び出された場合、OpenAIに質問を送信する
  if (command === "gpt") {
    // 質問を取得する
    const question = interaction.options.getString("質問");
    console.log(question); // 質問がコンソールに出力される

    // interactionの返信を遅延する
    await interaction.deferReply();

    // OpenAIに質問を送信し、回答を取得する
    (async () => {
      try {
        const completion = await openai.createChatCompletion({
          model: "gpt-3.5-turbo",
          messages: [{ role: "user", content: `${question}` }],
        });
        const answer = completion.data.choices[0].text;
        await interaction.editReply(
          `${question}\n>>${completion.data.choices[0].message.content.trim()}\r\n`
        );
      } catch (error) {
        console.error(error);
        await interaction.editReply(`エラーが発生しました: ${error.message}`);
      }
    })();
  }
});

//Discordクライアントにログイン
client.login(process.env.BOT_TOKEN);

詳しい説明は省略しますが、/gptというスラッシュコマンドを作成し、コマンドの引数に質問を入力しています。
下の部分でgpt-3-turboのオプションを設定しています。ここを変える事で動作が変わります。詳細は、詳細はOpenAIのドキュメンテーションを参照してください。

    // OpenAIに質問を送信し、回答を取得する
    (async () => {
      try {
        const completion = await openai.createChatCompletion({
          model: "gpt-3.5-turbo",
          messages: [{ role: "user", content: `${question}` }],
        });

Discord botの招待

Discordの開発者ポータルを開きOAuth2→URL Generatorを押します。
そして、以下のように設定します。
image.png
一番下にGENERATED URLというものがあるので、それをコピーします。
コピーしたリンクを開くとどのサーバーに追加するかを選択できるので、追加するサーバーを選択しbotを入れます。

実行

以下のコマンドをターミナルで打ち込むと、botが起動します。

node bot/index.js

Discord上で以下のように、/gpt 質問と入力し、送信します。
image.png
すると以下のような返答になりました。
ChatGPTと同じような動作をしています。
image.png

おわりに

結構サクッと書いていますが結構情報量が少なくコーディングに時間がかかりました。
Discord.jsは情報が少なかったのですが、ChatGPTを使って質問するのがGoogleで検索するよりも明らかに効率が良いことに驚きました。
このAPIを使えば様々なことに転用できそうですね。
最後まで見ていただきありがとうございました!

9
14
3

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
9
14