---
# System prepended metadata

title: DPO run

---

# DPO scripts
We will use the curated repo from Huggingface for training model (SFT and DPO)

[Alignment Handbook](https://github.com/huggingface/alignment-handbook)

# How to run it

We should use it on Linux or WSL.

## Installation

1. Create venv (Must be python v3.10)
```
conda create -n handbook python=3.10 && conda activate handbook
```

2. Install Pytorch 
```
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
```

3. Clone and install alignment handbook

```
git clone https://github.com/huggingface/alignment-handbook.git
cd ./alignment-handbook/
python -m pip install .
```

4. Install Flash Attention 2 for faster training

```
MAX_JOBS=4 pip install flash-attn --no-build-isolation
```

:::info
Note If using a machine has less than 96GB of RAM
```
python -m pip install flash-attn --no-build-isolation
```
:::

5. Set up Huggingface acount
```
huggingface-cli login --token <YOUR_TOKEN>
```

6. Git LFS
```
sudo apt-get install git-lfs
```

## Dataset preparation
Take a look at [this instruction](https://github.com/huggingface/alignment-handbook/blob/main/scripts/README.md#fine-tuning-on-your-datasets)

I created an example dataset here:
[Jan's subset](https://huggingface.co/datasets/jan-hq/ultrafeedback_binarized_subset)

## Training
The most important is YAML file
`recipes/{model_name}/{task}/config_lora.yaml`

We have 2 tasks: **SFT** and **DPO**
e.g.
`recipes/trinity-v1/dpo/config_lora.yaml`

The example for [config_lora.yaml](https://github.com/huggingface/alignment-handbook/blob/main/recipes/zephyr-7b-beta/dpo/config_lora.yaml)

The optimal one
```yaml
# Model arguments
model_name_or_path: jan-hq/trinity-v1
torch_dtype: auto

# LoRA arguments
use_peft: true
lora_r: 16 # best: 256 
lora_alpha: 32 # best: 512 
lora_dropout: 0.1
lora_target_modules:
- q_proj
- k_proj
- v_proj
- o_proj
- gate_proj
- up_proj
- down_proj

# Data training arguments

dataset_mixer:
  jan-hq/ultrafeedback_binarized_subset: 1.0
dataset_splits:
- train_sft
- test_sft
preprocessing_num_workers: 12

# DPOTrainer arguments
bf16: true
beta: 0.1
do_eval: true
evaluation_strategy: epoch
eval_steps: 100
gradient_accumulation_steps: 32
gradient_checkpointing: true
gradient_checkpointing_kwargs:
  use_reentrant: false
hub_model_id: trinity-v1-dpo
learning_rate: 5.0e-7
log_level: info
logging_steps: 10
lr_scheduler_type: linear
max_length: 1024 #increase to 2048 or 4096 is OK
max_prompt_length: 512
num_train_epochs: 1
optim: rmsprop
output_dir: data/trinity-v1-dpo
# It is handy to append `hub_model_revision` to keep track of your local experiments
per_device_train_batch_size: 2
per_device_eval_batch_size: 4
push_to_hub: true
save_strategy: "no"
save_total_limit: null
seed: 42
warmup_ratio: 0.1
report_to:
- wandb
```

**IMPORTANT NOTE**
As the script will auto handle the chat format for us so we must check the `chat_template` inside `tokenizer.json` of a model.

E.g. for ChatML template for [trinity](https://huggingface.co/jan-hq/trinity-v1/blob/main/tokenizer_config.json)

```json
"chat_template": "{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}"
```

:::info
If we can setup multi-GPUs use the deepspeedv3 for the fastest training process.

```
ACCELERATE_LOG_LEVEL=info accelerate launch --config_file recipes/accelerate_configs/deepspeed_zero3.yaml --num_processes={num_gpus} scripts/run_{task}.py recipes/{model_name}/{task}/config_lora.yaml
```
:::

## Evaluation
- LMM harness
```
git clone https://github.com/EleutherAI/lm-evaluation-harness.git
cd lm-evaluation-harness
pip install -e .
```

GSM8K
```
lm_eval --model hf \
    --model_args pretrained=<REPO_ID>,dtype="bfloat16" \
    --tasks gsm8k \
    --device cuda:0 \
    --num_fewshot 5 \
    --batch_size 8
```

We can also try [`MT-Bench`](https://github.com/lm-sys/FastChat/tree/main/fastchat/llm_judge) and [`AlpacaEval`](https://github.com/tatsu-lab/alpaca_eval)



2 tasks for Rex:
- [ ] add merge LORA to model
- [ ] add tokenizer.model

Merge LORA
```
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
import torch

adapter_path = "path/to/adapter"
base_model_path = "alignment-handbook/data/{base_model}"
merged_model= "alignment-handbook/data/{merged_path}"

print("Loading adapter...")

model = AutoModelForCausalLM.from_pretrained(
    base_model_path,
    torch_dtype=torch.bfloat16,
    low_cpu_mem_usage=True,
    trust_remote_code=True,
)

model = PeftModel.from_pretrained(model, adapter_path)

tokenizer = AutoTokenizer.from_pretrained(
    base_model_path,
    trust_remote_code=True,
)
model = model.merge_and_unload()
print("Saving merged model...")
print(model)
model.save_pretrained(merged_model)
tokenizer.save_pretrained(merged_model)
```