※※ 2023年 3月 12日 連絡追記 ※※
こちらの記事にて、stream対応版(1文字~1単語ずつ画面表示する)に修正しましたので、実装の説明はそちらを参照してください。
※stream対応しない版として、実装差異の確認ためこちらの記事は残しておきます。
概要
日本時間の2023年3月2日、OpenAIより"gpt-3.5-turbo"が公開されました。
これは、ChatGPTの内部で利用されているモデルがAPIとして公開されたものらしく、これまでの他のOpenAIのテキスト系生成AIよりも価格が1/10で、しかも応答が速い、とのことで、使わない手はありません。
そこで、APIの利用の練習も兼ねて、ChatGPTのAPI呼び出しをReact+Node.jsで実装してみました。
ソースをGitHubにて公開しています。
本記事では、動作手順と実装内容の抜粋を説明します。
Playgroundとは何が違う?
"gpt-3.5-turbo"は、OpenAI APIのPlaygroundからも利用が可能です。
今回作成したものはおおよそ同じことができますが、以下の違いがあります。
- 会話の保存ができます。
- 「summalize」ボタンを押すと、それまでの会話の要約を作ります。APIは、トークン数(≒扱える文章の長さ)には上限があるため、長くなってきたらこのボタンを押すことで要約し、会話を続けることができます。
- 応答のメッセージは、非同期では表示されません。APIから全文の応答があってから、画面に出力されます。
- Temparetureなどパラメーターは調整できません。
使用例
起動すると、以下のような画面が開きます。
- 左上の「System」が、システムパラメーターです。ChatGPTの役割を記載します。
- その下の「request」が、ユーザーが書き込むリクエスト内容です。入力してから、「Shift+Enter」または「send message」ボタンで送信します。
- 右の「chat gpt response」が、ユーザーとアシスタント(ChatGPT)の会話の履歴です。リクエストを投げると、この内容も自動的にAPIに渡されます。このため、会話の経緯も込みでAPIとやり取りが可能です。尚、経緯を書き換えることも可能です。
- 画面中央あたりの「summarrize」が、会話の要約ボタンです。右側の会話をクリアして、要約したものに書き換えます。
- 左下の「save」の欄に任意の名前を入力してsaveボタンを押すと、画面の内容を保存します。loadボタンを押すと、saveした時の内容を復元します。
動作手順
sample-chatgpt-nodejsのReadmeでも説明してますが、ざっくりこの記事でも説明します。
1.Node.js(npm)をPCにインストールする
Node.jsで動作するため、npmがコマンドプロンプトから実行できるようにインストールしてください。
2.GitHubからクローンする
sample-chatgpt-nodejsをローカルにクローンしてください。
GitHubのクライアントがあると便利ですが、無い場合は「Code」から「Download.zip」でダウンロードして解答してもOKです。
3.backフォルダで「npm install」を実行する。
backフォルダに、Reactをリリース形式にしたJavaScript類と、Node.jsとして動作するtsファイルなどがあります。
「npm install」を実行することで、Node.jsとして動作するために必要なプラグインをダウンロードします。
$ cd back
$ npm install
4.環境変数にAPIキーを設定する。
定番ですが、環境変数にAPIキーを設定します。
APIキーの取得方法はOpenAI APIのページなどを参照してください。
$ export OPENAI_API_KEY="APIキー"
5.Node.jsを起動する。
backフォルダにて、Node.jsを起動します。
npm start
実装内容の説明
OpenAIのReferenceからだいたいそのまま作った感じですが、API呼び出しの実装のあたりを紹介します。
サーバーは、Node.jsのフレームワークのExpressを利用しました。
import express from "express";
const app: express.Express = express();
app.use(express.json());
const port = 8000;
app.post("/api", (req: express.Request, res: express.Response) => {
const body = req.body;
// ここからOpenAI APIの呼び出し
});
以下のようにconfigにAPIキーを設定します。
let configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
あとは、画面の入力内容をChatCompletionRequestMessageのArrayに入れて、OpenAI APIを呼び出し、応答をレスポンスに設定します。
// メッセージのArrayを作成
const messages:Array<ChatCompletionRequestMessage> = new Array<ChatCompletionRequestMessage>();
// systemを設定する
messages.push({ role: "system", content: jsonData.system });
// メッセージを設定する
messages.push({ role: "user", content: message });
// メッセージを送信する
const completion = openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: messages
});
// 応答を返却する。
completion.then(response => {
res.json({ message : response.data.choices[0].message});
}).catch(e => {
console.log(e);
res.json({ message : e });
});
補足
- 突貫で作ったので、ソースが綺麗じゃないのはご容赦ください。
- 保存した名前が何だったかわからなくなった場合は、backフォルダのひとつ上のフォルダを確認してください。リクエスト内容がjsonで保存されています。
- 利用にあたっては自己責任でお願いします。
- APIキーが誤っていたり、トークン数を超えると、応答が「undefined」になります。必用に応じてやり直してください。(ちょうぜつ手抜き実装)
まとめ
OpenAI APIのPlaygroundでもちょっと遊んでみたのですが、やはり会話の保存機能は欲しいなというのと、ChatGPTみたいに会話が長くなると途中でトークン数(4K)がオーバーしてしまうので、要約機能が欲しくてつけてみました。
これをベースに、新しいAPIの利用をいろいろ試してみたいと思います。