ThunderPhone 2.0、提供開始。セルフサービスで、1分あたり2¢から。発表内容を見る

Connect tools & data

PipecatからThunderPhoneを使用

独自のトランスポートと電話機能を使用するPipecatパイプライン内で、ThunderPhone音声エージェントを音声間サービスとして実行します。

Pipecat は、組み合わせ可能なサービスから音声エージェントを構築するためのオープンソースフレームワークです。ThunderPhone は 音声間LLMサービス として接続されます。Pipecat が発信者の音声を送信すると、ThunderPhone はエージェントの音声、文字起こし、関数呼び出しを返し、Pipecat のトランスポート(Daily、LiveKit、Twilio、WebRTC、ローカルマイク)が音声を伝送します。音声認識、言語モデル、音声、ターンテイキング、47言語、ツールはすべて ThunderPhone 上で実行されます。

この方法で行った通話は、他のリアルタイム通話と同様に通話履歴に表示され、製品の分単位料金で請求されます。サブスクリプションは不要で、ThunderPhone の電話番号も使用しません。

インストール

pip install pipecat-thunderphone
export THUNDERPHONE_API_KEY=sk_live_...   # a secret API key

ThunderPhone の Realtime WebSocket は同じプロトコルを使用するため、このパッケージは Pipecat の OpenAI Realtime サービスをラップしています。pipecat-ai 1.8 以降が必要です。

保存済みエージェントを実行する

エージェントが行うすべての処理(プロンプト、音声、エンジン、言語、ツール、あいさつ、無音時のチェックイン)は ThunderPhone で設定します。パイプラインは音声のみを転送します。

from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.worker import PipelineParams, PipelineWorker
from pipecat.processors.aggregators.llm_context import LLMContext
from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair
from pipecat_thunderphone import ThunderPhoneRealtimeLLMService
 
llm = ThunderPhoneRealtimeLLMService(agent_id=12)
 
context = LLMContext()
aggregators = LLMContextAggregatorPair(context)
pipeline = Pipeline([
    transport.input(),
    aggregators.user(),
    llm,
    aggregators.assistant(),
    transport.output(),
])
worker = PipelineWorker(pipeline, params=PipelineParams(allow_interruptions=True))

保存済みエージェントは独自のタイミングで通話を開始するため、サービスは Pipecat に開始応答を要求しません。それでも開始応答が必要な場合は、greet_on_connect=True を渡します。

セッションをインラインで設定する

agent_id を指定しない場合、指示とツールは OpenAI と同様に Pipecat コンテキストから取得されます。product でエンジンを選択し、voice で ThunderPhone の音声を選択します。

from pipecat.adapters.schemas.function_schema import FunctionSchema
from pipecat.adapters.schemas.tools_schema import ToolsSchema
from pipecat.services.llm_service import FunctionCallParams
 
llm = ThunderPhoneRealtimeLLMService(product="bolt", voice="olivia", language="es")
 
async def check_availability(params: FunctionCallParams):
    slots = await calendar.free_slots(params.arguments["date"])
    await params.result_callback({"slots": slots})
 
llm.register_function("check_availability", check_availability)
 
context = LLMContext(
    messages=[{"role": "system", "content": "You are Acme Dental's receptionist."}],
    tools=ToolsSchema(standard_tools=[
        FunctionSchema(
            name="check_availability",
            description="Free appointment slots on a date",
            properties={"date": {"type": "string"}},
            required=["date"],
        )
    ]),
)

インラインセッションはクライアント主導です。コンテキスト到着時に Pipecat が応答を要求するため、エージェントが先に話し、メッセージを追加するか別の応答を要求しない限り、無音時は静かに待機します。

オプション

引数意味
api_keyシークレットキー(sk_live_...)。デフォルトは THUNDERPHONE_API_KEY
agent_id保存済みエージェントを実行。product および voice とは相互排他的。
productインラインセッション用エンジン: sparkbolt、または storm
voiceインラインセッション用の ThunderPhone 音声名。
languageインラインセッションの主要言語ヒント。例: es
from_number, to_numberパイプラインが電話回線の前段にある場合に、通話で記録する番号。
live_transcripts発話途中の発信者トランスクリプト断片をストリーミング(追加課金)。
greet_on_connectセッションの準備完了後すぐに最初の応答をリクエスト。
end_task_on_call_endedThunderPhone が通話を終了したときに EndWorkerFrame をプッシュ(デフォルトで有効)。

イベント

ThunderPhone はリアルタイムプロトコルに加えてプラットフォームイベントを追加します。サービスはこれらをハンドラーに配信します。

@llm.event_handler("on_call_ended")
async def on_call_ended(service, event):
    print("call ended:", event["reason"], "call id:", service.call_id)

service.call_id はセッションが開始されると設定されます。通話後に録音、トランスクリプト、評価を取得するには、GET /v1/calls/{call_id} とともに使用します。

制限

  • ターン検出はサーバー側で常に有効です。Pipecat 主導のターン(turn_detection=False)はサポートされていません。
  • サービスに登録した関数はインラインセッションでのみ実行されます。保存済みエージェントは ThunderPhone 上で独自のツールを実行します。
  • 音声は双方向とも 24 kHz、16 ビット、モノラル PCM です。
  • 動画フレームは無視されます。