leaderboard-parser-agent / experiments /smolagent_parser.py
tfrere's picture
first commit
0821095
raw
history blame
7.91 kB
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
SmoLAgent Parser - Extrait le premier modèle de chaque leaderboard Hugging Face
en utilisant Playwright et smolagents.
"""
import json
import os
import asyncio
from pathlib import Path
from typing import List, Dict, Any, Optional
from dotenv import load_dotenv
from huggingface_hub import login
from playwright.async_api import async_playwright
from smolagents import CodeAgent
from smolagents.models import HfApiModel
from smolagents.tools import Tool
# Charger les variables d'environnement depuis le fichier .env
load_dotenv()
# Récupérer le token Hugging Face
hf_token = os.getenv("HUGGING_FACE_HUB_TOKEN")
# Charger les leaderboards depuis le fichier JSON
def load_leaderboards() -> List[str]:
"""Charger les URLs des leaderboards depuis le fichier JSON."""
with open("leaderboards.json", "r") as f:
return json.load(f)
# Définir un outil pour utiliser Playwright
class PlaywrightBrowserTool(Tool):
"""Outil pour interagir avec un navigateur web via Playwright."""
name = "browser"
description = "Outil pour interagir avec un navigateur web via Playwright."
inputs = {
"goto": {
"url": {
"type": "string",
"description": "L'URL vers laquelle naviguer"
}
},
"get_content": {},
"get_title": {},
"take_screenshot": {
"path": {
"type": "string",
"description": "Le chemin où enregistrer la capture d'écran"
}
},
"run_js": {
"script": {
"type": "string",
"description": "Le code JavaScript à exécuter dans le contexte de la page"
}
},
"wait_for": {
"selector": {
"type": "string",
"description": "Le sélecteur CSS à attendre"
},
"timeout": {
"type": "integer",
"description": "Le temps maximum d'attente en millisecondes"
}
},
"click": {
"selector": {
"type": "string",
"description": "Le sélecteur CSS de l'élément à cliquer"
}
},
"fill": {
"selector": {
"type": "string",
"description": "Le sélecteur CSS du champ de formulaire"
},
"value": {
"type": "string",
"description": "La valeur à remplir dans le champ de formulaire"
}
}
}
output_type = "any"
def __init__(self, page):
self.page = page
async def goto(self, url: str) -> str:
"""Naviguer vers une URL."""
await self.page.goto(url, wait_until="networkidle", timeout=60000)
return f"Navigué vers {url}"
async def get_content(self) -> str:
"""Obtenir le contenu HTML de la page."""
return await self.page.content()
async def get_title(self) -> str:
"""Obtenir le titre de la page."""
return await self.page.title()
async def take_screenshot(self, path: str = "screenshot.png") -> str:
"""Prendre une capture d'écran de la page."""
await self.page.screenshot(path=path)
return f"Capture d'écran enregistrée dans {path}"
async def run_js(self, script: str) -> Any:
"""Exécuter du JavaScript dans le contexte de la page."""
return await self.page.evaluate(script)
async def wait_for(self, selector: str, timeout: int = 30000) -> str:
"""Attendre qu'un élément correspondant au sélecteur apparaisse."""
await self.page.wait_for_selector(selector, timeout=timeout)
return f"Élément avec le sélecteur '{selector}' trouvé"
async def click(self, selector: str) -> str:
"""Cliquer sur un élément correspondant au sélecteur."""
await self.page.click(selector)
return f"Cliqué sur l'élément avec le sélecteur '{selector}'"
async def fill(self, selector: str, value: str) -> str:
"""Remplir un champ de formulaire."""
await self.page.fill(selector, value)
return f"Rempli '{value}' dans l'élément avec le sélecteur '{selector}'"
async def extract_first_model(url: str) -> Optional[Dict[str, Any]]:
"""
Extraire le premier modèle d'un leaderboard en utilisant un agent.
Args:
url: L'URL du leaderboard
Returns:
Un dictionnaire contenant les informations sur le premier modèle, ou None si l'extraction a échoué
"""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False) # Mettre à True pour la production
page = await browser.new_page()
try:
# Créer l'outil Playwright
browser_tool = PlaywrightBrowserTool(page)
# Créer l'agent
agent = CodeAgent(
tools=[browser_tool],
model=HfApiModel()
)
# Exécuter l'agent
prompt = f"""
Extrais les informations sur le premier modèle du leaderboard à l'URL suivante: {url}
Utilise l'outil browser pour naviguer sur la page et extraire les informations suivantes:
- Nom du modèle
- Score
- Position/rang
- Créateur/auteur
Retourne les informations sous forme de dictionnaire Python.
"""
result = await agent.run(prompt)
print(f"Résultat brut de l'agent: {result}")
# Essayer de parser le résultat comme un dictionnaire
try:
# L'agent peut retourner une représentation textuelle d'un dictionnaire
if isinstance(result, str):
# Essayer de trouver une structure de dictionnaire dans la chaîne
import re
dict_match = re.search(r'\{.*\}', result, re.DOTALL)
if dict_match:
dict_str = dict_match.group(0)
# Remplacer les guillemets simples par des guillemets doubles pour un JSON valide
dict_str = dict_str.replace("'", '"')
return json.loads(dict_str)
return {"raw_result": result}
return result
except Exception as e:
print(f"Erreur lors du parsing du résultat: {e}")
return {"raw_result": str(result)}
except Exception as e:
print(f"Erreur lors de l'extraction des données de {url}: {e}")
await page.screenshot(path=f"error_{url.replace('://', '_').replace('/', '_')}.png")
return {"error": str(e)}
finally:
await browser.close()
async def main():
"""Fonction principale pour traiter tous les leaderboards."""
# Se connecter à Hugging Face
if hf_token:
print("Token Hugging Face trouvé dans le fichier .env")
login(token=hf_token)
print("Connexion à Hugging Face réussie!")
else:
print("Erreur: Token Hugging Face non trouvé dans le fichier .env")
return
leaderboards = load_leaderboards()
results = {}
for url in leaderboards:
print(f"Traitement du leaderboard: {url}")
result = await extract_first_model(url)
results[url] = result
print(f"Résultat: {result}")
# Sauvegarder les résultats dans un fichier JSON
with open("results_smolagent.json", "w") as f:
json.dump(results, f, indent=2)
print(f"Résultats sauvegardés dans results_smolagent.json")
if __name__ == "__main__":
asyncio.run(main())