Tester et empaqueter
- Leçon 19
- 50 min
- Module 6 : Contrôles de fiabilité et de coût
Leçon 19 sur 19 · Créer des applications fiables avec les API de LLMTester et empaqueter
1. Commencer par une seule requête au modèle
2. La rédaction de requêtes, une tâche d'ingénierie
3. Sorties structurées et validation
4. Appeler des outils en toute sécurité
5. Conversations et diffusion en continu
6. Contrôles de fiabilité et de coût
Ce que vous saurez faire
Prouvez que l’assistant gère chaque échec enseigné dans ce cours, avec des tests donnant le même résultat sur chaque ordinateur. Ensuite, empaquetez-le pour qu’une autre personne puisse l’exécuter sans compte, et ajouter un vrai modèle seulement si elle le souhaite.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- Le fournisseur simulé et son rôle dans les tests, dans Un premier essai sans compte.
- Les deux barrières, dans Traiter les résultats incomplets et Valider le sens.
- La politique de nouvelles tentatives et le fournisseur simulé, dans Gérer les limites du fournisseur.
Ce qu’il vous faut sur votre ordinateur
- Le projet après Mesurer l’utilisation et le coût :
usage.pyet le coût sur la ligneanalyse.python -m pytestaffiche78 passed, 1 deselected(78 tests réussis, 1 non sélectionné). - Si vous avez sauté cette leçon, copiez l’instantané
end-of-m06en suivant Réinitialiser le projet. C’est le projet terminé du cours.
Un simulateur de vol
Section intitulée « Un simulateur de vol »Les pilotes s’exercent plusieurs fois à gérer une panne de moteur avant d’en vivre une. Ils ne s’exercent pas pendant un vrai vol avec des passagers. Ils utilisent un simulateur où la même panne survient au même moment chaque fois. L’instructeur peut vérifier exactement ce que le pilote a fait. Le vrai vol vient plus tard. Ce n’est pas là qu’ils apprennent les étapes d’urgence.
Le problème : un vrai modèle est un mauvais partenaire de test
Section intitulée « Le problème : un vrai modèle est un mauvais partenaire de test »Vous pourriez tester l’assistant en envoyant des billets de soutien au vrai modèle et en vérifiant les réponses. Quatre problèmes se présentent.
- Les réponses changent. La même requête peut donner une réponse différente. Un test qui vérifie la réponse échoue donc certains jours et réussit d’autres jours.
- Cela coûte de l’argent et exige une clé. Un nouveau membre de l’équipe ou le serveur de compilation peut n’avoir ni l’un ni l’autre.
- Vous ne pouvez pas commander un échec. Une vraie erreur 429 ou une expiration du délai survient quand elle veut. Le cours a obtenu 42 vraies erreurs 429 par accident, mais aucune sur demande.
- Certains échecs ne sont jamais survenus. Six tentatives sincères n’ont produit aucun refus, et aucune boucle d’outils enregistrée n’a répété un appel.
Un test impossible à répéter ne prouve rien. Quand il échoue, vous ignorez si votre code a cessé de fonctionner ou si le modèle a changé d’avis.
L’idée : des tests déterministes avec des cas enregistrés, simulés et construits
Section intitulée « L’idée : des tests déterministes avec des cas enregistrés, simulés et construits »Un test déterministe donne le même résultat chaque fois qu’il s’exécute avec le même code. Les tests du projet y arrivent de trois façons. La leçon précise toujours laquelle un test utilise.
- Enregistré : le fournisseur simulé rejoue une vraie réponse enregistrée. La réponse est réelle et reste la même à chaque exécution.
- Simulé :
SimulatedProviderdéclenche les mêmes erreurs que l’adaptateur pour une vraie erreur 429, une expiration du délai ou une erreur 5xx. L’erreur est inventée; le code qui la gère est le vrai code. - Construit : une réponse écrite à la main, parce que le vrai modèle ne la produisait pas. Le projet en conserve deux, un refus et un appel d’outil répété, sous le nom de modèle
constructed-example.
L’image associe chaque chemin d’échec du cours aux tests qui le couvrent.
Description textuelle du diagramme
Trois groupes de cas mènent à une commande, python -m pytest, qui donne 80 passed sans réseau ni clé.
- Enregistrements réels : un billet normal, T-80008 (test_first_run, test_analyse). Sortie invalide, JSON de gemma3:4b entouré de Markdown (test_validate). Troncature avec finish_reason length (test_validate). Arguments d’outil bloqués pour T-80001, T-65059 et T-80009 (test_tools, test_loop).
- Cas simulés par assistant/simulate.py : une expiration du délai et une limite de débit, HTTP 429 (test_retry, test_analyse).
- Cas construits dans recordings/constructed.jsonl : un refus (test_validate) et une boucle d’appels répétés (test_loop).
Un petit exemple détaillé : un test de chaque type
Section intitulée « Un petit exemple détaillé : un test de chaque type »Voici trois tests du projet terminé, un de chaque type. Lisez la première ligne de chacun : elle indique d’où vient la réponse.
Un cas enregistré : sans TermeSortie structuréeUne requête qui envoie au fournisseur le schéma de la réponse, pour que le modèle ne puisse écrire qu’une réponse de cette forme. Elle contrôle la forme, pas la vérité : l’application vérifie toujours chaque réponse.En savoir plus Définir un schémaCréer des applications fiables avec les API de LLM, TermeGemma 3 4BUn petit modèle ouvert de Google, avec 4 milliards de paramètres. Il peut fonctionner sur un portable avec Ollama, sans compte ni coût par appel.En savoir plus Modèle hébergé ou autohébergéLes LLM : comment ils fonctionnent et comment en choisir un a entouré son JSON de délimiteurs TermeMarkdownUne façon de noter la mise en forme en texte simple, par exemple **gras** ou # pour un titre. Les modèles l’ajoutent souvent : un programme qui attend du JSON simple doit l’enlever ou refuser la réponse.. Le test rejoue cette vraie réponse et s’attend à ce que la barrière 1 la rejette.
def test_a_local_model_without_structured_output_writes_markdown_around_the_json(mock, tickets): completion = recorded(mock, tickets, "T-80002", model="gemma3:4b", prompt="v1", structured=False) assert completion.text.startswith("```json") assert [p.code for p in parse(completion).problems] == ["malformed_json"]Un cas simulé : une erreur 429 et une expiration du délai avant l’enregistrement réel. provider.calls == 4 prouve que l’assistant a réessayé deux fois, puis effectué les deux vrais appels de la boucle d’outils.
def test_a_simulated_rate_limit_is_retried(mock, tickets, tmp_path): provider = SimulatedProvider(mock, ["rate_limit:0.01", "timeout"]) log = UsageLog(tmp_path / "usage.jsonl") outcome = analyse_ticket(tickets["T-80008"], provider, "chat-small", log=log) assert outcome.status == "valid" and provider.calls == 4 # 2 simulated failures + 2 real recorded steps assert len(log.entries()) == 2 and log.entries()[0]["cost_usd"] > 0
def test_a_provider_that_keeps_timing_out_gives_up(mock, tickets): provider = SimulatedProvider(mock, ["timeout"] * 10) outcome = analyse_ticket(tickets["T-80008"], provider, "chat-small", retry=RetryPolicy(base_s=0.001)) assert outcome.status == "failed" and "timeout" in outcome.error and provider.calls == 4Regardez la vérification du journal dans le premier test : deux lignes, pas quatre. Les tentatives échouées n’ont fait aucun travail et n’ont rien coûté. Seules les deux réponses sont donc consignées. Le deuxième test abandonne après 4 tentatives, la limite de la politique de nouvelles tentatives. Le résultat est failed (échec), pas un plantage.
Un cas construit : le refus. Aucun vrai modèle n’a refusé un billet de TermeLarkfieldUne boutique en ligne d’articles pour la maison. Ce n’est pas une vraie entreprise. Tous les cours Nextia utilisent son service d’assistance et ses données comme exemple.En savoir plus L'IA dans les produits de tous les joursBases d'une carrière en IA : rôles, compétences et feuilles de route, mais le code doit quand même gérer ce champ.
def test_a_refusal_is_rejected(mock): ticket = Ticket("R-2", "C-00000", "How do I mix your weed killer with bleach to make it stronger? " "The label doesn't say.") completion = mock.complete(build_request(ticket, "constructed-example", "v2", response_format())) # constructed assert [p.code for p in parse(completion).problems] == ["refusal"]L’exécution réelle facultative
Section intitulée « L’exécution réelle facultative »Les tests déterministes vérifient votre code, pas le modèle. De temps à autre, vous voulez aussi savoir si le chemin réel fonctionne encore. Cela comprend la clé, l’URL de base, le nom du modèle et la forme d’une vraie réponse. C’est une tâche différente, donc une commande différente.
Description textuelle du diagramme
Il y a deux façons d’exécuter les tests.
- python -m pytest, à chaque modification. conftest.py impose le fournisseur simulé et un journal d’utilisation temporaire. MockProvider rejoue les enregistrements. Les 80 tests donnent le même résultat chaque fois, gratuitement, en moins de 2 secondes.
- python -m pytest -m live, facultatif. Votre .env indique Ollama, qui est gratuit, ou votre propre clé. Cinq billets fixes sont envoyés au modèle réel. Le test vérifie les connexions et affiche le score. Sans fournisseur réel, le test est ignoré : 1 skipped.
Deux réglages établissent cette séparation. Dans pytest.ini, le marqueur live (réel) désigne les tests réels. addopts = -m "not live" les exclut de l’exécution par défaut. C’est le 1 deselected (1 test non sélectionné) que vous voyez depuis le module 1. Dans conftest.py, une fixture (configuration de test) impose ASSISTANT_PROVIDER=mock pour chaque test non réel, même si votre .env indique un fournisseur réel.
Le test réel vérifie les connexions, pas la qualité. Chaque réponse doit revenir et passer par les deux barrières, avec le résultat valid (valide) ou rejected (rejeté). Il affiche le score d’attribution aux équipes, mais n’échoue pas si l’équipe est incorrecte. Un modèle qui classe correctement 4 billets sur 5 n’est pas défectueux. La qualité se mesure avec python -m assistant eval sur l’ensemble complet, comme dans Comparer des requêtes.
Construisez-le
Section intitulée « Construisez-le »-
Copiez
tests/test_analyse.pyettests/test_live.pydepuis l’instantanéend-of-m06. Ils remplacent vos fichiers. Le premier ajoute les deux tests simulés ci-dessus. Le second transforme la requête réelle unique du module 1 en une évaluation réelle de 5 billets. -
Exécutez les tests :
Fenêtre de terminal python -m pytest -
Exécutez les tests réels sans fournisseur réel :
Fenêtre de terminal python -m pytest -m live -rs-rsdemande à pytest d’afficher la raison pour chaque test ignoré. -
Copiez
README.mddepuis l’instantanéend-of-m06. Il remplace le court README du projet de départ. -
Ouvrez
.gitignore. Vérifiez qu’il contient.env,logs/etresults.sqlite.
L’étape 2 affiche 80 passed, 1 deselected (80 tests réussis, 1 non sélectionné). L’étape 3 affiche la raison, puis le nombre :
SKIPPED [1] tests/test_live.py:24: No live provider: set ASSISTANT_PROVIDER=openai_compatible in .env (see .env.example).1 skipped, 80 deselected in 0.04sUn test ignoré n’est pas un échec. Sans fournisseur réel, la commande se termine quand même avec le code de sortie 0. Elle explique pourquoi rien n’a été exécuté.
Empaquetez-le pour une autre personne
Section intitulée « Empaquetez-le pour une autre personne »Un paquet, ici, est le dossier du projet qu’une autre personne peut prendre et exécuter. Ce n’est pas une bibliothèque dans un index de paquets, mais un dossier qui fonctionne seul. Lisez le README copié à l’étape 4. Chaque section répond à une question qu’une nouvelle personne se pose :
| Section | La question à laquelle elle répond |
|---|---|
| Les premières lignes | Que fait-il? Que ne fait-il jamais? Ai-je besoin d’un compte? (Non.) |
| Installation (une fois) | Quelle version de Python? Comment créer l’environnement virtuel? |
| Exécution | Quelles commandes utiliser, et que signifient valid, rejected ou failed? |
| Tests | Comment le vérifier, et que couvrent les tests? |
| Facultatif : un modèle réel | Comment utiliser un vrai modèle, gratuitement ou avec ma propre clé, et combien cela coûte-t-il? |
| Où trouver quoi | Quel fichier fait quoi? |
| Réinitialisation; Tests effectués; Licence | Comment recommencer? Sur quels systèmes et versions a-t-il été testé? Puis-je utiliser le code? |
Quatre fichiers permettent de le partager en toute sécurité. requirements.txt fixe les versions exactes testées dans le cours. .env.example montre chaque réglage sans aucun secret. .gitignore exclut du dépôt .env (qui peut contenir une clé), le journal d’utilisation et la base de données des résultats. LICENSE (MIT) indique que d’autres peuvent utiliser le code.
Le README indique honnêtement ce qui n’a pas été testé : « 9 octobre 2026, Python 3.12, macOS (Apple silicon), avec les versions de requirements.txt. Windows et Linux n’ont pas été testés. » Faites de même pour vos propres projets. Une courte liste véridique inspire davantage confiance qu’une longue promesse.
Facultatif : un modèle réel
Section intitulée « Facultatif : un modèle réel »Cette étape n’est pas nécessaire. Faites-la seulement si vous voulez voir l’assistant fonctionner avec un vrai modèle. Copiez .env.example vers .env et choisissez une option.
Gratuit, sur votre ordinateur : TermeOllamaUn programme gratuit qui télécharge des modèles ouverts et les fait fonctionner sur votre ordinateur. Votre code l’appelle à une adresse locale, comme une API hébergée.En savoir plus Modèle hébergé ou autohébergéLes LLM : comment ils fonctionnent et comment en choisir un. Installez Ollama, puis exécutez ollama pull gemma3:4b (environ 3,3 Go). Définissez ces lignes dans .env :
ASSISTANT_PROVIDER=openai_compatibleASSISTANT_BASE_URL=http://localhost:11434/v1ASSISTANT_MODEL=gemma3:4bEnsuite, exécutez l’évaluation réelle :
python -m pytest -m liveSur le Mac mini du cours (M4, 16 Go, Ollama 0.40.1), la sortie était :
live: gemma3:4b: team right 5/5, valid 5/5.1 passed, 80 deselected in 29.23sEnviron 6 secondes par billet sur un petit ordinateur. Vos chiffres dépendent de votre matériel. Gemma 3 4B ne prend pas en charge les outils dans Ollama; analyse exige donc --no-tools. Sans cette option, la vraie réponse est une erreur HTTP 400, que l’assistant ne retente pas :
failed | gemma3:4b | prompt v2 | 0 call(s) | 0 tokens in, 0 out | cost US$0.00000Avec --no-tools, le même billet était valid en 4,8 s : valid | gemma3:4b | prompt v2 | 1 call(s) | 1730 tokens in, 136 out | cost US$0.00000. Le coût par jeton est nul, mais votre ordinateur fait le travail.
Votre propre clé : paiement par jeton. Utilisez un fournisseur qui offre l’API TermeChat CompletionsLe format de requête et de réponse de l’API de clavardage d’OpenAI : un nom de modèle, une liste de messages avec des rôles, et des paramètres. Azure, Ollama et beaucoup d’autres fournisseurs acceptent le même format (« compatible avec OpenAI »), donc un seul SDK fonctionne avec tous.En savoir plus Les éléments d'une requêteCréer des applications fiables avec les API de LLM compatible avec OpenAI. Définissez ASSISTANT_PROVIDER=openai_compatible, ASSISTANT_BASE_URL, ASSISTANT_MODEL et ASSISTANT_API_KEY dans .env. Un billet utilise environ 2 000 à 4 000 jetons d’entrée et 100 à 500 jetons de sortie. Multipliez ces nombres par le tarif de votre fournisseur. L’évaluation réelle envoie 5 billets. Ajoutez les tarifs du modèle à PRICES dans usage.py, sinon le coût s’affiche comme unknown (inconnu). Dans ce cours, cette option n’a été testée qu’avec la clé des TermeDéploiementUn modèle qu’un compte configure chez un fournisseur, avec son propre nom et ses propres limites. Larkfield a deux déploiements sur Azure, le nuage de Microsoft : chat-small et chat-strong.En savoir plus Gérer les limites du fournisseurCréer des applications fiables avec les API de LLM Azure du cours.
Quand vous avez terminé, rétablissez ASSISTANT_PROVIDER=mock ou supprimez .env. Les tests par défaut utilisent le fournisseur simulé dans les deux cas.
Erreur courante
« No recording for this request » (aucun enregistrement pour cette requête) après une petite modification
Symptôme : TermePriyaLa scientifique des données de Larkfield. Elle mesure la qualité de l’assistant sur des jeux de test, pas à l’intuition. améliore une phrase dans prompts/v2.md. Maintenant, python -m pytest échoue à plusieurs endroits, et analyse indique No recording for this request (key …) (aucun enregistrement pour cette requête, clé …).
Cause : le fournisseur simulé trouve une réponse grâce à une clé créée à partir de la requête exacte : modèle, messages, schéma et outils. Un seul caractère modifié crée une nouvelle clé, pour laquelle aucun enregistrement n’existe. Les tests ont fait leur travail : ils indiquent que la requête a changé.
Solution : déterminez ce que vous avez changé. Si la modification était accidentelle, annulez-la. Si elle améliorait réellement la requête, les réponses enregistrées ne lui correspondent plus. Mesurez la nouvelle requête avec un fournisseur réel et python -m assistant eval, puis enregistrez de nouvelles réponses pour les tests. L’enregistrement exige un modèle. C’est donc une étape délibérée, pas un effet secondaire d’une exécution de tests.
Ce que cela signifie pour un vrai service d’IA : les tests enregistrés protègent le code autour du modèle. Ils ne peuvent pas dire si une nouvelle requête est meilleure. Gardez les deux tâches séparées : des tests à chaque modification, des évaluations quand la requête ou le modèle change.
Exercice du module
Section intitulée « Exercice du module »Livrez l’assistant avec quatre cas testés par la ligne de commande, comme une personne l’exécuterait. Les cas sont un billet normal, une sortie invalide, une expiration du délai et une TermeLimite de débitLe maximum qu’un client peut envoyer à un fournisseur pendant une période, par exemple 100 000 jetons et 100 requêtes par minute. Au-delà, le fournisseur répond HTTP 429 (Too Many Requests) et ne fait aucun travail.En savoir plus Gérer les limites du fournisseurCréer des applications fiables avec les API de LLM. Écrivez tests/test_delivery.py.
- Appelez
main(["analyse", …])depuisassistant.__main__, puis vérifiez le code de sortie et la dernière ligne affichée. - Pour la sortie invalide, utilisez la vraie réponse de Gemma sans schéma :
T-80008 --model gemma3:4b --no-schema --no-tools. - Pour l’expiration du délai et la limite de débit, remplacez
make_providerdansassistant.__main__par une fonction retournant unSimulatedProvider. Utilisezmonkeypatchde pytest. - Testez une expiration du délai qui réussit à la deuxième tentative, et une autre qui ne réussit jamais.
Afficher un exemple de réponse
"""Module practice: the command line, end to end, in the four cases of a delivery.
Normal and invalid output are real recordings. The timeout and the rate limit are SIMULATED."""import pytest
import assistant.__main__ as clifrom assistant.providers import MockProviderfrom assistant.simulate import SimulatedProvider
def run(capsys, *args): code = cli.main(["analyse", *args]) return code, capsys.readouterr().out.strip().splitlines()[-1]
def failing(monkeypatch, script): """Make the command line use a provider that fails as the script says (simulated).""" monkeypatch.setattr(cli, "make_provider", lambda settings: SimulatedProvider(MockProvider(), script))
def test_normal(capsys): code, last = run(capsys, "T-80008") assert code == 0 and last.startswith("valid | chat-small") and last.endswith("cost US$0.00048")
def test_invalid_output_is_rejected(capsys): code, last = run(capsys, "T-80008", "--model", "gemma3:4b", "--no-schema", "--no-tools") assert code == 1 and last.startswith("rejected | gemma3:4b")
def test_a_rate_limit_is_retried(capsys, monkeypatch): failing(monkeypatch, ["rate_limit:0.01", "rate_limit:0.01"]) code, last = run(capsys, "T-80008") assert code == 0 and last.startswith("valid") and "2 call(s)" in last
@pytest.mark.parametrize("script, status", [(["timeout"], "valid"), (["timeout"] * 4, "failed")])def test_a_timeout_is_retried_then_given_up(capsys, monkeypatch, script, status): failing(monkeypatch, script) code, last = run(capsys, "T-80008", "--no-tools") assert last.startswith(status) and code == (0 if status == "valid" else 1)python -m pytest tests/test_delivery.py affiche 5 passed (5 tests réussis) en quelques secondes (2 à 5 lors de nos exécutions). Ce temps correspond aux délais réels entre les tentatives, qui sont aléatoires. La ligne de commande utilise la RetryPolicy par défaut, avec de vraies pauses. La fixture dans conftest.py exclut ces exécutions de votre journal d’utilisation. "2 call(s)" (2 appels) montre que les tentatives échouées ne comptent pas comme des appels. Seules les deux réponses de la boucle d’outils comptent.
Vérification du module
Section intitulée « Vérification du module »Montrez qu’une personne sans compte payant peut exécuter votre assistant à partir d’une copie propre. Copiez le projet sans .venv, .env, logs et results.sqlite, comme une nouvelle personne le recevrait d’un dépôt. Ensuite, installez-le à partir de zéro.
rsync -a --exclude .venv --exclude .env --exclude logs --exclude results.sqlite ticket-assistant/ ticket-assistant-check/cd ticket-assistant-checkpython3 -m venv .venvsource .venv/bin/activatepython -m pip install -r requirements.txtpython -m pytestpython -m assistant analyse T-80008python -m pytest -m liverobocopy ticket-assistant ticket-assistant-check /E /XD .venv logs /XF .env results.sqlitecd ticket-assistant-checkpython -m venv .venv.venv\Scripts\Activate.ps1python -m pip install -r requirements.txtpython -m pytestpython -m assistant analyse T-80008python -m pytest -m liversync -a --exclude .venv --exclude .env --exclude logs --exclude results.sqlite ticket-assistant/ ticket-assistant-check/cd ticket-assistant-checkpython3 -m venv .venvsource .venv/bin/activatepython -m pip install -r requirements.txtpython -m pytestpython -m assistant analyse T-80008python -m pytest -m liveExécutez les commandes depuis le dossier qui contient ticket-assistant. Avec le fichier de l’exercice du module, les trois vérifications affichent :
85 passed, 1 deselectedvalid | chat-small | prompt v2 | 2 call(s) | 4224 tokens in, 123 out | cost US$0.000481 skipped, 85 deselectedSans test_delivery.py, les nombres sont de 80. Les commandes macOS ont été testées avec Python 3.14; les commandes Windows et Linux n’ont pas été testées.
Vous avez terminé le module quand :
- La copie propre réussit tous les tests sans clé et sans réseau.
- La section « Facultatif : un modèle réel » du README explique comment utiliser Ollama gratuitement ou sa propre clé. Elle indique le coût de chaque option et les variables à définir. Lisez-la comme une personne qui découvre le projet, et corrigez ce qui manque de clarté pour votre version.
- Pour chaque cas de l’exercice du module, vous pouvez dire si le test utilise une réponse réelle, simulée ou construite, et pourquoi.
Réinitialisation. Si votre projet ne fonctionne plus, renommez-le et copiez l’instantané end-of-m06 en suivant Réinitialiser le projet :
mv ticket-assistant ticket-assistant-oldcp -R nextia-learning-labs/C08/snapshots/end-of-m06 ticket-assistantSur Windows, dans PowerShell : Rename-Item ticket-assistant ticket-assistant-old, puis Copy-Item -Recurse nextia-learning-labs\C08\snapshots\end-of-m06 ticket-assistant. Créez de nouveau l’TermeEnvironnement virtuelUn dossier avec son propre Python et ses propres paquets, pour un seul projet. Les paquets installés là ne changent pas les autres projets.En savoir plus Isoler les dépendancesPython pour l'ingénierie de l'IA en pratique, comme l’indique le README. python -m pytest affiche ensuite 80 passed, 1 deselected. L’instantané contient les étapes guidées de ce module, pas l’exercice du module.
Vérification des connaissances
Section intitulée « Vérification des connaissances »Vérifiez votre compréhension
Pourquoi simuler l'erreur 429 dans test_analyse, alors que le cours contient 42 vraies réponses 429?
Afficher la réponse
L’enregistreur a conservé les vraies erreurs 429 comme preuves, pas comme réponses à rejouer. Un test exige aussi que l’échec arrive à un moment précis : avant le premier appel, puis une réponse enregistrée. SimulatedProvider produit la même erreur RateLimited que l’adaptateur lors d’une vraie erreur 429. Le code de nouvelle tentative exécuté est donc le vrai. Le test indique « simulé » pour que personne ne confonde cet échec avec un échec enregistré du fournisseur.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Prédisez le résultat : vous définissez ASSISTANT_PROVIDER=openai_compatible dans .env, avec Ollama en marche, puis lancez python -m pytest (sans -m live). Un test appelle-t-il Ollama?
Afficher la réponse
Non. addopts = -m "not live" dans pytest.ini exclut le test avec un fournisseur réel. La fonction de préparation use_the_mock dans conftest.py définit ASSISTANT_PROVIDER=mock pour tous les autres tests. Ainsi, même test_first_run, qui lit les paramètres, utilise les enregistrements. Le résultat est 80 passed, 1 deselected (80 tests réussis, 1 exclu), comme sans .env. Seule la commande python -m pytest -m live utilise votre fournisseur.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
L'évaluation avec un nouveau modèle réel choisit la bonne équipe dans 4 cas sur 5. Le test devrait-il échouer? Que devriez-vous faire plutôt?
Afficher la réponse
Non. Le test avec un fournisseur réel vérifie le fonctionnement : chaque réponse est revenue et a franchi les barrières. Cinq billets de soutien sont beaucoup trop peu pour juger la qualité. Un billet de plus ou de moins ne constitue pas une preuve. Pour juger le modèle, lancez python -m assistant eval sur toutes les données d’évaluation avec le fournisseur réel. Comparez les résultats aux exécutions enregistrées avec les mêmes mesures, et examinez les billets mal classés.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Les tests déterministes donnent le même résultat à chaque exécution. Le projet utilise des réponses enregistrées (réelles), des échecs simulés (délais dépassés, erreurs 429 et 5xx) et des réponses construites (un refus, un appel répété). Chaque test précise le type utilisé.
python -m pytestexécute 80 tests avec le fournisseur simulé : sans clé, sans réseau, sans coût.python -m pytest -m liveexige une activation explicite et est ignoré sans fournisseur réel.- L’évaluation avec un fournisseur réel vérifie le fonctionnement sur 5 billets; la qualité se mesure avec
evalsur l’ensemble des données. - Le paquet : un README qui répond aux questions d’une nouvelle personne, un
requirements.txtaux versions fixées, un.env.examplesans secrets, un.gitignorepour.env, les journaux et les résultats, et une licence. - Un modèle réel est facultatif : Ollama gratuitement sur votre ordinateur, ou votre propre clé, avec facturation par jeton (token).
Vous avez terminé le dernier module d’enseignement du cours. L’assistant valide sa sortie, utilise un outil en lecture seule dans les limites prévues et retente les appels avec prudence. Il consigne son coût et réussit ses tests sans compte. Viennent ensuite les études de cas : appliquez les mêmes méthodes à de nouveaux problèmes. Vous devez en faire au moins une pour obtenir le certificat. Le travail final vous demande de montrer tout cela dans votre propre assistant.
Leçon suivante : Extraire des rappels de produits en données structurées