Module 05 · Leçon 4

Planification et auto-vérification

Une même tâche en plusieurs étapes, trois méthodes comparées – faire directement, établir un plan puis faire, vérifier soi-même après coup. Le plan a doublé le coût pour un résultat semblable ; l'auto-vérification a vraiment trouvé deux erreurs de source, mais a coûté quatre fois plus.

  • Environ 40 minutes
  • Niveau : Intermédiaire
  • Testé : 2026-09-14 deepseek-flash

Le code et les sorties des programmes sont reproduits tels qu’ils ont tourné : commentaires et sorties sont donc en chinois.

Dans les articles sur les agents, deux techniques reviennent presque toujours : la « planification » (planning) et la « réflexion » (reflection). D'abord faire établir un plan au modèle, puis l'exécuter ; une fois l'exécution terminée, lui faire vérifier son propre résultat et corriger les problèmes trouvés. Cela paraît raisonnable ; c'est aussi ainsi que les humains mènent les tâches complexes.

Mais ces techniques demandent toutes des appels de modèle supplémentaires. Qu'apportent-elles réellement, et valent-elles leur prix ? Cette leçon les mesure sur une vraie tâche en plusieurs étapes.

La tâche

« Compare si le Client et l'AsyncClient de httpx se configurent de la même façon pour trois choses : le délai d'expiration, le proxy, HTTP/2. Présente le résultat sous forme de tableau, en indiquant dans chaque case la source dans la documentation (nom de fichier et numéro de ligne). »

Cette tâche est plus complexe que les questions précédentes : trois sujets différents à chercher, deux clients à examiner pour chaque sujet, et des sources à noter précisément. On utilise toujours l'agent de la leçon 2 et ses trois outils de documentation.

Méthode 1 : faire directement

La tâche est confiée directement à l'agent, qui décide lui-même comment chercher.

Méthode 2 : un plan d'abord

On appelle d'abord une fois le modèle, en lui demandant seulement un plan, sans appel d'outils. Puis on joint ce plan à la tâche et on confie le tout à l'agent :

def with_plan():
    # 第一步:只列计划,不调用工具
    plan, usage = model([{"role": "system", "content": SYSTEM}, {"role": "user", "content":
                         TASK + "\n\n先不要调用工具。列出你打算怎么查,编号列出每一步要找什么,不超过 6 步。"}], None)
    answer, messages, stats = loop([
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": TASK + "\n\n按这个计划执行,执行中发现计划不对可以调整:\n" + plan.content},
    ])
    ……

La phrase « si, en exécutant, tu constates que le plan ne convient pas, tu peux l'ajuster » est importante. Le plan est établi avant d'avoir consulté quoi que ce soit ; le suivre à la lettre ferait manquer des pistes qu'on ne découvre qu'en cherchant.

Méthode 3 : faire, puis vérifier

On fait d'abord directement ; une fois la réponse obtenue, on la donne au modèle avec tous les textes d'origine que l'agent a trouvés en chemin, et on lui fait vérifier case par case :

def with_reflection():
    answer, messages, stats = plain()
    evidence = "\n\n".join(m["content"] for m in messages if m["role"] == "tool")
    review, usage = model([{"role": "user", "content": f"""下面是一份回答和查到的全部原文。逐格检查回答里的表格:
每一格的说法,原文里有没有依据?注明的出处(文件和行号)对不对?
只列出有问题的格子和原因。全部没问题就只回复"没有问题"。

回答:
{answer}

原文:
{evidence[:20000]}"""}], None)
    if "没有问题" in review.content[:20]:
        return answer, messages, stats
    # 有问题就把检查意见交回给智能体,让它继续查、修改回答
    messages += [{"role": "assistant", "content": answer},
                 {"role": "user", "content": "有人检查了你的回答,意见如下。需要的话继续查文档,然后给出修改后的完整回答。\n\n" + review.content}]
    revised, messages, more = loop(messages)
    ……

La vérification s'appuie sur « les textes d'origine trouvés », c'est-à-dire ce que les outils ont renvoyé, et non sur la mémoire du modèle. La leçon 6 du module précédent a montré qu'un juge qui juge de mémoire se trompe ; on le fait donc vérifier par rapport au matériau. En cas de problème, les remarques de vérification sont renvoyées à l'agent, qui peut continuer à consulter la documentation puis corriger sa réponse.

Code complet dans code/05-agents/planning_reflection.py.

Résultats

Chaque méthode exécutée une fois (les réponses sont toutes longues ; seuls les statistiques et les passages clés sont montrés ici) :

===== 直接做
  4 次模型调用,9 次工具调用,13155 词元,7 秒
===== 先列计划
  5 次模型调用,13 次工具调用,26086 词元,12 秒
===== 做完再检查
  7 次模型调用,14 次工具调用,50132 词元,17 秒

Faire directement donne déjà une réponse de bonne qualité. Pour la ligne HTTP/2, il a trouvé à la ligne 50 de http2.md le texte « HTTP/2 support is available on both Client and AsyncClient », avec une conclusion claire : « identique ». Pour les lignes délai et proxy, il indique honnêtement que les exemples de la documentation n'utilisent que httpx.Client, sans écriture pour AsyncClient, et qu'on ne peut donc que déduire que les deux sont identiques, « appui limité ». La nuance est très bien dosée : il ne présente pas une déduction comme un fait.

Un petit défaut : la première phrase de sa réponse est en anglais, « Based on the documentation, here is the comparison table ». Après avoir lu beaucoup de documentation en anglais, un agent dérive parfois dans la langue de réponse. Préciser « réponds en chinois » dans le prompt system l'évite.

Un plan d'abord a demandé 1 appel de modèle de plus, les appels d'outils sont passés de 9 à 13, les tokens ont doublé, et cela a pris 5 secondes de plus. Voici son plan :

1. 找 `Client` 的文档,定位它关于超时(timeout)的配置参数与说明。
2. 找 `AsyncClient` 的文档,定位它关于超时(timeout)的配置参数与说明,比对是否一致。
3. 分别在 `Client` 和 `AsyncClient` 文档中找代理(proxy/proxies)相关配置,比对。
4. 分别在 `Client` 和 `AsyncClient` 文档中找 HTTP/2 相关配置(如 http2 参数),比对。
5. 检查两者的基类/继承关系或 API 参考页,确认是否共用同一套初始化参数……

L'étape 5 du plan a apporté un peu de nouveau : il est allé voir api.md, a constaté que les listes de membres des deux classes sont presque identiques, seules close et aclose diffèrent, et s'en est servi pour étayer que « les deux partagent les mêmes paramètres de configuration ». Mais sa conclusion finale est la même qu'en faisant directement : HTTP/2 est clairement étayé, délai et proxy ne peuvent qu'être déduits. Deux fois plus cher, sans changement de fond dans la conclusion.

Faire, puis vérifier a trouvé de vrais problèmes. Les remarques de vérification ont signalé deux erreurs de source ; l'agent a continué à chercher, puis a indiqué les corrections dans sa réponse révisée :

### 本次更正的两处(评审意见成立)

1. 原标注 `advanced/timeouts.md:66-68`("`httpx.Timeout` 细调")有误:`:66-68` 只是 `httpx.Timeout(10.0, connect=60.0)` 与 `httpx.Client(timeout=timeout)` 的示例代码。`httpx.Timeout` 的细调说明实际在 `advanced/timeouts.md:41-68`(标题 `## Fine tuning the configuration` 在 `:41`)。……
2. 原标注 `advanced/transports.md:223` 不能作为 `timeout` 构造参数的出处:该行是 `httpx.HTTPTransport(proxy=proxy, **kwargs)`,只涉及 transport 的 `proxy`/`**kwargs`,与客户端 `timeout` 无关。已删除该引用。

J'ai vérifié dans timeouts.md : la ligne 41 est bien le titre « ## Fine tuning the configuration », et les lignes 66 à 68 ne sont bien que du code d'exemple. La première correction est juste. Il a aussi supprimé une citation sans rapport de la première version. Ce genre de « source mal indiquée », un lecteur le repère difficilement lui-même, et c'est justement ce que la vérification repère le mieux.

Le prix : 7 appels de modèle, 50 000 tokens, presque 4 fois plus qu'en faisant directement. L'étape de vérification doit contenir tous les textes trouvés, c'est la principale raison de son coût.

Mais la réponse révisée présente aussi un changement notable : la conclusion passe de « HTTP/2 identique, délai et proxy seulement déduits » à un titre bien visible, « les trois se configurent de façon exactement identique ». Le texte précise encore à la fin que délai et proxy sont déduits, mais le ton du titre est plus fort que les preuves. La vérification a corrigé les sources, tout en rendant la formulation de la conclusion plus affirmative. Une réponse révisée doit, elle aussi, être relue.

Quand cela vaut la peine

Une seule expérience ne permet pas de trancher, mais avec ce résultat, voici mon expérience :

Un plan d'abord convient aux tâches de nombreuses étapes où l'on oublie facilement une partie, par exemple « modifier ces 10 fichiers ». Le plan aide le modèle à se souvenir de ce qui reste à faire. Sur une tâche comme celle de cette leçon, bouclée en trois à cinq étapes, il apporte peu. Autre usage : le montrer à un humain. Présenter d'abord le plan à l'utilisateur et faire confirmer la direction avant d'exécuter coûte bien moins cher que de découvrir après coup qu'on s'est trompé de direction.

Faire, puis vérifier convient aux tâches dont le résultat comporte facilement des erreurs de détail, et où ces erreurs coûtent cher, par exemple les sources citées, les chiffres, le code. Pour la vérification, donnez toujours le matériau d'origine, pour qu'il compare avec lui plutôt que de se fier à sa mémoire. C'est cher, donc généralement fait une seule fois, sur le résultat final, pas à chaque étape.

Faire directement est un choix par défaut raisonnable pour la plupart des tâches. Commencez par faire directement, construisez une évaluation, voyez où se situent surtout les erreurs, puis ajoutez planification ou vérification de façon ciblée.

Exercices

  1. Ajoutez « réponds en chinois » (ou dans votre langue) au SYSTEM de planning_reflection.py, relancez, et voyez si la première phrase de « faire directement » est encore en anglais.
  2. Modifiez le prompt de l'étape de vérification pour ne donner que la réponse, sans les textes d'origine (« vérifie si cette réponse contient des erreurs »), et relancez. Comment évolue la qualité des remarques de vérification ?
  3. Exécutez chaque méthode 3 fois, en notant à chaque fois le nombre de tokens et les modifications apportées. Un seul essai s'écarte-t-il beaucoup de la moyenne de plusieurs ?

Auto-test

1. Quand on demande au modèle de « planifier puis exécuter », pourquoi lui dire qu'il « peut ajuster le plan s'il ne convient pas » ?

Le plan est établi avant d'avoir consulté quoi que ce soit ; ses étapes sont des suppositions. Les informations trouvées pendant l'exécution peuvent montrer que le plan d'origine pose problème ; le suivre à la lettre mènerait dans la mauvaise direction.

2. Quand on fait vérifier au modèle sa propre réponse, pourquoi lui donner aussi les textes d'origine trouvés ?

Avec la seule réponse, le modèle ne peut juger qu'avec sa propre mémoire, qui est peut-être justement la source de l'erreur ; le juge du module précédent a commis cette erreur. Avec les textes d'origine, il peut comparer point par point et trouver des problèmes concrets, comme une source mal indiquée ou une affirmation sans appui.

3. Dans l'expérience de cette leçon, l'auto-vérification a trouvé de vraies erreurs. Faut-il donc ajouter une auto-vérification à chaque tâche ?

Pas forcément. Dans cette leçon, l'auto-vérification a coûté presque 4 fois plus d'argent et plus de 2 fois plus de temps. Elle convient aux tâches où les erreurs coûtent cher et où les erreurs de détail sont fréquentes, et se fait généralement une seule fois sur le résultat final. De plus, une réponse révisée peut introduire de nouveaux problèmes, comme ici une formulation plus affirmative que les preuves.

Questions et discussion

Bloqué sur cette leçon ? Posez votre question ici. Et si vous pouvez répondre à quelqu'un, n'hésitez pas.

Une question rapporte 3 points, une réponse 6. Les messages paraissent après vérification.

Chargement de la discussion…