Assistant Message
L’assistant message est le message généré par le LLM en réponse à un user prompt, identifié par "role": "assistant" dans les API de chat. Il représente la « voix » du modèle dans la conversation et constitue l’unité de sortie de chaque tour de génération.
- Catégorie
- Architecture de conversation / Prompt Engineering
- Rôle dans l’API
"role": "assistant"dans les Messages API (OpenAI, Anthropic, Google)- Contenu
- Texte généré, appels d’outils (function calling), blocs de raisonnement (extended thinking), ou combinaisons de ces éléments
- Statut
- Généré par le modèle, mais peut aussi être injecté manuellement par le développeur (prefilling, messages synthétiques)
- Contrainte Anthropic
- Doit alterner avec les messages user. Ne peut pas être le premier message de la conversation.
- Verdict
- Bien plus qu’une simple réponse textuelle. Le prefilling et les messages synthétiques en font un outil de contrôle puissant.
Rôle de l’assistant message dans la conversation
Dans l’architecture conversationnelle des LLM, chaque échange se structure autour de trois rôles : system (les instructions du développeur), user (les messages de l’utilisateur), et assistant (les réponses du modèle). L’assistant message est la sortie du modèle : c’est le texte (ou les actions) que le LLM produit en réponse à un user prompt.
Quand le modèle reçoit une requête API, il traite l’ensemble du contexte (system prompt + historique des messages) et génère un nouvel assistant message. Ce message est retourné dans la réponse API et peut ensuite être ajouté à l’historique de conversation pour les tours suivants.
// Réponse API Anthropic
{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Voici la configuration Nginx recommandée..."
}
],
"model": "claude-opus-4-6",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 342,
"output_tokens": 187
}
}
Types de contenu dans un assistant message
L’assistant message ne se limite pas à du texte brut. Les LLM modernes peuvent produire plusieurs types de contenu dans une même réponse :
| Type de contenu | Description | Exemple d’usage |
|---|---|---|
| Texte | Réponse en langage naturel | Réponse à une question, rédaction, explication |
| Tool use / Function call | Appel structuré à un outil externe défini dans le system prompt | Appel à get_weather(location="Paris") |
| Thinking / Raisonnement | Blocs de raisonnement interne (extended thinking chez Anthropic) | Chaîne de pensée visible avant la réponse finale |
| Citations | Références aux passages sources utilisés (natif chez Anthropic) | Attribution des affirmations aux documents fournis |
Chez Anthropic, le champ content de l’assistant message est un tableau d’objets typés. Un seul assistant message peut contenir un bloc thinking (raisonnement interne), suivi d’un bloc text (réponse visible), suivi d’un bloc tool_use (appel d’outil). Cette structure permet au modèle de combiner raisonnement, réponse et action dans un seul tour.
// Assistant message avec tool use (Anthropic)
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "Je vais vérifier la météo à Paris pour vous."
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "get_weather",
"input": {"location": "Paris, France"}
}
]
}
Stop reason : pourquoi le modèle s’arrête
Chaque assistant message est accompagné d’un stop_reason qui indique pourquoi le modèle a cessé de générer. Comprendre ces valeurs est essentiel pour le traitement programmatique des réponses :
| Stop reason | Signification | Action recommandée |
|---|---|---|
end_turn | Le modèle a terminé sa réponse naturellement | Réponse complète, pas d’action requise |
max_tokens | Le modèle a atteint la limite de tokens de sortie | Réponse potentiellement tronquée. Augmentez max_tokens ou demandez au modèle de continuer |
stop_sequence | Le modèle a généré une séquence d’arrêt définie par le développeur | Arrêt intentionnel. Traitez la réponse jusqu’à la séquence d’arrêt |
tool_use | Le modèle demande l’exécution d’un outil | Exécutez l’outil, renvoyez le résultat dans un message tool_result |
pause_turn | Limite d’itérations atteinte (server tools Anthropic) | Le modèle a effectué le maximum d’appels autorisés dans la boucle |
max_tokens
Si votre application ne vérifie pas le stop_reason, vous risquez de traiter des réponses tronquées comme si elles étaient complètes. C’est une source fréquente de bugs en production, notamment quand le modèle génère du JSON tronqué qui n’est pas parsable. Vérifiez systématiquement que stop_reason est end_turn avant de traiter la réponse.
Technique avancée : le prefilling
Le prefilling (ou pré-remplissage) est une technique puissante qui consiste à injecter un assistant message partiel dans l’historique avant de lancer la génération. Le modèle continue alors à partir de ce début de réponse, comme s’il l’avait lui-même commencé.
Forcer un format de sortie
C’est l’usage le plus courant du prefilling. Pour garantir que le modèle réponde en JSON, commencez l’assistant message par { :
{
"model": "claude-opus-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Analyse le sentiment de cette phrase : 'Ce produit est excellent'. Réponds en JSON avec les champs sentiment et score."
},
{
"role": "assistant",
"content": "{"
}
]
}
Le modèle va compléter à partir de {, produisant naturellement un objet JSON valide. Cette technique est plus fiable que de simplement demander du JSON dans l’instruction, car elle contraint physiquement le début de la sortie.
Contraindre un choix
Le prefilling permet aussi de limiter les réponses possibles. Exemple pour un QCM :
{
"messages": [
{
"role": "user",
"content": "Quel est le nom latin de la fourmi ? (A) Apoidea (B) Rhopalocera (C) Formicidae"
},
{
"role": "assistant",
"content": "La réponse est ("
}
]
}
En combinant le prefilling avec max_tokens: 1, vous obtenez une classification en un seul token (A, B ou C), idéale pour les pipelines de traitement automatisé.
Maintenir un persona
Dans une conversation longue, le modèle peut « oublier » son persona. En injectant un assistant message synthétique qui rappelle le rôle, vous renforcez la cohérence. Exemple : commencer chaque tour par un assistant message partiel « En tant qu’expert juridique, » avant de laisser le modèle compléter.
thinking: {type: "enabled"}, vous ne pouvez pas pré-remplir l’assistant message. Choisissez l’un ou l’autre selon votre cas d’usage.
Messages assistant synthétiques
La documentation Anthropic le précise explicitement : les messages assistant dans l’historique n’ont pas besoin d’avoir été réellement générés par Claude. Vous pouvez construire un historique entièrement synthétique pour guider le comportement du modèle. C’est particulièrement utile pour :
Le few-shot conversationnel : simulez des échanges passés entre un utilisateur fictif et l’assistant pour montrer le style de réponse attendu, sans avoir réellement eu ces conversations. Le modèle traitera ces exemples comme du contexte et s’en inspirera.
Le bootstrapping de conversation : commencez une conversation avec un historique pré-construit qui établit le contexte (« L’utilisateur a déjà fourni ses préférences, voici le résumé »), permettant au modèle de démarrer avec un contexte riche sans que l’utilisateur ait réellement à fournir toutes ces informations.
La correction de trajectoire : si le modèle a dévié dans une réponse précédente, vous pouvez remplacer cette réponse dans l’historique par une version corrigée avant d’envoyer le prochain tour, remettant la conversation sur les rails.
Streaming des assistant messages
Les API modernes supportent le streaming : au lieu d’attendre la génération complète de l’assistant message, vous recevez les tokens au fur et à mesure qu’ils sont produits. C’est essentiel pour l’expérience utilisateur dans les interfaces chat, où attendre 10 à 30 secondes pour une réponse complète serait inacceptable.
En streaming, la réponse arrive sous forme d’événements SSE (Server-Sent Events) chez Anthropic ou de chunks chez OpenAI. Chaque événement contient un ou plusieurs tokens. Le développeur doit accumuler ces tokens pour reconstruire le message complet et gérer correctement les événements de fin (message_stop chez Anthropic, [DONE] chez OpenAI).
Le streaming introduit une complexité supplémentaire avec le function calling : un assistant message en streaming peut commencer par du texte, puis bifurquer vers un appel d’outil. Votre code doit gérer cette transition en temps réel, en surveillant les événements content_block_start pour détecter le type de chaque bloc.
Chez Anthropic, les événements de streaming suivent une séquence structurée : message_start (métadonnées), puis content_block_start (début d’un bloc), content_block_delta (tokens incrémentaux), content_block_stop (fin du bloc), et enfin message_delta (informations de fin comme le stop_reason) et message_stop. Gérer correctement cette séquence est indispensable pour les applications de production.
Assistant message et boucle tool use
Quand le modèle décide d’utiliser un outil, l’assistant message contient un bloc tool_use au lieu de (ou en plus de) du texte. Cela déclenche un cycle spécifique :
Premièrement, le modèle génère un assistant message avec un bloc tool_use contenant le nom de l’outil et les paramètres d’entrée. Deuxièmement, le développeur exécute l’outil côté serveur et obtient un résultat. Troisièmement, ce résultat est renvoyé au modèle dans un message user contenant un bloc tool_result. Quatrièmement, le modèle génère un nouvel assistant message qui intègre le résultat de l’outil dans sa réponse finale.
Ce cycle peut se répéter plusieurs fois si le modèle a besoin de plusieurs outils pour répondre à la question. Chaque itération produit un nouvel assistant message. L’ensemble de ces messages (assistant avec tool_use, user avec tool_result, assistant avec réponse) doit être conservé dans l’historique pour que le modèle comprenne la séquence des événements.
Flux tool use complet :
1. User: "Quelle météo à Paris demain ?"
2. Assistant: [text: "Je vérifie..."] + [tool_use: get_weather(Paris)]
3. User: [tool_result: {"temp": 18, "condition": "ensoleillé"}]
4. Assistant: [text: "Il fera 18°C et ensoleillé à Paris demain."]
Chez Anthropic, les « server tools » (comme la recherche web) sont exécutés automatiquement côté serveur dans une boucle interne, sans que le développeur ait à gérer le cycle manuellement. La boucle a une limite par défaut de 10 itérations.
Assistant message et extended thinking
L’extended thinking (raisonnement étendu) d’Anthropic ajoute un bloc thinking dans l’assistant message, avant le bloc text de la réponse finale. Ce bloc contient la chaîne de raisonnement interne du modèle, visible par le développeur mais généralement masquée à l’utilisateur final.
L’assistant message en mode extended thinking contient typiquement un bloc thinking (le raisonnement interne, parfois plusieurs milliers de tokens), suivi d’un bloc text (la réponse finale, plus concise). Les tokens de thinking sont facturés comme des tokens de sortie, ce qui peut significativement augmenter le coût par requête sur les tâches complexes.
En mode « adaptive thinking » (recommandé pour Claude Opus 4.6), le modèle décide automatiquement s’il a besoin de raisonner et combien de tokens y consacrer. Pour les questions simples, il peut sauter le thinking entièrement. Pour les problèmes complexes (mathématiques, code, raisonnement multi-étapes), il peut consacrer plusieurs milliers de tokens au raisonnement avant de produire sa réponse.
Coût des tokens de sortie
Les assistant messages consomment des tokens de sortie (output tokens), qui sont généralement plus chers que les tokens d’entrée. Sur Claude Opus 4.6, les tokens de sortie coûtent $25/M, soit 5× le prix des tokens d’entrée ($5/M). Sur GPT-5.4, le ratio est de $15/M en sortie vs $2,50/M en entrée, soit 6× le prix. Ce différentiel s’explique par le fait que la génération séquentielle de tokens (décodage auto-régressif) est plus coûteuse en calcul que le traitement parallèle des tokens d’entrée (pre-filling).
Implication pratique : contrôler la longueur des assistant messages a un impact direct sur vos coûts. Utilisez le paramètre max_tokens pour limiter la sortie, et formulez vos instructions pour encourager la concision quand c’est approprié. Un assistant message de 1 000 tokens sur Claude Opus 4.6 coûte $0,025, ce qui peut s’additionner rapidement à fort volume.
Place dans l’architecture conversationnelle
| Composant | Rôle | Auteur | Variabilité |
|---|---|---|---|
| System Prompt | Définit le comportement global | Développeur | Constant entre les requêtes |
| User Prompt | Formule une requête | Utilisateur | Change à chaque message |
| Assistant Message | Réponse du modèle | LLM (ou développeur via prefilling) | Généré à chaque tour |
| Conversation History | Contexte des échanges précédents | Accumulation automatique | Croît au fil de la conversation |
Bonnes pratiques pour les assistant messages en production
La gestion des assistant messages en production exige une attention particulière à plusieurs points. Le premier est la validation systématique du stop_reason. Ne traitez jamais un assistant message comme complet sans vérifier que stop_reason est end_turn. Une réponse tronquée par max_tokens peut contenir du JSON invalide, une instruction incomplète, ou une information coupée en milieu de phrase.
Le deuxième est la gestion de l’historique. À chaque tour, ajoutez l’assistant message reçu à votre tableau messages avant d’envoyer le prochain user message. Si vous oubliez cette étape, le modèle perd le contexte de ses propres réponses précédentes. Pour les conversations longues, surveillez la taille totale de l’historique et implémentez une stratégie de troncation ou de résumé quand vous approchez de la limite de la fenêtre de contexte.
Le troisième est le traitement des erreurs. L’API peut retourner des erreurs (rate limit, contexte trop long, erreur serveur) au lieu d’un assistant message. Votre code doit les gérer gracieusement, avec des mécanismes de retry (avec backoff exponentiel) et des messages de fallback pour l’utilisateur.
Le quatrième est la journalisation. Enregistrez les assistant messages (y compris les tool_use et les stop_reason) pour le débogage, l’évaluation qualité et la détection d’anomalies. En production, les logs d’assistant messages sont votre principal outil de diagnostic quand la qualité des réponses se dégrade.
Verdict
L’assistant message est bien plus qu’une simple « réponse du chatbot ». C’est une unité structurée qui peut contenir du texte, des appels d’outils, du raisonnement interne et des citations. Maîtriser le prefilling et les messages synthétiques vous donne un contrôle fin sur le comportement du modèle, souvent plus efficace que des instructions verbales complexes dans le system prompt. Et n’oubliez pas : les tokens de sortie coûtent 5 à 6 fois plus cher que les tokens d’entrée, ce qui fait de la longueur des assistant messages un levier économique majeur en production.
FAQ
Qu’est-ce qu’un assistant message dans un LLM ?
C’est le message généré par le modèle de langage en réponse à un user prompt, identifié par "role": "assistant" dans les API de chat. Il peut contenir du texte, des appels d’outils (function calling), des blocs de raisonnement (extended thinking), ou des citations. C’est la « voix » du modèle dans la conversation.
Qu’est-ce que le prefilling d’un assistant message ?
Le prefilling consiste à injecter un début d’assistant message dans l’historique avant de lancer la génération. Le modèle continue à partir de ce début. C’est utilisé pour forcer un format de sortie (commencer par { pour du JSON), contraindre un choix (« La réponse est ( »), ou maintenir un persona. Chez Anthropic, le prefilling n’est pas compatible avec l’extended thinking.
Quelle est la différence entre stop_reason end_turn et max_tokens ?
end_turn signifie que le modèle a terminé sa réponse naturellement. max_tokens signifie que la réponse a été tronquée par la limite de tokens de sortie. Vérifiez toujours le stop_reason en production : une réponse tronquée peut contenir du JSON invalide ou une réponse incomplète. Si vous obtenez fréquemment max_tokens, augmentez la valeur du paramètre max_tokens.
Pourquoi les tokens de sortie sont-ils plus chers que les tokens d’entrée ?
La génération de tokens (décodage auto-régressif) est séquentielle : chaque token est produit un par un, ce qui est plus coûteux en calcul GPU que le traitement parallèle des tokens d’entrée. Sur Claude Opus 4.6, la sortie coûte $25/M tokens vs $5/M en entrée (ratio 5×). Sur GPT-5.4, c’est $15/M vs $2,50/M (ratio 6×). Contrôler la longueur des réponses est donc un levier économique important.
Peut-on injecter de faux assistant messages dans l’historique ?
Oui. Les API sont stateless : elles ne vérifient pas si les assistant messages de l’historique ont réellement été générés par le modèle. Vous pouvez construire des historiques entièrement synthétiques pour le few-shot conversationnel, le bootstrapping de contexte, ou la correction de trajectoire. Cette technique est officiellement documentée par Anthropic et OpenAI.