內容串流

本指南介紹 Azure OpenAI 內容串流體驗與選項。 客戶可以在 API 生成時接收內容,而不必等待已驗證的內容區塊通過內容篩選。

非同步過濾設定需要在 Foundry 入口網站中修改內容過濾政策的權限。

選擇正確的串流模式

以下情況下使用預設串流:

  • 必須達到最高的安全性與合規性
  • 你需要在顯示任何內容前立即進行篩選
  • 您的應用程式無法處理追溯性內容移除
  • 範例:受管制產業中的面向客戶的聊天機器人

在以下情況下使用非同步濾波器:

  • 低延遲對使用者體驗至關重要
  • 你可以實作用戶端內容編修
  • 您的應用程式有額外的安全控制措施
  • 你願意接受延遲濾波訊號
  • 範例:內部開發工具、創意寫作助理

預設過濾行為

內容護欄系統已整合並預設啟用給所有客戶。 在預設串流情境中,完成內容會被緩衝,內容護欄系統會對緩衝的內容進行檢測。根據護欄配置,若內容未違反護欄政策(Microsoft 的預設或自訂使用者配置),則會返回給使用者;否則會立即被封鎖,並返回護欄錯誤。 這個過程會重複到串流結束。 內容會在返還給使用者前,依照護欄政策進行全面審核。 此時內容不是逐個標記回傳,而是以相應緩衝區大小的「內容區塊」回傳。

非同步過濾

用戶可選擇非同步過濾器作為額外選項,帶來全新的串流體驗。 在此情況下,內容過濾器以非同步方式運行,完成內容會立即以順暢的代幣逐代幣串流體驗返回。 沒有任何內容被緩衝,這讓串流體驗快速且不會因內容過濾而產生延遲。

客戶必須明白,雖然此功能能改善延遲,但這是在安全性與即時審查較小模型輸出區塊之間的取捨。 由於內容過濾是非同步執行的,內容審核訊息和違反政策的訊號會被延遲,這意味著某些原本會立即過濾的有害內容區塊可能會顯示給使用者。

註解:註解與內容審核訊息會在直播過程中持續回傳。 我們強烈建議您在應用程式中使用註解,並實施其他 AI 指引與控制機制,例如遮蔽內容或回傳其他安全資訊給使用者。

內容過濾訊號:內容過濾錯誤訊號會被延遲。 如果發生原則違規,其會在可提供時立即傳回,並且串流也會停止。 內容過濾訊號會在政策違反內容的約 1,000 字元範圍內被保證。

客戶著作權承諾:被追溯標記為受保護資料的內容,可能不符合客戶著作權承諾保障的資格。

成本考量

重要

串流中內容過濾的計費

當串流過程中觸發內容過濾時,提示與完成代幣都會被收費:

  • 狀態 400 (提示已篩選):針對提示評估收費
  • 狀態 200,finish_reason:「content_filter」:在過濾之前生成的提示和完成代幣均收費。

這適用於預設模式和非同步濾波器模式。 詳情請參見 Azure OpenAI 價格

要在 Microsoft Foundry 入口網站啟用非同步過濾,請依照 Content 過濾操作指南建立新的內容過濾設定,並在串流區段選擇 非同步篩選器

非同步過濾器可在 API 版本 2024-02-01 及更高版本中使用。 使用 OpenAI Python SDK v1.0+ 或 Azure OpenAI SDK 並搭配相容的 API 版本。

內容過濾模式比較

比較 串流 - 預設 串流 - 非同步濾波器
現況 GA GA
資格 所有客戶 所有客戶
如何啟用 預設啟用,無需操作 客戶可直接在 Foundry 入口網站 中設定(作為內容過濾配置的一部分,於部署層級應用)
模式與可用性 文字;所有 GPT 模型 文字;所有 GPT 模型
串流體驗 內容會被緩衝並以區塊回傳 零延遲(無緩衝,濾波器非同步執行)
內容過濾訊號 即時濾波訊號 延遲的篩選訊號 (最多 ~1,000 字元的增量)
內容過濾配置 支援預設及任何客戶自訂的過濾器設定(含選配型號) 支援預設及任何客戶自訂的過濾器設定(含選配型號)

註解與範例回應

提示註釋訊息

此訊息與預設註解相同。

data: { 
    "id": "", 
    "object": "", 
    "created": 0, 
    "model": "", 
    "prompt_filter_results": [ 
        { 
            "prompt_index": 0, 
            "content_filter_results": { ... } 
        } 
    ], 
    "choices": [], 
    "usage": null 
} 

完成詞元訊息

完成訊息會立即轉發。 該服務一開始不會進行審核或註解。

data: { 
    "id": "chatcmpl-7rAJvsS1QQCDuZYDDdQuMJVMV3x3N", 
    "object": "chat.completion.chunk", 
    "created": 1692905411, 
    "model": "gpt-35-turbo", 
    "choices": [ 
        { 
            "index": 0, 
            "finish_reason": null, 
            "delta": { 
                "content": "Color" 
            } 
        } 
    ], 
    "usage": null 
} 

註解訊息

文字欄位總是空字串,表示沒有新的標記。 註解只適用於已經寄出的標記。 多個註解訊息可以指向相同的標記。

"start_offset""end_offset" 是文字中低粒度的偏移量(從提示的開頭開始為 0),用來標示註解應用到的文字。

"check_offset" 顯示有多少文字是完全審核的。 它是未來的 "end_offset" 註解值的唯一下限。 它從未減少。

data: { 
    "id": "", 
    "object": "", 
    "created": 0, 
    "model": "", 
    "choices": [ 
        { 
            "index": 0, 
            "finish_reason": null, 
            "content_filter_results": { ... }, 
            "content_filter_raw": [ ... ], 
            "content_filter_offsets": { 
                "check_offset": 44, 
                "start_offset": 44, 
                "end_offset": 198 
            } 
        } 
    ], 
    "usage": null 
} 

重點領域說明:

  • check_offset:內容已完全審核的字元位置 (永不減少)
  • start_offset: 這個註解批次開始的字元位置
  • end_offset: 這個註解批次結束的字元位置

所有偏移量從原始提示文字開頭的 0 開始計算。

取樣響應流(通過篩選器)

以下範例顯示了使用非同步篩選器的真實聊天完成回應。 提示註解不變,完成標記未帶標記傳送,新的註解訊息則不包含標記。 相反地,這些新的註解訊息會連結到特定的內容篩選偏移量。

{"temperature": 0, "frequency_penalty": 0, "presence_penalty": 1.0, "top_p": 1.0, "max_tokens": 800, "messages": [{"role": "user", "content": "What is color?"}], "stream": true}

data: {"id":"","object":"","created":0,"model":"","prompt_annotations":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"choices":[],"usage":null} 

data: {"id":"chatcmpl-7rCNsVeZy0PGnX3H6jK8STps5nZUY","object":"chat.completion.chunk","created":1692913344,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"role":"assistant"}}],"usage":null} 

data: {"id":"chatcmpl-7rCNsVeZy0PGnX3H6jK8STps5nZUY","object":"chat.completion.chunk","created":1692913344,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":"Color"}}],"usage":null} 

data: {"id":"chatcmpl-7rCNsVeZy0PGnX3H6jK8STps5nZUY","object":"chat.completion.chunk","created":1692913344,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":" is"}}],"usage":null} 

data: {"id":"chatcmpl-7rCNsVeZy0PGnX3H6jK8STps5nZUY","object":"chat.completion.chunk","created":1692913344,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":" a"}}],"usage":null} 

... 

data: {"id":"","object":"","created":0,"model":"","choices":[{"index":0,"finish_reason":null,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"check_offset":44,"start_offset":44,"end_offset":198}}],"usage":null} 

... 

data: {"id":"chatcmpl-7rCNsVeZy0PGnX3H6jK8STps5nZUY","object":"chat.completion.chunk","created":1692913344,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":"stop","delta":{}}],"usage":null} 

data: {"id":"","object":"","created":0,"model":"","choices":[{"index":0,"finish_reason":null,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"check_offset":506,"start_offset":44,"end_offset":571}}],"usage":null} 

data: [DONE] 

取樣響應流(被濾波器阻擋)

{"temperature": 0, "frequency_penalty": 0, "presence_penalty": 1.0, "top_p": 1.0, "max_tokens": 800, "messages": [{"role": "user", "content": "Tell me the lyrics to \"Hey Jude\"."}], "stream": true}

data: {"id":"","object":"","created":0,"model":"","prompt_filter_results":[{"prompt_index":0,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}}}],"choices":[],"usage":null} 

data: {"id":"chatcmpl-8JCbt5d4luUIhYCI7YH4dQK7hnHx2","object":"chat.completion.chunk","created":1699587397,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"role":"assistant"}}],"usage":null} 

data: {"id":"chatcmpl-8JCbt5d4luUIhYCI7YH4dQK7hnHx2","object":"chat.completion.chunk","created":1699587397,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":"Hey"}}],"usage":null} 

data: {"id":"chatcmpl-8JCbt5d4luUIhYCI7YH4dQK7hnHx2","object":"chat.completion.chunk","created":1699587397,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":" Jude"}}],"usage":null} 

data: {"id":"chatcmpl-8JCbt5d4luUIhYCI7YH4dQK7hnHx2","object":"chat.completion.chunk","created":1699587397,"model":"gpt-35-turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":","}}],"usage":null} 

... 

data: {"id":"chatcmpl-8JCbt5d4luUIhYCI7YH4dQK7hnHx2","object":"chat.completion.chunk","created":1699587397,"model":"gpt-35- 

turbo","choices":[{"index":0,"finish_reason":null,"delta":{"content":" better"}}],"usage":null} 

data: {"id":"","object":"","created":0,"model":"","choices":[{"index":0,"finish_reason":null,"content_filter_results":{"hate":{"filtered":false,"severity":"safe"},"self_harm":{"filtered":false,"severity":"safe"},"sexual":{"filtered":false,"severity":"safe"},"violence":{"filtered":false,"severity":"safe"}},"content_filter_offsets":{"check_offset":65,"start_offset":65,"end_offset":1056}}],"usage":null} 

data: {"id":"","object":"","created":0,"model":"","choices":[{"index":0,"finish_reason":"content_filter","content_filter_results":{"protected_material_text":{"detected":true,"filtered":true}},"content_filter_offsets":{"check_offset":65,"start_offset":65,"end_offset":1056}}],"usage":null} 

data: [DONE] 

故障排除

串流因內容篩選完成原因而停止

症狀:串流意外以finish_reason: "content_filter"結束。

原因:模型產生的內容違反了內容過濾政策。 在非同步濾波模式下,這個訊號可能會在部分內容已經顯示完畢之後才到達。

解決:

  1. 在最後一段檢查content_filter_results,以識別觸發過濾的類別(仇恨、暴力、性、自殘、受保護的材料文本)
  2. 如果使用非同步過濾器,請在您的應用程式中實作內容遮蔽功能,以移除已顯示的內容
  3. 請檢視 Foundry 入口網站的內容過濾設定,如適用時調整嚴重性閾值
  4. 考慮重新表述提示,以避免觸發過濾器

註解未出現在串流中

症狀:串流成功完成,但 content_filter_results 總是空或為空。

原因:你的部署可能沒有啟用內容過濾註解,或你使用的 API 版本不支援註解。

解決:

  1. 請確認你使用的是 2024-02-01 或更新的 API 版本
  2. 請檢查 Foundry 入口網站的內容過濾設定
  3. 確保你選擇的濾鏡已啟用註解
  4. 請參閱護 欄註解文件 以了解設定步驟

非同步濾波模式下的延遲濾波訊號

症狀:應該被過濾的內容會暫時出現,然後被追後標記。

原因:這是非同步濾波器模式下預期的行為。 過濾以非同步方式執行,保證訊號長度在 ~1,000 字元內。

解決:

  1. 這是非同步篩選模式的預期運作方式。
  2. 收到延遲過濾信號時,請實作客戶端內容編輯
  3. 監控 check_offset 數值以追蹤調節進度
  4. 如果你的使用情境需要立即過濾,可以考慮使用預設串流模式

了解 content_filter_offsets

症狀:不清楚如何解讀 check_offset、 、 start_offsetend_offset 數值。

說明

  • check_offset:內容已完全審核的字元位置 (永不減少)
  • start_offset: 此註解適用的文字範圍起始
  • end_offset:此註解適用的文字範圍結束

所有位移皆為字元位置,提示開頭為 0。

下一步