Как поставщик услуг языковой модели искусственного интеллекта, OpenAI предоставляет ряд интерфейсов API, большинство из которых требуют доступа через HTTP-запросы. При запросах больших объемов данных традиционные синхронные запросы вызывают медленный ответ сети и не могут удовлетворить потребности обработки и анализа данных в реальном времени. Таким образом, чтобы оптимизировать эффективность вызовов этих интерфейсов, мы можем использовать технологию SSE (события, отправленные сервером) для реализации потокового вывода, чтобы гарантировать, что данные могут достигать клиента в режиме реального времени, и повысить эффективность обработки данных.
На языке PHP мы можем использовать библиотеки инструментов, такие как библиотека GuzzleHttp и библиотека ReactPHP, для реализации вызовов интерфейса API OpenAI и потоковой передачи вывода через технологию SSE. Ниже приведен конкретный код
use GuzzleHttp\Client;
use GuzzleHttp\Event\CompleteEvent;
use GuzzleHttp\Event\MessageCompleteEvent;
use GuzzleHttp\Message\Response;
use GuzzleHttp\Stream\Stream;
use React\EventLoop\Factory as EventLoopFactory;
use React\EventLoop\LoopInterface;
$openaiAccessToken = 'YOUR_OPENAI_ACCESS_TOKEN'; // Пожалуйста, замените на настоящий из Access Токен можно получить на сайтеchat.xingtupai.com.
function openaiApiRequestWithSse($query): void
{
global $openaiAccessToken;
$loop = EventLoopFactory::create();
$client = new Client();
$request = $client->createRequest('POST', 'https://api.openai.com/v1/engines/davinci-codex/completions');
$request->setHeader('Content-Type', 'application/json');
$request->setHeader('Authorization', "Bearer {$openaiAccessToken}");
$request->setBody(Stream::factory(json_encode($query)));
$client->send($request)->then(function (Response $response) use ($loop) {
echo 'data: ';
$stream = $response->getBody()->detach();
stream_set_blocking($stream, false);
$loop->addReadStream($stream, function ($stream, LoopInterface $loop) {
$data = '';
while ($buffer = fgets($stream, 2048)) {
$event = new MessageCompleteEvent(
new CompleteEvent(),
$response = new Response(200),
Stream::factory($buffer)
);
$data .= $buffer;
if (strpos($buffer, "\n\n") !== false) {
$loop->removeReadStream($stream);
$event->response = new Response(200, [], Stream::factory($data));
echo $data . PHP_EOL;
break;
}
}
});
});
$loop->run();
}
Давайте объясним приведенный выше код подробно. Сначала мы инициализировали HTTP-клиент Guzzle, а затем создали запрос OpenAI API. Затем мы устанавливаем заголовок запроса Authorization и передаем токен доступа, предоставленный OpenAI, чтобы убедиться, что у нас есть права доступа к API. Затем мы JSON сериализуем условия запроса в теле запроса и устанавливаем тело запроса в сериализованную строку JSON для последующих запросов.
Далее мы отправляем запрос и обрабатываем поток ответов, возвращаемый OpenAI. Обратите внимание, что здесь мы настраиваем прослушивание событий для потока ответов, чтобы проанализировать результаты ответа и добиться потокового вывода. В частности, мы вызвали метод addReadStream класса EventLoop, чтобы передать поток ответов OpenAI и параметры функции прослушивания потока ответов в цикл событий. В цикле событий мы получаем данные из потока ответов и читаем их построчно через цикл и функцию fgets. Затем мы используем цикл while, чтобы определить, содержат ли считанные данные два символа новой строки. Если данные содержат два символа новой строки, это означает, что текущие данные были прочитаны и сформирован полный результат данных. Итак, мы вызвали метод removeReadStream класса EventLoop, чтобы удалить текущий монитор потока ответов из цикла событий. Наконец, мы выводим текущий результат данных ответа.
Благодаря реализации приведенного выше кода мы можем легко выполнять вызовы SSE к интерфейсу API OpenAI для достижения потокового вывода и эффективного повышения эффективности обработки данных.
Примечание. Только для справки, я еще не проверял.