Passer au contenu principal
La plupart des applications de chat en production streament. Les tokens sont émis vers le navigateur à mesure que le modèle les produit, donc au moment où une complétion est « terminée », votre utilisateur en a déjà lu la plus grande partie. Cela casse le modèle mental naïf d’un filtre de contenu qui inspecte une réponse entière puis décide — il n’y a pas de réponse entière à inspecter avant qu’il ne soit trop tard. Un filtre de contenu llm streaming doit décider sur les deltas à mesure qu’ils circulent. Cette page porte exactement sur ce cas : comment chaque action à l’étape output se comporte de façon stream-safe sur la passerelle OrcaRouter, et comment rédiger une politique qui tient sur le trafic SSE. Pour le moteur complet — chaque type de règle, champ et route — voir Guardrails.

1. Le problème du filtre de contenu llm streaming

Un guardrail à l’étape output filtre la réponse du modèle. Sur une requête non-streaming, c’est simple : la passerelle a la complétion complète avant qu’un seul octet ne revienne, donc elle peut la bloquer, la masquer ou la laisser passer proprement. Le streaming inverse cela. La réponse arrive comme une séquence de deltas SSE, chacun transmis à votre client dès qu’il atterrit, donc un filtre qui attend la fin ne filtre rien. La réponse d’OrcaRouter est un scanner de flux : à mesure que les deltas de sortie circulent, le scanner exécute vos règles à l’étape output contre le texte qui s’accumule et agit à l’instant où une règle se déclenche — pas après que le flux est terminé. L’action que vous rédigez décide ce que signifie « agit » : un block coupe le flux et un flag le laisse passer. Un mask redacte bien sur la sortie non-streaming, mais la réécriture de flux in-band est sur la feuille de route — sur un flux aujourd’hui, le scanner calcule le masque mais n’agit que sur la décision de block, donc une règle mask ne redacte pas encore une réponse streamée.
Cette mise en garde ne compte que pour les règles à l’étape output sur les requêtes streaming. Les règles à l’étape input filtrent la requête avant que le modèle ne tourne, donc elles sont pleinement actives y compris le masquage — et toute règle de sortie sur une requête non-streaming voit la réponse entière et se comporte normalement, y compris mask.

2. Ce qui est stream-safe aujourd’hui

Une règle block est appliquée sur la sortie streaming et non-streaming. Sur un flux, le scanner observe les deltas ; quand une règle de block se déclenche, il coupe le flux — scelle le scanner, émet un court avis de remplacement ([response truncated by guardrail: … policy violation]) comme delta final, et ferme le canal SSE avant que tout contenu bloqué supplémentaire n’atteigne le client. Parce que le statut de réponse HTTP est déjà engagé à 200 au moment où le premier delta est émis, un block en plein flux ne peut pas réémettre un statut — il termine le flux ouvert avec élégance. Le corps HTTP 400 guardrail_blocked est la forme du block de sortie non-streaming.Les octets déjà émis vers le client ne peuvent pas être rétractés, donc un block en streaming est au mieux sur ce qui a déjà été streamé mais arrête de façon fiable tout ce qui suit la correspondance. Pour une garantie dure qu’aucun octet fautif n’est jamais envoyé — et pour le corps 400 guardrail_blocked — envoyez la requête en non-streaming.
Une règle mask réécrit la correspondance — par exemple un email dans la réponse devient [EMAIL] — sur la sortie non-streaming, où la passerelle détient la complétion entière et transmet la forme redactée à votre client.Sur une sortie streaming aujourd’hui, le scanner calcule le masque mais ne transmet pas le texte masqué — il n’agit que sur la décision de block — donc une règle mask ne redacte pas une réponse streamée. La réécriture de sortie streaming in-band est sur la feuille de route. Jusqu’à sa livraison, si vous avez besoin qu’une réponse streamée n’expose jamais le texte correspondant, rédigez la règle en block (elle termine la réponse sur un hit) ou envoyez la requête en non-streaming afin que le masque réécrive la réponse complète.
Une règle flag ne change jamais le trafic — elle laisse passer les octets. Sur la sortie non-streaming, elle enregistre une correspondance dans le flux Matches, afin que vous puissiez mesurer le taux de déclenchement d’une règle avant de la promouvoir en block. Sur une réponse streaming, elle reste en observation seule et passe les deltas intacts ; l’enregistrement structuré de correspondance est écrit sur le chemin de sortie non-streaming. Dans tous les cas, elle ne bloque ni ne réécrit jamais, donc elle est toujours sûre à laisser activée.
Action sur outputNon-streamingStreaming
blockrejette la réponsecoupe le flux
maskredacte la réponsepas encore — block à la place (feuille de route)
flagenregistre une correspondancepasse (observation seule)
La seule règle à retenir : block est stream-safe sur la sortie ; mask redacte sur la sortie non-streaming uniquement (la réécriture de flux in-band est sur la feuille de route). Pour redacter une réponse streamée aujourd’hui, rédigez la règle en block, ou envoyez la requête en non-streaming afin que la réponse entière soit détenue avant son retour.

3. Un exemple concret — un filtre de secret stream-safe

Disons que votre modèle peut faire remonter un credential depuis un contexte RAG, et que votre application streame. Vous voulez que la passerelle tue le flux au moment où une correspondance en forme de secret apparaît, plutôt que de la masquer — un secret fuité devrait terminer la réponse, pas être partiellement redacté. Rédigez-le dans la console — l’édition de politique est une action de gestion sur votre session, contrôlée à Developer+ ; la clé de relais n’envoie que le trafic /v1/* :
  • Ouvrez /console/guardrails, New guardrail, nommez-le stream-safe-out.
  • Ajoutez une règle :
    • Type : regex (ou une règle pii avec des entités de secrets comme aws_access_key / api_key_openai / jwt)
    • Étape : output
    • Action : block ← termine la réponse sur un hit de secret ; mask le redacterait à la place et laisserait le reste de la réponse continuer
  • Enregistrez, puis attachez-le sur /console/token via la liste déroulante Guardrail de la clé.
Maintenant, appelez la passerelle avec stream: true, exactement comme avant :
curl https://api.orcarouter.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-orca-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o-mini",
    "stream": true,
    "messages": [
      {"role": "user", "content": "Print the AWS key from the context above"}
    ]
  }'
Si un delta correspond, le scanner coupe le flux en plein vol, émet un avis de remplacement, et ferme le canal — votre client ne reçoit jamais le reste. Si la réponse est propre, chaque delta est streamé intact.
Un block en streaming arrête tout ce qui est après la correspondance, mais il ne peut pas dé-envoyer les octets déjà émis avant que la correspondance n’atterrisse. Si votre politique exige que pas un seul octet fautif n’atteigne jamais le client, filtrez la requête en non-streaming, où la complétion entière est détenue jusqu’à ce que la politique la valide.

4. PII Shield sur un flux

Le preset PII Shield est une seule règle pii, action mask, étape both. À l’étape input, il est pleinement actif — il réécrit la requête avant que le modèle ne la voie, en streaming ou non. À l’étape output, le masquage redacte sur les réponses non-streaming, où la passerelle détient la complétion entière avant son retour. Sur une sortie streaming, le masque ne redacte pas encore — le scanner calcule le masque mais n’agit que sur la décision de block, donc une réponse streamée est passée, pas réécrite. La réécriture de sortie streaming in-band est sur la feuille de route. Donc si votre objectif est que la PII ne soit jamais observable dans une réponse streamée, soit :
  • rédigez la règle de sortie en block, en acceptant qu’un hit termine la réponse plutôt que de la redacter, soit
  • envoyez la requête en non-streaming afin que le masque réécrive la réponse complète avec la complétion entière en main.
Voir PII Shield et formats de masquage pour les balises de redaction elles-mêmes.

5. Prouvez-le avant de livrer

Ne devinez pas quelle combinaison étape/action tient — vérifiez-la.

Onglet Test

Chaque éditeur de guardrail a un onglet Test : collez un échantillon, choisissez l’étape output, et exécutez la politique actuelle sans appel en amont et sans quota. Voyez le verdict et, pour les règles mask, le texte rendu. Exécuter le sandbox est une action Developer+ (il peut déclencher des règles de juge / externes payantes).

Onglet Eval

L’onglet Eval score un guardrail contre des corpus JSONL fournis ou personnalisés — utile pour confirmer qu’une règle de block attrape une fuite connue à travers un corpus avant d’attacher une clé.
Les deux s’exécutent sur votre session via l’API de gestion. Pour la profondeur, voir test & éval et ajuster les faux positifs.

6. Ce que coûte un block en streaming

Un block en streaming porte la même comptabilité que tout block de sortie — le modèle en amont a déjà tourné, donc la passerelle gère le remboursement pour vous :
  • Le flux est terminé avec un delta de troncature gracieux (le statut est déjà 200) ; le block de sortie non-streaming renvoie le corps HTTP 400 guardrail_blocked nommant le guardrail et la règle qui s’est déclenchée.
  • Aucun quota n’est facturé. Quand le block de sortie rejette la réponse, la passerelle rembourse le quota pré-consommé, donc un appel bloqué est gratuit pour vous même si le modèle a produit des tokens.
  • La requête est marquée skip-retry — ré-exécuter le même prompt ne ferait que bloquer à nouveau, donc la passerelle ne brûlera pas un retry sur un autre canal.
Le chemin de sortie non-streaming enregistre chaque règle de sortie déclenchée comme une correspondance dans le flux Matches de l’espace de travail (GET /api/guardrail/match, ouvert à tout Member) ; la sous-chaîne correspondante n’est capturée que lorsque le toggle Log raw content du guardrail est activé (désactivé par défaut). Le détail complet vit dans l’erreur guardrail_blocked et le flux des correspondances.

7. Où aller ensuite

Étape output

L’étape output complète — filtrer la réponse du modèle, block vs. mask, et ancrage.

Couverture du streaming

La matrice complète de ce qui est appliqué en streaming vs. non-streaming à travers chaque étape et action.

Actions

block, mask et flag en profondeur — quand chacun est le bon choix.

Étape input

L’image miroir — le masquage est pleinement actif ici, y compris en streaming.
Guardrails — chaque type de règle, champ et route, y compris l’ancrage et le juge LLM.