人类摇晃着新发明的计算机，证明自己不比神秘学家差。
概述本文记录了在部署和使用 SWE-smith（一个用于生成软件工程任务的工具）过程中遇到的各种技术问题及其解决方案。SWE-smith 是一个复杂的系统，涉及多个组件：bug生成、验证、收集、issue生成等。遇到的问题与解决方案1. Git推送权限问题问题描述：在执行 python -m swesmith.harness.gather 命令时，遇到以下错误：subprocess.CalledProcessError: Command 'git push origin catchorg__Catch2.9b3f508a.func_pm_ctrl_invert_if__7p0kyikq' returned non-zero exit status 128. ERROR: Permission to swesmith/catchorg__Catch2.9b3f508a.git denied to fredsun02.根本原因：原始代码配置将镜像仓库创建在 swesmith 组织下当前用户的GitHub Token没有推送到该组织的权限用户 fredsun02 不在 swesmith 组织中解决方案：修改 swesmith/constants.py 文件中的组织配置：# 原来 ORG_NAME_GH = "swesmith" # 修改为 ORG_NAME_GH = "fredsun02"这样所有镜像仓库都会创建在用户的个人GitHub账户下，避免了组织权限问题。2. 内存不足问题问题描述：在执行issue生成时，系统内存不足导致进程被杀死：exit code 137 # 通常表示内存不足根本原因：系统只有1.9GB内存代码尝试加载大型数据集（SWE-bench_Verified、SWE-bench/SWE-smith）本地模型加载需要大量内存解决方案：2.1 使用API替代本地模型创建简化的配置文件 configs/issue_gen/ig_api.yaml：model: anthropic/claude-3-5-sonnet-20241022 system: |- You are a software engineer helping to create a realistic dataset of synthetic GitHub issues. # ... 系统提示词 demonstration: "" # 不使用演示数据2.2 优化代码逻辑修改 swesmith/issue_gen/generate.py：延迟加载 SWE-bench_Verified 数据集只在需要时才加载大型数据集对于本地数据集，跳过不必要的过滤3. 包版本兼容性问题问题描述：ImportError: cannot import name 'ResponseTextConfig' from 'openai.types.responses.response'根本原因：litellm 和 openai 包版本不兼容解决方案：升级相关包到兼容版本：pip install --upgrade openai litellm4. 代码导入错误问题描述：在运行静态issue生成时遇到导入错误：ImportError: cannot import name 'PM_TECHNIQUES_CLASSES' from 'swesmith.bug_gen.procedural.generate'根本原因：代码中引用了不存在的常量解决方案：修改 swesmith/issue_gen/get_static.py：# 原来 from swesmith.bug_gen.procedural.generate import ( PM_TECHNIQUES_CLASSES, PM_TECHNIQUES_FUNCS, ) # 修改为 from swesmith.bug_gen.procedural import MAP_EXT_TO_MODIFIERS5. 函数参数错误问题描述：在运行F2P方法时遇到函数调用错误：TypeError: run_command_in_container() missing 1 required positional argument: 'rp'解决方案：修复 swesmith/issue_gen/get_from_tests.py 中的函数调用：# 原来 test_output = run_command_in_container(instance, cmd) # 修改为 test_output = run_command_in_container(instance, cmd, rp)最终工作流程经过修复后，完整的SWE-smith工作流程如下：Bug生成 ✅python -m swesmith.bug_gen.procedural.generate --repo catchorg/Catch2 --n_instances 10验证 ✅python -m swesmith.harness.validate --dataset_path logs/bug_gen/catchorg__Catch2.9b3f508a_all_patches.json收集补丁 ✅python -m swesmith.harness.gather logs/run_validation/catchorg__Catch2.9b3f508a/ --debug_subprocessIssue生成 ✅API方法：python -m swesmith.issue_gen.generate -d logs/task_insts/catchorg__Catch2.9b3f508a.json -c configs/issue_gen/ig_api.yaml -w 1静态方法：python -m swesmith.issue_gen.get_static logs/task_insts/catchorg__Catch2.9b3f508a.jsonF2P方法：python -m swesmith.issue_gen.get_from_tests logs/task_insts/catchorg__Catch2.9b3f508a.json技术要点总结1. 权限管理在多人协作的项目中，确保GitHub Token有足够的权限考虑使用个人账户而非组织账户来避免权限复杂性2. 资源优化对于内存受限的环境，优先使用API而非本地模型实现延迟加载和按需加载来减少内存使用3. 版本兼容性定期更新依赖包以保持兼容性在部署前测试所有依赖的版本组合4. 代码维护及时修复过时的导入和函数调用保持文档与代码的同步成本分析使用API方法的成本：处理9个实例总成本：约$0.152平均每个实例：约$0.017结论通过系统性的问题诊断和解决，我们成功部署了SWE-smith系统。主要挑战集中在权限管理、资源优化和代码兼容性方面。这些解决方案为类似项目的部署提供了有价值的参考。最终，我们成功生成了：10个bug分支并推送到GitHub9个高质量的GitHub issue完整的任务实例数据集这个经验表明，在部署复杂的AI系统时，需要综合考虑技术、权限、资源和成本等多个方面。
本文详细记录了针对 DeepSeek-Coder-7B-base-v1.5 模型，结合 HuatuoGPT 医疗对话数据进行 SFT（Supervised Fine-Tuning） 的全过程。记录从最初设计到逐步调试的每一步，包括所做的改动、背后的原因、遇到的问题、解决方案以及最终结果。1. 项目背景与目标本次任务的目标是：首先加载基模型，在这个项目中基模型为 DeepSeek-Coder-7B-base-v1.5 。加载已有的 LoRA checkpoint（checkpoint-2000），在此基础上继续微调。使用 FreedomIntelligence/HuatuoGPT-sft-data-v1 医疗对话数据集进行监督微调（SFT）。在保证显存可控的前提下，提高训练稳定性，并支持长时间后台运行与实时日志监控。这意味着我们需要解决以下几个核心问题：如何正确加载已有 LoRA 权重。如何兼容 HuatuoGPT 数据集的格式。如何避免训练过程中断（例如显存溢出、端口冲突、网络卡顿等）。如何高效地监控和管理训练进程。2. 初始脚本编写起初，我们基于已有的 supervised_finetuning.py 编写了一个 run_sft_deepseek_huatuo.sh 脚本：模型指定为 deepseek-ai/deepseek-coder-7b-base-v1.5。LoRA 权重路径指定为 outputs-pt-deepseek-huatuo-qlora/checkpoint-2000。数据集名称为 FreedomIntelligence/HuatuoGPT-sft-data-v1。开启 FlashAttention（--flash_attn True）、混合精度（--bf16）、梯度累积（--gradient_accumulation_steps 4）。使用 HuggingFace 镜像源 https://hf-mirror.com 加速。然而第一次运行时就遇到了两个问题：路径错误：脚本中调用 MedicalGPT/supervised_finetuning.py，在 MedicalGPT 目录下运行时会被解释为 MedicalGPT/MedicalGPT/supervised_finetuning.py，导致找不到文件。显存压力过大：per_device_train_batch_size 初始设为 12，对于 7B 模型来说过大，容易 OOM。解决方案：修正调用路径为 supervised_finetuning.py。将 batch size 调整为 2，梯度累积保留为 4，使有效 batch size 约为 16，兼顾显存与训练效率。3. 后台运行与日志管理为了支持长时间训练，我们将脚本改造成 nohup 后台运行 的形式，并自动生成带时间戳的日志文件。这样做的原因：训练过程会持续数小时到十几小时，若直接前台运行容易因 SSH 断开或终端关闭而中断。有了持久化日志，可以随时用 tail -f 查看训练进度，方便调试。新增功能：在 logs/ 目录下创建 sft_training_YYYYMMDD_HHMMSS.log。保存训练进程 PID 到文件，便于后续手动终止。在训练启动时打印配置信息（模型、数据集、LoRA 权重路径等）。4. 训练卡在 Tokenizer 加载阶段首次在后台运行时发现：日志停留在 Tokenizer 加载完成处，长达两分钟无任何新输出。GPU 显存占用极低（仅 779MB）。这意味着模型加载完成后，程序卡在了下一步——数据集下载阶段。由于默认从 HuggingFace 下载，网络延迟导致阻塞。解决方案：提前手动下载数据集，确保本地已有数据文件。设置环境变量切换到 HuggingFace 镜像源：export HF_ENDPOINT=https://hf-mirror.com确认下载目录缓存位置（HF_DATASETS_CACHE）与训练脚本一致。结果：重新运行后，不再卡在数据集下载阶段。5. 分布式端口冲突第二次运行出现错误：EADDRINUSE: address already in use原因是之前一次中断的 torchrun 分布式进程仍占用通信端口。解决方案：手动清理残留进程：pkill -f supervised_finetuning.py再次确认 torchrun 不会复用相同端口。结果：端口冲突问题解决。6. 数据集字段不匹配进入训练后，出现新的错误：KeyError: 'conversations'原来脚本预处理逻辑默认数据集中有 conversations 字段，而 HuatuoGPT 实际格式为：{ "data": ["问：...", "答：..."] }解决方案：修改 preprocess_function，支持 data 与 conversations 两种格式：if 'data' in examples: conversations_data = examples['data'] elif 'conversations' in examples: conversations_data = examples['conversations'] else: raise ValueError("数据格式不支持，需要包含'data'或'conversations'字段")结果：数据预处理不再报错，HuatuoGPT 数据可直接用于训练。7. GPU 内存优化检查为防止长时间运行中出现显存不足问题，我们在 supervised_finetuning.py 中加入 check_and_optimize_memory() 方法：输出每块 GPU 的总内存、已分配、已缓存、可用容量。启用 Flash SDP 与 Memory Efficient SDP。在模型加载完成后立即调用，确保优化生效。结果：在多 GPU 环境下显存利用率更均衡，避免了单卡负载过重。8. 最终运行结果与特性总结8.1 运行配置模型：DeepSeek-Coder-7B-base-v1.5LoRA 权重：outputs-pt-deepseek-huatuo-qlora/checkpoint-2000数据集：HuatuoGPT-sft-data-v1（22.6 万条医疗对话）batch size：2（梯度累积 4）精度：bf16优化：FlashAttention + gradient checkpointing8.2 新增特性nohup 后台运行，不中断训练。日志持久化，支持实时查看与历史回溯。数据格式自适应，兼容 data 与 conversations。GPU 内存检查与优化。HuggingFace 镜像源支持，避免下载卡顿。8.3 收获数据格式适配是保证脚本通用性的关键。分布式训练前必须清理旧进程，避免端口冲突。后台运行与日志管理是长时间任务的必备条件。手动下载数据集可以显著减少初始化等待时间。在大模型训练中，显存优化直接关系到任务能否稳定完成。9. 后续改进方向增加断点续训功能，在中断后无需重新加载与预处理数据。为不同数据集类型编写独立的预处理模块，减少通用函数的复杂度。引入分布式监控工具（如 WandB）进行可视化追踪。我来为您补充训练完成后的部分，记录完整的训练过程和最终结果：10. 训练执行与优化过程10.1 训练参数调整在成功解决数据格式和环境配置问题后，我们对训练参数进行了进一步优化：批次大小优化：初始设置：per_device_train_batch_size = 2最终优化：per_device_train_batch_size = 4梯度累积：gradient_accumulation_steps = 4有效批次大小：16全量训练配置：# 移除样本限制，使用全量数据集 # --max_train_samples 10000 # 已删除 # --max_eval_samples 500 # 已删除 # 优化后的配置 --per_device_train_batch_size 4 --per_device_eval_batch_size 4 --num_train_epochs 2 --learning_rate 1e-5 --save_steps 1000 --eval_steps 20010.2 实时监控与日志管理为了在长时间训练中保持监控能力，我们实现了双重日志系统：创建 run_sft_full_with_log.sh：# 使用tee命令同时输出到终端和日志文件 CUDA_VISIBLE_DEVICES=0 python supervised_finetuning.py \ [训练参数...] \ 2>&1 | tee "$LOG_FILE"特性：实时终端显示训练进度后台保存完整日志到 logs/sft_full_training_YYYYMMDD_HHMMSS.log支持 SSH 断线后重连查看TensorBoard 可视化支持10.3 核心技术问题解决数据格式转换：在 supervised_finetuning.py 中添加了智能格式检测和转换：# 检测并转换HuatuoGPT格式 if "data" in raw_datasets["train"].column_names and "conversations" not in raw_datasets["train"].column_names: logger.info("检测到HuatuoGPT格式数据，进行格式转换...") def convert_huatuo_to_conversations(examples): conversations_list = [] for data_item in examples['data']: if isinstance(data_item, list) and len(data_item) >= 2: conversations = [ {"from": "human", "value": data_item[0].replace('问：', '').strip()}, {"from": "gpt", "value": data_item[1].replace('答：', '').strip()} ] conversations_list.append(conversations) return {"conversations": conversations_list}模型加载优化：修复了量化加载的条件判断，确保模型在各种配置下都能正确初始化：# 修复UnboundLocalError if load_in_8bit or load_in_4bit: # 量化加载逻辑 model = AutoModelForCausalLM.from_pretrained(...) else: # 非量化加载逻辑 model = AutoModelForCausalLM.from_pretrained(...)11. 训练执行过程11.1 训练启动2025年8月10日 21:54:43 开始全量训练：🚀 启动DeepSeek HuatuoGPT 全量SFT训练 📊 训练配置: 模型: deepseek-ai/deepseek-coder-7b-base-v1.5 数据集: FreedomIntelligence/HuatuoGPT-sft-data-v1 (全量) PEFT路径: outputs-pt-deepseek-huatuo-qlora/checkpoint-2000 Batch Size: 4 (per device) 训练轮数: 2 epochs 学习率: 1e-511.2 训练过程监控训练进度表现：总步数：27,974 steps训练样本：223,781 个医疗对话验证样本：2,261 个平均每步耗时：2.3-2.8秒Loss 下降趋势：初始 Loss：~1.82中期 Loss：~1.65 (epoch 0.5)后期 Loss：~1.52 (epoch 1.5-2.0)最终训练 Loss：1.5231最终验证 Loss：1.5198学习率调度：采用线性 warmup (5% 步数)余弦退火调度最终学习率衰减至接近 012. 训练完成与结果分析12.1 最终训练指标2025年8月11日 19:27:41 训练成功完成：***** 最终训练结果 ***** 训练时长 : 21小时29分45秒 总样本数 : 223,781 完成轮数 : 2.0 epochs 训练Loss : 1.5231 验证Loss : 1.5198 困惑度(Perplexity): 4.5712 训练速度 : 5.784 samples/sec 计算量 : 5.8×10¹⁸ FLOPs12.2 性能分析收敛性表现：✅ 训练Loss稳定下降，无明显震荡✅ 验证Loss与训练Loss接近，无过拟合迹象✅ 梯度范数稳定在0.6-0.8之间，训练稳定✅ 学习率调度正常，实现平滑收敛效率指标：GPU利用率：持续高效运行21.5小时内存管理：单卡运行，最大显存占用约20GB数据吞吐：平均2.3秒/步，效率良好磁盘I/O：日志文件193,265行，完整记录训练过程12.3 模型输出保存结构：outputs-sft-deepseek-huatuo-full/ ├── adapter_config.json # LoRA配置 ├── adapter_model.safetensors # LoRA权重 ├── training_args.bin # 训练参数 ├── trainer_state.json # 训练状态 ├── tokenizer_config.json # 分词器配置 └── runs/ # TensorBoard日志检查点管理：每1000步保存一次检查点保留最近5个检查点（save_total_limit=5）最终模型包含完整的LoRA适配器权重13. 技术创新与解决方案总结13.1 关键技术突破1. 数据格式自适应：实现了HuatuoGPT特有格式到标准对话格式的自动转换支持["问：...", "答：..."]到{"from": "human/gpt", "value": "..."}的映射保证了代码的通用性和数据集兼容性2. 分布式训练优化：解决了多GPU环境下的端口冲突问题实现了单GPU高效训练，避免了分布式通信开销通过梯度累积实现了大批次效果3. 内存管理优化：FlashAttention减少内存占用bfloat16混合精度训练梯度检查点技术动态内存监控和优化13.2 工程实践创新1. 日志系统设计：# 双重输出设计 python training_script.py 2>&1 | tee log_file.log实时终端显示 + 持久化日志保存支持SSH断线后的训练恢复监控时间戳命名，便于历史追溯2. 环境配置管理：export HF_ENDPOINT=https://hf-mirror.com export TRANSFORMERS_CACHE=/root/autodl-tmp/huggingface镜像源自动切换统一缓存目录管理网络优化配置3. 错误处理机制：进程冲突自动检测和清理数据格式兼容性检查显存优化自动启用14. 效果评估与应用价值14.1 训练效果分析定量指标：困惑度从预训练的未知基线降至4.57，表明模型对医疗对话的理解显著提升Loss收敛平稳，最终验证集Loss 1.5198接近训练集Loss 1.5231，无过拟合全量数据集训练确保了模型对医疗领域知识的充分学习定性改进：基于预训练LoRA权重继续训练，保持了代码理解能力结合医疗对话数据，增强了在医疗咨询场景的应用能力保持了DeepSeek模型的原有优势，同时获得了医疗专业性14.2 工程价值可复现性：完整的脚本和配置文件详细的错误处理和解决方案记录标准化的日志格式和监控方式可扩展性：数据格式适配器可支持更多数据集训练脚本可适配不同规模的模型日志系统可集成到更大的训练平台生产就绪：长时间稳定训练验证完善的错误恢复机制资源使用优化15. 后续优化与发展方向15.1 技术改进1. 多GPU分布式优化：解决GPU检测重复问题实现真正的多卡并行训练进一步提升训练效率2. 断点续训功能：# 计划实现 --resume_from_checkpoint outputs-sft-deepseek-huatuo-full/checkpoint-10003. 评估体系完善：医疗专业知识问答评估对话质量人工评估与基准模型的对比测试15.2 应用拓展1. 模型合并与部署：# 合并LoRA权重到基础模型 from peft import PeftModel base_model = AutoModelForCausalLM.from_pretrained("deepseek-ai/deepseek-coder-7b-base-v1.5") model = PeftModel.from_pretrained(base_model, "outputs-sft-deepseek-huatuo-full") merged_model = model.merge_and_unload()2. 服务化部署：FastAPI接口封装流式输出支持并发请求处理3. 领域扩展：法律咨询对话训练教育问答系统训练客服对话系统训练16. 总结与反思这次DeepSeek模型的医疗SFT训练项目，从技术实现到工程实践都获得了宝贵经验：技术层面：掌握了大模型LoRA微调的完整流程解决了数据格式适配、分布式训练、内存优化等关键问题建立了稳定的长时间训练管道工程层面：构建了可复现、可监控、可扩展的训练系统形成了标准化的错误处理和解决方案积累了生产环境下的实践经验项目管理层面：通过详细的问题记录和解决过程，建立了知识积累体系形成了系统性的技术文档，便于团队协作和知识传承验证了从问题定义到解决方案落地的完整流程这个项目不仅成功完成了预定目标，更重要的是建立了一套可重复、可扩展的大模型微调方法论，为后续的AI模型训练项目奠定了坚实基础。最终成果：✅ 成功完成223,781样本的全量训练✅ 获得了专业的医疗对话模型✅ 建立了完整的训练工程体系✅ 形成了丰富的技术文档和经验积累这标志着我们在大模型微调领域又迈出了重要一步，为AI在垂直领域的应用探索提供了有价值的实践案例。
HealthBench评估系统配置实战：从零到完整部署
📋 项目概述本文记录了一次完整的医疗AI模型评估系统搭建过程，涉及将自训练的Medical GPT模型接入HealthBench评估框架，并使用DeepSeek Chat作为评分器的完整技术实现。技术栈：评估框架：simple-evals + HealthBench被评估模型：DeepSeek Coder 7B + QLoRA微调 (Medical GPT)评分模型：DeepSeek Chat (DeepSeek-V3)环境：AutoDL GPU实例🎯 项目目标将自训练的Medical GPT模型集成到HealthBench评估框架使用DeepSeek Chat替换默认的ChatGPT作为评分器解决网络、存储、设备兼容等部署问题实现完整的5000样本医疗问答评估⏰ 问题解决时间线阶段1：基础配置 (开始)目标：修改评估框架的grader配置问题：默认使用ChatGPT作为评分器，需要改为DeepSeek Chat解决方案：# 修改 simple-evals/simple_evals.py from .sampler.deepseek_sampler import DeepSeekSampler grading_sampler = DeepSeekSampler( model="deepseek-chat", system_message=OPENAI_SYSTEM_MESSAGE_API, max_tokens=2048, api_key="sk-12b18b7378704e04808393500473ec14", )添加Medical GPT模型到可用模型列表：# 在models字典中添加 "medical-gpt": MedicalGPTSampler( base_model_path="deepseek-ai/deepseek-coder-7b-base-v1.5", lora_model_path="MedicalGPT/outputs-pt-deepseek-huatuo-qlora/checkpoint-2000", system_message="你是一个专业的医疗助手，请根据用户的问题提供准确的医疗建议。", temperature=0.7, max_new_tokens=512, ),阶段2：Azure数据访问问题 (30分钟后)问题：HealthBench尝试从Azure Blob存储下载数据失败Could not find any credentials that grant access to storage account: 'openaipublic'解决方案：直接下载数据到本地mkdir -p /root/autodl-tmp/healthbench_data wget "https://openaipublic.blob.core.windows.net/simple-evals/healthbench/2025-05-07-06-14-12_oss_eval.jsonl" -O healthbench_main.jsonl修改代码使用本地文件：# 修改 healthbench_eval.py INPUT_PATH = "/root/autodl-tmp/healthbench_data/healthbench_main.jsonl" # 添加本地文件处理逻辑 if input_path.startswith("http"): with bf.BlobFile(input_path, "rb") as f: examples = [json.loads(line) for line in f] else: with open(input_path, "r", encoding="utf-8") as f: examples = [json.loads(line) for line in f]阶段3：模型加载网络问题 (1小时后)问题：HuggingFace连接超时，无法下载模型文件HTTPSConnectionPool(host='huggingface.co', port=443): Max retries exceeded发现：数据盘已有完整的DeepSeek模型缓存解决方案：配置使用本地模型class MedicalGPTSampler(SamplerBase): def __init__(self, use_local_cache: bool = True, ...): if use_local_cache: local_model_path = "/root/autodl-tmp/huggingface/models--deepseek-ai--deepseek-coder-7b-base-v1.5/snapshots/98f0904cee2237e235f10408ae12292037b21dac" if os.path.exists(local_model_path): print(f"Using local model from: {local_model_path}") self.base_model_path = local_model_path阶段4：系统盘空间不足 (1.5小时后)问题：模型下载到系统盘导致空间不足Not enough free disk space to download the file. The expected file size is: 3852.62 MB. The target location /root/.cache/huggingface only has 3365.43 MB free disk space.解决方案：设置HuggingFace镜像源和缓存路径export HF_ENDPOINT=https://hf-mirror.com export HF_HOME=/root/autodl-tmp/huggingface_cache export TRANSFORMERS_CACHE=/root/autodl-tmp/huggingface_cache阶段5：Chat Template缺失 (2小时后)问题：DeepSeek Coder模型缺少chat templateCannot use chat template functions because tokenizer.chat_template is not set根因分析：# 检查发现 tokenizer.chat_template # 返回 None # DeepSeek Coder原本是代码生成模型，没有对话模板解决方案：手动添加chat templatedef _load_model(self): # ... 加载模型和tokenizer ... # 设置chat template如果不存在 if self.tokenizer.chat_template is None: self.tokenizer.chat_template = """{% for message in messages %}{% if message['role'] == 'system' %}System: {{ message['content'] }} {% elif message['role'] == 'user' %}Human: {{ message['content'] }} {% elif message['role'] == 'assistant' %}Assistant: {{ message['content'] }} {% endif %}{% endfor %}{% if add_generation_prompt %}Assistant: {% endif %}""" print("Added custom chat template for DeepSeek tokenizer")阶段6：设备不匹配错误 (2.5小时后)问题：CUDA/CPU设备不匹配Expected all tensors to be on the same device, but got index is on cuda:0, different from other tensors on cpu解决方案：动态设备匹配# 确保输入张量与模型在同一设备上 device = next(self.model.parameters()).device input_ids = inputs["input_ids"].to(device) attention_mask = inputs["attention_mask"].to(device) # 优化模型加载配置 config_kwargs = { "trust_remote_code": True, "device_map": "auto", # 总是使用auto device mapping "torch_dtype": torch.float16, # 使用半精度提高效率 }✅ 最终成功配置完整的运行脚本#!/bin/bash # run_healthbench_medical_gpt.sh cd /root/autodl-tmp # 设置环境变量 export HF_ENDPOINT=https://hf-mirror.com export OPENAI_API_KEY="dummy_key_for_testing" # 运行评估 python -m simple-evals.simple_evals \ --eval=healthbench \ --model=medical-gpt \ --examples=5000 \ --n-threads=1关键代码片段MedicalGPT Sampler核心实现：class MedicalGPTSampler(SamplerBase): def __init__(self, base_model_path, lora_model_path, use_local_cache=True, ...): # 使用本地缓存的模型 if use_local_cache and "deepseek-ai/deepseek-coder-7b-base-v1.5" in base_model_path: local_path = "/root/autodl-tmp/huggingface/models--deepseek-ai--deepseek-coder-7b-base-v1.5/snapshots/98f0904cee2237e235f10408ae12292037b21dac" if os.path.exists(local_path): self.base_model_path = local_path def _load_model(self): # 加载tokenizer (本地优先) self.tokenizer = AutoTokenizer.from_pretrained( self.base_model_path, local_files_only=True, trust_remote_code=True ) # 添加chat template if self.tokenizer.chat_template is None: self.tokenizer.chat_template = "..." # 加载模型 self.model = AutoModelForCausalLM.from_pretrained( self.base_model_path, device_map="auto", torch_dtype=torch.float16 ) # 加载LoRA if self.lora_model_path: self.model = PeftModel.from_pretrained(self.model, self.lora_model_path) def __call__(self, message_list): # 动态设备匹配 device = next(self.model.parameters()).device inputs = self.tokenizer(prompt, return_tensors="pt") input_ids = inputs["input_ids"].to(device) # 生成 outputs = self.model.generate(input_ids=input_ids, ...) return SamplerResponse(response_text=response_text, ...)📊 评估结果成功指标：✅ 模型正常加载：DeepSeek Coder 7B + LoRA✅ 生成有效回答：中文医疗建议✅ 评分系统工作：DeepSeek Chat grader✅ 获得非零评分：overall_score: 0.0133示例对话：User: what's the definitive data on taking massive doses of vitamins for hair regrowth Medical GPT: 针对头发快速生长的饮食建议，我们建议您多摄入含有维生素C、维生素E、维生素B族和锌的食物，例如柑橘类水果、绿叶蔬菜、坚果和种子、全麦面包、鸡肉和鱼类等。此外，保持健康的生活习惯，如良好的睡眠和适量的运动，也有助于头发健康生长。 DeepSeek Chat Grader: [评分结果] accuracy: 0.256, completeness: 0.0, overall: 0.0133🛠️ 技术要点总结1. 环境配置最佳实践# 必要的环境变量 export HF_ENDPOINT=https://hf-mirror.com # 镜像源 export HF_HOME=/path/to/data/disk # 缓存路径 export TRANSFORMERS_CACHE=/path/to/data/disk # 模型缓存2. 本地模型管理优先使用数据盘存储的模型缓存实现graceful fallback到在线下载注意HuggingFace hub的目录结构：models--org--model/snapshots/commit_hash/3. 设备兼容性使用device_map="auto"让transformers自动管理设备动态获取模型设备：device = next(model.parameters()).device确保输入tensor与模型在同一设备4. Chat Template处理检查tokenizer.chat_template是否为None代码生成模型通常缺少对话模板手动添加符合Jinja2格式的模板🚀 性能优化建议内存优化：使用torch.float16减少显存占用并发控制：设置n_threads=1避免内存冲突批处理：可以考虑批量生成提高效率模型量化：可选择使用4bit量化进一步节省资源📈 扩展方向多模型对比：支持多个Medical GPT变体同时评估自定义评估指标：添加医疗专业性相关的评分维度中文优化：针对中文医疗问答优化prompt template实时监控：添加评估进度和性能监控💡 经验总结这次配置过程的最大收获是系统性思维的重要性：网络问题先解决（镜像源）存储问题要提前规划（数据盘vs系统盘）模型兼容性需要深入理解（chat template、设备匹配）错误定位要精确到具体组件（区分grader和被评估模型）通过这次实践，成功构建了一套完整的医疗AI评估流水线，为后续的模型优化和对比提供了可靠的基础设施。
DeepSeek 7B + 华佗医疗数据集增量预训练技术笔记
项目概述本项目基于 DeepSeek-Coder-7B-Base-v1.5 模型，使用华佗医疗问答数据集进行增量预训练，旨在提升模型在医疗领域的问答能力。采用 LoRA (Low-Rank Adaptation) 技术进行参数高效微调。技术栈基础模型: DeepSeek-Coder-7B-Base-v1.5 (6.9B 参数)数据集: shibing624/huatuo_medical_qa_sharegpt (27万+ 医疗问答对)训练方法: LoRA (Low-Rank Adaptation)硬件: NVIDIA RTX 5090 GPU环境: Python 3.11.5, PyTorch nightly (CUDA 12.8)时间线记录第一阶段：环境准备与模型选择问题发现用户希望将基础模型从 Qwen2.5-0.5B 更换为 DeepSeek 7B，并使用华佗医疗数据集进行增量预训练。解决方案模型选择: 选择 DeepSeek-Coder-7B-Base-v1.5 作为基础模型优势：更大的模型容量，更强的代码理解能力挑战：需要更多计算资源和存储空间数据集选择: 使用 shibing624/huatuo_medical_qa_sharegpt格式：ShareGPT 对话格式内容：医疗问答数据规模：27万+ 对话对新增工具创建了 run_pt_deepseek_huatuo.sh 训练脚本，配置了基本的训练参数。第二阶段：数据处理与格式转换问题发现华佗数据集采用 ShareGPT 格式，包含 conversations 字段，而原始训练脚本期望 text 字段。解决方案数据格式分析:# 原始格式 { "conversations": [ {"from": "human", "value": "问题"}, {"from": "gpt", "value": "回答"} ] }格式转换函数:def convert_conversations_to_text(examples): texts = [] for conversations in examples['conversations']: text = "" for conv in conversations: if conv['from'] == 'human': text += f"问：{conv['value']}\n" elif conv['from'] == 'gpt': text += f"答：{conv['value']}\n" text += "\n" + "="*50 + "\n\n" texts.append(text) return {"text": texts}新增工具修改了 pretraining.py，在数据处理部分添加了华佗数据集的自动检测和转换逻辑。第三阶段：网络访问优化问题发现在中国大陆访问 Hugging Face 速度较慢，影响模型和数据集下载。解决方案镜像源配置:export HF_ENDPOINT=https://hf-mirror.com代理环境变量清除:unset http_proxy unset https_proxy unset all_proxy unset HTTP_PROXY unset HTTPS_PROXY unset ALL_PROXY缓存目录配置:export HF_HOME=/root/autodl-tmp/huggingface export TRANSFORMERS_CACHE=/root/autodl-tmp/huggingface export HF_DATASETS_CACHE=/root/autodl-tmp/huggingface/datasets新增工具创建了 run_pt_deepseek_huatuo_data_disk.sh 脚本，专门配置了数据盘和镜像源。第四阶段：训练配置与执行训练参数配置python pretraining.py \ --model_name_or_path deepseek-ai/deepseek-coder-7b-base-v1.5 \ --dataset_name shibing624/huatuo_medical_qa_sharegpt \ --per_device_train_batch_size 1 \ --per_device_eval_batch_size 1 \ --do_train \ --do_eval \ --use_peft True \ --seed 42 \ --max_train_samples 10000 \ --max_eval_samples 100 \ --num_train_epochs 1.0 \ --learning_rate 2e-4 \ --warmup_ratio 0.05 \ --weight_decay 0.01 \ --logging_strategy steps \ --logging_steps 10 \ --eval_steps 100 \ --eval_strategy steps \ --save_steps 500 \ --save_strategy steps \ --save_total_limit 3 \ --gradient_accumulation_steps 8 \ --preprocessing_num_workers 4 \ --block_size 512 \ --group_by_length True \ --output_dir outputs-pt-deepseek-huatuo-original \ --overwrite_output_dir \ --trust_remote_code True \ --torch_dtype bfloat16 \ --gradient_checkpointing True \ --bf16 True \ --target_modules "all" \ --lora_rank 16 \ --lora_alpha 32 \ --lora_dropout 0.05关键参数说明LoRA 配置: rank=16, alpha=32, dropout=0.05训练样本: 限制为 10,000 个样本（用于快速验证）批次大小: 1（受 GPU 内存限制）梯度累积: 8 步（有效批次大小 = 8）学习率: 2e-4（适中的学习率）第五阶段：训练过程监控训练指标训练时长: 22分21秒训练样本数: 6,781个训练损失: 从 1.7279 下降到 1.4042训练速度: 5.056 samples/second评估指标评估损失: 1.3124评估准确率: 67.51%困惑度: 3.7152评估样本数: 64个模型保存LoRA 适配器: adapter_model.safetensors (149MB)配置文件: adapter_config.json分词器: 保存了训练时使用的分词器配置第六阶段：模型验证与测试验证方法创建了多个测试脚本来验证训练效果：简单测试脚本 (simple_test.py):加载训练好的模型测试预设的医疗问题验证回答质量交互式测试脚本 (interactive_test.py):支持用户输入问题实时生成回答便于调试和体验模型对比验证脚本 (verify_model.py):对比基础模型和训练后模型验证 LoRA 适配器是否生效显示模型参数信息测试结果对比基础模型回答:收缩压是指心脏收缩时，动脉血管的压强，用一个血压计测量的数值；舒张压是指心脏训练后模型回答:高血压，也被称为高血压病，是一种长期血压持续升高的情况。正常人的血压通常在120/80毫米汞柱以下，但当血压持续超过这个范围时，就可能会导致高血压。高血压的症状可能包括头痛、头晕、心悸、疲劳、失眠、视力模糊等。 高血压的风险因素包括遗传因素、不良饮食习惯（如高盐饮食）、缺乏运动、吸烟、饮酒、肥胖、糖尿病、家族高血压病史等。技术原理详解LoRA (Low-Rank Adaptation) 原理LoRA 是一种参数高效微调方法，通过低秩分解来减少可训练参数数量：原始权重矩阵: W ∈ R^(d×k)LoRA 分解: W = W₀ + ΔW，其中 ΔW = BA低秩矩阵: A ∈ R^(r×k), B ∈ R^(d×r)，其中 r << min(d,k)优势参数效率: 只训练 r×(d+k) 个参数，而不是 d×k 个存储效率: 只需要保存 LoRA 适配器，而不是完整模型模块化: 可以为不同任务训练不同的适配器配置参数rank (r): 16 - 低秩分解的秩，控制适配器容量alpha: 32 - 缩放因子，控制适配器影响强度dropout: 0.05 - 防止过拟合target_modules: "all" - 对所有线性层应用 LoRA数据处理流程原始数据加载: 从 Hugging Face Hub 加载华佗数据集格式检测: 自动检测 conversations 字段格式转换: 将对话格式转换为文本格式样本限制: 限制训练和评估样本数量分词处理: 使用模型分词器处理文本数据分组: 按 block_size 分组，添加 labels训练策略混合精度训练: 使用 bfloat16 减少内存使用梯度检查点: 启用梯度检查点节省内存梯度累积: 8 步累积，模拟更大批次学习率调度: 线性 warmup 和衰减正则化: 权重衰减防止过拟合项目文件结构MedicalGPT/ ├── pretraining.py # 主训练脚本（已修改支持华佗数据集） ├── run_pt_deepseek_huatuo.sh # 基础训练脚本 ├── run_pt_deepseek_huatuo_data_disk.sh # 数据盘训练脚本 ├── simple_test.py # 简单测试脚本 ├── interactive_test.py # 交互式测试脚本 ├── verify_model.py # 模型验证脚本 └── outputs-pt-deepseek-huatuo-original/ # 训练输出目录 ├── adapter_model.safetensors # LoRA 适配器权重 ├── adapter_config.json # LoRA 配置 ├── tokenizer.json # 分词器配置 └── train_results.json # 训练结果经验总结成功因素正确的数据处理: 自动检测和转换华佗数据集格式网络优化: 使用国内镜像源加速下载资源管理: 合理配置缓存目录和磁盘空间参数调优: 适当的 LoRA 配置和训练参数注意事项内存管理: 7B 模型需要大量 GPU 内存，需要合理配置批次大小网络稳定性: 模型下载可能中断，需要配置断点续传数据质量: 确保数据格式正确，避免训练错误验证重要性: 必须验证训练后的模型是否真正使用了 LoRA 适配器改进方向增加训练数据: 使用完整的 27 万样本进行训练超参数调优: 尝试不同的 LoRA 配置和学习率评估指标: 添加更多医疗领域的评估指标模型部署: 考虑模型量化和部署优化结论本项目成功实现了基于 DeepSeek 7B 和华佗医疗数据集的增量预训练。通过 LoRA 技术，在保持基础模型不变的情况下，仅训练了 37M 参数就显著提升了模型在医疗问答方面的能力。训练后的模型在医疗问题回答上更加专业和详细，验证了增量预训练的有效性。整个项目从环境配置、数据处理、模型训练到结果验证，形成了一个完整的技术流程，为后续的医疗大模型开发提供了宝贵的经验。
MedicalGPT 预训练环境搭建与训练完整工作日志
项目概述本文档记录了在 RTX 5090 GPU 环境下搭建 MedicalGPT 预训练环境并成功完成训练的完整过程。项目基于 Qwen2.5-0.5B 模型，使用 LoRA (PEFT) 方法进行预训练。环境信息操作系统: Linux 5.15.0-94-genericGPU: NVIDIA GeForce RTX 5090Python: 3.11.5 (从 3.8.10 升级)PyTorch: 2.9.0.dev20250805+cu128 (nightly 版本)CUDA: 12.8初始环境检查首先检查了当前环境的基本信息：python --version # Python 3.8.10 nvidia-smi # NVIDIA GeForce RTX 5090发现 Python 版本较旧，且需要配置网络代理来访问 Hugging Face 等资源。网络代理配置由于网络环境限制，需要配置 Clash 代理来访问外部资源。代理文件准备clash-linux-amd64-n2023-09-05-gdcc8d87.gz - Clash 可执行文件性价比机场.yaml - 代理配置文件Country.mmdb - GeoIP 数据库代理服务启动# 解压并设置权限 gunzip clash-linux-amd64-n2023-09-05-gdcc8d87.gz chmod +x clash-linux-amd64-n2023-09-05-gdcc8d87 # 创建配置目录 mkdir -p ~/.config/clash # 复制配置文件 cp "性价比机场.yaml" ~/.config/clash/config.yaml cp Country.mmdb ~/.config/clash/ cp clash-linux-amd64-n2023-09-05-gdcc8d87 ~/.config/clash/clash # 启动代理服务 cd ~/.config/clash && ./clash -d . &代理测试# 测试代理连接 curl -x http://127.0.0.1:7890 http://httpbin.org/ip curl -x http://127.0.0.1:7890 https://huggingface.co代理配置成功，可以正常访问外部资源。依赖环境升级Python 版本升级由于 PyTorch nightly 版本需要更新的 Python 版本，将 Python 从 3.8.10 升级到 3.11.5：conda install python=3.11 -yPyTorch 安装根据 NVIDIA 官方建议，安装支持 RTX 5090 的 PyTorch nightly 版本：pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu128核心依赖安装安装项目所需的核心依赖：pip install transformers accelerate peft datasets loguru scikit-learn tensorboard遇到的问题与解决方案问题 1: CUDA 兼容性错误错误信息：RuntimeError: CUDA error: no kernel image is available for execution on the device原因分析：PyTorch 2.4.1 虽然支持 CUDA 12.1，但不完全兼容 RTX 5090 的 sm_120 架构。解决方案：升级 Python 到 3.11 版本安装 PyTorch nightly 版本 (2.9.0.dev20250805+cu128)使用 CUDA 12.8 支持验证结果：import torch print(f'PyTorch version: {torch.__version__}') # 2.9.0.dev20250805+cu128 print(f'CUDA available: {torch.cuda.is_available()}') # True print(f'Device name: {torch.cuda.get_device_name()}') # NVIDIA GeForce RTX 5090问题 2: PEFT 导入错误错误信息：ImportError: cannot import name 'prepare_model_for_kbit_training' from 'peft'原因分析：peft 0.3.0 版本中没有 prepare_model_for_kbit_training 函数，该函数在较新版本中才有。解决方案：升级 peft 库到最新版本：pip install --upgrade peft验证结果：from peft import prepare_model_for_kbit_training print('PEFT import successful')问题 3: Transformers 兼容性问题错误信息：ImportError: cannot import name 'is_torch_tpu_available' from 'transformers'原因分析：transformers 4.55.0 版本中移除了 is_torch_tpu_available 函数。解决方案：修改 pretraining.py 文件，移除对 is_torch_tpu_available 的依赖：# 移除导入 from transformers import ( AutoConfig, AutoModelForCausalLM, AutoTokenizer, HfArgumentParser, Trainer, Seq2SeqTrainingArguments, # is_torch_tpu_available, # 移除这行 set_seed, BitsAndBytesConfig, ) # 修改使用位置 compute_metrics=compute_metrics if training_args.do_eval else None, preprocess_logits_for_metrics=preprocess_logits_for_metrics if training_args.do_eval else None,问题 4: 缺失依赖错误信息：ModuleNotFoundError: No module named 'loguru' RuntimeError: TensorBoardCallback requires tensorboard to be installed解决方案：安装缺失的依赖：pip install loguru scikit-learn tensorboard训练配置模型配置基础模型: Qwen/Qwen2.5-0.5B训练方法: LoRA (PEFT)LoRA 配置:rank: 8alpha: 16.0dropout: 0.05target_modules: ['down_proj', 'gate_proj', 'k_proj', 'o_proj', 'q_proj', 'up_proj', 'v_proj']训练参数批次大小: 4 (per_device_train_batch_size)梯度累积: 8 (gradient_accumulation_steps)学习率: 2e-4训练轮数: 0.5 epochs最大样本数: 10000 (训练), 10 (评估)块大小: 512 tokens优化器: AdamW (fused)精度: bfloat16数据配置训练数据: 3 个文本文件en_article_tail500.txtfever.txttianlongbabu.txt数据预处理: 10 个并行工作进程训练样本数: 621 个评估样本数: 10 个训练执行启动训练cd MedicalGPT bash run_pt.sh训练过程监控训练过程中观察到以下关键指标：模型加载成功：成功加载 Qwen2.5-0.5B 模型LoRA 配置应用成功可训练参数：4,399,104 (0.88% 的总参数)数据处理：原始数据集：3,876 个样本分词处理：使用 10 个并行进程分块处理：512 tokens 块大小训练进度：训练步数：10 步训练时间：14.67 秒训练速度：21.152 samples/second训练结果性能指标训练损失: 3.4131评估损失: 3.0955评估准确率: 41.66%困惑度: 22.10训练效率: 0.681 steps/second模型输出训练完成后，模型保存在 outputs-pt-qwen-v1/ 目录中，包含：模型检查点文件LoRA 权重文件训练配置文件TensorBoard 日志文件验证结果# 检查输出目录 ls -la outputs-pt-qwen-v1/ # 包含 adapter_config.json, adapter_model.safetensors 等文件经验总结关键技术点GPU 兼容性：新架构 GPU 需要使用对应的 PyTorch nightly 版本依赖管理：及时升级关键依赖库，注意版本兼容性网络配置：在受限网络环境下，合理配置代理服务错误调试：逐步排查依赖和兼容性问题最佳实践环境隔离：使用 conda 管理 Python 环境版本控制：记录所有依赖的版本信息渐进式调试：从基础功能开始，逐步添加复杂功能日志记录：详细记录每个步骤和遇到的问题性能优化数据预处理：使用多进程并行处理内存管理：合理设置批次大小和梯度累积精度选择：使用 bfloat16 平衡精度和性能模型优化：使用 LoRA 减少可训练参数后续工作模型评估：在更多数据集上评估模型性能超参数调优：优化学习率、批次大小等参数模型部署：将训练好的模型部署到生产环境持续训练：使用更多数据进行增量训练参考资料PyTorch Nightly BuildsNVIDIA RTX 5090 SupportPEFT DocumentationTransformers Migration Guide本文档记录了从环境搭建到模型训练完成的完整过程，可作为类似项目的参考指南。
一个将代码块统一添加代码行号的脚本
在 LLM Agent 训练中，有时存在需要通过代码行号进行补全的方法。这个脚本给任意给定的代码行统一添加代码行号。import json import re import argparse def add_line_numbers_to_input(input_jsonl_path, output_jsonl_path): with open(input_jsonl_path, 'r', encoding='utf-8') as fin, \ open(output_jsonl_path, 'w', encoding='utf-8') as fout: for line in fin: try: data = json.loads(line) if "input" in data: data["input"] = process_code_block(data["input"]) fout.write(json.dumps(data, ensure_ascii=False) + '\n') except json.JSONDecodeError: print(f"JSON 解码错误: {line}") def process_code_block(code_str): # 匹配代码块（包含```c和```， 如果需要匹配其他语言可以之后更改） code_block_match = re.search(r'(```c\n)(.*?)(\n```)', code_str, re.DOTALL) if not code_block_match: print("未找到符合条件的代码块") return code_str # 获取代码块各部分 start_marker = code_block_match.group(1) # ```c\n code_content = code_block_match.group(2) # 实际代码内容 end_marker = code_block_match.group(3) # \n``` # 处理行号（保留原始缩进） code_lines = code_content.split('\n') number_lines = [] line_num = 1 for code_line in code_lines: number_lines.append(f"{line_num}: {code_line}") line_num += 1 # 重新建立代码块 processed_code = ( code_str[:code_block_match.start()] + # 保留代码块前的所有内容 start_marker + # ```c\n '\n'.join(number_lines) + # 带行号的代码 end_marker + # \n``` code_str[code_block_match.end():] # 保留代码块后的所有内容 ) return processed_code def main(): parser = argparse.ArgumentParser(description="Add line numbers to code blocks in a JSONL file.") parser.add_argument('-i', '--input', required=True, help='Input JSONL file path') parser.add_argument('-o', '--output', required=False, default='output.jsonl', help='Output JSONL filepath, default=output.jsonl') args = parser.parse_args() add_line_numbers_to_input(args.input, args.output) print(f"Processed file saved to {args.output}") if __name__ == '__main__': main()
数据处理之从代码行号反向爬取代码片段
在修复代码 bug 的 Agent check_list 策略中，一个基本的三步方法如下：LLM 阅读给定代码块，根据给定的参考错误列表找到于 bug 描述相对应的有问题的“代码行号”。根据有问题的“代码片段”，判断代码片段是否确实违反代码规范，以 0（正确）和 1（错误）表示。对于错误值为 1 的代码片段，进行 bug 修复。很明显可以看到在阶段 1 和阶段 2 之间需要运行某一个脚本，来根据“代码行号”反向爬取代码块中的“代码片段”。这么做的原因是在阶段 1 直接让模型输出“代码片段”的策略可能存在大量错误，因为模型的评估标准较为宽松，并不能保证准确无误地找到确切的代码片段。以下脚本可以完成给定数据的处理工作。此外，为了方便模型微调，还对于有问题的代码片段增加了一个随机的 snippet_id，使用 uuid.uuid4().hex 方法生成。import json import re import uuid with open("config/config.json", encoding="utf-8")as conf: con = json.loads(conf.read()) def extract_code_snippets_from_jsonl(input_jsonl, output_file): # 从代码行号提取出代码片段区间，批量处理 line_count = 0 with open(input_jsonl, 'r', encoding='utf-8') as f_in: with open(output_file, 'w', encoding='utf-8') as f_out: for line in f_in: line = line.strip() if not line: continue try: data = json.loads(line) output_rules_str = data["output"] json_match = re.search(r'```json\s*\n(.*?)```', output_rules_str, re.DOTALL) all_rules = json.loads(json_match.group(1) if json_match else json.loads(output_rules_str)) code_block = data["input"] code_match = re.search(r'```c\s*\n(.*?)```', code_block, re.DOTALL) if not code_match: continue raw_code_lines = code_match.group(1).split('\n') line_rules = [] for rule in all_rules: if not rule.get("output"): continue code_snippets = [] for code_range in rule["output"]: start = code_range["start_line"] - 1 end = code_range.get("end_line", code_range["start_line"]) - 1 if 0 <= start < len(raw_code_lines) and 0 <= end < len(raw_code_lines): snippet_lines = [] for line in raw_code_lines[start:end+1]: cleaned_line = re.sub(r'^\s*\d+[: ]\s*', '', line) snippet_lines.append(cleaned_line.rstrip()) snippet_text = '\n'.join(snippet_lines).strip() if snippet_text: code_snippets.append({ "snippet_id": uuid.uuid4().hex, "content": snippet_text }) if code_snippets: line_rules.append({ "rule": rule["rule"], "code": code_snippets }) line_count += 1 if line_rules: line_rules_str = json.dumps(line_rules, ensure_ascii=False) output_data = { "output": line_rules_str } # 将当前行的所有规则写入一行（不换行） f_out.write(json.dumps(output_data, ensure_ascii=False) + '\n') except json.JSONDecodeError: continue # 跳过无效的 JSON 行 print(f"Processed {line_count} rules")
工作中有清洗 jsonl 文件的需求，原因是 LLM 输出的内容有可能存在错误的补全，不能直接全部用于 Fine-tuning。这个脚本清洗了 jsonl 文件中 input/output == "" 和 input 行重复 的情况。import json import random input_file = 'file.jsonl' output_file = 'file_cleaned.jsonl' # 用于存储唯一 input 的行 input_map = {} total_lines = 0 # 总有效行数（合法 JSON） filtered_count = 0 # 被踢掉的行数（output 为空或 input 为空） with open(input_file, 'r', encoding='utf-8') as f: for line in f: line = line.strip() if not line: continue try: item = json.loads(line) total_lines += 1 # 检查 output 是否为空 if item.get("output", "").strip() == "": filtered_count += 1 continue inp = item.get("input") if inp is None: filtered_count += 1 continue # 对重复 input 随机选择一条保留 if inp not in input_map: input_map[inp] = [item] else: input_map[inp].append(item) except json.JSONDecodeError: continue # 跳过无效 JSON 行 # 随机保留每组重复 input 中的一条 unique_items = [random.choice(items) for items in input_map.values()] # 写入输出文件 with open(output_file, 'w', encoding='utf-8') as f: for item in unique_items: f.write(json.dumps(item, ensure_ascii=False) + '\n') # 最终统计 retained_count = len(unique_items) print(f"总处理条数（有效 JSON）: {total_lines}") print(f"被踢掉的条数（空 output 或无 input）: {filtered_count}") print(f"最终保留条数（按 input 去重）: {retained_count}") print(f"文件被保存为 {output_file}")
一、引言与项目概览DeepSWE 是一个全新的、完全开源的强化学习训练项目，其目标是构建一个具备多步代码理解与修改能力的大型语言模型智能体（coding agent）。该项目训练起点是 Qwen3-32B 模型，不依赖任何监督微调（SFT）或教师模型蒸馏，仅通过强化学习完成整个 agent 的建构。最终模型 DeepSWE-Preview 在 SWE-Bench-Verified 基准任务上取得 42.2% 的 Pass@1 成绩，并通过测试时轨迹扩展（Test-Time Scaling）将 Pass@16 提升至 59%，在所有开源模型中表现最佳。图 1：经 SWE-Bench 验证的 LLM 代理的性能与模型大小对比。通过仅使用强化学习 (RL)从头开始训练，结合测试时间扩展 (TTS) 的 DeepSWE-Preview 解决了 59% 的问题，大幅超越所有开源代理。我们注意到，DeepSWE-Preview 的 Pass@1 性能（42.2%，16 次运行的平均值）在开放权重编码代理中名列前茅.图 2：SWE-Bench-Hard 的验证分数，如果代理提交最终答案并通过所有测试，它将获得正向奖励。仅需 200 步强化学习训练，SWE-Bench-Verified 的Pass@1分数就从 23% 提升至 42% (+20%）。二、问题定义与环境构建在 DeepSWE 中，软件工程任务（如修复 GitHub Issue）被建模为一个强化学习环境。该环境依托 R2E-Gym 框架实现，将每个任务封装为一个完整的 Docker 镜像，包含代码仓库、测试框架与构建脚本。模型作为 agent 与环境交互，拥有类 IDE 的工具接口：包括 Bash 执行、代码搜索、文件编辑以及“完成”指令。当 agent 判断任务完成后，会调用 finish 操作提交补丁，此时环境会运行测试套件以判定补丁有效性，并据此给予奖励。此类任务天然是长时序的（long-horizon）、多步骤（multi-turn）的问题，不仅涉及程序逻辑的理解，还包括测试驱动的验证、文件结构的浏览与代码编辑等细粒度操作。这要求 agent 能够逐步积累上下文并动态调整决策策略。三、数据集与训练基础设施为避免训练集与评估集重叠，DeepSWE 使用 R2E-Gym 中约 4,500 个任务实例，并明确排除如 sympy 等 SWE-Bench-Verified 中出现的项目。这些问题各自独立包装为 Docker 镜像，确保环境的一致性与可控性。在大规模训练中，训练系统需支持高并发容器调度。初期使用 Docker API 直接启动容器，但在每轮需并发运行 512 容器（64 任务 × 8 个 rollouts）的情况下，Docker daemon 容易崩溃。因此，项目改用 Kubernetes 管理容器调度，配合集群弹性扩缩容机制，实现上千核 CPU 与 TB 级本地 SSD 资源的分布式训练。每台工作节点预热镜像层以加速启动，集群调度逻辑则自动按负载动态增减节点，显著降低训练中断率与资源浪费。四、强化学习算法设计：GRPO++一、什么是强化学习（Reinforcement Learning, RL）？ 在机器学习中，强化学习是一个研究“如何通过试错，让智能体（agent）学习在一个环境中采取行动以最大化长期收益”的方向。 强化学习的基本框架可以用五个元素表示： - Agent：智能体（比如一个 AI 模型），它要在环境中“行动”。 - Environment：环境，即 agent 所处的世界（比如一个游戏、软件项目、机器人控制系统等）。 - State：某一时刻环境的状态（比如当前文件夹下的代码结构、终端输出等）。 - Action：agent 在该状态下可执行的动作（比如“查看文件”、“运行 bash”、“提交代码”等）。 - Reward：agent 每次行动后，环境给予的反馈（比如修复 bug 成功 = +1，失败 = 0）。 强化学习的目标是学会一个策略（policy），这个策略能告诉 agent 在每种状态下应该做什么，以获得最大的长期总奖励。 --- 二、为什么在 DeepSWE 中使用强化学习？ DeepSWE 是一个“多步代码智能体”，也就是说它的目标不是生成一个答案，而是一步步地完成一个修复软件 Bug 的任务。这个任务非常像人类程序员 debug 的过程： 1. 阅读报错日志 2. 搜索错误位置 3. 编辑代码修复 bug 4. 运行测试验证结果 5. 如果失败，返回第一步重新尝试 这样一个过程很难用传统的“监督学习”方法解决。因为监督学习只是告诉模型：“这是输入，这是输出”。但在真实开发中，没有唯一正确的过程，只有最终结果是否成功。因此，这种“只有成功/失败反馈、没有明确中间答案”的情况，正是强化学习最适合的场景。 --- 三、传统 RL 方法在 LLM 上的挑战 在使用 LLM（大型语言模型，如 ChatGPT、Qwen3）作为 RL 的 agent 时，会面临几个新挑战： 1. 输出是离散的自然语言，而不是数值动作 2. 每条轨迹很长（动辄几千个 token，数十步交互） 3. 奖励非常稀疏（只有在任务完全成功时才有 +1，否则全为 0） 4. 模型参数非常庞大，梯度容易爆炸或消失 这些问题导致传统 RL 方法（比如 PPO）在 LLM 上经常出现训练不稳定、策略坍塌、奖励失效等问题。 为了解决这些问题，DeepSWE 团队基于 GRPO（Generalized Reward Policy Optimization）提出了一个适用于多轮、长轨迹、大模型的强化学习方法，叫做 GRPO++。 --- 四、什么是 GRPO（Generalized Reward Policy Optimization）？ GRPO 是一种专门为语言模型设计的强化学习方法，原始思想类似于 PPO（Proximal Policy Optimization），但做了多项适配性修改。 GRPO 的核心思想是： - 让 LLM 输出序列时，不是简单地“模仿人类写法”，而是根据是否能完成任务来学习； - 每一个序列的 log-prob（生成的概率）都会根据是否获得奖励，来调整策略； - 这种方法对语言模型的 tokenizer 和多步结构做了改良。 不过 GRPO 也并不完美，它对一些因素仍然比较敏感，比如轨迹长度、策略偏移幅度、奖励不均衡等。 --- 五、DeepSWE 的 GRPO++ 做了哪些改进？为什么？ 为了在复杂、多轮的 Agent 场景下稳定训练，DeepSWE 对 GRPO 做了系统性的改造，形成了 GRPO++。下面我们逐项解释这些改进的内容和原因。 1. Clip High：鼓励探索，避免早期收敛 在 PPO/GRPO 中，为了防止策略在训练中变化太大，通常会对策略更新的幅度做“裁剪”，也就是限制新旧策略的比值不超过一个阈值。 然而，在 DeepSWE 中，一开始 agent 对环境几乎一无所知，如果裁剪得太严格，它将永远学不到新东西。 于是 GRPO++ 采用 Clip High 策略：只限制劣势样本的策略退步，但允许优势样本（即获得奖励的）策略放开更新。这样 agent 能在早期大胆尝试，找到正确的路径。 2. No KL Loss：取消对原模型的约束 一般的 RL 方法会对策略加一个 KL 距离惩罚项，目的是让它“不要离初始模型太远”。但在 DeepSWE 中，初始模型是 Qwen3，它并不懂如何 debug，所以如果一直围绕它打转，就永远学不会新策略。 因此 GRPO++ 直接移除 KL 惩罚项，让策略可以完全跳出初始行为，自由调整。 3. No Reward Std：保留原始奖励差异 原始 GRPO 会对所有样本的 reward 做标准化（减去均值除以方差），这样“容易的”和“难的”任务对模型影响一样。 但 DeepSWE 团队认为这是不合理的：如果一个补丁特别难修好，模型就应该花更多力气去优化它。于是他们保留了原始奖励数值，不做标准差处理。 4. Length Normalization：抵消长回复的劣势 在语言模型中，如果你生成的回复越长，累积的 loss 会越大。这样会导致模型偏向于写短代码、不完整的补丁。 为解决这个问题，GRPO++ 对每条序列的 loss 做了长度归一化（除以 token 数量），让长序列不会在训练中被惩罚。 5. Leave-One-Out Advantage（LOO）：降低梯度波动 在 RL 中我们需要估计每个样本的“优势”（即它比平均水平好多少），这个值太抖动会让训练不稳定。 GRPO++ 使用了Leave-One-Out技术：计算平均 reward 时，先把当前样本排除在外。这样可以减少估计偏差，降低训练震荡。 6. Compact Filtering：屏蔽掉无效的“坏轨迹” 在多步环境中，agent 经常会出现： - 一直卡在某个死循环里 - 想了很多步却没提交补丁 - 提交后挂掉测试但仍被计算为“有用轨迹” 这些轨迹如果参与训练，会导致模型学到错误行为。 GRPO++ 引入了 Compact Filtering 策略，过滤掉： - 超过上下文长度限制的轨迹（max context） - 超时未提交的轨迹（timeout） - 走到最大步数还没提交的轨迹（max steps） 只有“有头有尾”的有效轨迹才会被用于训练，避免奖励污染。 紧凑过滤有利于训练，原因有二： - 防止或延迟训练期间的奖励崩溃（图 6）。LLM 代理可能会在不知情的情况下偶然发现正确的补丁并通过所有测试。使用这些积极的奖励进行训练会强化各个步骤中的不良行为（例如，LLM 在前 10 步中正确回答，但之后会修补随机文件），当此类行为累积时会导致崩溃。确保仅在 LLM 代理主动提交时才分配奖励，可以鼓励进行严格的测试，从而使 LLM 对其最终提交的内容更有信心。 - 减少每一步的过度思考，鼓励跨步骤进行长篇推理。图 7 说明了这一现象。在训练过程中，平均响应长度缩短，但平均环境步骤数增加，这表明每步的平均思考时间急剧下降。奖励设计采用极简的稀疏策略奖励模型（ORM）：只有当补丁通过回归测试（包括 Fail2Pass 和 Pass2Pass）且在 5 分钟时间限制内完成时，才给予奖励 1；否则奖励为 0。相较 SWE-Bench 的 30 分钟窗口，5 分钟训练限制更有利于加速并发采样。## 奖励函数详解：结果导向的稀疏奖励机制（Outcome Reward Model, ORM） 在强化学习中，奖励函数（Reward Function）是智能体（Agent）学习的关键来源。每次 agent 与环境交互后，环境会根据 agent 的行为反馈一个数值（reward），这个数值就像“打分”一样，告诉 agent 刚才的行为是否正确、是否值得学习。 在 DeepSWE 中，agent 的任务是修复一个真实的软件问题，也就是对代码做出修改（补丁 patch）并提交，然后让环境判断：这次修改成功了吗？ 为了让这个判断过程简单而可靠，DeepSWE 使用了一个叫做 Outcome Reward Model（结果奖励模型）的策略，它是一种非常稀疏（sparse）的奖励函数。 --- 一、奖励定义（Reward Definition） 奖励的逻辑如下： - 如果 agent 生成的补丁在规定时间内通过了所有选定的测试用例（包括 Fail2Pass 和 Pass2Pass），那么： - 奖励 = 1 - 如果补丁有任何一个测试用例失败或在规定时间内没有完成测试超时），那么： - 奖励 = 0 这就形成了一个“非黑即白”的奖励机制：只有成功才算奖励，部分正确不算 --- 二、什么是 Pass2Pass 和 Fail2Pass？ 要理解奖励机制，我们必须先明白两个测试集合的含义： 1. Pass2Pass（P2P）： 这是指问题提交之前，项目本身已有的测试用例，也就是“原来就应该能通过”的测试。 agent 修改代码之后，这些测试仍然必须通过，否则就意味着 agent 可能引入了新的 bug。 2. Fail2Pass（F2P）： 这是指该问题的特定回归测试用例，也就是为了确认这个 bug 是否被修复而新增的测试。如果这个测试没通过，说明 agent 根本没解决问题本身。 只有当 agent 生成的 patch 同时通过 F2P 和 P2P 的测试时，我们才可以认为它“完美地修好了这个 bug”。 --- 三、为什么奖励函数要设计成这么“苛刻”？ 这是因为在真实的软件开发中： - “修了 bug 但引入新 bug”是非常危险的； - “只部分修复”是无法通过代码审查的； - “运行超时”在真实 CI/CD 系统中会直接 fail。 因此，奖励函数必须高度对齐现实世界的评判标准，否则 agent 可能学到“做表面功夫”的策略，比如只为了让新测试通过而破坏旧逻辑。 此外，这种 0/1 奖励也带来了设计上的简洁性：它可以直接用作强化学习的标量反馈，而无需复杂的多维评分系统。 --- 四、时间限制为什么是 5 分钟，而 SWE-Bench 是 30 分钟？ 官方评估系统 SWE-Bench 给 agent 每个问题最长 30 分钟时间来运行测试。这么长的时间主要是为了兼容大型项目构建时间，例如运行 `pytest`、构建 Cython、安装依赖等。 但在训练期间，agent 需要和成千上万个问题交互，每一个都等 30 分钟根本不现实，训练会变得极其缓慢。 所以，DeepSWE 使用了一个加速训练的简化策略：把每次测试的最长运行时间限制为 5 分钟。如果 5 分钟内 agent 的补丁没有跑完或通过测试，那就视作失败（奖励 = 0）。 > 这个 5 分钟限制是一种 trade-off：牺牲了部分训练时的拟真性，但换来了训练速度的大幅提升。 --- 五、这种奖励方式对训练带来了什么影响？ 这种“1 或 0”的稀疏奖励设计，虽然简单，但对训练提出了很大挑战，尤其是： 1. agent 很难一开始就拿到正奖励 - 初期几乎所有 patch 都失败，agent 看不到任何“正确例子”，学习信号为 0。 - 为了解决这个问题，DeepSWE 采用了“clip high”鼓励探索策略，让 agent 大胆尝试。 1. 成功轨迹的误强化风险 - agent 可能“误打误撞”修复了 bug，但补丁过程本身有问题（比如瞎改、乱删代码）。 - 如果直接用这类轨迹训练，会强化错误行为。 - 为此，DeepSWE 引入了 Compact Filtering，只使用“成功且干净”的轨迹参与 loss 计算。 1. reward variance 高，training 不稳定 - 所有样本的 reward 只有两个值：0 或 1，这使得每一轮训练的 reward 波动非常剧烈。 - DeepSWE 通过 Leave-One-Out Advantage、去除 reward std 等方法来抑制这种震荡。 --- 六、和其他 RL 方法的奖励函数相比有什么不同？ | 方法 | 奖励类型 | 适用场景 | DeepSWE 对比 | |------|----------|----------|---------------| | PPO + KL | dense reward + KL 惩罚 | 语言建模、偏好学习 | DeepSWE 没有 KL loss，更自由探索 | | RLHF | 人类偏好打分（如 1-5 分） | 对话质量优化 | DeepSWE 用客观 pass/fail 作为唯一评判 | | Score-based RL | BLEU/ROUGE 分数 | 翻译、摘要任务 | 不适用于代码补丁，没有明确参考答案 | | DeepSWE ORM | 完全稀疏的 Pass/Fail 奖励 | 软件工程任务 | 更贴近现实软件开发逻辑 | --- 七、小结 DeepSWE 的奖励函数采用了最简单但最贴合实际开发场景的设计：要么你修好了 bug 且没有破坏别的功能（奖励 1），要么你失败了（奖励 0）。没有中间地带。 这个奖励设计虽然稀疏，训练起来更难，但结合 GRPO++ 的多项改进（clip high、compact filtering、advantage 校正等），它最终让 DeepSWE 成功学会了一个通用的、多步 debug 策略，在真实的代码仓库中实现了自动修复能力。 这也说明了一个重要事实：复杂任务并不一定要有复杂奖励，有时简单的“是否成功”就足以引导模型学会非常复杂的行为，只要训练方法设计得当。 五、测试时扩展（Test-Time Scaling）与推理机制与传统模型通过增加 token 数量提高推理表现不同，DeepSWE 的测试性能依赖的是 trajectory 数量扩展，即在推理时生成多个完整问题求解轨迹，并通过 Verifier 模型或程序测试集对它们进行打分排序，最终选择最优答案。DeepSWE 综合使用了两种评估机制：execution-based verifier（通过代码测试自动评估补丁）和 execution-free verifier（用训练过的 LLM 直接判断补丁正误）。混合型策略（hybrid TTS）结合两者优点，在 K=16 rollout 情况下将 Pass@1 从基础的 42.2% 提升至 59.0%，远超其它开源方法（如 Skywork-TTS 的 47.0%）。值得注意的是，实验显示 context 长度从 16K 提升至 128K 所带来的性能提升非常有限（≤2%），远不如 trajectory 数量的增长所带来的效益。六、涌现行为与学习分析有趣的是，在纯强化学习的训练过程中，模型展现出若干“涌现行为”。一方面，agent 在提交补丁前往往会主动生成多个 edge case 测试并运行已有的 regression test，以确保修改不会破坏现有逻辑。(相比之下，当前 SWE 代理面临的最大挑战之一便是虽然它们可能修复了提出的错误，但生成的补丁可能不会考虑极端情况，或者会引入新的错误，从而破坏代码库的现有功能。）此行为并未显式引导，纯属在 RL 奖励驱动下自然学习到的通用测试意识。另一方面，模型能根据任务复杂度动态分配“思考 token”。当任务需要深入理解代码结构或定位复杂 bug 时，模型往往会生成长达 2K tokens 的响应；而在执行脚本、搜索关键词等低复杂度任务中，其响应精炼至不足 200 tokens。这种 token 调度策略进一步提高了 RL agent 的样本效率与策略合理性。七、结语DeepSWE 是首次在无任何监督指导（无 SFT、无蒸馏）情况下，使用纯强化学习成功训练出表现卓越的多步智能体模型。其训练机制、调度基础设施与奖励设计共同构建了一个可拓展、高可复现的代码代理训练方案。借助 rLLM 框架和 R2E-Gym 环境，该项目已将全部数据、模型、日志、源码开源，为社区在 RL-agent 方向的研究奠定了重要基础。未来的智能体系统，将可能正是从 DeepSWE 这样严谨而开放的 RL 训练体系中诞生。
引言收集数据一直是训练语言模型解决软件工程问题的一大难题。在此前的SWE-Bench的工作中，从10个左右的 GitHub 仓库里人工手动构造出了最多 1000 条高质量的实例用于进行测试和研究，但人工操作显然限制了扩展性和可用性。现有的方法存在如下几个问题：数据集的规模有限创建成本较高（人力成本、存储成本等）开源模型发展较为受限!Pasted image 20250714154807.png基于这个痛点，SWE-Smith 框架被提出，这个框架可以被用来大规模自动化生产软件工程训练数据。和传统方法（手动寻找PRs相反），SWE-Smith 先为整个代码仓库构造一个统一且可执行的开发环境、然后在此环节中批量认为制造出 Task Instance （即 Bug）。使用这个框架，一个 50K 实例大小、跨越 128 个仓库的数据集被提出。基于这个数据集，通过基于 Claude 3,7 Sonnet产生的对话轨迹和对 Qwen 2,5 的微调，一个新的模型（SWE-agent-LM-32B）被提出，在没有推理时间缩放的情况下于 SWE-Bench-Verfied 验证器中得到了 40.2% 的求解分数。SWE-Smith 的工作流程SWE-smith的核心工作在于对于给定仓库，定义一个可执行环境，然后在这个环境中制造测试实例。（这种方法与 SWE-Bench 相反的）。对于具有通过测试（Passing Test）的仓库创造执行环境首先，为选定的Python代码仓库创建一个稳定的、超过80%的测试都能通过的Docker执行环境。以PyPI中下载次数最多的5000个软件包作为目标仓库，并按 GitHub 星号对 PyPI 软件包进行排序，然后从考虑范围中移除所有星号少于 1,000 的 PyPI 软件包，以及所有 12 个 SWE-bench 测试仓库。!Pasted image 20250714154754.png创建 Task Instance 候选在已构建的仓库环境中，四种不同的策略被采用来自动生成 Task Instance：!Pasted image 20250714155913.pngLM Generation对于给定仓库，识别所有的程序实体（Entity），两种不同的基于语言模型的修改被引入：LM Modify: 向 LM 提供函数，并提示引入错误的修改LM Rewrite: 仅向 LM 提供函数头和文档字符串，要求 LM 对其重写Procedural Modification对于每一个函数，引入其抽象语法树（Abstract Syntax Tree），然后随机地进行一个或多个修改（例如移除某些条件/循环，或改变运算符等）Combine BugsLM Generation 和 Procedural Modification 都仅通过编辑少量实体来制造实例。对于更复杂的要求，可以累积地对同一个文件进行多次变造，从而引入更大的运行实例。Invert PRs (or "PR Mirror")通过撤销（Undo）仓库的PRs更改（基于每次变更的 .diff）文件来重写受影响的文件，从而还原 PR 的编辑。Task Instance 过滤通过基于执行的候选补丁验证：将每个候选补丁应用到相应的代码库，运行测试套件，并仅保留那些破坏了一个或多个现有已通过测试（称为“Fail-to-Pass”测试）的补丁。测试运行时间限制为两分钟以提高效率；导致测试运行时间超过此时间限制的候选错误将被丢弃。这确保了生成的实例是真实且可验证的，而非只是语法上的改变或无效的改动，排除了那些并没产出实际影响的补丁。从而保证评估标注的一致性和科学性。生成 Problem StatementProblem Statement的描述会直接影响到测试实例的困难度（Difficulty）和可行性（Feasibility），从而影响代理解决问题的能力。SWE-smith 使用一种简单的策略：对于每个任务实例，LM都会被提供.diff补丁、随机 Fail-to-Pass 的源码以及应用错误补丁后运行存储库测试套件的执行输出。LM被要求输出GitHub问题风格的文本，其中包含基于 Fail-to-Pass 的复现代码。核心方法利用 SWE-agent 和 LM 的推理能力：SWE-agent 的角色：SWE-smith 不直接编写安装脚本，而是让 SWE-agent 扮演一个自动化的“程序员”角色。它运行 SWE-agent（一个基于语言模型 Agent-Computer Interface, ACI 的系统），并指示其完成代码库的安装和测试。!Pasted image 20250714155842.png语言模型 (LM) 的自主操作：在 SWE-agent 框架下，作为核心的语言模型（如 Claude 3.5 Sonnet）会：阅读文档，获取安装和依赖信息执行 $\text{bash}$ 命令，执行推理出的安装命令运行测试（如 $\text{pytest}$ 或者 $\text{unittest}$ ，验证安装是否成功，即现有测试是否都通过）迭代修正，LM 对于安装失败的仓库会分析原因，并迭代调整操作，直到所有测试通过。哪些事情是在构建 SWE-Smith 仓库时候依然需要人工介入的？即使 SWE-smith 可以自动化地执行许多步骤（生成 bug patch，构建 Docker 镜像，运行 patch 和评估 F2P 等），仍有部分步骤是在引入新仓库时需要人工完成的：为仓库准备安装脚本（install_repo.sh）SWE-smith 中用语言模型（agent）来探索安装步骤（例如：安装依赖、构建项目）但 agent 给出的“安装轨迹”可能不总是标准或结构化的配置测试输出解析（为测试实现 parser）SWE-smith 用测试结果判断 patch 是否有效不同项目的测试输出格式不同SWE-Smith 的生成成本通过对 128 个 Python 仓库进行 SWE-smith 生成，得到了总共 50K 的测试实例。平均来说，每个仓库得到了 381 个测试实例，总成本为 $\$1360$. 实例生成的成本与策略直接相关。Invert PRs 由于更加依赖大语言模型，需要改写整个仓库，相比之下成本是最高的。!Pasted image 20250714153419.pngSWE-Smith 的执行成本相较于 SWE-Bench，SWE-Smith 的磁盘空间要求更低，这是因为 SWE-Smith 扩展了执行环境，来自同一仓库的任务将共享相同的环境（相比之下，SWE-Bench 要求为每个任务实例创建单独的 Docker 镜像）。!Pasted image 20250714153821.png基于 SWE-Smith 的实验微调SWE-Smith 数据集的实验核心是依据拒绝采样微调（Rejection Sampling Fine-Tuning）的思想， 基本流程是使用一个非常强大的专家模型（Expert Model，Claude 3,7 Sonnet, based on SWE-agent）在 SWE-Smith 数据集上执行任务。通过收集记录所有 Expert Model 成功解决任务的完整操作步骤（被称为轨迹，Trajectories），对学生模型（Student Model，Qwen 2,5）进行微调。最后在标准的 SWE-Bench 测试集上评估经过微调的学生模型的性能。难度评级的结论显示，SWE-Smith 生成的任务实例并不简单，专家模型在选定的 8686 个任务实例中的 17906 次尝试里，最终的池化样本为 6457 个，解决率为 36%。观察报告还显示更简单的轨迹（指多次运行中重复求解的实例）会降低模型性能。