Raisonnement
Le raisonnement constitue l’étape suivante du CoT (Chain of Thought), utilisée pour décrire les étapes logiques générées par le modèle avant d’aboutir à une conclusion. Le raisonnement renforce cette capacité en faisant intervenir des étapes d’apprentissage qui incitent le modèle à développer librement ses chaînes de pensée avant de produire la réponse finale. Cela permet aux modèles d’approfondir l’analyse du problème et d’atteindre une solution plus pertinente, en utilisant du temps de calcul supplémentaire pour générer plus de tokens et ainsi améliorer la réponse : on parle également de Test Time Computation.

Les modèles brillent sur des cas d’usage complexes comme les mathématiques ou le code, mais peuvent aborder des problématiques très variées. Le résultat fourni par un modèle de raisonnement inclut une séquence explicitant la démarche suivie, avant de livrer la réponse finale.
Mistral propose deux approches du raisonnement :
-
Ajustable — Disponible sur
mistral-small-latestetmistral-medium-3-5via le paramètrereasoning_effort. Permet au modèle de doser la profondeur de réflexion. -
Natif — Disponible sur
magistral-small-latestetmagistral-medium-latest. Ces modèles génèrent toujours une trace de raisonnement et sont conçus pour traiter des situations nécessitant un travail d’analyse poussé.
Modèle
mistral-small-latest: Prend en charge le raisonnement ajustable via le paramètrereasoning_effort. Aucune configuration supplémentaire requise : il suffit d’ajouter le paramètre à n’importe quelle requête de Chat completion.mistral-medium-3-5: Prend en charge le raisonnement ajustable via le paramètrereasoning_effort. Pour les cas d’usage agentique et de code, il est recommandé d’utiliserreasoning_effort="high".
Le paramètre reasoning_effort contrôle la façon dont le raisonnement apparaît dans la réponse :
reasoning_effort = "high": La réponse inclut un bloc de réflexion complet avant la réponse finale, au prix d’une consommation de tokens plus importante.reasoning_effort = "none": Le modèle raisonne au minimum et le bloc de réflexion est omis dans la réponse.
reasoning_effort est également proposé sur les endpoints Agents et Conversations de l’API, à l’intérieur du champ completion_args.
Utilisation
Utilisation
Raisonnement avec Chat completion
Raisonnement avec Chat completion
Voici un exemple via notre endpoint chat completions :
import os
from mistralai.client import Mistral
api_key = os.environ["MISTRAL_API_KEY"]
model = "mistral-small-latest"
client = Mistral(api_key=api_key)
chat_response = client.chat.complete(
model = model,
messages = [
{
"role": "user",
"content": "John is one of 4 children. The first sister is 4 years old. Next year, the second sister will be twice as old as the first sister. The third sister is two years older than the second sister. The third sister is half the age of her older brother. How old is John?",
},
],
reasoning_effort="high"
)Gestion des blocs de réflexion
Gestion des blocs de réflexion
Lorsque reasoning_effort est réglé sur "high", la réponse message.content est une liste de blocs et non plus une chaîne simple. Deux types de blocs apparaissent :
ThinkChunk(type: "thinking") : contient la trace du raisonnement du modèle. Le champthinkingest lui-même une liste d’objetsTextChunk.TextChunk(type: "text") : contient la réponse finale.
Quand reasoning_effort est à "none", message.content est une simple chaîne de caractères, sans trace de réflexion.
Analyse de la réponse
Analyse de la réponse
from mistralai.client.models import TextChunk, ThinkChunk
# En supposant que chat_response provient de l’exemple ci-dessus
content = chat_response.choices[0].message.content
# reasoning_effort="none" retourne une chaîne de caractères simple
if isinstance(content, str):
print(content)
else:
for chunk in content:
if isinstance(chunk, ThinkChunk):
print("--- thinking ---")
for inner in chunk.thinking:
if isinstance(inner, TextChunk):
print(inner.text)
print("--- /thinking ---")
elif isinstance(chunk, TextChunk):
print(chunk.text)Flux de données (streaming)
Flux de données (streaming)
En streaming, la forme de delta.content évolue au fil de la réponse :
- Phase de réflexion :
delta.contentest une liste contenant unThinkChunk - Transition : une liste unique contenant à la fois un
ThinkChunkde clôture et le premierTextChunk - Phase de réponse :
delta.contentdevient une chaîne de caractères simple
import os
from mistralai.client import Mistral
from mistralai.client.models import TextChunk, ThinkChunk
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
in_thinking = False
for event in client.chat.stream(
model="mistral-medium-3-5",
messages=[{"role": "user", "content": "What is 17 * 23?"}],
reasoning_effort="high",
):
delta = event.data.choices[0].delta.content
if not delta:
continue
# Après réflexion, delta est une chaîne simple
if isinstance(delta, str):
if in_thinking:
print("\n--- /thinking ---")
in_thinking = False
print(delta, end="", flush=True)
continue
# Pendant la réflexion, delta est une liste de blocs
for chunk in delta:
if isinstance(chunk, ThinkChunk):
if not in_thinking:
print("--- thinking ---")
in_thinking = True
for inner in chunk.thinking:
if isinstance(inner, TextChunk):
print(inner.text, end="", flush=True)
elif isinstance(chunk, TextChunk):
if in_thinking:
print("\n--- /thinking ---")
in_thinking = False
print(chunk.text, end="", flush=True)Conversations multi-tours
Conversations multi-tours
Quand vous construisez des conversations multi-tours avec raisonnement, veillez à toujours réinjecter le message complet de l’assistant (y compris le ThinkChunk) dans l’historique des messages. Supprimer la trace du raisonnement entre les tours dégrade la performance du modèle.
from mistralai.client import Mistral
from mistralai.client.models import TextChunk, ThinkChunk, UserMessage
client = Mistral(api_key="your-api-key", timeout_ms=300_000)
messages = []
for user_text in ["What is 17 * 23?", "Now multiply that by 3."]:
messages.append(UserMessage(content=user_text))
response = client.chat.complete(
model="mistral-medium-3-5",
messages=messages,
reasoning_effort="high",
)
assistant_message = response.choices[0].message
# Affiche uniquement la réponse finale (pour affichage)
content = assistant_message.content
if isinstance(content, str):
print(content)
else:
answer = "".join(
c.text for c in (content or []) if isinstance(c, TextChunk)
)
print(answer)
# IMPORTANT : ajouter le message complet de l’assistant à l’historique.
# Cela préserve ThinkChunk pour que le modèle voie sa propre trace de raisonnement lors des tours suivants.
# Ne reconstruisez PAS le message uniquement avec le texte de la réponse finale.
messages.append(assistant_message)Ne retirez pas le ThinkChunk des messages assistant avant de les réinjecter. Le modèle s’appuie sur la trace du raisonnement pour maintenir la cohérence entre les tours. Retirer ces blocs améliore l’efficacité en tokens mais dégrade fortement la qualité de la sortie.
