※内容が古くなりました、詳細は記事内で※【チャットAI】ChatGPTのAPI呼び出しをReact＋Node.jsで実装してみた（要約機能、会話保存機能付き）

# ※※ 2023年 3月 12日 連絡追記 ※※
[こちらの記事](https://qiita.com/falman_ai/items/d7f46c6ff7645ed03d4e)にて、stream対応版（１文字～１単語ずつ画面表示する）に修正しましたので、実装の説明はそちらを参照してください。

※stream対応しない版として、実装差異の確認ためこちらの記事は残しておきます。

# 概要
日本時間の2023年3月2日、OpenAIより"gpt-3.5-turbo"が公開されました。
これは、ChatGPTの内部で利用されているモデルがAPIとして公開されたものらしく、これまでの他のOpenAIのテキスト系生成AIよりも価格が1/10で、しかも応答が速い、とのことで、使わない手はありません。
そこで、APIの利用の練習も兼ねて、ChatGPTのAPI呼び出しをReact＋Node.jsで実装してみました。

ソースをGitHubにて公開しています。
本記事では、動作手順と実装内容の抜粋を説明します。

[sample-chatgpt-nodejs](https://github.com/falman-ai-coding/sample-chatgpt-nodejs)

# Playgroundとは何が違う？
"gpt-3.5-turbo"は、OpenAI APIの[Playground](https://platform.openai.com/playground)からも利用が可能です。
今回作成したものはおおよそ同じことができますが、以下の違いがあります。

- 会話の保存ができます。
- 「summalize」ボタンを押すと、それまでの会話の要約を作ります。APIは、トークン数（≒扱える文章の長さ）には上限があるため、長くなってきたらこのボタンを押すことで要約し、会話を続けることができます。
- 応答のメッセージは、非同期では表示されません。APIから全文の応答があってから、画面に出力されます。
- Temparetureなどパラメーターは調整できません。

# 使用例
起動すると、以下のような画面が開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3142603/9cc346b5-a156-de8b-c5d4-84b66a2e158f.png)

- 左上の「System」が、システムパラメーターです。ChatGPTの役割を記載します。
- その下の「request」が、ユーザーが書き込むリクエスト内容です。入力してから、「Shift+Enter」または「send message」ボタンで送信します。
- 右の「chat gpt response」が、ユーザーとアシスタント（ChatGPT）の会話の履歴です。リクエストを投げると、この内容も自動的にAPIに渡されます。このため、会話の経緯も込みでAPIとやり取りが可能です。尚、経緯を書き換えることも可能です。
- 画面中央あたりの「summarrize」が、会話の要約ボタンです。右側の会話をクリアして、要約したものに書き換えます。
- 左下の「save」の欄に任意の名前を入力してsaveボタンを押すと、画面の内容を保存します。loadボタンを押すと、saveした時の内容を復元します。


# 動作手順
[sample-chatgpt-nodejs](https://github.com/falman-ai-coding/sample-chatgpt-nodejs)のReadmeでも説明してますが、ざっくりこの記事でも説明します。

## 1.Node.js(npm)をPCにインストールする
Node.jsで動作するため、npmがコマンドプロンプトから実行できるようにインストールしてください。

[Node.js](https://nodejs.org/ja/)

## 2.GitHubからクローンする
[sample-chatgpt-nodejs](https://github.com/falman-ai-coding/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のページ](https://platform.openai.com/)などを参照してください。

```
$ export OPENAI_API_KEY="APIキー"
```

## 5.Node.jsを起動する。
backフォルダにて、Node.jsを起動します。

```
npm start
```

# 実装内容の説明
OpenAIのReferenceからだいたいそのまま作った感じですが、API呼び出しの実装のあたりを紹介します。

サーバーは、Node.jsのフレームワークのExpressを利用しました。
```TypeScript:（抜粋）
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キーを設定します。

```TypeScript:（抜粋）
let configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
```

あとは、画面の入力内容をChatCompletionRequestMessageのArrayに入れて、OpenAI APIを呼び出し、応答をレスポンスに設定します。

```TypeScript:（抜粋）
// メッセージの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の利用をいろいろ試してみたいと思います。