Text Generation
Transformers
Safetensors
hy_v3
hunyuan
hy3
Mixture of Experts
conversational
Eval Results
Instructions to use tencent/Hy3 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use tencent/Hy3 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="tencent/Hy3", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("tencent/Hy3") model = AutoModelForCausalLM.from_pretrained("tencent/Hy3", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use tencent/Hy3 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "tencent/Hy3" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "tencent/Hy3", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/tencent/Hy3
- SGLang
How to use tencent/Hy3 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "tencent/Hy3" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "tencent/Hy3", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "tencent/Hy3" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "tencent/Hy3", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use tencent/Hy3 with Docker Model Runner:
docker model run hf.co/tencent/Hy3
Upload folder using huggingface_hub
Browse files- .gitattributes +1 -0
- assets/rl-training.png +3 -0
- rl/README.md +216 -0
- rl/README_CN.md +216 -0
.gitattributes
CHANGED
|
@@ -35,3 +35,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
assets/benchmark-appendix.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
assets/benchmark.png filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
assets/benchmark-appendix.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
assets/benchmark.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
assets/rl-training.png filter=lfs diff=lfs merge=lfs -text
|
assets/rl-training.png
ADDED
|
Git LFS Details
|
rl/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Hy3 Reinforcement Learning Training
|
| 2 |
+
|
| 3 |
+
English | [简体中文](./README_CN.md)
|
| 4 |
+
|
| 5 |
+
This document describes how to run reinforcement learning training for Hy3 with [verl](https://github.com/volcengine/verl). Training runs on [Megatron-LM](https://github.com/NVIDIA/Megatron-LM); NVIDIA [Megatron-Bridge](https://github.com/NVIDIA-NeMo/Megatron-Bridge) (`HYV3Bridge`) converts the HF checkpoint into a Megatron model on the fly at training startup — no offline conversion needed. Rollout runs on [vLLM](https://github.com/vllm-project/vllm).
|
| 6 |
+
|
| 7 |
+
Training script: [`examples/grpo_trainer/run_hy_v3_megatron.sh`](https://github.com/verl-project/verl/blob/main/examples/grpo_trainer/run_hy_v3_megatron.sh) in the verl repository.
|
| 8 |
+
|
| 9 |
+
## Quick Start
|
| 10 |
+
|
| 11 |
+
### Environment
|
| 12 |
+
|
| 13 |
+
Recommended image: `verlai/verl:vllm023.dev1`
|
| 14 |
+
|
| 15 |
+
Verified version combination:
|
| 16 |
+
|
| 17 |
+
| Component | Version |
|
| 18 |
+
| --- | --- |
|
| 19 |
+
| verl | [220e903](https://github.com/verl-project/verl/commit/220e9039902c6db56860e2afd659803dc34ec005) |
|
| 20 |
+
| Megatron-Bridge | [df0852c](https://github.com/NVIDIA-NeMo/Megatron-Bridge/commit/df0852cf94c674de07f9f7ef933c484de8aca505) |
|
| 21 |
+
| transformers | 5.6.0 |
|
| 22 |
+
| nvidia-modelopt | 0.44.0rc5 |
|
| 23 |
+
|
| 24 |
+
### Prepare dependencies
|
| 25 |
+
|
| 26 |
+
Clone verl at the verified version, then clone the dependencies into `third_party/` under the repository root:
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
git clone https://github.com/verl-project/verl.git
|
| 30 |
+
cd verl
|
| 31 |
+
git checkout 220e903
|
| 32 |
+
|
| 33 |
+
mkdir third_party
|
| 34 |
+
git clone https://github.com/NVIDIA-NeMo/Megatron-Bridge.git third_party/Megatron-Bridge
|
| 35 |
+
git -C third_party/Megatron-Bridge checkout df0852c
|
| 36 |
+
|
| 37 |
+
git clone https://github.com/Ascend/TransferQueue.git third_party/TransferQueue
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
Create a `runtime_env.yaml` so the Ray runtime env ships the working directory (including `third_party/`) to every worker node and adds the dependencies to `PYTHONPATH`:
|
| 41 |
+
|
| 42 |
+
```yaml
|
| 43 |
+
# runtime_env.yaml
|
| 44 |
+
working_dir: ./
|
| 45 |
+
excludes: [
|
| 46 |
+
"/.git/",
|
| 47 |
+
"/third_party/Megatron-Bridge/.git/",
|
| 48 |
+
"/third_party/TransferQueue/.git/",
|
| 49 |
+
"**/__pycache__/",
|
| 50 |
+
]
|
| 51 |
+
env_vars:
|
| 52 |
+
PYTHONPATH: third_party/Megatron-Bridge/src:third_party/TransferQueue
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
### Prepare the dataset
|
| 56 |
+
|
| 57 |
+
The script defaults to [DAPO-Math-17k](https://huggingface.co/datasets/BytedTsinghua-SIA/DAPO-Math-17k) (train) and [AIME-2024](https://huggingface.co/datasets/BytedTsinghua-SIA/AIME-2024) (validation). Both are already in the format verl expects on HuggingFace — just download and dump to parquet:
|
| 58 |
+
|
| 59 |
+
```python
|
| 60 |
+
# prepare_data.py
|
| 61 |
+
import datasets
|
| 62 |
+
|
| 63 |
+
dapo = datasets.load_dataset("BytedTsinghua-SIA/DAPO-Math-17k", "default")["train"]
|
| 64 |
+
dapo.to_parquet("DAPO-Math-17k/dapo-math-17k.parquet")
|
| 65 |
+
|
| 66 |
+
aime = datasets.load_dataset("BytedTsinghua-SIA/AIME-2024", "default")["train"]
|
| 67 |
+
aime.to_parquet("AIME-2024/aime-2024.parquet")
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
```bash
|
| 71 |
+
python prepare_data.py # output layout matches the script's default DATA_DIR
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
Place the data under the verl repository root (`DATA_DIR` defaults to `$PWD`), or point elsewhere with `DATA_DIR=/path/to/data`.
|
| 75 |
+
|
| 76 |
+
### Submit the job
|
| 77 |
+
|
| 78 |
+
Use the HuggingFace checkpoint directly; training data is in parquet format. Point `RAY_ADDRESS` at the cluster head node, then submit with `ray job submit`:
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
export RAY_ADDRESS=http://<head_node_ip>:<port>
|
| 82 |
+
|
| 83 |
+
ray job submit --no-wait --runtime-env=runtime_env.yaml -- \
|
| 84 |
+
bash examples/grpo_trainer/run_hy_v3_megatron.sh
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
> **Note**: on H20, rollout (vLLM inference) requires at least TP=16 (the script defaults to `ROLLOUT_TP=16`) — the weights of a single instance only fit when sharded across 16 GPUs.
|
| 88 |
+
|
| 89 |
+
### Key parameters
|
| 90 |
+
|
| 91 |
+
**Hy3 settings**
|
| 92 |
+
|
| 93 |
+
| Parameter | Value | Reason |
|
| 94 |
+
| --- | --- | --- |
|
| 95 |
+
| `moe_router_enable_expert_bias` | True | Hy3 routes with a per-expert bias (aux-loss-free) |
|
| 96 |
+
| `moe_router_bias_update_rate` | 0 | 0 freezes the bias (it still participates in scoring but is never updated) |
|
| 97 |
+
| `moe_router_load_balancing_type` | none | no auxiliary load-balancing loss |
|
| 98 |
+
|
| 99 |
+
**Training setup**
|
| 100 |
+
|
| 101 |
+
| Parameter | What it does |
|
| 102 |
+
| --- | --- |
|
| 103 |
+
| `data.train_batch_size` | prompts sampled per step |
|
| 104 |
+
| `rollout.n` | responses generated per prompt, i.e. the GRPO group size (the in-group advantage baseline is computed over them), typically 8–16 |
|
| 105 |
+
| `actor.ppo_mini_batch_size` | samples per actor parameter update |
|
| 106 |
+
| `actor.optim.lr` | actor learning rate, typically the 1e-6 scale |
|
| 107 |
+
| `data.max_response_length` | maximum generation length, task-dependent |
|
| 108 |
+
|
| 109 |
+
**Algorithm behavior**
|
| 110 |
+
|
| 111 |
+
| Parameter | What it does | How to set it |
|
| 112 |
+
| --- | --- | --- |
|
| 113 |
+
| `algorithm.norm_adv_by_std_in_grpo` | whether advantages are divided by the in-group std | True is original GRPO; False is the [Dr.GRPO](https://arxiv.org/abs/2503.20783) fix, preventing too-easy/too-hard prompts with tiny variance from being amplified |
|
| 114 |
+
| `actor.clip_ratio_low` / `clip_ratio_high` | PPO trust-region bounds | a slightly relaxed upper bound (clip-higher, e.g. 0.2/0.28) gives low-probability tokens more room to rise, mitigating entropy collapse |
|
| 115 |
+
| `actor.clip_ratio_c` | [dual-clip](https://arxiv.org/abs/1912.09729) lower-bound constant | caps the penalty on negative-advantage tokens to keep a single step from blowing up the policy |
|
| 116 |
+
| `actor.kl_loss_coef` | KL-regularization strength toward the reference policy | 0 means KL-free (rely on clipping); add a small value (e.g. 1e-3) if training is unstable |
|
| 117 |
+
| `algorithm.rollout_correction.rollout_is` / `rollout_is_threshold` | correction for the rollout/training log-prob mismatch (IcePop) | `token` plus lower/upper bounds (e.g. `0.5_4.0`; token weights outside the range are zeroed); recommended whenever the numeric gap between the two engines is non-negligible |
|
| 118 |
+
| `rollout.temperature` / `top_p` | rollout sampling exploration strength | typically 0.9–1.0; too low a temperature reduces in-group diversity and degrades the GRPO baseline |
|
| 119 |
+
|
| 120 |
+
**Memory and sequence length**
|
| 121 |
+
|
| 122 |
+
Parameters that must move together when extending the sequence length (changing `data.max_response_length` alone is not enough):
|
| 123 |
+
|
| 124 |
+
| Parameter | Coupling |
|
| 125 |
+
| --- | --- |
|
| 126 |
+
| `data.max_response_length` | target response length |
|
| 127 |
+
| `rollout.max_model_len` | vLLM context length, must be ≥ prompt + response |
|
| 128 |
+
| `actor.ppo_max_token_len_per_gpu` | training-side per-GPU token budget; sequences are split across CP ranks, so each GPU actually holds `(prompt+response)/CP` per sequence — the requirement is budget × CP ≥ prompt + response |
|
| 129 |
+
| `actor.megatron.context_parallel_size` | scale up proportionally for much longer sequences (activation memory grows linearly with sequence length and is sharded by CP) |
|
| 130 |
+
|
| 131 |
+
For training-side OOM (the error occurs during actor update / log_prob), you can try:
|
| 132 |
+
|
| 133 |
+
1. Lower `actor.ppo_max_token_len_per_gpu` — dynamic batching packs micro batches against it, so it directly bounds the activation peak;
|
| 134 |
+
2. Set `actor.ppo_micro_batch_size_per_gpu` to 1;
|
| 135 |
+
3. Lower `ref.log_prob_max_token_len_per_gpu` / `rollout.log_prob_max_token_len_per_gpu`;
|
| 136 |
+
4. Raise `actor.megatron.context_parallel_size` (activations are sharded by CP) or `pipeline_model_parallel_size` (fewer layers per stage).
|
| 137 |
+
|
| 138 |
+
Offload and recompute:
|
| 139 |
+
|
| 140 |
+
| Config | Script default | What it does |
|
| 141 |
+
| --- | --- | --- |
|
| 142 |
+
| `actor.megatron.param_offload` | True | offloads parameters to CPU while training is idle, freeing GPU memory for rollout |
|
| 143 |
+
| `actor.megatron.optimizer_offload` | True | offloads optimizer state (fp32 master weights + momenta — the biggest memory consumer) to CPU |
|
| 144 |
+
| `actor.megatron.grad_offload` | True | offloads gradient buffers to CPU |
|
| 145 |
+
| `override_transformer_config.recompute_granularity` | full | full activation recomputation: forward stores no activations, backward recomputes them — trades ~30% extra compute for most of the activation memory |
|
| 146 |
+
| `override_transformer_config.recompute_method` / `recompute_num_layers` | uniform / 1 | recompute uniformly at 1-layer granularity — the finest granularity, lowest peak |
|
| 147 |
+
|
| 148 |
+
Both substantially relieve OOM: offload keeps parameters/optimizer state/gradients out of GPU memory at the cost of per-step CPU↔GPU transfers, and recompute keeps activations out of GPU memory at the cost of one extra forward pass during backward.
|
| 149 |
+
|
| 150 |
+
## Customizing Your Training
|
| 151 |
+
|
| 152 |
+
### Using your own dataset
|
| 153 |
+
|
| 154 |
+
verl reads parquet data where each row contains 5 fields (see the verl docs: [Prepare Data](https://verl.readthedocs.io/en/latest/preparation/prepare_data.html)):
|
| 155 |
+
|
| 156 |
+
```python
|
| 157 |
+
{
|
| 158 |
+
"data_source": "my_dataset", # dataset name; the RewardManager uses it to index the scoring function
|
| 159 |
+
"prompt": [ # HuggingFace chat template format; the tokenizer renders and tokenizes it
|
| 160 |
+
{"role": "user", "content": "1+1=?"}
|
| 161 |
+
],
|
| 162 |
+
"ability": "math", # task category
|
| 163 |
+
"reward_model": {
|
| 164 |
+
"style": "rule",
|
| 165 |
+
"ground_truth": "2" # reference answer; the reward function's scoring logic must align with its format
|
| 166 |
+
},
|
| 167 |
+
"extra_info": {"split": "train", "index": 0}, # metadata
|
| 168 |
+
}
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
Write a preprocessing script that converts your data into this format (verl's [`examples/data_preprocess/`](https://github.com/verl-project/verl/tree/main/examples/data_preprocess) ships a dozen ready-to-adapt templates — GSM8K, MATH, etc.), save as parquet, then point the script at your files via environment variables:
|
| 172 |
+
|
| 173 |
+
```bash
|
| 174 |
+
TRAIN_FILES=/path/to/my_train.parquet \
|
| 175 |
+
VAL_FILES=/path/to/my_val.parquet \
|
| 176 |
+
bash examples/grpo_trainer/run_hy_v3_megatron.sh
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
**Reward function**: math-style tasks with rule-verifiable answers can reuse the default DAPO reward as-is (it routes to a built-in scoring function by `data_source`); other tasks need a custom reward function, specified via `custom_reward_function.path` (see the verl docs: [Implement Reward Function](https://verl.readthedocs.io/en/latest/preparation/reward_function.html)).
|
| 180 |
+
|
| 181 |
+
### Switching the RL algorithm
|
| 182 |
+
|
| 183 |
+
The script defaults to GRPO, but the algorithm layer is decoupled from the model layer, so switching algorithms requires no changes to the Hy3-specific configuration.
|
| 184 |
+
|
| 185 |
+
**Switch between built-in algorithms (one config key)**: verl ships a dozen advantage estimators, selected via `algorithm.adv_estimator` — options include `gae` (PPO), `grpo`, `rloo`, `remax`, `reinforce_plus_plus`, `opo`, `gpg`, etc. (full list in `AdvantageEstimator` in [`core_algos.py`](https://github.com/verl-project/verl/blob/main/verl/trainer/ppo/core_algos.py)); the policy loss is selected via `actor_rollout_ref.actor.policy_loss.loss_mode` (`vanilla`, `gspo`, `cispo`, `clip_cov`, etc.). See the verl docs for each algorithm's theory and configuration: [PPO](https://verl.readthedocs.io/en/latest/algo/ppo.html) / [GRPO](https://verl.readthedocs.io/en/latest/algo/grpo.html) / [DAPO](https://verl.readthedocs.io/en/latest/algo/dapo.html).
|
| 186 |
+
|
| 187 |
+
**Training Hy3 with a recipe**: full-pipeline algorithms (e.g. DAPO with dynamic sampling) live as standalone implementations under verl's [`recipe/`](https://github.com/verl-project/verl/tree/main/recipe) directory, each with its own launch script. When pointing a recipe at Hy3, carry over the following required Hy3 settings into the recipe's launch script:
|
| 188 |
+
|
| 189 |
+
```bash
|
| 190 |
+
# Required Hy3 settings (apply to any recipe)
|
| 191 |
+
actor_rollout_ref.model.path=/path/to/Hy3
|
| 192 |
+
actor_rollout_ref.model.trust_remote_code=True
|
| 193 |
+
data.trust_remote_code=True
|
| 194 |
+
actor_rollout_ref.actor.megatron.use_mbridge=True
|
| 195 |
+
actor_rollout_ref.actor.megatron.vanilla_mbridge=False
|
| 196 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_enable_expert_bias=True
|
| 197 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_bias_update_rate=0
|
| 198 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_load_balancing_type=none
|
| 199 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_grouped_gemm=True
|
| 200 |
+
```
|
| 201 |
+
|
| 202 |
+
For implementing entirely new algorithms, see the verl docs: [Extend to other RL algorithms](https://verl.readthedocs.io/en/latest/advance/dpo_extension.html).
|
| 203 |
+
|
| 204 |
+
## Results
|
| 205 |
+
|
| 206 |
+
We launched Hy3 GRPO training on 128 H20 GPUs (16 nodes × 8) with [`run_hy_v3_megatron.sh`](https://github.com/verl-project/verl/blob/main/examples/grpo_trainer/run_hy_v3_megatron.sh): math reasoning on the DAPO dataset at 8192 max response length, with PP/CP/EP parallelism plus full offload, and BF16 rollout + BF16 training.
|
| 207 |
+
|
| 208 |
+
Exact values used in this run: batch 128 prompts × 16 samples (2048 trajectories/step), `ppo_mini_batch_size=128` (one update per step), lr 1e-6, clip 0.2/0.28 (dual-clip c=10.0), KL-free, DAPO overlong buffer (len 4096 / penalty 1.0), IcePop threshold `0.5_4.0`, sampling temperature 0.9 / top_p 1.0.
|
| 209 |
+
|
| 210 |
+
The training dynamics are stable: the rollout/training log-prob drift (`rollout_probs_diff`) stays below 0.015 throughout, and both reward and the AIME validation score grow steadily over the run.
|
| 211 |
+
|
| 212 |
+

|
| 213 |
+
|
| 214 |
+
## Acknowledgements
|
| 215 |
+
|
| 216 |
+
We thank the Tencent Hunyuan team for their support on model training and engineering infrastructure, as well as the [verl](https://github.com/volcengine/verl), [Megatron-Bridge](https://github.com/NVIDIA-NeMo/Megatron-Bridge), [Megatron-LM](https://github.com/NVIDIA/Megatron-LM), and [vLLM](https://github.com/vllm-project/vllm) communities for their help.
|
rl/README_CN.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Hy3 强化学习训练
|
| 2 |
+
|
| 3 |
+
[English](./README.md) | 简体中文
|
| 4 |
+
|
| 5 |
+
本文档介绍如何使用 [verl](https://github.com/volcengine/verl) 对 Hy3 进行强化学习训练。训练侧使用 [Megatron-LM](https://github.com/NVIDIA/Megatron-LM),并通过 NVIDIA [Megatron-Bridge](https://github.com/NVIDIA-NeMo/Megatron-Bridge)(`HYV3Bridge`)在训练启动时将 HF checkpoint 在线转换为 Megatron 模型,无需离线转换;rollout 侧使用 [vLLM](https://github.com/vllm-project/vllm)。
|
| 6 |
+
|
| 7 |
+
训练脚本:verl 仓库 [`examples/grpo_trainer/run_hy_v3_megatron.sh`](https://github.com/verl-project/verl/blob/main/examples/grpo_trainer/run_hy_v3_megatron.sh)
|
| 8 |
+
|
| 9 |
+
## 快速开始
|
| 10 |
+
|
| 11 |
+
### 环境
|
| 12 |
+
|
| 13 |
+
推荐镜像:`verlai/verl:vllm023.dev1`
|
| 14 |
+
|
| 15 |
+
已验证的版本组合:
|
| 16 |
+
|
| 17 |
+
| 组件 | 版本 |
|
| 18 |
+
| --- | --- |
|
| 19 |
+
| verl | [220e903](https://github.com/verl-project/verl/commit/220e9039902c6db56860e2afd659803dc34ec005) |
|
| 20 |
+
| Megatron-Bridge | [df0852c](https://github.com/NVIDIA-NeMo/Megatron-Bridge/commit/df0852cf94c674de07f9f7ef933c484de8aca505) |
|
| 21 |
+
| transformers | 5.6.0 |
|
| 22 |
+
| nvidia-modelopt | 0.44.0rc5 |
|
| 23 |
+
|
| 24 |
+
### 准备依赖
|
| 25 |
+
|
| 26 |
+
clone verl 并切换到已验证版本,然后在仓库根目录下将依赖 clone 到 `third_party/`:
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
git clone https://github.com/verl-project/verl.git
|
| 30 |
+
cd verl
|
| 31 |
+
git checkout 220e903
|
| 32 |
+
|
| 33 |
+
mkdir third_party
|
| 34 |
+
git clone https://github.com/NVIDIA-NeMo/Megatron-Bridge.git third_party/Megatron-Bridge
|
| 35 |
+
git -C third_party/Megatron-Bridge checkout df0852c
|
| 36 |
+
|
| 37 |
+
git clone https://github.com/Ascend/TransferQueue.git third_party/TransferQueue
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
编写 `runtime_env.yaml`,通过 Ray runtime env 将工作目录(含 `third_party/`)分发到各 worker 节点,并加入 `PYTHONPATH`:
|
| 41 |
+
|
| 42 |
+
```yaml
|
| 43 |
+
# runtime_env.yaml
|
| 44 |
+
working_dir: ./
|
| 45 |
+
excludes: [
|
| 46 |
+
"/.git/",
|
| 47 |
+
"/third_party/Megatron-Bridge/.git/",
|
| 48 |
+
"/third_party/TransferQueue/.git/",
|
| 49 |
+
"**/__pycache__/",
|
| 50 |
+
]
|
| 51 |
+
env_vars:
|
| 52 |
+
PYTHONPATH: third_party/Megatron-Bridge/src:third_party/TransferQueue
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
### 准备数据集
|
| 56 |
+
|
| 57 |
+
脚本默认使用 [DAPO-Math-17k](https://huggingface.co/datasets/BytedTsinghua-SIA/DAPO-Math-17k)(训练)和 [AIME-2024](https://huggingface.co/datasets/BytedTsinghua-SIA/AIME-2024)(验证),两者在 HuggingFace 上已是 verl 所需格式,下载后转存 parquet 即可:
|
| 58 |
+
|
| 59 |
+
```python
|
| 60 |
+
# prepare_data.py
|
| 61 |
+
import datasets
|
| 62 |
+
|
| 63 |
+
dapo = datasets.load_dataset("BytedTsinghua-SIA/DAPO-Math-17k", "default")["train"]
|
| 64 |
+
dapo.to_parquet("DAPO-Math-17k/dapo-math-17k.parquet")
|
| 65 |
+
|
| 66 |
+
aime = datasets.load_dataset("BytedTsinghua-SIA/AIME-2024", "default")["train"]
|
| 67 |
+
aime.to_parquet("AIME-2024/aime-2024.parquet")
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
```bash
|
| 71 |
+
python prepare_data.py # 输出路径与脚本默认的 DATA_DIR 布局一致
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
数据放在 verl 仓库根目录(`DATA_DIR` 默认为 `$PWD`)下,或通过 `DATA_DIR=/path/to/data` 指定。
|
| 75 |
+
|
| 76 |
+
### 提交任务
|
| 77 |
+
|
| 78 |
+
模型直接使用 HuggingFace 格式 checkpoint,训练数据为 parquet 格式。设置 `RAY_ADDRESS` 指向集群 head 节点后,通过 `ray job submit` 提交:
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
export RAY_ADDRESS=http://<head_node_ip>:<port>
|
| 82 |
+
|
| 83 |
+
ray job submit --no-wait --runtime-env=runtime_env.yaml -- \
|
| 84 |
+
bash examples/grpo_trainer/run_hy_v3_megatron.sh
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
> **注**:H20 上 rollout(vLLM 推理)最小需要 TP=16(脚本默认 `ROLLOUT_TP=16`),单实例权重需跨 16 卡切分才放得下。
|
| 88 |
+
|
| 89 |
+
### 关键参数
|
| 90 |
+
|
| 91 |
+
**Hy3配置**
|
| 92 |
+
|
| 93 |
+
| 参数 | 值 | 原因 |
|
| 94 |
+
| --- | --- | --- |
|
| 95 |
+
| `moe_router_enable_expert_bias` | True | Hy3 使用 per-expert bias 路由(aux-loss-free) |
|
| 96 |
+
| `moe_router_bias_update_rate` | 0 | 设 0 冻结 bias(只参与打分、不再更新)。 |
|
| 97 |
+
| `moe_router_load_balancing_type` | none | 不使用辅助负载均衡 loss |
|
| 98 |
+
|
| 99 |
+
**训练设置**
|
| 100 |
+
|
| 101 |
+
| 参数 | 作用 |
|
| 102 |
+
| --- | --- |
|
| 103 |
+
| `data.train_batch_size` | 每步采样的 prompt 数 |
|
| 104 |
+
| `rollout.n` | 每个 prompt 生成的 response 数,即 GRPO 组大小(组内计算 advantage 基线),常用 8–16;
|
| 105 |
+
| `actor.ppo_mini_batch_size` | actor 每次参数更新的样本量 |
|
| 106 |
+
| `actor.optim.lr` | actor 学习率,常用 1e-6 量级 |
|
| 107 |
+
| `data.max_response_length` | 最长生成长度,依任务而定 |
|
| 108 |
+
|
| 109 |
+
**算法行为**
|
| 110 |
+
|
| 111 |
+
| 参数 | 作用 | 怎么设 |
|
| 112 |
+
| --- | --- | --- |
|
| 113 |
+
| `algorithm.norm_adv_by_std_in_grpo` | advantage 是否除以组内 std | True 为原版 GRPO;False 为 [Dr.GRPO](https://arxiv.org/abs/2503.20783) 修正,避免过易/过难样本因方差小被放大 |
|
| 114 |
+
| `actor.clip_ratio_low` / `clip_ratio_high` | PPO 信任域上下界 | 上界略放宽(clip-higher,如 0.2/0.28)给低概率 token 更多上升空间,缓解熵坍缩 |
|
| 115 |
+
| `actor.clip_ratio_c` | [dual-clip](https://arxiv.org/abs/1912.09729) 下界常数 | 封顶负 advantage token 的惩罚,防止策略被单步拉爆 |
|
| 116 |
+
| `actor.kl_loss_coef` | 向参考策略的 KL 正则强度 | 0 为 KL-free(靠 clip 约束);训练不稳时可加小值(如 1e-3) |
|
| 117 |
+
| `algorithm.rollout_correction.rollout_is` / `rollout_is_threshold` | rollout 与训练引擎的 log-prob 偏差校正(IcePop) | `token` + 上下阈值(如 `0.5_4.0`,权重超界的 token 置零);两侧引擎精度偏差不可忽略时建议开启 |
|
| 118 |
+
| `rollout.temperature` / `top_p` | rollout 采样探索强度 | 常用 0.9–1.0;温度过低组内多样性不足,GRPO 组内基线退化 |
|
| 119 |
+
|
| 120 |
+
**显存与序列长度**
|
| 121 |
+
|
| 122 |
+
| 参数 | 联动关系 |
|
| 123 |
+
| --- | --- |
|
| 124 |
+
| `data.max_response_length` | 目标响应长度 |
|
| 125 |
+
| `rollout.max_model_len` | vLLM 上下文长度,需 ≥ prompt + response |
|
| 126 |
+
| `actor.ppo_max_token_len_per_gpu` | 训练侧每卡 token 预算;序列被 CP 切分到多卡,单条序列每卡实际占 `(prompt+response)/CP`,故需满足 预算 × CP ≥ prompt + response |
|
| 127 |
+
| `actor.megatron.context_parallel_size` | 序列显著变长时按比例增大(激活显存随序列长度线性增长,由 CP 分摊) |
|
| 128 |
+
|
| 129 |
+
训练侧 OOM(报错发生在 actor update / log_prob 阶段),可尝试:
|
| 130 |
+
|
| 131 |
+
1. 调小 `actor.ppo_max_token_len_per_gpu`——动态 batch 按它打包 micro batch,直接决定激活峰值;
|
| 132 |
+
2. `actor.ppo_micro_batch_size_per_gpu` 调为 1;
|
| 133 |
+
3. 调小 `ref.log_prob_max_token_len_per_gpu` / `rollout.log_prob_max_token_len_per_gpu`;
|
| 134 |
+
4. 增大 `actor.megatron.context_parallel_size`(激活按 CP 分摊)或 `pipeline_model_parallel_size`(每 stage 层数更少)。
|
| 135 |
+
|
| 136 |
+
offload 与 recompute:
|
| 137 |
+
|
| 138 |
+
| 配置 | 脚本默认 | 作用 |
|
| 139 |
+
| --- | --- | --- |
|
| 140 |
+
| `actor.megatron.param_offload` | True | 训练空闲期把参数下放 CPU,给 rollout 腾显存 |
|
| 141 |
+
| `actor.megatron.optimizer_offload` | True | 优化器状态(fp32 master 权重 + 动量,显存大头)放 CPU |
|
| 142 |
+
| `actor.megatron.grad_offload` | True | 梯度缓冲放 CPU |
|
| 143 |
+
| `override_transformer_config.recompute_granularity` | full | 全量激活重算:前向不存激活、反向重算,用约 30% 额外计算换掉大部分激活显存 |
|
| 144 |
+
| `override_transformer_config.recompute_method` / `recompute_num_layers` | uniform / 1 | 按每 1 层为单位均匀重算,粒度最细、峰值最低 |
|
| 145 |
+
|
| 146 |
+
两者都能显著缓解 OOM,offload 用每步 CPU↔GPU 搬运耗时换取参数/优化器/梯度不占显存,recompute 用反向多一次前向计算换取激活不占显存。
|
| 147 |
+
|
| 148 |
+
## 自定义训练
|
| 149 |
+
|
| 150 |
+
### 使用自己的数据集
|
| 151 |
+
|
| 152 |
+
verl 读取 parquet 格式数据,每行需包含 5 个字段(详见 verl 官方文档 [Prepare Data](https://verl.readthedocs.io/en/latest/preparation/prepare_data.html)):
|
| 153 |
+
|
| 154 |
+
```python
|
| 155 |
+
{
|
| 156 |
+
"data_source": "my_dataset", # 数据集名称,RewardManager 据此索引对应的打分函数
|
| 157 |
+
"prompt": [ # HuggingFace chat template 格式,tokenizer 会渲染并分词
|
| 158 |
+
{"role": "user", "content": "1+1=?"}
|
| 159 |
+
],
|
| 160 |
+
"ability": "math", # 任务类别
|
| 161 |
+
"reward_model": {
|
| 162 |
+
"style": "rule",
|
| 163 |
+
"ground_truth": "2" # 标准答案;reward 函数的判分逻辑须与其格式对齐
|
| 164 |
+
},
|
| 165 |
+
"extra_info": {"split": "train", "index": 0}, # 元信息
|
| 166 |
+
}
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
编写预处理脚本转换为上述格式(verl 的 [`examples/data_preprocess/`](https://github.com/verl-project/verl/tree/main/examples/data_preprocess) 提供了 GSM8K、MATH 等十余个可直接套用的模板),保存为 parquet 后通过环境变量指定:
|
| 170 |
+
|
| 171 |
+
```bash
|
| 172 |
+
TRAIN_FILES=/path/to/my_train.parquet \
|
| 173 |
+
VAL_FILES=/path/to/my_val.parquet \
|
| 174 |
+
bash examples/grpo_trainer/run_hy_v3_megatron.sh
|
| 175 |
+
```
|
| 176 |
+
|
| 177 |
+
**reward 函数**:答案可规则判分的数学类任务可直接沿用默认的 DAPO reward(按 `data_source` 自动路由到内置打分函数);其他任务需自定义 reward 函数,通过 `custom_reward_function.path` 指定(见 verl 文档 [Implement Reward Function](https://verl.readthedocs.io/en/latest/preparation/reward_function.html))。
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
### 更换 RL 算法
|
| 181 |
+
|
| 182 |
+
训练脚本默认 GRPO,但算法层与模型层解耦,换算法时 Hy3 相关配置无需改动。
|
| 183 |
+
|
| 184 |
+
**切换内置算法(改一个配置项)**:verl 内置了十余种 advantage 估计器,通过 `algorithm.adv_estimator` 直接切换,可选值包括 `gae`(PPO)、`grpo`、`rloo`、`remax`、`reinforce_plus_plus`、`opo`、`gpg` 等(完整列表见 [`core_algos.py`](https://github.com/verl-project/verl/blob/main/verl/trainer/ppo/core_algos.py) 的 `AdvantageEstimator`);policy loss 通过 `actor_rollout_ref.actor.policy_loss.loss_mode` 切换(`vanilla`、`gspo`、`cispo`、`clip_cov` 等)。各算法的原理与配置说明见 verl 文档:[PPO](https://verl.readthedocs.io/en/latest/algo/ppo.html) / [GRPO](https://verl.readthedocs.io/en/latest/algo/grpo.html) / [DAPO](https://verl.readthedocs.io/en/latest/algo/dapo.html)。
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
**使用 recipe 训练 Hy3**:训练流程级的完整算法(如 dynamic sampling 版 DAPO)在 verl [`recipe/`](https://github.com/verl-project/verl/tree/main/recipe) 目录下有独立实现,各自带启动脚本。将其模型指向 Hy3 时,须把以下 Hy3 必需配置带入 recipe 的启动脚本:
|
| 188 |
+
|
| 189 |
+
```bash
|
| 190 |
+
# Hy3 必需配置(任何 recipe 通用)
|
| 191 |
+
actor_rollout_ref.model.path=/path/to/Hy3
|
| 192 |
+
actor_rollout_ref.model.trust_remote_code=True
|
| 193 |
+
data.trust_remote_code=True
|
| 194 |
+
actor_rollout_ref.actor.megatron.use_mbridge=True
|
| 195 |
+
actor_rollout_ref.actor.megatron.vanilla_mbridge=False
|
| 196 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_enable_expert_bias=True
|
| 197 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_bias_update_rate=0
|
| 198 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_router_load_balancing_type=none
|
| 199 |
+
+actor_rollout_ref.actor.megatron.override_transformer_config.moe_grouped_gemm=True
|
| 200 |
+
```
|
| 201 |
+
|
| 202 |
+
自定义全新算法的扩展方式见 verl 文档 [Extend to other RL algorithms](https://verl.readthedocs.io/en/latest/advance/dpo_extension.html)。
|
| 203 |
+
|
| 204 |
+
## 实验结果
|
| 205 |
+
|
| 206 |
+
我们在 128 张 H20 GPU(16 机 × 8 卡)上启动了 Hy3 的 GRPO 训练(脚本:[`run_hy_v3_megatron.sh`](https://github.com/verl-project/verl/blob/main/examples/grpo_trainer/run_hy_v3_megatron.sh)):数学推理任务(DAPO 数据集),max response length 8192,采用 PP/CP/EP 多维并行 + 全量 offload,BF16 rollout + BF16 训练。
|
| 207 |
+
|
| 208 |
+
本次实验的具体取值:batch 128 prompts × 16 samples(2048 条轨迹/步)、`ppo_mini_batch_size=128`(每步单次更新)、lr 1e-6、clip 0.2/0.28(dual-clip c=10.0)、KL-free、DAPO overlong buffer(len 4096 / penalty 1.0)、IcePop 阈值 `0.5_4.0`、采样 temperature 0.9 / top_p 1.0。
|
| 209 |
+
|
| 210 |
+
训练动态稳定:rollout 与训练侧的 log-prob 偏差(`rollout_probs_diff`)全程基本小于 0.015,reward 与 AIME 验证集分数在整个训练过程中稳步上升。
|
| 211 |
+
|
| 212 |
+

|
| 213 |
+
|
| 214 |
+
## 致谢
|
| 215 |
+
|
| 216 |
+
感谢腾讯混元(Hunyuan)团队在模型训练与工程落地上的支持,以及 [verl](https://github.com/volcengine/verl)、[Megatron-Bridge](https://github.com/NVIDIA-NeMo/Megatron-Bridge)、[Megatron-LM](https://github.com/NVIDIA/Megatron-LM)、[vLLM](https://github.com/vllm-project/vllm) 社区的帮助。
|