選擇應用程式使用的 API。每個 API 都有各自的身分驗證、工作階段建立方式及事件規範。
從伺服器控制 GPT-Live 工作階段
當伺服器需要接收對話事件、執行私有工具或更新對話時,請將應用程式伺服器連接至現有的 GPT-Live WebRTC 或 SIP 工作階段。這個第二條連線稱為 邊帶 WebSocket。兩條連線共用同一個工作階段,主要音訊則由 WebRTC 或 SIP 傳輸。
邊帶用於傳輸事件與指令。工具執行、授權檢查與業務規則由你的應用程式負責。請將 API 金鑰與工具憑證保留在伺服器上。
判斷是否需要邊帶
對於瀏覽器應用程式,請使用 WebRTC 資料通道處理字幕與本機 UI 更新。當逐字稿處理作業在伺服器上執行時,例如防護機制檢查、情緒分析或推測性工具呼叫,請使用邊帶。伺服器可以直接接收事件並引導同一個工作階段,而瀏覽器音訊仍透過 WebRTC 傳輸。如需範例,請參閱回應逐字稿片段。
如果後端已經負責主要的 WebSocket 連線,就已能接收工作階段的事件並傳送指令。
Responses 委派也可以在沒有邊帶的情況下運作。瀏覽器可以將資料通道中的函式呼叫事件轉送至經過身分驗證的後端來執行。OpenAI 託管的工具會透過受委派的後端執行,不需要應用程式提供工具執行器。
連接至現有工作階段
-
儲存後端將要控制的工作階段 ID。若使用 WebRTC,請使用
POST /v1/live/sessions的 JSON 回應中的session.id。若使用 SIP,請先接聽來電,再使用其 webhook 中的data.session_id。請將此 ID 與應用程式的使用者及對話紀錄一併儲存。 -
從伺服器透過下列 URL 建立 WebSocket 連線,並原樣代入已儲存的 ID。請使用建立或接受該工作階段時所用的專案身分驗證資訊,以
Authorization: Bearer $OPENAI_API_KEY進行身分驗證。請包含建立工作階段時所需的相同連線標頭。wss://api.openai.com/v1/live/sessions/{session_id}/attach -
透過已連接的通訊端接收事件並傳送指令。工作階段已在執行中,請勿再次傳送
session.start。
請將工作階段 ID 視為不需解析的值。保留其前綴,且僅用於應用程式獲授權存取的工作階段。請從 Live JSON 回應讀取 ID,而不是從 Realtime 的 Location 標頭或 call_id URL 參數讀取。
觀察事件並傳送指令
| 任務 | 事件或指令 |
|---|---|
| 追蹤對話 | 接收使用者與助理的逐字稿增量、委派事件及巢狀 Responses 事件。 |
| 更新後端組態 | 使用 session.update,在現有委派模式下變更支援的設定。前端模型與音訊組態等啟動設定會維持固定。 |
| 提供上下文 | 使用 session.instructions.append 提供指示、session.thinking.append 提供不需朗讀的上下文,以及 session.commentary.append 提供可供朗讀的更新。 |
| 傳回工具結果 | 使用 Responses 委派時,先傳送 response.item.create,再傳送 response.create,以繼續後端作業。 |
| 控制麥克風輸入 | 使用 session.input_audio.mute 與 session.input_audio.unmute。將輸入靜音並不會停止助理的輸出。 |
| 結束工作階段 | 請先傳送 session.close 並收到 session.closed,再中斷連線。 |
指令遵循與主要連線相同的驗證與委派規則。附加上下文時,請對一般工作階段上下文使用 delegation_id: null;非 null 的 ID 必須指向現有的用戶端委派。如需組態、函式執行及附加上下文的範例,請參閱委派與工具。
對於瀏覽器工作階段,請讓麥克風輸入與喇叭輸出維持在已協商的 WebRTC 媒體軌道上。使用邊帶處理對話事件與控制。逐字稿事件或指令確認訊息並不能證明音訊已播放,或使用者已聽到音訊。
接收音訊副本
主要連線傳輸即時媒體時,邊帶也會接收後續輸入與輸出音訊的副本:
| 事件 | 音訊欄位 | 時間資訊 |
|---|---|---|
session.input_audio.append | audio | 無時間戳記。 |
session.output_audio.delta | delta | start_ms 與 end_ms 描述輸出在工作階段時間軸上的範圍。 |
無論主要傳輸通道的音訊格式為何,這兩種酬載都是以 base64 編碼、取樣率為 24 kHz 的原始單聲道 PCM16LE。這兩種事件都沒有 event_id。輸入副本包含輸入靜音處理前接收到的音訊,並不能確認模型已處理這些取樣。輸出副本的時間範圍可能因影格遺失而出現間隙,也不代表來電者實際聽到音訊的時間。
這些是伺服器事件,並不表示可以透過邊帶傳送音訊。請透過主要傳輸通道傳送麥克風音訊;請勿在已連接的通訊端上傳送 session.input_audio.append。
為每個動作指定單一負責端
決定每個動作由瀏覽器還是後端處理。如果兩條連線都收到同一個函式呼叫事件,函式只能執行一次。對上下文更新與繼續後端作業的請求,也應套用相同的負責端規則。
將逐字稿與工具狀態儲存在應用程式中。如果後端需要從一開始就觀察對話,請及早連接,並保留連接前已收集的所有歷史紀錄。請勿依賴連接工作階段來重建先前的逐字稿或工具結果。
邊帶本身不會向瀏覽器隱藏工作階段事件。請將敏感的工具憑證與授權決策保留在後端,並只傳回對話所需的上下文。
套用對話防護機制
使用伺服器的連線監控對話,依據應用程式的政策檢查請求,並在檢查觸發時介入。邊帶讓伺服器能夠存取工作階段事件與指令;應用程式則負責執行檢查,並落實檢查結果。當伺服器已負責主要 WebSocket 連線時,同樣適用這個工作流程。
在對話進行的同時執行檢查
防護機制是在逐字稿片段抵達時即時處理的一種用途。同一串流也可以在執行這些檢查的同時,啟動推測性查詢或更新 UI。
- 監控逐字稿。 累積
session.input_transcript.delta片段,檢查使用者請求是否涉及越獄嘗試、敏感資訊或違反政策的情況。使用session.output_transcript.delta檢查助理的語音內容是否包含缺乏依據的說法,或超出應用程式範圍的回應。請將每項檢查與其評估的逐字稿及應用程式請求保持關聯。 - 並行執行檢查。 快速、輕量的模型可以在對話持續進行時評估請求。傳回精簡的結構化結果,例如
{"triggered": true},讓應用程式能據此採取動作。需要核准的動作在通過檢查前應持續封鎖;逾時或檢查失敗都不代表核准。 - 封鎖受影響的動作。 當檢查觸發時,在應用程式狀態中將請求標記為已封鎖。執行工具或提交變更前,請先檢查該狀態,已排入佇列的作業也不例外。口頭拒絕並不會阻止工具執行。
- 停止相關作業。 如果後端支援取消作業,請取消由應用程式管理的作業,並捨棄已封鎖或已被取代的請求所傳回的延遲結果。使用 Responses 委派時,請停止執行受影響的自訂函式,且不要傳送
response.create來繼續已封鎖的作業。這不會取消已在執行中的託管回應,也不會停止前端語音。 - 記錄並重新引導。 將決策連同受影響的請求 ID 與委派 ID 寫入紀錄,再傳送修正指示。
guardrail.triggered之類的事件名稱屬於應用程式的遙測資料,並非 GPT-Live API 事件。
如需瞭解如何收集片段,請參閱逐字稿增量;如需瞭解如何讓後端結果與目前任務保持一致,請參閱委派與工具。
重新引導對話
使用 session.instructions.append 依據防護機制引導對話。它可以中斷進行中的語音,並套用新的指示。例如,應用程式封鎖請求後,傳送:
export function sendUpdate(connection) {
connection.send({
type: "session.instructions.append",
event_id: "guardrail_block_17",
delegation_id: null,
content:
"Stop speaking immediately. Do not continue or act on the last request. Refuse briefly, then wait.",
});
}指示應由應用程式撰寫。請勿將不受信任的使用者文字複製進去作為指示。針對這項適用於整個工作階段的修正,請使用 delegation_id: null,並將 content 控制在 500 個 Token 以內。
透過 client_event_id 將 session.instructions.appended 與你送出的指令對應。確認訊息會在預估的上下文注入時間之後送達,但這不代表助理已停止說話,也不代表佇列中的音訊已停止播放。修正指示無法收回使用者已經聽到的音訊。
如果揭露聲明需要使用特定措辭說出,也應使用指示。範例與播放注意事項請參閱傳達揭露聲明。
視需要控制播放
先測試修正指示與動作封鎖。如果應用程式還需要封鎖模型音訊,請在用戶端或媒體轉送端控制輸出:暫時將輸出靜音或丟棄輸出、丟棄本機佇列中的音訊、傳送修正指示,再依照應用程式的復原政策恢復播放。恢復播放前,請清除過時的音訊。單靠側通道無法控制媒體傳輸路徑,而指示的確認訊息也不是恢復播放的訊號。
session.input_audio.mute 控制的是通話者的麥克風輸入,不會將模型輸出靜音,也不會取消已委派的工作。
GPT-Live 會在說話時串流傳送轉錄文字片段。如果必須在使用者聽到音訊前完成檢查,應用程式就需要先緩衝音訊,並在核准後才播放。這會增加延遲。未播放的音訊也可能讓模型的對話上下文超前於使用者實際聽到的內容,因此請測試對話恢復後的情況。
測試介入措施
請測試允許與封鎖的請求、誤判、檢查緩慢或失敗、說話期間觸發檢查、工具執行期間觸發檢查,以及工作取消後才送達的結果。分別驗證動作封鎖、應用程式狀態、修正後的語音與實際播放情況。如果你有控制輸出,測試也應涵蓋佇列中的音訊與復原流程。使用語音智慧體評估 Cookbook 比較任務成功率與語音回應時間。
妥善結束工作階段
當後端負責執行工具或收集最終用量時,請持續接收事件。傳送 session.close 前,先註冊 session.closed 處理常式,並在等待待處理工作全部完成期間,保持 WebRTC 連線、資料通道與側通道開啟。清理前,請儲存工作階段的最終用量,以及透過 Responses 事件收到的所有後端用量。如果在最終事件送達前連線就已失敗,請將結束處理記錄為未完成。關閉順序請參閱管理工作階段。
Realtime API 允許用戶端透過 WebRTC 或 SIP 直接連線至 API 伺服器。不過,你多半會希望將工具使用與其他業務邏輯放在應用程式伺服器上,讓這些邏輯保持私密,且不依賴特定用戶端。
透過「側通道」控制通道連線,可將工具使用、業務邏輯與其他細節安全地保留在伺服器端。目前 SIP 與 WebRTC 連線都支援側通道。
使用側通道連線時,同一個 Realtime 工作階段會同時有兩條作用中的連線:一條來自使用者的用戶端,另一條來自你的應用程式伺服器。伺服器連線可用來監控工作階段、更新指示,以及回應工具呼叫。
搭配 WebRTC 使用
- 建立對等連線時,你會向 Realtime API 請求並接收 SDP 回應,以設定連線。如果你使用 WebRTC 指南中的範例程式碼,大致會如下所示:
const baseUrl = "https://api.openai.com/v1/realtime/calls";
const sdpResponse = await fetch(baseUrl, {
method: "POST",
body: offer.sdp,
headers: {
Authorization: `Bearer ${EPHEMERAL_KEY}`,
"Content-Type": "application/sdp",
},
});- 擷取的回應會包含
Location標頭,其中有唯一的通話 ID。伺服器可使用此 ID 建立連至同一個 Realtime 工作階段的 WebSocket 連線。
// Location: /v1/realtime/calls/rtc_123456
const location = sdpResponse.headers.get("Location");
const callId = location?.split("/").pop();
console.log(callId);- 接著,你可以在伺服器上將該通話 ID 帶入 URL
wss://api.openai.com/v1/realtime?call_id=rtc_xxxxx,如同使用一般 Realtime API WebSocket 連線一樣,監聽事件並設定工作階段,如下所示:
import WebSocket from "ws";
const callId = "rtc_u1_9c6574da8b8a41a18da9308f4ad974ce";
// Connect to a WebSocket for the in-progress call
const url = "wss://api.openai.com/v1/realtime?call_id=" + callId;
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
},
});
ws.on("open", function open() {
console.log("Connected to server.");
// Send client events over the WebSocket once connected
ws.send(
JSON.stringify({
type: "session.update",
session: {
type: "realtime",
instructions: "Be extra nice today!",
},
})
);
});
// Listen for and parse server events
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});如此一來,你就能在伺服器上新增工具、監控工作階段並執行業務邏輯,無須在用戶端設定這些動作。
搭配 SIP 使用
- 使用者以電話透過 SIP 連線至 OpenAI。
- OpenAI 會將 webhook 傳送至應用程式伺服器的 webhook URL,通知應用程式目前的工作階段狀態。webhook 大致如下所示:
POST https://my_website.com/webhook_endpoint
user-agent: OpenAI/1.0 (+https://platform.openai.com/docs/webhooks)
content-type: application/json
webhook-id: wh_685342e6c53c8190a1be43f081506c52 # unique id for idempotency
webhook-timestamp: 1750287078 # timestamp of delivery attempt
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4= # signature to verify authenticity from OpenAI
{
"object": "event",
"id": "evt_685343a1381c819085d44c354e1b330e",
"type": "realtime.call.incoming",
"created_at": 1750287018, // Unix timestamp
"data": {
"call_id": "some_unique_id",
"sip_headers": [
{ "name": "From", "value": "sip:+142555512112@sip.example.com" },
{ "name": "To", "value": "sip:+18005551212@sip.example.com" },
{ "name": "Call-ID", "value": "03782086-4ce9-44bf-8b0d-4e303d2cc590"}
]
}
}
- 應用程式伺服器會使用 webhook 提供的
call_id值,透過類似wss://api.openai.com/v1/realtime?call_id={callId}的 URL,建立連至 Realtime API 的 WebSocket 連線。這條 WebSocket 連線會在整個 SIP 通話期間保持開啟。
接著便可使用這條 WebSocket 連線傳送與接收事件來控制通話,操作方式與透過 WebSocket 連線啟動的工作階段相同。這包括監控通話、動態更新指示,以及回應工具呼叫。