> ## Documentation Index
> Fetch the complete documentation index at: https://docs.responsibleailabs.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python : Middleware

> RAILMiddleware - enveloppez toute fonction LLM asynchrone avec une évaluation RAIL automatique.

<Info>
  **Concept :** [Middleware](/concepts/middleware) | **API :** [Evaluation API](/api-reference/evaluation)
</Info>

`RAILMiddleware` enveloppe toute fonction asynchrone qui génère des réponses LLM, ajoutant un score RAIL automatique sans modifier votre logique d'appel LLM.

<CodeGroup>
  ```python Basic setup theme={null}
  import asyncio
  from rail_score_sdk import RAILMiddleware

  async def my_llm(messages, **kwargs):
      # Votre appel LLM ici — retourne une chaîne
      return "Le LLM a généré cette réponse."

  async def main():
      mw = RAILMiddleware(
          api_key="YOUR_RAIL_API_KEY",
          generate_fn=my_llm,
          threshold=7.0,
          policy="block",
          eval_input=True,
          input_threshold=5.0,
      )

      result = await mw.run(
          messages=[
              {"role": "system", "content": "Vous êtes un assistant utile."},
              {"role": "user", "content": "Expliquez l'informatique quantique."},
          ]
      )
      print(f"Score : {result.score}, Seuil atteint : {result.threshold_met}")
      print(f"Contenu : {result.content}")

  asyncio.run(main())
  ```

  ```python Observe mode (no blocking) theme={null}
  mw = RAILMiddleware(
      api_key="YOUR_RAIL_API_KEY",
      generate_fn=my_llm,
      # Pas de seuil — évalue chaque réponse mais ne bloque jamais
  )

  result = await mw.run(messages=[...])
  print(result.score)        # Toujours présent
  print(result.threshold_met)  # Aucun — aucun seuil défini
  ```

  ```python Auto-regenerate on fail theme={null}
  mw = RAILMiddleware(
      api_key="YOUR_RAIL_API_KEY",
      generate_fn=my_llm,
      threshold=7.0,
      policy="regenerate",
      max_iterations=3,
  )

  result = await mw.run(messages=[...])
  print(result.content)           # Meilleur contenu à travers les itérations
  print(result.iterations_taken)  # 1 si l'original a réussi
  ```
</CodeGroup>

## Paramètres

| Paramètre         | Type             | Par défaut | Description                                  |
| ----------------- | ---------------- | ---------- | -------------------------------------------- |
| `api_key`         | `str`            | —          | Clé API RAIL                                 |
| `generate_fn`     | `async callable` | —          | Votre fonction LLM                           |
| `threshold`       | `float`          | `None`     | Bloquer/régénérer en dessous de ce score     |
| `policy`          | `str`            | `"block"`  | `"block"` ou `"regenerate"`                  |
| `eval_input`      | `bool`           | `False`    | Évaluer également les messages d'entrée      |
| `input_threshold` | `float`          | `None`     | Seuil pour l'évaluation des entrées          |
| `max_iterations`  | `int`            | `3`        | Nombre maximal de tentatives de régénération |
