- PHP 8.2.12
- "guzzlehttp/guzzle": "^7.9"
OpenAI Assistants APIをPHPにて実装してみます。
HTTPクライアントはguzzleを使用します。Laravelでのシステムにて利用することを想定しています。
APIキーは、OPENAI_API_KEYという名前で環境変数に入れてあります。phpdotenvを使ってます。
$ composer require guzzlehttp/guzzle
$ composer require vlucas/phpdotenv
Assistantの作成とファイルのアップロード
Assistantの作成とファイルのアップロードはダッシュボードから行います。
- Assistantを作成し、名前を決めたりmodelを選択したり、役割を設定したりします
- Storageの作成画面で、Vecotor storesを選択します
- Vecotor storeを作成し名前を決めます
- ファイルをアップロードします。
- Vector storeのIDをコピーします
- Assistantの画面に戻ってTools > File Searchを有効にします
- ファイルの追加画面で、Vecotr storeのIDを入力し追加します
- AssistantのIDをコピーします > このIDをプログラムで使用します
実装:準備
先ほどコピーしたAssistantのIDを変数に入れます。
assistant.php
require __DIR__.'/vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Dotenv\Dotenv;
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();
$assistantId = 'asst_.....';
実装:Threadの作成
assistant.php
<?php
$header = [
'Authorization' => 'Bearer '.$_ENV['OPENAI_API_KEY'],
'Content-Type' => 'application/json',
'OpenAI-Beta' => 'assistants=v2'
];
$url = 'https://api.openai.com/v1/threads';
$client = new Client();
$response = $client->post($url, [
'headers' => $header,
]);
$thread = json_decode($response->getBody()->getContents(), true);
//print($thread['id']);
ThreadはIDを保存しておくと継続した会話ができます。
Threadが長くなるとAPIのコストが高くなるそうなので、今回Threadは一回きりで削除しています。
実装:Threadにメッセージを登録
assistant.php
$prompt = 'この資料の目的を教えてください。';
$url = 'https://api.openai.com/v1/threads/'.$thread['id'].'/messages';
$data = [
'role' => 'user',
'content' => [['type' => 'text', 'text' => $prompt]]
];
$response = $client->post($url, [
'headers' => $header,
'json' => $data,
]);
$message = json_decode($response->getBody()->getContents(), true);
// print($message['id'].PHP_EOL);
実装:Threadを実行する(Run)
assistant.php
$data = [
'assistant_id' => $assistantId
];
$url = 'https://api.openai.com/v1/threads/'.$thread['id'].'/runs';
$response = $client->post($url, [
'headers' => $header,
'json' => $data,
]);
$run = json_decode($response->getBody()->getContents(), true);
実装:実行完了を待つ
assistant.php
while($run['status'] != 'completed') {
print($run['status'].PHP_EOL);
$url = sprintf('https://api.openai.com/v1/threads/%s/runs/%s', $thread['id'], $run['id']);
$response = $client->get($url, [
'headers' => $header,
]);
$run = json_decode($response->getBody()->getContents(), true);
}
実装:実行結果のメッセージを取得する
実行結果に、注釈(annotations)が含まれているので、削除してます。
ファイルの参照箇所らしきものが書いてあるのですが、解釈の仕方がわかりませんでした。
assistant.php
$url = 'https://api.openai.com/v1/threads/'.$thread['id'].'/messages?order=asc&limit=100';
// $url .= '&after='.$lastMessageId;
$response = $client->get($url, [
'headers' => $header,
]);
$response = json_decode($response->getBody()->getContents(), true);
$messages = [];
foreach ($response['data'] as $message) {
$content = $message['content'][0]['text']['value'];
foreach ($message['content'][0]['text']['annotations'] as $annotation) {
$content = str_replace($annotation['text'], '', $content);
}
print($content.PHP_EOL);
}
実装:Threadを削除する
Threadはマメに削除する方針ですが、残しておく場合もあると思います。
assistant.php
$url = 'https://api.openai.com/v1/threads/'.$thread['id'];
$response = $client->delete($url, [
'headers' => $header,
]);
$response = json_decode($response->getBody()->getContents(), true);
if ($response['deleted'] == true) {
print('deleted');
}
紹介
OpenAI API, ChatGPTの組み込みサンプルを紹介しています。
ご興味あればみてみてください。