見出し画像

生成AIのタイプライターのような出力を実現するSSEについて

この記事では、生成AIとのリアルタイムなやりとりを実現する技術の一つである「SSE(Server-Sent Events)」について解説します。

ChatGPTやClaudeなどの生成AIがタイプライターのように文字を出力する際に使われている技術になります。


SSEとは?

SSE(Server-Sent Events)は、サーバーからクライアント(ブラウザ)へ一方向にデータをリアルタイムで送信するための技術です。従来のHTTP通信では、クライアントがリクエストを送り、サーバーがレスポンスを返すという1回限りのやりとりでしたが、SSEでは一度接続を確立すると、サーバーから継続的にデータを送信し続けることができます。

SSEの特徴

1. シンプルな実装

  • WebSocketと比較して実装が簡単

  • 標準的なHTTPプロトコル上で動作

  • 特別なプロトコルの切り替えが不要

2. 一方向通信

  • サーバーからクライアントへの一方向の通信のみ

  • クライアントからサーバーへデータを送りたい場合は、別途通常のHTTPリクエストが必要

3. 自動再接続

  • 接続が切れた場合に自動的に再接続を試みる機能が標準で組み込まれている

4. イベントID

  • 各メッセージにIDを付与できるため、接続が切れても最後に受信したイベントからの再開が可能

5. テキストベース

  • データ形式はテキストベース(通常はJSON形式でデータをやり取り)

SSEが特に適している用途

  • 生成AIのストリーミング出力(タイプライターのような表示)

  • リアルタイム通知システム

  • ライブフィード(Twitter/Xのタイムラインなど)

  • 株価や天気など、定期的に更新されるデータの配信

  • チャットアプリケーション(メッセージの受信部分)

クライアント側のサンプルコード(JS)

// SSE接続の作成
const eventSource = new EventSource('/api/events');

// メッセージ受信時の処理
eventSource.onmessage = function(event) {
  const data = JSON.parse(event.data);
  console.log('受信したデータ:', data);
  
  // 例:生成AIの出力をDOMに追加
  document.getElementById('ai-response').textContent += data.text;
};

// 接続開始時の処理
eventSource.onopen = function() {
  console.log('SSE接続が確立されました');
};

// エラー発生時の処理
eventSource.onerror = function(error) {
  console.error('SSE接続でエラーが発生しました:', error);
  // 必要に応じて再接続ロジックを実装
};

// 特定のイベントタイプを購読する場合
eventSource.addEventListener('custom-event', function(event) {
  const data = JSON.parse(event.data);
  console.log('カスタムイベント:', data);
});

// 接続を閉じる(必要な場合)
function closeConnection() {
  eventSource.close();
}

サーバー側のサンプルコード(Express+Node.js)

const express = require('express');
const app = express();

app.get('/api/events', (req, res) => {
  // SSEヘッダーの設定
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
  
  // クライアントに送信する初期データ
  res.write('data: {"message": "接続が確立されました"}\n\n');
  
  // 生成AIの出力をシミュレート(単語ごとに送信)
  const sentence = "こんにちは!私はAIアシスタントです。タイプライターのような出力をSSEで実現しています。";
  const words = sentence.split('');
  
  let index = 0;
  // 定期的にデータを送信(単語を1文字ずつ送信)
  const intervalId = setInterval(() => {
    if (index < words.length) {
      // データ形式: data: {JSONデータ}\n\n
      res.write(`data: {"text": "${words[index]}"}\n\n`);
      index++;
    } else {
      // 全ての単語を送信し終えたら終了
      clearInterval(intervalId);
      res.write('event: complete\ndata: {"message": "生成完了"}\n\n');
    }
  }, 100); // 100ミリ秒ごとに送信
  
  // クライアントが接続を切った場合の処理
  req.on('close', () => {
    clearInterval(intervalId);
    console.log('クライアントが接続を閉じました');
  });
});

app.listen(3000, () => {
  console.log('サーバーが起動しました。ポート: 3000');
});

まとめ


SSEは、サーバーからクライアントへのリアルタイムなデータ送信が必要な場合にとても便利な技術です。生成AIのタイプライター風の出力表示など、ユーザー体験を向上させるために広く活用されています。

同様の技術にWebSocketがありますが、WebSocketと比較して実装が簡単で、標準的なHTTPプロトコル上で動作するのも特徴です。

生成AIからの出力にはよく使う技術なので、今後の動画教材でも必要に応じてご紹介していきたいと思います。


有料マガジン

AIエージェントのマガジン

コンテンツ作成のマガジン

個人開発のマガジン

読書・論文のマガジン



Udemy講座 生成AIもいくつかあります(Dify, 画像生成AI, ChatGPTなど)

udemy講師紹介ページ

udemy講座のクーポン一覧

最後まで記事をお読みいただきありがとうございます❗

さらなる良記事を執筆するためのモチベーションアップのため、

よろしければスキ & フォローもお願いいたします😊

フォローバック100%させていただきます💯

いいなと思ったら応援しよう!

青木亮宏(世界のアオキ) | テイルウインド株式会社 | 生成AI仕様駆動開発 よろしくお願いします。いただいたサポート費用はクリエイターとして、レベルアップするための活動に役立てるようにいたします。ありがとうございます🥰