PFPO 如何用 GPT-4o 合成解法并在 APPs 数据上完成代码 SFT?
2026/9/14 5:50:48 网站建设 项目流程

PFPO 如何用 GPT-4o 合成解法并在 APPs 数据上完成代码 SFT?

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

如果你要给一个 7B 级的代码模型补强算法题能力,直接拿 GPT-4o 的输出做蒸馏数据有个明显风险:模型生成的解法里混着错误代码。PFPO(Preference Optimization for Reasoning with Pseudo Feedback,ICLR 2025,代码位于本仓库PFPO/目录)的代码实验采用了一条“先合成、后用官方测试用例过滤、再 SFT”的路径:以deepseek-coder-7b-instruct-v1.5为底模,用 GPT-4o 按 APPs 题目批量生成解法,只保留能通过 APPs 自带input_output测试用例的解法,然后启动 SFT 训练。下面按这条路径还原仓库中给出的完整操作步骤与验证方式。

准备环境

PFPO/README.md 给出的依赖安装方式:

  • 大部分依赖列在 requirements.txt,按该文件安装即可;
  • flash-attention 需要单独自行安装(pip install,需要匹配的 CUDA/PyTorch 环境);
  • 官方也提供 docker 镜像,一条命令拉取:
docker pull jiaofangkai/normal:torch-2.5.1-vllm-0.6.4.post1-eval-1206

注意:拉取镜像只完成环境准备,不替代后续任何步骤。合成解法和过滤脚本需要网络执行环境(见下文 sandbox 说明),SFT 训练需要多机 GPU 资源(仓库中的配置按 2 台 8xV100 节点编写)。

第一步:从 APPs 训练集生成 GPT-4o 提示词

README 在 “SFT on APPs” 小节中说明,团队用一种特殊格式从 GPT-4o 收集 SFT 数据,提示词模板的生成入口是:

python scripts/apps/pp_solution_gen_inputs.py

阅读 pp_solution_gen_inputs.py 可以看到它的具体行为:

  • 从 HuggingFace 加载codeparrot/apps数据集的train分片(可用--split参数更换);
  • 对每条数据,把question字段填入内置的vanilla提示词模板(要求模型按“先分析复杂度、再逐步设计算法、最后写出 Python 程序”的顺序作答,并把代码放在<BEGIN><END>标签之间);
  • 结果写入一个 JSON Lines 文件,每行在原 APPs 字段(含questionproblem_idinput_output等)之外多出一个prompt字段。

这里有一个 README 命令中没有写出的必选参数:脚本的--output_filerequired=True,实际执行时必须指定,例如:

python scripts/apps/pp_solution_gen_inputs.py --output_file outputs/apps/apps.train.r2c.vanilla.gpt-4o.prompts.jsonl

--prompt_type默认为vanilla,当前仓库中只有这一种模板,无需修改。

生成好带prompt的请求文件后,将请求发给 GPT-4o 服务获取解法。仓库提供了两个 API 调用入口:openai_api_caller_v1.py(OpenAI API 推理入口,基于 Hydra 配置)和 service_api_caller_v1.py(服务化 API 入口)。两者都是标准的@hydra.main(config_path="conf", config_name="config")程序,用-cp/-cn指定PFPO/conf/下的配置目录与配置名来驱动。README 没有给出合成 APPs 解法这一环节对应的具体配置名,执行前请在PFPO/conf/下确认你使用的 GPT-4o 服务版本,并把产出保存为下文过滤脚本所需的 completion 文件。

第二步:用 APPs 官方测试用例过滤 GPT-4o 解法

拿到 completion 文件(GPT-4o 的原始输出)后,运行 README 给出的过滤命令:

python scripts/apps/solution_fail_extract.py --completion_file $completion_file --output_file $output_file --num_workers 16

$completion_file是上一步的 GPT-4o 输出文件,也支持 glob 模式(脚本会按problem_id去重合并多个分片文件);$output_file是过滤结果的保存路径。

阅读 solution_fail_extract.py 可以确认它的判定逻辑,这也是“可核对”的关键:

  • 用正则<BEGIN>(.*?)<END>从每条 completion 中提取代码,提取失败的解法直接判为不可用(results记为False);
  • 对提取成功的代码,调用 utils_execute.py 中的check_correctness,在 APPs 数据自带的input_output测试用例上逐条执行(超时 10 秒);
  • 某解法全部测试用例通过时才记True,只要有任一用例失败即为False
  • 结果写入$output_file,每个条目带pred(提取出的解法)、res(各 completion 是否全部通过)、full_res(逐用例结果)、outputserrors等字段。

脚本跑完后会在终端打印三行统计,这是本步骤的验证信号:

Missing: {missing / len(outputs)} Correct: {corr / len(outputs)} Correct at k: {corr_at_k / len(outputs)}

这是文档示例形式的输出模板,具体数值取决于你的 completion 数据。Missing表示无法从输出中提取出代码的比例,Correct表示首个 completion 通过全部测试用例的比例,Correct at k表示至少一个 completion 通过的比例。若Missing偏高,说明 GPT-4o 输出没有稳定遵守<BEGIN>/<END>标签格式,需要回到提示词或服务配置环节检查。

过滤产出的文件同时承担了下一个步骤的“正样本表”:SFT 配置通过extra_file从中按problem_id取出通过测试的解法。

第三步:配置并启动 SFT 训练

训练入口是trainer_base_ds_mul_fs_tp.py,README 给出的 APPs SFT 启动命令为:

torchrun --nnodes 2 --nproc_per_node 8 --node_rank $NODE_RANK --master_addr $MASTER_ADDR --master_port $MASTER_PORT trainer_base_ds_mul_fs_tp.py \ -cp conf/exp/apps/r2c_generation/deepseek_coder/sft/ -cn gpt4o-distil-v3.1-v100

$NODE_RANK$MASTER_ADDR$MASTER_PORT是两节点分布式训练的环境变量,在各节点上按你的集群设置导出。README 明确该实验运行在 2 台 8xV100 节点上;GPU 更少时,按 README 中数学部分给出的方法相应调大配置里的gradient_accumulation_steps

对应配置文件是 gpt4o-distil-v3.1-v100.yaml,其中与“GPT-4o 解法 SFT”直接相关的字段:

  • train_file: "hf:codeparrot/apps":从 HuggingFace 加载 APPs 训练集,由data.apps.APPsWithFunctionName读取(apps.py),train_sub_split: train表示先按 apps_train_sub_val_ids.json 剔除留出验证子集,use_starter_code: True表示把题目自带的 starter code 拼进question
  • extra_file: ${data_path_prefix}outputs/apps/apps.train.r2c.vanilla.gpt-4o.tem1.0.n11.exec.dpo_v1.0.json:这就是第二步过滤结果文件的路径(通过field_extract_alignerproblem_id提取pos字段,即通过测试的 GPT-4o 解法,再经recompose_template拼入训练样本)。你的实际产物路径不同时,需要在这里改成自己的文件;
  • prompt指向 r2c_prompt_0shot_v1.0.txt,与第一步的 vanilla 模板一致(要求把代码写在<BEGIN><END>之间);
  • model_name_or_path: ${model_path_prefix}/deepseek-coder-7b-instruct-v1.5model_path_prefix默认为../pretrained-models/:底模 deepseek-coder-7b-instruct-v1.5 需放在该相对路径下,或修改前缀指向你的模型目录;
  • 训练超参:learning_rate: 1e-5per_gpu_train_batch_size: 1gradient_accumulation_steps: 16max_steps: 500max_seq_length: 3072(collator 内)、fp16: Truesave_steps: 100
  • 输出目录:${output_path_prefix}experiments/${exp_name}exp_name形如deepseek-coder-v1.5-ins.7b.apps.r2c.gpt4o.distil.V100.w8.v3.1.dp4.tp4.s42,checkpoint 按save_steps周期性落盘。

训练启动后以 loss 日志(logging_steps: 5)与experiments/<exp_name>/apps/checkpoint-*目录下产出 checkpoint 作为进行中的检查点;本配置中do_eval: False,训练过程不含验证集评估。

一个需要在启动前确认的限制:该配置tp_size: 4,即启用了基于 FairScale 的张量并行(模型加载走models.llama_tp.LlamaForCausalLM.from_pretrained)。README 的 “Enable Tensor Parallel based on FairScale” 小节说明,启用张量并行前需要用scripts/model_converter/convert_llama_to_llama_tp.py把原始模型转换为张量并行格式,且该脚本目前只支持LlamaQwenMistral系列;当前仓库PFPO/scripts/model_converts/下并未包含这个转换脚本(只有llama_hf_mp_split.pypad_model_embedding.py)。因此如果你的底模不在上述受支持系列内,不能直接照搬该配置,需要先解决张量并行模型的转换问题,或参照 README 数学部分的说明把tp_size置 1 并另行处理并行配置。

结果验证:用仓库评测配置跑 SFT 模型

训练结束后,README 的 “Evaluation Configs” 小节给出的评测方式是:python vllm_inference.py -cp $config_path -cn $config_name,评测包含在推理过程中,不需要单独的评估命令。代码任务对应的配置文件:

  • APPs:conf/api/vllm/apps/deepseek_coder/r2c/dev_v2_0.yaml
  • HumanEval:conf/api/vllm/human_eval/ds_coder/r2c/test_v2_2_local.yaml
  • MBPP-257:conf/api/vllm/mbpp_sanitized/r2c/test_v1_0_local.yaml

README 的 APPs 结果表中列出了这条 SFT 路径的参考成绩(deepseek-coder-7B-v1.5底模):

阶段APPs OverallHumanEvalMBPP
底模 Instruct14.375.673.9
w/ SFT (APPs)15.472.072.8

这是论文实验值,作为判断你复现结果是否落在合理区间的参考,而不是固定预期。

边界与下一步

  • 整条链路里 GPT-4o 解法的合法性完全由 APPs 自带测试用例保证(check_correctness全通过才保留),不要把未过滤的原始 completion 直接喂给 SFT 配置;
  • solution_fail_extract.py会在本地多线程执行模型生成的 Python 代码(每条用例 10 秒超时),README 在类似的伪测试用例执行环节明确建议“in sandbox”运行,本步骤执行任意生成代码前请同样做好隔离;
  • 完成 SFT 后,README “DPO on APPs based Ground-truth Test Cases” 一节给出了下一步:用 SFT checkpoint 跑vllm_inference.py(配置conf/api/vllm/apps/deepseek_coder/r2c/train_v2_0)采样完整轨迹,再用 construct_prefer_pair.py 依据测试用例结果构造偏好对,做 DPO 训练。这属于 PFPO 偏好优化阶段,与本文的 SFT 任务是独立环节,按需参考。

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

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

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

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

立即咨询