AI聊天アプリケーションを作成する際、ユーザーが「タイピング中」のように文字が少しずつ表示される体験に憧れたことはないでしょうか?この技術は「Server-Sent Events(SSE)」と呼ばれ、APIがリアルタイムでデータを少しずつ送信する方法です。この記事では、HolySheep AIのAPIを使って、初心者の人でも理解できる从头开始的SSE実装方法を紹介します。

SSE(サーバー送信イベント)とは何か?

традиционном API呼び出しでは、サーバーが完全に準備できるまで待つ必要があります。例えば、長い文章を生成する場合、完了するまでに数秒かかることもあります。

でもSSEを使うと、まるで水流のようにデータが少しずつ届きます。イメージとしては、泉から水が少しずつ湧き出すようなものです。

SSEが優れている理由

Step 1:准备工作

まず、必要なものと設定を確認しましょう。

必要なもの

💡 スクリーンショットヒント:ブラウザでChromeを開き、URL欄に「chrome://settings/」と入力して開発者ツールが有効になっていることを確認してください。

API ключの取得

HolySheep AIでは、今すぐ登録してダッシュボードからAPIキーを取得できます。¥1=$1のレートで使他、主要な支払い方法としてWeChat PayとAlipayにも対応しています。

Step 2:HTMLファイルの作り方

まずは、最もシンプルなHTMLファイルを作成しましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HolySheep AI 流式応答デモ</title>
    <style>
        body {
            font-family: 'Segoe UI', sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: #f5f5f5;
        }
        #chat-container {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        #message {
            min-height: 50px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
            line-height: 1.6;
        }
        #message.loading::after {
            content: '▊';
            animation: blink 0.5s infinite;
        }
        @keyframes blink {
            0%, 100% { content: '▊'; }
            50% { content: '█'; }
        }
        button {
            background: #4CAF50;
            color: white;
            border: none;
            padding: 12px 25px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            margin-top: 15px;
        }
        button:hover {
            background: #45a049;
        }
        button:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
    </style>
</head>
<body>
    <div id="chat-container">
        <h2>🤖 AI 流式応答デモ</h2>
        <p>下のボタンを押して、AIの返答が少しずつ表示されるのを確認しましょう!</p>
        <div id="message">ここにAIの返答が表示されます...</div>
        <button id="send-btn" onclick="sendMessage()">AIに質問する</button>
    </div>
    
    <script>
        // ここにJavaScriptのコードを記入します
    </script>
</body>
</html>

💡 スクリーンショットヒント:このコードを「index.html」という名前で保存し、ダブルクリックしてブラウザで開いてください。緑色のボタンと灰色のメッセージエリアが表示されるはずです。

Step 3:SSE実装の核心コード

では、実際のSSE通信部分を実装しましょう。HolySheep AIのAPIを使う点がポイントです。

async function sendMessage() {
    const messageDiv = document.getElementById('message');
    const sendBtn = document.getElementById('send-btn');
    
    // 初期化
    messageDiv.textContent = '';
    messageDiv.classList.add('loading');
    sendBtn.disabled = true;
    sendBtn.textContent = '考え中...';
    
    try {
        // HolySheep AIのAPIエンドポイント
        const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer YOUR_HOLYSHEEP_API_KEY'
            },
            body: JSON.stringify({
                model: 'gpt-4.1',
                messages: [
                    {
                        role: 'user',
                        content: '日本料理について教えてください。数文程度で简短に説明してください。'
                    }
                ],
                stream: true  // ★重要:これをtrueにするとSSEが有効になる
            })
        });
        
        // ストリームの 리더を取得
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let fullText = '';
        
        // リアルタイムでデータを処理
        while (true) {
            const { done, value } = await reader.read();
            
            if (done) break;
            
            // バイナリデータを文字列に変換
            const chunk = decoder.decode(value);
            
            // SSEのフォーマットをパース
            // フォーマット: data: {"choices":[{"delta":{"content":"文字"}}]}
            const lines = chunk.split('\n');
            
            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    const data = line.slice(6); // "data: "を削除
                    
                    // [DONE] 信号をチェック
                    if (data === '[DONE]') {
                        console.log('ストリーム完了');
                        continue;
                    }
                    
                    try {
                        const json = JSON.parse(data);
                        const content = json.choices?.[0]?.delta?.content;
                        
                        if (content) {
                            fullText += content;
                            messageDiv.textContent = fullText;
                        }
                    } catch (e) {
                        // パースエラーは無視(正常なケースもある)
                    }
                }
            }
        }
        
    } catch (error) {
        console.error('エラー発生:', error);
        messageDiv.textContent = 'エラーが発生しました: ' + error.message;
        messageDiv.style.color = 'red';
    } finally {
        messageDiv.classList.remove('loading');
        sendBtn.disabled = false;
        sendBtn.textContent = 'AIに質問する';
    }
}

💡 スクリーンショットヒント:開発者ツール(F12キー)を開いて「Console」タブを見ると、「ストリーム完了」と表示されながら、文字が少しずつ追加されていく様子が観察できます。

Step 4:より実用的なバージョン

実際のアプリケーションでは、複数回の対話をやり取りできるようにしましょう。

class HolySheepStreamChat {
    constructor(apiKey, model = 'gpt-4.1') {
        this.apiKey = apiKey;
        this.model = model;
        this.messages = [];
        this.baseUrl = 'https://api.holysheep.ai/v1';
    }
    
    // メッセージを追加
    addMessage(role, content) {
        this.messages.push({ role, content });
    }
    
    // ストリーミング応答を処理
    async streamResponse(userMessage, onChunk, onComplete, onError) {
        // ユーザーメッセージを追加
        this.addMessage('user', userMessage);
        
        try {
            const response = await fetch(${this.baseUrl}/chat/completions, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': Bearer ${this.apiKey}
                },
                body: JSON.stringify({
                    model: this.model,
                    messages: this.messages,
                    stream: true
                })
            });
            
            if (!response.ok) {
                throw new Error(HTTPエラー: ${response.status});
            }
            
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            let assistantMessage = '';
            
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                
                const chunk = decoder.decode(value, { stream: true });
                
                // SSEの行を処理
                for (const line of chunk.split('\n')) {
                    if (!line.startsWith('data: ')) continue;
                    
                    const data = line.slice(6);
                    if (data === '[DONE]') continue;
                    
                    try {
                        const parsed = JSON.parse(data);
                        const content = parsed.choices?.[0]?.delta?.content;
                        
                        if (content) {
                            assistantMessage += content;
                            onChunk(content); // リアルタイムコールバック
                        }
                    } catch (e) {
                        // 空または不正な行をスキップ
                    }
                }
            }
            
            // アシスタントの応答を履歴に追加
            this.addMessage('assistant', assistantMessage);
            onComplete(assistantMessage);
            
        } catch (error) {
            onError(error);
        }
    }
}

// 使用例
const chat = new HolySheepStreamChat('YOUR_HOLYSHEEP_API_KEY');

async function startChat() {
    const output = document.getElementById('message');
    
    await chat.streamResponse(
        'おいしいチョコレートの選び方を教えて',
        
        // 文字が得られるたびに呼び出される
        (chunk) => {
            output.textContent += chunk;
        },
        
        // 完了時に呼び出される
        (fullText) => {
            console.log('完全な応答:', fullText);
        },
        
        // エラー時に呼び出される
        (error) => {
            console.error('エラー:', error);
            output.textContent = 'エラー: ' + error.message;
        }
    );
}

💡 スクリーンショットヒント:クラスを用いたこのバージョンでは、複数回の会話を続けると、AIが前の会話の内容を踏まえて返答するようになります。

HolySheep AIを選ぶ理由

私は複数のAI API 서비스를 利用してきましたが、HolySheep AIは以下の理由で特に気に入っています:

応用:進捗バーと文字カウント

さらに一歩踏み込んで、進捗情况和文字数を表示する版本も作ってみましょう。

<!-- HTML部分 -->
<div id="progress-container">
    <div id="progress-bar" style="width: 0%; height: 5px; background: #4CAF50;"></div>
    <div id="char-count">文字数: 0</div>
    <div id="status">待機中</div>
</div>

<script>
class EnhancedStreamChat {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.charCountEl = document.getElementById('char-count');
        this.progressBar = document.getElementById('progress-bar');
        this.statusEl = document.getElementById('status');
    }
    
    updateProgress(current, estimatedTotal) {
        const percentage = Math.min((current / estimatedTotal) * 100, 100);
        this.progressBar.style.width = percentage + '%';
        this.charCountEl.textContent = 文字数: ${current};
    }
    
    async stream(userMessage, callback) {
        this.statusEl.textContent = '🔄 接続中...';
        let charCount = 0;
        
        // 進捗更新の定时器
        const progressInterval = setInterval(() => {
            if (charCount > 0) {
                this.updateProgress(charCount, charCount * 2); // 推定
            }
        }, 100);
        
        try {
            const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': Bearer ${this.apiKey}
                },
                body: JSON.stringify({
                    model: 'gpt-4.1',
                    messages: [{ role: 'user', content: userMessage }],
                    stream: true
                })
            });
            
            this.statusEl.textContent = '📡 データ受信中...';
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                
                const chunk = decoder.decode(value);
                for (const line of chunk.split('\n')) {
                    if (!line.startsWith('data: ') || line === 'data: [DONE]') continue;
                    
                    try {
                        const content = JSON.parse(line.slice(6))
                            .choices?.[0]?.delta?.content;
                        
                        if (content) {
                            charCount += content.length;
                            callback(content);
                        }
                    } catch (e) {}
                }
            }
            
            this.statusEl.textContent = '✅ 完了';
            this.progressBar.style.width = '100%';
            clearInterval(progressInterval);
            
        } catch (error) {
            this.statusEl.textContent = '❌ エラー';
            this.progressBar.style.background = '#f44336';
            clearInterval(progressInterval);
            throw error;
        }
    }
}

// 使用
const enhancedChat = new EnhancedStreamChat('YOUR_HOLYSHEEP_API_KEY');
enhancedChat.stream('こんにちは!', (text) => {
    console.log('受信:', text);
});
</script>

よくあるエラーと対処法

エラー1:Access-Control-Allow-Origin ポリシーエラー

// ❌ エラーメッセージ:
// Access to fetch at 'https://api.holysheep.ai/v1/chat/completions' 
// from origin 'null' has been blocked by CORS policy

// ✅ 解決策:ローカルサーバーを立てる(Chrome拡張やPython-simplehttpserver)
// ターミナルで以下を実行:
// Python 3.x: python -m http.server 8000
// Python 2.x: python -m SimpleHTTPServer 8000

// またはfetchオプションに credentials を含める
fetch(url, {
    mode: 'cors',
    credentials: 'include',
    // ...
});

エラー2:APIキーが無効です

// ❌ エラーメッセージ:
// {"error":{"message":"Invalid API key","type":"invalid_request_error"}}

// ✅ 解決策:
// 1. APIキーが正しくコピーされているか確認
// 2. 先頭と末尾の空白文字が含まれていないか確認
// 3. 有効なHolySheep APIキーであることを確認
// 4. ダッシュボードでAPIキーの有効期限を確認

// 正しいフォーマット:
const headers = {
    'Authorization': 'Bearer sk-xxxxxxxxxxxxxxxxxxxx'
    // Bearer とスキーマ名を含む
};

エラー3:JSON解析エラー

// ❌ エラーメッセージ:
// SyntaxError: Unexpected token in JSON at position 0

// ✅ 解決策:空のデータ行をスキップする
for (const line of chunk.split('\n')) {
    if (!line.startsWith('data: ')) continue;
    
    const data = line.slice(6);
    if (!data || data.trim() === '') continue; // 空行をスキップ
    if (data === '[DONE]') break;
    
    try {
        const json = JSON.parse(data);
        // ...
    } catch (e) {
        // 不正なJSONはスキップして続行
        console.warn('スキップ:', data);
    }
}

エラー4:stream: true がない

// ❌ エラーメッセージ:
// 通常のJSON応答が返ってくる(ストリーミングしない)

// ✅ 解決策:必ず request body に stream: true を指定
const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': Bearer ${apiKey}
    },
    body: JSON.stringify({
        model: 'gpt-4.1',
        messages: [{ role: 'user', content: 'こんにちは' }],
        stream: true  // ★これがないとストリーミングしない
    })
});

エラー5:reader.read() で止まる

// ❌ エラーメッセージ:
// 応答が永遠に終わらない

// ✅ 解決策:タイムアウト処理を追加
async function streamWithTimeout(url, options, timeoutMs = 30000) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
    
    try {
        const response = await fetch(url, {
            ...options,
            signal: controller.signal
        });
        clearTimeout(timeoutId);
        return response;
    } catch (error) {
        if (error.name === 'AbortError') {
            throw new Error('リクエストがタイムアウトしました');
        }
        throw error;
    }
}

まとめ

今回は、Server-Sent Events(SSE)を使ってAIの応答をリアルタイムで画面に表示する方法介绍了しました。 핵심は次の3点です:

  1. stream: true をリクエストボディに含める
  2. fetch + getReader() でストリームデータを読み取る
  3. SSEフォーマット(data: {"choices":[...]}) を正しくパースする

HolySheep AIを使えば、<50msの低レイテンシと¥1=$1の手頃な价格で、より滑らかなストリーミング体験を実現できます。DeepSeek V3.2なら$0.42/MTokという圧倒的な安さも大きなメリットです。

まずは今すぐ登録して無料クレジットを使い、小さなデモ부터 作ってみてはいかがでしょうか?

👉 HolySheep AI に登録して無料クレジットを獲得