在本文中,我們將探討主流的大型語言模型(LLM)提供商如何實現其流式輸出的 HTTP API。我們將深入研究流式輸出的工作原理,探討其優勢,并提供示例代碼以幫助您理解如何在實際應用中使用流式輸出。


什么是流式輸出?

流式輸出(Streaming Output)是一種使后端將數據分塊、逐步發送到前端的技術。通過這種方法,前端應用能夠即時接收和渲染數據,不必等到整個響應體生成完畢后再處理。

傳統的API 通常會一次性返回所有數據,然后客戶端一次性接收。

流式輸出則允許服務器在生成數據的同時將其發送給客戶端,從而實現實時更新。

流式輸出通常用于以下幾種場景:

流式 API 的優勢

流式 API 提供了即時響應的體驗,允許用戶在內容生成過程中即時查看部分結果。相比等待整個響應完成,流式輸出極大提高了用戶體驗。適用于多種場景,例如:

流式輸出的實現方式

在具體實現流式輸出時,常用的技術包括:

本文主要講解SSE的實現。

SSE數據格式

Server-Sent Events(SSE)返回的數據格式是由一系列文本流組成,每行包含一個鍵值對,表示一個數據事件。每條事件消息由事件名稱、數據內容等字段組成,并且這些字段具有特定的格式和規則。

  1. SSE 格式的基本結構
    SSE 使用 Content-Type: text/event-stream,將數據以純文本的方式分塊傳輸到客戶端,每次傳輸一個事件,數據傳輸結束時不需要關閉連接。每個事件消息有幾個常用字段:
  1. SSE 數據格式示例
    在每條事件中,字段通過換行分隔,格式如下:
event: custom-event
id: 1
retry: 5000
data: {"message": "Hello, World!"}
  1. 多行數據
    data 字段支持多行。對于多行內容,在每行前都需要加 data: 前綴, 并且以兩個換行符(\n\n)結尾,SSE 會自動將其拼接為單個字符串傳遞到客戶端。例如:
data: {"message": "Part 1 of the message"}

data: {"message": "Part 2 of the message"}

data: {"message": "Part 3 of the message"}

在客戶端收到時,這幾行會被拼接成一條數據。

示例:使用SSE實現流式輸出

  1. 后端實現
    后端需要實現一個 HTTP 接口,該接口返回一個流式響應。在 C# 中,可以使用 ASP.NET Core 來實現。以下是一個簡單的示例:
[HttpPost, HttpGet]
[ActionTitle(Name = "聊天")]
[Route("chat")]
public async Task Completions([FromBody] ChatDto chatDto)
{
Response.ContentType = "text/event-stream";

await foreach( var message in GetStreamingResponseAsync(chatDto.Input) ) {
var data = $"data: {message}\n\n";
Console.Write(data);
var bytes = Encoding.UTF8.GetBytes(data);
await Response.Body.WriteAsync(bytes);
await Response.Body.FlushAsync();
await Task.Delay(100);
}
}

public static async IAsyncEnumerable<string> GetStreamingResponseAsync(string userInput)
{
// 隨機獲取一個配置
GptConfig gptConfig = new GptConfig() {
ApiKey = "your-api-key",
Version = "2023-03-15-preview"
};

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"URL_ADDRESS");
request.Headers.Add("api-key", gptConfig.ApiKey);

var requestBody = new {
messages = new[]
{
new { role = "user", content = userInput }
},
stream = true
};

var jsonRequestBody = JsonSerializer.Serialize(requestBody);
request.Content = new StringContent(jsonRequestBody, Encoding.UTF8, "application/json");

using HttpClient httpClient = new HttpClient();

using( var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead) ) {
response.EnsureSuccessStatusCode();
var responseStream = await response.Content.ReadAsStreamAsync();

using( var reader = new StreamReader(responseStream) ) {
while( !reader.EndOfStream ) {
var line = await reader.ReadLineAsync();
if( !string.IsNullOrWhiteSpace(line) && line.StartsWith("data:") ) {
var jsonData = line.Substring(5).Trim();
if( jsonData == "[DONE]" )
break;

var data = JsonSerializer.Deserialize<JsonElement>(jsonData);

// 檢查是否包含 content 字段,避免報錯
if( data.TryGetProperty("choices", out var choices) &&
choices[0].TryGetProperty("delta", out var delta) &&
delta.TryGetProperty("content", out var content) ) {
yield return content.GetString();
}
}
}
}
}

}

前端實現
在前端,我們可以使用 vue3來實現。以下是一個簡單的示例:

chat() {
fetch(/v20/openai/chat, { method: 'POST', body: JSON.stringify({ input: this.input }), headers: { 'Content-Type': 'application/json' } }).then((res) => { const reader = res.body.getReader(); this.handleReadStream(reader) }).finally(() => { this.input = '' }) }, // 流式對話 handleReadStream(stream) { stream.read().then(({ done, value }) => { if (done) { return } const data = new TextDecoder().decode(value) if (!data) { return } this.message += data.replaceAll('data: ', '') // 強制 Vue 渲染更新 this.$nextTick(() => { console.log("Stream updated"); }); // 遞歸處理流 this.handleReadStream(stream) }) },

實現效果

需要注意的是,vue3項目在本地開發代理api接口的時候似乎默認啟用了gzip壓縮,導致前端無法正常解析SSE的數據格式。可以在vue.config.js中配置關閉gzip壓縮。

devServer: {
port: 9588,
compress: false,
allowedHosts: "all",
proxy: {
'v20': { target: 'http://localhost:2222', changeOrigin: true },
}
}

結論

流式輸出是一種強大的工具,能夠顯著改善數據傳輸體驗,特別適用于實時和大數據場景。合理選擇適合的流式輸出技術并處理好前后端的數據解析和錯誤恢復,可以顯著提升應用的交互性和性能。

文章轉自微信公眾號@ITProHub

上一篇:

Python 云計算接口集成秘籍:十招搞定云服務 API

下一篇:

Web Audio API 太強了,讓我們一起領略音頻之美
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費