Shiranai - 开发随想
type: channel
link: https://fredss.cn/index.php/category/coding/
description: 人类摇晃着新发明的计算机，证明自己不比神秘学家差。
items: 从强化学习到近端策略优化（PPO）
items: Post-LN Transformer 训练不稳定性的数学分析
items: MetaGPT Agent 动态 Action 机制详解
items: SWE-smith 部署与问题解决技术报告
items: DeepSeek + HuatuoGPT SFT 调试全记录
items: HealthBench评估系统配置实战：从零到完整部署
items: DeepSeek 7B + 华佗医疗数据集增量预训练技术笔记
items: MedicalGPT 预训练环境搭建与训练完整工作日志
items: 一个将代码块统一添加代码行号的脚本
items: 数据处理之从代码行号反向爬取代码片段

从强化学习到近端策略优化（PPO）
type: item
date: 2025-12-06T15:59:00+00:00

Post-LN Transformer 训练不稳定性的数学分析
type: item
date: 2025-12-05T09:59:00+00:00

MetaGPT Agent 动态 Action 机制详解
type: item
date: 2025-11-09T04:15:18+00:00
description: 概述本文档详细记录了如何在 MetaGPT 框架中实现一个具有动态 Action 创建能力的 Agent。通过本教程，你将深入理解 MetaGPT 的 React 机制（run → react → think → act）以及如何在运行时动态切换 Action 序列。作业目标：创建一个 Agent，初始化时拥有三个动作：Print1, Print2, Print3顺序执行这三个动作执行完毕后，动态生成新的动作：Print4, Print5, Print6继续顺序执行新动作学习重点：MetaGPT 的 React 循环机制状态管理（state, todo, actions）动态 Action 创建与替换Python 对象引用与多态核心概念1. MetaGPT 的 React 机制┌─────────────────────────────────────┐ │ run(message) │ │ - 接收消息并存入 memory │ │ - 调用 react() │ └──────────────┬──────────────────────┘ ↓ ┌─────────────────────────────────────┐ │ react() │ │ - while True 循环 │ │ - think() → 决定下一个动作 │ │ - 检查 todo 是否为 None │ │ - act() → 执行当前动作 │ └──────────────┬──────────────────────┘ ↓ ┌──────────────┴──────────────────────┐ │ │ │ ┌─────────────┐ ┌──────────────┐ │ │ │ think() │ │ act() │ │ │ │ 分配下一个 │ │ 执行当前 │ │ │ │ 动作 │ │ 动作 │ │ │ └─────────────┘ └──────────────┘ │ │ │ └─────────────────────────────────────┘2. 关键属性self.actions # 动作列表 [Action1, Action2, ...] self.states # 状态列表 ['0. Action1', '1. Action2', ...] self.rc.state # 当前状态索引 (int) self.rc.todo # 当前要执行的动作 (Action 对象或 None)3. 状态转换# _set_state() 方法的作用 def _set_state(self, state: int): self.rc.state = state self.rc.todo = self.actions[state] if state >= 0 else None状态值含义：state = -1 → 无任务，todo = Nonestate = 0 → 执行第一个动作，todo = actions[0]state = 1 → 执行第二个动作，todo = actions[1]以此类推...完整实现Step 1: 定义 Action 类from metagpt.actions import Action from metagpt.logs import logger class PrintAction(Action): """简单的打印动作 Args: name: 动作名称 content: 要打印的内容 """ name: str = "PrintAction" content: str = "" async def run(self, *args, **kwargs) -> str: """执行打印操作""" logger.info(f"执行 {self.name}: {self.content}") return self.content关键点：继承自 Action 基类run() 方法必须是 async（因为可能调用 LLM）返回执行结果（字符串）Step 2: 定义 Agent 类框架from metagpt.roles.role import Role, RoleReactMode from metagpt.schema import Message class SimpleAgent(Role): """简单的顺序执行 Agent Args: name: 角色名称 profile: 角色描述 """ name: str = "SimpleAgent" profile: str = "Simple Sequential Agent" phase: int = 1 # 当前阶段（1 或 2） def __init…

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 } # …