Aller au contenu principal
Leçon 7 sur 66 · Claude sur Google Cloud (Vertex AI / Agent Platform)

Le streaming des réponses

Leçon 7 sur 66 Mis à jour le 5 novembre 2026 Développeur
Sur cette page
  1. Le problème d’expérience utilisateur
  2. Comment ça marche : les événements SSE
  3. Implémentation basique avec stream=True
  4. La méthode simplifiée : client.messages.stream()
  5. Récupérer le message complet après streaming
  6. Gérer les événements individuels
  7. Quand utiliser le streaming
  8. Résumé
  9. À vous de jouer
  10. Points clés à retenir

Le problème d’expérience utilisateur

Quand vous envoyez une requête à Claude, le modèle peut mettre entre 10 et 30 secondes à générer sa réponse complète. Sans streaming, votre utilisateur fixe un écran vide pendant tout ce temps, sans savoir si quelque chose se passe.

Le streaming résout ce problème : au lieu d’attendre la réponse entière, vous recevez les tokens au fur et à mesure qu’ils sont générés. L’utilisateur voit le texte apparaître progressivement, exactement comme dans l’interface chat de Claude.

Comment ça marche : les événements SSE

Le streaming ne rend pas la génération plus rapide — le dernier token arrive au même moment dans les deux modes. Ce qu’il change, c’est le premier token : l’utilisateur voit la réponse commencer en une seconde au lieu de fixer un écran vide pendant vingt. À vitesse égale, la perception est radicalement différente, et c’est cette perception qui fait la qualité d’une interface conversationnelle.

Techniquement, le streaming utilise le protocole Server-Sent Events (SSE). Le serveur envoie un flux d’événements structurés, chacun contenant une partie de la réponse.

Voici les types d’événements dans l’ordre où ils arrivent :

ÉvénementDescription
message_startDébut du message, contient les métadonnées (id, modèle, usage)
content_block_startDébut d’un bloc de contenu (texte, outil, etc.)
content_block_deltaFragment du bloc en cours : text_delta pour le texte, thinking_delta et signature_delta pour la réflexion, input_json_delta pour un appel d’outil
content_block_stopFin du bloc de contenu
message_deltaMétadonnées de fin (stop_reason, usage de sortie)
message_stopFin du message

Un message typique produit cette séquence :

Les événements d'un flux Frise à quatre jalons : message_start, blocs de contenu (start, deltas de réflexion ou de texte, stop), message_delta avec stop_reason, message_stop. STREAMING Les événements d'un flux 1 message_start métadonnées, jetons d'entrée 2 Blocs réflexion puis texte : start, deltas, stop 3 message_delta stop_reason, jetons de sortie 4 message_stop fin du message On n'affiche que les text_delta ; text_stream fait ce tri ; get_final_message() rend le message complet.
D'après la leçon « Response streaming » (Claude Academy, Claude on Google Cloud) et la page Streaming messages (documentation Claude).

Sur Sonnet 5.5, qui réfléchit par défaut, un bloc de réflexion passe souvent avant le bloc de texte, avec son texte vide par défaut. Des événements ping peuvent s’intercaler, et une erreur (par exemple overloaded_error en période de forte charge) arrive dans le flux sous forme d’événement error.

Implémentation basique avec stream=True

La façon la plus directe d’activer le streaming est de passer stream=True à messages.create. On reçoit alors un itérateur d’événements, que le cours officiel affiche tels quels pour les découvrir :

from anthropic import AnthropicVertex

client = AnthropicVertex(project_id="votre-projet", region="global")
model = "claude-sonnet-5-5"

stream = client.messages.create(
    model=model,
    max_tokens=4096,
    messages=[{"role": "user", "content": "Décris en une phrase une base de données imaginaire."}],
    stream=True,
)
for event in stream:
    if event.type == "content_block_delta" and event.delta.type == "text_delta":
        print(event.delta.text, end="", flush=True)

Le filtre sur event.delta.type est indispensable avec les modèles actuels : les deltas de réflexion n’ont pas d’attribut text. Le paramètre flush=True force l’affichage immédiat de chaque fragment, sans attendre un saut de ligne.

La méthode simplifiée : client.messages.stream()

Le SDK Python fournit un context manager qui simplifie considérablement le streaming. Plutôt que de gérer chaque événement SSE manuellement, vous utilisez stream.text_stream :

from anthropic import AnthropicVertex

client = AnthropicVertex(project_id="votre-projet", region="global")

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {"role": "user", "content": "Écris un court poème sur la mer."}
    ]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

print()  # Saut de ligne final

stream.text_stream est un itérateur qui vous donne uniquement les fragments de texte, sans vous encombrer avec les événements de structure. C’est le bon niveau d’abstraction pour 90 % des usages : la mécanique SSE de la section précédente reste utile à comprendre — elle explique ce que le SDK fait pour vous — mais vous n’aurez presque jamais à la manipuler directement (start, stop, delta).

Récupérer le message complet après streaming

Parfois, vous avez besoin à la fois du streaming (pour l’affichage) et du message complet (pour le traiter ensuite). La méthode get_final_message() vous donne le message reconstitue après la fin du flux :

from anthropic import AnthropicVertex

client = AnthropicVertex(project_id="votre-projet", region="global")

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {"role": "user", "content": "Donne-moi 3 idées de projets Python pour débutants."}
    ]
) as stream:
    # Affichage en temps réel
    for text in stream.text_stream:
        print(text, end="", flush=True)

    # Récupération du message complet
    message = stream.get_final_message()

print()
print(f"\nTokens d'entrée : {message.usage.input_tokens}")
print(f"Tokens de sortie : {message.usage.output_tokens}")
print(f"Raison d'arrêt : {message.stop_reason}")

Le message retourné est identique à ce que vous auriez obtenu sans streaming : c’est un objet Message complet avec tout le contenu, l’usage de tokens, et les métadonnées.

Gérer les événements individuels

Si vous avez besoin d’un contrôle plus fin (par exemple pour mettre à jour une barre de progression ou détecter le début d’un bloc outil), vous pouvez écouter chaque type d’événement :

from anthropic import AnthropicVertex

client = AnthropicVertex(project_id="votre-projet", region="global")

with client.messages.stream(
    model="claude-sonnet-5-5",
    max_tokens=4096,
    messages=[
        {"role": "user", "content": "Explique la photosynthèse."}
    ]
) as stream:
    for event in stream:
        if event.type == "content_block_start":
            print(f"[Début du bloc {event.content_block.type}]")
        elif event.type == "content_block_delta":
            if event.delta.type == "text_delta":
                print(event.delta.text, end="", flush=True)
        elif event.type == "content_block_stop":
            print("\n[Fin du bloc]")
        elif event.type == "message_stop":
            print("\n[Message terminé]")

Quand utiliser le streaming

  • Applications interactives : chatbots, assistants, interfaces conversationnelles
  • Réponses longues : articles, analyses détaillées, génération de code
  • Feedback utilisateur : montrer que le système travaille

Le streaming n’ajoute aucun coût supplémentaire et ne change pas le contenu de la réponse. La seule vraie contrepartie est architecturale : votre code aval doit accepter de travailler avec une réponse incomplète, ou attendre get_final_message(). C’est pourquoi le réflexe utile est de streamer vers l’affichage et de traiter sur le message final — chaque consommateur reçoit la forme qui lui convient. C’est purement une amélioration de l’expérience utilisateur.

Résumé

ApprocheUsage
client.messages.stream() + text_streamCas général, simple et efficace
Itération sur stream (événements bruts)Contrôle fin sur chaque événement
stream.get_final_message()Récupérer le message complet après streaming

C’est aussi ce que montre le cours officiel : stream=True pour découvrir les événements, puis client.messages.stream() et text_stream pour l’affichage, et get_final_message() pour enregistrer le message complet, par exemple en base de données. La documentation conseille aussi le streaming pour toute requête longue : le SDK refuse une requête non diffusée dont la durée estimée dépasse dix minutes.

À vous de jouer

Voir les événements. Lancez l’exemple stream=True en affichant event.type pour chaque événement : repérez le bloc de réflexion, le bloc de texte, et le message_delta qui porte stop_reason.

Streamer et enregistrer. Écrivez une fonction stream_and_save(messages) qui affiche la réponse au fil de l’eau avec text_stream, puis renvoie get_final_message() ; ajoutez ce message à l’historique d’une conversation.

Sources officielles : Response streaming (Claude Academy) · Streaming messages (documentation Claude : types d’événements et de deltas)

Points clés à retenir

  • Le streaming n’accélère pas la génération, il fait arriver le premier fragment tout de suite.
  • Ordre des événements : message_start, blocs de contenu (start, deltas, stop), message_delta, message_stop ; ping et error peuvent s’intercaler.
  • Avec stream=True, on filtre les text_delta ; client.messages.stream() et text_stream font ce tri.
  • get_final_message() rend le message complet pour l’enregistrer ou le traiter.