Вы когда-нибудь задумывались, как воссоздать знаменитый «эффект печати» ChatGPT в собственных веб-приложениях?

Потоковая передача данных, а не предоставление их в статическом формате, может создавать привлекательные интерфейсы и повышать удовлетворенность пользователей. Поскольку пользователям не нужно долго ждать появления текстового ответа, они остаются более заинтересованными и менее нетерпеливыми. К тому же… выглядит круто!

В этом сообщении блога мы объясним концепцию потоковой передачи и ее преимущества, а также продемонстрируем, как выполнять потоковую передачу текста в реальном времени с помощью API OpenAI ChatGPT и Ajax (PHP с JavaScript).

  1. Что такое потоковое вещание и его преимущества

Под потоковой передачей в веб-приложениях понимается предоставление данных пользователю в виде непрерывного потока вместо того, чтобы объединять их в единый статический пакет. Это особенно полезно в случаях, когда содержимое может генерироваться «на лету» или когда размер данных может быть непредсказуемым. Некоторые преимущества потоковой передачи включают в себя:

  • Визуализация в режиме реального времени. Потоковые данные могут создать захватывающий пользовательский интерфейс, отражающий текущие события, такие как живые чаты или корреляции данных.
  • Вовлечение пользователей: отображение контента в режиме реального времени может заинтересовать пользователей и побудить их взаимодействовать с вашей платформой.
  • Эффективная обработка данных: потоковая передача позволяет обрабатывать большие объемы данных без значительных задержек или перегрузки ресурсов сервера.

2. Предпосылки

Чтобы упростить потоковую передачу текста в реальном времени с помощью API OpenAI ChatGPT, мы будем использовать следующие технологии:

  • API OpenAI: зарегистрируйте учетную запись OpenAI и получите ключ API.
  • PHP: убедитесь, что ваш веб-сервер поддерживает возможности PHP.
  • JavaScript: базовые знания о том, как взаимодействовать с HTML через JavaScript.

3. Настройка серверного PHP-скрипта

Первым шагом является создание PHP-скрипта на стороне сервера, который взаимодействует с API OpenAI. Этот скрипт должен использовать потоки событий для отправки данных клиенту порциями, что позволяет отображать данные в реальном времени.

<?php
// Set the headers for Server-Sent Events (SSE) and prevent caching
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');

// Define the API key (replace this with your actual API key)
define('API_KEY', 'sk-YOUR-KEY-HERE');

// Get the input from the user via a GET parameter
$input = $_GET['input'];
$prompt = $input;

// Prepare the request data to be sent to the GPT API
$data = array(
  'model' => 'gpt-3.5-turbo',
  'stream' => true,
  'messages' => array(
    array(
      'role' => 'user',
      'content' => $prompt
    )
  )
);

// Set the curl options for the API request
$options = array(
  CURLOPT_URL => 'https://api.openai.com/v1/chat/completions',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POSTFIELDS => json_encode($data),
  CURLOPT_HTTPHEADER => array(
    'Content-Type: application/json',
    'Authorization: Bearer ' . API_KEY
  ),
  // Process each chunk of data as it arrives
  CURLOPT_WRITEFUNCTION => function($ch, $chunk) {
    echo $chunk;
    return strlen($chunk);
  }
);

// Initialize the curl request
$ch = curl_init();

// Set the curl options specified earlier
curl_setopt_array($ch, $options);

// Execute the curl request and close the connection
curl_exec($ch);
curl_close($ch);

?>

Сценарий использует cURL для выполнения вызова API, а CURLOPT_WRITEFUNCTION настроена на пользовательскую функцию, которая обрабатывает фрагменты данных по мере их поступления, отправляя данные на клиентский JavaScript с помощью echo.

Он использует события, отправленные сервером (SSE), для непрерывной передачи данных в режиме реального времени при обработке ответов API по частям, что позволяет получать поток данных из API в реальном времени.

Ожидаемый результат:

Теперь вы сможете протестировать файл PHP. Либо установите текстовую переменную подсказки ввода «$ input» вручную для тестирования, либо передайте ей переменную $_GET в URL-адресе как «?input=Your prompt here».

Вы должны увидеть потоковую передачу «фрагментов данных», поскольку скрипт анализирует ответ от ChatGPT API:

4. Что такое события, отправленные сервером (SSE)?

События, отправленные сервером (SSE), – это технология, обеспечивающая непрерывный обмен данными в режиме реального времени между сервером и клиентом (обычно веб-браузером) через одно HTTP-соединение. Это простой и эффективный протокол для отправки обновлений в реальном времени с сервера клиенту, который в основном используется для включения обновлений данных в реальном времени, таких как уведомления или оперативные обновления в приложениях.

События, отправленные сервером (SSE), обеспечивают связь в реальном времени между сервером (скрипт PHP) и клиентом (JavaScript), обрабатывая и отправляя данные порциями по мере их поступления. Это приводит к живому потоку данных из API, который можно эффективно и беспрепятственно отображать или манипулировать на стороне клиента.

5. Отображение читаемого текста с помощью Javascript

Файл PHP работает для разбора потока, но он все еще не в удобочитаемом формате. Чтобы создать интерфейс на стороне клиента, настройте макет HTML, который включает div с идентификатором 'streamingText'. Здесь ответ API будет отображаться в режиме реального времени.

<html>
<body>
<div id="streamingText" style="font-size: 22px; overflow: scroll;"></div>
</body>
</html>

Используйте JavaScript для отправки пользовательского ввода через URL-адрес и запроса текстовой информации. Следующий фрагмент кода JavaScript иллюстрирует, как взаимодействовать с файлом PHP на стороне сервера и обрабатывать результаты:

<script>
// Set your request input
const yourInput = 'Generate example text of medium length, talking about the feature of API response streaming to resemble real time typing, from the ChatGPT API.';

// Send the input data as a query parameter to your PHP script
const url = `ajax.php?input=${encodeURIComponent(yourInput)}`;

// Create a new EventSource object for real-time server-sent events (SSE)
const source = new EventSource(url);

// Initialize the response content and current index for displaying typed characters
let responseContent = '';
const streamingTextElement = document.getElementById('streamingText');
let currentIndex = 0;

// Function that types out received chunks character by character
function typeCharacter() {
  if (currentIndex < responseContent.length) {
    streamingTextElement.textContent += responseContent.charAt(currentIndex);
    currentIndex++;
    setTimeout(typeCharacter, 100); // Adjust the typing speed by changing the delay (in milliseconds)
  }
}

// Process the received SSE events
source.onmessage = function (event) {
  const data = JSON.parse(event.data);

  if (data.id) {
    // Process the data message chunk
    const choices = data.choices;
    if (choices && choices.length > 0) {
      const content = choices[0].delta.content;
      if (content) {
        responseContent += content;
        typeCharacter();

        // Auto-scroll to the bottom as new content is added
        streamingTextElement.scrollTop = streamingTextElement.scrollHeight;
      }
    }
  } else if (data === '[DONE]') {
    // All data received, logging it and closing the connection
    console.log('All data received:', responseContent);
    source.close(); // Close the connection
  }
};

// Handling errors in receiving SSE events
source.onerror = function (error) {
  console.error('Error:', error);
  source.close(); // Close the connection
};
</script>

6. Реализация эффекта набора текста в реальном времени

Для имитации набора текста в реальном времени используйте функцию setTimeout в коде JavaScript. Эта функция позволяет определить задержку между отдельными символами, создавая визуальный эффект, напоминающий ввод текста в реальном времени.

Этот фрагмент уже включен в более длинный код выше, но вот он снова, чтобы вы могли видеть, что происходит:

// Function that types out received chunks character by character
function typeCharacter() {
  if (currentIndex < responseContent.length) {
    streamingTextElement.textContent += responseContent.charAt(currentIndex);
    currentIndex++;
    setTimeout(typeCharacter, 100); // Adjust the typing speed by changing the delay (in milliseconds)
  }
}

7. Обработка ошибок и завершение трансляции

Правильная обработка ошибок важна для любого приложения. Обработчик событий onerror регистрирует ошибки, закрывая соединение в случае возникновения проблем. Сообщение о событии, сигнализирующее о завершении, помогает закрыть соединение, когда больше нет данных для приема.

// Handling errors in receiving SSE events
source.onerror = function (error) {
  console.error('Error:', error);
  source.close(); // Close the connection
};

Заключение

Потоковая передача текста в режиме реального времени с использованием OpenAI ChatGPT API, PHP и JavaScript обеспечивает плавную визуализацию контента, повышает вовлеченность пользователей и эффективно обрабатывает данные.

Пример, представленный в этом сообщении в блоге, можно адаптировать для многих вариантов использования, включая чат-боты, генерацию живого контента и другие динамические приложения. Испытайте трансформацию, которую потоковая передача в реальном времени может принести вашим веб-приложениям, и откройте бесчисленные возможности для уникального взаимодействия с пользователем!