Shiranai - 开发随想
type: channel
link: http://43.138.70.71/index.php/category/coding/
description: 人类摇晃着新发明的计算机，证明自己不比神秘学家差。
items: SWE-smith 部署与问题解决技术报告
items: DeepSeek + HuatuoGPT SFT 调试全记录
items: HealthBench评估系统配置实战：从零到完整部署
items: DeepSeek 7B + 华佗医疗数据集增量预训练技术笔记
items: MedicalGPT 预训练环境搭建与训练完整工作日志
items: 一个将代码块统一添加代码行号的脚本
items: 数据处理之从代码行号反向爬取代码片段
items: 一个清洗 jsonl 文件的小脚本
items: DeepSWE: 基于纯 RL 训练的 Agent
items: SWE-Smith 是如何工作的？

SWE-smith 部署与问题解决技术报告
type: item
date: 2025-08-21T12:28:45+00:00
description: 概述本文记录了在部署和使用 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生成…

DeepSeek + HuatuoGPT SFT 调试全记录
type: item
date: 2025-08-10T14:46:00+00:00
description: 本文详细记录了针对 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": ["问：...", "答：..."] }解决方案：修改 pre…

HealthBench评估系统配置实战：从零到完整部署
type: item
date: 2025-08-10T14:36:00+00:00
description: 📋 项目概述本文记录了一次完整的医疗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-ba…

DeepSeek 7B + 华佗医疗数据集增量预训练技术笔记
type: item
date: 2025-08-06T03:25:29+00:00
description: 项目概述本项目基于 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_ra…

MedicalGPT 预训练环境搭建与训练完整工作日志
type: item
date: 2025-08-06T01:59:25+00:00
description: 项目概述本文档记录了在 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_…

一个将代码块统一添加代码行号的脚本
type: item
date: 2025-08-02T16:45:33+00:00
description: 在 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()

数据处理之从代码行号反向爬取代码片段
type: item
date: 2025-08-02T04:26:00+00:00
description: 在修复代码 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 } # …

一个清洗 jsonl 文件的小脚本
type: item
date: 2025-08-02T04:22:00+00:00
description: 工作中有清洗 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: 基于纯 RL 训练的 Agent
type: item
date: 2025-08-01T09:26:50+00:00
description: 一、引言与项目概览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. 如果失败，返回第一步重新尝试 这样一个过程很难用传统的“监督学习”方法解决。因为监督学习只是告诉模型：“这是输入，这是输出”。但在真实开发中，没有唯一正确的过程，只有最终结果是否成功。因此，这种“只有成…

SWE-Smith 是如何工作的？
type: item
date: 2025-08-01T09:23:00+00:00
description: 引言收集数据一直是训练语言模型解决软件工程问题的一大难题。在此前的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) 的自主操作：在 S…