章节导航 第 30 章 / 共 30 章
端到端案例、工具与未来展望
一个从数据到 7B 模型的端到端案例,配套工具链,以及对数据工程未来的判断(含附录)。
“纸上得来终觉浅,绝知此事要躬行。“——两本书讲过的所有方法论,都将在本章第一部分被串成一条完整的实战主线。
“预测未来最好的方法是创造它。“——而在走完全程之后,我们再抬头看看这个领域正在驶向何方。
本章是《AI数据全书》的收官章,整合自《AI数据工程》与《大模型数据工程》的最后几个章节,分为四个部分:
- 第一部分:端到端 7B 案例——从需求定义到最终评估,完整走一遍一个 7B 模型的数据工程全流程,把散落在前面各章的方法论全部串起来;
- 第二部分:工具链全景——预训练与后训练工具栈、关键工具详解、平台建设与溯源、管线编排,以及 Llama 3、DeepSeek、Qwen、Kimi K3 的数据工程拆解;
- 第三部分:未来趋势——数据墙、合成数据代际演进、多模态、Agent 数据、持续学习、数据飞轮、法律合规与开放问题;
- 第四部分:附录资源——数据集一览、工具速查表、质量评估 Checklist 与推荐阅读。
第一部分:端到端案例——从零构建一个 7B 模型的数据
前面各章讲了大量的方法论和技术细节,这一部分我们把它们全部串起来——从需求定义到最终评估,完整走一遍一个 7B 模型的数据工程全流程。
30.1 需求分析与数据策略制定
项目背景
假设你是一家中型 AI 公司的数据负责人,团队决定从零训练一个 7B 参数的中英双语通用模型,目标是在通用能力上达到接近 Qwen2.5-7B / Llama3.1-8B 的水平,并在代码和数学能力上有额外增强。
关键约束条件:
| 维度 | 约束 |
|---|---|
| 模型规模 | 7B 参数(Transformer decoder-only) |
| 算力预算 | 256 × H100 × 30 天 |
| 目标语言 | 中文 + 英文(比例约 3:7) |
| 重点能力 | 通用对话、代码生成、数学推理 |
| 合规要求 | 中国数据安全法、GDPR(如需出海) |
| 时间线 | 数据准备 8 周,训练 4 周,后训练 2 周 |
Token 预算估算
根据 Chinchilla Scaling Laws 的修正版本(考虑 over-training),7B 模型的训练预算可以这样估算:
"""
7B 模型的数据预算估算
"""
def estimate_token_budget(
params_b: float = 7.0, # 参数量(十亿)
chinchilla_ratio: float = 20, # Chinchilla 最优比例
overtrain_factor: float = 3.0, # over-training 倍率
) -> dict:
"""估算各阶段的 token 预算"""
# Chinchilla 最优:每参数 20 个 token
chinchilla_optimal = params_b * chinchilla_ratio * 1e9 # 140B tokens
# 实践中通常 over-train 2-5 倍
# Llama 3.1 8B 用了 15T(~1875x),这里取保守 3x
pretrain_tokens = chinchilla_optimal * overtrain_factor # 420B tokens
# 中训练:预训练 token 数的 5-15%
midtrain_tokens = pretrain_tokens * 0.10 # 42B tokens
# SFT:通常 1M-10M 条,平均 2K tokens/条
sft_samples = 2_000_000
sft_tokens = sft_samples * 2000 # 4B tokens
# RL:通常 100K-1M 条
rl_samples = 500_000
rl_tokens = rl_samples * 4000 # 2B tokens(含推理过程)
return {
"pretrain_tokens": f"{pretrain_tokens/1e9:.0f}B",
"midtrain_tokens": f"{midtrain_tokens/1e9:.0f}B",
"sft_samples": f"{sft_samples/1e6:.0f}M ({sft_tokens/1e9:.0f}B tokens)",
"rl_samples": f"{rl_samples/1e6:.1f}M ({rl_tokens/1e9:.0f}B tokens)",
"total_tokens": f"{(pretrain_tokens + midtrain_tokens + sft_tokens + rl_tokens)/1e9:.0f}B",
}
budget = estimate_token_budget()
for k, v in budget.items():
print(f"{k}: {v}")
# 输出:
# pretrain_tokens: 420B
# midtrain_tokens: 42B
# sft_samples: 2M (4B tokens)
# rl_samples: 0.5M (2B tokens)
# total_tokens: 468B
关键决策点:420B 的预训练 token 需要大约 2.5-3TB 的高质量去重后文本数据。考虑到原始数据到可用数据的转化率通常在 5-15%,你需要准备至少 20-50TB 的原始数据。
数据策略总览
基于目标和约束,制定四阶段数据策略:
"""
数据策略总览——四阶段规划
"""
DATA_STRATEGY = {
"stage_1_pretrain": {
"目标": "通用知识 + 语言能力",
"token_budget": "420B",
"数据配比": {
"英文网页(高质量过滤后)": 0.45,
"中文网页(高质量过滤后)": 0.20,
"代码(GitHub, 多语言)": 0.15,
"学术论文(arXiv, S2ORC)": 0.05,
"书籍": 0.05,
"百科(Wikipedia, 百度百科)": 0.03,
"数学(LaTeX, 教材, 合成)": 0.04,
"多语言(日韩法德西等)": 0.03,
},
"周期": "6 周准备 + 3-4 周训练",
},
"stage_2_midtrain": {
"目标": "长上下文 + 代码数学增强",
"token_budget": "42B",
"数据配比": {
"长文档(>8K tokens)": 0.25,
"高质量代码(star>10, 有文档)": 0.30,
"数学数据(教材+合成)": 0.15,
"通用回放数据": 0.30,
},
"周期": "2 周准备 + 1 周训练",
},
"stage_3_sft": {
"目标": "指令遵循 + 对话能力 + 工具调用",
"samples": "3M(含 200K 工具调用轨迹,2026 提升到 10-15%)",
"数据配比": {
"通用对话": 0.25,
"代码生成/调试": 0.20,
"数学推理": 0.15,
"创作/翻译": 0.10,
"知识问答": 0.10,
"工具调用": 0.10,
"多轮对话": 0.05,
"安全拒答": 0.05,
},
"周期": "3 周准备 + 3 天训练",
},
"stage_4_rl": {
"目标": "偏好对齐 + 推理增强 + Agentic RL",
"samples": "600K(含 agentic RL 数据,如 RODS 边界检测、APIGen-MT 多轮)",
"数据构成": {
"偏好数据(DPO 格式)": "200K pairs",
"代码 RL(可验证奖励)": "150K problems",
"数学 RL(可验证奖励)": "100K problems",
"Agentic RL(工具调用)": "100K trajectories(ASTRA / TOUCAN 风格)",
"通用 RLHF": "50K pairs",
},
"周期": "2 周准备 + 1 周训练",
},
}
💡 反直觉发现:很多团队在数据准备上花的时间远超训练本身。对于一个 7B 模型,典型的时间分配是:数据准备 60-70%,训练 20-25%,评估迭代 10-15%。数据工作是真正的瓶颈。
30.2 预训练数据构建
原始数据采集
第一步是获取足够量的原始数据。我们的策略是以开源数据为主,辅以自行爬取的中文数据。
数据源规划表(表 30.1):
| 数据源 | 语言 | 原始规模 | 清洗后可用量 | License | 获取方式 |
|---|---|---|---|---|---|
| FineWeb 2 | 多语言 | ~10T tokens | 按需采样 | ODC-BY | HuggingFace |
| Common Pile | 英文 | ~1T tokens (8TB) | 按需采样 | Permissive (curated) | Allen AI |
| Dolma 3 | 英文 | ~6T tokens | 按需采样 | ODC-BY | HuggingFace |
| RedPajama 2 | 英文 | ~30T tokens | 按需采样 | Various | Together AI |
| Nemotron-CC | 英文 | ~6.3T tokens | 4 阶段蒸馏后 504B-2T | Multi-licence | NVIDIA |
| DCLM-baseline | 英文 | ~3.8T tokens | 按需采样 | CC-BY-4.0 | Community + Apple + AI2 |
| Zyda 2 | 英文 | ~5T tokens | 按需采样 | Permissive | Zyphra |
| SlimPajama | 英文 | ~627B tokens | 直接使用 | Apache 2.0 | Cerebras |
| The Stack v2 | 代码 | ~3T tokens | ~400GB 精选 | BigCode | BigCode |
| Wikipedia (全语言) | 多语言 | ~100GB | ~80GB | CC-BY-SA | Dump 下载 |
| arXiv 全文 | 英文 | ~300GB | ~200GB | CC-BY | S3 bulk 下载 |
| WanjuanCC(上海 AI Lab) | 中文 | ~1T tokens (高质量) / 100B tokens (开源) | 按需采样 | Apache-2.0 | OpenDataLab (github.com/opendatalab) |
| CCI3-Data | 中文 | 多 TB | 按需采样 | Custom | CCI |
| ChineseWebText | 中文 | 多源融合 | 按需采样 | Various | 多源 |
| SkyPile-150B(商汤) | 中文 | 150B tokens | 按需采样 | Custom | 商汤 |
| 中文书籍(公版) | 中文 | ~50GB | ~40GB | Public Domain | 古腾堡/维基文库 |
实际决策:对于资源有限的团队,一个务实的做法是——不从 Common Crawl 原始 WARC 开始处理,而是基于已有的高质量开源数据集进行二次筛选和混合。2026 年推荐的数据源选择范式:
- 多语言高质量过滤代表 → FineWeb 2(~10T tokens,6.7× 扩张)
- fully-permissive(明确版权清理)代表 → Common Pile(~1T tokens / 8TB,训练 Comma v0.1-1T/2T)
- 商业级 CC 蒸馏范式 → Nemotron-CC(6.3T → 504B-2T,4 阶段蒸馏 + ASI-Evolve 自主清洗使 MMLU 提升 18.64 个百分点)
- 学术级 baseline → DCLM-baseline(3.8T tokens,CC-BY-4.0)
2026 年的实战策略已从”自建爬虫+清洗”演进到”高质量开源 + 选择性二次过滤”——节省 70%+ 清洗工作量,且质量天花板更高。
"""
数据源管理配置
"""
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class DataSource:
name: str
language: str
raw_size_gb: float
estimated_yield: float # 可用数据占比
priority: int # 1=最高
license: str
notes: str = ""
# 数据源注册表
SOURCES = [
DataSource("fineweb-edu-2", "en", 5000, 0.40, 1, "ODC-BY",
"FineWeb 教育价值过滤版,英文主力"),
DataSource("dclm-baseline", "en", 3000, 0.50, 2, "CC-BY-4.0",
"DCLM 过滤后的高质量英文网页"),
DataSource("cc-zh-2024", "zh", 2000, 0.08, 1, "Custom",
"Common Crawl 中文子集,需自行清洗"),
DataSource("wanjuan-cc", "zh", 800, 0.30, 2, "Apache-2.0",
"智源 WanJuan 中文语料"),
DataSource("starcoder-data-v3", "code", 3000, 0.15, 1, "Apache-2.0",
"多语言代码,按质量分层"),
DataSource("arxiv-fulltext", "en", 300, 0.70, 3, "CC-BY",
"学术论文,LaTeX 转纯文本"),
DataSource("wiki-all", "multi", 100, 0.80, 2, "CC-BY-SA",
"全语言 Wikipedia"),
DataSource("math-corpus", "en/zh", 200, 0.60, 2, "Mixed",
"数学教材、StackExchange 数学、合成数学"),
]
def plan_data_budget(target_tokens_b: float = 420):
"""按配比规划各数据源的采样量"""
# 假设平均 1GB ≈ 250M tokens(清洗后的文本)
TOKENS_PER_GB = 0.25 # 十亿 tokens/GB
target_gb = target_tokens_b / TOKENS_PER_GB # 1680 GB
# 按配比分配
allocation = {
"en_web": (0.45, ["fineweb-edu-2", "dclm-baseline"]),
"zh_web": (0.20, ["cc-zh-2024", "wanjuan-cc"]),
"code": (0.15, ["starcoder-data-v3"]),
"academic": (0.05, ["arxiv-fulltext"]),
"wiki": (0.03, ["wiki-all"]),
"math": (0.04, ["math-corpus"]),
}
plan = {}
for domain, (ratio, sources) in allocation.items():
domain_gb = target_gb * ratio
plan[domain] = {
"target_gb": round(domain_gb, 1),
"target_tokens_b": round(domain_gb * TOKENS_PER_GB, 1),
"sources": sources,
}
return plan
数据处理管线
预训练数据处理管线是整个项目中工作量最大的部分。我们分五个阶段实现:
"""
完整的预训练数据处理管线
"""
import hashlib
import re
from collections import Counter
from typing import List, Dict, Tuple, Optional
class PretrainPipeline:
"""五阶段预训练数据处理管线"""
def __init__(self, config: dict):
self.config = config
self.stats = {
"stage_input": Counter(),
"stage_output": Counter(),
"filter_reasons": Counter(),
}
# ========== 阶段 1:文本提取 ==========
def stage1_extract(self, raw_html: str, url: str) -> Optional[str]:
"""从 HTML 提取纯文本"""
# 实际项目中使用 trafilatura 或 resiliparse
# 这里展示核心逻辑
import trafilatura
text = trafilatura.extract(
raw_html,
include_tables=True,
include_links=False,
include_images=False,
favor_recall=False, # 精确优先
min_extracted_size=200,
)
if text is None:
self.stats["filter_reasons"]["extract_failed"] += 1
return None
# 后处理:规范化空白字符
text = re.sub(r'\n{3,}', '\n\n', text)
text = re.sub(r'[ \t]+', ' ', text)
return text.strip()
# ========== 阶段 2:语言识别与基础过滤 ==========
def stage2_langfilter(self, text: str, target_lang: str = "zh") -> Optional[str]:
"""语言识别 + 基础启发式过滤"""
# 长度过滤
if len(text) < 200:
self.stats["filter_reasons"]["too_short"] += 1
return None
# 语言识别(使用 fasttext lid 模型)
# lang, confidence = fasttext_model.predict(text.replace('\n', ' ')[:500])
# if lang != target_lang or confidence < 0.65:
# return None
# 启发式过滤
lines = text.split('\n')
# 短行比例(<10 字的行)
short_line_ratio = sum(1 for l in lines if len(l.strip()) < 10) / max(len(lines), 1)
if short_line_ratio > 0.7:
self.stats["filter_reasons"]["too_many_short_lines"] += 1
return None
# 特殊字符比例
special_chars = sum(1 for c in text if not c.isalnum() and c not in ' \n\t。,、;:?!""''()—…')
if special_chars / max(len(text), 1) > 0.3:
self.stats["filter_reasons"]["too_many_special_chars"] += 1
return None
# 重复行检测
unique_lines = set(l.strip() for l in lines if len(l.strip()) > 20)
if len(unique_lines) < len(lines) * 0.5:
self.stats["filter_reasons"]["too_many_duplicate_lines"] += 1
return None
return text
# ========== 阶段 3:质量过滤 ==========
def stage3_quality_filter(self, text: str) -> Tuple[Optional[str], float]:
"""质量评分与过滤"""
score = 0.0
total_weight = 0.0
# 维度 1:段落结构(权重 0.2)
paragraphs = [p for p in text.split('\n\n') if len(p.strip()) > 50]
para_score = min(len(paragraphs) / 3, 1.0) # 至少 3 个实质段落
score += para_score * 0.2
total_weight += 0.2
# 维度 2:词汇丰富度(权重 0.2)
words = text.split()
if len(words) > 50:
unique_ratio = len(set(words)) / len(words)
vocab_score = min(unique_ratio / 0.6, 1.0) # 60% 唯一词为满分
score += vocab_score * 0.2
total_weight += 0.2
# 维度 3:信息密度——通过标点和句子长度估算(权重 0.2)
sentences = re.split(r'[。!?.!?]+', text)
avg_sent_len = sum(len(s) for s in sentences) / max(len(sentences), 1)
density_score = 1.0 if 20 < avg_sent_len < 200 else 0.5
score += density_score * 0.2
total_weight += 0.2
# 维度 4:无广告/导航噪声(权重 0.2)
ad_patterns = ['点击这里', '立即购买', 'subscribe', 'click here',
'cookie', '免费试用', '©', '版权所有']
ad_count = sum(1 for p in ad_patterns if p.lower() in text.lower())
ad_score = max(0, 1.0 - ad_count * 0.2)
score += ad_score * 0.2
total_weight += 0.2
# 维度 5:教育价值(简化版,实际用 classifier)(权重 0.2)
edu_signals = ['因此', '研究表明', '例如', 'therefore', 'research',
'however', '综上', '实验结果', '算法', '公式']
edu_count = sum(1 for s in edu_signals if s.lower() in text.lower())
edu_score = min(edu_count / 3, 1.0)
score += edu_score * 0.2
total_weight += 0.2
# 归一化
final_score = score / total_weight if total_weight > 0 else 0
# 阈值过滤
if final_score < self.config.get("quality_threshold", 0.4):
self.stats["filter_reasons"]["low_quality"] += 1
return None, final_score
return text, final_score
# ========== 阶段 4:去重 ==========
def stage4_dedup(self, texts: List[str]) -> List[str]:
"""两级去重:精确 + 模糊"""
# 精确去重(SHA-256)
seen_hashes = set()
exact_deduped = []
for text in texts:
h = hashlib.sha256(text.encode()).hexdigest()
if h not in seen_hashes:
seen_hashes.add(h)
exact_deduped.append(text)
else:
self.stats["filter_reasons"]["exact_duplicate"] += 1
# 模糊去重(MinHash + LSH)
# 实际使用 datasketch 库或 datatrove 内置
# 这里展示接口
from datasketch import MinHash, MinHashLSH
lsh = MinHashLSH(threshold=0.8, num_perm=128)
final_texts = []
for i, text in enumerate(exact_deduped):
m = MinHash(num_perm=128)
# 中文用 2-gram, 英文用 5-gram
ngrams = self._get_ngrams(text, n=5)
for ng in ngrams:
m.update(ng.encode('utf-8'))
# 查询是否有近似重复
result = lsh.query(m)
if len(result) == 0:
lsh.insert(f"doc_{i}", m)
final_texts.append(text)
else:
self.stats["filter_reasons"]["fuzzy_duplicate"] += 1
return final_texts
def _get_ngrams(self, text: str, n: int = 5) -> List[str]:
"""提取 n-gram"""
words = text.split()
return [' '.join(words[i:i+n]) for i in range(len(words) - n + 1)]
# ========== 阶段 5:PII 脱敏与安全过滤 ==========
def stage5_safety(self, text: str) -> Optional[str]:
"""PII 脱敏 + 敏感内容过滤"""
# PII 替换
# 手机号(中国大陆)
text = re.sub(r'1[3-9]\d{9}', '<PHONE>', text)
# 邮箱
text = re.sub(r'[\w.+-]+@[\w-]+\.[\w.]+', '<EMAIL>', text)
# 身份证号
text = re.sub(r'\d{17}[\dXx]', '<ID_CARD>', text)
# IP 地址
text = re.sub(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', '<IP>', text)
# 敏感内容检测(实际用分类器)
# if nsfw_classifier.predict(text) > 0.8:
# self.stats["filter_reasons"]["nsfw"] += 1
# return None
return text
# ========== 完整管线 ==========
def process_document(self, raw_html: str, url: str, lang: str = "zh") -> Optional[Dict]:
"""处理单个文档的完整管线"""
self.stats["stage_input"]["total"] += 1
# Stage 1: 提取
text = self.stage1_extract(raw_html, url)
if text is None:
return None
# Stage 2: 语言+基础过滤
text = self.stage2_langfilter(text, lang)
if text is None:
return None
# Stage 3: 质量过滤
text, quality_score = self.stage3_quality_filter(text)
if text is None:
return None
# Stage 5: 安全过滤(去重在批量阶段做)
text = self.stage5_safety(text)
if text is None:
return None
self.stats["stage_output"]["passed"] += 1
return {
"text": text,
"url": url,
"lang": lang,
"quality_score": quality_score,
"token_count": len(text) // 2, # 粗略估计
}
数据配比实验
数据配比是预训练阶段最关键的超参数之一。我们使用小模型代理实验来确定最终配比:
"""
数据配比代理实验框架
使用 400M 参数小模型在 10B tokens 上快速验证配比效果
"""
# 候选配比方案
MIXING_EXPERIMENTS = {
"baseline": {
"en_web": 0.50, "zh_web": 0.20, "code": 0.12,
"academic": 0.05, "wiki": 0.03, "math": 0.03,
"books": 0.04, "multilingual": 0.03,
},
"code_heavy": {
"en_web": 0.40, "zh_web": 0.18, "code": 0.22,
"academic": 0.05, "wiki": 0.03, "math": 0.04,
"books": 0.04, "multilingual": 0.04,
},
"math_heavy": {
"en_web": 0.42, "zh_web": 0.18, "code": 0.15,
"academic": 0.05, "wiki": 0.03, "math": 0.08,
"books": 0.05, "multilingual": 0.04,
},
"balanced_plus": {
"en_web": 0.45, "zh_web": 0.20, "code": 0.15,
"academic": 0.05, "wiki": 0.03, "math": 0.04,
"books": 0.05, "multilingual": 0.03,
},
}
# 代理实验结果(400M 模型, 10B tokens)
PROXY_RESULTS = """
| 方案 | MMLU(5-shot) | GSM8K | HumanEval | C-Eval | 平均 |
|------|-------------|-------|-----------|--------|------|
| baseline | 32.1 | 18.5 | 15.2 | 34.8 | 25.2 |
| code_heavy | 30.8 | 19.2 | 22.1 | 33.5 | 26.4 |
| math_heavy | 31.5 | 24.7 | 16.8 | 34.2 | 26.8 |
| balanced_plus | 32.8 | 21.3 | 18.9 | 35.1 | 27.0 |
"""
# 决策:选择 balanced_plus 作为最终配比
# 原因:综合分数最高,且没有单项短板
# 代码和数学能力在中训练阶段再做针对性增强
FINAL_PRETRAIN_MIX = {
"en_web": 0.45,
"zh_web": 0.20,
"code": 0.15,
"academic": 0.05,
"wiki": 0.03,
"math": 0.04,
"books": 0.05,
"multilingual": 0.03,
}
🔬 显微镜案例:代码配比的决定
在代理实验中,
code_heavy方案在 HumanEval 上提升了 45%(15.2→22.1),但 MMLU 下降了 1.3 分。这是经典的能力跷跷板效应。最终选择balanced_plus的 15% 代码配比,因为:
- 中训练阶段会再追加高质量代码数据
- 预训练阶段的代码主要目标是建立代码理解的基础能力
- 15% 代码已经能提供显著的推理能力溢出效应
数据质量评估与迭代
预训练数据不是处理一遍就结束的。我们建立了一个迭代评估机制:
"""
预训练数据质量评估 Dashboard
"""
class DataQualityDashboard:
"""数据质量实时监控"""
def __init__(self, data_dir: str):
self.data_dir = data_dir
self.metrics = {}
def run_quality_audit(self, sample_size: int = 10000) -> dict:
"""对数据集执行质量审计"""
report = {
"total_documents": 0,
"total_tokens_b": 0,
"language_distribution": Counter(),
"quality_score_distribution": {
"excellent (>0.8)": 0,
"good (0.6-0.8)": 0,
"acceptable (0.4-0.6)": 0,
"poor (<0.4)": 0,
},
"length_stats": {
"min": float('inf'),
"max": 0,
"mean": 0,
"median": 0,
"p10": 0,
"p90": 0,
},
"issues_found": [],
}
# 抽样检查
# ... 实际实现省略
return report
def check_benchmark_contamination(
self,
training_data_sample: List[str],
benchmark_name: str = "mmlu",
ngram_size: int = 13,
) -> dict:
"""Benchmark 污染检测"""
# 加载 benchmark 题目
# benchmark_items = load_benchmark(benchmark_name)
contaminated = []
# for item in benchmark_items:
# item_ngrams = set(get_ngrams(item, ngram_size))
# for doc in training_data_sample:
# doc_ngrams = set(get_ngrams(doc, ngram_size))
# overlap = len(item_ngrams & doc_ngrams) / max(len(item_ngrams), 1)
# if overlap > 0.5:
# contaminated.append({"benchmark_item": item[:100], "overlap": overlap})
return {
"benchmark": benchmark_name,
"total_items_checked": 0, # len(benchmark_items),
"contaminated_items": len(contaminated),
"contamination_rate": 0, # len(contaminated) / len(benchmark_items),
"action": "REMOVE contaminated documents" if contaminated else "CLEAN",
}
def generate_iteration_report(self, version: str) -> str:
"""生成数据版本迭代报告"""
report = f"""
# 预训练数据质量报告 - {version}
> **概览**
- 总文档数: {self.metrics.get('total_docs', 'N/A')}
- 总 Token 数: {self.metrics.get('total_tokens', 'N/A')}
- 平均质量分: {self.metrics.get('avg_quality', 'N/A')}
> **本版本变更**
{self.metrics.get('changes', '无')}
> **已知问题**
{self.metrics.get('known_issues', '无')}
> **下版本计划**
{self.metrics.get('next_plan', '无')}
"""
return report
数据迭代实录(节选):
| 版本 | 变更 | 影响 |
|---|---|---|
| v0.1 | 初始管线,基础规则过滤 | Baseline |
| v0.2 | 加入教育价值分类器,过滤阈值 0.3 | MMLU +1.8 |
| v0.3 | 中文数据加入繁简转换统一 | C-Eval +0.9 |
| v0.4 | 发现并移除 MMLU 污染数据 3.2K 条 | MMLU -0.3(真实水平) |
| v0.5 | 代码数据加入 lint 过滤,去除语法错误代码 | HumanEval +2.1 |
| v1.0 | 最终版本,全量去重完成 | 最终 baseline |
30.3 中训练数据构建
预训练完成后,我们进入中训练阶段。目标是:
- 长上下文:从 4K 扩展到 32K
- 代码增强:提升代码生成和理解能力
- 数学增强:提升数学推理能力
长上下文数据
"""
长上下文数据构造管线
目标:支持 32K 上下文窗口
"""
class LongContextDataBuilder:
"""渐进式长上下文数据构造"""
# 三阶段渐进方案
PHASES = [
{"name": "phase1", "max_len": 8192, "ratio": 0.4, "tokens_b": 8},
{"name": "phase2", "max_len": 16384, "ratio": 0.35, "tokens_b": 7},
{"name": "phase3", "max_len": 32768, "ratio": 0.25, "tokens_b": 5},
]
# 长文档来源及优先级
LONG_DOC_SOURCES = {
"books": {
"min_length": 10000,
"description": "公版书籍,自然长文本",
"priority": 1,
},
"academic_papers": {
"min_length": 5000,
"description": "学术论文全文,结构化长文本",
"priority": 1,
},
"legal_documents": {
"min_length": 8000,
"description": "法律文书,精确性要求高",
"priority": 2,
},
"code_repos": {
"min_length": 10000,
"description": "完整代码仓库,跨文件依赖",
"priority": 1,
},
"long_conversations": {
"min_length": 5000,
"description": "多轮长对话数据",
"priority": 2,
},
"concatenated_wiki": {
"min_length": 8000,
"description": "同主题 Wikipedia 文章拼接",
"priority": 3,
},
}
def build_phase_data(self, phase_idx: int, docs: list) -> list:
"""构建某一阶段的长上下文数据"""
phase = self.PHASES[phase_idx]
max_len = phase["max_len"]
selected = []
for doc in docs:
tokens = len(doc.split()) # 简化的 token 计数
if tokens <= max_len:
selected.append(doc)
else:
# 对超长文档进行智能切分
chunks = self._smart_split(doc, max_len)
selected.extend(chunks)
# 长度分布验证
lengths = [len(d.split()) for d in selected]
print(f"Phase {phase_idx+1} ({phase['name']}):")
print(f" 文档数: {len(selected)}")
print(f" 平均长度: {sum(lengths)/len(lengths):.0f} tokens")
print(f" 目标 tokens: {phase['tokens_b']}B")
return selected
def _smart_split(self, doc: str, max_len: int) -> list:
"""智能切分:在段落/章节边界处切分,保持语义完整"""
paragraphs = doc.split('\n\n')
chunks = []
current_chunk = []
current_len = 0
for para in paragraphs:
para_len = len(para.split())
if current_len + para_len > max_len and current_chunk:
chunks.append('\n\n'.join(current_chunk))
# 保留最后一段作为上下文重叠
current_chunk = [current_chunk[-1]] if current_chunk else []
current_len = len(current_chunk[0].split()) if current_chunk else 0
current_chunk.append(para)
current_len += para_len
if current_chunk:
chunks.append('\n\n'.join(current_chunk))
return chunks
代码增强数据
"""
代码增强数据构造
目标:从 The Stack v2 中精选高质量代码 + Repo 级上下文
"""
class CodeDataBuilder:
"""代码数据四级质量分层"""
QUALITY_TIERS = {
"tier1_premium": {
"criteria": "star > 100 AND has_readme AND has_tests AND lint_pass",
"ratio": 0.30,
"description": "顶级仓库代码",
},
"tier2_good": {
"criteria": "star > 10 AND has_docstring_ratio > 0.3",
"ratio": 0.35,
"description": "优质代码,有文档",
},
"tier3_acceptable": {
"criteria": "lint_pass AND file_size > 100",
"ratio": 0.25,
"description": "可用代码,通过基本检查",
},
"tier4_supplementary": {
"criteria": "basic_syntax_valid",
"ratio": 0.10,
"description": "补充量的普通代码",
},
}
# 编程语言配比
LANG_MIX = {
"python": 0.35,
"javascript/typescript": 0.20,
"java": 0.10,
"c/c++": 0.10,
"go": 0.05,
"rust": 0.05,
"shell": 0.03,
"sql": 0.03,
"other": 0.09,
}
def score_code_file(self, code: str, metadata: dict) -> float:
"""代码文件质量评分"""
score = 0.0
# 1. 有文档字符串 (+0.2)
if '"""' in code or "'''" in code or '/**' in code:
score += 0.2
# 2. 函数/类定义比例合理 (+0.2)
lines = code.split('\n')
def_lines = sum(1 for l in lines if l.strip().startswith(('def ', 'class ', 'function ', 'public ', 'private ')))
if 0.05 < def_lines / max(len(lines), 1) < 0.3:
score += 0.2
# 3. 注释比例适中 (+0.15)
comment_lines = sum(1 for l in lines if l.strip().startswith(('#', '//', '/*', '*')))
comment_ratio = comment_lines / max(len(lines), 1)
if 0.05 < comment_ratio < 0.4:
score += 0.15
# 4. 仓库星级 (+0.25)
stars = metadata.get("stars", 0)
if stars > 100:
score += 0.25
elif stars > 10:
score += 0.15
elif stars > 1:
score += 0.05
# 5. 文件不是自动生成的 (+0.2)
autogen_patterns = ['generated by', 'auto-generated', 'do not edit',
'generated from', 'THIS FILE IS AUTOMATICALLY']
if not any(p.lower() in code.lower()[:500] for p in autogen_patterns):
score += 0.2
return min(score, 1.0)
def build_repo_context(self, repo_files: list) -> str:
"""构建 Repo 级上下文序列"""
# 按依赖关系排序文件
sorted_files = self._topological_sort(repo_files)
context_parts = []
for f in sorted_files:
context_parts.append(f"# File: {f['path']}\n{f['content']}")
return "\n\n---\n\n".join(context_parts)
def _topological_sort(self, files: list) -> list:
"""按 import 依赖进行拓扑排序"""
# 简化实现:README → 配置文件 → 工具类 → 核心逻辑 → 测试
priority = {
'readme': 0, 'setup': 1, 'config': 2, 'util': 3,
'model': 4, 'main': 5, 'test': 6,
}
def get_priority(f):
name = f['path'].lower()
for key, val in priority.items():
if key in name:
return val
return 4
return sorted(files, key=get_priority)
数学增强数据
"""
数学增强数据构造
"""
class MathDataBuilder:
"""数学数据四级难度梯度"""
DIFFICULTY_LEVELS = {
"level1_basic": {
"description": "小学到初中数学",
"examples": ["计算 234 × 56", "解方程 2x + 3 = 15"],
"ratio": 0.20,
"source": ["GSM8K-like synthetic", "教材题"],
},
"level2_intermediate": {
"description": "高中数学",
"examples": ["求导 f(x)=x³+2x²-5x+1", "概率组合问题"],
"ratio": 0.35,
"source": ["MATH dataset", "高考真题", "合成变体"],
},
"level3_advanced": {
"description": "大学数学",
"examples": ["多元微积分", "线性代数证明", "概率论推导"],
"ratio": 0.30,
"source": ["arXiv 数学论文", "大学教材", "合成高级题"],
},
"level4_competition": {
"description": "竞赛/研究级别",
"examples": ["IMO 风格题目", "组合数论"],
"ratio": 0.15,
"source": ["AMC/AIME/IMO", "合成竞赛题"],
},
}
def process_latex_content(self, raw_text: str) -> str:
"""处理 LaTeX 数学内容"""
import re
# 标准化 LaTeX 环境
text = raw_text
# \begin{equation} → $$ ... $$
text = re.sub(
r'\\begin\{equation\*?\}(.*?)\\end\{equation\*?\}',
r'$$\1$$',
text,
flags=re.DOTALL
)
# 清理常见的 LaTeX 噪声
text = re.sub(r'\\label\{[^}]*\}', '', text)
text = re.sub(r'\\ref\{[^}]*\}', '[ref]', text)
# 确保行间公式有换行
text = re.sub(r'(?<!\n)\$\$', '\n$$', text)
text = re.sub(r'\$\$(?!\n)', '$$\n', text)
return text
def generate_synthetic_math(
self,
template_type: str,
difficulty: int,
count: int = 100,
) -> list:
"""生成合成数学题(框架示例)"""
# 实际项目中使用 GPT-4/Claude 等强模型生成
# 这里展示生成配置
generation_config = {
"model": "gpt-4-turbo",
"temperature": 0.7,
"system_prompt": f"""You are a math problem generator.
Create {template_type} problems at difficulty level {difficulty}/4.
Each problem must include:
1. Clear problem statement
2. Step-by-step solution
3. Final answer in \\boxed{{}}
Ensure variety in:
- Number choices (avoid trivial values)
- Problem context
- Solution approaches
""",
"post_processing": [
"verify_answer_correctness", # 用 sympy 验证答案
"check_step_validity", # 检查每步推导
"dedup_against_benchmarks", # 与评测集去重
],
}
return generation_config
中训练配比与遗忘防控
"""
中训练数据最终配比和遗忘监控方案
"""
MIDTRAIN_FINAL_MIX = {
# 新增能力数据(70%)
"long_context_data": {
"ratio": 0.25,
"description": "渐进式长文档,4K→8K→16K→32K",
},
"code_enhanced": {
"ratio": 0.30,
"description": "高质量代码 + Repo 级上下文",
},
"math_enhanced": {
"ratio": 0.15,
"description": "数学数据四级梯度",
},
# 回放数据(30%)—— 防止灾难性遗忘
"replay_en_web": {
"ratio": 0.12,
"description": "英文通用网页回放",
},
"replay_zh_web": {
"ratio": 0.08,
"description": "中文通用网页回放",
},
"replay_wiki": {
"ratio": 0.05,
"description": "百科知识回放",
},
"replay_diverse": {
"ratio": 0.05,
"description": "学术/书籍/对话混合回放",
},
}
# 遗忘监控方案
FORGETTING_MONITORS = {
"checkpoints": "每 1B tokens 保存一次",
"eval_frequency": "每 2B tokens 评估一次",
"eval_benchmarks": [
"MMLU (5-shot) — 通用知识",
"C-Eval (5-shot) — 中文知识",
"HumanEval — 代码能力(应上升)",
"GSM8K — 数学能力(应上升)",
"HellaSwag — 常识推理(不应下降)",
"ARC-Challenge — 科学推理(不应下降)",
],
"alert_threshold": {
"任意 benchmark 下降超过 2%": "WARNING",
"任意 benchmark 下降超过 5%": "CRITICAL — 暂停训练",
"通用能力平均下降超过 3%": "CRITICAL — 回退到上个 checkpoint",
},
}
30.4 SFT 数据构建
种子数据设计
SFT 的第一步是设计高质量的种子数据。种子数据不需要多——100-500 条精心设计的样本足矣——但它定义了模型的”人格”和回复风格。
"""
SFT 种子数据设计框架
"""
# 种子数据分类和模板
SEED_DATA_SCHEMA = {
"identity_samples": {
"count": 20,
"purpose": "定义模型身份和基本行为",
"example": {
"instruction": "你是谁?",
"response": "我是 [模型名],一个由 [公司] 开发的 AI 助手。我可以帮你回答问题、编写代码、进行分析等。有什么我可以帮到你的吗?",
},
},
"format_samples": {
"count": 50,
"purpose": "教会模型输出格式(markdown/代码块/列表等)",
"types": [
"使用 markdown 表格回答对比类问题",
"使用有序列表回答步骤类问题",
"使用代码块回答编程问题",
"使用分点论述回答分析类问题",
],
},
"safety_samples": {
"count": 80,
"purpose": "安全拒答和边界行为",
"types": [
"有害请求的礼貌拒绝",
"隐私敏感问题的处理",
"不确定信息的诚实回应",
"价值观冲突场景的平衡回答",
],
},
"capability_seeds": {
"count": 100,
"purpose": "各核心能力的标杆样本",
"types": [
"代码生成:从简单函数到完整模块",
"数学推理:清晰的逐步推导",
"创意写作:有文采有结构",
"知识问答:准确且有深度",
"翻译:信达雅",
],
},
"multi_turn_seeds": {
"count": 50,
"purpose": "多轮对话的质量标杆",
"requirements": [
"上下文记忆一致",
"自然的追问和澄清",
"话题切换的流畅处理",
],
},
}
def create_seed_quality_checklist() -> dict:
"""种子数据质量检查清单"""
return {
"必须满足": [
"指令意图明确,无歧义",
"回复完整、准确、有用",
"格式规范(markdown 正确,代码可运行)",
"语言流畅自然,无机器味",
"不含任何事实性错误",
],
"应当满足": [
"回复长度适中(不过短也不冗余)",
"有结构感(分段、标题、列表)",
"体现专业性和深度",
"包含必要的注意事项或边界条件",
],
"加分项": [
"有具体例子或类比",
"提供进一步学习的方向",
"预判用户的后续问题",
],
}
大规模合成与过滤
种子数据之后,通过合成扩展到 200 万条:
"""
SFT 数据合成与过滤管线
"""
class SFTDataFactory:
"""SFT 数据工厂:合成 + 过滤 + 配比"""
def __init__(self, strong_model: str = "gpt-4-turbo"):
self.strong_model = strong_model
self.quality_stats = Counter()
# ========== 合成方法 1:Evol-Instruct ==========
def evolve_instruction(self, seed_instruction: str, evolution_type: str) -> str:
"""指令进化(WizardLM 方法)"""
evolution_prompts = {
"deepen": f"""将以下指令变得更深入、更具体、需要更多专业知识来回答。
原始指令: {seed_instruction}
进化后的指令:""",
"broaden": f"""将以下指令扩展到更广泛的场景,增加约束条件。
原始指令: {seed_instruction}
进化后的指令:""",
"concretize": f"""将以下指令变得更具体,添加具体的数字、场景、约束。
原始指令: {seed_instruction}
进化后的指令:""",
"complicate": f"""增加以下指令的复杂度,加入多步骤要求或条件分支。
原始指令: {seed_instruction}
进化后的指令:""",
}
prompt = evolution_prompts.get(evolution_type, evolution_prompts["deepen"])
# response = call_llm(self.strong_model, prompt)
# return response
return prompt # 框架示例
# ========== 合成方法 2:拒绝采样 ==========
def rejection_sampling(
self,
instruction: str,
n_samples: int = 8,
temperature: float = 0.8,
) -> dict:
"""拒绝采样:生成多个 → 评分 → 选最优"""
# 生成 n 个候选回复
candidates = []
for i in range(n_samples):
# response = call_llm(self.strong_model, instruction, temperature=temperature)
# candidates.append(response)
pass
# 多维度评分
scored = []
for resp in candidates:
score = self._score_response(instruction, resp)
scored.append({"response": resp, "score": score})
# 选择最高分
scored.sort(key=lambda x: x["score"], reverse=True)
return scored[0] if scored else None
def _score_response(self, instruction: str, response: str) -> float:
"""回复质量评分"""
score = 0.0
# 1. 长度合理性 (0-0.2)
resp_len = len(response)
if 200 < resp_len < 3000:
score += 0.2
elif resp_len >= 100:
score += 0.1
# 2. 格式质量 (0-0.2)
has_structure = any(marker in response for marker in
['##', '- ', '1.', '```', '|'])
if has_structure:
score += 0.2
# 3. 指令相关性 (0-0.3) — 简化版
instruction_keywords = set(instruction.lower().split())
response_keywords = set(response.lower().split())
overlap = len(instruction_keywords & response_keywords)
relevance = min(overlap / max(len(instruction_keywords), 1), 1.0)
score += relevance * 0.3
# 4. 无重复/无幻觉信号 (0-0.3)
# 检查是否有重复段落
paragraphs = response.split('\n\n')
unique_paras = set(p.strip() for p in paragraphs if len(p.strip()) > 50)
if len(unique_paras) >= len(paragraphs) * 0.9:
score += 0.15
# 检查是否有明显的不确定性承认(积极信号)
uncertainty_phrases = ['不确定', '可能', 'I\'m not sure', '需要更多信息']
# 在适当的地方承认不确定性是好的
score += 0.15 # 基础分
return min(score, 1.0)
# ========== 过滤管线 ==========
def filter_pipeline(self, sample: dict) -> bool:
"""SFT 数据多级过滤"""
instruction = sample.get("instruction", "")
response = sample.get("response", "")
# Level 1: 基础检查
if len(instruction) < 10 or len(response) < 50:
self.quality_stats["too_short"] += 1
return False
# Level 2: 格式检查
if response.count('```') % 2 != 0: # 未闭合的代码块
self.quality_stats["broken_format"] += 1
return False
# Level 3: 重复检测
lines = response.split('\n')
if len(lines) > 5:
unique_lines = set(l.strip() for l in lines if len(l.strip()) > 20)
if len(unique_lines) < len(lines) * 0.6:
self.quality_stats["repetitive"] += 1
return False
# Level 4: IFD 评分(需要模型推理)
# ifd_score = compute_ifd(instruction, response, reference_model)
# if ifd_score > threshold: # IFD 高说明模型本来就会
# self.quality_stats["too_easy"] += 1
# return False
self.quality_stats["passed"] += 1
return True
2026 工具调用 SFT 数据集新范例
工具调用 SFT 数据从 5% 提升到 10-15%,数据来源从”工具 API 合成”扩展到 2026 年的”工具 agent 合成范式”:
| 数据集 | 规模 | 工具来源 | 训练阶段 | 实战效果 |
|---|---|---|---|---|
| TOUCAN | 1.5M 工具轨迹 | 500+ 真实 MCP 环境 | SFT | BFCL v3 训练开源模型超越闭源 SOTA |
| ASTRA | 1,585 MCP / 19,036 工具 / 41 领域 | 公开 MCP Registry | SFT + RL 两阶段 | 14B/32B 模型 BFCL v3 / τ²-Bench / ACEBench 三基准 SOTA |
| APIGen-MT | 多轮轨迹 | 多轮 API 合成 | SFT | Salesforce/XLang 多轮 agent 训练 |
ASTRA 的工程创新详解(SFT 阶段):
- 工具调用图合成(非线性拼接):从公开 MCP Registry 收集 1,585 服务器 / 19,036 工具,构造”工具依赖图”
- 图遍历生成:按图遍历而非线性拼接,生成多轮结构化轨迹——避免”工具不兼容”假数据
- QA 分解构造可验证 Python 环境(RL 阶段):ground-truth 反馈避免 reward hacking
TOUCAN 的方法论(SFT 阶段):
- 从 500+ 真实 MCP 环境合成 1.5M 工具轨迹
- 覆盖并行/多步调用、多轮对话、边缘案例
- 无需人类标注(环境本身提供 ground-truth)
端到端 agent 数据准备流程(2026 实战):
- MCP 工具池构建:从公开 MCP Registry 收集 N 个服务器、M 个工具
- 工具调用图合成:建模工具依赖图,按图遍历生成多轮结构化轨迹
- 可验证环境构造:QA 分解构造可验证 Python / Web 环境
- SFT + RL 两阶段统一训练:ASTRA 风格统一框架处理两个阶段
🔬 数据配方系统消融:OctoMed 的五维实验(CVPR 2026)。上文关于”推理链多样性""质量控制”的判断多为工程直觉,而 OctoMed(MSR + UW-Madison,CVPR 2026,arXiv:2511.23269)在 7B 多模态医学推理场景下做了首个把”数据配方”作为一等公民的系统控制变量实验——以 Qwen2.5-VL-7B-Instruct 为基础模型,用 DeepSeek-R1 + GPT-4o 作为教师蒸馏推理链,经拒绝采样筛出 800 万例 / 68 亿 token 结构化医学推理数据,最终在 MedQA 达到 90.8%。其五维消融为章内直觉提供了定量依据:(1) 教师模型选择——强教师(DeepSeek-R1)与弱教师(GPT-4o 蒸馏)的质量差距无法被数据量补偿;(2) 每例推理链数量——提供多个有效推理链比重复同一最佳推理链更有效;(3) 推理链长度混合——混合长短推理链使模型自发产生任务难度感知(OOD 困难任务自动延长推理链);(4) 模态覆盖——纯文本推理数据在某些纯文本医学基准上比多模态数据更有效;(5) 数据规模——800 万例已接近收益递减区。核心结论:“多样性优于重复”在推理链设计中成立,且推理链结构比数据量的边际收益更高。
SFT 数据最终配比
"""
SFT 数据最终配比方案
总量:2M 条
"""
SFT_FINAL_MIX = {
"通用对话": {
"ratio": 0.25,
"samples": 500_000,
"来源": "种子进化 + 合成",
"特点": "单轮为主,覆盖日常问答、解释、建议",
},
"代码生成与调试": {
"ratio": 0.20,
"samples": 400_000,
"来源": "代码任务合成 + 拒绝采样",
"特点": "Python/JS/Java/C++ 多语言,含调试场景",
"难度分布": "简单40% / 中等40% / 困难20%",
},
"数学推理": {
"ratio": 0.15,
"samples": 300_000,
"来源": "数学题合成 + 步骤验证",
"特点": "要求完整推导过程,答案可验证",
},
"创作与翻译": {
"ratio": 0.10,
"samples": 200_000,
"来源": "多样化 prompt + 高质量回复",
"特点": "文风多样,含中英互译",
},
"知识问答": {
"ratio": 0.10,
"samples": 200_000,
"来源": "Wikipedia/百科 + QA 格式转化",
"特点": "覆盖科学/历史/地理/文化等",
},
"多轮对话": {
"ratio": 0.10,
"samples": 200_000,
"来源": "合成多轮 + 人工审核",
"特点": "平均 4-6 轮,含追问、澄清、话题切换",
},
"工具调用": {
"ratio": 0.10,
"samples": 200_000,
"来源": "工具 API 合成 + TOUCAN/ASTRA 工具轨迹",
"特点": "MCP 工具调用图合成 + 函数调用 + 参数提取 + 结果解释(2026 工具调用占比从 5% 提升到 10-15%)",
},
"安全拒答": {
"ratio": 0.05,
"samples": 100_000,
"来源": "红队测试 + 安全回复生成",
"特点": "有害请求拒绝 + 边界场景处理",
},
}
# 长度分布要求
SFT_LENGTH_DISTRIBUTION = {
"短回复 (<200 tokens)": 0.15,
"中短回复 (200-500)": 0.30,
"中等回复 (500-1000)": 0.30,
"中长回复 (1000-2000)": 0.18,
"长回复 (>2000 tokens)": 0.07,
}
30.5 RL 数据构建
偏好数据构造(DPO)
"""
DPO 偏好数据构造管线
目标:200K pairs
"""
class PreferenceDataBuilder:
"""偏好数据构造"""
def build_preference_pair(
self,
prompt: str,
n_responses: int = 4,
) -> dict:
"""构造一个偏好对"""
# 步骤 1:为同一个 prompt 生成多个回复
responses = []
for i in range(n_responses):
# 不同温度生成多样化回复
temp = 0.5 + i * 0.2 # 0.5, 0.7, 0.9, 1.1
# response = call_llm(model, prompt, temperature=temp)
# responses.append(response)
# 步骤 2:使用 LLM-as-Judge 评分
scores = []
for resp in responses:
score = self._judge_response(prompt, resp)
scores.append(score)
# 步骤 3:选择最高和最低作为 chosen/rejected
# 要求 margin > 0.5(差距要足够大)
sorted_pairs = sorted(zip(responses, scores), key=lambda x: x[1], reverse=True)
chosen = sorted_pairs[0]
rejected = sorted_pairs[-1]
margin = chosen[1] - rejected[1]
if margin < 0.5:
return None # margin 太小,弃用
return {
"prompt": prompt,
"chosen": chosen[0],
"rejected": rejected[0],
"chosen_score": chosen[1],
"rejected_score": rejected[1],
"margin": margin,
}
def _judge_response(self, prompt: str, response: str) -> float:
"""LLM-as-Judge 评分(含位置消偏)"""
judge_prompt = f"""请对以下 AI 助手的回复进行评分(1-10 分)。
评分标准:
1. 准确性:信息是否正确
2. 有用性:是否真正回答了问题
3. 清晰性:表达是否清楚易懂
4. 完整性:是否全面覆盖了要点
5. 安全性:是否有任何有害内容
用户问题: {prompt}
AI 回复: {response}
请给出 1-10 的综合评分,只输出数字:"""
# score_str = call_llm("gpt-4-turbo", judge_prompt, temperature=0)
# return float(score_str) / 10.0
return 0.0 # 框架示例
# Margin 分布要求
PREFERENCE_MARGIN_DISTRIBUTION = {
"easy (margin > 3.0)": "30% — 明显好/差的对比",
"medium (1.5 < m < 3.0)": "50% — 模型需要学习的主体",
"hard (0.5 < m < 1.5)": "20% — 微妙的质量差异",
}
推理增强 RL 数据
"""
推理增强 RL 数据构造
使用可验证奖励进行 GRPO 训练
"""
class ReasoningRLDataBuilder:
"""推理 RL 数据构造"""
def build_math_rl_data(self, target_count: int = 100_000) -> dict:
"""数学 RL 数据"""
difficulty_tiers = {
"tier1_warmup": {
"ratio": 0.20,
"solve_rate_target": "60-80%",
"source": "GSM8K 变体",
"description": "热身阶段,建立基本推理模式",
},
"tier2_learning": {
"ratio": 0.40,
"solve_rate_target": "30-50%",
"source": "MATH level 3-4",
"description": "主要学习区,最大信息增益",
},
"tier3_challenge": {
"ratio": 0.30,
"solve_rate_target": "15-30%",
"source": "MATH level 5 + 合成难题",
"description": "挑战区,推动能力边界",
},
"tier4_frontier": {
"ratio": 0.10,
"solve_rate_target": "5-15%",
"source": "竞赛题 + 极难合成题",
"description": "前沿区,少量但有价值",
},
}
return {
"total": target_count,
"tiers": difficulty_tiers,
"reward_type": "verifiable — 答案匹配",
"format": "每题含标准答案,用于自动奖励计算",
}
def build_code_rl_data(self, target_count: int = 150_000) -> dict:
"""代码 RL 数据"""
return {
"total": target_count,
"difficulty_distribution": {
"function_level": {
"ratio": 0.40,
"description": "单函数实现,有测试用例",
"avg_test_cases": 10,
},
"file_level": {
"ratio": 0.35,
"description": "多函数/类实现,模块级测试",
"avg_test_cases": 15,
},
"project_level": {
"ratio": 0.25,
"description": "多文件项目,集成测试",
"avg_test_cases": 20,
},
},
"reward_type": "verifiable — 测试用例通过率",
"languages": {
"python": 0.50,
"javascript": 0.20,
"java": 0.15,
"c++": 0.15,
},
}
def dynamic_difficulty_adjustment(
self,
current_solve_rates: dict,
target_solve_rate: float = 0.35,
) -> dict:
"""动态难度调整"""
adjustments = {}
for tier, rate in current_solve_rates.items():
if rate > target_solve_rate + 0.15:
adjustments[tier] = "↑ 提升难度或减少此级别比例"
elif rate < target_solve_rate - 0.15:
adjustments[tier] = "↓ 降低难度或增加此级别比例"
else:
adjustments[tier] = "✓ 在最佳学习区"
return adjustments
⚠️ SFT 数据与 RL 数据的工程分工:AceReason-Nemotron 1.1(NVIDIA,2025-06-16 发布)。SFT 数据和 RL 数据在数据工程层面有本质差异:SFT 数据需要展示”完整的怎么做”——包含推理步骤、中间结论和最终答案;RL 数据只需要”做得对不对”的可验证信号——问题 + 可自动判定的正确答案即可。NVIDIA 的 AceReason-Nemotron-1.1-7B(基于 Qwen2.5-Math-7B)清晰体现了这一分工:SFT 阶段使用 383K 个提示(数学 247K + 代码 136K,经 9-gram 去污染过滤后由 DeepSeek-R1 生成响应,并沿 v1→v7 配方逐步扩展至 2.2M 样本),随后用 GRPO 做 RL——严格 on-policy 采样、无 KL 项、响应长度预算从 8K 逐步增长到 32K、数学与代码阶段交替进行。关键发现:更强的 SFT 起点在 RL 后仍持续领先(虽差距在 RL 过程中收窄),RL 相较 SFT 起点在 AIME24 额外提升 10.6 分、LCB v6 提升 8.3 分。工程启示:数据团队应为 SFT 和 RL 规划独立的数据预算与生成策略——混淆两者会浪费 RL 阶段最稀缺的资源:可验证的 ground truth 问题。
最终评估
"""
全流程评估方案
"""
FINAL_EVALUATION = {
"通用能力": {
"MMLU (5-shot)": {"target": "> 62", "baseline": "Qwen2.5-7B: 63.2"},
"C-Eval (5-shot)": {"target": "> 72", "baseline": "Qwen2.5-7B: 74.1"},
"HellaSwag (10-shot)": {"target": "> 77", "baseline": "Llama3.1-8B: 78.5"},
"ARC-Challenge (25-shot)": {"target": "> 55", "baseline": "Qwen2.5-7B: 56.3"},
},
"代码能力": {
"HumanEval": {"target": "> 65", "note": "代码增强重点"},
"MBPP": {"target": "> 60"},
},
"数学能力": {
"GSM8K": {"target": "> 75", "note": "数学增强重点"},
"MATH": {"target": "> 40"},
},
"对话能力": {
"MT-Bench": {"target": "> 7.5", "note": "多轮对话"},
"AlpacaEval 2.0": {"target": "> 20% LC win rate"},
},
"安全性": {
"TruthfulQA": {"target": "> 50"},
"内部红队测试": {"target": "有害回复率 < 3%"},
},
}
# 评估时间表
EVAL_SCHEDULE = """
| 阶段 | 评估频率 | 评估集 | 决策 |
|------|---------|--------|------|
| 预训练 | 每 20B tokens | MMLU, C-Eval, HellaSwag | 监控收敛,检查数据质量 |
| 中训练 | 每 2B tokens | 全量 benchmark | 遗忘监控,决定是否调整配比 |
| SFT | 每 epoch | MT-Bench + 人工抽检 | 调整数据配比或停止训练 |
| RL | 每 5K steps | MT-Bench + 安全测试 | 监控 reward hacking |
| 最终 | 一次性全量 | 全部 benchmark + 人工盲测 | 决定是否发布 |
"""
30.6 全流程时间线与成本估算
"""
7B 模型全流程数据工程时间线与成本
"""
PROJECT_TIMELINE = {
"第 1-2 周": {
"任务": "需求分析 + 数据源调研 + 管线原型",
"人力": "数据工程师 ×2, 研究员 ×1",
"关键输出": "数据策略文档、处理管线 v0.1",
},
"第 3-6 周": {
"任务": "预训练数据全量处理 + 迭代",
"人力": "数据工程师 ×3, GPU 集群用于质量模型推理",
"关键输出": "420B tokens 预训练数据 v1.0",
"计算资源": "32×A100 用于质量分类器推理",
},
"第 7-8 周": {
"任务": "中训练数据准备 + 预训练启动",
"人力": "数据工程师 ×2(中训练数据), 训练工程师 ×2(启动预训练)",
"关键输出": "42B tokens 中训练数据",
},
"第 9-12 周": {
"任务": "预训练进行中 + SFT/RL 数据并行准备",
"人力": "数据工程师 ×2(SFT数据), 标注团队 ×5(种子数据)",
"关键输出": "2M SFT 数据 + 500K RL 数据",
"计算资源": "256×H100 预训练 + 16×A100 数据合成",
},
"第 13 周": {
"任务": "中训练",
"关键输出": "中训练完成的 checkpoint",
},
"第 14 周": {
"任务": "SFT + RL",
"关键输出": "最终模型",
},
"第 15 周": {
"任务": "全量评估 + 问题修复",
"关键输出": "评估报告,决定是否发布",
},
}
COST_ESTIMATE = {
"计算成本": {
"预训练 (256×H100×30天)": "~$800K",
"中训练 (256×H100×5天)": "~$130K",
"SFT+RL (64×H100×5天)": "~$35K",
"数据处理 (32×A100×30天)": "~$65K",
"评估 (8×A100×10天)": "~$5K",
"小计": "~$1.03M",
},
"数据成本": {
"存储 (50TB×3个月)": "~$5K",
"数据下载带宽": "~$2K",
"标注人力 (种子数据+质量审核)": "~$30K",
"合成数据 API 调用": "~$15K",
"小计": "~$52K",
},
"人力成本 (15周)": {
"数据工程师 ×3": "~$45K",
"训练工程师 ×2": "~$30K",
"研究员 ×1": "~$15K",
"小计": "~$90K",
},
"总计": "~$1.17M",
}
30.7 案例要点回顾
| 要点 | 说明 |
|---|---|
| 数据准备是主要工作 | 数据工程占项目总时间的 60-70%,远超训练本身 |
| 小模型代理很重要 | 用 400M 模型做配比实验可以节省大量算力 |
| 四阶段数据量递减 | 420B → 42B → 4B → 2B tokens,但单条价值递增 |
| 遗忘防控从数据开始 | 中训练阶段 30% 的回放数据是防止遗忘的第一道防线 |
| SFT 重质量不重数量 | 100 条精心设计的种子数据比 10 万条随机数据更重要 |
| RL 需要可验证奖励 | 数学和代码的可验证奖励大幅降低了人工偏好标注的需求 |
| 迭代是常态 | 预训练数据经历了 5 个版本迭代才达到最终质量 |
| 成本结构 | 算力占 88%,数据处理占 5%,人力占 7% |
💡 最重要的一课:没有完美的数据,只有足够好的数据和持续改进的流程。与其追求一次性做到完美,不如建立一个快速迭代的数据工程体系。好的数据工程不是一个项目,而是一种能力。
第二部分:工具链全景
工具是数据工程师的”手脚”。
从 trafilatura 到 OpenRLHF,工具栈的演进就是数据工程的进化史。
第一部分的手工实战告诉我们数据工作应该”做什么”;这一部分回答”用什么做”。工具栈选型的核心原则是:算子选最好的原子工具,编排用最可靠的开源框架,平台把溯源和版本管理做成基础设施。
30.8 工具栈全景
预训练数据工具栈
| 工具 | 用途 |
|---|---|
| trafilatura | 网页正文抽取 |
| resiliparse | 网页解析(备选) |
| fastText | 语言识别 |
| CCNet | 高级语言过滤 |
| FineWeb-Edu | 教育内容分类器 |
| KenLM | 困惑度过滤 |
| datasketch | MinHash 去重 |
| Presidio | PII 检测与脱敏 |
| SentencePiece | BPE/Unigram 分词 |
| tiktoken | OpenAI 风格分词 |
| DoReMi | 数据配比优化 |
| DataTrove | 分布式数据处理管线框架 |
后训练数据工具栈
| 工具 | 用途 |
|---|---|
| Self-Instruct | 种子驱动合成 |
| Evol-Instruct | 进化合成 |
| Magpie | 零种子合成 |
| UltraFeedback | RLAIF 偏好数据 |
| OpenRLHF | RL/DPO 训练框架 |
| TRL | HuggingFace 后训练框架 |
| vLLM | 高效 rollout 推理 |
| MT-Bench | 多轮评测 |
| τ-Bench | Agent 评测 |
| BFCL | 工具调用评测 |
30.9 关键工具详解
trafilatura(网页抽取)
import trafilatura
# 从 HTML 抽取正文
html = fetch_url("https://example.com/article")
text = trafilatura.extract(html,
include_comments=False,
include_tables=True,
favor_precision=True # 偏精确
)
# 元数据抽取
metadata = trafilatura.extract_metadata(html)
踩坑:
favor_precision=True召回低但质量高- 对中文网页效果一般,需要配合 resiliparse
datasketch(MinHash 去重)
from datasketch import MinHash, MinHashLSH
# 创建 MinHash
m1 = MinHash(num_perm=128)
for ngram in get_ngrams(text1, n=5):
m1.update(ngram.encode())
# LSH 索引
lsh = MinHashLSH(threshold=0.7, num_perm=128)
lsh.insert("doc1", m1)
# 查询相似文档
matches = lsh.query(m2)
经验:
num_perm=128是工业级甜点threshold=0.7适合 Jaccard 相似度- 大规模去重用 LSH(百万级以上)
Presidio(PII 脱敏)
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine
analyzer = AnalyzerEngine()
anonymizer = AnonymizerEngine()
# 检测 PII
results = analyzer.analyze(
text="我的电话是 13800138000,邮箱是 test@example.com",
language="zh"
)
# 脱敏
anonymized = anonymizer.anonymize(
text="我的电话是 13800138000",
analyzer_results=results
)
# 输出: "我的电话是 <PHONE_NUMBER>"
局限:
- 中文 PII 识别不如英文
- 需要自定义规则补充(如身份证、地址)
OpenRLHF(后训练框架)
OpenRLHF(OpenRLHF Team, 2024)是开源的 RL/DPO 训练框架:
# OpenRLHF 训练 DPO 示例
from openrlhf.datasets import PreferenceDataset
from openrlhf.trainer import DPOTrainer
dataset = PreferenceDataset.from_json("preference.json")
trainer = DPOTrainer(
model="llama-3-8b",
ref_model="llama-3-8b-sft",
beta=0.1,
learning_rate=5e-7
)
trainer.train(dataset)
优点:
- 支持 SFT/DPO/PPO/GRPO 全套
- 分布式训练(Ray + DeepSpeed / Molt)
- 与 vLLM 集成做高效 rollout
Molt 后端(2026-06, v0.10.4):OpenRLHF 新增基于 Automodel 的 Molt 后端,摆脱 DeepSpeed 依赖,可将 RL 训练扩展到数千亿参数规模。Molt 后端使 RL 训练不再受限于 DeepSpeed 框架,同时 v0.10 已支持多轮 VLM RL(图像输入 + 截图反馈)和 VLM RLHF。
TRL(HuggingFace 后训练)
from trl import SFTTrainer, DPOTrainer
# SFT
trainer = SFTTrainer(
model="llama-3-8b",
train_dataset=sft_dataset,
max_seq_length=4096
)
trainer.train()
# DPO
trainer = DPOTrainer(
model="llama-3-8b-sft",
ref_model="llama-3-8b-sft",
beta=0.1,
train_dataset=preference_dataset
)
trainer.train()
优点:
- 与 HuggingFace 生态无缝集成
- 简单易用
- 社区活跃
缺点:
- 大规模训练效率不如 OpenRLHF
- RL 阶段功能较弱
新竞争者:Google OpenRL(2026-07)是实验性自托管后训练微调服务,支持 macOS / Nvidia GPU / GKE,兼容 Tinker 端点。FeynRL 强调微调方案与系统逻辑分离,基于 DeepSpeed / Ray / vLLM 实现规模化,降低新方法开发门槛(Google OpenRL 仍为实验性,选型时需验证)。
vLLM(高效推理)
from vllm import LLM, SamplingParams
# 批量生成(用于 rollout)
llm = LLM(model="llama-3-8b")
sampling = SamplingParams(
n=16, # 一次采 16 个
temperature=0.7,
max_tokens=8192
)
outputs = llm.generate(prompts, sampling)
价值:RLVR 训练时每 prompt 要采 N=8-64 次,vLLM 的 PagedAttention 让推理速度提升 5-10 倍。
30.10 平台建设
分布式计算
Spark(预训练数据处理):
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("DataPipeline").getOrCreate()
# 大规模去重
df = spark.read.parquet("raw_data/")
df = df.repartition(1000).apply(minhash_dedup)
df.write.parquet("deduped/")
Ray(后训练):
import ray
@ray.remote(num_gpus=1)
def generate_response(prompt):
return model.generate(prompt)
# 并行生成 100K 响应
futures = [generate_response.remote(p) for p in prompts]
results = ray.get(futures)
SLURM(集群调度):
# 提交训练任务
sbatch --gres=gpu:8 --nodes=4 train.sh
数据管理平台
工业级数据管理平台的核心功能:
- 数据湖存储:原始/清洗/训练版本分层
- 溯源索引:每条数据可追溯到来源
- 版本控制:DVC 风格的数据版本管理
- 质量监控:自动跑 IFD/多样性/污染检测
- 配方管理:可视化管理三轴配方
- A/B 对比:版本间对比评测
溯源索引
# 每条数据都有溯源元数据
{
"id": "data_2026_07_06_0001",
"source": {
"type": "synthetic",
"generator": "llama-3-70b",
"method": "magpie",
"timestamp": "2026-07-06T10:00:00Z"
},
"lineage": {
"raw_id": "raw_2026_07_06_001",
"processed_by": ["magpie_gen", "pii_filter", "dedup", "deita_select"]
},
"training_runs": ["sft_v3", "dpo_v2"]
}
溯源索引让数据问题能快速定位——某次训练掉分,能查到是哪批数据导致的。
为什么不能依赖平台自带的许可字段
一个反直觉但必须知道的事实:数据集托管平台上标注的许可信息,本身是不可信的。Data Provenance Initiative 对来自 44 个广泛使用文本集合的 1,858 个微调数据集做了大规模法律+专家标注审计(Nature Machine Intelligence, 2024),结论是:
| 发现 | 数字 | 说明 |
|---|---|---|
| 许可未指定率 | >70%(GitHub / HuggingFace 72%,Papers with Code 83%) | 平台上最流行的数据集里,三分之二以上根本没标许可 |
| 严格重标注后类别不符率 | 66%(HuggingFace) | 平台标注的许可使用类别与原作者实际许可不同 |
| 其中”标得比原作者更宽松” | 约 29%(GitHub)/ 27%(HF)/ 16%(Papers with Code) | 这是最危险的一类:你会以为可以商用,实际不行 |
| 人工标注后可降到 | 30.7% | 说明问题不是”没有许可”,而是”没有登记” |
对数据工程的直接含义有三条:
source字段里的license不能只抄平台元数据。抄来的值有 66% 概率是错的,且错误方向偏宽松——这正好是会造成法律后果的方向。必须回溯到数据集的原始出处(作者的 GitHub 仓库 LICENSE 文件 / 论文声明)确认,并把”我核对过”这件事本身记录成字段(例如license_verified_by/license_verified_at)。- “未指定”不等于”无限制”。审计发现大量数据集其实有许可,只是上传者没填。把未指定当作可自由使用,是实践中最常见的合规漏洞。
- 集合型数据集的许可是 composition 问题。许多公开集合是几十上百个子数据集的再打包,上传者常给整体挂一个许可,而子数据集要求各不相同(有的禁商用、有的要求署名)。溯源索引如果只记录最终集合的许可,就丢掉了真正决定合规性的那层信息——
lineage数组里应保留每一层的许可,而不只是最外层。
该计划同时开源了 Data Provenance Explorer(dataprovenance.org),可按许可条件、语言覆盖、是否模型生成等维度筛选数据集,并自动生成”数据溯源卡”(data provenance card)——这套卡片格式可以直接作为溯源元数据的字段设计参考。
GPU 加速数据管线
趋势:数据处理从 CPU 向 GPU 迁移。
NVIDIA NeMo Curator 已利用 RAPIDS cuDF / cuML 实现 GPU 加速去重和过滤,CPU→GPU 迁移是下一代数据平台方向。vLLM v0.25.1(2026-07-14)已支持 Python 3.10-3.14,推理和数据处理的全栈 GPU 化正在加速。
管线编排层与算子层的分工
前文的工具栈表格列的是算子(分词器、MinHash 去重库、质量分类器)。但工业级管线真正的工作量不在写算子,而在编排:
| 层 | 职责 | 开源代表 |
|---|---|---|
| 算子层 | 单个变换:抽取、过滤、去重、打标 | trafilatura / datasketch / fastText / FineWeb-Edu 分类器 |
| 编排层 | DAG 组装、分片、断点续跑、跨节点调度、产物登记 | DataTrove(HuggingFace 开源) |
| 加速层 | 把算子搬到 GPU / 多节点上跑 | NeMo Curator(RAPIDS cuDF / cuML) |
DataTrove 的定位是编排层:它把数据处理抽象为 PipelineStep 的组合,每个 step 独立处理一个数据分片(shard),因此天然支持断点续跑——某个 step 失败只需重跑该 step,不必从头再来。它同时提供本地多进程、Slurm 集群、Ray 集群三种 executor,同一份 pipeline 代码可以不改动地从笔记本调试切换到上百节点跑生产。FineWeb、FineWeb-Edu、SmolLM 的公开数据管线都是以 DataTrove 为基础构建的,这也使得它成为目前复现 SOTA 开源数据配方时最省力的起点。
为什么编排层值得单独投入:数据管线的成本结构里,算子开发是一次性的,而重跑是反复发生的。配比要调、上游源要换、模型换代后要重新过滤——每一次都意味着 TB 级数据重新过一遍。编排层决定的是”改一个参数后要付多少钱”:有分片和断点续跑,重跑成本是 O(变更的 step);没有,则是 O(全管线)。
工程判据(落地自查):
- 分片粒度:shard 足够小才能并行与续跑,但太小会让元数据管理开销上升。经验起点是让单个 shard 处理时间在分钟级。
- 产物可追溯:每个 shard 的每一步都应留下”输入 hash → 输出 hash + 参数快照”,否则溯源索引只能记到数据集粒度,记不到样本粒度。
- CPU 与 GPU 的边界:文本抽取、正则清洗这类逐字节操作放 GPU 上收益有限;MinHash 去重、嵌入排序、模型打标(分类器推理)才是 GPU 加速的主战场。盲目全栈 GPU 化往往只是把瓶颈从 CPU 挪到 PCIe 带宽。
- 失败是常态:上游源里混入的超长行、编码错误、空文件,在 TB 级数据上必然出现。编排层必须默认”每一步都会有一小部分数据失败”,并提供失败样本隔离而非整体中断的机制。
⚠️ 避免把”全栈 GPU 化”当目标:GPU 加速解决的是吞吐,不解决正确性。NeMo Curator 之类的加速只有在算子语义与 CPU 版本严格对齐时才有意义——去重阈值、分类器阈值在不同实现下的细微差异,会在 TB 级数据上放大成配方漂移。加速前应先固化 CPU 基线的产物指纹,作为加速版的对齐基准。
30.11 典型案例拆解
Llama 3:15T 高质量数据
核心数据工程:
-
15T tokens 预训练数据
- 网页:70%(FineWeb 风格清洗)
- 代码:15%(GitHub stars 过滤)
- 书籍:5%
- 学术:5%
- 数学/推理:5%
-
DoReMi 配比优化
- 用 1B 参考模型找最优配比
- 优化后下游任务 +3-6%
-
后训练
- SFT:人工标注 50K(高质量)
- DPO:100K 对偏好数据
- RLVR:未公开细节
关键经验:
- 预训练数据质量 >> 数量(15T 精选胜过 30T 粗制)
- 人工标注的核心地位(40 人全职团队)
DeepSeek-V3 + R1:MoE 与纯 RL
DeepSeek-V3:
- MoE 架构(671B 总参数,37B 激活)
- 14.8T tokens 预训练
- 数据工程亮点:数学与代码数据占比 40%+
DeepSeek-R1:
- R1-Zero:跳过 SFT,直接 RLVR
- 涌现长链思维(输出 12K+ tokens)
- 数学:sympy verifier
- 代码:单测 verifier
关键经验:
- RLVR 可以让模型”涌现”推理能力
- 不给参考 CoT,模型能突破数据上限
- Verifier 设计是 RLVR 的核心
Qwen:多语言数据
Qwen 系列:
- Qwen-2.5:18T tokens 预训练
- 多语言:29 种语言
- 数据工程亮点:
- 中文数据占比 30%(最大中文模型之一)
- 多语言均衡,避免英文主导
- 代码与数学加强
关键经验:
- 多语言数据要”按比例配”,不能英文主导
- 中文场景需要专门的清洗规则(如繁简转换、标点归一化)
Kimi K3:首个 3 万亿级开源模型(2026-07)
Kimi K3(Moonshot AI, 2026-07)以 2.8T 参数规模成为首个开源 3 万亿级模型,MIT 修改许可证发布。
核心数据工程:
- 开源权重但数据配方尚未完整公开
- MXFP4 精度下需约 1.4TB 显存,极少实验室能本地全量运行
- Arena.ai Frontend Code Arena 以 1,679 分超过 Claude Fable 5(1,631 分)
数据工程意义:Kimi K3 标志着开源模型的参数上限从千亿级正式迈入万亿级。MXFP4 精度下的数据工程(如量化感知训练的数据配方设计)成为新的研究课题。待技术报告充分公开后,其数据配比和合成数据策略值得深入拆解。
第三部分:未来趋势
“预测未来最好的方法是创造它。” 从 GPT-3 到 DeepSeek-R1,短短五年间数据工程经历了多次范式转变。这一部分把两书对未来趋势的判断合并收敛为一张地图——不是作为预言,而是作为值得探索的方向。
30.12 数据墙:已被突破的天花板
问题的本质:
人类文明积累的高质量互联网文本总量大约在 10-15T tokens 的量级。当前最大的模型(Llama 3 训练了 15T tokens)已经逼近甚至触及了这个天花板。去重后的高质量文本就更少了——FineWeb 2 的全量去重数据也不过约 15T tokens。
互联网高质量文本的供给曲线(估算)
可用量
(T tokens)
15 | ┌──────── 天花板 ───────
| ╱
10 | ╱
| ╱
5 | ╱
| ╱
0 |╱
+──────────────────────────────
2020 2022 2024 2026 2028
问题:2026 年之后,高质量互联网文本的增量已经
无法满足模型规模的指数增长需求。
⚠️ 上面这条曲线画的是”物理可用量”,不是”合法可用量”。 同一批 token 会因为三种原因退出可用集合,而这与曲线本身无关:出版方更激进地屏蔽 AI 爬虫、授权成本上升、以及权利人的选择退出(EU DSM 指令第 4(3) 条)。这是一条独立的、向下的衰减路径,且它与 30.18 节的合规义务是同一件事的两面。
工程后果是:“重过滤”这条腿不能只过滤质量,还要过滤许可状态。本书第二部分溯源索引里”许可不能只抄平台元数据”那条在这里接上——Data Provenance Initiative 的审计发现平台标注类别不符率 66%,其中约 27–29% 标得比原作者更宽松。供给侧的物理墙和合规墙必须画在同一张图上,否则会得出”再爬一遍就有数据”的错误结论。
⚠️ 待验证:本条为定性补充——出版方封锁与授权成本的衰减幅度目前没有可引用的量化数据,只确认方向。(多来源一致支持方向)
但是——数据墙已在 2026 年被实际突破:
2026 年上半年的关键数据表明,数据墙不再是理论上的威胁,而是一个已被工程手段突破的现实:
- 合成数据占比飙升:新训练 token 中合成数据占比从 2023 年的 26% 增至 2026 年的 60%+(部分研究引用 68% 估算值)——合成数据已从”补充”变为”主力”
- 模型崩溃率 < 2%:在严格的验证-拒绝管道下,合成数据导致的模型崩溃率已降至 2% 以下
- 验证驱动成为关键:不是”合成数据有无风险”的问题,而是”验证管道是否足够严格”的问题
⚠️ 引用任何”崩溃率”之前,先问一句”它的生成侧种子是怎么设的”。 崩溃类指标对采样配置高度敏感,而这一点在绝大多数报告里不会被写进实验设置。arXiv:2609.11149《Break Step: Recursive Training Resonates with Replayed Sampling Noise》(Liu & Han,2026-09-10)给出的是迄今最干净的一次归因:
在 vLLM 下,当一个 batch 由同一个种子化的采样配置提供服务时,每个请求拿到的是同一串随机数,而固定种子会让这串随机数在每一代被重放。两个条件必须同时成立才会出问题:
- 跨请求共享(batch 内同一串随机数)+ 跨代重放(每代都重放同一串)→ 两个条件都在时,来自五个家族的 7 个 checkpoint 到第 3 代时 unique 4-gram 比例掉到 0.045–0.38;
- 去掉任意一个(每代换掉共享种子,或给每个请求各自的种子但每代重复)→ 两个 StableLM checkpoint 的 unique 4-gram 比例在第 3 代仍保持在起始值 0.98 附近。
作者的结论是:部分被报告的”模型崩溃”,其来源是采样器的设置,而不是递归训练本身。 更值得记的是后面半句——用”每个请求各自取种子”的方式去解码,那条被重放的 StableLM-2-1.6B 链在第 3 代的权重能恢复大部分多样性。也就是说这种情况下权重并没有被永久写坏,坏的是解码时看到的那一串随机数。
因此本节的”崩溃率 < 2%“应当读作:在特定的生成-验证管道下测到的读数,而不是”递归训练本身的风险已降到 2% 以下”。跨研究比较崩溃率时,采样配置(是否共享种子、是否跨代重放、top-p 设置)必须作为实验条件一并记录。
这意味着:从”被动利用互联网存量数据”到”主动构造高信息密度的训练信号”的范式转变已经完成。 数据墙曾推动了合成数据、验证驱动、Agent 轨迹等创新方向的发展,但结果不是”绕过”了数据墙,而是”突破”了它。
2025-2026 数据集 4-5× 规模扩张(数据墙的工程化回答)
| 数据集 | 2024 规模 | 2026 规模 | 扩张倍数 | 维护者 |
|---|---|---|---|---|
| FineWeb | 1.5T | FineWeb 2 ~10T | 6.7× | Hugging Face |
| RedPajama | v1 1.2T | v2 ~30T | 25× | Together AI |
| Dolma | 1.6T | Dolma 3 ~6T | 3.75× | Allen AI |
| Nemotron-CC | — | 6.3T | 新增 | NVIDIA |
| Common Pile | — | ~1T (8TB) | 新增 | Allen AI + EleutherAI |
| Zyda | — | Zyda 2 5T | 新增 | Zyphra |
前沿模型实际训练 token(与数据集规模脱钩):
| 模型 | 训练 token | 相对 Chinchilla 倍数 |
|---|---|---|
| Llama 3.1 8B | 15.6T | ~1950×(7B 模型 1875×) |
| DeepSeek-V3 | 14.8T | ~370×(671B 模型) |
| Qwen 3 | ~36T | ~300×(最大变体) |
关键结论:
- 数据集规模 4-5× 扩张 + 商业级蒸馏(Nemotron-CC 4 阶段)+ fully-permissive 合规(Common Pile)+ 多语言高质量过滤(FineWeb 2)三路并行
- 趋势从”原始 CC dump”到”重过滤+去重+分类器评分子集”——数据墙的工程化回答不是绕过,而是”重过滤 + 合成”双轮驱动
- 7B 模型过训练 5-7× 已成主流(参考 Llama 3.1 8B 的 15.6T),实际需要 1T-2T tokens 训练预算
后数据墙时代的核心挑战:
数据墙被突破后,新的挑战浮出水面:
| 挑战 | 说明 | 当前状态 |
|---|---|---|
| 质量天花板 | 合成数据受限于教师模型能力,天花板效应明显 | 研究前沿 |
| 分布偏差 | 合成数据的分布窄于真实数据,长尾覆盖不足 | 工程可缓解 |
| 验证成本 | 高质量验证管道的计算成本可能超过训练本身 | 持续优化中 |
| 混合比例 | 合成 vs 真实数据的最优混合比例尚无定论 | 经验驱动(30.12.1 给出可用的区间与因果结构) |
应对策略矩阵:
| 策略 | 成熟度 | 效果 | 风险 |
|---|---|---|---|
| 合成数据 | ✅ 成熟 | 已成主力(60%+ 占比) | 分布偏差、验证成本 |
| 多模态数据 | 快速发展中 | 开辟新数据源 | 标注成本高 |
| 数据效率优化 | 研究前沿 | 同量数据训练效果更好 | 理论不完善 |
| Agent 交互数据 | 早期落地 | 全新数据类型 | 质量参差不齐 |
| 无环境 Agent 数据 | 研究突破 | 无需搭建环境,降本增效 | 教师模型依赖 |
| 主动数据收集 | 早期探索 | 针对性强 | 成本和伦理问题 |
| 数据重复使用 | 有争议 | 简单直接 | 收益递减,过拟合 |
30.12.1 混合比例:可用区间、因果结构与损失侧旋钮
上表把混合比例写成”经验驱动、尚无定论”,这在方法论上诚实,但对工程没有可操作性。2026 年已经有三类可以写进正文的东西。
① 可用的实践区间:合成 30–50%,其余真实且经策展。 多份来源反复给出的经验区间落在这里,方向是”不是越高越好”。注意这与上面”60%+“并不矛盾——按 30.13 已有的四类口径表(token vs 样本、预训练 vs 后训练、改写算不算、蒸馏算不算)对齐后,60%+ 多为后训练口径或含改写;预训练侧的常见实践区间是 30–50%。写的时候必须标口径,否则章内自相矛盾。
② 因果结构:数据闸门是必要条件,奖励设计不是充分条件。 这条对 30.16 的”闭环数据引擎”最直接。Survive or Collapse: The Asymmetric Roles of Data Gating and Reward Grounding in Self-Play RL(arXiv:2605.22217,Pu et al.,2026-05-21)在 Python 输出预测任务与一个剔除预训练先验/输出歧义/执行器噪声的确定性 DSL 孪生任务上同时变动奖励设计与数据级过滤的严格度,结论是:严格的数据闸门在我们测试的每一种奖励变体下都足以维持稳定,包括一个拿不到真值的自洽奖励;而闸门一旦移除,没有任何奖励变体能阻止崩溃。
⚠️ 适用范围:该实验设置是自博弈 RL 的窄任务(代码预测、DSL),不可外推到 web 规模预训练。它支持的是”自生成闭环必须自带闸门”这一条,不是”预训练数据过滤的普适结论”。
③ 损失侧也有旋钮,不只是数据侧。 ForTIFAI(arXiv:2509.08972,npj Artificial Intelligence 2026)的核心观察是:自回归模型对它自己生成的文本会给出高置信度。据此提出 Confidence-Aware Loss(CAL),以 Truncated Cross-Entropy(TCE)为主要实例——在训练时对高置信 token 降权(按置信阈值 mask 掉),等效于把”很可能是机器产物的部分”从学习信号里滤掉。实测:模型可容忍超过 2.3 倍于标准交叉熵的合成数据量才出现崩溃。TCE 是 model-agnostic 的,可以直接叠在标准 CE 上。
配套还有一条对工程判断有用的观察:训练指标会先于验证准确率发散——尾部流失最先出现在分布类度量上,而不是准确率上。这意味着用准确率监控崩溃会系统性滞后。
三条放在一起的读法:闸门(数据侧过滤)→ 是必要条件;损失侧(CAL/TCE)→ 是延后崩溃 onset 的旋钮,不替代闸门;混合比例 → 是区间而非单调。三者不是互斥的替代品,而是三层。
🔮 判断:数据墙不是一个需要绕过的弯道,而是一面已被工程手段突破的墙。2026 年的真正挑战不再是”数据够不够”,而是”数据好不好”——质量天花板、分布偏差、验证成本构成了新的约束三角。
⚠️ “文本数据墙”与”Agent 数据墙”是两种性质不同的瓶颈。文本数据墙的核心约束是高质量自然语言 token 的稀缺性——合成数据通过模型生成补充了这一缺口。Agent 数据墙的核心约束是”环境的物理成本”——每新增一个应用组合需要搭建全套沙盒环境(服务器+数据库+接口),且边缘案例覆盖依赖运气而非系统生成。2026 年 7 月 Apple 的 ESAT(见本章”Agent 数据”一节)为 Agent 数据墙提供了类似”合成数据突破文本数据墙”的潜在路径——用模型的想象力替代物理环境。理解两类瓶颈的本质差异,有助于数据工程师为不同阶段制定正确的突破策略。
30.13 合成数据的代际演进
合成数据是应对数据墙最直接的方案。它的占比仍在持续上升,但在引用任何具体百分比之前,必须先问清口径。
⚠️ “合成数据占比”数字在引用前必须先问清口径:
“合成数据占比”至少有四种互不等价的算法——按 token 数还是按样本数?只算后训练还是包含预训练?合成改写(真实文本经模型润色)算合成还是算真实?蒸馏自其他模型的输出算不算?
后训练阶段的合成占比本来就天然很高(Magpie 这类零种子合成几乎全是合成数据),因此”占比 70%+“如果统计的是后训练样本,含金量远低于它统计预训练 token 时的含金量。不同来源给出的预测数字差异,绝大多数来自口径差异,而非判断分歧。因此在引用任何具体百分比前,先确认它统计的是哪一层;跨来源直接比较这些数字是没有意义的。
代表实践:
- Microsoft Phi 系列:合成数据为主
- NVIDIA Nemotron:合成数据 + 真实数据混合
- Anthropic Claude:合成 Constitutional 数据
关键挑战:
- 合成数据的”模型偏置”如何消除
- 合成数据的”能力上限”如何突破
- 合成数据的法律风险(OpenAI ToS 禁止用 GPT 输出训练竞品)
合成数据本身正在快速代际演进,理解其演进脉络比记住任何单一数字更重要。
第一代(2023):直接生成
- 方法:用 GPT-4/Claude 直接生成
- 特点:质量受限于教师模型能力
- 问题:多样性不足、存在系统性偏差、有 Model Collapse 风险
第二代(2024-2025):验证驱动
第二代合成数据的四大特征:
1. 验证驱动(Verification-driven)
┌─────────────────────────────────────┐
│ 生成 → 验证 → 反馈 → 再生成 │
│ 不是"生成即可用",而是"验证后可用" │
└─────────────────────────────────────┘
2. 环境交互(Environment-grounded)
┌─────────────────────────────────────┐
│ 模型在环境中行动 → 收集轨迹数据 │
│ 代码执行、工具调用、网页浏览 │
└─────────────────────────────────────┘
3. 自我博弈(Self-play)
┌─────────────────────────────────────┐
│ 多个模型相互博弈 → 产生新的训练信号 │
│ 类似 AlphaGo 的自我进化 │
└─────────────────────────────────────┘
4. 课程化(Curricular)
┌─────────────────────────────────────┐
│ 根据模型当前能力动态调整合成难度 │
│ 始终保持在"最近发展区" │
└─────────────────────────────────────┘
第三代(2026):推理优先(Reasoning-first)
第二代合成数据的验证驱动模式已大规模落地,但 2026 年出现了更深层的范式转变:不是先有数据再训练推理能力,而是先构造推理链,再由推理链生成数据。
第三代合成数据的核心逻辑:
传统方向:数据 → 模型 → 推理能力
(希望涌现)
第二代方向:生成 → 验证 → 可用数据
(过滤式)
第三代方向:推理链 → 数据 → 模型
(构造式,反转因果)
第三代的关键方法:
| 方法 | 来源 | 核心思想 | 效果 |
|---|---|---|---|
| Reasoning-first | Google/EPFL Simula | 先构建推理链,再由推理链生成数据,反转”数据→推理”的传统方向 | 推理密度高,多样性好 |
| SynthLLM | 微软亚洲研究院 | 系统性合成高质量预训练数据:知识图谱→教材→习题的结构化教学生成 | 信息密度显著高于直接生成 |
| 自博弈+验证收敛 | 多团队 | 不仅是生成-过滤,而是生成-验证-迭代-收敛的完整循环 | 崩溃率 < 2%,质量持续提升 |
| 隐私保护合成 | AWS Clean Rooms 等 | 企业级隐私保护环境下的合成数据生成 | 解决数据合规瓶颈 |
代际演进总结:
| 代际 | 核心范式 | 关键技术 | 风险控制 |
|---|---|---|---|
| 第一代(2023) | 直接生成 | GPT-4/Claude 生成 | 无 |
| 第二代(2024-2025) | 验证驱动 | 生成→验证→反馈→再生成 | 过滤式,崩溃率 ~5% |
| 第三代(2026) | 推理优先 | 推理链→数据→模型 | 构造式,崩溃率 < 2% |
微软 SynthLLM 框架给出了一个有价值的方向:不是让模型直接生成答案式数据,而是让模型设计”知识图谱 → 教材 → 习题”这样的结构化教学内容。这种方法产生的合成数据信息密度更高,多样性也更好。微软 Synthetic Data Showcase 持续演进,提供结构化教学数据生成的完整工具链。
值得注意的是,验证驱动(Verification-driven)的合成方法正逐步成熟——从”生成即可用”转向”验证后可用”。结合 Agent-based Data Preparation Systems 的初步探索(arXiv: 2603.14712),合成数据的技术栈正在从手工设计走向自动化管线。
🔬 工业级参考:Poolside Hive 六组件编排架构(2026-07 公开)。合成数据工程的一个关键趋势是从”固定多阶段脚本”向”自适应编排框架”升级。Poolside 的 Hive 框架将数据生成流程分解为六个可组合组件:Seeds(原始输入)→ Metadata(任务类型/难度/语言等副指令)→ Generator(LLM Agent 加工具)→ Filters/Validators(正确性/去重/格式)→ Orchestrator(动态调度——根据质量门控实时决定”下一步执行哪个 Agent""是否注入新元数据""是否回退到上一步”)→ Supervisor(全局终止条件与部分结果聚合)。四种流水线形态对应不同成本-质量权衡:Rephrasing(单 Agent 低成本)、Multi-stage Aggregation(分解复杂任务为子步骤)、Cross-domain Porting(模态转换如数学→代码)、Multi-turn Evolution(Evolver+Judge 迭代)。Hive 的核心启示:Orchestrator 层的动态调度将合成数据生成从”确定性流水线”升级为”自适应智能工作流”——未来的数据工程平台可能不再是预设的管道配置,而是”元管道”——由数据工程师定义组件和规则,由 Orchestrator 动态组合执行路径。
第四代(2026 下半年):工具 Agent 合成范式(Tool-Use Synthesis)
第三代”推理优先”范式解决了推理密度问题,但 2026 年下半年的实战暴露出新需求:模型不仅要会”想”,还要会”用工具”。这推动了第四代工具 Agent 合成范式——直接以”工具调用”为数据单元合成。
| 第四代代表 | 规模 | 核心方法 | 效果 |
|---|---|---|---|
| TOUCAN | 1.5M 工具轨迹 / ~500 MCP 环境 | 从近 500 个真实 MCP 环境合成多轮工具调用轨迹(并行/多步/多轮/边缘案例) | BFCL v3 训练的开源模型超越闭源模型(SOTA) |
| ASTRA | 1,585 MCP / 19,036 工具 / 14B/32B 模型 | 工具调用图合成多轮结构化轨迹(SFT)+ QA 分解构造可验证 Python 环境(RL) | BFCL v3 / τ²-Bench / ACEBench 三基准 SOTA |
| MCP-Flow | 1,166 servers / 11,536 tools / 68,733 pairs | MCP 工具池 + 工具调用图结构化合成 | 大规模工具对数据集 |
| APIGen-MT | 多轮 agent 训练数据 | 多轮工具调用合成(Salesforce/XLang 团队) | 2026 多轮 agent 训练新范式 |
其方法论(MCP 工具池构建 → 工具调用图合成 → 可验证环境构造)及 ASTRA/TOUCAN 的工程创新细节,已在第一部分 30.4 作为 SFT 数据来源详述,此处不再重复。
与第三代的区别:
| 维度 | 第三代:推理优先 | 第四代:工具 Agent |
|---|---|---|
| 数据单元 | 推理链 + 答案 | 思考→工具调用→观察→再思考 |
| 验证方式 | 答案正确性 | 任务是否成功完成 + 工具调用正确性 |
| 训练目标 | 推理能力 | 工具协作 + 推理能力 |
| 典型数据集 | SynthLLM / Reasoning-first | TOUCAN / ASTRA / MCP-Flow / APIGen-MT |
🔮 判断:第四代工具 Agent 合成范式将在 2026-2027 年成为 Agent 训练的事实标准。从”模型能想”到”模型能用工具解决问题”是 Agent 产品化的最后一步。
30.14 多模态数据工程:下一个数据洪流
互联网上的文本数据在逼近天花板,但视觉数据、音频数据、视频数据的可用量还远未被充分挖掘。
多模态数据的规模估算:
| 模态 | 估算可用量 | 当前利用率 | 潜力 |
|---|---|---|---|
| 文本 | 10-15T tokens | ~80% | 低(接近饱和) |
| 图文对 | 100B+ 对 | ~20% | 高 |
| 视频 | 数十亿小时 | <5% | 极高 |
| 音频/播客 | 数十亿小时 | <5% | 极高 |
| 代码+执行轨迹 | 无限(可生成) | <10% | 极高 |
| 3D/空间数据 | 快速增长 | <1% | 极高 |
多模态数据工程面临的新挑战:
- 对齐问题:图片和文字的语义对齐、视频和旁白的时序对齐——高质量对齐数据本身就很稀缺
- 质量定义:多模态数据的”质量”比纯文本更难定义和度量
- 处理成本:视频数据的存储和处理成本比文本高 100-1000 倍,其中”时间维度”的处理(时序切分、关键帧、事件边界)是全新的工程问题
- 标注复杂度:多模态标注需要更复杂的标注协议和更专业的标注员
- 去重难度:跨模态的语义去重是尚未解决的问题
- 多模态 PII:人脸、声音、步态等生物特征信息比文本 PII 更难检测与脱敏
代表实践:
- GPT-4V:图文混合训练
- Gemini:原生多模态
- Qwen-VL:开源多模态
30.15 Agent 数据:从对话到行动
2025-2026 年,AI Agent 从概念走向产品。Agent 需要一种全新类型的训练数据——行动轨迹数据(Action Trajectory Data)。
传统对话数据:
User: "帮我查一下明天的天气"
Assistant: "明天北京多云,最高温度 25°C..."
Agent 轨迹数据:
User: "帮我查一下明天的天气,如果会下雨就帮我在日历上标注带伞"
[Thought] 需要先查天气,然后根据结果决定是否操作日历
[Action] call_api("weather", location="北京", date="tomorrow")
[Observation] {"condition": "rain", "temperature": "18°C", ...}
[Thought] 会下雨,需要在日历上添加提醒
[Action] call_api("calendar", action="add_event", ...)
[Observation] {"status": "success", "event_id": "..."}
[Response] 明天北京有雨,18°C。我已经在你的日历上标注了"带伞"提醒。
Agent 数据构造的核心挑战:
- 环境多样性:Agent 需要在各种环境中行动——网页、API、文件系统、数据库。每种环境需要不同的数据
- 错误恢复:好的 Agent 数据不仅包含成功轨迹,还要包含错误-恢复的轨迹
- 规划与反思:需要包含显式的思考过程(CoT),而不仅是 action 序列
- 安全边界:Agent 可以”真正”操作系统,因此安全约束的数据尤为重要
MCP 协议:Agent 数据采集的标准化基础设施:MCP(Model Context Protocol)已突破 9700 万安装量(2026-03),成为 Agent 工具调用的行业标准协议。MCP 工具调用记录天然具有结构化格式(工具名→参数→结果),是理想的 Agent 轨迹数据来源。通过 MCP Session 的完整消息历史,可以高效采集高质量的 Agent 交互数据。建议将 MCP 协议数据采集纳入 Agent 数据工程的标准管线。
前文(第一部分 30.4)已经展示了 TOUCAN、ASTRA、MCP-Flow、APIGen-MT 等数据集如何基于真实 MCP 环境与工具调用图合成大规模 Agent 训练数据——那是 Agent 数据”从哪来”的答案。这里更值得关注的是它”往哪去”:
Agent 数据的未来架构:
| 层次 | 数据类型 | 构造方法 |
|---|---|---|
| 基础能力层 | 工具调用格式数据 | 模板合成 + 人工验证 |
| 环境交互层 | 成功/失败轨迹 | 沙盒环境自动采集 |
| 规划推理层 | 多步骤推理链 | 强模型蒸馏 + RL |
| 自主执行层 | 目标设定与自主规划数据 | /goal 类命令的隐式规划链 |
| 安全约束层 | 安全边界案例 | 红队测试 + 规则生成 |
| 自我改进层 | 反思-修正轨迹 | 自我博弈 + 人工审核 |
⚠️ 范式转移:无环境 Agent 轨迹合成——ESAT(Apple, arXiv:2607.16900, 2026-07)。以上 Agent 数据构造路径都基于一个共同假设:必须先搭建真实环境(沙盒)才能生成数据。Apple 研究团队的 ESAT(Environment-Free Synthetic Agentic Trajectory)挑战了这一假设。其核心机制是让 LLM 扮演”双簧”:一个 LLM 模拟数字世界(返回逼真的系统响应),另一个 LLM 扮演 AI 助手执行任务——仅凭一份接口说明书即可自动生成完整的 Agent 操作轨迹。关键数据:ESAT-AW7 从 3 万候选任务中通过四层质量控制(参数完整性→模拟器重试→裁判评估→最终筛选)产出 9,352 条高质量轨迹;用 ESAT 数据训练的模型在 AppWorld 基准上普通任务 84.2% 成功率,挑战性任务 79%,混合真实数据后额外提升 4.1-15.3%。这种范式转化的意义:如果 ESAT 路线规模化,Agent 数据工程的重心将从”建环境”转移到”写接口说明书→合成流水线”——而接口说明书恰恰是正常软件开发的标准产出物。这意味着未来 Agent 数据的生产可能像软件开发一样可标准化、可流水线化、可自动化。
30.16 持续学习:从一次性项目到持续运转的数据系统
当前的大模型训练范式是”训练一次,部署很久”。但这带来一个根本问题——模型的知识会过时。
持续学习的数据挑战:
挑战 1: 知识更新 vs 遗忘
- 注入新知识时如何不破坏旧知识?
- 中训练的回放策略是初步方案,但不够优雅
挑战 2: 增量训练的数据策略
- 每周/每月有新数据到来
- 哪些旧数据需要保留?哪些可以丢弃?
- 新旧数据的配比如何动态调整?
挑战 3: 灾难性遗忘的长期管理
- 经过 10 次增量训练后,最初的能力还剩多少?
- 有没有"数据保鲜期"的概念?
挑战 4: 数据流的质量保证
- 持续到来的数据如何保持一致的质量标准?
- 自动化质量监控如何适应数据分布的漂移?
🔮 判断:未来的大模型数据工程不再是”一次性项目”,而将成为一个持续运转的数据系统——类似于搜索引擎的持续爬取和索引系统。数据工程师的角色将从”建设者”转变为”运营者”。
2026 持续学习三大数据工程案例:
| 案例 | 团队 | 范式 | 数据效率 | 关键创新 |
|---|---|---|---|---|
| RODS | 蚂蚁集团 + 浙大 + 上海创智学院 + 西湖大学(arXiv:2606.19047, 2026-06-17) | 奖励驱动在线数据合成 | 400 种子样本 ≈ 17K 离线样本(20-42× 数据效率) | 进度奖励方差作为零成本边界检测器 |
| AIDE | agentic in-context learning, 2026 | 在线学习范式 | 持续 in-context 适应 | 任务执行中即时学习新技能 |
| APIGen-MT | Salesforce/XLang 团队, 2026 | 多轮工具调用合成 | 大规模多轮轨迹 | 多轮 agent 训练新范式 |
RODS 的核心方法(深度展开):
- 动机:多轮工具 agent 训练数据成本极高;多轮数据前后依赖强,传统数据增强可能扩充出”看起来合理但实际全错”的假数据
- 方案:利用 GRPO 训练时的奖励信号在线合成新数据
- 边界检测:进度奖励方差 = 边界检测器(μ ≈ 0.5 时方差最大,源自 Popoviciu upper bound)
- 重采样合成:识别边界样本后,通过技能对齐的重采样管道合成结构复杂度(API 拓扑、依赖深度)匹配的新多轮变体
- 动态重放缓冲区:三层淘汰机制(预演过滤 / 边界漂移剔除 / 方差优先级剪枝)+ 分阶段注入避免分布偏移
- 结果:从 400 人类种子 + 约 800 活跃训练样本,达到与 17K 离线合成管道相当的性能(~20× 数据效率)
- 泛化:Qwen3-4B-Instruct 56.0% vs 静态 50.0% / EnvTuning 50.5%;在 BFCL v4、τ²-bench、ACEBench 等 OOD 任务上均提升
对持续学习的指导:
- 梯度饥饿问题:静态数据集训练中,大部分样本在后期对梯度贡献接近零(“被掌握”或”太难”)——RODS 用边界检测识别”对当前模型最具梯度的样本”
- 避免 hallucinated 反馈:重采样管道保留种子功能依赖结构(API 拓扑、依赖深度),避免无意义的实体替换
- 闭环数据引擎:训练过程与数据生成过程耦合,根据能力边界动态合成新数据
- 过滤器不能是被过滤对象自己(2026-10 补):用生成模型自己的判断去过滤它自己的产物,等于让被评估方出考题——用生成模型当裁判的过滤,是被生成模型悄悄满足的过滤。有约束力的闸门必须是外部可复核的:verifier、测试套件、held-out 检查、人工金标。
第 4 条不是新发现,而是同一条原则在三处的投影,值得一次点破:第二十九章 §29.4 的 reward hacking(策略骗过 verifier)、本章 §30.21”验证管道本身的可靠性”、以及这里的过滤器独立性——三者都是”裁判与被裁判者不能是同一个东西”。在自博弈 / 自生成闭环里这条尤其致命,因为反馈回路比预训练紧得多:模型既生成轨迹,也生成任务(自博弈时),中间没有任何外生锚点。RODS 用外部可复核结构(API 拓扑、依赖深度)做约束,正是这一条的正确实现。
🔬 显微镜观察:RODS 证明了在 Agent 训练中,“在何处合成数据”比”合成多少数据”更为关键——这是对数据工程”数量优先”传统假设的根本挑战。
30.17 自适应数据工程与数据飞轮
持续学习解决”数据何时来”,自适应数据工程解决”数据往哪去”。两者合起来,构成一个完整的数据飞轮:模型评估暴露薄弱能力 → 主动收集/合成针对性数据 → 注入训练 → 再评估。数据工程从”一次性配置”变成”持续优化”。
主动学习:让模型主动”要”它需要的数据
def active_learning_loop(model, unlabeled_pool, budget=1000):
for round in range(10):
# 1. 模型评估未标注数据
uncertainties = [model.uncertainty(x) for x in unlabeled_pool]
# 2. 选最不确定的样本标注
to_label = top_k(uncertainties, k=budget)
labeled = human_label(to_label)
# 3. 训练
model.finetune(labeled)
# 4. 评估
score = evaluate(model)
if score > target:
break
价值:减少 80% 标注成本,达到同样效果。
自适应数据工程:根据模型当前能力动态调整数据配方
def adaptive_data_engineering(model, data_pool):
while True:
# 1. 评估模型各能力维度
scores = {
'math': evaluate(model, 'MATH'),
'code': evaluate(model, 'HumanEval'),
'safety': evaluate(model, 'XSTest'),
...
}
# 2. 找最弱维度
weakest = min(scores, key=scores.get)
# 3. 动态调整配方,加强弱项
recipe = adjust_recipe(recipe, boost=weakest)
# 4. 训练 + 再评估
model.finetune(sample(data_pool, recipe))
趋势:从”静态配方”到”动态配方”,数据工程变成”持续优化”。
最优数据策略能否自动发现
这是最令人兴奋的开放问题。当前的数据策略(配比、过滤阈值、课程顺序)主要依靠人类经验和大量实验。有没有可能让模型自己发现最优的数据策略?
已有探索:
- DoReMi:用参考模型引导数据配比优化
- Data Mixing Laws:用小实验预测大模型最优配比
- AutoML for Data:将数据处理参数作为超参数搜索
- 在线配比调整:根据训练中的 loss 信号动态调整数据比例
arXiv 2603.14712 综述提出了一个引人注目的愿景:Agent-based Data Preparation Systems——用 AI Agent 自动完成数据准备的全流程,包括采集、清洗、过滤、配比。
未来的自动化数据工程系统(概念架构):
┌─────────────────────────────────────────┐
│ 数据策略 Agent │
│ ┌──────────┐ ┌──────────┐ │
│ │ 配比优化 │ │ 质量评估 │ │
│ │ Agent │ │ Agent │ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ ┌────▼──────────────▼─────┐ │
│ │ 数据处理管线 Agent │ │
│ │ ┌──────┐ ┌──────┐ │ │
│ │ │ 清洗 │ │ 过滤 │ │ │
│ │ └──────┘ └──────┘ │ │
│ │ ┌──────┐ ┌──────┐ │ │
│ │ │ 去重 │ │ 合成 │ │ │
│ │ └──────┘ └──────┘ │ │
│ └─────────────┬───────────┘ │
│ │ │
│ ┌─────────────▼───────────┐ │
│ │ 训练反馈回路 │ │
│ │ 模型能力评估 → 数据调整 │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────┘
这个愿景距离现实还有不小的差距,但方向是清晰的:数据工程的未来是自动化和智能化。RODS 的在线合成、Poolside Hive 的动态编排,都是这个飞轮上已经开始转动的齿。
30.18 数据法律与版权
趋势:数据合规从”事后审查”变成”前置约束”。
已生效的硬时间线(EU AI Act 通用人工智能模型条款):
| 时间 | 事项 | 依据 |
|---|---|---|
| 2025-08-02 | 通用 AI 模型提供者义务正式适用,含 Article 53(1)(d) 训练内容公开摘要(须使用 AI Office 提供的强制模版) | Article 113(b) |
| 2025-08-02 | 配套的《通用人工智能模型训练内容公开摘要模版》启用 | AI Office |
| 2026-08-02 | 欧盟委员会对 GPAI 提供者的监督与执法权启动(此前为一年调整期) | Article 88 / 89 |
| 2027-08-02 | 2025-08-02 前已投放市场的存量模型合规宽限期截止 | Article 111(3) |
2026 年立法变更:Digital Omnibus 推迟高风险义务,但没有动 GPAI
Regulation (EU) 2026/1744(“Omnibus on AI”,2026-07-08)改写了 AI Act 的适用时间表。修订后的 Article 113 把第三章第 1–3 节(高风险 AI 系统的分类规则、要求、提供者与部署者义务)的适用日整体后移:
| 义务范围 | 原定 | 修订后 |
|---|---|---|
| Annex III 独立高风险系统(Article 6(2) 口径:生物识别、关键基础设施、教育、就业、执法、边境管理等) | 2026-08-02 | 2027-12-02 |
| Annex I 嵌入式高风险系统(Article 6(1) 口径:医疗器械、机械、车辆等受部门安全法覆盖的产品中的 AI 安全部件) | 2026-08-02 | 2028-08-02 |
立法理由写在修订文本里:标准、通用规范、指南与成员国主管机关的到位进度跟不上原时间表,强行在 2026-08-02 适用会危及这些义务的实际落地,并带来不成比例的实施成本。
关键限定语:这次推迟不涉及 GPAI 义务,也不涉及委员会的执法权——上表三行不受影响。修订文本还把罚则与程序条款(Articles 102–110)的适用日明确提前到 2026-07-27。另外,Article 5 新增的 AI 生成 CSAM 与非自愿性明示图像禁令自 2026-12-02 适用。
同一天生效的另一端:Article 50 透明度义务
2026-08-02 起有两件事一并生效,且都落在”透明度”而非”高风险”轨道上:
- Article 50(1):与自然人直接交互的 AI 系统,须设计成让当事人知悉自己正在与 AI 交互。
- Article 50(2):生成合成图像、音频、视频或文本内容的 AI 系统(GPAI 系统包含在内),其输出必须以机器可读格式标记,且可被检测为人工生成或被操纵。提供者须确保其技术方案”有效、可互操作、稳健、可靠”,以技术上可行为限——条文要求一并考虑各类内容的特性与局限、实施成本,以及公认的技术水平。
宽限期只有一条:2026-08-02 之前已投放市场的生成式系统,须在 2026-12-02 前完成 Article 50(2) 合规(Article 111(4))。新建系统没有宽限。配套的《AI 生成内容透明度行为准则》属自愿性文件。
罚则:Article 99 分四档,不是一个数字——
| 违规类型 | 上限(金额与营业额取较高者) |
|---|---|
| 违反 Article 5 禁止性 AI 实践 | 3500 万欧元 或 全球年营业额 7% |
| 违反 Article 5 以外的其他义务(含 Article 50) | 1500 万欧元 或 3% |
| 向监管机构或公告机构提供错误、不完整或误导性信息 | 750 万欧元 或 1% |
| GPAI 提供者违反本法(Article 101) | 1500 万欧元 或 3% |
中小企业(含初创)适用”取较低者”的减免规则。要留意的是 3% 这一档并非 GPAI 独有——Article 50 的标记义务同样落在这一档,对数据团队来说这比 GPAI 那条更可能踩到。
对数据工程的直接含义:公开摘要模版把数据来源分成六类——公开数据集、第三方非公开数据集、网络爬取数据、用户数据、合成数据、其他。其中对数据工程约束最硬的两条是:
- 大型数据集须披露名称与链接:某一模态下、单个公开数据集的数据量占所有公开数据集该模态总量 3% 以上即属”大型”,需公开可识别特征/名称与链接。
- 网络爬取数据须披露域名清单:按数据量列出前 10% 的域名(中小企业为前 5%,且不超过 1000 个),并尽量覆盖所有模态的代表性数据。披露粒度是域名而非 URL,这是立法者对企业商业秘密的让步。
换句话说,“我们爬了网页”不再是可接受的合规答案——你需要能回答”爬了哪些域名、各占多少比例”。这恰好是第二部分溯源索引要解决的问题:如果 source 字段里只记了 type: "web" 而没有域名维度的聚合统计,到填模版时就得临时回扫全部原始数据。因此建议在溯源索引的设计阶段就预留按域名/按数据集的 token 量聚合视图,而不是等到合规审计时再补。
这个触发条件在 2026-10 已经变硬了。 上面 RFI 的 Track B 把三件事写进了正式索要范围:训练数据集的完整文档、DSM 第 4(3) 条选择退出的遵守情况、爬取数据的过滤技术架构。因此按域名/数据集的 token 聚合视图不再是”合规审计时的便利”,而是可能在很短时间内被正式要求提交的材料——而且不提交与提交得不完整适用同一档罚则。
顺带补一条容易被混为一谈的区分:“能回答爬了哪些域名、各占多少”与”能回答某条数据来自哪个域名”是两个不同的能力。前者只需要聚合视图(一个统计表就够),后者需要样本级溯源(见第十三章)。填模版、答 RFI 要的是前者;做删除权、做许可传染排查、做逐条去污染要的是后者。两者都要有,且聚合视图应能按模态拆分——模版要求覆盖各模态的代表性数据,只给一个文本侧的合计数是不够的。
⚠️ 执法强度的现实预期:欧盟 AI 办公室已明确表示不会对摘要做逐一评估(work-by-work assessment),也不会逐条比对训练数据;与权利人之间的具体纠纷鼓励走调解等替代性争议解决机制。这意味着模版合规的下限是”如实填写”,而非”经第三方核验”。把摘要当作对外沟通文档认真写,比把它当作法务免责文件应付了事更划算。
执法姿态尚未定型。 GPAI 行为准则是自愿性文件,签署方包括 Amazon、Anthropic、Google、IBM、Microsoft、Mistral AI、OpenAI、ServiceNow 等;据公开报道,Meta 未签署,xAI 只签了安全与安保章。负责监督的委员会 AI Office,其执法单元规模按公开报道在数十人量级——用这个体量去监督全球资本最密集的一批公司,是该法公信力被公开质疑的一点。截至 2026-09 尚无公开的首个执法行动或正式的提供者争议:法律机器已经就位,但从未被使用过。
⚠️ 上面划掉的那句是错的,而且在本章写下它的那一刻就已经是错的。 本段原写”截至 2026-09 尚无公开的首个执法行动……法律机器已经就位,但从未被使用过”。但欧委会在 2026-08-29 / 09-01 就已经公开确认首批执法动作,比本章 2026-09-23 写下这句话早了三周。更严重的是:本书第十三章(13.1.1)已经把这件事完整回源并写成一节,两章直接矛盾,而第十三章是回过源的那一条。
事实:2026-08-29 欧盟执行副主席 Henna Virkkunen 确认 AI Office 已向 GPAI 提供方发出正式信息请求;2026-09-01 欧委会发言人 Thomas Regnier 在午间吹风会确认:AI Office 已依 Art. 91 向 30 余家 AI 公司发出其历史上的第一批信息请求(RFI)——执法权(2026-08-02 生效)生效后不到一个月。分两条轨道:
- Track A 安全与安保:模型如何防御攻击、是否有独立外部评估、部署后如何监控;
- Track B 版权与透明度:训练数据的实际构成、EU 版权法合规(特别是权利人依 DSM 第 4(3) 条行使的 opt-out)、以及抓取过滤的技术架构。
Track B 的靶向性值得单独记:据报道这一条线发给了尚未公布训练内容摘要、且未参与 AI Office 非正式合规对话的提供方——“还没写训练摘要”本身已被用作筛选检查对象的依据。
罚则链条(对数据团队最要紧的一条):Art. 91(4) 要求每次 RFI 的文本必须载明 Art. 101 的罚则——提供不正确、不完整或误导性信息的,最高 1500 万欧元或全球年营业额 3%,二者取其高。而不回应 RFI 与实质性违规同罚。这意味着”我们还没准备好文档”本身就是风险敞口,不是”等被问了再说”。
合规触发不再只自上而下:举报人通道与下游提供方投诉渠道已上线,透明度缺陷可以由内部员工或下游客户触发。
原判断保留但降级:AI Office 已明确不会对训练摘要做逐条核验,所以”如实填写”仍然是合规下限——这一条没变。变的是现在真的会有人来问:分水岭不是”第一批案件”,而是已经开始的第一批信息请求。
本书式自我提醒:这正是本章自己写过的教训的又一次应验——“变更记录不可信""凡按今天的榜单 X=Y 必须重抓”,以及本轮跨章发现的这条:“尚无 / 还没有 / 零命中”是衰减最快的句式,且它会在同一本书的不同章节之间不同步腐烂。凡写这类状态断言,必须自带观察日期,并在下一轮按该日期复查;且跨章同一事实应指向同一条回源记录,而不是各写各的。
上面两条是输入端的要求(爬了什么、用了哪些数据集),Article 50 补上了输出端。 合成数据一旦进入生成式系统的输出链路,就带上机器可读标记义务。这不是法务话题,而是字段设计问题:管线能不能回答”这条内容是不是模型生成的”,以及能不能把这个标记一路带到下游系统的输出侧。
落到 schema 上,溯源索引需要第三个维度:
synthetic: bool——是否含模型生成内容;synthetic_level: enum——合成的程度(纯合成 / 模型重写 / 人工改写 / 人工原创);- 标记能否随数据导出——下游水印系统要消费的元数据放在哪里。
这与第十三章的溯源字段是同一套体系的两面:那套字段用来填 EU 的公开摘要模版(六类来源分类),这里要求它额外承担输出侧的标记义务。一个字段体系同时服务两项合规要求,这正是 source 不能只记 type: "web" 的原因。30.13 讲的合成数据代际(纯合成 → 模型重写 → 人工改写)可以直接映射成 synthetic_level 的枚举值,两处口径应当统一。
时间压力点在于:水印的 2026-12-02 是存量系统的宽限,新建系统没有宽限;而合成数据在训练 token 中的占比已经过半(见 30.12),意味着相当一部分新建管线从第一天起就在义务范围内。
关键问题:
- 网页数据的版权如何处理
- 合成数据的版权归属
- 用户数据的隐私边界
- 训练数据的”被遗忘权”
应对:
- 建立数据来源白名单
- 实现”数据撤回”机制
- 跟踪数据使用许可(CC-BY/CC0/Commercial)
- 定期合规审计
30.19 扩散语言模型:新范式的前夜
趋势:扩散解码作为自回归的替代范式进入工业探索。
Nemotron TwoTower(NVIDIA, 2026-07)证明:持有自回归检查点的实验室可以仅训练第二个去噪器网络实现扩散并行生成,仅需原数据预算的一小部分,推理吞吐提升 2.42x,质量保持 98.7%。这意味着数据工程可能迎来新的需求——扩散专用训练数据格式、噪声调度设计等。该方向仍处早期,但值得保持关注。
30.20 数据工程师的进化
从”数据清洗工”到”数据科学家”
大模型数据工程这个领域还很年轻——2020 年之前几乎不存在”专门做大模型数据”的岗位。它的演变大致如下:
2020: "数据清洗工"
└─ 会写 Python 脚本处理文本就行
└─ 主要工作:去重、过滤、格式化
2022: "数据工程师"
└─ 需要理解 NLP 基础知识
└─ 主要工作:建设完整的数据管线
2024: "数据科学家"
└─ 需要理解模型训练原理
└─ 主要工作:数据策略设计、配比优化、质量模型
2026: "数据架构师"
└─ 需要跨越数据和模型的完整认知
└─ 主要工作:端到端数据系统设计、数据-模型协同优化
2028+: "数据-模型协同工程师"(预测)
└─ 数据工程和模型训练不再分离
└─ 模型在训练过程中自主决定需要什么数据
└─ 工程师的角色是设计和维护这个自动化系统
T 型能力
工业级 AI 数据工程师需要 T 型能力:
横向(广度):
- 数据采集(爬虫/API/合成)
- 数据清洗(去重/过滤/脱敏)
- 数据评估(质量/多样性/污染)
- 数据配比(三轴配方/课程化)
- 数据闭环(归因/调整/再训练)
纵向(深度):
- 至少在一个领域(如数学/代码/多语言)深入
- 至少在一个阶段(如预训练/后训练)深入
工程能力清单
- Python 工程能力:能写生产级代码
- 分布式计算:Spark/Ray 实操经验
- 深度学习框架:PyTorch/HuggingFace 熟练
- 数据管道:Airflow/Prefect 经验
- 评测能力:能设计评测集、分析结果
- 业务理解:理解模型上线后的用户场景
数据直觉的培养
好的数据工程师有一种”数据直觉”——看一眼数据就能判断它对训练有没有价值。这种直觉不是天生的,而是通过大量实践培养的。
培养数据直觉的建议:
- 看数据:每个项目至少花 10 个小时亲自阅读原始数据。不是采样统计,而是逐条阅读。你会发现很多统计无法捕捉的问题。
- 做消融:每次修改管线后,都做一个小规模消融实验。不需要训练大模型——400M 参数的小模型在 5B tokens 上训练,就能反映大多数数据质量问题。
- 建基准:建立你自己的”数据质量直觉基准”——收集 100 条你认为是”好数据”和 100 条”坏数据”,用它来校准你的判断。
- 跨领域:不要只看文本数据。理解代码数据、数学数据、多模态数据的不同特征,可以让你对”质量”有更全面的认识。
- 读论文:系统阅读 FineWeb、DCLM、RedPajama、Dolma 等项目的技术报告。这些报告中有大量的数据工程经验和反直觉发现。
与模型训练团队的协作模式
数据工程师和训练工程师的协作模式也在演变:
传统模式(2020-2023):
数据团队 训练团队
│ │
│ "这是处理好的数据" │
│ ────────────────────────→ │
│ │ 训练...
│ │
│ "效果不好" │
│ ←──────────────────────── │
│ │
│ 调整管线... │
│ │
│ "新版数据" │
│ ────────────────────────→ │
│ │
反馈循环很慢,通常需要数周
现代模式(2024-2026):
数据团队 训练团队
│ │
│ ←── 共享评估 Dashboard ──→ │
│ │
│ 实时监控训练 loss 和指标 │
│ 发现异常后立即调查数据 │
│ │
│ 数据版本与 checkpoint 对应 │
│ 可以精确定位哪个数据版本 │
│ 导致了哪个能力变化 │
│ │
反馈循环缩短到天级甚至小时级
未来模式(2027+):
┌─────────── 自动化数据-训练循环 ───────────┐
│ │
│ 模型训练中 │
│ ↓ │
│ 在线评估发现薄弱能力 │
│ ↓ │
│ 自动调整数据配比 / 合成针对性数据 │
│ ↓ │
│ 数据注入训练流 │
│ ↓ │
│ 再评估... │
│ │
└────────────── 人工监督+干预 ──────────────┘
持续学习方向
- 论文追踪:每周读 1-2 篇数据相关论文
- 开源贡献:参与 datasketch、OpenRLHF 等项目
- 社区交流:HuggingFace Forums、paperswithcode
- 实战迭代:每季度做一次端到端数据工程实战
30.21 开放问题
我们还需要多少数据?
这是一个看似简单实际极深刻的问题。不同的回答反映了对智能本质的不同理解。
乐观派:数据需求有上限。当模型足够大、数据足够好时,模型可以从有限的数据中”涌现”出超越数据的能力。证据包括:
- 少量高质量合成数据可以训练出强大模型(Phi 系列)
- LIMA 表明 1000 条数据就能实现表面对齐
- DeepSeek-R1-Zero 仅用 RL 就能涌现推理能力
悲观派:数据需求会持续增长。模型本质上是数据的压缩表示,没有足够多样的数据就不可能获得足够多样的能力。证据包括:
- 更大的数据一致带来更好的效果(Scaling Laws)
- Model Collapse 表明合成数据不能替代真实数据
- 现实世界的长尾分布意味着永远有未覆盖的场景
本书的观点:数据的总量需求可能会趋于平缓,但数据的类型和质量需求会持续演化。未来的瓶颈不是”有多少数据”,而是”有多少正确类型的、高信息密度的数据”。2026 年的合成数据突破(60%+ 占比、< 2% 崩溃率)表明总量不是问题,但质量天花板、分布偏差和验证成本构成了新的约束三角。
合成数据能否完全替代真实数据?
基于 Nature 发表的 Model Collapse 研究和后续的大量实验,短期内的答案是否。
但 2026 年的现实让这个问题变得更微妙:合成数据占比已达 60%+,崩溃率 < 2%(该读数的采样配置前提见 30.12 的订正),“完全替代”在工程上已接近可行。关键不再是”能不能替代”,而是”替代的代价是什么”。
把”代价”说具体。 2026-10 的领域共识形态是两句,缺一不可:
- 完全崩溃在常规数据卫生下是可避免的——“替换一切”式的递归循环并不是真实语料的组装方式,保留真实数据基本上就拆掉了它;
- 但”未经过滤的合成数据导致长尾覆盖悄然流失”仍然是活的问题,而且更难测量。
第二句才是”替代的代价”真正的样子。它与 Dohmatob et al. 给出的那种较弱形态一致:即使保留了真实数据,合成污染仍会给”更多数据带来的收益”封顶。这正好落回本节开头那五条”真实数据提供了什么”——长尾分布、意外性、尚未被识别的”微量元素”——它们不会让准确率掉下来,所以按准确率监控看不到;它们只在分布类度量上先出现(30.12.1 已记:训练指标先于验证准确率发散)。因此这一章原本”能不能替代”的问法,正确的推进方向是“替代的代价长什么样、用什么度量才看得见”。
但这个问题的更深层含义值得思考:
如果合成数据不能完全替代真实数据,
那么"真实数据"中到底有什么是合成数据缺乏的?
可能的答案:
1. 信息的多样性——真实世界的长尾分布
2. 噪声的价值——适度的噪声帮助模型泛化
3. 文化和常识——隐含在自然文本中的社会知识
4. 创造性——人类创作的非规律性和意外性
5. 时效性——真实世界不断产生新的信息
如果我们能精确定义这些因素,
或许就能设计出不会导致 collapse 的合成方法。
一个有趣的类比:这就像营养学中的”合成维生素 vs 天然维生素”之争。合成维生素化学结构相同,但天然食物中还包含微量元素、纤维、酶等协同因素。训练数据也类似——真实文本中包含大量我们尚未识别但对模型有益的”微量元素”。
数据质量有没有统一的度量标准?
至今没有。这是数据工程领域最大的理论缺口之一。
当前的困境:
- “质量”是一个依赖于下游任务的概念——对预训练好的数据对 SFT 可能不好
- 不同的质量代理指标(PPL、教育价值分类器、LLM 评分)有各自的偏差
- 没有类似”BLEU for translation”或”FID for images”这样被广泛接受的数据质量度量
可能的方向:
- 基于信息论的度量:数据对模型参数的信息增益
- 基于学习曲线的度量:加入数据后的学习效率变化
- 多维度组合度量:流畅性 × 信息密度 × 多样性 × 安全性的加权组合
- 任务无关的内在质量度量:不依赖下游任务的数据本身质量分数
Nemotron-CC 商业级数据质量度量范式(NVIDIA 6.3T token, 2026)
Nemotron-CC 给出了工程可落地的”4 阶段蒸馏”质量度量框架:
| 阶段 | 度量 | 实现 |
|---|---|---|
| 领域分类 | 文档属于哪个 STEM 领域 | fastText 分类器 / Qwen 分类器 |
| 质量分类器集成 | 文档教育价值 / 噪声率 | 多分类器集成(FastText + KenLM + Qwen) |
| 去重 | 跨文档 / 跨数据集重复 | MinHash LSH + SemDeDup 语义去重 |
| 合成数据 | 蒸馏合成数据的质量 | 验证驱动合成 + ASI-Evolve 自主清洗 |
关键效果:
- 80 亿参数模型在 MMLU 提升 5 分、ARC-Challenge 提升 3.1 分
- 比 DCLM 在 MMLU 高 5.6 分(商业级 vs 学术级对比)
- ASI-Evolve(上海交大 GAIR-NLP, 2026-03):通过自主清洗使 MMLU 提升 18.64 个百分点(504B token Nemotron-CCASI+ vs 168B 低质原数据)
三维质量度量框架(基于 Nemotron-CC 实践经验):
- 领域覆盖度:数据集涵盖的 STEM / 通用 / 专业领域的分布
- 知识密度:每 token 的”知识”含量(教育价值、信息密度)
- 噪声率:低质量 / 重复 / 无关内容的比例
期待:未来 3-5 年内,社区需要建立一个像 ImageNet 对计算机视觉那样的数据质量 Benchmark——不是评估模型,而是评估数据的好坏。这将是数据工程从手艺走向科学的关键一步。
合成数据的分布偏差如何量化和校正?
合成数据已占新训练 token 的 60%+,但它的分布天然窄于真实数据——教师模型的偏好、验证函数的盲区、合成模板的局限性,都会导致系统性的分布偏差。
当前的困境:
- 没有标准化的分布偏差度量——不同维度(主题、风格、难度、文化)的偏差需要不同的度量方法
- 校正偏差可能引入新的偏差(上采样不足群体 → 重复增加 → 过拟合风险)
- “真实分布”本身也是未知的——互联网数据本身就有偏差,合成数据应该对标什么?
可能的方向:
- 参照基准法:用高质量人工标注数据集作为”真实分布”的代理
- 多教师集成:用多个不同的教师模型合成数据,降低单一模型的偏差
- 对抗检测:训练偏差检测器,自动发现合成数据的盲区
- 混合优化:将合成/真实比例作为优化变量,搜索最优混合策略
验证管道本身的可靠性和成本如何平衡?
第三代合成数据的”推理优先”范式依赖高质量的验证管道——但验证管道本身也是模型,也有出错的可能。当验证器的准确率为 95% 时,5% 的错误验证会导致什么后果?如果验证成本超过训练成本的 50%,是否还有经济可行性?
关键问题:
- 验证器的校准(calibration):验证器的置信度分数是否准确反映实际质量?
- 验证成本的可扩展性:随着数据量增长,验证成本是线性增长还是可以摊薄?
- 验证-训练的耦合:用同一模型验证自己生成的数据是否存在系统性偏差?
30.22 写在最后:数据工程的黄金时代
核心观点回顾
- 数据是上限:模型能力的天花板由数据决定,算法只是逼近天花板
- 质量 >> 数量:精选 1 万胜过粗制 10 万(Deita 实证)
- 闭环是关键:数据-训练-评估的闭环是工业级团队的分水岭
- 多样性是生命线:4-gram ≥ 0.6,InsTag ≥ 1000
- 可验证性优先:RLVR 的 0/1 奖励是后训练最锋利的工具
数据工程的”道”
技术会过时,工具会更新,但数据工程的”道”不变:
- 敬畏数据:每条数据都在塑造模型行为
- 闭环思维:没有评估的数据工程是盲修
- 多源对冲:单一来源必然偏置
- 持续迭代:数据工程是”养”出来的,不是”造”出来的
认知的演变
我们正处于大模型数据工程的黄金时代。这个领域足够年轻——核心方法论在过去 3-5 年内才逐步成型;又足够重要——“Data is all you need” 不是口号,而是现实。
回顾过去五年的发展脉络:
| 年份 | 核心认知 |
|---|---|
| 2020 | 数据越多越好 |
| 2021 | Chinchilla: 数据和参数要匹配 |
| 2022 | 质量比数量更重要 |
| 2023 | 合成数据可以弥补真实数据不足 |
| 2024 | 系统化的数据工程是可复现的科学 |
| 2025 | 数据工程进入精细化、多阶段时代 |
| 2026 | 数据系统走向自动化和持续化 |
每一年的认知都在演变,而且经常推翻之前的”共识”。这意味着——如果你在读这本书时发现某些观点已经过时了,那是一件好事,说明这个领域还在快速进步。
未来 3 年,后训练数据工程将出现三大变化:
- 从”造数据”到”养数据”:自适应数据工程成为主流
- 从”人工标注”到”合成 + 验证”:验证驱动的合成数据成为后训练主力
- 从”单模态”到”多模态”:图文音视频混合数据工程
给数据工程师的建议
如果你刚入行:
- 从动手做一个完整的小规模数据管线开始(比如处理 10GB 的 Common Crawl 数据)
- 训练一个 400M 的小模型来验证你的数据质量——这是最快的反馈循环
- 精读 FineWeb、DCLM 的技术报告——它们是最好的数据工程教材
如果你已有经验:
- 关注合成数据和 Agent 数据这两个快速演进的方向
- 建立你的数据质量直觉——这是很难被自动化替代的核心能力
- 思考如何让你的数据管线从”一次性项目”变成”持续运转的系统”
如果你是技术负责人:
- 数据工程的投入应占整个大模型项目的 30-50%——很多团队严重低估了这个比例
- 建立数据和训练团队之间的紧密反馈循环
- 投资数据基础设施——它的回报周期比你想象的短
推荐学习路径:
- 入门级:理解数据工程全貌;跑通 HuggingFace datasets + TRL 的 SFT 示例;用 Magpie 生成 10K 数据,训练一个小模型
- 进阶级:掌握后训练三大阶段;复现 Tulu-3 流程(SFT → DPO → RLVR);参与一个开源数据项目(如 OpenHermes)
- 专家级:掌握质量评估与闭环方法论;独立设计一个数据工程流水线;在 NeurIPS/ICML 等会议发表数据相关论文
最后的话
写书的过程中,作者反复感受到一件事:数据工程是一门手艺,更是一门科学。
说它是手艺,因为很多关键决策依赖于经验和直觉——某个过滤阈值设 0.5 还是 0.6,某两类数据的配比是 7:3 还是 8:2,这些看似微小的选择可能对最终模型有巨大影响。好的数据工程师就像好的厨师,配方重要,但火候和手感同样关键。
说它是科学,因为这个领域正在快速建立自己的理论基础——Scaling Laws、Data Mixing Laws、合成数据的信息论分析、遗忘的定量度量。这些理论让数据决策从”拍脑袋”逐渐走向”可推导”。
未来几年,数据工程将成为大模型技术栈中最值得投入的方向之一。不是因为模型架构不重要,而是因为架构的优化空间正在收窄,数据的优化空间却依然广阔。
在这个”数据决定一切”的时代,愿本书能帮你在数据的海洋中找到方向。数据工程是 AI 的”深水区”——愿本书成为你的潜水指南。
第四部分:附录资源
以下附录精选自《大模型数据工程》附录,作为全书收尾的速查资源:数据集一览、工具速查表、质量评估 Checklist、运行环境与推荐阅读。
附录 A:主要开源预训练数据集一览表
A.1 英文通用语料
| 数据集 | 规模 | 许可 | 发布时间 | 特点 |
|---|---|---|---|---|
| FineWeb | 15T tokens | ODC-BY | 2024.05 | HuggingFace 出品,源自 96 个 CC 快照,多级过滤 |
| FineWeb-Edu | 1.3T tokens | ODC-BY | 2024.05 | FineWeb 的教育价值子集,分类器过滤 |
| FineWeb-2 | 15T tokens | ODC-BY | 2025.02 | 多语言版 FineWeb,覆盖 1000+ 语言 |
| DCLM-Baseline | 3.8T tokens | CC-BY-4.0 | 2024.06 | DataComp-LM 竞赛基线,模型过滤 |
| RedPajama-V2 | 30T tokens | Apache-2.0 | 2023.10 | Together AI 出品,含质量信号 |
| Dolma | 3T tokens | AI2 ImpACT | 2024.01 | Allen AI OLMo 训练数据,完全可复现 |
| Dolma v1.7 | 4.3T tokens | AI2 ImpACT | 2024.10 | OLMo 2 训练数据,含 DCLM 过滤 |
| The Pile | 825 GB | MIT | 2020.12 | EleutherAI 经典数据集,22 个子集 |
| C4 | 305 GB | ODC-BY | 2019.10 | Google T5 训练数据,历史意义 |
| RefinedWeb | 5T tokens | ODC-BY | 2023.06 | Falcon 训练数据,CC 精细清洗 |
| SlimPajama | 627B tokens | Apache-2.0 | 2023.06 | RedPajama 去重精简版 |
| CulturaX | 6.3T tokens | CC-BY-4.0 | 2023.09 | 多语言清洗数据,167 语言 |
A.2 中文语料
| 数据集 | 规模 | 许可 | 特点 |
|---|---|---|---|
| WanJuan 1.0 | 600B tokens | Apache-2.0 | 智源出品,中英双语 |
| ChineseWebText 2.0 | 6TB | 研究用 | CC 中文子集,质量评分 |
| SkyPile | 150B tokens | Apache-2.0 | 天工 MiniMax 中文数据 |
| MNBVC | 数 TB | 多种 | 社区众包中文语料,覆盖广泛 |
| WuDaoCorpus | 200GB | 研究用 | 智源悟道中文语料 |
| CLUECorpus2020 | 100GB | Apache-2.0 | CLUE 中文语言理解评估语料 |
A.3 代码数据
| 数据集 | 规模 | 许可 | 特点 |
|---|---|---|---|
| The Stack v2 | 67.5 TB | 混合 | HuggingFace + SWH,619 语言 |
| StarCoder Data | 35B tokens | 混合 | StarCoder 系列训练数据 |
| CodeParrot | 180 GB | Apache-2.0 | GitHub Python 代码 |
| MBPP / HumanEval | 题库 | MIT | 代码评测基准(非训练用) |
A.4 数学数据
| 数据集 | 规模 | 许可 | 特点 |
|---|---|---|---|
| OpenWebMath | 14.7B tokens | ODC-BY | CC 中的数学内容,LaTeX 解析 |
| Proof-Pile-2 | 55B tokens | 混合 | 数学证明语料 |
| MathPile | 9.5B tokens | CC-BY-SA | 数学综合语料 |
| AutoMathText | 200 GB | Apache-2.0 | 自动标注的数学文本 |
A.5 学术论文
| 数据集 | 规模 | 许可 | 特点 |
|---|---|---|---|
| S2ORC | 81M 篇 | ODC-BY | Semantic Scholar 论文全文 |
| PeS2o | 40M 篇 | ODC-BY | S2ORC 精选子集,Dolma 使用 |
| arXiv bulk | ~2.5M 篇 | CC 混合 | arXiv 论文 LaTeX 源码 |
| PubMed | 36M 篇 | 公共领域 | 生物医学文献 |
附录 B:主要 SFT 与偏好数据集一览表
B.1 SFT 指令数据
| 数据集 | 规模 | 许可 | 特点 |
|---|---|---|---|
| OpenAssistant Conversations (OASST) | 161K 条 | Apache-2.0 | 人工标注多轮对话,35 语言 |
| ShareGPT | ~90K 条 | 非商用 | 用户分享的 GPT 对话 |
| Alpaca | 52K 条 | CC-BY-NC | 斯坦福,Self-Instruct 合成 |
| WizardLM-Evol | 250K 条 | 非商用 | Evol-Instruct 进化方法 |
| UltraChat | 1.5M 条 | MIT | 大规模多轮对话合成 |
| SlimOrca | 518K 条 | MIT | 去噪后的 OpenOrca 子集 |
| LIMA | 1K 条 | CC-BY-NC | 精选高质量样本 |
| Magpie | 1M+ 条 | Apache-2.0 | 从 Llama 3 自然生成 |
| Tulu Mix | 混合 | Apache-2.0 | Allen AI Tulu 系列训练数据 |
| Open-Hermes-2.5 | 1M 条 | Apache-2.0 | 多源混合 SFT 数据 |
B.2 偏好/对齐数据
| 数据集 | 规模 | 格式 | 特点 |
|---|---|---|---|
| UltraFeedback | 64K 条 | DPO pairs | GPT-4 评判生成的偏好数据 |
| HH-RLHF | 170K 条 | Chosen/Rejected | Anthropic 人工标注偏好 |
| OpenAssistant-2 | 91K 条 | Ranking | 人工排序偏好 |
| Nectar | 182K 条 | Ranking (1-7) | 多模型多维度排序 |
| Argilla DPO Mix | 混合 | DPO | 多数据集混合 DPO 格式 |
| PRM800K | 800K 步 | Step-level | OpenAI 过程奖励数据 |
| Math-Shepherd | - | Step-level | 自动步骤级标注 |
B.3 安全/红队数据
| 数据集 | 规模 | 用途 |
|---|---|---|
| SafeRLHF | 30K 条 | 安全偏好标注 |
| CValues | 145K 条 | 中文安全与价值观 |
| BeaverTails | 330K 条 | 安全分类标注 |
| HarmBench | 评测集 | 安全评测基准 |
附录 C:数据处理工具速查表
C.1 数据处理框架
| 工具 | 开发者 | 语言 | 特点 | 适用场景 |
|---|---|---|---|---|
| datatrove | HuggingFace | Python | FineWeb 同款,模块化管线 | 中大规模通用处理 |
| NeMo-Curator | NVIDIA | Python | GPU 加速,企业级 | 大规模高性能处理 |
| dolma | Allen AI | Rust+Python | OLMo 同款,高性能 | 大规模去重和过滤 |
| RedPajama toolkit | Together AI | Python | RedPajama 同款 | 中等规模处理 |
| text-dedup | ChenghaoMou | Python | 专注去重 | 去重任务 |
| CCNet | Meta | Python | CC 数据处理 | Common Crawl 处理 |
| DataFlow | 北大 OpenDCAI | Python | LLM 在环的合成+精炼,近 200 算子 / 六条领域管线 | 后训练 / 领域适配:PDF·纯文本·低质 QA → SFT/RL/RAG 监督数据(⚠️ 不做预训练级去重,勿与上行工具混用,见 ch28 §28.1) |
C.2 文本提取
| 工具 | 语言 | 速度 | 质量 | 推荐场景 |
|---|---|---|---|---|
| trafilatura | Python | 中 | 高 | 通用网页提取(首选) |
| Resiliparse | C++/Python | 快 | 中高 | 大规模处理 |
| jusText | Python | 中 | 中 | 段落级提取 |
| readability | JS/Python | 中 | 中高 | 文章类页面 |
| beautifulsoup | Python | 慢 | 可控 | 自定义提取规则 |
C.3 语言识别
| 工具 | 模型 | 语言数 | 速度 | 推荐 |
|---|---|---|---|---|
| fastText lid | lid.176.bin | 176 | 极快 | 首选 |
| CLD3 | Neural | 107 | 快 | 备选 |
| lingua | 统计+规则 | 75 | 中 | 短文本 |
| langdetect | 统计 | 55 | 快 | 轻量场景 |
C.4 质量评估
| 工具/方法 | 类型 | 速度 | 用途 |
|---|---|---|---|
| KenLM | PPL 过滤 | 极快 | 困惑度过滤 |
| fastText 分类器 | 二分类 | 极快 | 质量二分类 |
| FineWeb-Edu 分类器 | 回归 | 中 | 教育价值评分 |
| DAS(DataPrep-Bench) | 分布对齐(MMD) | 极快(零训练成本) | 候选数据集训练价值预判/排序;Math/Science/Medical 上 r>0.70,⚠️ 金融域失效(r 0.42–0.50),见 ch29 §29.5.1b |
| DCLM 过滤器 | LLM 打分 | 慢 | 高质量过滤 |
| GPT-4/Claude 评分 | LLM-as-Judge | 很慢 | 精细评估(采样) |
C.5 去重工具
| 工具 | 方法 | 规模适用 | 特点 |
|---|---|---|---|
| datasketch | MinHash+LSH | TB 级 | Python 库,灵活 |
| datatrove dedup | MinHash | PB 级 | 分布式,与 datatrove 集成 |
| text-dedup | MinHash/SimHash/Suffix | TB 级 | 多方法集成 |
| dolma dedup | Bloom filter + MinHash | PB 级 | Rust 实现,高性能 |
| Google deduplicate-text | Suffix array | TB 级 | 子串级精确去重 |
C.6 数据版本管理
| 工具 | 类型 | 特点 | 适用 |
|---|---|---|---|
| DVC | Git 扩展 | 类 Git 操作,简单 | 中小规模 |
| lakeFS | Git-like 对象存储 | S3 兼容,分支/合并 | 大规模 |
| Delta Lake | 表格式版本 | 事务性,时间旅行 | 结构化数据 |
| Hugging Face Hub | 托管平台 | 社区生态,易分享 | 开源数据集 |
| Manifest 文件 | 自定义 | 灵活,无依赖 | 任何场景 |
附录 D:数据质量评估 Checklist
D.1 预训练数据 Checklist
□ 数据来源
□ 数据来源是否明确记录?
□ 是否有适当的使用许可?
□ 是否遵守了 robots.txt 和 ToS?
□ 是否有数据溯源机制?
□ 文本提取
□ 提取器的选择是否经过对比测试?
□ 是否验证了提取质量(抽样检查)?
□ 非 HTML 格式(PDF、Word)是否正确处理?
□ 表格和列表是否合理保留?
□ 语言识别
□ 语言识别模型是否适合目标语言?
□ 置信度阈值是否经过调优?
□ 混合语言文本的处理策略是否合理?
□ 清洗与过滤
□ 过滤规则是否有文档记录?
□ 每条规则的过滤量是否统计?
□ 是否检查了过滤规则的误杀率?
□ 是否经过"过度过滤"测试?
□ 去重
□ 精确去重是否完成?
□ 模糊去重的阈值是否合理?
□ 去重的粒度(文档/段落/行)是否合适?
□ 是否做了跨数据源去重?
□ 质量评估
□ 是否使用了质量分类器?
□ 质量阈值的选择是否有消融实验支持?
□ 是否人工抽样检查了过滤后的数据?
□ 质量评分的分布是否合理?
□ PII 与安全
□ PII 检测覆盖了哪些类型?
□ PII 处理方式(替换/删除/掩码)是否合理?
□ 敏感内容过滤是否到位?
□ 是否有安全审计日志?
□ 数据配比
□ 各域数据的配比是否有实验依据?
□ 是否做了配比消融实验?
□ 语言配比是否符合目标?
□ 评估与验证
□ 是否做了 Benchmark 污染检测?
□ 是否有小模型代理验证?
□ 数据统计 dashboard 是否建立?
□ 版本管理
□ 数据是否有版本号?
□ 版本间的差异是否有记录?
□ 数据是否可以回溯到任意版本?
D.2 SFT 数据 Checklist
□ 数据构造
□ 种子数据是否经过精心设计和审核?
□ 合成方法是否有质量保证机制?
□ 是否使用了拒绝采样或类似方法?
□ 数据是否覆盖了所有目标能力?
□ 质量控制
□ 每条样本是否检查了格式正确性?
□ 代码样本是否可执行/可编译?
□ 数学样本的答案是否经过验证?
□ 事实性内容是否准确?
□ 是否做了重复检测?
□ 多样性
□ 任务类型分布是否合理?
□ 难度分布是否覆盖了各级别?
□ 长度分布是否避免了偏向?
□ 是否使用 embedding 做了多样性分析?
□ 一致性
□ 回复风格是否统一?
□ 多轮对话的上下文是否一致?
□ 安全策略是否一致?
□ 安全
□ 是否包含安全拒答样本?
□ 有害内容是否被过滤?
□ 是否做了红队测试?
D.3 RL/偏好数据 Checklist
□ 偏好数据
□ Chosen 和 Rejected 的质量差异是否真实?
□ Margin 分布是否合理?
□ 是否消除了长度偏好和格式偏好?
□ LLM-as-Judge 的偏差是否校正?
□ 可验证奖励数据
□ 数学题答案是否经过符号计算验证?
□ 代码题测试用例是否充分?
□ 难度分布是否在最佳学习区(20-50% solve rate)?
□ 是否做了 Benchmark 去污染?
□ 安全对齐
□ 安全相关的偏好标注是否准确?
□ 边界案例(helpful vs harmless 冲突)是否有清晰的处理策略?
□ 是否考虑了 Reward Hacking 的风险?
附录 E:运行环境、性能参考与推荐阅读
E.1 运行环境
# 推荐环境
Python >= 3.10
PyTorch >= 2.1 (如需 GPU 加速)
# 核心依赖
pip install \
trafilatura \ # 文本提取
fasttext \ # 语言识别与分类
datasketch \ # MinHash 去重
transformers \ # 模型推理
datasets \ # 数据加载
numpy pandas \ # 数据分析
scikit-learn \ # 聚类和分析
sympy \ # 数学验证
kenlm \ # 困惑度过滤
# 可选依赖
pip install \
datatrove \ # 数据处理框架
nemo-curator \ # NVIDIA 数据处理
dvc \ # 数据版本管理
E.2 数据处理性能参考
以下是各处理阶段在典型硬件上的性能参考值:
| 处理阶段 | 硬件 | 吞吐量 | 内存需求 |
|---|---|---|---|
| HTML 提取 (trafilatura) | 8 核 CPU | ~1,000 页/秒 | 4 GB |
| 语言识别 (fastText) | 8 核 CPU | ~50,000 文档/秒 | 2 GB |
| 启发式过滤 | 8 核 CPU | ~30,000 文档/秒 | 2 GB |
| MinHash 计算 (128 perm) | 8 核 CPU | ~5,000 文档/秒 | 依数据量 |
| MinHash LSH 查询 | 8 核 CPU | ~2,000 查询/秒 | 依索引量 |
| 质量分类器 (fastText) | 8 核 CPU | ~20,000 文档/秒 | 2 GB |
| 质量分类器 (BERT-based) | 1 × A100 | ~3,000 文档/秒 | 8 GB |
| LLM 评分 (7B) | 1 × A100 | ~100 文档/秒 | 40 GB |
| PII 检测 (正则) | 8 核 CPU | ~30,000 文档/秒 | 1 GB |
估算提示:处理 1TB 原始文本(约 5 亿个文档)的完整管线,使用 32 核 CPU 服务器约需 3-5 天。加入 GPU 质量分类器约需额外 1-2 天(取决于 GPU 数量)。
E.3 推荐阅读
核心论文:
- Penedo et al. “The FineWeb Datasets: Decanting the Web for the Finest Text Data at Scale” (2024)
- Li et al. “DataComp-LM: In Search of the Next Generation of Training Sets for Language Models” (2024)
- Soldaini et al. “Dolma: an Open Corpus of Three Trillion Tokens” (2024)
- Longpre et al. “A Pretrainer’s Guide to Training Data” (2023)
- Zhou et al. “LIMA: Less Is More for Alignment” (2023)
- Shumailov et al. “AI models collapse when trained on recursively generated data” (Nature, 2024)
- Liu et al. “Best Practices and Lessons Learned on Synthetic Data for Language Models” (2024)
- Ye et al. “Data Mixing Laws: Optimizing Data Mixtures by Predicting Language Modeling Performance” (2024)
- DeepSeek Team. “DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning” (2025)
- Wang et al. “Towards Next-Generation LLM Training: From the Data Perspective” (arXiv 2603.14712, 2026)
技术博客:
- HuggingFace FineWeb Blog: https://huggingface.co/spaces/HuggingFaceFW/blogpost-fineweb-v1
- Allen AI Dolma Blog: https://blog.allenai.org/dolma-3-trillion-tokens-open-llm-corpus
- Microsoft SynthLLM: https://www.microsoft.com/en-us/research/articles/synthllm/
- Together AI RedPajama: https://www.together.ai/blog/redpajama-data-v2
书籍(按推荐顺序):
- 本书
- Jurafsky & Martin, “Speech and Language Processing” (3rd ed., draft)
- Lilian Weng’s Blog 系列 (lilianweng.github.io) — 严格来说是博客,但质量堪比书籍