""" CoT 数据清洗脚本 功能: 1. 自动识别 think 模式新数据 / 旧数据两种格式 - 新数据 (think 模式): [草稿] Ref-Delta → 丢弃草稿,将 Ref-Delta 包入 - 旧数据: [Ref-Delta] (保持原逻辑) 2. 处理重复 标签 3. 验证必要字段完整性 4. 输出清洗报告 用法: python clean_cot_data.py input.jsonl -o output.jsonl python clean_cot_data.py input.jsonl # 覆盖原文件 """ import re import sys import json import argparse from pathlib import Path def clean_response(response: str, gt_answer: str = "") -> tuple[str, list[str]]: """清洗单条 response,返回 (清洗后文本, 修复记录列表)""" fixes = [] # ---- 1. 保护 和 块 ---- answer_match = re.search(r"(.*?)", response, re.DOTALL) answer_block = answer_match.group(0).strip() if answer_match else "" kf_match = re.search(r"(.*?)", response, re.DOTALL) kf_block = kf_match.group(0).strip() if kf_match else "" # ---- 2. 识别格式:新(think模式) vs 旧 ---- # 新格式特征:Ref-Delta 在 之后(草稿在 内部) # 旧格式特征:Ref-Delta 在 内部 think_match = re.search(r"(.*?)(.*)", response, re.DOTALL) is_new_format = False if think_match: after_think = think_match.group(2) if "Reference frame at" in after_think or "" in after_think: is_new_format = True if is_new_format: # 新格式:丢弃 内的草稿,取 之后的 Ref-Delta 作为内容 after_think = think_match.group(2) content = re.sub(r".*?", "", after_think, flags=re.DOTALL) content = re.sub(r".*?", "", content, flags=re.DOTALL) content = content.strip() fixes.append("think模式新格式: 去除内部草稿,保留Ref-Delta") n_think_open = n_think_close = 1 else: # 旧格式:去掉所有 标签,内容原样保留 body = response body = re.sub(r".*?", "", body, flags=re.DOTALL) body = re.sub(r".*?", "", body, flags=re.DOTALL) n_think_open = len(re.findall(r"", body)) n_think_close = len(re.findall(r"", body)) content = re.sub(r"", "", body).strip() # ---- 3. 清理 think 内容 ---- # 3a. 把 bullet list 转为散文 (去掉行首 - • * 符号) if re.search(r"^\s*[-•*]\s", content, re.MULTILINE): lines = content.split("\n") cleaned_lines = [] for line in lines: stripped = re.sub(r"^\s*[-•*]\s+", "", line) if stripped != line: fixes.append(f"去除bullet: {line.strip()[:60]}") cleaned_lines.append(stripped) content = "\n".join(cleaned_lines) # 3b. 把 "At