GraphDancer is a two-stage post-training framework that teaches Large Language Models (LLMs) to interleave natural-language reasoning with graph function execution. The first stage (Curriculum-PPO) uses proximal policy optimization with executable rule-based rewards to teach the model how to interact with the graph. The second stage (Curriculum-DPO) refines the PPO policy on self-generated preference pairs to make interactions more grounded and efficient. Both stages are organized by a graph-aware curriculum that progressively increases task difficulty based on the structural complexity of information-seeking trajectories (S-rounds and E-rounds). With a 3B backbone, GraphDancer outperforms graph-agent baselines built on substantially larger or stronger models.
This repository contains the official implementation of the paper: GraphDancer: Training LLMs to Explore and Reason over Graphs via Two-Stage Curriculum Post-Training.
- Two-Stage Post-Training: Curriculum-PPO (online, rule-based reward over executable graph calls) followed by Curriculum-DPO (offline preference learning over self-sampled trajectories ranked by six trajectory-level keys with fixed tie-break priority).
- Interleaved Reasoning & Action: Trains agents to alternate between
<think>(reasoning),<graph>(function execution),<information>(environment feedback), and<answer>blocks. - Graph-Aware Curriculum: A graph-specific scheduler that decomposes trajectories into Singleton lookup rounds (S-rounds) and Neighborhood expansion rounds (E-rounds), and biases batch composition from Easy to Hard via a time-varying mixture.
- Rule-Based Reward Shaping: Format-aware and correctness-based rewards with no learned reward model.
- Cross-Domain Generalization: Train on the Academic domain and evaluate on four unseen GRBench domains (E-commerce, Literature, Healthcare, Legal) plus out-of-distribution question types.
βββ graphdancer/ # Core logic for multi-turn generation and tool management
β βββ llm_agent/
β βββ generation*.py # Rollout drivers for the interleaved think/graph/information loop
β βββ tensor_helper.py
β βββ tools/ # Graph function executor and retriever
βββ verl/
β βββ trainer/
β β βββ ppo/ # Stage 1: Curriculum-PPO (online RL)
β β βββ dpo/ # Stage 2: Curriculum-DPO (offline preference learning)
β βββ experimental/
β β βββ dataset/ # E2H biased-mixture curriculum sampler (crl_e2h.py)
β βββ ... # upstream verl utilities
βββ scripts/
β βββ launchers/ # Entry points for Stage 1 / Stage 2 training and evaluation
β βββ curriculum/ # Curriculum prompt templates (graph-aware and Graph-CoT)
β βββ dpo/ # Stage 2 preference-pair construction + analysis
β βββ graph_data/ # Utilities for converting raw graph data to parquet
β βββ build_*.sh # Dataset construction scripts
βββ data/ # Placeholder for processed datasets and graph files
βββ eval.py # Evaluation script (Exact Match, BLEU, ROUGE, GPT4-Score)
βββ LICENSE # CC BY 4.0
Create a virtual environment and install dependencies. We recommend Python 3.10+.
conda create -n graphdancer python=3.10 -y
conda activate graphdancer
# Install PyTorch (adjust cuda version as needed)
pip install torch torchvision torchaudio
# Install repository dependencies and the package in editable mode
pip install -r requirements.txt
pip install -e .GraphDancer uses the graph environments and QA formats from GRBench (Jin et al., 2024). We provide pre-processed datasets on Hugging Face for a quick start.
cd data
git lfs install
git clone https://huggingface.co/datasets/yuyangbai/GRBench-copy graphs
# For the legal graph, concatenate the chunks
cd graphs/legal
cat chunk_* > graph.json
cd ../..pip install huggingface_hub
python3 << 'EOF'
from huggingface_hub import hf_hub_download
import os, shutil
repo_id = "yuyangbai/GraphDancer-data"
os.makedirs("data/train", exist_ok=True)
for domain in ["biomedical", "goodreads", "amazon", "legal"]:
os.makedirs(f"data/test/{domain}", exist_ok=True)
train_file = hf_hub_download(repo_id=repo_id, filename="train/train.parquet", repo_type="dataset")
shutil.copy2(train_file, "data/train/train.parquet")
for domain in ["biomedical", "goodreads", "amazon", "legal"]:
test_file = hf_hub_download(repo_id=repo_id, filename=f"test/{domain}/test.parquet", repo_type="dataset")
shutil.copy2(test_file, f"data/test/{domain}/test.parquet")
EOFdata/
βββ graphs/ # Graph data from GRBench
β βββ dblp/graph.json # Academic
β βββ biomedical/graph.json # Healthcare
β βββ legal/graph.json # Legal (chunked on HF)
β βββ amazon/graph.json # E-commerce
β βββ goodreads/graph.json # Literature
βββ train/train.parquet # Academic training set
βββ test/<domain>/test.parquet # Per-domain test sets
Stage 1 trains the policy with executable rule-based rewards on the Academic domain.
Trains with the biased-mixture curriculum scheduler described in Β§2.4 of the paper.
export GRAPH_DIR=./data/graphs
export DATA_DIR=./data/train
export OUTPUT_DIR=./checkpoints/graphdancer_curriculum_ppo
bash scripts/launchers/train_graphdancer_ppo_e2h_mix.shbash scripts/launchers/train_graphdancer_ppo_e2h.shbash scripts/launchers/train_graphdancer_ppo.shStage 2 refines the Stage 1 checkpoint via DPO on self-generated preference pairs ranked by the six trajectory-level keys defined in Β§2.3 of the paper with fixed tie-break priority. The full procedure is described in Β§2.3, Algorithm 1 Phase 2, and Appendix A.2 of the paper.
Run the verl rollout entry point in eval-only mode against the Academic training set with val_kwargs.n=8, dumping per-trajectory traces to results.jsonl. Default decoding: temperature 1.0, top-p 0.95, max_turns 10.
python scripts/dpo/build_preference_pairs.py \
--jsonl_glob "./data/dpo/k8_rollouts/*/results.jsonl" \
--train_parquet ./data/train/train.parquet \
--out_parquet ./data/dpo/pair_parquet/pairs.parquet \
--lex_version v1The script ranks the M=8 trajectories per question by (EM, EH, VF, -loop_limit, -invalid_tool, -n_graph_rounds) with fixed tie-break priority and emits one extreme pair per qid (rank-1 vs rank-M), along with character-level <information> spans needed for the agent-token mask.
export PAIR_PARQUET=./data/dpo/pair_parquet/pairs.parquet
export PPO_CHECKPOINT=./checkpoints/graphdancer_curriculum_ppo/actor/global_step_200
export OUTPUT_DIR=./checkpoints/graphdancer_curriculum_dpo
bash scripts/launchers/train_graphdancer_dpo.shThe launcher trains for 100 steps with Ξ²=0.1, learning rate 2e-7, linear warmup over 5% of steps, and the same E2H biased-mixture curriculum used in Stage 1.
Evaluate a trained checkpoint on a specific domain (e.g., Healthcare):
export GRAPH_DIR=./data/graphs
export DOMAIN=biomedical
export CHECKPOINT=./checkpoints/graphdancer_curriculum_dpo/actor/global_step_100
export BASE_MODEL=$CHECKPOINT
bash scripts/launchers/eval_graphdancer.sh# Basic metrics
python eval.py --result_file results/biomedical/results.jsonl
# GPT-4 based scoring (requires OPENAI_API_KEY)
python eval.py --result_file results/biomedical/results.jsonl --use_gpt4_scoreThis project builds upon several excellent open-source projects:
- Graph-CoT for the graph function implementation and the GRBench benchmark.
- Search-R1 for inspiring our agentic RL training framework design.
- veRL for a robust and scalable RL training framework.
- vLLM for efficient and high-throughput LLM inference.
We also thank Lambda for providing GPU resources.
This repository is released under the Creative Commons Attribution 4.0 International (CC BY 4.0) license. See LICENSE for the full text.
The verl/ subdirectory contains upstream code from the verl project and is licensed under Apache 2.0; the original copyright and license headers are retained.
If you find our work useful, please consider citing:
@misc{bai2026graphdancertrainingllmsexplore,
title={GraphDancer: Training LLMs to Explore and Reason over Graphs via Two-Stage Curriculum Post-Training},
author={Yuyang Bai and Zhuofeng Li and Ping Nie and Yu Wang and Jianwen Xie and Yu Zhang},
year={2026},
eprint={2602.02518},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2602.02518},
}