Conception de l'infrastructure pour réduire les coûts de proxy et les jetons lors du déploiement en production d'Agent-Reach
2026년 6월 19일
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
Les agents basés sur Agent-Reach qui fonctionnaient parfaitement sur une CLI locale se heurtent à des obstacles dès qu'ils sont déployés sur un serveur de production. Lorsqu'ils sont inondés de dizaines de milliers de requêtes de scraping, ils se font bloquer par les pare-feux CDN comme Cloudflare, entraînant des interdictions d'IP en série. Cependant, se limiter à des proxys résidentiels payants rend les coûts de bande passante intenables. De plus, injecter du HTML brut directement dans un LLM peut faire exploser le contexte et entraîner des factures de jetons astronomiques. Pour résoudre ces problèmes, une architecture de routage dynamique et un pipeline de prétraitement sont indispensables.
Exploiter Agent-Reach sans précaution peut coûter des milliers de dollars en proxys résidentiels. Dans un système traitant 100 000 requêtes par jour avec une taille moyenne de page de 150 Ko et un taux d'échec atteignant 50 %, le transfert de données mensuel atteint 675 Go. Les proxys résidentiels premium comme Bright Data ou Oxylabs coûtent entre 4 et 8 dollars par Go. Faire passer tout le trafic par ces services ferait grimper la facture mensuelle à 5 400 dollars.
En déployant Scrapoxy, un agrégateur de proxy open source, en tant que super-proxy basé sur des conteneurs Docker, vous pouvez contrôler les coûts d'infrastructure tout en conservant un point de terminaison unique. Commencez par créer un fichier docker-compose.yml à la racine du projet et définissez les images valkey/valkey:7.2-alpine et fabienvauchelles/scrapoxy:latest. Dans le conteneur Valkey, utilisez la commande --appendonly yes --requirepass [mot_de_passe] pour garantir la persistance de la mise en cache des identifiants. Après avoir configuré le nom d'utilisateur et le mot de passe dans les variables d'environnement de Scrapoxy, lancez les conteneurs avec la commande docker compose up -d. Cette configuration permet d'économiser plus de 200 dollars par mois en frais d'abonnement à des services payants.
Selon les politiques de sécurité de la plateforme cible, la rotation des IP doit être différenciée pour ne pas rompre les sessions. Pour les requêtes publiques en lecture seule ne nécessitant pas d'authentification, définissez un TTL agressif compris entre 30 secondes et 3 minutes pour forcer l'allocation d'une nouvelle IP à chaque fois via un mode round-robin. C'est une mesure pour éviter les blocages basés sur les seuils. En revanche, pour les plateformes nécessitant une authentification et le maintien de cookies de session (comme X ou Reddit), activez la fonction d'injection de cookies de Scrapoxy pour conserver le même nœud IP résidentiel pendant 5 à 10 minutes. Cela évite l'expiration de la session d'authentification due à un changement soudain de localisation géographique de l'IP.
Pour réduire davantage les coûts, optimisez le routage du trafic au niveau de la couche passerelle API NGINX. Dans le fichier de configuration NGINX (/etc/nginx/nginx.conf), définissez dans le bloc upstream des pools de proxys de centre de données à faible coût (comme DataImpulse, à environ 1 dollar par Go) et des pools de proxys résidentiels Scrapoxy séparément. Dans le bloc server, créez une location /fetch/generic/ pour rediriger le trafic HTML public à faible risque (flux RSS, recherche GitHub, etc.) vers les proxys de centre de données. Créez ensuite une location /fetch/social/ pour router uniquement les requêtes exigeantes vers les points de terminaison sociaux vers le backend Scrapoxy, tout en injectant les en-têtes nécessaires. Ce routage à deux voies évite le gaspillage de bande passante coûteuse des proxys résidentiels et réduit les coûts totaux de proxy jusqu'à 90 %.
Les données HTML brutes sont un amas d'éléments DOM redondants, de feuilles de style et de scripts en ligne. Si vous les injectez directement dans un LLM, vous consommez inutilement des jetons et diluez les résultats de l'inférence. Convertir la page web brute en Markdown avant de l'injecter dans la fenêtre de contexte permet de réduire la taille des données de 75 % à 90 %. Effectuer un nettoyage basé sur des expressions régulières et une sérialisation en Markdown lors de l'étape de prétraitement du pipeline permet d'économiser plus de 40 % sur la consommation de jetons de l'API LLM tout en prévenant les erreurs de dépassement de fenêtre.
Implémentez une fonction Python utilisant les composants Trafilatura et html2text pour prétraiter les données d'entrée. Lors de l'appel à la fonction trafilatura.extract(), utilisez l'option favor_recall=False pour exclure les barres latérales et les publicités, et ne conserver que le texte principal. En cas d'échec de l'extraction du bloc de contenu principal, insérez un code de secours utilisant un objet html2text.HTML2Text() avec ignore_images=True et body_width=0. Exécutez une routine de nettoyage avec des expressions régulières (re.sub) pour supprimer les balises restantes (<script>, <style>) et réduire les espaces blancs consécutifs dans le texte Markdown extrait afin de réduire la latence de réponse de l'agent.
Lors du découpage (chunking) de documents longs, remplacez le simple comptage de caractères par un algorithme de segmentation basé sur la similarité sémantique pour préserver le contexte. Calculez la similarité cosinus entre les vecteurs d'embedding de segments de texte divisés par phrase pour capturer les points de rupture sémantique.
Similarity(u, v) = rac{u cdot v}{\|u\| \|v\|}Après avoir calculé la distance entre les phrases adjacentes, déterminez les points de segmentation sémantique là où la différence de distance dépasse le 95e percentile de l'ensemble du document pour générer la liste des chunks. L'application du découpage sémantique plutôt que du découpage à longueur fixe empêche la perte d'informations liées à la fragmentation des données pertinentes et améliore la précision de la recherche d'informations par le LLM.
Les plateformes comme X ou LinkedIn imposent des limites de vitesse strictes. Les erreurs HTTP 429 ou 403 sont fréquentes. Si un processus d'application synchrone répète immédiatement les tentatives dans ces situations de défaillance temporaire, les ressources du serveur sont épuisées et le niveau de blocage IP augmente. Pour garantir la résilience du système, il est nécessaire de disposer d'un middleware de traitement d'exceptions asynchrone capable d'identifier la nature de l'exception et d'ajuster dynamiquement la charge imposée au serveur cible.
Lors de la conception de la classe de gestion des erreurs, séparez précisément les erreurs temporaires des erreurs permanentes. Les erreurs HTTP 429, 502, 503, 504, ou les messages contenant “timeout” ou “connection refused” doivent être classés comme erreurs temporaires et soumis à une nouvelle tentative. En revanche, les erreurs 401 ou 400 doivent être jugées permanentes et isolées immédiatement dans une Dead Letter Queue (DLQ). Pour les erreurs temporaires, appliquez un algorithme d'exponentiation avec backoff avec un jitter (gigue) aléatoire en millisecondes pour éviter le problème de “Thundering Herd” causé par des requêtes affluant en même temps. La formule de calcul du temps d'attente est la suivante :
En réglant le délai de base () à 30 secondes et en limitant le maximum () à 600 secondes, la troisième tentative garantit un temps d'attente distribué d'environ 240 secondes, contournant ainsi les politiques de blocage de la plateforme cible.
Pour bloquer les pannes en cascade où la défaillance ou le renforcement de la sécurité d'une plateforme spécifique paralyse tout le flux de travail, implémentez un modèle de “bulkhead” (cloisonnement) basé sur Redis dans la couche middleware. Au lieu d'une file d'attente mondiale unique, créez des listes Redis indépendantes séparées par domaine cible (queue:bulkhead:twitter, queue:bulkhead:reddit, queue:bulkhead:general). Allouez des limites de concurrence maximales différenciées pour les pools de workers consommant chaque file d'attente (par exemple, 3 pour Twitter, 25 pour le Web général). Pour gérer le calendrier des tentatives des tâches ayant échoué, écrivez une routine de traitement différé utilisant les “Sorted Sets” de Redis pour enregistrer le timestamp de retour comme score. Grâce à cette structure de cloisonnement, même en cas de blocage d'API sur un réseau social spécifique, seuls les workers concernés entrent en état d'attente, maintenant le taux de réussite global des tâches de recherche de l'agent au-dessus de 95 %.
Les données brutes récupérées aléatoirement sur divers sites web contiennent souvent des incohérences de dates ou des faits erronés, ce qui expose le LLM à des raisonnements biaisés. Avant de fournir du contexte à un modèle d'IA générative, il est nécessaire d'intégrer une couche de validation discrète à la fin du pipeline, capable de calculer la fiabilité du contenu des fichiers Markdown et de vérifier la cohérence numérique, afin de bloquer les phénomènes d'hallucination.
Concevez une classe de filtre déterministe qui calcule la validité temporelle des métadonnées collectées et les pondérations par source de plateforme. Excluez immédiatement les documents contenant des horodatages futurs par rapport à l'heure système ou des dates au format ISO non valides. Déclarez également un dictionnaire mappant les pondérations de confiance par source : GitHub reçoit 0,95, Wikipedia 0,90, tandis que les réseaux sociaux comme Reddit (0,50) ou Twitter (0,40) reçoivent des scores de base inférieurs. Ajoutez un bonus de pondération de 0,05 uniquement si le nom de l'auteur et le titre sont intacts dans le document, pour obtenir un score de confiance final. Les ressources d'information dont le score est inférieur à un seuil sont exclues dès l'étape d'assemblage du prompt LLM.
Pour garantir la qualité finale des données de sortie, exécutez un script de notation qui compare les candidats de réponse générés avec le contexte source :
\b\d+(?:\.\d+)?%?\b) pour effectuer une intersection entre l'ensemble des symboles numériques présents dans le dataset source et ceux de la phrase générée. Si des chiffres ou des unités monétaires arbitraires non présents dans la source sont détectés, déclenchez un drapeau d'incohérence numérique et demandez une réexécution via le middleware de routage.En couplant ces couches de validation multicouches, les problèmes de manipulation numérique et de citations erronées commis par les agents basés sur le crawling sont bloqués au niveau de l'architecture, garantissant que seuls les résultats de recherche entièrement vérifiés sont livrés à l'utilisateur final.