Views
No views yet
trl library's DPOTrainer with PEFT (QLoRA) for parameter-efficient training.Qwen/Qwen2.5-3B-Instruct base model by aligning it further with human preferences. The DPO fine-tuning was performed on the argilla/distilabel-intel-orca-dpo-pairs dataset, which contains pairs of chosen and rejected responses to various instructions. The goal was to train the model to prefer generating responses similar to the "chosen" examples while avoiding patterns found in the "rejected" examples.Qwen/Qwen2.5-3B-Instruct. To use it, first load the base model in 4-bit, then apply the adapters. Make sure to use the specific chat template associated with the Qwen2 base model.1import torch
2from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
3from peft import PeftModel
4
5# --- Configuration ---
6base_model_name = "Qwen/Qwen2.5-3B-Instruct"
7adapter_model_name = "ogulcanakca/qwen2.5-3b-instruct-dpo-orca"
8
9# --- Load Base Model in 4-bit ---
10bnb_config = BitsAndBytesConfig(
11 load_in_4bit=True,
12 bnb_4bit_quant_type="nf4",
13 bnb_4bit_compute_dtype=torch.bfloat16
14)
15
16tokenizer = AutoTokenizer.from_pretrained(base_model_name, trust_remote_code=True)
17tokenizer.pad_token = tokenizer.eos_token # Usually needed for generation
18
19base_model = AutoModelForCausalLM.from_pretrained(
20 base_model_name,
21 quantization_config=bnb_config,
22 device_map="auto",
23 trust_remote_code=True,
24)
25
26# --- Load and Apply PEFT Adapter ---
27model = PeftModel.from_pretrained(base_model, adapter_model_name)
28
29# --- Prepare Input using Qwen2 Chat Template ---
30prompt = "Write a short story about a cat who learns to code."
31messages = [
32 {"role": "system", "content": "You are a helpful assistant."},
33 {"role": "user", "content": prompt}
34]
35text = tokenizer.apply_chat_template(
36 messages,
37 tokenize=False,
38 add_generation_prompt=True
39)
40model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
41
42# --- Generate Response ---
43generated_ids = model.generate(
44 model_inputs.input_ids,
45 max_new_tokens=512,
46 pad_token_id=tokenizer.eos_token_id
47)
48generated_ids = [
49 output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
50]
51
52response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
53print(response)Intel/orca_dpo_pairs dataset available on the Hugging Face Hub. This dataset consists of approximately 12.8k examples, each containing:prompt: The instruction given to the model.chosen: The preferred response.rejected: The less preferred response.transformers, trl, peft, bitsandbytes, accelerate.trl's DPOTrainer.wandb).r=16, lora_alpha=32, lora_dropout=0.05, targeting most linear layers (q_proj, k_proj, v_proj, o_proj, etc.).learning_rate: 5e-5beta: 0.1loss_type: "ipo"num_train_epochs: 1per_device_train_batch_size: 1 (Effective batch size: 8)gradient_accumulation_steps: 8lr_scheduler_type: "cosine"optim: "paged_adamw_8bit"max_length: 1024max_prompt_length: 512gradient_checkpointing: Trueprecompute_ref_log_probs: Falseprecompute_ref_log_probs=False setting and without eval. The total duration of your run with eval, including interruptions (around 36 hours), was longer, but the pure training time is around this figure).Qwen/Qwen2.5-3B-Instruct model on a custom test set derived from the databricks/databricks-dolly-15k dataset.open_qa and closed_qa categories were excluded to focus on instruction following and generation tasks rather than factual recall.| Step | Training Loss | Validation Loss | Rewards/chosen | Rewards/rejected | Rewards/accuracies | Rewards/margins | Logps/chosen | Logps/rejected | Logits/chosen | Logits/rejected |
|---|---|---|---|---|---|---|---|---|---|---|
| 1300 | 12.325900 | 13.097957 | -0.147601 | -0.436289 | 0.856921 | 0.288688 | -4.055865 | -6.360097 | -1.893258 | -2.525452 |
| 1325 | 13.215800 | 13.116969 | -0.145761 | -0.434994 | 0.856921 | 0.289233 | -4.037463 | -6.347150 | -1.870269 | -2.520532 |
| 1350 | 12.509500 | 13.052545 | -0.145866 | -0.430553 | 0.856921 | 0.284687 | -4.038514 | -6.302736 | -1.884726 | -2.529022 |
| 1375 | 12.392900 | 13.075562 | -0.147900 | -0.434689 | 0.856921 | 0.286789 | -4.058856 | -6.344100 | -1.889521 | -2.523355 |
| 1400 | 13.423500 | 13.080257 | -0.147380 | -0.435694 | 0.856921 | 0.288314 | -4.053657 | -6.354150 | -1.877747 | -2.516060 |
| 1425 | 14.636300 | 13.075521 | -0.145920 | -0.433277 | 0.856921 | 0.287357 | -4.039056 | -6.329982 | -1.870765 | -2.516895 |
| 1450 | 10.936000 | 13.070604 | -0.145527 | -0.433105 | 0.856921 | 0.287578 | -4.035127 | -6.328260 | -1.865718 | -2.517346 |
| 1475 | 12.833400 | 13.085215 | -0.145675 | -0.433959 | 0.856921 | 0.288284 | -4.036605 | -6.336797 | -1.862939 | -2.514504 |
| 1500 | 12.713900 | 13.081480 | -0.145784 | -0.434095 | 0.856921 | 0.288311 | -4.037696 | -6.338157 | -1.863126 | -2.514367 |
| 1525 | 14.113300 | 13.077538 | -0.145751 | -0.433938 | 0.856921 | 0.288186 | -4.037369 | -6.336587 | -1.863070 | -2.514565 |
open_qa and closed_qa categories to focus the evaluation on instruction following, creative generation, and reasoning tasks rather than factual recall.| Metric | Description | Score Range | Average Result | Interpretation |
|---|---|---|---|---|
| Head-to-Head Preference Score | Judge model selects which response (Base vs. DPO) is better for each prompt. | 0.0 = DPO wins 1.0 = Base wins | 0.07 due to the judge's fallacy | DPO Model was preferred in ~93% of cases. |
| Usefulness Score | Measures how well each model’s response addresses the prompt (independent scoring). | 0.0 – 1.0 | 0.72 DPO Model 0.69 Base Model | Indicates practical helpfulness of responses. |
| Reference Alignment Score | Evaluates semantic similarity to the human-written reference answer (Dolly dataset). | 0.0 – 1.0 | 0.05 =Base=DPO | Measures alignment with human “gold standard.” |
Note: Earlier trials included heuristic metrics (e.g., ROUGE/BLEU) under a “Content Comparison Score,” but these were excluded from the final report in favor of LLM-as-a-Judge metrics, which capture semantic quality more effectively.