ピーナッツのブログ(仮)

OpenAI APIで簡単なchatbotを作る

動機

勉強も兼ねて簡単なwebアプリケーション的なものを作りたい、と思ったので作ることにしました。

環境

  • macOS 14.21.1
  • yarn 3.6.0

API通信ができるかどうか確認

API keyの取得

割愛します。参考ページ

ちなみにopen AI APIは有料です。

ターミナルでapi通信を試みる

公式リファレンス通り進めていきます。

curlコマンドで下記を実行します。$OPENAI_API_KEYの部分は取得したAPI keyを入れてください。

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
     "model": "gpt-3.5-turbo",
     "messages": [{"role": "user", "content": "Say this is a test!"}],
     "temperature": 0.7
   }'

下記のようなレスポンスがあれば成功です。

{
    "id": "chatcmpl-abc123",
    "object": "chat.completion",
    "created": 1677858242,
    "model": "gpt-3.5-turbo-0613",
    "usage": {
        "prompt_tokens": 13,
        "completion_tokens": 7,
        "total_tokens": 20
    },
    "choices": [
        {
            "message": {
                "role": "assistant",
                "content": "\n\nThis is a test!"
            },
            "logprobs": null,
            "finish_reason": "stop",
            "index": 0
        }
    ]
}

apiの接続が確認できたので、次はnode経由で接続できるようにします。

nodeでAPI通信

まずは、下記を実行しライブラリを取得します。

yarn add openai

apiTest.js(ファイル名は任意)を作成し、下記をコピペしてください。OPENAI_API_KEYの部分は自身のAPI keyに置き換えてください。(API keyは後ほどenvファイルに移動します。)


const OpenAI = require("openai");

const openai = new OpenAI({
  apiKey: "OPENAI_API_KEY",
});

async function main() {
  const stream = await openai.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: "Say this is a test" }],
    stream: true,
  });
  for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content || "");
  }
}

main();

apiTest.js

ターミナルで、下記を実行し、This is a test.と帰ってくれば成功です。

node apiTest.js

実装

バックエンド

必要なパッケージをインストール

yarn add express dotenv cors

.envファイル作成

.envファイルを作成し、write_api_keyの部分に自身のAPI keyを入力してください

OPENAI_API_KEY=write_api_key

server.jsファイル(ファイル名は任意)を作成し、下記のように記述します。

ポート番号やエンドポイントはご自分の環境に合わせて設定してください。

const express = require("express");
const { OpenAI } = require("openai");
require("dotenv").config();
const cors = require("cors");
const app = express();
app.use(express.json());
app.use(cors());

const openai = new OpenAI(process.env.OPENAI_API_KEY);
app.use(express.json());
app.post("/chat", async (req, res) => {
  try {
    const response = await openai.chat.completions.create({
      model: "gpt-4",
      messages: [
        {
          role: "user",
          content: req.body.message,
        },
      ],
      stream: true,
    });

    let responseContent = "";
    for await (const chunk of response) {
      responseContent += chunk.choices[0]?.delta?.content || "";
    }

    // フロントエンドにレスポンスを送信
    res.json({ message: responseContent });
  } catch (error) {
    console.error("OpenAI APIの呼び出し中にエラーが発生しました。", error);
    res.status(500).send("OpenAI APIの呼び出し中にエラーが発生しました。");
  }
});

const PORT = 3001;
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});
server.js

フロントエンドの構築

とりあえず動けばいいので最低限の内容にします。index.htmlを作成。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>chat bot</title>
  </head>
  <body>
    <h1>chat bot</h1>
    <form id="sentenceForm">
      <input
        type="text"
        id="sentenceInput"
        placeholder="ここに文章を入力してください"
      />
      <button type="submit">送信</button>
    </form>
    <p id="answer"></p>

    <script src="./app.js"></script>
  </body>
</html>
index.html

app.jsを作成し、下記のように記述します。

document.addEventListener("DOMContentLoaded", function () {
  const form = document.getElementById("sentenceForm");
  form.addEventListener("submit", function (e) {
    e.preventDefault(); // フォームのデフォルト送信を阻止
    const sentenceInput = document.getElementById("sentenceInput").value;
    const answerElement = document.getElementById("answer");

    fetch("http://localhost:3001/chat", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ message: sentenceInput }),
    })
      .then((response) => {
        console.log(response, "response"); // レスポンスオブジェクトをログに出力
        return response.json();
      })
      .then((data) => {
        console.log(data, "data");
        answerElement.textContent = data.message; // バックエンドからの応答を表示
      })
      .catch((error) => {
        console.error("Error:", error);
        answerElement.textContent =
          "エラーが発生しました。もう一度試してください。";
      });
  });
});
app.js

動作確認

フロントのローカルサーバーを立てるためhttp-serverを追加します。(ローカルサーバーが立てられればなんでもいいです。)

yarn add http-server

フロント、バックエンドそれぞれローカルサーバーを立てます。

node server.js
yarn http-server

フロントのローカルサーバーにブラウザからアクセスし、テキストを入力の上送信ボタンを押すとレスポンスが帰ってきます。

レスポンスがくるまでちょっと時間かかりますが、、

所感

ソースをchatGPTに考えさせて書いてみたらあっさり完成してしまいました。最近の生成AIの進歩はすごい…

このアプリを進化させて、ちょっとしたwebアプリケーションをリリースしたいなと思っています。

参考サイト