Passer au contenu principal
Les agents de recherche sont utiles lorsque vous voulez plus qu’un simple résultat de recherche ou qu’une réponse rapide d’un modèle. Un bon agent de recherche peut transformer un sujet large en requêtes de recherche, collecter des sources, extraire les preuves importantes, suivre les lacunes et rédiger un briefing sourcé que vous pouvez ensuite inspecter. Dans ce tutoriel, nous allons créer un agent de recherche privé en utilisant Python et l’API Venice. À la fin, vous disposerez d’une CLI capable de rechercher un sujet, de scraper des pages publiques en Markdown, de résumer des morceaux de source, d’exécuter des passes de recherche complémentaires conscientes des lacunes et de générer un rapport sourcé avec des artefacts JSONL locaux optionnels. Intéressé par l’implémentation complète du code ? Consultez le dépôt GitHub. Avant de continuer, vous aurez besoin d’une clé API Venice :

Ce que nous allons construire

L’implémentation de référence est un petit projet Python avec quelques parties clairement définies : Le flux ressemble à ceci : Pipeline de l'agent de recherche privé
  1. Demander à Venice de générer des requêtes de recherche diversifiées pour le sujet.
  2. Rechercher sur le web avec un ou plusieurs fournisseurs.
  3. Dédupliquer les URL avant de les lire.
  4. Utiliser l’endpoint de scraping de Venice pour transformer chaque page source publique en Markdown.
  5. Diviser les longues pages en chunks.
  6. Demander à Venice d’extraire les preuves de chaque chunk.
  7. Demander à Venice de transformer les preuves des chunks en notes de source.
  8. Identifier les lacunes de recherche et les problèmes d’équilibre des sources avant de générer des requêtes complémentaires.
  9. Demander à Venice de synthétiser le rapport final avec des citations de style notes de bas de page.
C’est « privé » au sens pratique où l’agent conserve l’orchestration, les notes de source, les artefacts et les rapports finaux sur votre machine. Venice gère les appels au modèle et le scraping via son API. L’implémentation de référence par défaut envoie toujours les requêtes de recherche à DuckDuckGo ou arXiv, donc considérez le choix du fournisseur comme partie intégrante de votre conception de confidentialité.

Configuration du projet

Le projet de référence utilise Python 3.13 et uv, mais le même code fonctionne aussi avec un environnement virtuel normal. Créez un nouveau projet :
Installez les dépendances :
Si vous préférez pip, créez un environnement virtuel et installez les mêmes paquets :
Créez un fichier .env pour le développement local :
Nous utilisons VENICE_MODEL afin que vous puissiez changer de modèle sans modifier le code. L’implémentation de référence utilise actuellement openai-gpt-55 par défaut, mais vous pouvez le remplacer par un autre modèle de chat disponible pour votre compte Venice.

Création des modèles de données

Avant d’écrire la logique de l’agent, nous allons définir les objets qui circulent dans le pipeline. Ces modèles facilitent la compréhension du reste du code car chaque source porte sa provenance : d’où elle vient, quelle requête l’a trouvée, quand elle a été récupérée et comment elle a été découpée en chunks. Créez research_agent/models.py :
Les champs importants ici sont canonical_url, content_hash et chunks. canonical_url permet à l’agent d’éviter de lire la même source plusieurs fois lorsque les résultats de recherche ne diffèrent que par des paramètres de suivi ou des fragments. content_hash aide à détecter les pages dupliquées même lorsqu’elles se trouvent à des URL différentes. chunks nous permet de résumer de longues pages en petits morceaux au lieu de perdre des preuves utiles à cause des limites de contexte. Ajoutez les fonctions utilitaires sous les dataclasses :
Le chunking est délibérément simple ici : des chunks de taille fixe en caractères avec chevauchement. C’est suffisant pour un agent de recherche de démonstration car l’endpoint de scraping de Venice renvoie du Markdown, qui est généralement beaucoup plus propre que du HTML brut. Pour la recherche en production sur de longs documents techniques, vous pouvez améliorer cela en découpant selon les titres, les paragraphes ou le nombre de tokens.

Construction du client Venice

Ensuite, nous allons créer un petit client Venice. Vous pourriez utiliser le SDK Python d’OpenAI pour les chat completions car Venice est compatible OpenAI, mais l’implémentation de référence utilise directement httpx afin que le même client puisse appeler l’endpoint POST /augment/scrape de Venice. Créez research_agent/venice.py :
L’utilitaire from_env() empêche les secrets de figurer dans votre code source. Il rend également le développement local pratique car python-dotenv peut charger VENICE_API_KEY et VENICE_MODEL depuis .env. Maintenant, ajoutez les chat completions :
Pour le rapport final, nous voulons utiliser le streaming car les rapports approfondis peuvent prendre beaucoup plus de temps (car ils produiront beaucoup plus de texte). Cela peut entraîner des problèmes de timeout pour les requêtes où la production de la sortie finale peut prendre extrêmement longtemps. En utilisant le streaming, nous pouvons éliminer ce problème et rendre la requête plus résistante aux échecs de timeout :
Ensuite, ajoutez le scraping :
L’endpoint de scraping de Venice accepte une URL accessible publiquement et renvoie la page en Markdown. Cela signifie que le modèle n’a pas besoin d’analyser du HTML brut, et vos prompts d’extraction de source peuvent travailler avec du texte plus propre. L’utilitaire restant gère les retries et le parsing des réponses :
Le dépôt complet inclut également un utilitaire robuste _post_chat_stream() qui lit les server-sent events des chat completions en streaming. Vous pouvez commencer sans streaming, puis l’ajouter une fois que le reste du flux de recherche fonctionne.

Ajout des fournisseurs de recherche

La couche de recherche a deux tâches : trouver les URL sources et récupérer ces URL via le scraper Venice. L’implémentation de référence utilise l’endpoint HTML de DuckDuckGo pour la recherche web générale et l’API Atom d’arXiv pour les papiers. Créez research_agent/web.py :
Maintenant, ajoutez DuckDuckGo :
Et arXiv :
La classe WebSearch coordonne les fournisseurs et récupère les pages :
L’implémentation de référence complète ajoute des retries, des délais de requête au niveau de l’hôte et des erreurs plus claires. Cela vaut la peine d’être conservé car les agents de recherche passent beaucoup de temps à gérer des pages qui bloquent l’automatisation, redirigent de manière inattendue ou renvoient des erreurs transitoires. Ajoutez les petits utilitaires de fournisseurs en bas :

Écriture des artefacts locaux

Pour les workflows de recherche, l’auditabilité est importante. Si le rapport final dit quelque chose de surprenant, vous devriez pouvoir inspecter quelle source y a mené. Créez research_agent/artifacts.py :
Cela écrit un objet JSON par ligne, ce qui rend les artefacts faciles à ajouter, à inspecter et à traiter avec des outils en ligne de commande par la suite.

Construction de l’agent de recherche

Maintenant que nous avons Venice, la recherche, les modèles et les artefacts, nous pouvons construire l’agent lui-même. Créez research_agent/agent.py :
Le system prompt est le garde-fou comportemental principal. Nous ne voulons pas que le modèle produise un rapport au son impressionnant à partir de sa mémoire. Nous voulons qu’il utilise le matériel source et signale les incertitudes lorsque les preuves sont minces. Nous avons également besoin de deux dataclasses finales dans models.py si vous ne les avez pas encore ajoutées :
Ensuite, définissez le ResearchAgent :
La méthode run() coordonne les passes de recherche :
Les deux ensembles seen_* sont ce qui empêche l’agent de perdre du temps sur des sources dupliquées. La déduplication d’URL détecte les liens répétés. La déduplication par hachage de contenu détecte les miroirs, les articles syndiqués et les pages qui redirigent vers le même contenu final.

Planification des recherches initiales et complémentaires

Le premier appel au modèle transforme le sujet en requêtes de recherche :
Après chaque passe de recherche, l’agent mis à jour effectue une étape d’analyse des lacunes plus délibérée. Il examine les notes actuelles, compte les clusters de sources par domaine, demande à Venice quelle couverture est manquante, écrit ces lacunes dans les artefacts, puis utilise les requêtes résultantes pour la passe suivante. Boucle d'analyse des lacunes Commencez par suivre l’équilibre des sources :
Cela donne à l’agent un moyen simple de remarquer la capture par cluster de sources. Si toutes les sources proviennent d’une seule entreprise, d’un seul framework ou d’un seul domaine, les requêtes complémentaires devraient délibérément élargir l’ensemble des sources au lieu d’en collecter davantage du même type. Utilisez maintenant ces informations d’équilibre lors de la création des recherches complémentaires :
La nouvelle implémentation de référence enveloppe cela dans _gap_follow_up_queries(), qui demande à Venice de renvoyer à la fois les enregistrements de lacunes et les requêtes :
Lorsque --artifacts est activé, ces enregistrements sont écrits dans research_gaps.jsonl. Cela vous donne une trace d’audit utile pour comprendre pourquoi l’agent a recherché une requête particulière en deuxième passe. Le parseur doit être tolérant. Si le modèle renvoie un JSON mal formé, l’agent revient au sujet original :
Ce modèle vaut la peine d’être utilisé partout dans le code d’agent : demander une sortie structurée, la parser et fournir un fallback simple lorsque la sortie n’est pas utilisable.

Lecture et résumé des sources

Maintenant, nous collectons les notes de source. L’agent recherche chaque requête, récupère chaque résultat via le scraping Venice, découpe le Markdown en chunks et résume les preuves utiles.
Les échecs individuels de recherche et de récupération ne devraient pas arrêter l’exécution entière. Le web public est désordonné. Certaines pages bloquent le scraping, certaines renvoient des PDF, certaines sont indisponibles et certaines redirigent vers des endroits inattendus. Un agent de recherche devrait continuer à avancer et enregistrer ce qui a échoué. Voici la méthode de lecture de source :
Pour chaque chunk de source, demandez à Venice un court résumé des preuves et des citations exactes :
Puis condensez les résumés de chunks en une note de source :
Cette résumé en deux étapes est ce qui rend l’agent plus fiable qu’un simple script « résumer ces URL ». Le modèle lit d’abord les chunks de la source, puis écrit une note au niveau de la source à partir de ces éléments de preuve extraits.

Rédaction du rapport final

Une fois que l’agent dispose des notes de source, il peut rédiger le rapport. Commencez par un rédacteur de rapport en une seule passe :
L’implémentation de référence va plus loin pour les rapports approfondis : elle demande à Venice un plan, rédige chaque section du rapport séparément, puis demande une passe d’édition finale pour assembler le rapport terminé et convertir les ID de source internes en citations de style notes de bas de page. Cette approche par étapes est utile lorsque vous voulez une sortie de recherche en long format car un seul prompt géant compresse souvent trop d’informations. Les prompts mis à jour orientent également le rapport vers une étude large et sourcée plutôt qu’un mince guide de décision. Si la base de sources est biaisée vers un cluster, le prompt de l’éditeur indique à Venice de reconnaître ce biais et de ne pas le présenter comme représentatif de l’ensemble du domaine. Ajoutez les utilitaires de digest :
Enfin, ajoutez l’enregistrement des erreurs :
À ce stade, la boucle de recherche principale est en place.

Ajout de la CLI

Nous avons maintenant besoin d’un point d’entrée en ligne de commande. Créez main.py :
La CLI expose les paramètres que vous ajusterez réellement pendant la recherche : Maintenant, reliez le tout :
Cela nous donne une CLI de recherche locale fonctionnelle.

Exécution de l’agent

Exécutez une passe de recherche rapide :
Écrivez le rapport dans un fichier Markdown :
Utilisez plus de sources et plusieurs fournisseurs :
Choisissez le style du rapport final :
Utilisez brief pour un briefing concis sourcé, standard pour une étude plus complète et deep pour le workflow par étapes plan/section/éditeur. Enregistrez des artefacts auditables :
Lorsque les artefacts sont activés, vous verrez des fichiers comme :
Ces fichiers sont utiles lorsque vous voulez comprendre comment l’agent est arrivé à une conclusion. Par exemple, source_notes.jsonl montre les preuves de source résumées, research_gaps.jsonl montre pourquoi des recherches complémentaires ont été générées, et errors.jsonl montre les pages qui ont échoué pendant la recherche, le scraping ou le résumé.

Notes sur la confidentialité et la fiabilité

Un agent de recherche touche à plusieurs systèmes, il est donc utile d’être précis sur ce qui va où : Limites de données de l'agent de recherche privé Si vous voulez garder une plus grande partie du chemin de recherche à l’intérieur de Venice, vous pouvez adapter la couche de fournisseurs pour appeler l’endpoint POST /augment/search de Venice au lieu d’interroger directement DuckDuckGo. L’implémentation de référence utilise des fournisseurs publics légers afin que la démo reste facile à exécuter et à comprendre. Pour la fiabilité, gardez ces valeurs par défaut prudentes :
  • Utilisez des retries pour les appels à Venice et les requêtes web.
  • Ajoutez un petit --request-delay si vous lisez de nombreuses pages du même hôte.
  • Plafonnez --max-sources pour que les sujets larges ne s’exécutent pas indéfiniment.
  • Enregistrez --artifacts pour les rapports importants afin de pouvoir auditer la sortie finale.
  • Traitez le rapport comme un briefing, pas comme une vérité absolue. Suivez les citations jusqu’à la source originale lorsque la précision est importante.

Tester les composants

Vous n’avez pas besoin de requêtes web en direct ni d’appels Venice pour tester la plupart du système. Le dépôt de référence utilise de fausses classes Venice et web pour tester la boucle de recherche, le comportement de déduplication, les artefacts et les prompts de rapport. Un premier test utile est la canonicalisation des URL :
Testez ensuite que le contenu dupliqué est ignoré :
Les faux rendent les tests d’agent beaucoup plus rapides et moins instables. Vous pouvez vérifier la logique d’orchestration sans dépendre de résultats de recherche en direct, des conditions du réseau ou de la sortie du modèle.

Benchmarking

De nombreux fournisseurs d’IA ont maintenant leurs propres workflows de recherche approfondie, donc le dépôt de référence inclut un benchmark simple comparé à l’outil Deep Research de Perplexity. Les deux agents ont été chargés de rédiger un rapport sur l’architecture des frameworks d’agents IA, puis les rapports générés ont été commités dans le dépôt GitHub. Ceci n’est pas censé être un benchmark formel. C’est une façon pratique d’inspecter la structure du rapport, la couverture des sources, la qualité des citations et de voir si l’agent se concentre trop sur un cluster de sources. C’est aussi pour cela que l’implémentation mise à jour suit research_gaps.jsonl et l’équilibre des sources avant les recherches complémentaires.

Étendre cet exemple

Une fois que l’agent de base fonctionne, voici des moyens pratiques de l’améliorer :
  • Ajouter un fournisseur de recherche Venice en utilisant POST /augment/search.
  • Stocker les rapports et les artefacts dans une petite base de données SQLite au lieu de fichiers JSONL.
  • Ajouter des allowlists ou blocklists de sources pour les domaines de recherche de confiance.
  • Ajouter le support PDF en combinant le scraping Venice avec l’analyse de documents pour les sources qui n’exposent pas de HTML propre.
  • Ajouter un ensemble d’évaluation de sujets et de types de sources attendus afin de pouvoir comparer la qualité de la recherche après des modifications de prompts.
  • Ajouter une étape de relecture qui demande à Venice de trouver les affirmations non étayées dans le rapport final avant de l’enregistrer.
La plus grosse amélioration concerne généralement la sélection des sources. La génération de requêtes aide, mais vous pouvez également améliorer la qualité en privilégiant les sources primaires, les documents de normes, les docs officielles, les papiers, les changelogs et les pages de jeux de données plutôt que les résumés à faible signal.

Pour finir

Merci d’avoir lu ! J’espère que cela vous a aidé à créer un agent de recherche privé pratique avec Python et l’API Venice. Le modèle utile ici n’est pas seulement « demander à un modèle de rechercher quelque chose ». C’est de décomposer la recherche en étapes auditables : planifier les recherches, collecter les sources, extraire les preuves, écrire des notes de source, suivre les lacunes et synthétiser avec des citations. En gardant ces étapes explicites, nous obtenons un workflow de recherche plus facile à inspecter, à tester et à améliorer au fil du temps.