Aller au contenu principal

Rôles et messages

Mis à jour le 29 juillet 2026

Le cœur du protocole conversationnel

L’API Chat Completions ne reçoit pas un simple texte brut : elle attend un tableau de messages structurés, chacun associé à un rôle. Ce système de rôles permet au modèle de distinguer qui parle, quel est le contexte, et comment il doit répondre. Un même texte — « Répondez toujours en JSON » — n’aura pas le même poids selon qu’il arrive comme consigne du développeur ou comme phrase tapée par un utilisateur. Maîtriser cette structure est ce qui sépare un chatbot cohérent d’un système qui dérive au bout de trois échanges.

Les quatre rôles

L’API Mistral reconnaît quatre rôles distincts, et chacun a une fonction précise dans la conversation.

Le rôle system

Le message système définit le comportement global du modèle. Placé en première position, il est lu avant tout échange : c’est là que vous fixez le ton, les contraintes et le contexte de votre application. Imaginez un assistant destiné à un cabinet d’avocats ; le message système est l’équivalent de la note de cadrage que vous remettriez à un nouveau collaborateur avant son premier dossier.

messages = [
    {
        "role": "system",
        "content": "Vous êtes un assistant juridique spécialisé en droit français. "
                   "Répondez de manière précise et citez les articles de loi pertinents. "
                   "Si vous n'êtes pas sûr, dites-le explicitement."
    }
]

Ce message est géré par le développeur, jamais par l’utilisateur final, et il n’apparaît nulle part dans l’interface de votre application.

Le rôle user

Vient ensuite le message de l’utilisateur humain : la question, l’instruction ou le texte à traiter. C’est la seule partie de la conversation que vos utilisateurs contrôlent directement.

messages.append({
    "role": "user",
    "content": "Quels sont les délais de prescription en matière civile ?"
})

Le rôle assistant

Ce rôle porte les réponses précédentes du modèle. Il devient indispensable dès que la conversation dépasse un tour : sans lui, l’utilisateur qui demande « et pour une créance commerciale ? » obtiendrait une réponse hors sujet, faute de savoir de quoi on parlait.

messages.append({
    "role": "assistant",
    "content": "En droit civil français, le délai de prescription de droit commun est de 5 ans..."
})

Le rôle tool

Le dernier rôle intervient dans le cadre du function calling. Quand le modèle demande l’exécution d’une fonction externe — interroger une API météo, par exemple — vous exécutez cette fonction de votre côté et vous lui rendez le résultat sous ce rôle, en rappelant l’identifiant de l’appel concerné :

messages.append({
    "role": "tool",
    "content": '{"temperature": 22, "ville": "Paris"}',
    "tool_call_id": "call_abc123"
})

Structure complète d’un échange multi-tours

Voyons ces rôles à l’œuvre dans une conversation réelle, où l’utilisateur affine sa demande après une première réponse :

from mistralai import Mistral
import os

client = Mistral(api_key=os.getenv("MISTRAL_API_KEY"))

conversation = [
    {
        "role": "system",
        "content": "Vous êtes un chef cuisinier français. Proposez des recettes simples et savoureuses."
    },
    {
        "role": "user",
        "content": "Je veux préparer un dessert avec des pommes."
    }
]

# Premier tour
response = client.chat.complete(
    model="mistral-large-latest",
    messages=conversation
)

assistant_reply = response.choices[0].message.content
print(assistant_reply)

# Ajouter la réponse à l'historique
conversation.append({"role": "assistant", "content": assistant_reply})

# Deuxième tour
conversation.append({
    "role": "user",
    "content": "Peux-tu adapter cette recette pour 8 personnes ?"
})

response = client.chat.complete(
    model="mistral-large-latest",
    messages=conversation
)

print(response.choices[0].message.content)

Observez ce que fait réellement ce code : à chaque tour, il renvoie tout l’historique. Le modèle n’a aucune mémoire persistante entre deux requêtes ; « cette recette » n’a de sens que parce que la réponse précédente est encore dans le tableau. La gestion de l’état de la conversation vous appartient entièrement.

Le contenu structuré

Le champ content accepte deux formes. La plus courante est une simple chaîne de caractères. Mais dès que vous transmettez autre chose que du texte — une image à décrire, par exemple — vous passez à une liste de blocs typés :

# Contenu simple (texte)
{"role": "user", "content": "Décrivez cette image."}

# Contenu structuré (multimodal)
{"role": "user", "content": [
    {"type": "text", "text": "Décrivez cette image."},
    {"type": "image_url", "image_url": {"url": "https://exemple.com/image.jpg"}}
]}

Le prefix flag

Mistral propose une fonctionnalité qui lui est propre : le prefix flag. Vous écrivez vous-même le début de la réponse de l’assistant, et le modèle est contraint de continuer à partir de là. C’est redoutablement efficace quand vous devez parser la sortie sans marge d’erreur.

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {"role": "system", "content": "Vous répondez toujours en JSON."},
        {"role": "user", "content": "Liste 3 capitales européennes."},
        {"role": "assistant", "content": '{"capitales": [', "prefix": True}
    ]
)

Le modèle reprend la génération après {"capitales": [, ce qui élimine d’emblée le risque de voir apparaître un « Bien sûr, voici votre JSON : » avant l’accolade. En production, cette garantie de format vaut souvent mieux qu’une consigne répétée trois fois dans le message système.

Deux réflexes valent d’être adoptés tout de suite. Gardez le message système concis : un paragraphe bien rédigé produit de meilleurs résultats que deux pages de règles, dont le modèle finit par ignorer une partie. Et n’inventez jamais de fausses réponses assistant pour orienter le modèle, à une exception près — le few-shot learning, que nous verrons à la leçon 10. Sur les conversations longues, renvoyez l’historique complet, mais surveillez la fenêtre de contexte et élaguez les tours les plus anciens avant de la dépasser.

Points clés à retenir

  • Quatre rôles : system (comportement), user (requête), assistant (réponse), tool (résultat de fonction)
  • Le message système se place en premier et définit le cadre de l’application
  • Le modèle n’a pas de mémoire : renvoyez l’historique complet à chaque requête
  • Le prefix flag force le début de la réponse pour contrôler le format de sortie