Aide

Besoin d’aide ?

Posez votre question sur le Discord de MiniLab, dans le salon de cette page :

#questions-generation

Ouvrir le salon ↗

Pas encore membre ? Rejoindre le Discord, puis revenez sur ce bouton.

Ma progression

Sauvegarder ma progression

Chargement…

Votre progression est enregistrée dans ce navigateur, pour cette adresse seulement. Gardez ce code : il la restaure dans un autre navigateur, sur un autre ordinateur, ou si les données du site ont été effacées.

MINILAB-0-1C
Mentions légales
Affichage

Personnaliser l’affichage

Ce réglage s’applique à la vue côte à côte.
LEÇON 14LE VOYAGE D’UNE REQUÊTE

Du champ de saisie au modèle.

Vous connaissez maintenant le modèle de l’intérieur : tokens, vecteurs, attention, blocs, logits, sampling, entraînement et alignement. La leçon 13 nous a fait entrer dans la dernière partie du parcours, avec la vraie tokenisation. Reprenons maintenant le trajet du point de vue de l’utilisateur. Il tape une question dans un champ de saisie et appuie sur « Envoyer ». Que se passe-t-il exactement entre ce clic et le moment où le premier token entre dans le modèle ? Une requête réseau, une liste de messages, des instructions cachées, un chat template, un budget de tokens… et parfois un passage de document retrouvé pour l’occasion.

01

Du navigateur au serveur

Quand vous cliquez sur « Envoyer », le code JavaScript de la page envoie une requête HTTP, le plus souvent de type POST, avec un corps au format JSON. Elle ne part pas directement chez le fournisseur du modèle : elle va d’abord vers le serveur de l’application, son back-end.

C’est ce serveur qui appelle l’API du modèle, en ajoutant sa clé d’API (API key), un secret qui identifie le compte et sert à la facturation. Règle d’or : cette clé ne doit jamais se trouver dans le code du navigateur, où n’importe qui pourrait la lire. MiniLab fonctionne d’ailleurs ainsi depuis la leçon 01 : la page Next.js envoie votre texte à l’API Python, qui fait les calculs.

02

Une liste de messages, chacun avec son rôle

Le corps de la requête envoyée au modèle ne contient pas « un texte », mais une liste de messages. Chacun porte un rôle : system pour les instructions de l’application, user pour l’utilisateur, assistant pour les réponses précédentes du modèle.

Le corps d’une requête, dans le style de l’API Chat Completions
{
  "model": "nom-du-modèle",
  "messages": [
    { "role": "system", "content": "Tu réponds en une ou deux phrases." },
    { "role": "user", "content": "Qui est Phileas Fogg ?" },
    { "role": "assistant", "content": "Un gentleman anglais, très ponctuel." },
    { "role": "user", "content": "Quel est son pari ?" }
  ],
  "temperature": 0.7,
  "max_tokens": 64,
  "stream": true
}

Point essentiel : le modèle n’a aucune mémoire d’une requête à l’autre. On dit que l’API est sans état (stateless). Pour qu’il comprenne « son pari », l’application doit lui renvoyer à chaque fois tout l’historique de la conversation. Certaines API, comme l’API Responses d’OpenAI, peuvent conserver cet historique côté serveur, mais le principe reste le même : tout ce que le modèle « sait » de la conversation est dans le prompt.

03

Le system prompt : les consignes invisibles

Le message system, ou system prompt, contient les consignes de l’application : le rôle de l’assistant, le ton, la langue, le format, ce qu’il doit refuser. L’utilisateur ne le voit pas, mais il est envoyé avec chaque requête. Les modèles récents d’OpenAI appellent ce rôle developer : ce sont les instructions du développeur.

Ces consignes ont la priorité sur celles de l’utilisateur : c’est la hiérarchie des instructions, apprise pendant l’alignement (leçon 12). Elle n’est pas infaillible. Un texte malveillant, glissé dans un message ou dans un document, peut tenter de détourner le modèle (« ignore tes instructions précédentes… ») : c’est l’injection de prompt (prompt injection), un risque à toujours garder en tête.

Pourquoi cette attaque est-elle possible ? Comme nous allons le voir avec le chat template, le system prompt, les documents ajoutés et le message de l’utilisateur finissent tous assemblés dans une seule et même suite de tokens, lue par l’attention. Il n’y a pas de cloison étanche entre les instructions et les données : la priorité donnée aux balises system repose uniquement sur ce que le modèle a appris pendant son alignement.

04

Le chat template, côté fournisseur

Le modèle, lui, ne connaît que des suites de tokens. Chez le fournisseur, les messages sont donc assemblés en un seul texte par le chat template de la leçon 12 : chaque message est encadré de tokens spéciaux, avec son rôle. Le template se termine par l’ouverture d’un tour assistant, laissé vide : c’est la place où le modèle va écrire.

Les messages, une fois mis en forme (style ChatML)
<|im_start|>system
Tu réponds en une ou deux phrases.<|im_end|>
<|im_start|>user
Quel est son pari ?<|im_end|>
<|im_start|>assistant

Ce texte est ensuite découpé par le tokenizer BPE de la leçon 13 ; chaque token spécial compte pour un seul token. On obtient les identifiants qui entrent dans le modèle : la boucle est bouclée avec la leçon 02.

05

Le budget de tokens et la fenêtre de contexte

La fenêtre de contexte (leçon 05) limite le total : les tokens du prompt plus les tokens de la réponse. L’API vérifie donc que prompt + max_tokens ≤ fenêtre de contexte. Sinon, elle renvoie une erreur, par exemple context_length_exceeded chez OpenAI.

Attention à un malentendu fréquent : par défaut, l’API du fournisseur ne raccourcit pas d’elle-même une requête trop longue, elle la rejette en bloc. C’est donc au serveur de l’application (le back-end) de compter les tokens avant d’envoyer la requête, et de la raccourcir si besoin pour garantir que prompt + max_tokens ≤ fenêtre de contexte. L’API Responses d’OpenAI propose bien une option truncation, mais elle est désactivée par défaut.

Dans le laboratoire, avec une fenêtre de 512 tokens, notre question et son historique occupent 174 tokens : il en reste 338 pour la réponse. Quand la conversation devient trop longue, le serveur de l’application doit faire des choix. La stratégie la plus simple est la troncature (truncation) : retirer les tours les plus anciens, une question et sa réponse à la fois, en gardant toujours le system prompt et le dernier message. D’autres résument les anciens échanges pour libérer de la place.

En retour, l’API indique ce qui a été consommé dans un champ usage : prompt_tokens pour l’entrée et completion_tokens pour la réponse. Ce sont ces nombres qui sont facturés. Un long historique coûte donc à chaque nouveau message : c’est aussi pour cela que le prompt caching, que nous verrons à la leçon 15, est précieux.

06

Les paramètres de génération

Avec les messages voyagent les réglages que vous connaissez déjà. temperature et top_p pilotent le sampling (leçon 09). max_tokens limite la longueur de la réponse et réserve sa place dans la fenêtre. stop définit des séquences d’arrêt, seed rend le tirage reproductible. Enfin, stream demande que la réponse arrive token par token, au fil de la génération : nous le verrons à la leçon 16.

07

Ce que le serveur peut ajouter

Entre le clic et le modèle, le serveur de l’application peut enrichir la requête. Il peut fournir au modèle des outils (tools, ou function calling) : le modèle répond alors par une demande structurée, par exemple meteo("Paris"). Attention : le modèle n’exécute jamais de code ni d’appel réseau lui-même, il ne produit que du texte. C’est le serveur de l’application qui exécute réellement la fonction, puis renvoie son résultat au modèle dans un nouveau message portant le rôle tool, pour que le modèle puisse formuler sa réponse finale. Il peut aussi filtrer les contenus interdits avec un outil de modération. Et il peut aller chercher des informations pour les glisser dans le prompt : c’est le RAG.

08

Observez par vous-même

Dans le laboratoire, tapez Quel est le pari de Phileas Fogg ?. Regardez le corps JSON de la requête, puis le même contenu mis en forme par le chat template, avec ses tokens spéciaux.

Réduisez ensuite la fenêtre de contexte à 256 tokens et activez le RAG : les anciens tours disparaissent, puis le passage lui-même ne tient plus. Passez max_tokens à 16 : le passage revient. Enfin, remettez max_tokens à 64 et essayez une fenêtre de 128 tokens : même seule, la question ne laisse plus assez de place pour la réponse.

Activez le RAG et comparez trois questions. « Quel est le pari de Phileas Fogg ? » et « Qui est Passepartout ? » retrouvent un passage du roman. « Qui a inventé le Wi-Fi ? », hors du roman, n’en trouve aucun : le prompt reste court. Méfiez-vous aussi des faux amis : « Quel temps fait-il à Paris ? » remonte un passage sans rapport, simplement parce que le mot « Paris » apparaît dans le roman. C’est la limite d’une recherche par mots-clés.

09

Les limites de notre exemple

Notre laboratoire ne contacte aucun vrai modèle : il construit la requête et calcule son budget, sans générer de réponse. Les tokens sont comptés avec notre petit BPE de 300 fusions, bien moins efficace que celui d’un vrai modèle : les vrais prompts sont plus courts. Et notre RAG cherche par mots-clés, pas avec des embeddings.

La requête est arrivée : le modèle a reçu toute la conversation sous forme de tokens. Mais comment traite-t-il ce long prompt, puis génère-t-il sa réponse token après token sans tout recalculer à chaque fois ? C’est le sujet de la prochaine leçon : le cache KV et la vitesse de génération.

À retenir

Le navigateur envoie le message au back-end de l’application (HTTP POST, JSON), qui appelle l’API du modèle avec une clé secrète. La requête contient une liste de messages avec des rôles (system ou developer, user, assistant, tool) et des paramètres (temperature, top_p, max_tokens, stop, seed, stream). L’API est sans état : l’historique est renvoyé à chaque requête. Le fournisseur assemble les messages avec le chat template, terminé par un tour assistant vide, puis tokenise.

Contrainte : prompt_tokens + max_tokens ≤ fenêtre de contexte ; au-delà, erreur ou troncature des tours les plus anciens. L’usage (prompt_tokens, completion_tokens) est facturé. Le serveur peut ajouter des outils (function calling), de la modération et du RAG : rechercher des passages pertinents (souvent par embeddings) et les insérer dans le prompt.

Text generation : messages et rôles · OpenAI ↗
Retrieval (RAG) · OpenAI ↗

VÉRIFIER SES CONNAISSANCES

Valider cette étape

Répondez aux trois questions pour débloquer la suite. Vous pouvez réessayer autant de fois que nécessaire.

Chargement de la progression…

Mise en ligne le

ESPACE DE PRATIQUE

Le laboratoire

Construisez la requête envoyée au modèle.

● EN DIRECT
01

Votre texte

MODIFIABLE
02

Ce que l’application ajoute

Fenêtre de contexte

max_tokens : la place réservée à la réponse

Construction de la requête…

À retenir

Le modèle reçoit une liste de messages avec des rôles, renvoyée en entier à chaque requête, assemblée par le chat template puis tokenisée. Le prompt et la réponse doivent tenir ensemble dans la fenêtre de contexte ; au-delà, on tronque les tours les plus anciens.

Ce laboratoire construit la requête sans appeler de vrai modèle. Les tokens sont comptés avec le petit BPE de la leçon 13, et le RAG utilise une recherche par mots-clés au lieu d’embeddings.

07

Pour aller plus loin

FACULTATIF

Le RAG : donner au modèle les bons documents

Le RAG (Retrieval-Augmented Generation) permet à un assistant de répondre à partir de vos propres documents, à jour, plutôt que de sa seule mémoire d’entraînement : on découpe les documents en passages, on les transforme en embeddings rangés dans une base vectorielle, on retrouve les plus proches de la question, puis on les ajoute au prompt. C’est la technique la plus utilisée pour les assistants d’entreprise et la recherche documentaire. Elle sort du cadre de ce parcours, mais ces ressources officielles permettent de l’apprendre pas à pas.

Pour la requête elle-même, ces ressources officielles détaillent les messages, les rôles et les outils.