Aller au contenu

Le format de prompt

Le format est décrit par une implémentation Python autonome, encoding.py, publiée avec les poids. Ce chapitre en donne l'essentiel.

Les jetons spéciaux

Jeton Rôle
<|begin▁of▁sentence|> début de séquence, une seule fois au tout début
<|end▁of▁sentence|> fin d'un tour d'assistant
<|User|> préfixe de tour utilisateur
<|Assistant|> préfixe de tour assistant
<|System|> message système en milieu de conversation
<|latest_reminder|> rappel courant (date, locale…)
<think> / </think> délimiteurs du bloc de raisonnement
|DSML| jeton de balisage DSML
<|deepseek_image|> emplacement d'image dans la chaîne de prompt

La structure de base

En mode chat (thinking_mode="chat"), </think> est placé immédiatement après <|Assistant|> pour fermer aussitôt le bloc de réflexion, de sorte que le modèle produise directement du contenu :

<|begin▁of▁sentence|>{prompt_système}
<|User|>{message}<|Assistant|></think>{réponse}<|end▁of▁sentence|>
<|User|>{message_2}<|Assistant|></think>{réponse_2}<|end▁of▁sentence|>

En mode réflexion (thinking_mode="thinking") :

<|begin▁of▁sentence|><|System|>{préfixe_effort}{prompt_système}
<|User|>{message}<|Assistant|><think>{raisonnement}</think>{réponse}<|end▁of▁sentence|>

Les trois changements par rapport à DeepSeek-V4

1. Les balises DSML prennent une espace initiale

Les appels d'outils sont encadrés par <|DSML| calls> avec les balises <|DSML| invoke> et <|DSML| parameter> — espace incluse avant calls, invoke et parameter. V4 utilisait <|DSML|tool_calls> sans espace.

C'est le genre de détail qui casse silencieusement un parseur repris de V4.

2. L'effort de raisonnement est numérique

Le préfixe d'effort est rendu ainsi :

<|System|>Reasoning Effort: {budget} (range 1-100, the higher the value, the more thorough the reasoning)

V4 utilisait des descriptions en langage naturel. Les alias de chaîne correspondent aux paliers de l'API : "low" → 50, "high" → 75, "max" → 100, le défaut étant "high".

Le préfixe n'est rendu qu'en mode réflexion et qu'au tout début de la conversation, à l'index 0.

3. Les messages système en milieu de conversation

Ils sont supportés via le jeton <|System|>. Du point de vue de l'ajout de l'en-tête de génération de l'assistant, un tel message se comporte comme un message utilisateur.

Les appels d'outils

Les outils sont définis sur le message système, au format compatible OpenAI. Un bloc de schéma est alors injecté dans le prompt système, et un appel produit par le modèle ressemble à :

<|DSML| calls>
<|DSML| invoke name="nom_de_fonction">
<|DSML| parameter name="param" string="true">valeur_texte</|DSML| parameter>
<|DSML| parameter name="count" string="false">5</|DSML| parameter>
</|DSML| invoke>
</|DSML| calls><|end▁of▁sentence|>

L'attribut string distingue deux cas :

  • string="true" — la valeur est une chaîne brute ;
  • string="false" — la valeur est du JSON (nombre, booléen, tableau, objet).

Pourquoi cet attribut existe

Il lève l'ambiguïté classique du passage de paramètres en balisage : sans lui, impossible de distinguer la chaîne "5" de l'entier 5, ou la chaîne "[1,2]" du tableau [1, 2]. Encoder le typage dans la balise évite d'imposer que tous les paramètres soient du JSON valide — ce qui obligerait à échapper chaque chaîne.

Les résultats d'outils sont renvoyés dans des balises <tool_result> à l'intérieur d'un message utilisateur :

<|User|><tool_result>{résultat_json}</tool_result><|Assistant|><think>...

Un message de rôle tool n'est donc jamais rendu directement : il est fusionné dans le message utilisateur précédent. Quand plusieurs résultats sont présents, ils sont ordonnés selon l'ordre des tool_calls dans le message assistant précédent.

Les espaces de noms d'outils

Une définition d'outil peut porter un namespace, sous forme de chaîne ou d'objet avec name et description optionnelle. Le schéma et l'invocation utilisent alors la forme qualifiée espace::outil. La description de l'espace est préfixée à celle de l'outil.

Le parseur renvoie le nom et l'espace séparément, de sorte que sa sortie peut être repassée directement à encode_messages().

La gestion du raisonnement entre tours

Le paramètre drop_thinking, à True par défaut, contrôle la conservation du raisonnement des tours précédents :

  • sans outils — le raisonnement des tours antérieurs au dernier message utilisateur est supprimé. Seul le dernier tour d'assistant garde son bloc <think> ;
  • avec outils — drop_thinking est automatiquement désactivé. Tous les tours conservent leur raisonnement, parce que les conversations à appels d'outils exigent le contexte complet pour suivre un raisonnement multi-étapes.

Un piège d'implémentation

Ce basculement automatique signifie qu'activer les outils change la longueur du prompt de façon non linéaire : l'historique de raisonnement, normalement élagué, est intégralement conservé. Sur une trajectoire d'agent longue à effort élevé, cela représente des centaines de milliers de jetons.

Les jetons d'instruction rapide

Six jetons spéciaux déclenchent des comportements spécialisés à sortie courte, destinés aux tâches auxiliaires de classification et de génération :

Jeton Fonction
<|action|> décide si le prompt exige une recherche web ou peut être traité directement
<|title|> produit un titre de conversation concis après la première réponse
<|query|> génère des requêtes de recherche pour le prompt
<|authority|> classe le besoin d'autorité des sources
<|domain|> identifie le domaine du prompt
<|read_url|> décide si chaque URL du prompt doit être récupérée et lue

Ces jetons révèlent l'architecture du produit DeepSeek : le routage vers la recherche web, la génération de titres et le filtrage d'URL sont assurés par le même modèle, appelé en mode court, plutôt que par des modèles auxiliaires séparés.

Le multimodal

Les images sont représentées dans le prompt par <|deepseek_image|>. La structure retournée par encode_messages contient les enregistrements d'images dans l'ordre exact de leur apparition dans le prompt. Le chargement des pixels et l'expansion en jetons image sont assurés par inference/image_processor.py.

Deux notations d'entrée sont acceptées : le format de blocs de contenu style OpenAI, et une notation TXT compacte (texte<image>chemin.jpeg</image>suite) convertie vers les mêmes blocs. La suite de tests vérifie que les deux produisent un prompt identique et le même ordre d'images.

Une mise en garde de l'auteur

Le parseur de référence n'est pas robuste

« parse_message_from_completion_text est conçu pour traiter uniquement des sorties de modèle bien formées. Il ne tente pas de corriger ni de récupérer une sortie malformée que le modèle pourrait occasionnellement générer. Pour un usage en production, une gestion d'erreur additionnelle est recommandée. »

C'est explicite : l'implémentation publiée est une référence de format, pas un composant de production.


Chapitre suivant : Inférence locale