ThunderPhone 2.0 正式登場。自助開通,價格低至每分鐘 2¢查看公告

Connect tools & data

使用 ThunderPhone 配合 OpenAI Realtime 用戶端

將與 OpenAI Realtime 相容的伺服器用戶端連接至 ThunderPhone,可使用已儲存的智能體或內嵌工作階段設定。

ThunderPhone 實作了 OpenAI Realtime 事件模型中一個專注的子集。 現有的伺服器端客戶端可在使用 ThunderPhone 語音智能體時,保留其 WebSocket、音訊、工作階段及回應事件流程。

連接前準備

你需要 ThunderPhone 組織私密 API 金鑰,以及可開啟 WebSocket 的伺服器運行環境。 請勿從瀏覽器程式碼連接,亦不要向瀏覽器公開金鑰。若要使用已儲存的智能體,請先部署,然後複製其數字智能體 ID。

連接至:

wss://api.thunderphone.com/v1/realtime

從你的伺服器驗證 WebSocket 升級請求:

Authorization: Bearer sk_live_YOUR_API_KEY

對於無法設定握手標頭的客戶端,可使用查詢字串驗證;但 URL 較容易洩漏至日誌。

選擇由誰管理設定

模式連接方式設定來源
已儲存智能體?agent_id=12已部署的提示、語音、產品、語言、知識庫及相容的伺服器執行工具
內嵌agent_id由你的客戶端發出的首個已接受 session.update

已儲存智能體

使用已部署的智能體 ID 連接:

wss://api.thunderphone.com/v1/realtime?agent_id=12

智能體會在 Socket 連接期間啟動。其問候語仍然可用, 但 Realtime 會停用其語音靜默提示,並略過 transfer_callsend_keypad_input。其他相容工具會在 ThunderPhone 上執行。請勿在此模式下傳送內嵌指示或由客戶端執行的工具。

在智能體啟動前,使用 input_audio_formatoutput_audio_formatinput_rateoutput_rate 查詢參數設定傳輸音訊。你無法在連接後更改已儲存的設定或音訊格式。

內嵌工作階段

不使用 agent_id 時,請等待 session.created,然後傳送 session.update

{
  "type": "session.update",
  "session": {
    "type": "realtime",
    "instructions": "Answer questions clearly and keep responses brief.",
    "audio": {
      "input": {
        "format": { "type": "audio/pcm", "rate": 24000 }
      },
      "output": {
        "format": { "type": "audio/pcm", "rate": 24000 },
        "voice": "olivia"
      }
    },
    "config": {
      "product": "bolt"
    }
  }
}

首個已接受的更新會開通通話。session.updated 表示 工作階段已啟用。指示、語音、產品、工具及音訊格式在此之後均不可更改。

內嵌工作階段不設自動問候語或語音靜默提示。若要讓智能體首先說話,請附加系統或使用者訊息,然後傳送 response.create。完全閒置的工作階段仍會在平台的靜默通話上限時結束,預設為 600 秒。

使用官方 OpenAI SDK

傳入以 /v1 結尾的 WebSocket 基礎 URL;SDK 會附加 /realtimemodel 值為相容性名稱,不會選擇 ThunderPhone 產品。請在工作階段設定或已儲存的智能體中選擇產品。

此連線檢查會建立內嵌 Bolt 工作階段、列印事件直至第一個 session.updated,然後關閉連線。使用最精簡 Python 用戶端串流音訊。

import asyncio
import os
 
from openai import AsyncOpenAI
 
 
async def main():
    client = AsyncOpenAI(
        api_key=os.environ["THUNDERPHONE_API_KEY"],
        websocket_base_url="wss://api.thunderphone.com/v1",
    )
 
    async with client.realtime.connect(
        model="thunderphone-realtime"
    ) as connection:
        await connection.session.update(session={
            "type": "realtime",
            "instructions": "Listen to the caller and help them complete the call.",
            "config": {"product": "bolt"},
        })
        async for event in connection:
            print(event.type)
            if event.type == "session.updated":
                break
 
 
if __name__ == "__main__":
    asyncio.run(main())

保留你現有的輸入音訊附加、回應音訊增量、中斷、函數呼叫、錯誤及正常關閉 socket 的處理方式。內嵌自訂函數會在你的用戶端執行;請透過 Realtime 協定傳回結果。已儲存智能體的工具會在 ThunderPhone 上執行。

工作階段生命週期及故障

每個 WebSocket 代表一通電話。無效的智能體 ID 或遭拒絕的內嵌設定會產生 error 事件。在收到 session.updated 前,不應將工作階段視為已啟用。請宣告實際的輸入及輸出格式與取樣率:PCM 取樣率不符會令音訊播放過快或過慢,而不會產生驗證錯誤。

工作階段開始後,當你的應用程式完成工作時,請正常關閉 socket。內嵌工作階段可使用由用戶端執行的函數。已儲存智能體工作階段使用相容的 ThunderPhone 執行工具,且不提供轉接或按鍵輸入。

測試整合

先使用最精簡 Python WAV 用戶端 及符合其已宣告取樣率的單聲道 PCM16 WAV。請確認:

  1. 伺服器接受設定並傳送 session.updated
  2. 輸入會以預期速度產生逐字稿及回應音訊事件。
  3. 中斷及取消回應會停止餘下的輸出音訊。
  4. 內嵌函數結果或已儲存智能體工具結果會傳回至模型。
  5. 無效輸入會產生由你的用戶端處理的 error 事件。
  6. 你的用戶端會關閉 socket,且通話會顯示於通話記錄

Realtime WebSocket 參考文件列出可接受的 事件、音訊格式、工作階段欄位及完整範例。

費用

Realtime 通話採用所選產品的標準每分鐘收費。啟用即時逐字稿增量會為整個工作階段增加每分鐘附加費;有關收費請參閱即時逐字稿,產品收費請參閱價格

POST /v1/realtime/sessions 是獨立管理的 LiveKit 路徑。它會建立房間及具範圍限制的參與者權杖;直接 WebSocket 連線不需要使用它。

如需框架整合,請參閱從 Pipecat 使用 ThunderPhone從 LiveKit Agents 使用 ThunderPhone