Passer au contenu principal
Le middleware est le pattern qui consiste à intercepter chaque réponse LLM et à y attacher un score RAIL avant qu’elle n’atteigne le reste de votre application. Vous remplacez votre client LLM par un wrapper RAIL. Le wrapper appelle le LLM, évalue la réponse et retourne à la fois le contenu et les scores dans un seul objet.

Le problème que ça résout

Sans middleware, ajouter des vérifications d’IA responsable à chaque appel LLM implique d’écrire du code d’évaluation partout où vous appelez le LLM, de dupliquer la logique, de risquer des lacunes de couverture et d’encombrer votre code applicatif :
# 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

Comment ça fonctionne

Lorsque vous appelez une méthode sur le wrapper RAIL, trois choses se passent de manière transparente :
  1. Vos messages sont transmis à l’API LLM sous-jacente comme un appel API normal.
  2. La réponse du LLM est soumise à l’endpoint d’évaluation RAIL dans le mode que vous avez configuré.
  3. Un objet de réponse enrichi est retourné, contenant le contenu original, le score RAIL, les scores par dimension et un booléen threshold_met, le tout en une seule valeur de retour.

Fournisseurs pris en charge

WrapperEncapsulePythonJavaScript
RAILOpenAIOpenAI chat completionsOuiOui
RAILGeminiGoogle GeminiOuiOui
RAILAnthropicAnthropic ClaudeOuiOui
RAILLangChainTout LLM LangChainOui
Wrapper personnaliséTout LLM basé sur HTTPOuiOui

Mode observation vs mode application

Évaluez chaque réponse, sans jamais bloquer. Utilisez ce mode pour mesurer la qualité sans interrompre le flux de réponses.
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 LLM's response
print(response.rail_score)     # RAIL score (always present)
print(response.threshold_met)  # None — no threshold configured

Écrire un middleware personnalisé

Si vous utilisez un fournisseur LLM sans wrapper intégré, construisez votre propre middleware en utilisant l’appel eval() de base :
from rail_score_sdk import RailScoreClient

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

async def rail_middleware(llm_call, messages, threshold=7.0):
    """Generic RAIL middleware for any async LLM call."""
    content = await llm_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 LLM:
content, score = await rail_middleware(my_llm_call, messages, threshold=7.5)

Et ensuite

Concepts : Moteur de politiques

Des règles déclaratives pour agir sur les scores au sein d’une session.

Python : Intégrations

Documentation complète des wrappers de fournisseurs et options.

JavaScript : Fournisseurs

Wrappers TypeScript pour OpenAI, Gemini, Anthropic.

Python : SDK Middleware

RAILMiddleware - encapsulez n’importe quelle fonction LLM.