Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Async, await et réponses en flux

Après cette leçon: Je peux dire pourquoi on attend un appel lent et comment arrive une réponse en flux.

Leçon de 60 min3 commandesLab agent de code IA : utiliser opencode pour expliquer et corriger du code, et vérifier son travail

Un appel lent ne doit rien figer

Un appel à un modèle peut durer plusieurs secondes. Votre programme ne doit pas se figer pendant l’attente. Le code asynchrone lui permet d’attendre sans se bloquer.

Le flux va plus loin. La réponse arrive par morceaux, et l’utilisateur peut commencer à lire tout de suite.

À la fin de cette leçon

Remarque

Je peux dire pourquoi on attend un appel lent et comment arrive une réponse en flux.

Mots clés

MotCe que ça veut dire
Promesseun remplaçant pour un résultat qui n’est pas encore arrivé
Awaitmettre une fonction en pause jusqu’au résultat d’une promesse
Fonction asyncune fonction qui a le droit d’utiliser await
Fluxune réponse envoyée par morceaux à mesure qu’elle se fabrique
Fragmentun morceau d’une réponse en flux

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Un appel lent renvoie une promesse

Quand vous lancez un travail lent, l’appel revient aussitôt avec une promesse. Le résultat n’est pas encore là. Votre programme passe à la ligne suivante.

Quand le résultat arrive, la promesse le livre. L’ordre compte : les lignes après l’appel peuvent s’exécuter avant le résultat.

Voir l’ordre des événements

Commande
docker exec -w /home/node/project agent node -e "const attendre=(ms,t)=>new Promise(r=>setTimeout(()=>r(t),ms));console.log('1 début');attendre(300,'3 l’appel lent est terminé').then(console.log);console.log('2 le programme continue')"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Await met en pause une fonction

Dans une fonction async, await met cette fonction en pause jusqu’au résultat de la promesse. Le reste du programme n’est pas bloqué.

Deux appels lents indépendants peuvent partir ensemble avec Promise.all. Cela prend à peu près le temps du plus lent, pas la somme des deux.

Attendre un par un, puis ensemble

Commande
docker exec -w /home/node/project agent node -e "const attendre=(ms,t)=>new Promise(r=>setTimeout(()=>r(t),ms));const arrondi=(t0)=>Math.round((Date.now()-t0)/100)*100;(async()=>{let t0=Date.now();await attendre(200,'a');await attendre(200,'b');console.log('l’un après l’autre : environ '+arrondi(t0)+' ms');t0=Date.now();await Promise.all([attendre(200,'a'),attendre(200,'b')]);console.log('ensemble : environ '+arrondi(t0)+' ms')})()"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Une réponse en flux arrive par fragments

Si vous demandez stream: true, le service envoie la réponse à mesure qu’il la fabrique. La plupart des API de modèles utilisent des événements serveur : des lignes qui commencent par data:, chacune avec un petit morceau de texte.

La dernière ligne est data: [DONE]. Joignez les morceaux dans l’ordre pour obtenir la réponse entière.

Exemple travaillé : un flux, ligne par ligne

Ligne reçueCe qu’elle donne
data: {"choices":[{"delta":{"content":"Sal"}}]}Sal
data: {"choices":[{"delta":{"content":"ut"}}]}ut
data: [DONE]La fin, sans texte
AssembléSalut

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Lire une réponse en flux

Commande
docker exec -w /home/node/project agent node -e "const u=(process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions';(async()=>{try{const r=await fetch(u,{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer lab'},body:JSON.stringify({model:'lab',messages:[{role:'user',content:'Comptez de un à cinq en lettres.'}],max_tokens:40,stream:true})});if(r.ok===false)throw new Error(r.status);const d=new TextDecoder();let b='',n=0,t='';for await(const p of r.body){b+=d.decode(p,{stream:true});const L=b.split(String.fromCharCode(10));b=L.pop();for(const l of L){const x=l.slice(6);if(l.startsWith('data: ')&&(x==='[DONE]')===false){const c=JSON.parse(x).choices?.[0]?.delta?.content;if(c){n++;t+=c}}}}console.log('Fragments avec du texte : '+n);console.log('Texte assemblé : '+t)}catch(e){console.log('Aucun flux ('+e.message+'). Exemple enregistré :');console.log('Fragments avec du texte : 5');console.log('Texte assemblé : un, deux, trois, quatre, cinq')}})()"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Une erreur fréquente

Attention

Beaucoup de gens pensent que le flux rend le modèle plus rapide. La réponse entière prend à peu près le même temps. Vous voyez les premiers mots plus tôt, ce qui paraît plus rapide. Un flux peut aussi s’arrêter en route : vérifiez que le marqueur de fin est arrivé.

À propos de ce labo et de sa source: Lab agent de code IA : utiliser opencode pour expliquer et corriger du code, et vérifier son travail

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.