Guide pratique pour les réponses en texte brut et JSON
Leçons tirées de la construction d'une simulation Jeopardy IA à 12 joueurs alimentée par Ministral-3-14B-Instruct-2512.
Exécution Ministral-3 sur vLLM est étonnamment puissant. Le modèle est rapide, créatif et capable de produire des réponses de haute qualité même sous de lourdes charges de travail.
Mais une fois que vous passez de simples invites de chat à sorties structurées, automatisation ou utilisation programmatiqueles choses se compliquent rapidement.
Au cours du développement d'un Jeu Jeopardy piloté par l'IA avec 12 joueurs simultanés et des centaines d'appels de modèles, nous avons rencontré plusieurs problèmes pratiques :
Ce guide résume leçons pratiques tirées de la résolution de ces problèmes, ainsi que des modèles concrets que vous pouvez réutiliser dans vos propres projets.
Notre projet de référence simule un jeu complet de Jeopardy où :
Une seule partie peut facilement dépasser 800 appels d'API.
Cet environnement a révélé des cas limites qui apparaissent rarement dans des démonstrations simples, ce qui en fait un excellent banc d'essai pour comprendre comment Ministral se comporte dans des conditions de production réelles.
Modèles Ministral ne pas utiliser la configuration standard du tokenizer HuggingFace.
Cela signifie que la commande de lancement doit explicitement activer le Format de tokenizer Mistral.
vllm serve mistralai/Ministral-3-14B-Instruct-2512 \
--tokenizer_mode mistral \
--config_format mistral \
--load_format mistral
Si votre application en dépend appel de fonction, ajoutez les options supplémentaires :
--enable-auto-tool-choice
--tool-call-parser mistral
Contrairement à certains autres modèles, Ministral ne prend pas en charge chat_template_kwargs.
Si vous envoyez une requête comme celle-ci :
{
"chat_template_kwargs": {
"enable_thinking": false
}
}
vLLM renvoie :
HTTP 400: chat_template is not supported for Mistral tokenizers
Cela signifie que des fonctionnalités telles que basculement explicite du "mode de réflexion" (utilisés avec des modèles tels que Qwen ou DeepSeek) sont tout simplement non disponible.
Heureusement, ce n'est que rarement nécessaire car Ministral produit déjà des sorties concises par défaut.
Le documentation officielle vLLM utilise systématiquement la valeur suivante avec Ministral-3 :
temperature = 0.15
Au premier abord, cela semble extrêmement bas. Cependant, il s'avère que ce n'est pas le cas. essentiel pour les tâches structurées.
En utilisant la valeur par défaut de type OpenAI :
temperature: 0.7
le modèle devient trop créatif avec la structure.
Une simple requête comme :
{ "expertise": "2-3 topics they know best" }
peut renvoyer quelque chose comme :
{
"expertise": [
{
"category": "Gourmet Pizza Alchemy",
"detail": "Can transform random ingredients into Michelin-star pizza"
},
{
"category": "Sumo Wrestling Physics",
"detail": "Understands body mechanics and center-of-gravity combat"
}
]
}
Bien que techniquement valide JSON, ce n'est pas le cas. ce n'est pas ce que le schéma demandait.
Le résultat :
max_tokens les limites sont dépassées0.15 fonctionne mieuxÀ basse température, le modèle devient discipliné structurellement.
temperature: 0.15
Avantages :
Même la génération de texte créatif reste performante — le modèle cesse simplement d'improviser avec la structure.
Recommandation :
Utiliser temperature: 0.15 par défaut pour Ministral-3.
La production JSON lisible par une machine provenant des LLM est plus difficile qu'il n'y paraît.
Ministral a tendance à interpréter les champs de schéma sémantiquement plutôt que structurellement, ce qui conduit à une sortie profondément imbriquée.
Une invite comme :
Return JSON with these fields.
produit souvent des structures verbeuses.
Exemple de requête :
{ "expertise": "2-3 topics they know best" }
Réponse typique :
{
"expertise": [
{
"category": "Ancient Roman Engineering",
"detail": "Knows aqueduct systems in surprising detail"
},
{
"category": "Pizza Dough Chemistry",
"detail": "Obsessed with yeast fermentation dynamics"
}
]
}
Cela consomme trois fois le nombre de jetons attendus.
La solution la plus fiable combine deux instructions.
Respond with ONLY valid JSON.
No markdown, no explanation, no text before or after the JSON.
Keep values as short plain strings — never use nested objects or arrays.
Juste à côté de la définition du schéma :
Every value MUST be a short plain string — NO arrays, NO nested objects.
Combiné à température 0.15ce qui produit JSON plat et prévisible.
Même lorsqu'il est limité, Ministral a tendance à produire des valeurs plus longues que les autres modèles.
Exemple d'observation de notre référence :
| Modèle | Jetons nécessaires |
|---|---|
| GPT-4o | ~512 |
| Qwen | ~512 |
| Ministral-3 | ~1024 |
Une règle de sécurité :
Prévoir 1,5 à 2 fois le nombre de jetons pour les sorties JSON.
Même avec des invites parfaites, les modèles génèrent occasionnellement du JSON malformé.
Une bonne stratégie consiste à ajouter couches d'analyse défensives.
function extractJSON(raw, shape) {
var text = raw.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '').trim();
if (shape === 'array') {
var m = text.match(/\[[\s\S]*\]/);
if (m) text = m[0];
} else {
var m = text.match(/\{[\s\S]*\}/);
if (m) text = m[0];
}
return text;
}
Suivre les crochets ouverts et les fermer automatiquement :
var stack = [];
var inStr = false, esc = false;
for (var i = 0; i < text.length; i++) {
var ch = text[i];
if (esc) { esc = false; continue; }
if (ch === '\\') { esc = true; continue; }
if (ch === '"') { inStr = !inStr; continue; }
if (inStr) continue;
if (ch === '{') stack.push('}');
else if (ch === '[') stack.push(']');
else if (ch === '}' || ch === ']') stack.pop();
}
text = text.replace(/,\s*$/, '');
while (stack.length > 0)
text += stack.pop();
Si le modèle renvoie encore des structures imbriquées :
if (Array.isArray(value)) {
flat = value.map(function(item) {
if (typeof item === 'string') return item;
if (typeof item === 'object') return Object.values(item).join(' — ');
return String(item);
}).join(', ');
}
Une simple boucle de nouvelles tentatives augmente considérablement la fiabilité.
Parce que Ministral se comporte de manière cohérente à basse températureles nouvelles tentatives réussissent généralement.
Recommandé :
2–3 retry attempts
Ministral adore le formatage.
Même lorsque vous demandez du texte brut, il a tendance à produire :
Cela se produit parce que le modèle est livré avec un système intégré. invite de système encourageant le formatage Markdown riche.
De nombreux pipelines s'appuient sur des vérifications de chaînes de caractères simples.
Exemple :
verdict.toUpperCase().startsWith('CORRECT')
Mais si le modèle renvoie :
**CORRECT**
la vérification échoue.
L'approche la plus sûre consiste à normaliser toutes les sorties avant traitement.
function stripMarkdown(text) {
if (!text) return text;
var s = text.replace(/\*\*([^*]+)\*\*/g, '$1');
s = s.replace(/__([^_]+)__/g, '$1');
s = s.replace(/\*([^*]+)\*/g, '$1');
s = s.replace(/^#{1,6}\s+/gm, '');
s = s.replace(/`([^`]+)`/g, '$1');
s = s.replace(/^```[a-z]*\s*$/gm, '');
return s.trim();
}
Appliquez ceci à chaque réponse du modèle, pas seulement Ministral.
Cela évite les branchements spécifiques aux modèles et maintient la cohérence des pipelines.
Si votre système prend en charge plusieurs familles de modèles (Mistral, Qwen, DeepSeek, Llama, etc.), la conception la plus maintenable est de centraliser le comportement du modèle en un seul endroit.
Exemple :
function buildModelProfile(modelName) {
var lower = modelName.toLowerCase();
var isMistral = lower.includes('mistral') || lower.includes('ministral');
return {
family: isMistral ? 'Mistral' : 'Generic',
jsonSystemInstruction: isMistral
? 'Respond with ONLY valid JSON. No markdown. Keep values as short plain strings.'
: 'You output only valid JSON. No markdown fences, no explanation.',
jsonSchemaHint: isMistral
? ' Every value MUST be a short plain string — NO arrays, NO nested objects.'
: '',
jsonTemperature: isMistral ? 0.15 : 0.7,
defaultTemperature: isMistral ? 0.15 : 0.7,
plainTextInstruction: ' Do not use markdown formatting.'
};
}
Cela permet au reste de votre système de rester indépendant du modèle.
L'ajout d'un nouveau modèle devient trivial.
| Paramètre | Valeur recommandée | Raison |
|---|---|---|
| tokenizer_mode | mistral | Requis pour le tokenizer correct |
| config_format | mistral | Requis |
| load_format | mistral | Requis |
| chat_template_kwargs | Ne pas envoyer | Non pris en charge |
| température | 0.15 | Empêche les hallucinations structurelles |
| Instruction JSON | Valeurs explicites et plates | Évitez les objets imbriqués |
| max_tokens | 1,5–2× typique | Le modèle est verbeux |
| Suppression du Markdown | Toujours | Éviter les erreurs de formatage |
| Nouvelles tentatives JSON | 2–3 tentatives | Récupération fiable |
Ministral-3 fonctionne extrêmement bien lorsqu'il est correctement réglé.
Une fois que vous :
le modèle devient remarquablement prévisible et prêt pour la production.
Dans notre évaluation Jeopardy, cette configuration a pris en charge :
Tout s'exécutant localement sur Infrastructure GPU Trooper.AI.
Essayez le modèle de déploiement vLLM complet ici : Serveur compatible vLLM OpenAI
Louez votre propre serveur GPU dès aujourd'hui et commencez à développer des applications d'IA incroyables ! Les serveurs GPU Trooper.AI sont construits à partir de technologies haut de gamme entièrement recyclées des dernières années, conçus pour vous offrir les meilleures performances, sécurité et fiabilité pour tous vos besoins en IA.
Localisation dans l'UE · Haute confidentialité · Excellentes performances · Meilleur support