串流輸出是什麼?一分鐘搞懂核心概念

串流輸出(Streaming Output)是一種讓伺服器逐塊發送資料而非一次性返回完整結果的技術。當 AI 回覆使用串流輸出時,使用者可以像看別人打字一樣,即時看到回覆內容逐字出現,大幅提升互動體驗。這項技術的核心關鍵在於Server-Sent Events(SSE)HTTP Chunked Transfer Encoding,讓伺服器與客戶端維持一個持續連線,逐步推送內容。

實作串流輸出的基本流程是:客戶端發送請求 → 伺服器建立持續連線 → AI 生成內容時即時分塊傳送 → 客戶端逐塊渲染顯示。這種方式不僅提升使用者感受,還能在生成過程中就開始顯示內容,減少等待時間。

後端串流輸出實作:Python Flask 範例

串流輸出最常見的實作方式是使用 Flask 框架搭配 Python。以下範例展示如何建立一個支援串流輸出的 API 端點:

from flask import Flask, Response, stream_with_context
import time

app = Flask(__name__)

@app.route('/stream-chat')
def stream_chat():
    def generate():
        message = "這是一個串流輸出的範例回覆"
        for char in message:
            yield f"data: {char}\n\n"
            time.sleep(0.05)  # 模擬 AI 生成延遲
    
    return Response(
        stream_with_context(generate()),
        mimetype='text/event-stream',
        headers={
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive'
        }
    )

if __name__ == '__main__':
    app.run(debug=True, port=5000)

這段程式碼的關鍵在於使用 stream_with_context 包裝生成器函數,並設置正確的 MIME 類型 text/event-stream。每個資料區塊必須以 data: 開頭,結尾用兩個換行符號 \n\n 標記區塊結束。

前端接收串流:JavaScript EventSource 實作

前端接收 SSE 串流非常簡單,瀏覽器原生支援 EventSource API。以下程式碼展示如何即時顯示串流內容:

const outputDiv = document.getElementById('response');
const eventSource = new EventSource('/stream-chat');

eventSource.onmessage = function(event) {
    // 將收到的字元追加到顯示區域
    outputDiv.textContent += event.data;
};

eventSource.onerror = function(error) {
    console.error('串流連線錯誤:', error);
    eventSource.close();
};

使用 EventSource 的優點是程式碼簡潔,瀏覽器會自動處理連線維持與自動重連。但要注意的是,EventSource 只支援文字格式,若需要傳遞複雜資料結構,建議使用 Fetch API 搭配 ReadableStream。

進階實作:Fetch API + ReadableStream 處理複雜資料

當你需要傳遞 JSON 格式或更複雜的資料時,EventSource 就不足夠了。此時可以使用 Fetch API 搭配 ReadableStream:

async function streamChat(messages) {
    const response = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ messages })
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let result = '';

    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        const chunk = decoder.decode(value);
        result += chunk;
        updateDisplay(result);  // 即時更新 UI
    }
}

這種方式的彈性更大,你可以自定義資料格式、處理二進制資料,甚至實作更複雜的協議如 Server-Side Events 或 WebSocket。

常見應用場景與效能優化建議

串流輸出廣泛應用於 AI 對話、即時搜尋建議、股票報價等場景。實作時有以下幾點建議:

  • 連線逾時處理:長時間串流可能會逾時,建議定時發送心跳維持連線
  • 錯誤復原機制:建立自動重連邏輯,避免網路波動時中斷體驗
  • 緩衝區優化:不要每收到一個字元就更新 DOM,建議使用節流(throttle)技術
  • 壓縮傳輸:啟用 gzip 壓縮減少傳輸量,特別是長文本場景

串流輸出能夠顯著提升使用者體驗,讓 AI 回覆更具互動感。透過本文介紹的技術,你可以在任何現代網頁應用中快速實現即時顯示功能。