AI・機械学習
上級

セマンティックルーター(セマンティックルーター)

セマンティックルーター(Semantic Router)とは、ユーザーのプロンプトをベクトル埋め込み(Embedding)に変換し、意味的類似度に基づいてリクエストを最適なLLMモデルやハンドラーに振り分けるルーティング技術である。Aurelio AIが開発したOSSライブラリ「semantic-router」が代表的実装であり、従来のキーワードマッチングやルールベースの分岐では捉えきれない「意味の近さ」を活用して、高精度かつ低レイテンシのルーティングを実現する。

0 回閲覧
0 いいね

セマンティックルーターとは

セマンティックルーター(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-small1536速い○ 高$0.02/1Mトークン
OpenAI text-embedding-3-large3072中速◎ 最高$0.13/1Mトークン
Cohere embed-v31024速い○ 高$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」は、セマンティックルーティングの事実上の標準実装として広く利用されている。

項目詳細
GitHubaurelio-labs/semantic-router
ライセンスMIT
対応言語Python 3.9+
対応EmbeddingOpenAI、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 Pro100万トークン対応
multilingual中国語に翻訳GPT-4o多言語性能が高い

この構成により、プロンプトの意味内容に基づいて最適なモデルが自動選択され、コスト効率と品質の両立が実現できる。

性能特性とベンチマーク

セマンティックルーターの性能は、ルート数・utterance数・Embeddingモデルの選択に依存する。

構成ルート数utterance数/ルートレイテンシ(P50)分類精度
小規模5108ms92%
中規模202012ms89%
大規模505025ms85%
超大規模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%のさらなるコスト削減が見込まれる。