iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0

Day 3|Streaming 回應:串流的用途

昨天分享的模型回應與平常大家用聊天介面有個不一樣的地方:程式是等模型「全部生成」完回應,才將內容印出來,而平常在使用聊天機器人時,介面都是一個字一個字或一段一段輸出。這個並不是由前端做的效果,而是 API 本身自帶的機制——streaming(串流)


為什麼要用串流?

LLM 生成回應的方式,本質上是一次產生一個 token,再根據前面已經產生的內容繼續生成,一路生成到結束。也就是說,「整段回應」其實是逐步組裝出來的,只是不用串流的話,程式會等到全部組裝完成才一次拿到。

兩者的差別呈現在使用體驗上。假設一次回應需要 8 秒才能完整生成:

  • 不用串流:使用者盯著空白畫面等 8 秒,才看到結果。
  • 用串流:大概 1 秒內就開始看到文字冒出來,雖然一樣要等 8 秒才看到完整內容,但視覺上看得到模型在跑動。

這個概念叫做 perceived latency(感知延遲)——實際花的時間沒有變,但讓使用者「感覺」系統有在動。任何會產生較長回應、或是面向使用者即時互動的場景(聊天機器人、客服回應),串流幾乎是必要的。


技術原理

串流的實作,會由 SDK 包裝掉底層細節(常見的做法是用 Server-Sent Events 這類逐段推送的協定),不需要自己處理協定層。

因此我們需要了解,串流底下拿到的回應,不再是「一個完整的 response 物件」了,而是「一連串的事件(chunk / event)」,每個事件帶著一小塊內容,需要透過組裝來獲得完整的回應內容。


程式範例

import os
import anthropic

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

full_text = ""
with client.messages.stream(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "用三句話介紹台灣夜市文化"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
        full_text += text

print("\n---完整內容組裝完成---")

這裡用了 SDK 提供的 text_stream,是一個逐段吐出文字的產生器(generator),用 for 迴圈把每一小段接起來,同時印出來,也累積成完整字串,方便之後還需要用到整段內容(例如記錄到資料庫、算 token 用量)。


不同廠商,連拿「串流」的方式都不一樣

延續昨天的觀察,串流這件事在不同廠商手上,資料的取用方式也不同。以 OpenAI 為例:

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

full_text = ""
stream = client.chat.completions.create(
    model="gpt-4.1",
    max_tokens=1024,
    messages=[{"role": "user", "content": "用三句話介紹台灣夜市文化"}],
    stream=True,
)

for event in stream:
    delta = event.choices[0].delta.content or ""
    print(delta, end="", flush=True)
    full_text += delta

print("\n---完整內容組裝完成---")

Anthropic vs. OpenAI

  • Anthropic:直接呼叫一個獨立方法 client.messages.stream() 代表要 stream 回應,並透過 context manager(with ... as stream)搭配 text_stream 產生器逐段取值拼湊完整回應。
  • OpenAI:則是與昨天呼叫同一個方法 client.chat.completions.create(),並透過設置參數 stream=True 來指定串流形式,再透過 for 迴圈從 delta.content 取值。

這也代表:如果你的程式同時要支援多家模型的串流輸出,「把串流資料轉成統一格式」這件事本身也是一塊需要獨立處理的邏輯。


今日小結

Streaming 的回應可以用來提升使用者體感上的問題,在資料處理上並不複雜。

雖然 Streaming 可以讓使用者閱讀與使用的更流暢,但若要讓模型的回覆在程式中更有效地被應用,該如何讓這一段一段的文字變成可以被解析的結構化資料呢?

明天會針對模型回應的處理做分享!


上一篇
Day 02:如何在程式中呼叫LLM API?
下一篇
Day 04:Structured Output / Tool Use 讓 LLM 回傳程式看得懂的資料
系列文
從呼叫 API 到打造 Gateway:LLM 工程化 30 天4
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言