Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

rlhf_dpo.py

08_training_techniques/rlhf_dpo.py  ·  75 lines  ·  view on GitHub

"""
RLHF and DPO from Scratch
Interview question: "Explain RLHF and DPO"
"""
import numpy as np

def dpo_loss(policy_logprobs_chosen: float,
             policy_logprobs_rejected: float,
             reference_logprobs_chosen: float,
             reference_logprobs_rejected: float,
             beta: float = 0.1) -> float:
    """
    DPO Loss: Direct Preference Optimization
    
    Directly optimizes policy to prefer chosen over rejected
    No reward model needed
    
    Args:
        policy_logprobs_chosen: Log prob of chosen (from policy)
        policy_logprobs_rejected: Log prob of rejected (from policy)
        reference_logprobs_chosen: Log prob of chosen (from reference)
        reference_logprobs_rejected: Log prob of rejected (from reference)
        beta: Temperature parameter
    """
    # Log ratio
    log_ratio_chosen = policy_logprobs_chosen - reference_logprobs_chosen
    log_ratio_rejected = policy_logprobs_rejected - reference_logprobs_rejected
    
    # DPO objective
    loss = -np.log(1 / (1 + np.exp(-beta * (log_ratio_chosen - log_ratio_rejected))))
    
    return loss

def rlhf_loss(policy_logprob: float, reference_logprob: float,
              reward: float, beta: float = 0.1) -> float:
    """
    RLHF Loss (simplified PPO-style)
    
    Args:
        policy_logprob: Log prob from current policy
        reference_logprob: Log prob from reference model
        reward: Reward from reward model
        beta: KL penalty coefficient
    """
    # Ratio
    ratio = np.exp(policy_logprob - reference_logprob)
    
    # Policy gradient + KL penalty
    loss = -ratio * reward + beta * (policy_logprob - reference_logprob)
    
    return loss


# Usage
if __name__ == "__main__":
    print("RLHF and DPO")
    print("=" * 60)
    
    # DPO example
    policy_chosen = -2.0
    policy_rejected = -3.0
    ref_chosen = -2.5
    ref_rejected = -3.2
    
    dpo = dpo_loss(policy_chosen, policy_rejected, ref_chosen, ref_rejected)
    print(f"DPO Loss: {dpo:.4f}")
    
    # RLHF example
    policy_logprob = -2.0
    ref_logprob = -2.5
    reward = 0.8
    
    rlhf = rlhf_loss(policy_logprob, ref_logprob, reward)
    print(f"RLHF Loss: {rlhf:.4f}")