Loading...

BLOG ブログ
BLOG

BLOGブログ

2023-03-31技術的コラム

未来のチャットボット!OpenAI APIで対話型プログラムを手軽に作成

概要

話題のchatGPTですが、2023/3/14に最新の人工知能モデル「GPT-4」がリリースされました。
流行に遅れないようにと個人的にGPT-4に課金しましたが、とてつもない性能だと感心しています。

今回は、chatGPTの制作元のOpenAIが提供しているOpenAI APIを使った対話プログラムを作成しようと思います。
ただ、せっかくGPT-4に課金したので、自分でコードは書かず作ってもらいたいと思います。
OpenaAI APIの使い方も合わせて説明していきます。

公式リファレンスを参考にすれば、分かりやすいかと思います。
https://platform.openai.com/docs/api-reference/introduction?lang=curlhttps://platform.openai.com/docs/api-reference/introduction?lang=curl

公式で提供しているライブラリがpythonやnode.jsなので、OpenAI APIの関連記事がそれらの言語に偏っている気がしました。そこで、初学者でも馴染みのあるphpで作成しようと思います。しかし、phpでhttp通信をするにはライブラリを使うか、curlを使う必要があるので、その辺も考慮してプログラムを生成してくれるか、注目していきます。

GPT-4で対話型プログラムを生成

ここから先が、プログラムの生成の過程です。

--------------------------------------------------------------------------------------------------------------------

自分: phpでopenAIを使って対話型プログラムを生成してください

GPT-4:
OpenAIのGPTモデルを使って、PHPで対話型プログラムを作成するには、まずOpenAIのAPIを利用するためのクライアントライブラリをインストールし、その後でAPIを利用してモデルに質問を送信し、回答を受け取るプログラムを実装します。以下に手順を示します。

  1. まずはOpenAIのAPIキーを取得します。https://beta.openai.com/signup/にアクセスしてアカウントを作成し、APIキーを取得してください。
  2. PHPでOpenAI APIを利用するためのクライアントライブラリがない場合、GuzzleというHTTPクライアントを使ってAPIとやり取りしましょう。Composerを使ってGuzzleをインストールします。
composer require guzzlehttp/guzzle
  1. 以下のPHPコードを参考に、対話型プログラムを実装します。APIキーを YOUR_API_KEY の部分に入力してください。
<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

function promptUser($message) {
    echo $message;
    return rtrim(fgets(STDIN));
}

function fetchGptResponse($apiKey, $input) {
    $client = new Client([
        'base_uri' => 'https://api.openai.com/v1/engines/davinci-codex/completions',
        'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $apiKey
        ]
    ]);

    $payload = json_encode([
        'prompt' => $input,
        'max_tokens' => 150,
        'n' => 1,
        'stop' => null,
        'temperature' => 0.5,
    ]);

    try {
        $response = $client->post('', ['body' => $payload]);
        $result = json_decode($response->getBody(), true);
        return $result['choices'][0]['text'];
    } catch (Exception $e) {
        echo 'Error: ' . $e->getMessage();
        return '';
    }
}

$apiKey = 'YOUR_API_KEY';

echo "対話型プログラムへようこそ!\n";
echo "質問を入力してください。終了するには 'exit' と入力してください。\n";

while (true) {
    $input = promptUser("> ");
    if ($input === 'exit') {
        break;
    }

    $gptResponse = fetchGptResponse($apiKey, $input);
    echo "GPT-4: " . $gptResponse . "\n";
}

echo "対話を終了します。";

自分: composerファイルはどうやって作成したら良いですか?

GPT-4:
Composerファイル(composer.json)は、プロジェクトの依存関係やオートローディング設定など、プロジェクトの構成情報を記述するためのファイルです。Composerファイルを作成するには、以下の手順に従ってください。

  1. ターミナルでプロジェクトのルートディレクトリに移動します。
  2. 次のコマンドを実行して、composer.json ファイルを生成します。
composer init
  1. コマンドが実行されると、対話形式でプロジェクトに関する情報を入力します。例えば、プロジェクト名、説明、作者、ライセンスなどです。デフォルトの設定で問題ない場合は、そのままEnterキーを押して次へ進んでください。
  2. composer init コマンドが完了すると、composer.json ファイルがプロジェクトのルートディレクトリに生成されます。

例として、以下のような composer.json ファイルが生成されるでしょう。

{
    "name": "yourname/yourproject",
    "description": "A sample project using OpenAI with PHP",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
            "name": "Your Name",
            "email": "your.email@example.com"
        }
    ],
    "require": {}
}

依存関係を追加するには、composer.json ファイルの require セクションにパッケージ名とバージョンを追記します。ただし、通常は composer require コマンドを使って依存関係を追加し、composer.json ファイルが自動的に更新されるので、手動で編集する必要はありません。例えば、Guzzleをインストールするには次のコマンドを実行します。

composer require guzzlehttp/guzzle
  1. コマンドが成功すると、composer.jsonrequire セクションにGuzzleが追加され、composer.lock ファイルと vendor ディレクトリが生成されます。これでプロジェクトの依存関係が管理されるようになります。

これで、Composerファイルの作成と依存関係の追加が完了しました。Composerを使ってプロジェクトを管理することで、依存関係のインストールやアップデートが簡単になり、他の開発者との共同作業が容易になります。

--------------------------------------------------------------------------------------------------------------------

ここまででプログラム生成ファイルを作成してくれました。公式だとcurlの説明がありましたが、Guzzleを使うように教えてくれています。composerインストールの解説も丁寧で非常に分かりやすい。
初学者でも十分わかる内容だと思いました。すごすぎ。。

実際に動くか確認

さて、それっぽく動きそうですが、実際動作するか検証してみます。

ChatGPT4が説明してくれているように、OpenAI APIを使うにはAPI KEYを作成する必要があります。新規登録してリンクから発行できます。ちゃんと漏れないように保管しておきます。https://platform.openai.com/account/api-keys

ファイルを実行してみます。phpのwarningがでていますが、これは関係ないので無視してください。
ちゃんとファイルは実行されています!

次に「こんにちは」と入力してみます。

ん?思ったのと違う回答が返ってきましたね。。

ちょっとソースを確認してみます。

対話プログラムを作成してとオーダーしましたが、エンドポイントが異なっているようです。

'base_uri' => 'https://api.openai.com/v1/engines/davinci-codex/completions'

davinci-codexはGPT-4曰く、「OpenAIのGPT-3ファミリーの一部で、高度な言語理解とコーディング能力を持っています。このエンドポイントを使うことで、特定のエンジンに対してリクエストを送信し、そのエンジンに基づいて生成されたテキストを取得できます。」らしいです。

少し手直しが必要そうなので、エンドポイントをchatに変えて一部修正します。

修正してみる

chatのエンドポイントを使って、プログラムを少し修正しました。
こちらは自分で手を加えています。
chatのリファレンスはこちら(https://platform.openai.com/docs/api-reference/chat)

修正した内容がこちらです。

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

function promptUser($message) {
    echo $message;
    return rtrim(fgets(STDIN));
}

function fetchGptResponse($apiKey, $messages) {
    $client = new Client([
        'base_uri' => 'https://api.openai.com/v1/chat/completions',
        'headers' => [
            'Content-Type' => 'application/json',
            'Authorization' => 'Bearer ' . $apiKey
        ]
    ]);

    $payload = [
        'model' => 'gpt-3.5-turbo',
        "messages" => $messages,
        'max_tokens' => 150,
        'n' => 1,
        'stop' => null,
        'temperature' => 0.7,
    ];

    try {
        $response = $client->post('', ['json' => $payload]);
        $result = json_decode($response->getBody(), true);
        return $result['choices'][0]['message']['content'];
    } catch (Exception $e) {
        echo 'Error: ' . $e->getMessage();
        return '';
    }
}

$apiKey = $API_KEY;

echo "対話型プログラムへようこそ!\n";
echo "質問を入力してください。終了するには 'exit' と入力してください。\n";

$messages = [["role" => "system", "content" => "あなたは100歳のお爺さんです。回答するときはお爺さんのように回答してください。"]];
while (true) {
    $input = promptUser("あなた > ");
    if ($input === 'exit') {
        break;
    }
    array_push($messages, ["role" => "user", "content" => $input]);
    $gptResponse = fetchGptResponse($apiKey, $messages);
    echo "お爺さん: " . $gptResponse . "\n";
}

echo "対話を終了します。";

主な修正内容は、3点あります。

1. エンドポイントの変更

chat用のエンドポイントに変更しました。

'base_uri' => 'https://api.openai.com/v1/chat/completions'

2. requestのbodyにmodelとmessagesの追加

    $payload = [
        'model' => 'gpt-3.5-turbo',
        "messages" => $messages,
        'max_tokens' => 150,
        'n' => 1,
        'temperature' => 0.7,
    ];

chat用のエンドポイントを使う場合、bodyに含めるパラメータにmodelとmessageが必須になります。
各パラメータについて説明します。

model:
必須のパラメータです。モデルはエンドポイントごとに種類があります。最新版はgpt-4のモデルですが、使用するには予約が必要なようだったので、`gpt-3.5-turbo`を使用しています。(https://platform.openai.com/docs/models/gpt-3)

messages:
必須のパラメータです。システムに渡す値を設定します。(https://platform.openai.com/docs/guides/chat/introduction)

max_tokens:
モデルが生成する応答の最大トークン数を制限するために使用されます。
具体的な使用方法をGPT-4に聞いたところ、以下の回答がありました。
1. 応答の長さを制御することができます。短い回答を望んでいる場合や、長すぎる回答が不適切であるアプリケーションに適した結果を得ることができます。
2. 生成されるテキストの品質を向上させることができます。長すぎる回答が短い回答よりも品質が低下しやすいため、適切な max_tokens の設定が重要です。
3. APIのコストを抑えることができます。OpenAI APIの課金は、リクエストと応答のトークン数に基づいて行われるため、max_tokens を適切に設定することで、使用料金を抑制することができます。」

n :
各入力メッセージに対して、チャット補完の選択肢をいくつ生成するかに使われます。

temperature:
0から1の範囲の値で設定でき、高い値(0.8)などを設定するとより多様な回答が得られるようになります。ただし、高い値だと意味不明の回答になることもあります。低い値だと回答に面白みがなく、冗長的になりますが、一貫性のある回答を得られます。

3. roleの設定

$messagesに配列の形でroleとcontentを追加しています。

roleは「system」,「user」,「assistant」の三つを持っています。
system: GPT-4にどのような振る舞いをさせたいか定義します。
user: GPT-4に対してユーザーから指示を出します。具体的には入力内容を設定します。
assistant: 今回は使いませんでしたが、事前の応答を保存して文脈を把握して質問に答えることができます。
例えば、事前にassistantに「2020年のワールドシリーズは、テキサス州アーリントンのグローブライフ・フィールドで行われました。」と設定しておくことで、「それはどこで開催されましたか?」という質問に答えることができます。

今回はsystemにキャラ付けを行うことで、少し面白くしてみました。

各roleの設定などはリファレンスを参照してください(https://platform.openai.com/docs/guides/chat)

$messages = [["role" => "system", "content" => "あなたは100歳のお爺さんです。回答するときはお爺さんのように回答してください。"]];
array_push($messages, ["role" => "user", "content" => $input]);

修正内容の実行

修正した内容で実行したところ、無事回答を得ることができました。

素晴らしいです。簡単にチャットbotのサービスを作れそうだし、何より色んなキャラクターも設定できて面白いです。今後のエンジニアの開発はAIをいかに上手く使うかにかかってきそうですね。

ちなみにタイトルである「未来のチャットボット!OpenAI APIで対話型プログラムを手軽に作成」もGPT-4に提案してもらいました。

今回は以上になります。何か面白い内容がありましたら、また記事にしたいと思います。

奥村彰良

Akiyoshi Okumura

バックエンドエンジニア


Share