PFPO 如何用 vLLM 推理结果与 construct_prefer_pair 构造数学 DPO 偏好对并启动训练?
2026/9/14 12:48:36 网站建设 项目流程

PFPO 如何用 vLLM 推理结果与 construct_prefer_pair 构造数学 DPO 偏好对并启动训练?

【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm

在 unilm 仓库的 PFPO(Preference Optimization for Reasoning with Pseudo Feedback,ICLR 2025)中,数学 DPO 的完整数据流是:先用 SFT 模型在数学训练集上做多路采样推理,用标准答案给每条解答判对错,再把这些"有的题有对有错"的样本转成偏好对,最后交给 DPO 训练器。本文按 PFPO/README.md 中 "DPO using Ground-truth Feedback" 一节的流程,覆盖从推理到启动训练的全过程。适用前提是你已经有一个数学 SFT 检查点(README 以 Mathstral-7B 在 MathScale 上 SFT 为例),并且有 GPU 环境:DPO 训练默认配置基于单节点 8xA100-80G。

准备条件

环境方面,README 要求:

  • 大部分依赖在 PFPO/requirements.txt 中,另外需要自行安装 flash-attention(DPO 训练配置使用attn_implementation: "flash_attention_2");
  • 或者直接使用官方 Docker 镜像:
docker pull jiaofangkai/normal:torch-2.5.1-vllm-0.6.4.post1-eval-1206

数据与检查点方面,需要准备:

  • 推理数据文件:一个 JSON 文件,内容是 item 列表,每个 item 必须有questionidlabel三个字段(label是标准答案,供判对错使用);
  • SFT 检查点目录,其下包含形如checkpoint-100的子目录;
  • 推理配置 4o_mathstral_train_0shot_v1_0.yaml 与训练配置 mathstral-dpo-4o-iter0-v1.1-a100.yaml 中预置的data_path_prefixmodel_path_prefixoutput_path_prefix等是作者挂载路径(/mnt/fangkai_blob/...),test_fileoutput_dirsft_model_dirtrain_file需要替换成你自己的路径。

以下命令均在PFPO目录下执行。

第一步:用 vLLM 对 SFT 检查点做多路采样推理

python vllm_inference.py test_file=${test_file} output_dir=${output_dir} eval_sub_path=${eval_sub_path} \ # Can keep the default values in the config file sampling_params.n=8 sampling_params.temperature=1.0 sampling_params.top_p=0.9 split_size=1 split_id=0 \ -cp conf/api/vllm/mathscale/ -cn 4o_mathstral_train_0shot_v1_0

三个占位符的替换对象(来自 README 的说明):

  • test_file:上节所述的推理数据文件;
  • output_dir:你的检查点所在目录;
  • eval_sub_path:检查点子路径,例如checkpoint-100

-cp/-cn指定 Hydra 配置目录和配置名(不带.yaml后缀),即 conf/api/vllm/mathscale/4o_mathstral_train_0shot_v1_0.yaml。命令行参数会覆盖配置中的默认值:该配置默认sampling_params.n: 10temperature: 1.0top_p: 0.9max_tokens: 4096,示例命令把n改成了 8。split_size=1 split_id=0表示不做数据切分、整份数据一次跑完;数据量大时可按split_size/split_id分成多份并行,构造偏好对时再用 glob 合起来(见下文示例)。

推理过程由 vllm_inference.py 完成:它以tensor_parallel_size=cfg.n_gpu(即用满本机所有 GPU)加载 vLLMLLM,逐条生成后交给配置中的post_process——post_processors.openai_api_callback.MathScaleCallBack。这个回调把每条样本的response(采样文本列表)、pred(抽取出的\boxed{}答案)、res(每条响应与label是否一致的布尔列表)、idlabel写入配置的output_file(路径由配置中output_file模板拼出,含output_dir/eval_sub_path)。推理结束时还会生成对应的.metrics.json,并打印 "Evaluation Results" 指标日志(包含accpass@k等),可用于确认推理确实跑完且数据有效。

第二步:用 construct_prefer_pair.py 构造偏好对

python scripts/math_scale/construct_prefer_pair.py --input_file $input_file_glob_path --output_file $output_file_path
  • input_file:上一步输出的推理结果文件路径,支持 glob 模式(construct_prefer_pair.py 在路径不是单个已存在文件时会按 glob 遍历,把多个分片文件合并;同一id的样本会自动合并response/res/pred列表);
  • output_file:偏好对文件的保存路径。

脚本内部逻辑(可对照源码理解):

  • 每条 item 必须带res字段;缺失时会抛出RuntimeError: Use 'fix_answer_extract_and_verify.py' to add 'res' field to the input file,即需要先用 fix_answer_extract_and_verify.py 补上判题结果再重跑;
  • 把每个响应对应的res分为正确/错误两组,分别写入该 item 的posneg字段;
  • 只有同时存在正例和负例的 item 才会进入输出文件;全部正确或全部错误的样本被剔除,其中各取前 100 条分别另存为output_file同名的.pos.sample.json.neg.sample.json,便于你抽查被剔除样本。

脚本运行结束会打印统计信息,文件头部 docstring 中保留了一次真实运行的文档示例(数值仅为示例,不是固定预期):

Total number of items: 491733 Acc: 0.6720944089577067 Pass at k: 0.8531032084484873 No positive solutions: 72234 / 491733 No negative solutions: 187738 / 491733 Num pairs: 3873158

判断依据:Num pairs大于 0 且输出文件已生成,说明偏好对构造成功;如果No positive solutions/No negative solutions两项异常地接近总样本数,说明模型在该温度下的采样结果过于一致(几乎全对或全错),可考虑调整采样参数重跑推理。

如果你走的是"自生成反馈"而非"标准答案判题"这条路线,README 给出的是另一个脚本 construct_prefer_pair_sc.py(基于多测试用例自一致性),命令形如:

python scripts/math_scale/construct_prefer_pair_sc.py --input_file $full_trajectory_data --output_file $output_file --top_p $confidence_threshold

本文主线使用标准答案判题的construct_prefer_pair.py;pDPO(前缀级偏好对)是另一套独立流程,此处不涉及。

第三步:启动 DPO 训练

torchrun --nnodes 1 --nproc_per_node 8 trainer_base_ds_mul_fs_tp.py -cp conf/exp/mathscale/mistral/dpo/ -cn mathstral-dpo-4o-iter0-v1.1-a100

训练入口 trainer_base_ds_mul_fs_tp.py 基于 Hydra + Deepspeed,-cp/-cn指定训练配置 mathstral-dpo-4o-iter0-v1.1-a100.yaml。README 明确说明:该配置按单节点 8xA100-80G 设置,启动前必须改两处——

  • train_file:改成你上一步保存的偏好对文件;
  • sft_model_dir:改成 SFT 模型检查点目录(model_name_or_path引用它,作为 DPO 待训练模型和 ref model 的加载来源)。

这份配置中影响数据与训练行为的关键项:

model: _target_: models.mistral.MistralForCausalLMDPO.from_pretrained_with_ref_model beta: 0.5 sft_loss: True sft_loss_weight: 0.2 attn_implementation: "flash_attention_2" read_tensor: _target_: data.combine_dataset.MultiMappingDataset aligner: _target_: data.input_aligner.dpo_bi_random_choice_aligner pos_field: pos neg_field: neg

dpo_bi_random_choice_aligner从每条样本的pos/neg字段中随机选一对组成 chosen/rejected,prompt 模板为{question}\n\nPlease put your final answer within \boxed{}.</s>。训练超参为learning_rate: 1e-7per_gpu_train_batch_size: 4gradient_accumulation_steps: 16num_train_epochs: 3max_seq_length: 2048(collator 中),Deepspeed 配置由defaults引入的train_hybrid_engine_zero1_optim_offload_cosine提供,tp_size: 1表示不启用张量并行。资源不足时,README 建议按其"Memory Optimization"一节的顺序(zero1 > zero2 > intra-node-zero3 等)调整 Deepspeed 配置,并按需修改 batch size、梯度累积与tp_size

结果验证与下一步

  • 推理阶段:vllm_inference.py打印 "Evaluation Results" 指标并生成output_file.metrics.json;确认输出 JSON 中每条 item 含response/res/label/id后再进入下一步;
  • 偏好对阶段:construct_prefer_pair.py打印Num pairs并写出偏好对文件(item 含pos/neg列表),同时可检查.pos.sample.json/.neg.sample.json中被剔除的样本是否符合预期;
  • 训练阶段:输出写入配置的output_dir${output_path_prefix}experiments/${exp_name}),配置中save_steps: 200save_ds_state: True,即每 200 步保存一次检查点;post_process: DPOEvalPostProcessor与 Wandb 记录中可见chosen_reward/rejected_reward曲线,可作为训练正常进行的观察指标。

训练得到新检查点后,README 的 "Evaluation Configs" 一节给出评估方式:直接用推理入口加载检查点跑评测集,例如 MWPBench(含 MATH、GSM8K)使用配置 mathstral_test_0shot_v1_0.yaml:

python vllm_inference.py -cp conf/api/vllm/mwp-bench -cn mathstral_test_0shot_v1_0

需要注意的边界:res字段缺失会被construct_prefer_pair.py直接报错终止;全部正确或全部错误的题目不会进入训练数据;配置文件中作者路径(/mnt/fangkai_blob/...)必须全部替换为你自己的路径后才能执行。

【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询