メインコンテンツへスキップ
ミドルウェアは、すべてのLLMレスポンスを傍受し、アプリケーションの残りの部分に到達する前にRAILスコアを付加するパターンです。LLMクライアントをRAILラッパーに置き換えます。ラッパーはLLMを呼び出し、レスポンスを評価し、コンテンツとスコアの両方を単一のオブジェクトで返します。

解決する問題

ミドルウェアがない場合、すべてのLLM呼び出しに責任あるAIチェックを追加することは、LLMを呼び出すすべての場所に評価コードを書くことを意味し、ロジックの重複、カバレッジのギャップのリスク、アプリケーションコードの混乱を引き起こします:
# 評価コードが至る所に散らばっている
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

    # すべての関数で評価を忘れないようにしなければならない
    score = rail_client.eval(content=content, mode="basic")
    if score.rail_score.score < 7.0:
        raise ValueError("レスポンスが品質基準を下回っています")

    return content

仕組み

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

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

ラッパーラップするPythonJavaScript
RAILOpenAIOpenAIチャット完了はいはい
RAILGeminiGoogle Geminiはいはい
RAILAnthropicAnthropic Claudeはいはい
RAILLangChain任意のLangChain LLMはい
カスタムラッパー任意のHTTPベースのLLMはいはい

観察モードと強制モード

すべてのレスポンスにスコアを付け、ブロックはしません。レスポンスフローを中断せずに品質を測定するために使用します。
client = RAILOpenAI(
    openai_api_key="...",
    rail_api_key="...",
    eval_mode="basic",
    # スレッショルドなし — 常にレスポンスを返す
)

response = await client.chat(messages=[...])
print(response.content)        # LLMのレスポンス
print(response.rail_score)     # RAILスコア(常に存在)
print(response.threshold_met)  # なし — スレッショルドが設定されていない

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

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

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

async def rail_middleware(llm_call, messages, threshold=7.0):
    """任意の非同期LLM呼び出しのための一般的なRAILミドルウェア。"""
    content = await llm_call(messages)

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

    if result.rail_score.score < threshold:
        raise ValueError(
            f"レスポンスのスコアが {result.rail_score.score:.1f} で、基準 {threshold} を下回っています。"
            f"失敗した次元: {[d for d, s in result.dimension_scores.items() if s.score < threshold]}"
        )

    return content, result

# 任意のLLMで使用:
content, score = await rail_middleware(my_llm_call, messages, threshold=7.5)

次に何をするか

概念: ポリシーエンジン

セッション全体でスコアに基づいてアクションを実行する宣言的ルール。

Python: 統合

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

JavaScript: プロバイダ

OpenAI、Gemini、AnthropicのためのTypeScriptラッパー。

Python: ミドルウェアSDK

RAILMiddleware - 任意のLLM関数をラップします。