JevCode / パターン

信頼度ルーティング

信頼度を2つ目の判断軸として扱う。回答は「何であるか」を示し、信頼度は「実行すべきかどうか」を判断する。

本文はzh-CNからの機械翻訳です。校正は未実施で、参考情報としてのみご利用ください。

ソース: docs.typesafe.ai/patterns/confidence-routingconfidenceroutingsafety
Confidence routing

このパターンが解決する問題

回答と信頼度は独立した2つの情報次元です。回答のみに基づいて分岐を行うことは、モデルが提供している情報の半分を捨てることに等しいです。

信頼度によるルーティングのアプローチは、まず回答を取得し、その後に信頼度を用いてその回答が実行に耐えうるほど信頼できるかどうかを判断します。これは、信頼性が高く安全なシステムを構築するための基盤となります。

例:音声による銀行操作

音声インターフェースを構築し、ユーザーが音声でアカウントを操作できるようにしていると想像してください。意図認識の信頼度は高いに越したことはありませんが、アクションのリスクが異なるため、異なる信頼度の閾値が必要です。

ステップ1:ユーザーの意図を特定する

Choice の呼び出しにより意図を取得します。候補には check_balance(残高照会)や approve_transfer(送金承認)などがあります。

ステップ2:信頼度に基づいてルーティングする

action = response.answers["intent"]

# いかなるアクションも、信頼度が 0.6 未満の場合はサポート担当者へ転送
if action.confidence < 0.6:
    route_to_support_agent(account_id)

elif action.choice == "check_balance":
    # リスクが低い。信頼度 0.6 で十分である。
    show_balance(account_id)

elif action.choice == "approve_transfer":
    if action.confidence > 0.85:
        # リスクは高いが、信頼度も高い。実行する。
        ...
    else:
        # リスクは高いが、信頼度は中程度。確認を求める。
        ask_user_to_confirm(account_id)

なぜ閾値を段階化する必要があるか

上記のコードにある3つの閾値を見てみましょう。

閾値 役割
< 0.6 で一律ブロック モデルが不確実性を自己申告した場合、いかなるアクションも実行しない
check_balance の閾値 0.6 読み取り専用の操作であり、誤っても回復可能
approve_transfer の閾値 0.85 資金に関わるため、誤ると不可逆となる

これが「リスクに応じた閾値のスケーリング」のエンジニアリング的な表現です。システム全体で単一の統一された閾値しか使用しない場合、リスクの低いアクションではユーザーに過度な干渉を行ってしまうか、リスクの高いアクションでは慎重さが不足してしまいます。

デザイン上のポイント

まずハードル(下限値)を設定し、次にアクションごとの閾値を設定します。 ハードル(例では 0.6)は、モデルが「確かに不確実である」と自己申告した場合をブロックし、セーフティネットとして機能します。アクションごとの閾値は、この上でリスクに応じて段階化されます。

閾値を散在するマジックナンバーではなく、明示的な設定としてください。 各アクションの閾値を1か所に集中して定義することで、監査や調整を容易にします。ビジネスサイドから「なぜこの送金には手動確認が必要なのか」と問われた際、具体的な数値を指し示すことができます。

信頼度でビジネスロジックの検証を代替しないでください。 信頼度はモデルの自己評価であり、ビジネスルールの代わりにはなりません。金額の上限や権限チェックといった決定性の高いルールは、依然としてコード内に記述する必要があります。

実際のデータを用いて閾値を調整してください。 公式には、適切な閾値はあなたのドメインと、あなたのユースケースにおけるモデルの性能に依存すると明確に指摘されています。保守的な閾値から始め、独自のデータでテストし、観察結果に基づいて調整してください。

使用すべきでない場合

ある決定を誤っても影響がない場合(例えば、ログへのタグ付けなど)、信頼度の閾値を追加するのは複雑さと人的コストを増やすだけです。信頼度によるルーティングの価値は、決定の不可逆性と比例します。

関連