Text Generation
PEFT
Safetensors
lora
trl
grpo
gdpo
dpo
divpo
rlhf
diversity
creative-writing
mode-collapse
Instructions to use Mercity/creative-writing-llm with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use Mercity/creative-writing-llm with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Add configs
Browse files- configs/E0_baseline.yaml +67 -0
- configs/E1_div_individual.yaml +68 -0
- configs/E2_div_group.yaml +69 -0
- configs/E3_multipos.yaml +25 -0
- configs/E3_multipos_8b.yaml +25 -0
- configs/E4a_divpo_emb.yaml +35 -0
- configs/E4a_divpo_emb_8b.yaml +35 -0
- configs/E4b_divpo_prob.yaml +36 -0
- configs/E4b_divpo_prob_8b.yaml +36 -0
configs/E0_baseline.yaml
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E0 -- quality-only GRPO baseline (the collapse control).
|
| 2 |
+
# Measures how much semantic diversity is destroyed by standard quality-only
|
| 3 |
+
# post-training. Every other arm is scored against this.
|
| 4 |
+
name: E0-baseline
|
| 5 |
+
seed: 42
|
| 6 |
+
model: Qwen/Qwen3-4B-Instruct-2507
|
| 7 |
+
wandb: true
|
| 8 |
+
|
| 9 |
+
reward:
|
| 10 |
+
arm: E0 # channels: [quality]
|
| 11 |
+
tau: 5.0 # unused in E0 (no diversity channel to gate)
|
| 12 |
+
|
| 13 |
+
lora:
|
| 14 |
+
r: 32
|
| 15 |
+
alpha: 64
|
| 16 |
+
dropout: 0.0
|
| 17 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 18 |
+
|
| 19 |
+
train:
|
| 20 |
+
max_steps: 300
|
| 21 |
+
num_generations: 8 # G
|
| 22 |
+
per_device_train_batch_size: 1 # forward micro-batch only; TRL requires
|
| 23 |
+
# generation_batch (= 2*8 = 16) to be divisible by G, not this
|
| 24 |
+
gradient_accumulation_steps: 16 # generation_batch = 2*8 = 16 = 2 prompts x G=8
|
| 25 |
+
max_completion_length: 1024 # ~790 words. The length gate rejects
|
| 26 |
+
# anything >600 words (~780 tok), so this sits
|
| 27 |
+
# ABOVE the entire accept region: no story we would
|
| 28 |
+
# ever score gets truncated by it.
|
| 29 |
+
vllm_max_model_length: 1280 # 180 prompt + 1024 completion + margin
|
| 30 |
+
learning_rate: 3.0e-5 # 10x the plan's 3e-6. The plan's 1e-6..5e-6 band is a
|
| 31 |
+
# FULL fine-tuning range; these are LoRA adapters (r=32,
|
| 32 |
+
# alpha=64), which typically want 10-50x that.
|
| 33 |
+
# Evidence: E0 at 3e-6 ran 171 steps with KL PINNED near
|
| 34 |
+
# 0.0008 and never growing -- the adapter was effectively
|
| 35 |
+
# frozen, and every metric stayed inside its noise band
|
| 36 |
+
# (quality +-0.08, deviation +-0.007, logdet +-0.30).
|
| 37 |
+
# A probe at 3e-5 showed KL compounding instead:
|
| 38 |
+
# 0.0008 -> 0.0081 by step 12, ~9x E0 at the same step,
|
| 39 |
+
# with gate pass still 1.000, quality 6.36 -> 6.53 and
|
| 40 |
+
# deviation 0.120 -> 0.137. Healthy movement, not instability.
|
| 41 |
+
lr_scheduler_type: constant_with_warmup
|
| 42 |
+
warmup_steps: 10
|
| 43 |
+
beta: 0.02 # KL to reference
|
| 44 |
+
temperature: 1.0
|
| 45 |
+
top_p: 1.0
|
| 46 |
+
scale_rewards: group
|
| 47 |
+
save_steps: 50
|
| 48 |
+
save_only_model: true # checkpoints are for EVALUATING intermediate
|
| 49 |
+
# policies, never for resuming; optimizer state is
|
| 50 |
+
# ~660MB of the 768MB and is pure waste here
|
| 51 |
+
save_total_limit: 7
|
| 52 |
+
# Liger is OFF: TRL routes use_liger_kernel=True to compute_liger_loss, which
|
| 53 |
+
# logs only [clip_ratio, kl] and NOT entropy. Per-token policy entropy is a
|
| 54 |
+
# first-class metric here (entropy collapse = creativity death), and it cannot
|
| 55 |
+
# be recovered from a finished run. Liger was only needed at micro-batch 2;
|
| 56 |
+
# at micro-batch 1 the logits tensor is already halved, and vLLM's budget is
|
| 57 |
+
# trimmed below to buy back the rest.
|
| 58 |
+
use_liger_kernel: false
|
| 59 |
+
vllm_gpu_memory_utilization: 0.29
|
| 60 |
+
|
| 61 |
+
judge:
|
| 62 |
+
model: deepseek/deepseek-v4-flash-0731
|
| 63 |
+
concurrency: 16 # == stories per generation batch (2 prompts x G=8),
|
| 64 |
+
# so a step's judge calls all fire at once. Measured
|
| 65 |
+
# ~3.5s/call, so this is 3.5s/step not 4.7s/step.
|
| 66 |
+
price_in: 0.140 # $ per 1M tokens
|
| 67 |
+
price_out: 0.280
|
configs/E1_div_individual.yaml
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E0 -- quality-only GRPO baseline (the collapse control).
|
| 2 |
+
# Measures how much semantic diversity is destroyed by standard quality-only
|
| 3 |
+
# post-training. Every other arm is scored against this.
|
| 4 |
+
name: E1-div-individual
|
| 5 |
+
seed: 42
|
| 6 |
+
model: Qwen/Qwen3-4B-Instruct-2507
|
| 7 |
+
wandb: true
|
| 8 |
+
|
| 9 |
+
reward:
|
| 10 |
+
arm: E1 # channels: [quality, deviation]
|
| 11 |
+
alpha: 0.5 # weight on the deviation channel (in GDPO-standardized units)
|
| 12 |
+
tau: 5.0 # deviation credit only if judge quality >= tau
|
| 13 |
+
|
| 14 |
+
lora:
|
| 15 |
+
r: 32
|
| 16 |
+
alpha: 64
|
| 17 |
+
dropout: 0.0
|
| 18 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 19 |
+
|
| 20 |
+
train:
|
| 21 |
+
max_steps: 300
|
| 22 |
+
num_generations: 8 # G
|
| 23 |
+
per_device_train_batch_size: 1 # forward micro-batch only; TRL requires
|
| 24 |
+
# generation_batch (= 2*8 = 16) to be divisible by G, not this
|
| 25 |
+
gradient_accumulation_steps: 16 # generation_batch = 2*8 = 16 = 2 prompts x G=8
|
| 26 |
+
max_completion_length: 1024 # ~790 words. The length gate rejects
|
| 27 |
+
# anything >600 words (~780 tok), so this sits
|
| 28 |
+
# ABOVE the entire accept region: no story we would
|
| 29 |
+
# ever score gets truncated by it.
|
| 30 |
+
vllm_max_model_length: 1280 # 180 prompt + 1024 completion + margin
|
| 31 |
+
learning_rate: 3.0e-5 # 10x the plan's 3e-6. The plan's 1e-6..5e-6 band is a
|
| 32 |
+
# FULL fine-tuning range; these are LoRA adapters (r=32,
|
| 33 |
+
# alpha=64), which typically want 10-50x that.
|
| 34 |
+
# Evidence: E0 at 3e-6 ran 171 steps with KL PINNED near
|
| 35 |
+
# 0.0008 and never growing -- the adapter was effectively
|
| 36 |
+
# frozen, and every metric stayed inside its noise band
|
| 37 |
+
# (quality +-0.08, deviation +-0.007, logdet +-0.30).
|
| 38 |
+
# A probe at 3e-5 showed KL compounding instead:
|
| 39 |
+
# 0.0008 -> 0.0081 by step 12, ~9x E0 at the same step,
|
| 40 |
+
# with gate pass still 1.000, quality 6.36 -> 6.53 and
|
| 41 |
+
# deviation 0.120 -> 0.137. Healthy movement, not instability.
|
| 42 |
+
lr_scheduler_type: constant_with_warmup
|
| 43 |
+
warmup_steps: 10
|
| 44 |
+
beta: 0.02 # KL to reference
|
| 45 |
+
temperature: 1.0
|
| 46 |
+
top_p: 1.0
|
| 47 |
+
scale_rewards: group
|
| 48 |
+
save_steps: 50
|
| 49 |
+
save_only_model: true # checkpoints are for EVALUATING intermediate
|
| 50 |
+
# policies, never for resuming; optimizer state is
|
| 51 |
+
# ~660MB of the 768MB and is pure waste here
|
| 52 |
+
save_total_limit: 7
|
| 53 |
+
# Liger is OFF: TRL routes use_liger_kernel=True to compute_liger_loss, which
|
| 54 |
+
# logs only [clip_ratio, kl] and NOT entropy. Per-token policy entropy is a
|
| 55 |
+
# first-class metric here (entropy collapse = creativity death), and it cannot
|
| 56 |
+
# be recovered from a finished run. Liger was only needed at micro-batch 2;
|
| 57 |
+
# at micro-batch 1 the logits tensor is already halved, and vLLM's budget is
|
| 58 |
+
# trimmed below to buy back the rest.
|
| 59 |
+
use_liger_kernel: false
|
| 60 |
+
vllm_gpu_memory_utilization: 0.29
|
| 61 |
+
|
| 62 |
+
judge:
|
| 63 |
+
model: deepseek/deepseek-v4-flash-0731
|
| 64 |
+
concurrency: 16 # == stories per generation batch (2 prompts x G=8),
|
| 65 |
+
# so a step's judge calls all fire at once. Measured
|
| 66 |
+
# ~3.5s/call, so this is 3.5s/step not 4.7s/step.
|
| 67 |
+
price_in: 0.140 # $ per 1M tokens
|
| 68 |
+
price_out: 0.280
|
configs/E2_div_group.yaml
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E0 -- quality-only GRPO baseline (the collapse control).
|
| 2 |
+
# Measures how much semantic diversity is destroyed by standard quality-only
|
| 3 |
+
# post-training. Every other arm is scored against this.
|
| 4 |
+
name: E2-div-group
|
| 5 |
+
seed: 42
|
| 6 |
+
model: Qwen/Qwen3-4B-Instruct-2507
|
| 7 |
+
wandb: true
|
| 8 |
+
|
| 9 |
+
reward:
|
| 10 |
+
arm: E2 # channels: [quality, deviation, marginal]
|
| 11 |
+
alpha: 0.5 # weight on deviation
|
| 12 |
+
gamma: 0.5 # weight on log-det marginal contribution (z-scored per group)
|
| 13 |
+
tau: 5.0 # both diversity channels gated on judge quality >= tau
|
| 14 |
+
|
| 15 |
+
lora:
|
| 16 |
+
r: 32
|
| 17 |
+
alpha: 64
|
| 18 |
+
dropout: 0.0
|
| 19 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 20 |
+
|
| 21 |
+
train:
|
| 22 |
+
max_steps: 300
|
| 23 |
+
num_generations: 8 # G
|
| 24 |
+
per_device_train_batch_size: 1 # forward micro-batch only; TRL requires
|
| 25 |
+
# generation_batch (= 2*8 = 16) to be divisible by G, not this
|
| 26 |
+
gradient_accumulation_steps: 16 # generation_batch = 2*8 = 16 = 2 prompts x G=8
|
| 27 |
+
max_completion_length: 1024 # ~790 words. The length gate rejects
|
| 28 |
+
# anything >600 words (~780 tok), so this sits
|
| 29 |
+
# ABOVE the entire accept region: no story we would
|
| 30 |
+
# ever score gets truncated by it.
|
| 31 |
+
vllm_max_model_length: 1280 # 180 prompt + 1024 completion + margin
|
| 32 |
+
learning_rate: 3.0e-5 # 10x the plan's 3e-6. The plan's 1e-6..5e-6 band is a
|
| 33 |
+
# FULL fine-tuning range; these are LoRA adapters (r=32,
|
| 34 |
+
# alpha=64), which typically want 10-50x that.
|
| 35 |
+
# Evidence: E0 at 3e-6 ran 171 steps with KL PINNED near
|
| 36 |
+
# 0.0008 and never growing -- the adapter was effectively
|
| 37 |
+
# frozen, and every metric stayed inside its noise band
|
| 38 |
+
# (quality +-0.08, deviation +-0.007, logdet +-0.30).
|
| 39 |
+
# A probe at 3e-5 showed KL compounding instead:
|
| 40 |
+
# 0.0008 -> 0.0081 by step 12, ~9x E0 at the same step,
|
| 41 |
+
# with gate pass still 1.000, quality 6.36 -> 6.53 and
|
| 42 |
+
# deviation 0.120 -> 0.137. Healthy movement, not instability.
|
| 43 |
+
lr_scheduler_type: constant_with_warmup
|
| 44 |
+
warmup_steps: 10
|
| 45 |
+
beta: 0.02 # KL to reference
|
| 46 |
+
temperature: 1.0
|
| 47 |
+
top_p: 1.0
|
| 48 |
+
scale_rewards: group
|
| 49 |
+
save_steps: 50
|
| 50 |
+
save_only_model: false # checkpoints are for EVALUATING intermediate
|
| 51 |
+
# policies, never for resuming; optimizer state is
|
| 52 |
+
# ~660MB of the 768MB and is pure waste here
|
| 53 |
+
save_total_limit: 7
|
| 54 |
+
# Liger is OFF: TRL routes use_liger_kernel=True to compute_liger_loss, which
|
| 55 |
+
# logs only [clip_ratio, kl] and NOT entropy. Per-token policy entropy is a
|
| 56 |
+
# first-class metric here (entropy collapse = creativity death), and it cannot
|
| 57 |
+
# be recovered from a finished run. Liger was only needed at micro-batch 2;
|
| 58 |
+
# at micro-batch 1 the logits tensor is already halved, and vLLM's budget is
|
| 59 |
+
# trimmed below to buy back the rest.
|
| 60 |
+
use_liger_kernel: false
|
| 61 |
+
vllm_gpu_memory_utilization: 0.29
|
| 62 |
+
|
| 63 |
+
judge:
|
| 64 |
+
model: deepseek/deepseek-v4-flash-0731
|
| 65 |
+
concurrency: 16 # == stories per generation batch (2 prompts x G=8),
|
| 66 |
+
# so a step's judge calls all fire at once. Measured
|
| 67 |
+
# ~3.5s/call, so this is 3.5s/step not 4.7s/step.
|
| 68 |
+
price_in: 0.140 # $ per 1M tokens
|
| 69 |
+
price_out: 0.280
|
configs/E3_multipos.yaml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E3 -- multi-positive diverse DPO, DDPO-style deviation-weighted loss.
|
| 2 |
+
# 4 greedy-diverse chosens per prompt vs rotating r_D/r_Q negatives.
|
| 3 |
+
name: E3-multipos
|
| 4 |
+
seed: 42
|
| 5 |
+
model: Qwen/Qwen3-4B-Instruct-2507
|
| 6 |
+
wandb: true
|
| 7 |
+
|
| 8 |
+
lora:
|
| 9 |
+
r: 32
|
| 10 |
+
alpha: 64
|
| 11 |
+
dropout: 0.0
|
| 12 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 13 |
+
|
| 14 |
+
dpo:
|
| 15 |
+
epochs: 1
|
| 16 |
+
learning_rate: 5.0e-6
|
| 17 |
+
beta: 0.1
|
| 18 |
+
loss_type: sigmoid
|
| 19 |
+
max_length: 1600
|
| 20 |
+
gradient_accumulation_steps: 8
|
| 21 |
+
per_device_train_batch_size: 2
|
| 22 |
+
lr_scheduler_type: cosine
|
| 23 |
+
warmup_steps: 20
|
| 24 |
+
pairs: outputs/pairs_4b/multipos_train.jsonl
|
| 25 |
+
weighted: true # per-sample loss weight = chosen deviation d_i
|
configs/E3_multipos_8b.yaml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E3 -- multi-positive diverse DPO, DDPO-style deviation-weighted loss.
|
| 2 |
+
# 4 greedy-diverse chosens per prompt vs rotating r_D/r_Q negatives.
|
| 3 |
+
name: E3-multipos-8b
|
| 4 |
+
seed: 42
|
| 5 |
+
model: Qwen/Qwen3-8B
|
| 6 |
+
wandb: true
|
| 7 |
+
|
| 8 |
+
lora:
|
| 9 |
+
r: 32
|
| 10 |
+
alpha: 64
|
| 11 |
+
dropout: 0.0
|
| 12 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 13 |
+
|
| 14 |
+
dpo:
|
| 15 |
+
epochs: 1
|
| 16 |
+
learning_rate: 5.0e-6
|
| 17 |
+
beta: 0.1
|
| 18 |
+
loss_type: sigmoid
|
| 19 |
+
max_length: 1600
|
| 20 |
+
gradient_accumulation_steps: 16
|
| 21 |
+
per_device_train_batch_size: 1
|
| 22 |
+
lr_scheduler_type: cosine
|
| 23 |
+
warmup_steps: 20
|
| 24 |
+
pairs: outputs/pairs_8b/multipos_train.jsonl
|
| 25 |
+
weighted: true # per-sample loss weight = chosen deviation d_i
|
configs/E4a_divpo_emb.yaml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E4a -- faithful DivPO (Lanchantin et al. 2025), embedding-deviation criterion.
|
| 2 |
+
# One pair per prompt, no loss weighting. Clean literature baseline.
|
| 3 |
+
name: E4-divpo-emb
|
| 4 |
+
seed: 42
|
| 5 |
+
model: Qwen/Qwen3-4B-Instruct-2507
|
| 6 |
+
wandb: true
|
| 7 |
+
|
| 8 |
+
lora:
|
| 9 |
+
r: 32
|
| 10 |
+
alpha: 64
|
| 11 |
+
dropout: 0.0
|
| 12 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 13 |
+
|
| 14 |
+
dpo:
|
| 15 |
+
epochs: 4
|
| 16 |
+
# STEP-COUNT PARITY (deviation from the plan's "1-2 epochs").
|
| 17 |
+
# E3 has 3593 multi-positive rows; E4 has 956 single-pair rows. At the plan's
|
| 18 |
+
# 1 epoch and effective batch 16, E4 gets ~60 optimizer steps vs E3's ~449 --
|
| 19 |
+
# a 7.5x asymmetry. The validation run confirmed the consequence empirically:
|
| 20 |
+
# loss stayed at 0.691 (= log 2, no separation), reward accuracy 0.53, margin
|
| 21 |
+
# 0.026. E4 would have "lost" the head-to-head purely by undertraining, which
|
| 22 |
+
# says nothing about DivPO's pair selection.
|
| 23 |
+
# Fix: same effective batch (1 x 8) for every DPO arm, and epochs chosen so
|
| 24 |
+
# optimizer steps match: E4 956x4/8 = 478 vs E3 3593x1/8 = 449.
|
| 25 |
+
|
| 26 |
+
learning_rate: 5.0e-6
|
| 27 |
+
beta: 0.1
|
| 28 |
+
loss_type: sigmoid
|
| 29 |
+
max_length: 1600
|
| 30 |
+
gradient_accumulation_steps: 8
|
| 31 |
+
per_device_train_batch_size: 1
|
| 32 |
+
lr_scheduler_type: cosine
|
| 33 |
+
warmup_steps: 20
|
| 34 |
+
pairs: outputs/pairs_4b/divpo_emb_train.jsonl
|
| 35 |
+
weighted: false
|
configs/E4a_divpo_emb_8b.yaml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E4a -- faithful DivPO (Lanchantin et al. 2025), embedding-deviation criterion.
|
| 2 |
+
# One pair per prompt, no loss weighting. Clean literature baseline.
|
| 3 |
+
name: E4-divpo-emb-8b
|
| 4 |
+
seed: 42
|
| 5 |
+
model: Qwen/Qwen3-8B
|
| 6 |
+
wandb: true
|
| 7 |
+
|
| 8 |
+
lora:
|
| 9 |
+
r: 32
|
| 10 |
+
alpha: 64
|
| 11 |
+
dropout: 0.0
|
| 12 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 13 |
+
|
| 14 |
+
dpo:
|
| 15 |
+
epochs: 4
|
| 16 |
+
# STEP-COUNT PARITY (deviation from the plan's "1-2 epochs").
|
| 17 |
+
# E3 has 3593 multi-positive rows; E4 has 956 single-pair rows. At the plan's
|
| 18 |
+
# 1 epoch and effective batch 16, E4 gets ~60 optimizer steps vs E3's ~449 --
|
| 19 |
+
# a 7.5x asymmetry. The validation run confirmed the consequence empirically:
|
| 20 |
+
# loss stayed at 0.691 (= log 2, no separation), reward accuracy 0.53, margin
|
| 21 |
+
# 0.026. E4 would have "lost" the head-to-head purely by undertraining, which
|
| 22 |
+
# says nothing about DivPO's pair selection.
|
| 23 |
+
# Fix: same effective batch (1 x 8) for every DPO arm, and epochs chosen so
|
| 24 |
+
# optimizer steps match: E4 956x4/8 = 478 vs E3 3593x1/8 = 449.
|
| 25 |
+
|
| 26 |
+
learning_rate: 5.0e-6
|
| 27 |
+
beta: 0.1
|
| 28 |
+
loss_type: sigmoid
|
| 29 |
+
max_length: 1600
|
| 30 |
+
gradient_accumulation_steps: 16
|
| 31 |
+
per_device_train_batch_size: 1
|
| 32 |
+
lr_scheduler_type: cosine
|
| 33 |
+
warmup_steps: 20
|
| 34 |
+
pairs: outputs/pairs_8b/divpo_emb_train.jsonl
|
| 35 |
+
weighted: false
|
configs/E4b_divpo_prob.yaml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E4b -- faithful DivPO, model-probability criterion.
|
| 2 |
+
# chosen = lowest length-normalized logprob among quality>=rho (the
|
| 3 |
+
# principled 'reject the greedy decode'); rejected = highest among quality<rho.
|
| 4 |
+
name: E4-divpo-prob
|
| 5 |
+
seed: 42
|
| 6 |
+
model: Qwen/Qwen3-4B-Instruct-2507
|
| 7 |
+
wandb: true
|
| 8 |
+
|
| 9 |
+
lora:
|
| 10 |
+
r: 32
|
| 11 |
+
alpha: 64
|
| 12 |
+
dropout: 0.0
|
| 13 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 14 |
+
|
| 15 |
+
dpo:
|
| 16 |
+
epochs: 4
|
| 17 |
+
# STEP-COUNT PARITY (deviation from the plan's "1-2 epochs").
|
| 18 |
+
# E3 has 3593 multi-positive rows; E4 has 956 single-pair rows. At the plan's
|
| 19 |
+
# 1 epoch and effective batch 16, E4 gets ~60 optimizer steps vs E3's ~449 --
|
| 20 |
+
# a 7.5x asymmetry. The validation run confirmed the consequence empirically:
|
| 21 |
+
# loss stayed at 0.691 (= log 2, no separation), reward accuracy 0.53, margin
|
| 22 |
+
# 0.026. E4 would have "lost" the head-to-head purely by undertraining, which
|
| 23 |
+
# says nothing about DivPO's pair selection.
|
| 24 |
+
# Fix: same effective batch (1 x 8) for every DPO arm, and epochs chosen so
|
| 25 |
+
# optimizer steps match: E4 956x4/8 = 478 vs E3 3593x1/8 = 449.
|
| 26 |
+
|
| 27 |
+
learning_rate: 5.0e-6
|
| 28 |
+
beta: 0.1
|
| 29 |
+
loss_type: sigmoid
|
| 30 |
+
max_length: 1600
|
| 31 |
+
gradient_accumulation_steps: 8
|
| 32 |
+
per_device_train_batch_size: 1
|
| 33 |
+
lr_scheduler_type: cosine
|
| 34 |
+
warmup_steps: 20
|
| 35 |
+
pairs: outputs/pairs_4b/divpo_prob_train.jsonl
|
| 36 |
+
weighted: false
|
configs/E4b_divpo_prob_8b.yaml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E4b -- faithful DivPO, model-probability criterion.
|
| 2 |
+
# chosen = lowest length-normalized logprob among quality>=rho (the
|
| 3 |
+
# principled 'reject the greedy decode'); rejected = highest among quality<rho.
|
| 4 |
+
name: E4-divpo-prob-8b
|
| 5 |
+
seed: 42
|
| 6 |
+
model: Qwen/Qwen3-8B
|
| 7 |
+
wandb: true
|
| 8 |
+
|
| 9 |
+
lora:
|
| 10 |
+
r: 32
|
| 11 |
+
alpha: 64
|
| 12 |
+
dropout: 0.0
|
| 13 |
+
target_modules: [q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj]
|
| 14 |
+
|
| 15 |
+
dpo:
|
| 16 |
+
epochs: 4
|
| 17 |
+
# STEP-COUNT PARITY (deviation from the plan's "1-2 epochs").
|
| 18 |
+
# E3 has 3593 multi-positive rows; E4 has 956 single-pair rows. At the plan's
|
| 19 |
+
# 1 epoch and effective batch 16, E4 gets ~60 optimizer steps vs E3's ~449 --
|
| 20 |
+
# a 7.5x asymmetry. The validation run confirmed the consequence empirically:
|
| 21 |
+
# loss stayed at 0.691 (= log 2, no separation), reward accuracy 0.53, margin
|
| 22 |
+
# 0.026. E4 would have "lost" the head-to-head purely by undertraining, which
|
| 23 |
+
# says nothing about DivPO's pair selection.
|
| 24 |
+
# Fix: same effective batch (1 x 8) for every DPO arm, and epochs chosen so
|
| 25 |
+
# optimizer steps match: E4 956x4/8 = 478 vs E3 3593x1/8 = 449.
|
| 26 |
+
|
| 27 |
+
learning_rate: 5.0e-6
|
| 28 |
+
beta: 0.1
|
| 29 |
+
loss_type: sigmoid
|
| 30 |
+
max_length: 1600
|
| 31 |
+
gradient_accumulation_steps: 16
|
| 32 |
+
per_device_train_batch_size: 1
|
| 33 |
+
lr_scheduler_type: cosine
|
| 34 |
+
warmup_steps: 20
|
| 35 |
+
pairs: outputs/pairs_8b/divpo_prob_train.jsonl
|
| 36 |
+
weighted: false
|