Open-Assistant StackExchange 指令数据集构建全流程解析:从 XML 归档到 Parquet 训练数据

Open-Assistant StackExchange 指令数据集构建全流程解析:从 XML 归档到 Parquet 训练数据 Open-Assistant StackExchange 指令数据集构建全流程解析从 XML 归档到 Parquet 训练数据【免费下载链接】Open-AssistantOpenAssistant is a chat-based assistant that understands tasks, can interact with third-party systems, and retrieve information dynamically to do so.项目地址: https://gitcode.com/gh_mirrors/op/Open-Assistant本文以 Open-Assistant 仓库中 data/datasets/oa_stackexchange 目录为线索完整讲解如何将 Stack Exchange 全站历史问答归档Internet Archive 提供的 XML 转储转换为可用于 SFT 指令微调的 Instruction 数据集。读者将掌握「下载 → XML 流式解析 → 过滤与格式转换 → 统计 → 合并 → 上传 Hugging Face」六阶段流水线的每步操作、关键参数长度阈值、评分阈值、每站最大答案数及对应的源码实现细节并能直接复现出与仓库发布版本一致的数据集。一、数据集概览What WhyStack Exchange 是互联网上规模最大的高质量问答社区网络覆盖编程、数学、物理、烹饪、棋类等数百个垂直主题站点。Open-Assistant 从 Internet Archive 的 stackexchange 归档下称归档中提取帖子数据构建了名为Open-Assistant StackExchange Instructionpretty name的指令数据集。该数据集最终以单个合并后的 parquet 文件形式发布并带有以下数据集卡片信息见 data/datasets/oa_stackexchange/README.md 的 YAML frontmatter字段值数据列INSTRUCTION、RESPONSE、SOURCE、METADATAanswer_score、question_score、tagssplitstrain 单折6,331,083 条样本数据大小dataset_size ≈ 6,549,838,664 字节约 6.1 GiBdownload_size ≈ 3,755,782,987 字节licensecc-by-sa-4.0遵循 Stack Exchange 数据许可languageen、uk、ru、de、fr、it、es 等数据源于归档中各站点公开的Posts.xml文件原始提取代码由 b-mc2 定义的 Instruction 数据集规范四列INSTRUCTION、RESPONSE、SOURCE、METADATA。数据集的核心过滤规则归档中包含各站点的全部帖子问题、回答、评论等本数据集按如下规则过滤README.md 与 process.py 双重印证仅保留有被采纳回答accepted answer的帖子线程问题与回答的字符长度均小于 1000 字符源码常量MAX_LENGTH 1000其他回答、无采纳答案的问题、过长条目一律丢弃。也就是说每一行代表一个「问题 → 被采纳回答」的高质量问答对天然契合指令微调所需的 INSTRUCTION/RESPONSE 结构。每行数据结构每行包含四列INSTRUCTION由问题标题Title与问题正文BodyHTML 转 Markdown 后拼接而成格式为Title\nBody_markdownRESPONSE被采纳回答正文HTML 转 Markdown 后SOURCE固定格式stackexchange-{site_name}例如stackexchange-ai用于标注数据出处便于训练时做去重与溯源METADATAJSON 结构包含tags站点标签如python pandas、question_score问题评分、answer_score回答评分。二、数据集复现流水线五步操作仓库在oa_stackexchange目录下提供了完整的可复现脚本链依次执行即可从原始 XML 归档重建整个数据集第 1 步下载全部 XML 文件将归档中所有站点的Posts.xml下载到xml/目录./download.pydownload.py 的实现要点先请求归档目录页解析 HTML 表格拿到全部*.7z归档文件名并对站点名做归一化处理如meta.stackoverflow.com转为meta_stackoverflow再拼出view_archive.php的直链使用ThreadPoolExecutorNUM_PARALLEL 20并发下载跳过_meta与stackoverflow.com-命名的文件RE_IGNORE正则已有缓存xml/{name}.xml存在时直接复用避免重复下载注意stackoverflow.com-Posts.7z体积约 18GB脚本特意提示手动下载或用 torrentstackexchange_archive.torrent的 658 号文件解压后重命名为xml/stackoverflow.xml放入目录即可。第 2 步解析 XML、过滤并转换为 OA 格式./process.py不带参数时process.py 会自动扫描xml/*.xml逐个处理也可以显式传入站点名只处理特定站点。每个站点输出到parquet/{site}.parquet。第 3 步统计各站点样本数./stats.pystats.py 遍历parquet/下所有 parquet 文件用 pyarrow 的ParquetDataset统计每个站点的行数并打印- {topic}: {count:,}格式的清单即 README 中统计列表的来源。第 4 步合并为单一 parquet 文件./combine.pycombine.py 将full/目录下的 parquet 全部合并为stackexchange.parquet合并前会再做一次长度收紧INSTRUCTION 与 RESPONSE 均 1000 字符并清洗 METADATA 字段打印每个文件的缩短比例合并逻辑由 merge_parquets.py 实现——它通过 pyarrow 流式读写ParquetWriter逐表写入、iter_batches逐批读取并用coalesce按行数默认max_size 2**20分批拼接避免大文件一次性载入内存。第 5 步上传 Hugging Face Hub./upload.py先执行huggingface-cli login完成认证然后运行./upload.pyupload.py 使用datasets库加载本地stackexchange.parquet并push_to_hubmax_shard_size500MB自动分片最终上传到donfu/oa-stackexchange。完整流程也符合仓库总则 data/datasets/README.md 中「Convert → Login → Push → 更新 HF README」的规范步骤。三、源码级深入process.py 的解析与过滤原理3.1 流式 SAX 解析应对超大 XMLStack Exchange 的 Posts.xml 动辄数 GB如 stackoverflow 的 Posts.xml 超过 60GB无法整体载入内存。parse_and_convert采用lxml.etree.iterparse的end 事件流式解析context etree.iterparse(path, events(end,)) for _, element in tqdm(context, totaltotal_rows): if element.tag row: if len(element.get(Body)) MAX_LENGTH: continue rows.append(parse_row(element)) element.clear() while element.getprevious() is not None: del element.getparent()[0]关键点预先用grep -c row统计总行数用于 tqdm 进度条MAX_LENGTH 1000正文超长直接跳过这是 README 所述「长度 1000」的底层实现element.clear()配合删除前序兄弟节点及时释放已处理节点的内存每处理10**6行或全部完成时将累积行构造 DataFrame、调用convert_to_oa转换随后del df / del oa / gc.collect()强制回收内存——即分块批处理模式。parse_row从 XML 属性中提取Id、PostTypeId、Body、Title、Tags、Score、AcceptedAnswerId、ParentId八个字段缺失字段用 0 或空串兜底。3.2 问答配对以内连接实现「有采纳答案」过滤convert_to_oa是过滤逻辑的核心questions all[all[AcceptedAnswerId] ! 0] merged pd.merge( questions, all, howinner, left_onAcceptedAnswerId, right_onId, suffixes(_q, _a), )即先筛出所有带AcceptedAnswerId的问题再与该问题表自身按AcceptedAnswerId Id做 inner join把问题行与被采纳回答行拼成一对。没有采纳答案的问题、以及未被采纳的其他回答都在这一步自然被丢弃。之后构造四列merged[INSTRUCTION] merged[Title_q] \n merged[Body_q].apply(to_markdown) merged[RESPONSE] merged[Body_a].apply(to_markdown) merged[SOURCE] source merged[METADATA] merged.apply(create_metadata, axis1)注意脚本还定义了MAX_ANSWERS 10、QUESTION_SCORE_TRESHOLD 0、ANSWER_SCORE_TRESHOLD 0等常量其中后两者在 join 前可作为评分下限过滤的扩展点当前版本未启用该过滤仅保留常量。3.3 正文清洗HTML → Markdown去链接去 emoji问答正文是 Stack Exchange 的 HTML 片段直接喂给模型会引入大量噪声。to_markdown做了三级清洗用html2text(text, bodywidth0)将 HTML 转为 Markdown转换失败时退化为正则剔除所有...标签用正则\[([^\]])\]\(([^\)])\)将 Markdown 链接text替换为纯文本text再用https?:\/\/[^\s]删除残余裸链接remove_emojis按 Unicode 区块emoticons、symbols pictographs、transport map、flags、dingbats 等剔除 emoji。3.4 标签清洗与元数据convert_tags将 Stack Exchange 的分隔的原始标签串如pythonpandas转换为人类可读的逗号分隔文本python, pandas同时把-替换为空格如machine-learning→machine learning。create_metadata最终产出{ tags: python, pandas, question_score: 42, answer_score: 7, }3.5 落盘规范save_parquet使用 pandas 的to_parquet并强制row_group_size100, enginepyarrow, indexFalse——这正是 data/datasets/README.md 规定的仓库级数据格式要求parquet 必须带row_group_size100与indexFalse保证全仓库数据集格式统一。四、统计结果数据集覆盖面与规模README 中列出的按站点统计的样本数来源于stats.py输出展示了该数据集的广度。以下节选若干代表站点站点样本数站点样本数stackoverflow4,269,779ru_stackoverflow106,714math501,019serverfault81,229superuser128,488askubuntu78,472unix54,338gaming44,899english42,415electronics41,717tex42,808physics35,386apple32,603gis30,249ell30,428salesforce27,962pt_stackoverflow27,650blender25,527wordpress24,270sharepoint24,934......合计约 180 个站点6,331,083值得注意的几点长尾明显stackoverflow 与 math 两个站点贡献了约 75% 的样本而bioacoustics70、cseducators71、conlang101、interpersonal199等小众站点样本极少为数据集带来跨领域多样性多语言覆盖包含es_stackoverflow、ja_stackoverflow、pt_stackoverflow、ru_stackoverflow、ukrainian、chinese、japanese、french、german等非英语站点与数据集卡片标注的 7 种语言一致可用于多语言 SFT 训练含 meta 站点meta_stackoverflow、meta_askubuntu等元站点也被收录需注意这类站点内容以社区治理讨论为主使用时可结合 METADATA 的 tags 按需过滤。五、数据集在训练链路中的使用方式该数据集按仓库规范属于Instruction 数据集data/datasets/README.md 中明确定义必须含INSTRUCTION、RESPONSE、SOURCE、METADATA四列。在模型训练侧model/model_training的 SFT 训练器会读取这类指令样本并与对话式数据混合使用——以 model/model_training/custom_datasets/oasst_dataset.py 为例其load_oasst_export会按DatasetEntrySftconversation由Utterance(text, role, ...)序列组成组织样本role取prompter/assistant对应到本数据集即为INSTRUCTION → prompter、RESPONSE → assistant。用户可仿照该模式将本数据集的问答对映射为 SFT 对话样本参与微调METADATA 中的question_score、answer_score还可作为质量加权或过滤的依据。六、复现注意事项与边界磁盘与内存全部 XML 解压后体积庞大仅 stackoverflow 一项约 60GB建议按站点分批处理且process.py的分块批处理与merge_parquets.py的流式合并都明确针对大文件场景设计依赖process.py需要pandas、lxml、html2text、tqdm、pyarrowdownload.py需要requests、beautifulsoup4upload.py需要datasets与huggingface_hub网络要求归档托管于 Internet Archive下载依赖其可用性stackoverflow.com-Posts.7z建议走官方提示的 torrent 方式许可证数据遵循 Stack Exchange 的 CC BY-SA 4.0 许可归档详情页亦有说明使用与再分发时须保留署名并遵守相同许可条款上游引用原始提取与转换思路来自 b-mc2 的公开代码本仓库脚本在此基础上适配了 Open-Assistant 的四列 Instruction 格式。七、小结oa_stackexchange数据集是 Open-Assistant 训练数据体系中最具规模的指令数据集之一它以 Stack Exchange 的「问题 被采纳回答」结构为天然指令对通过「仅保留有采纳答案、双方均 1000 字符」的过滤策略控制质量与长度借助iterparse流式解析 pandas 批处理 pyarrow 流式合并解决了超大数据集的内存瓶颈最终以统一四列 Schema 的 parquet 文件交付。仓库内的 download.py、process.py、stats.py、combine.py、upload.py 五步脚本链即为完整可复现的参考答案开发者可在此基础上调整长度阈值、评分阈值或站点白名单构建属于自己的 Stack Exchange 指令数据集。【免费下载链接】Open-AssistantOpenAssistant is a chat-based assistant that understands tasks, can interact with third-party systems, and retrieve information dynamically to do so.项目地址: https://gitcode.com/gh_mirrors/op/Open-Assistant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考