> ## 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.

# Middleware

> Drop-in provider wrappers जो हर AI response को intercept करके अपने आप एक RAIL score जोड़ते हैं।

Middleware वह pattern है जिसमें हर AI response को intercept करके, उसके आपकी बाकी application तक पहुंचने से पहले उस पर एक RAIL score जोड़ा जाता है। आप अपने AI client को एक RAIL wrapper से बदल देते हैं। wrapper model को call करता है, response को evaluate करता है, और content व scores दोनों को एक ही object में लौटा देता है।

<Info>
  **Python SDK:** [Integrations reference](/integrations/overview) | **API:** [Evaluation endpoint](/api-reference/evaluation)
</Info>

## यह किस समस्या को हल करता है

middleware के बिना, हर AI call में responsible-AI checks जोड़ने का मतलब है कि जहाँ-जहाँ आप model को call करते हैं वहाँ evaluation code लिखना, logic को बार-बार दोहराना, coverage में गैप का खतरा, और application code को भर देना:

<CodeGroup>
  ```python Without middleware theme={null}
  # 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
  ```

  ```python With middleware theme={null}
  # Scoring is automatic - set up once, forget about it
  from rail_score_sdk.integrations import RAILOpenAI

  client = RAILOpenAI(
      openai_api_key="...",
      rail_api_key="YOUR_RAIL_API_KEY",
      eval_mode="basic",
      threshold=7.0,
  )

  async def get_response(user_message):
      response = await client.chat(messages=[{"role": "user", "content": user_message}])
      return response.content  # .rail_score and .threshold_met are also available
  ```
</CodeGroup>

## यह कैसे काम करता है

```mermaid theme={null}
flowchart LR
    App["Your Application"] --> Wrapper["RAIL Wrapper"]
    Wrapper -->|"1. Forward request"| LLM["AI Model API\n(OpenAI / Gemini / Anthropic)"]
    LLM -->|"2. Response content"| Wrapper
    Wrapper -->|"3. Evaluate"| RAIL["RAIL Score API"]
    RAIL -->|"Score + dimensions"| Wrapper
    Wrapper -->|"content + rail_score\n+ threshold_met"| App
```

जब आप RAIL wrapper पर कोई method call करते हैं, तो तीन चीज़ें पर्दे के पीछे होती हैं:

1. आपके messages एक सामान्य API call की तरह नीचे वाले model API को forward किए जाते हैं।
2. model की response आपके configure किए गए mode में RAIL evaluation endpoint को भेजी जाती है।
3. एक wrapped response object लौटता है जिसमें original content, RAIL score, per-dimension scores, और एक `threshold_met` boolean, सब एक ही return value में होते हैं।

## Supported providers

| Wrapper         | Wraps                    | Python | JavaScript |
| --------------- | ------------------------ | ------ | ---------- |
| `RAILOpenAI`    | OpenAI chat completions  | Yes    | Yes        |
| `RAILGemini`    | Google Gemini            | Yes    | Yes        |
| `RAILAnthropic` | Anthropic Claude         | Yes    | Yes        |
| `RAILLangChain` | Any LangChain model      | Yes    | —          |
| Custom wrapper  | किसी भी HTTP-based model | Yes    | Yes        |

## Observe mode vs enforce mode

<Tabs>
  <Tab title="Observe only">
    हर response को score करें, कभी block न करें। इसे तब use करें जब आप response flow में रुकावट डाले बिना quality मापना चाहते हैं।

    ```python theme={null}
    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
    ```
  </Tab>

  <Tab title="Enforce threshold">
    जब कोई response बार पूरा न करे तो `ThresholdError` raise करें।

    ```python theme={null}
    client = RAILOpenAI(
        openai_api_key="...",
        rail_api_key="...",
        eval_mode="basic",
        threshold=7.0,
    )

    try:
        response = await client.chat(messages=[...])
        return response.content
    except ThresholdError as e:
        # e.rail_score and e.failed_dimensions are available
        return fallback_response()
    ```
  </Tab>

  <Tab title="Auto-regenerate">
    जब कोई response threshold से नीचे रह जाए तो अपने आप Safe Regeneration trigger करें।

    ```python theme={null}
    client = RAILOpenAI(
        openai_api_key="...",
        rail_api_key="...",
        eval_mode="basic",
        threshold=7.0,
        on_fail="regenerate",
        max_iterations=3,
    )

    # Returns the best content — original or regenerated
    response = await client.chat(messages=[...])
    print(response.content)
    print(response.iterations_taken)  # 1 if original passed
    ```
  </Tab>
</Tabs>

## अपना custom middleware लिखना

अगर आप किसी ऐसे model provider को use करते हैं जिसका built-in wrapper नहीं है, तो core `eval()` call का इस्तेमाल करके अपना middleware बनाएं:

```python theme={null}
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)
```

## आगे क्या

<CardGroup cols={2}>
  <Card title="Concepts: Policy Engine" icon="gavel" href="/concepts/policy-engine">
    किसी session भर scores पर action लेने के लिए declarative rules।
  </Card>

  <Card title="Python: Integrations" icon="python" href="/integrations/overview">
    पूरा provider wrapper documentation और options।
  </Card>

  <Card title="JavaScript: Providers" icon="js" href="/sdk/javascript/overview">
    OpenAI, Gemini, Anthropic के लिए TypeScript wrappers।
  </Card>

  <Card title="Python: Middleware SDK" icon="layer-group" href="/sdk/python/middleware">
    RAILMiddleware - किसी भी model function को wrap करें।
  </Card>
</CardGroup>
