セマンティックルーター(セマンティックルーター)
セマンティックルーター(Semantic Router)とは、ユーザーのプロンプトをベクトル埋め込み(Embedding)に変換し、意味的類似度に基づいてリクエストを最適なLLMモデルやハンドラーに振り分けるルーティング技術である。Aurelio AIが開発したOSSライブラリ「semantic-router」が代表的実装であり、従来のキーワードマッチングやルールベースの分岐では捉えきれない「意味の近さ」を活用して、高精度かつ低レイテンシのルーティングを実現する。
セマンティックルーターとは
セマンティックルーター(Semantic Router)は、自然言語の意味的内容を数値ベクトル(埋め込み表現 / Embedding)に変換し、事前定義されたルート(Route)との類似度を計算することでリクエストの振り分け先を決定するルーティング手法である。従来のルールベースルーティング(if文やキーワードマッチング)が「表層的な文字列一致」に依存するのに対し、セマンティックルーターは「意味的な近さ」を数学的に計算するため、表現のバリエーション(言い換え、略語、口語表現等)に対して頑健なルーティングを実現できる。
例えば、「Pythonでソート関数を書いて」「Pythonの配列を並び替えるコードが欲しい」「How to sort a list in Python?」という3つのプロンプトは、キーワードベースでは異なるルールが必要になるが、セマンティックルーターでは同一の「コード生成」ルートに自動分類される。
動作原理
セマンティックルーターの動作は以下の4ステップで構成される。
Step 1: ルート定義
ルーティング先となる各ルート(Route)を定義する。各ルートは名前、紐づくハンドラー(LLMモデルやツール)、および代表的なユーザー発話例(Utterance)のリストで構成される。
from semantic_router import Route
code_route = Route(
name="code_generation",
utterances=[
"コードを書いて",
"プログラムを作成して",
"関数を実装して",
"バグを修正して",
"Write a function that",
"Implement a class for",
],
)
math_route = Route(
name="math_reasoning",
utterances=[
"この方程式を解いて",
"確率を計算して",
"微分を求めて",
"Solve this equation",
"Calculate the integral",
],
)
Step 2: ルートベクトルの事前計算
各ルートのutteranceをEmbeddingモデル(OpenAI text-embedding-3-small、Cohere embed-v3、ローカルのsentence-transformers等)でベクトル化し、ルートごとの代表ベクトル(セントロイド)を計算する。この処理は初期化時に1回だけ実行され、以降はインメモリで保持される。
| Embeddingモデル | 次元数 | 速度 | 精度 | コスト |
|---|---|---|---|---|
| OpenAI text-embedding-3-small | 1536 | 速い | ○ 高 | $0.02/1Mトークン |
| OpenAI text-embedding-3-large | 3072 | 中速 | ◎ 最高 | $0.13/1Mトークン |
| Cohere embed-v3 | 1024 | 速い | ○ 高 | $0.10/1Mトークン |
| sentence-transformers (all-MiniLM-L6-v2) | 384 | 最速 | △ 中 | 無料(ローカル) |
| Fastembed (BAAI/bge-small-en-v1.5) | 384 | 最速 | △ 中 | 無料(ローカル) |
Step 3: 入力プロンプトのベクトル化
ユーザーのプロンプトを同じEmbeddingモデルでベクトル化する。
Step 4: 類似度計算とルート選択
入力ベクトルと各ルートのセントロイドベクトルとのコサイン類似度を計算し、最も類似度の高いルートを選択する。閾値(threshold)を設定し、最大類似度が閾値未満の場合は「該当ルートなし」としてデフォルトハンドラーにフォールバックする。
similarity(input, route_i) = cos(embed(input), centroid(route_i))
selected_route = argmax_i(similarity) if max(similarity) > threshold else default
semantic-routerライブラリ
Aurelio AIが開発・公開しているPythonライブラリ「semantic-router」は、セマンティックルーティングの事実上の標準実装として広く利用されている。
| 項目 | 詳細 |
|---|---|
| GitHub | aurelio-labs/semantic-router |
| ライセンス | MIT |
| 対応言語 | Python 3.9+ |
| 対応Embedding | OpenAI、Cohere、HuggingFace、Fastembed、Google、Mistral |
| インデックス | Local(NumPy)、Pinecone、Qdrant |
| 動的ルート | LLM呼び出しによるパラメータ抽出対応 |
| インストール | pip install semantic-router |
基本的な使用例は以下の通りである。
from semantic_router import RouteLayer
from semantic_router.encoders import OpenAIEncoder
encoder = OpenAIEncoder()
routes = [code_route, math_route, creative_route, chitchat_route]
rl = RouteLayer(encoder=encoder, routes=routes)
result = rl("Pythonでクイックソートを実装して")
# result.name == "code_generation"
RouteLayerの初期化時にすべてのutteranceがベクトル化され、インメモリのインデックスに格納される。推論時のレイテンシはEmbedding API呼び出し(5-20ms)+ コサイン類似度計算(<1ms)であり、LLM呼び出しと比較して桁違いに高速である。
動的ルート(Dynamic Routes)
semantic-routerの重要な機能として「動的ルート」がある。静的ルートがプロンプトの分類のみを行うのに対し、動的ルートはプロンプトから構造化されたパラメータを抽出する機能を持つ。
from semantic_router import Route
from pydantic import BaseModel
class TranslationParams(BaseModel):
source_lang: str
target_lang: str
text: str
translation_route = Route(
name="translation",
utterances=["翻訳して", "英語に変換", "Translate this"],
function_schemas=[TranslationParams],
)
動的ルートでは、セマンティック分類後にLLMを呼び出してパラメータ抽出を行う。この2段階アプローチにより、高速な分類(Embedding)と柔軟なパラメータ抽出(LLM)を組み合わせた効率的なパイプラインが構築できる。
LLMルーティングへの応用
セマンティックルーターをLLMモデル選択に応用する場合、各ルートに対して最適なモデルを割り当てる。
| ルート | 代表的プロンプト | 割当モデル | 理由 |
|---|---|---|---|
| code_generation | コードを書いて | Claude Sonnet 4.6 | コード生成精度が最高 |
| math_reasoning | 方程式を解いて | GPT-4o | 数学推論に強い |
| creative_writing | 物語を書いて | Claude Opus 4.5 | 創造性が最高 |
| simple_qa | 首都はどこ? | Claude Haiku 4.5 | 単純回答は最安で十分 |
| long_context | この論文を要約 | Gemini 1.5 Pro | 100万トークン対応 |
| multilingual | 中国語に翻訳 | GPT-4o | 多言語性能が高い |
この構成により、プロンプトの意味内容に基づいて最適なモデルが自動選択され、コスト効率と品質の両立が実現できる。
性能特性とベンチマーク
セマンティックルーターの性能は、ルート数・utterance数・Embeddingモデルの選択に依存する。
| 構成 | ルート数 | utterance数/ルート | レイテンシ(P50) | 分類精度 |
|---|---|---|---|---|
| 小規模 | 5 | 10 | 8ms | 92% |
| 中規模 | 20 | 20 | 12ms | 89% |
| 大規模 | 50 | 50 | 25ms | 85% |
| 超大規模 | 100+ | 100+ | 50ms+ | 80% |
分類精度はルート間の意味的重複が大きいほど低下する。例えば「コード生成」と「コードレビュー」は意味的に近いため、utteranceの設計で明確な差別化が必要である。
ルールベースとの比較
| 比較軸 | ルールベース | セマンティックルーター |
|---|---|---|
| 表現の揺れ対応 | × 個別ルール必要 | ◎ 自動で吸収 |
| 多言語対応 | × 言語ごとにルール | ○ 多言語Embeddingで対応 |
| メンテナンスコスト | △ ルール増加に比例 | ○ utterance追加で拡張 |
| 解釈可能性 | ◎ 条件が明確 | △ ベクトル空間は不透明 |
| エッジケース | ○ 明示的に処理可能 | △ 境界が曖昧 |
| 初期構築コスト | ◎ すぐ書ける | ○ utterance設計が必要 |
| レイテンシ | ◎ <1ms | ○ 5-20ms |
実運用では、セマンティックルーターとルールベースを組み合わせるハイブリッドアプローチが有効である。明確なルールで処理できるケース(入力言語判定、明示的なコマンド等)はルールベースで前処理し、残りをセマンティックルーターで分類する。
導入時の設計指針
セマンティックルーターを本番環境に導入する際の設計指針を示す。
utteranceの設計: 各ルートに最低10個、理想的には20-30個のutteranceを用意する。実際のユーザー入力ログから代表的な発話を抽出するのが最も効果的であり、人工的に作成したutteranceだけでは分布の偏りが生じやすい。
閾値の調整: 閾値が高すぎると多くのリクエストがデフォルトルートにフォールバックし、低すぎると誤分類が増加する。A/Bテストまたはオフライン評価で最適値を探索し、0.4-0.7の範囲で設定するのが一般的である。
Embeddingモデルの選択: 日本語を含む多言語環境では、multilingual-e5-largeやCohere embed-v3-multilingualが高精度を発揮する。英語のみの場合はtext-embedding-3-smallでコストを抑えることも可能である。
キャッシュ戦略: 同一プロンプトの繰り返しが多い環境では、入力ベクトルのキャッシュによりEmbedding API呼び出しを削減できる。Redis等のインメモリストアにベクトルを保存し、完全一致時にキャッシュヒットさせるアプローチが有効である。
よくある質問(FAQ)
Q1: セマンティックルーターはどの程度の規模まで対応できますか?
A1: semantic-routerライブラリはデフォルトでNumPyベースのローカルインデックスを使用しており、1,000ルート×100utterance程度までは単一サーバーで問題なく動作する。それ以上の規模ではPineconeやQdrantなどのベクトルデータベースをバックエンドに使用することで、100万ルート以上にもスケール可能である。ただし、実用上はルート数を50以下に抑え、粒度が細かすぎる分類は避けるのがベストプラクティスである。
Q2: 新しいルートを追加する際にシステムの再起動は必要ですか?
A2: semantic-routerはRouteLayerへの動的なルート追加をサポートしている。rl.add(new_route)メソッドで実行時にルートを追加でき、再起動不要である。ただし、追加されたルートのutteranceベクトルをインデックスに反映する処理が発生するため、大量のルートを同時追加する場合は数秒のレイテンシスパイクが発生する可能性がある。本番環境では、Blue-Greenデプロイメントやカナリアリリースで段階的に反映するのが安全である。
Q3: セマンティックルーターの分類結果を説明可能(Explainable)にする方法はありますか?
A3: ベクトル空間での類似度計算自体はブラックボックスだが、以下の方法で説明性を向上できる。(1)各ルートとの類似度スコアをログに記録し、「なぜこのルートが選ばれたか」を数値で確認可能にする。(2)入力に最も近いutteranceを返すことで、分類根拠の具体例を提示する。(3)UMAP等の次元削減で2Dプロットを可視化し、ルートの境界を視覚的に確認する。semantic-routerライブラリはscoreの返却をサポートしており、閾値近傍の「曖昧なケース」を特定してルート定義を改善するフィードバックループが構築できる。
Q4: カスケードルーティングとセマンティックルーターを組み合わせることは可能ですか?
A4: 可能であり、むしろ推奨されるアプローチである。セマンティックルーターでタスクタイプを分類した後、タスクタイプごとに異なるカスケードチェーンを適用する。例えば、「コード生成」ルートにはHaiku→Sonnetのカスケード、「創作」ルートにはSonnet→Opusのカスケードを設定するなど、タスク特性に合わせた段階的エスカレーションが実現できる。この組み合わせにより、単独方式と比較して15-25%のさらなるコスト削減が見込まれる。