Skip to content

Evref-BL/benchmark-GraphRag

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

benchmark-graphRag

Benchmark pour évaluer la capacité d’un GraphRAG à localiser les classes Java impactées à partir de descriptions d’issues GitHub.

Le workflow est en 2 étapes:

  1. Miner un repository GitHub pour construire un dataset Issue -> MRs merged -> impacted files.
  2. Exécuter GraphRAG sur chaque issue retenue et calculer precision, recall, F1.

Objectif

À partir d’une issue (titre + description), retrouver les classes Java effectivement modifiées dans les merge requests associées à cette issue.

La vérité terrain est dérivée des fichiers modifiés dans les PR mergées liées à l’issue.

Structure du projet

benchmark-graphRag/
├── scripts/
│   ├── mine_github_issues.py
│   ├── evaluator_core.py
│   ├── evaluate_graphrag_benchmark.py
│   ├── evaluate_llm_api_benchmark.py
│   ├── evaluate_manual_input_benchmark.py
│   └── export_benchmark_queries.py
├── mined_projects/              # sorties JSON (ignoré par git)
├── evaluation_results/          # rapports evaluator (ignoré par git)
├── queries/                     # queries LLM exportées (ignoré par git)
├── .env.github                  # token GitHub local (ignoré par git)
└── README.md

Prérequis

  • Python 3.10+
  • uv (pour lancer GraphRAG)
  • Un projet GraphRAG déjà indexé, avec un dossier output exploitable.
  • Optionnel mais fortement recommandé: un token GitHub (sinon rate limits API très bas).

Architecture Evaluators

Les évaluateurs reposent sur une base commune:

  • BaseBenchmarkEvaluator dans scripts/evaluator_core.py gère le pipeline séquentiel complet (chargement benchmark, filtrage, prompts, métriques, rapport).
  • evaluate_graphrag_benchmark.py est une spécialisation GraphRAG (appel uv run ... graphrag query).
  • evaluate_llm_api_benchmark.py est une spécialisation API LLM (Ollama/OpenAI/Mistral).

Configuration du token GitHub

Créer/éditer .env.github à la racine:

GITHUB_TOKEN=ghp_xxx

Le script de mining résout le token dans cet ordre:

  1. --token
  2. variable d’environnement GITHUB_TOKEN
  3. fichier .env.github (répertoire courant puis racine du projet)

1) Mining GitHub

Script: scripts/mine_github_issues.py

Ce que le script retient

Une issue est conservée si:

  • elle est closed,
  • au moins une PR mentionnée dans sa conversation est merged,
  • la fermeture de l’issue est postérieure (ou égale) au merge d’au moins une de ces PR.

Les PR liées sont détectées dans:

  • le body de l’issue,
  • les commentaires de l’issue,
  • la timeline de l’issue.

Si plusieurs PR mergées sont liées à une même issue, elles sont toutes conservées.

Commandes

Mining simple (sortie par défaut dans mined_projects/):

python3 scripts/mine_github_issues.py "https://github.com/stleary/JSON-java"

Plusieurs repos:

python3 scripts/mine_github_issues.py \
  "https://github.com/mybatis/jpetstore-6" \
  "https://github.com/NanoHttpd/nanohttpd"

Limiter le nombre d’issues scannées:

python3 scripts/mine_github_issues.py "https://github.com/stleary/JSON-java" --issue-limit 300

--issue-limit (alias --max-issues) vaut 200 par défaut.

Format de sortie (fichier de mining)

Un fichier JSON par projet, par exemple: mined_projects/stleary__json-java__YYYYMMDDTHHMMSSZ.json

Structure simplifiée:

{
  "project_name": "stleary/json-java",
  "github_url": "https://github.com/stleary/JSON-java",
  "issues": [
    {
      "number": 296,
      "title": "...",
      "description_message": "...",
      "linked_merged_pull_requests": [
        {
          "number": 646,
          "url": "...",
          "merged_at": "...",
          "impacted_files": [
            "src/main/java/org/json/JSONObject.java"
          ]
        }
      ]
    }
  ]
}

2) Évaluation GraphRAG

Script: scripts/evaluate_graphrag_benchmark.py

Le script:

  1. lit un fichier de mining,
  2. construit une requête par issue avec title + description + prompt,
    • ajoute systématiquement un pré-prompt obligatoire aligné sur le response_type par défaut du script,
  3. exécute GraphRAG:
    • uv run python -m graphrag query "<query>" --root . --method <method> --data ./output --response-type "<valeur par défaut interne du script>"
  4. extrait les classes prédites,
  5. compare aux fichiers Java attendus,
  6. calcule les métriques par issue et globales.

Le response_type n’est pas paramétrable en ligne de commande: il est fixé dans le script pour garantir un format de sortie stable.

Commande type

python3 scripts/evaluate_graphrag_benchmark.py \
  mined_projects/stleary__json-java__20260420T090843Z.json \
  --graphrag-dir /path/to/graphrag \
  --method local

Méthode GraphRAG configurable

--method accepte uniquement:

  • local
  • drift
  • global

Exemples:

python3 scripts/evaluate_graphrag_benchmark.py <mined.json> --graphrag-dir /path/to/graphrag --method drift
python3 scripts/evaluate_graphrag_benchmark.py <mined.json> --graphrag-dir /path/to/graphrag --method global

Options utiles

  • --issue-limit N: limite le nombre d’issues évaluées.
  • --output-dir /path/folder: dossier de sortie des rapports (par défaut: evaluation_results/).
  • --output-file /path/report.json: chemin de sortie du rapport.
  • --timeout-seconds 300: timeout par requête GraphRAG.
  • --extra-prompt "...": suffixe de prompt custom.
  • --keep-raw-response: inclut la réponse brute GraphRAG dans le rapport.
  • --include-empty-java: inclut aussi les issues sans cible Java.
  • --dry-run: n’exécute pas GraphRAG (test pipeline uniquement).

Métriques calculées

Par issue:

  • TP: classes Java attendues retrouvées.
  • FP: classes prédites non matchées.
  • FN: classes attendues non retrouvées.
  • precision = TP / (TP + FP)
  • recall = TP / (TP + FN)
  • f1 = 2 * precision * recall / (precision + recall)

Global:

  • micro (agrégation globale TP/FP/FN)
  • macro (moyenne des scores par issue)

Matching attendu vs prédit

Le matching accepte plusieurs formats côté prédiction:

  • chemin .java,
  • nom pleinement qualifié (FQCN),
  • nom de classe simple.

Si un nom simple est ambigu (plusieurs classes possibles), il n’est pas matché automatiquement.

Pré-prompt obligatoire

Chaque requête envoyée à GraphRAG inclut automatiquement un pré-prompt obligatoire qui impose:

  • un format strict conforme au response_type par défaut du script,
  • aucune explication hors format attendu.

Rapport d’évaluation

Sortie par défaut: dans evaluation_results/, avec suffixe __graphrag_eval__<timestamp>.json.

Le rapport contient:

  • les paramètres d’exécution,
  • un résumé global,
  • les métriques par issue,
  • les classes attendues / prédites.

Workflow recommandé

  1. Préparer le token GitHub (.env.github).
  2. Miner un projet:
    • python3 scripts/mine_github_issues.py "<repo-url>"
  3. Lancer l’évaluation GraphRAG:
    • python3 scripts/evaluate_graphrag_benchmark.py <mined-file.json> --graphrag-dir <path> --method local
  4. Comparer les résultats entre local, drift, global.

3) Export des queries LLM

Script: scripts/export_benchmark_queries.py

Objectif:

  • générer un JSON contenant uniquement les queries à envoyer au LLM,
  • en réutilisant la même construction de prompt que l’evaluator,
  • inclure le contexte d’issue et les chemins de classes attendues.

Sortie:

  • par défaut dans queries/,
  • un fichier nommé selon le projet benchmark, par exemple:
    • queries/mybatis__jpetstore-6__queries.json

Commande type:

python3 scripts/export_benchmark_queries.py \
  mined_projects/mybatis__jpetstore-6__20260420T093019Z.json

Options utiles:

  • --output-dir /path/folder
  • --output-file /path/file.json
  • --issue-limit N
  • --include-empty-java
  • --extra-prompt "..."

4) Évaluation Via API LLM (Ollama/OpenAI/Mistral)

Script: scripts/evaluate_llm_api_benchmark.py

Objectif:

  • évaluer le benchmark sans passer par graphrag query,
  • interroger directement une API LLM (Ollama local, OpenAI, Mistral),
  • calculer les mêmes métriques (precision, recall, f1).

Exemples:

Ollama (local):

python3 scripts/evaluate_llm_api_benchmark.py \
  mined_projects/mybatis__jpetstore-6__20260420T093019Z.json \
  --provider ollama \
  --model gemma2 \
  --keep-raw-response

OpenAI:

export OPENAI_API_KEY="..."
python3 scripts/evaluate_llm_api_benchmark.py \
  mined_projects/mybatis__jpetstore-6__20260420T093019Z.json \
  --provider openai \
  --model gpt-4.1-mini

Mistral:

export MISTRAL_API_KEY="..."
python3 scripts/evaluate_llm_api_benchmark.py \
  mined_projects/mybatis__jpetstore-6__20260420T093019Z.json \
  --provider mistral \
  --model mistral-small-latest

Options utiles:

  • --base-url pour un endpoint custom,
  • --api-key pour surcharger la clé env,
  • --temperature, --max-tokens,
  • --issue-limit,
  • --keep-raw-response,
  • --dry-run.

5) Évaluation Semi-Automatique (saisie manuelle)

Script: scripts/evaluate_manual_input_benchmark.py

Objectif:

  • lire un benchmark,
  • construire la query pour chaque issue,
  • afficher cette query à l’utilisateur,
  • attendre la réponse manuelle (copier/coller depuis un LLM/GraphRAG),
  • calculer automatiquement les métriques.

Commande type:

python3 scripts/evaluate_manual_input_benchmark.py \
  mined_projects/mybatis__jpetstore-6__20260420T093019Z.json \
  --keep-raw-response

Mode de saisie:

  • le script affiche la query,
  • la query est automatiquement copiée dans le presse-papier (si supporté par l’environnement),
  • tu colles la réponse multi-ligne,
  • tu termines en faisant simplement Entrée sur une ligne vide,
  • les lignes vides internes dans un gros collage multi-ligne sont désormais tolérées (le script évite de passer involontairement à l’issue suivante),
  • optionnellement, tu peux aussi terminer avec EOF (ou un token custom via --end-token),
  • si tu tapes STOP sur une ligne, l’évaluation s’arrête immédiatement et un fichier de résultats partiels est généré avec les données déjà collectées.

Options utiles:

  • --issue-limit N
  • --include-empty-java
  • --keep-raw-response
  • --end-token DONE
  • --no-copy-query-to-clipboard

Format de sortie (par entrée):

  • issue_number
  • query
  • expected_classes_paths

Troubleshooting

  • Erreur API rate limit exceeded:
    • vérifier GITHUB_TOKEN (.env.github ou env var).
  • Erreur GraphRAG directory not found:
    • passer --graphrag-dir vers le bon dossier.
  • Beaucoup de FP:
    • réduire le prompt à une sortie plus contrainte,
    • ajuster le DEFAULT_RESPONSE_TYPE directement dans le script,
    • vérifier l’ambiguïté des noms de classes simples.
  • Pas d’issues pertinentes:
    • le repository n’a peut-être pas d’issues fermées reliées à des PR mergées selon les règles du miner.

Notes

  • mined_projects/ est ignoré par git.
  • evaluation_results/ est ignoré par git.
  • queries/ est ignoré par git.
  • .env.github est ignoré par git.
  • Le projet privilégie des outputs JSON pour faciliter l’analyse offline et les comparaisons de runs.

About

A small python tool to scrap github project looking for impacted classes linked to an closed issue (via pull requests)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages