メインコンテンツへスキップ
ミドルウェアは、すべての AI レスポンスをインターセプトし、アプリケーションの他の部分に届く前に RAIL スコアを付与するパターンです。AI クライアントを RAIL ラッパーに置き換えます。ラッパーはモデルを呼び出し、レスポンスを評価し、コンテンツとスコアの両方を 1 つのオブジェクトで返します。

解決する課題

ミドルウェアがないと、すべての AI 呼び出しに責任ある AI のチェックを追加するには、モデルを呼び出すすべての箇所に評価コードを書くことになり、ロジックの重複、カバレッジの抜け、アプリケーションコードの煩雑化を招きます:
# Eval code scattered everywhere
async def get_response(user_message):
    response = await openai_client.chat.completions.create(
        model="gpt-4o", messages=[{"role": "user", "content": user_message}]
    )
    content = response.choices[0].message.content

    # Must remember to eval in every function
    score = rail_client.eval(content=content, mode="basic")
    if score.rail_score.score < 7.0:
        raise ValueError("Response below quality threshold")

    return content

仕組み

RAIL ラッパーのメソッドを呼び出すと、3 つのことが透過的に行われます:
  1. メッセージは通常の API 呼び出しとして、基盤となるモデルの API へ転送されます。
  2. モデルのレスポンスは、設定したモードで RAIL 評価エンドポイントに送信されます。
  3. 元のコンテンツ、RAIL スコア、次元ごとのスコア、threshold_met のブール値をすべて 1 つの戻り値に含む、ラップされたレスポンスオブジェクトが返されます。

サポートされているプロバイダ

ラッパーラップ対象PythonJavaScript
RAILOpenAIOpenAI chat completionsはいはい
RAILGeminiGoogle Geminiはいはい
RAILAnthropicAnthropic Claudeはいはい
RAILLangChain任意の LangChain モデルはい
カスタムラッパー任意の HTTP ベースのモデルはいはい

観察モードとエンフォースモード

すべてのレスポンスをスコアリングしますが、ブロックはしません。レスポンスのフローを中断せずに品質を測定したいときに使います。
client = RAILOpenAI(
    openai_api_key="...",
    rail_api_key="...",
    eval_mode="basic",
    # No threshold — always returns response
)

response = await client.chat(messages=[...])
print(response.content)        # The model's response
print(response.rail_score)     # RAIL score (always present)
print(response.threshold_met)  # None — no threshold configured

カスタムミドルウェアの作成

組み込みラッパーのないモデルプロバイダを使う場合は、コアの eval() 呼び出しを使って独自のミドルウェアを構築します:
from rail_score_sdk import RailScoreClient

rail = RailScoreClient(api_key="...")

async def rail_middleware(model_call, messages, threshold=7.0):
    """Generic RAIL middleware for any async model call."""
    content = await model_call(messages)

    result = rail.eval(content=content, mode="basic")

    if result.rail_score.score < threshold:
        raise ValueError(
            f"Response scored {result.rail_score.score:.1f} — below threshold {threshold}. "
            f"Failed: {[d for d, s in result.dimension_scores.items() if s.score < threshold]}"
        )

    return content, result

# Use with any model:
content, score = await rail_middleware(my_model_call, messages, threshold=7.5)

次のステップ

コンセプト: ポリシーエンジン

セッション全体でスコアに基づきアクションを取る宣言的ルール。

Python: インテグレーション

プロバイダラッパーの完全なドキュメントとオプション。

JavaScript: プロバイダ

OpenAI、Gemini、Anthropic 用の TypeScript ラッパー。

Python: ミドルウェア SDK

RAILMiddleware — 任意のモデル関数をラップします。