※ 本記事は、以下 Agora 公式ドキュメントを基に、編集・構成しました。
・https://docs.agora.io/en/conversational-ai/get-started/quickstart
・https://docs.agora.io/en/conversational-ai/rest-api/agent/join
・https://docs.agora.io/en/conversational-ai/develop/custom-llm
Agora Conversational AI Engine は、開発者がリアルタイムで自然な音声対話を行える AI アプリケーションを、迅速かつ容易に構築するために設計されたエンジンです。
このエンジンは、カスタマイズ可能な AI エージェントの実行環境を提供します。その内部では、ASR (音声認識) によるテキスト化、LLM (大規模言語モデル) による応答生成、TTS (音声合成) による音声化という一連の処理が、パイプライン (Chained Model) として実行されます。
このパイプラインを通じて、ASR、LLM、TTS の各コンポーネントがシームレスに連携し、単一の AI エージェントとして機能します。
このほか Agora Convo AI の特徴・詳細については、こちらの入門記事も併せてご覧ください。
Convo AI は、標準で主要な AI ベンダー(OpenAI, Azure など)の汎用 LLM と連携できるよう設計されており、対応ベンダーは継続的に拡充されています。
本記事の主題である RAG (Retrieval Augmented Generation) や Tool Calling など、独自処理を組み合わせた高度な AI エージェントを構築する場合、Convo AI では、これらのロジックを LLM と共に内包する形で構築された Custom LLM サービスと連携するアプローチを採用しています。
Custom LLM として連携するサービスを構築するには、以下の技術要件を満たす必要があります。
上記要件を満たす Custom LLM サービスを構築することで、Convo AI のリアルタイム音声パイプラインを活用しつつ、RAG による情報検索や Tool Calling を組み合わせた AI エージェントの実装ができるようになります。
Custom LLM サービスを構築するためには、Convo AI と Chat Completions 互換プロトコルで対話するインターフェースの実装が必要です。
ここでは、Agora の公式ドキュメントをベースに、Python (FastAPI) を使用した実装例を解説します。
Note: 本記事では Python を使用しますが、Agora 公式のサンプルリポジトリでは Go や Node.js を使用した実装例も提供されています。これらの言語での開発に関心がある方は、以下のリソースも併せてご参照ください。
まず、Agora Convo AI から送信されるリクエストのスキーマを Pydantic の BaseModel を使って定義します。これにより、FastAPI がリクエストの型チェックとバリデーションを自動的に行います。
次に、エンドポイント (本記事では /chat/completions とする) を定義します。リクエストボディの型として ChatCompletionRequest を指定します。
Custom LLM サービスで処理したテキストデータをメッセージチャンクとして順次ストリーミングする形でレスポンスを返却します。 ここでは、固定メッセージを返却する Custom LLM サービスを例とします。
ブログのスペースの都合上、Pydantic のモデル定義の一部は省略し、連携に必要な最小限の構成にしています。完全な定義は公式ドキュメントをご参照ください。
import json
import asyncio
import uuid
import time
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from typing import Dict, Any, Optional, List, Union
app = FastAPI()
# --- Pydantic モデル定義 (インターフェースの定義) ---
class SystemMessage(BaseModel):
role: str = "system"
content: Union[str, List[str]]
class UserMessage(BaseModel):
role: str = "user"
content: Union[str, List[Dict[str, Any]]] # 簡易的に型を定義
class AssistantMessage(BaseModel):
role: str = "assistant"
content: Optional[str] = None
tool_calls: Optional[List[Dict]] = None
class ToolMessage(BaseModel):
role: str = "tool"
content: str
tool_call_id: str
class ChatCompletionRequest(BaseModel):
messages: List[Union[SystemMessage, UserMessage, AssistantMessage, ToolMessage]]
stream: bool = True
model: Optional[str] = None
# tools や tool_choice などのフィールドも定義可能
# --- ここまで Pydantic モデル定義 ---
FIXED_RESPONSE = "こちらは Custom LLM からの固定応答メッセージです。"
# --- ストリーミングレスポンスの実装 ---
async def fixed_message_generator():
"""
固定メッセージを SSE 形式でストリーミングするジェネレーター (デモ用の最小ロジック)
"""
words = FIXED_RESPONSE.split(" ")
message_id = f"chatcmpl-{uuid.uuid4().hex}"
created_time = int(time.time())
for word in words:
chunk_data = {
"id": message_id,
"object": "chat.completion.chunk",
"created": created_time,
"model": "fixed_model",
"choices": [
{
"index": 0,
"delta": {
"role": "assistant",
"content": word + " ",
},
"finish_reason": None,
}
],
}
yield f"data: {json.dumps(chunk_data)}\n\n"
await asyncio.sleep(0.1)
final_chunk = {
"id": message_id,
"object": "chat.completion.chunk",
"created": created_time,
"model": "fixed_model",
"choices": [
{
"index": 0,
"delta": {},
"finish_reason": "stop",
}
],
}
yield f"data: {json.dumps(final_chunk)}\n\n"
yield "data: [DONE]\n\n"
# --- ここまで ストリーミングレスポンスの実装 ---
# --- エンドポイントの実装 ---
@app.post("/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest):
"""
OpenAI Chat Completions API 互換のエンドポイント。
Pydantic モデルでリクエストを受け取り、固定メッセージをストリーミングで返す。
"""
if not request.stream:
raise HTTPException(
status_code=400, detail="chat completions require streaming"
)
return StreamingResponse(fixed_message_generator(), media_type="text/event-stream")
# --- ここまで エンドポイントの実装 ---
前節で構築した Custom LLM サーバーを実際に Convo AI と連携させるには、専用の RESTful API (join API) を使用して、サーバー設定と共に AI エージェントを起動します。
ここで重要なのがサーバーの接続性です。Convo AI エンジンはクラウド上で動作し、そこから直接 LLM サービスへアクセスするため、Custom LLM サービスは Agora のクラウドエンジンからアクセス可能な状態にある必要があります。
テスト目的であれば ngrok などのトンネリングツールを使用するか、本番運用を見越して Render、Railway、AWS などのクラウドサービスへデプロイし、https://your-service-domain.com のような公開 URL を取得してください。
エージェントの起動には join API を使用します。 API の詳細な仕様やパラメータについては、以下の公式ドキュメントや過去の技術ブログでも詳しく解説していますので、併せてご参照ください。
join API のリクエストボディにおいて、llm オブジェクトを以下のように設定します。url フィールドに自作サービスの公開 URL (エンドポイント) を指定することが必須です。
// ... (他の設定項目)
"llm": {
"url": "https://your-service-domain.com/chat/completions",
"api_key": "", // Custom LLM サービス側で認証が必要な場合、認証情報を提供します
"system_messages": [
{
"role": "system",
"content": "あなたは有能な AI エージェントです。"
}
]
},
// ... (TTS, ASR などの設定)
このリクエストが成功すると、AI エージェントが指定したチャンネルに参加します。
// 200 OK
{
"agent_id": "1NT29X10YHxxxxxWJOXLYHNYB",
"create_ts": 1737111452,
"status": "RUNNING"
}
ユーザーが話しかけると、Custom LLM サービスが反応して、先ほど実装した固定応答メッセージ(例: "こちらは Custom LLM からの...")が AI エージェントから聞こえてくるはずです。
前節では、仕組みを理解するために「固定メッセージを返す」だけのシンプルな実装を行いました。
しかし、Custom LLM の真価は、「対話の裏側で任意のプログラムを実行できる」点にあります。単に LLM にテキストを生成させるだけでなく、データベースを検索したり、計算を行ったり、外部システムを操作したりといった独自のビジネスロジックを、対話のパイプラインに直接組み込むことができるのです。
この「プログラムによる制御」を活かすことで、以下のような高度な対話システムが実現可能になります。
社内ドキュメントや製品マニュアルに基づいた回答を生成させたい場合、RAG の実装が有効です。
Convo AI の Custom LLM はストリーミング応答に対応しているため、検索処理さえ高速であれば、RAG を挟んでもスムーズな音声対話を維持できます。
尚、Agora 公式ブログ (英語) では、一例としてベクトルデータベースの Pinecone を使用して、この RAG 構成を実装する具体的な手順を紹介しています。実装の際は、ぜひ以下の記事も参考にしてください。
「会議室を予約して」「電気を消して」といったリクエストに応えるには、専用の外部 API との連携 (Tool Calling) が必要です。
これを実現する場合の例として、Custom LLM サービスとして、開発者は利用可能なツールの定義と実行ロジックをサービス内部で管理させることが想定されます。Custom LLM 側で独自のビジネスロジックに基づき、ユーザーの意図に応じて適切な API を実行、その実行結果を含めて最終的な回答を生成するロジックを実装することで、現実世界のアクションを伴う AI エージェントが構築できます。
Custom LLM は、Convo AI と実際の言語モデルとの間の「プロキシ (仲介役)」としても機能します。
このように、Custom LLM サービスを利用することで、Agora Convo AI のリアルタイム音声対話機能を活用しつつ、独自のビジネス要件に合わせた柔軟な機能拡張が可能になります。
Agora Conversational AI (Convo AI) は、リアルタイムな音声対話に必要な ASR (音声認識)、TTS (音声合成)、RTC (通信) の機能をまとめて提供するプラットフォームです。
本記事で解説した Custom LLM 連携 は、このプラットフォーム上で、開発者が独自のビジネスロジックを実行するための仕組みです。
Custom LLM を OpenAI Chat Completions 互換のインターフェースとして確立することで、バックエンドの LLM の種類や複雑なロジックを Convo AI から抽象化できます。これにより、既存のナレッジベースを活用した RAG や、外部システムを操作する Tool Calling など、汎用的な LLM だけでは実現できない実用的な要件に応える AI エージェントを、より容易かつ柔軟に実装することが可能になります。
ぜひ、Custom LLM を活用して、独自の要件に特化した対話型 AI を構築してみてください。