Implémenter les Predicted Outputs en Python
Mis à jour le 29 juillet 2026
Du concept au code de production
Vous comprenez le principe des Predicted Outputs et leurs cas d’usage. Cette leçon vous donne le code Python complet, prêt à intégrer dans vos applications, avec gestion d’erreurs et mesure de performance.
Implémentation de base
Le pattern minimal tient en un paramètre : prediction, auquel vous passez le contenu attendu. Tout le reste de l’appel est inchangé — même modèle, mêmes messages, même traitement de la réponse. C’est ce qui rend la fonctionnalité facile à adopter, et tout aussi facile à retirer si la mesure ne confirme pas le gain :
from mistralai import Mistral
client = Mistral(api_key="votre-clé-api")
code_source = """
import pandas as pd
def load_data(filepath):
df = pd.read_csv(filepath)
df['date'] = pd.to_datetime(df['date'])
df = df.dropna(subset=['value'])
return df
def compute_stats(df):
return {
'mean': df['value'].mean(),
'median': df['value'].median(),
'std': df['value'].std()
}
"""
prompt = (
"Ajoutez un paramètre 'separator' à la fonction load_data "
"(défaut ',') et utilisez-le dans read_csv. "
"Répondez uniquement avec le code complet modifié."
)
response = client.chat.complete(
model="codestral-latest",
messages=[
{"role": "user", "content": prompt},
{"role": "user", "content": code_source}
],
prediction={"type": "content", "content": code_source}
)
code_modifie = response.choices[0].message.content
print(code_modifie)
Classe utilitaire pour la production
L’encapsulation a ici un intérêt qui dépasse la propreté du code : elle centralise la décision d’activer ou non la prédiction. C’est précisément le genre de réglage qu’on veut pouvoir couper d’un coup — si un déploiement révèle des prédictions systématiquement fausses, vous désactivez en un point au lieu de chasser le paramètre dans toute la base de code :
from mistralai import Mistral
import time
from dataclasses import dataclass
@dataclass
class PredictionResult:
content: str
latency_ms: float
tokens_input: int
tokens_output: int
model: str
class PredictedEditor:
"""Éditeur de contenu utilisant les Predicted Outputs."""
def __init__(self, api_key: str, model: str = "mistral-large-latest"):
self.client = Mistral(api_key=api_key)
self.model = model
def edit(
self,
original: str,
instruction: str,
system_prompt: str | None = None
) -> PredictionResult:
"""Édite un contenu avec prédiction de sortie."""
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.extend([
{"role": "user", "content": instruction},
{"role": "user", "content": original}
])
start = time.perf_counter()
response = self.client.chat.complete(
model=self.model,
messages=messages,
prediction={"type": "content", "content": original}
)
latency = (time.perf_counter() - start) * 1000
choice = response.choices[0]
return PredictionResult(
content=choice.message.content,
latency_ms=round(latency, 1),
tokens_input=response.usage.prompt_tokens,
tokens_output=response.usage.completion_tokens,
model=self.model
)
def edit_code(self, code: str, instruction: str) -> PredictionResult:
"""Raccourci pour l'édition de code."""
return self.edit(
original=code,
instruction=instruction,
system_prompt=(
"Vous êtes un assistant de programmation. "
"Répondez uniquement avec le code modifié, "
"sans explication ni markdown."
)
)
def edit_text(self, text: str, instruction: str) -> PredictionResult:
"""Raccourci pour l'édition de texte."""
return self.edit(
original=text,
instruction=instruction,
system_prompt=(
"Vous êtes un éditeur de texte professionnel. "
"Appliquez la modification demandée en préservant "
"le style et la structure du texte original. "
"Répondez uniquement avec le texte modifié."
)
)
Utilisation de la classe
editor = PredictedEditor(api_key="votre-clé-api", model="codestral-latest")
# Éditer du code
result = editor.edit_code(
code=mon_fichier_python,
instruction="Remplacez tous les print() par des appels logging.info()"
)
print(f"Latence : {result.latency_ms} ms")
print(f"Tokens : {result.tokens_input} in / {result.tokens_output} out")
print(result.content)
Benchmark : avec vs sans prédiction
Ne sautez pas cette étape : le gain des Predicted Outputs dépend entièrement de la justesse de vos prédictions, qui dépend de vos données — aucun chiffre lu dans une documentation ne remplace la mesure sur vos propres cas. Le script compare les deux modes sur les mêmes entrées, et sa sortie vous donne la réponse en secondes :
import statistics
def benchmark_prediction(
client, model, messages, prediction_content, runs=5
):
"""Compare la latence avec et sans Predicted Output."""
times_normal = []
times_predicted = []
for _ in range(runs):
# Sans prédiction
start = time.perf_counter()
client.chat.complete(model=model, messages=messages)
times_normal.append((time.perf_counter() - start) * 1000)
# Avec prédiction
start = time.perf_counter()
client.chat.complete(
model=model,
messages=messages,
prediction={"type": "content", "content": prediction_content}
)
times_predicted.append((time.perf_counter() - start) * 1000)
avg_normal = statistics.mean(times_normal)
avg_predicted = statistics.mean(times_predicted)
gain_pct = (1 - avg_predicted / avg_normal) * 100
return {
"sans_prediction_ms": round(avg_normal, 1),
"avec_prediction_ms": round(avg_predicted, 1),
"gain_pourcentage": round(gain_pct, 1),
"runs": runs
}
Gestion des erreurs
La gestion d’erreurs est simple ici, pour une raison structurelle : une prédiction fausse n’est pas une erreur. Le modèle l’ignore et génère normalement — vous perdez le gain de latence, jamais la qualité. Les vrais cas limites sont ailleurs :
def safe_edit(editor, original, instruction):
"""Édition avec gestion d'erreurs robuste."""
try:
result = editor.edit(original, instruction)
# Vérifier que la réponse n'est pas vide
if not result.content or len(result.content.strip()) < 10:
raise ValueError("Réponse trop courte ou vide")
return result
except Exception as e:
# Fallback : réessayer sans prédiction
print(f"Predicted Output échoué ({e}), fallback standard...")
response = editor.client.chat.complete(
model=editor.model,
messages=[
{"role": "user", "content": instruction},
{"role": "user", "content": original}
]
)
return PredictionResult(
content=response.choices[0].message.content,
latency_ms=0,
tokens_input=response.usage.prompt_tokens,
tokens_output=response.usage.completion_tokens,
model=editor.model
)
Contraintes à connaître
Avant de déployer, trois points méritent d’être intégrés à votre revue de code. D’abord, le paramètre n (générations multiples) est incompatible avec prediction : si votre pipeline demande plusieurs complétions, il faudra choisir. Ensuite, la correspondance entre prédiction et sortie est gérée par le modèle quelle que soit la position du contenu dans la réponse — vous n’avez pas d’alignement à préparer. Enfin, et c’est ce qui rend la fonctionnalité sûre à déployer : une mauvaise prédiction ne dégrade jamais la qualité de la réponse, elle fait seulement perdre le gain de latence. Le pire scénario est donc simplement un retour à la vitesse normale, sur les deux modèles compatibles (mistral-large-latest et codestral-latest).
Points clés à retenir
- Le paramètre
predictions’ajoute simplement à l’appelchat.complete() - Encapsulez la logique dans une classe réutilisable pour la production
- Mesurez systématiquement le gain avec un benchmark avant de déployer
- Prévoyez un fallback sans prédiction en cas d’erreur
- Une mauvaise prédiction ne dégrade pas la qualité, seulement la latence