Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 17,657 Bytes
970eef1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
#!/usr/bin/env python3
"""
Script pour tester les résultats de Yourbench et vérifier les datasets sur le Hub Hugging Face.
"""
import os
import sys
import json
import argparse
import requests
import tempfile
from datetime import datetime
from typing import Dict, List, Any, Optional, Tuple
# Vérifier si les bibliothèques nécessaires sont installées
try:
from dotenv import load_dotenv
from huggingface_hub import HfApi, DatasetInfo, ModelInfo
from loguru import logger
import pandas as pd
except ImportError:
print("Installation des dépendances...")
import subprocess
subprocess.run(["pip", "install", "python-dotenv", "huggingface_hub", "loguru", "pandas", "pyarrow"], check=True)
from dotenv import load_dotenv
from huggingface_hub import HfApi, DatasetInfo, ModelInfo
from loguru import logger
import pandas as pd
# Charger les variables d'environnement depuis .env
load_dotenv()
# Configuration de la journalisation
logger.remove()
logger.add(sys.stderr, format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <level>{message}</level>")
logger.add("yourbench_tests.log", rotation="10 MB", retention="1 week")
def configure_argument_parser() -> argparse.ArgumentParser:
"""Configure le parser d'arguments."""
parser = argparse.ArgumentParser(description="Tester les résultats de Yourbench et vérifier les datasets")
parser.add_argument("--dataset", type=str, help="Nom du dataset à vérifier (sans le nom de l'organisation)")
parser.add_argument("--org", type=str, default=os.environ.get("HF_ORGANIZATION", "yourbench"),
help="Organisation Hugging Face (défaut: valeur de HF_ORGANIZATION dans .env ou 'yourbench')")
parser.add_argument("--verbose", "-v", action="store_true", help="Afficher des informations détaillées")
return parser
class YourbenchTester:
"""Classe pour tester les résultats et datasets de Yourbench."""
def __init__(self, organization: str, verbose: bool = False):
"""Initialise le testeur Yourbench.
Args:
organization: Nom de l'organisation sur Hugging Face
verbose: Afficher des informations détaillées
"""
self.organization = organization
self.verbose = verbose
self.hf_token = os.environ.get("HF_TOKEN")
if not self.hf_token:
logger.error("Variable d'environnement HF_TOKEN non trouvée dans le fichier .env")
sys.exit(1)
self.api = HfApi(token=self.hf_token)
logger.info(f"Initialisation du testeur pour l'organisation: {organization}")
def test_dataset_exists(self, dataset_name: str) -> Optional[DatasetInfo]:
"""Vérifie si un dataset existe sur le Hub.
Args:
dataset_name: Nom du dataset à vérifier
Returns:
Informations sur le dataset s'il existe, None sinon
"""
full_dataset_name = f"{self.organization}/{dataset_name}"
logger.info(f"Vérification de l'existence du dataset: {full_dataset_name}")
try:
dataset_info = self.api.dataset_info(full_dataset_name)
logger.success(f"Dataset {full_dataset_name} trouvé!")
if self.verbose:
logger.info(f"ID: {dataset_info.id}")
logger.info(f"Dernière modification: {dataset_info.lastModified}")
logger.info(f"SHA: {dataset_info.sha}")
return dataset_info
except Exception as e:
logger.error(f"Impossible de trouver le dataset {full_dataset_name}: {str(e)}")
return None
def analyze_dataset_content(self, dataset_name: str) -> Tuple[bool, Dict[str, Any]]:
"""Analyse le contenu d'un dataset.
Args:
dataset_name: Nom du dataset à analyser
Returns:
Tuple contenant un booléen indiquant si l'analyse a réussi et un dictionnaire de statistiques
"""
full_dataset_name = f"{self.organization}/{dataset_name}"
logger.info(f"Analyse du contenu du dataset: {full_dataset_name}")
stats = {
"fichiers": 0,
"taille_totale": 0,
"fichiers_json": 0,
"fichiers_parquet": 0,
"a_questions": False,
"nb_questions": 0,
"structure_parquet": {},
"types_documents": set()
}
try:
# Lister les fichiers dans le dataset
files = self.api.list_repo_files(full_dataset_name, repo_type="dataset")
stats["fichiers"] = len(files)
if self.verbose:
logger.info(f"Fichiers trouvés dans le dataset: {len(files)}")
for file in files[:10]: # Limiter à 10 fichiers pour éviter un affichage trop verbeux
logger.info(f" - {file}")
if len(files) > 10:
logger.info(f" ... et {len(files) - 10} fichiers supplémentaires")
# Vérifier la présence de fichiers questions
question_files = [f for f in files if "question" in f.lower() and f.endswith(".json")]
stats["fichiers_json"] = len([f for f in files if f.endswith(".json")])
# Vérifier les fichiers Parquet qui sont utilisés par Yourbench
parquet_files = [f for f in files if f.endswith(".parquet")]
stats["fichiers_parquet"] = len(parquet_files)
if parquet_files:
logger.info(f"Fichiers Parquet trouvés: {len(parquet_files)}")
# Analyser un échantillon de fichiers Parquet
for parquet_file in parquet_files[:3]: # Limiter à 3 fichiers pour l'analyse
category = parquet_file.split('/')[0] if '/' in parquet_file else "unknown"
logger.info(f"Analyse du fichier Parquet: {parquet_file} (catégorie: {category})")
try:
# Télécharger le fichier Parquet
temp_file = self.api.hf_hub_download(
repo_id=full_dataset_name,
filename=parquet_file,
repo_type="dataset"
)
# Lire le fichier Parquet avec pandas
df = pd.read_parquet(temp_file)
# Ajouter des statistiques
stats["structure_parquet"][category] = {
"colonnes": list(df.columns),
"nb_lignes": len(df),
"exemple": df.iloc[0].to_dict() if len(df) > 0 else {}
}
# Vérifier si ce fichier contient des questions
if any(col for col in df.columns if "question" in col.lower()):
stats["a_questions"] = True
question_col = next(col for col in df.columns if "question" in col.lower())
stats["nb_questions"] = len(df)
# Récupérer un exemple de question
if len(df) > 0 and question_col in df.columns:
logger.info(f"Exemple de question: {df[question_col].iloc[0][:100]}...")
# Identifier les types de documents si disponible
if "doc_type" in df.columns and len(df) > 0:
doc_types = df["doc_type"].unique()
stats["types_documents"].update(doc_types)
except Exception as e:
logger.warning(f"Erreur lors de l'analyse du fichier {parquet_file}: {str(e)}")
# Convertir le set en liste pour la sérialisation JSON
stats["types_documents"] = list(stats["types_documents"])
if question_files:
stats["a_questions"] = True
# Analyser un fichier de questions pour comprendre sa structure
sample_file = question_files[0]
content = self.api.hf_hub_download(
repo_id=full_dataset_name,
filename=sample_file,
repo_type="dataset"
)
with open(content, 'r') as f:
data = json.load(f)
if isinstance(data, list):
stats["nb_questions"] = len(data)
elif isinstance(data, dict) and "questions" in data:
stats["nb_questions"] = len(data["questions"])
logger.success(f"Fichiers de questions trouvés: {len(question_files)}")
logger.info(f"Exemple de fichier analysé: {sample_file}")
logger.info(f"Nombre de questions trouvées: {stats['nb_questions']}")
return True, stats
except Exception as e:
logger.error(f"Erreur lors de l'analyse du dataset {full_dataset_name}: {str(e)}")
return False, stats
def check_evaluation_results(self, dataset_name: str) -> bool:
"""Vérifie s'il existe des résultats d'évaluation pour ce dataset.
Args:
dataset_name: Nom du dataset à vérifier
Returns:
True si des résultats d'évaluation existent, False sinon
"""
logger.info(f"Recherche de résultats d'évaluation pour le dataset: {dataset_name}")
try:
# Lister tous les datasets de l'organisation
datasets = self.api.list_datasets(author=self.organization)
# Chercher les datasets d'évaluation
eval_datasets = [ds for ds in datasets if ds.id.startswith(f"{self.organization}/evaluation-")]
if self.verbose:
logger.info(f"Datasets d'évaluation trouvés: {len(eval_datasets)}")
for ds in eval_datasets[:5]:
logger.info(f" - {ds.id}")
# Vérifier si le dataset spécifié est mentionné dans les évaluations
for eval_ds in eval_datasets:
try:
# Télécharger le README pour voir si le dataset est mentionné
readme_path = self.api.hf_hub_download(
repo_id=eval_ds.id,
filename="README.md",
repo_type="dataset"
)
with open(readme_path, 'r') as f:
readme_content = f.read()
if dataset_name in readme_content:
logger.success(f"Résultats d'évaluation trouvés dans: {eval_ds.id}")
return True
except:
continue
logger.warning(f"Aucun résultat d'évaluation trouvé pour le dataset: {dataset_name}")
return False
except Exception as e:
logger.error(f"Erreur lors de la recherche de résultats d'évaluation: {str(e)}")
return False
def check_model_performances(self, dataset_name: str) -> Dict[str, float]:
"""Vérifie les performances des modèles sur le dataset spécifié.
Args:
dataset_name: Nom du dataset à vérifier
Returns:
Dictionnaire des performances des modèles (model_name -> score)
"""
logger.info(f"Vérification des performances des modèles sur le dataset: {dataset_name}")
performances = {}
try:
# Cette partie est spéculative car nous ne connaissons pas la structure exacte
# des résultats. Une approche possible serait de chercher des fichiers JSON
# contenant des métriques dans les datasets d'évaluation.
# Chercher les datasets d'évaluation
datasets = self.api.list_datasets(author=self.organization)
eval_datasets = [ds for ds in datasets if ds.id.startswith(f"{self.organization}/evaluation-")]
for eval_ds in eval_datasets:
try:
files = self.api.list_repo_files(eval_ds.id, repo_type="dataset")
result_files = [f for f in files if "result" in f.lower() and f.endswith(".json")]
for result_file in result_files:
file_path = self.api.hf_hub_download(
repo_id=eval_ds.id,
filename=result_file,
repo_type="dataset"
)
with open(file_path, 'r') as f:
results = json.load(f)
# Analyse basique des résultats (à adapter selon la structure réelle)
if "model_name" in results and "metrics" in results:
model_name = results["model_name"]
metrics = results["metrics"]
# Prendre la première métrique trouvée comme score
if metrics and isinstance(metrics, dict):
first_metric = list(metrics.keys())[0]
performances[model_name] = metrics[first_metric]
except:
continue
if performances:
logger.success(f"Performances trouvées pour {len(performances)} modèles")
for model, score in performances.items():
logger.info(f" - {model}: {score}")
else:
logger.warning("Aucune performance de modèle trouvée")
return performances
except Exception as e:
logger.error(f"Erreur lors de la vérification des performances: {str(e)}")
return {}
def main():
"""Fonction principale."""
parser = configure_argument_parser()
args = parser.parse_args()
if not args.dataset:
logger.error("Veuillez spécifier un dataset avec --dataset")
parser.print_help()
return
# Créer le testeur
tester = YourbenchTester(args.org, args.verbose)
# 1. Vérifier l'existence du dataset
dataset_info = tester.test_dataset_exists(args.dataset)
if not dataset_info:
logger.error(f"Le dataset {args.org}/{args.dataset} n'existe pas ou n'est pas accessible")
return
# 2. Analyser le contenu du dataset
success, stats = tester.analyze_dataset_content(args.dataset)
if success:
logger.info("\n=== Statistiques du dataset ===")
logger.info(f"Nombre de fichiers: {stats['fichiers']}")
logger.info(f"Fichiers JSON: {stats['fichiers_json']}")
logger.info(f"Fichiers Parquet: {stats['fichiers_parquet']}")
logger.info(f"Contient des questions: {'Oui' if stats['a_questions'] else 'Non'}")
if stats['a_questions']:
logger.info(f"Nombre de questions: {stats['nb_questions']}")
if 'types_documents' in stats and stats['types_documents']:
logger.info(f"Types de documents: {', '.join(stats['types_documents'])}")
# Afficher la structure des fichiers Parquet
if 'structure_parquet' in stats and stats['structure_parquet']:
logger.info("\n=== Structure des fichiers Parquet ===")
for category, info in stats['structure_parquet'].items():
logger.info(f"\nCatégorie: {category}")
logger.info(f"Nombre de lignes: {info['nb_lignes']}")
logger.info(f"Colonnes: {', '.join(info['colonnes'])}")
if args.verbose and 'exemple' in info and info['exemple']:
logger.info("\nExemple de ligne:")
for key, value in info['exemple'].items():
# Tronquer les valeurs trop longues
if isinstance(value, str) and len(value) > 100:
value = value[:100] + "..."
logger.info(f" {key}: {value}")
# 3. Vérifier s'il existe des résultats d'évaluation
has_evaluations = tester.check_evaluation_results(args.dataset)
if has_evaluations:
# 4. Vérifier les performances des modèles
performances = tester.check_model_performances(args.dataset)
if performances:
logger.info("\n=== Classement des modèles ===")
# Trier les modèles par score (du plus élevé au plus bas)
sorted_models = sorted(performances.items(), key=lambda x: x[1], reverse=True)
for i, (model, score) in enumerate(sorted_models, 1):
logger.info(f"{i}. {model}: {score:.4f}")
logger.success("Test terminé !")
if __name__ == "__main__":
main() |