大模型-llamafactory ppo训练模型,不使用llm作为reward模型 -73

LlamaFactory PPO 训练:拥抱自定义奖励函数,告别LLM-as-a-Judge

在利用 LlamaFactory 进行近端策略优化(PPO)训练时,您完全可以摆脱对大型语言模型(LLM)作为奖励模型的依赖,转而使用自定义的 Python 函数来对模型的生成结果进行评分。这种方法不仅为评估标准提供了极大的灵活性,还可能显著降低训练成本和复杂性。

核心思想:以函数替代模型
传统的 PPO 训练流程中,一个独立的奖励模型(通常是另一个经过特殊训练的 LLM)负责评估策略模型(被训练的模型)生成的响应质量,并给出一个标量奖励分数。
PPO、DPO 和 KTO 这三种用于大语言模型(LLM)对齐的强化学习算法

LlamaFactory 巧妙地设计了其 PPO 训练器,使其能够接受一个 Python 函数作为奖励信号的来源。

这意味着,您可以根据任务的具体需求,编写任意复杂的逻辑来判断生成内容的优劣,而无需训练和部署一个庞大的奖励模型。

自定义奖励函数的规范

要使您的自定义函数与 LlamaFactory 的 PPO 训练流程兼容,它需要遵循特定的函数签名。

def custom_reward_function(prompts: list[str], completions: list[str], **kwargs) -> list[float]:
    """
    计算并返回每个生成结果的奖励分数。

    Args:
        prompts (list[str]): 提供给模型的输入提示列表。
        completions (list[str]): 模型针对每个提示生成的响应列表。
        **kwargs: 一个字典,可能包含来自数据集的其他字段,
                  例如 "answer" 或 "solution",用于与生成结果进行比较。

    Returns:
        list[float]: 一个包含每个生成结果对应奖励分数的列表。
    """
    # 在此实现您的奖励计算逻辑
    rewards = []
    for i in range(len(completions)):
        # 示例逻辑:如果生成的内容包含特定关键词,则给予奖励
        if "您好" in completions[i]:
            rewards.append(1.0)
        else:
            rewards.append(0.0)
    return rewards

输入: 函数接收两个主要列表:prompts 和 completions,分别代表输入给模型的提示和模型生成的内容。此外,**kwargs 允许您从数据集中传递额外的信息(例如,参考答案),这对于计算准确率等指标至关重要。
输出: 函数必须返回一个浮点数列表,其长度与 completions 列表相同。每个浮点数代表对应生成结果的奖励分数。

实战演练

自定义奖励函数
创建一个名为 my_rewards.py 的 Python 文件,并在其中定义您的奖励函数。在这个例子中,我们将实现一个简单的奖励函数:如果模型生成的答案与数据集中的标准答案完全匹配,则给予奖励 1.0,否则为 0.0。

# my_rewards.py

def accuracy_reward(prompts: list[str], completions: list[str], **kwargs) -> list[float]:
    """
    如果生成结果与参考答案完全匹配,则奖励为 1.0,否则为 0.0。
    """
    if "answer" not in kwargs:
        raise ValueError("数据集中必须包含 'answer' 字段以计算准确率。")

    answers = kwargs["answer"]
    rewards = []
    for i in range(len(completions)):
        if completions[i].strip() == answers[i].strip():
            rewards.append(1.0)
        else:
            rewards.append(0.0)
    return rewards

准备数据集
您的数据集需要包含用于计算奖励的必要信息。在我们的例子中,除了 instruction 和 input,还需要一个 answer 字段

[
  {
    "instruction": "中国的首都是哪里?",
    "input": "",
    "output": "中国的首都是北京。",
    "answer": "北京"
  },
  {
    "instruction": "法国的国旗是什么颜色的?",
    "input": "",
    "output": "法国的国旗是蓝色、白色和红色。",
    "answer": "蓝、白、红"
  }
]

修改 LlamaFactory 源码以注册您的函数
最新版本的 LlamaFactory 中,您可能可以通过命令行参数直接指定自定义奖励函数的文件和名称,从而无需修改源代码。
请查阅最新的官方文档以获取确切信息。
如果需要手动注册,您需要找到 LlamaFactory 中处理奖励计算的部分,并添加对您自定义函数的引用。这通常涉及到修改 PPO 训练器或相关工具类。
一个可能的修改点是在 src/llmtuner/train/ppo/trainer.py (路径可能因版本而异) 中。您需要导入您的函数并将其添加到一个奖励函数的字典中。

配置并运行 PPO 训练
train_bash.py 的命令行示例

#!/bin/bash

# 确保 my_rewards.py 在 Python 路径中
export PYTHONPATH=$PYTHONPATH:$(pwd)

CUDA_VISIBLE_DEVICES=0 python src/train_bash.py \
    --stage ppo \
    --do_train \
    --model_name_or_path path_to_your_sft_model \
    --dataset my_dataset \
    --dataset_dir ./data \
    --template default \
    --finetuning_type lora \
    --lora_target q_proj,v_proj \
    --reward_model path_to_your_sft_model \
    # 关键参数:指定自定义奖励函数
    --reward_fn my_rewards.accuracy_reward \
    --output_dir path_to_save_ppo_model \
    --per_device_train_batch_size 2 \
    --gradient_accumulation_steps 4 \
    --lr_scheduler_type cosine \
    --logging_steps 10 \
    --save_steps 1000 \
    --learning_rate 1e-5 \
    --num_train_epochs 1.0

--reward_model: 在 PPO 中,即使使用自定义奖励函数,通常也需要一个价值头(value head)来估计状态价值。这里我们复用 SFT 阶段的模型作为基础。
--reward_fn: 这是指定您的自定义奖励函数的关键。格式为 模块名.函数名。请确保包含该函数的文件(如此处的 my_rewards.py)在您的 Python 解释器可以找到的路径中。
总之,LlamaFactory 提供的自定义奖励函数功能为 PPO 训练开辟了新的可能性,使得研究人员和开发者能够更加精细和高效地调整语言模型以适应各种复杂任务。

posted @ 2025-06-24 09:59  jack-chen666  阅读(611)  评论(0)    收藏  举报