章节导航 第 20 章 / 共 20 章
工具栈、案例与未来展望
工具栈(预训练: trafilatura/fastText/FineWeb-Edu/datasketch/Presidio/SentencePiece/DoReMi; 后训练: Self-Instruct/Magpie/UltraFeedback/OpenRLHF/TRL/MT-Bench)、平台建设(Spark/Ray/SLURM分布式/数据管理平台/溯源索引)、典型案例拆解(Llama 3: 15T高质量数据/DoReMi配比; DeepSeek-V3: MoE训练数据工程/R1纯RL; Qwen: 多语言数据)、未来展望(合成数据规模化Phi/Nemotron/主动学习/自适应数据工程/多模态数据工程/数据法律版权)
工具是数据工程师的”手脚”。
从 trafilatura 到 OpenRLHF,工具栈的演进就是数据工程的进化史。
20.1 工具栈全景
20.1.1 预训练数据工具栈
| 工具 | 用途 | 章节 |
|---|---|---|
| trafilatura | 网页正文抽取 | 第 3 章 |
| resiliparse | 网页解析(备选) | 第 3 章 |
| fastText | 语言识别 | 第 4 章 |
| CCNet | 高级语言过滤 | 第 4 章 |
| FineWeb-Edu | 教育内容分类器 | 第 4 章 |
| KenLM | 困惑度过滤 | 第 4 章 |
| datasketch | MinHash 去重 | 第 5 章 |
| Presidio | PII 检测与脱敏 | 第 6 章 |
| SentencePiece | BPE/Unigram 分词 | 第 8 章 |
| tiktoken | OpenAI 风格分词 | 第 8 章 |
| DoReMi | 数据配比优化 | 第 7 章 |
| DataTrove | 分布式数据处理管线框架 | 第 5 章 |
20.1.2 后训练数据工具栈
| 工具 | 用途 | 章节 |
|---|---|---|
| Self-Instruct | 种子驱动合成 | 第 13 章 |
| Evol-Instruct | 进化合成 | 第 13 章 |
| Magpie | 零种子合成 | 第 13 章 |
| UltraFeedback | RLAIF 偏好数据 | 第 14 章 |
| OpenRLHF | RL/DPO 训练框架 | 第 15 章 |
| TRL | HuggingFace 后训练框架 | 第 14-15 章 |
| vLLM | 高效 rollout 推理 | 第 15 章 |
| MT-Bench | 多轮评测 | 第 18 章 |
| τ-Bench | Agent 评测 | 第 18 章 |
| BFCL | 工具调用评测 | 第 18 章 |
20.2 关键工具详解
20.2.1 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
20.2.2 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(百万级以上)
20.2.3 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 识别不如英文
- 需要自定义规则补充(如身份证、地址)
20.2.4 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。
20.2.5 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 实现规模化,降低新方法开发门槛。
20.2.6 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 倍。
20.3 平台建设
20.3.1 分布式计算
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
20.3.2 数据管理平台
工业级数据管理平台的核心功能:
- 数据湖存储:原始/清洗/训练版本分层
- 溯源索引:每条数据可追溯到来源
- 版本控制:DVC 风格的数据版本管理
- 质量监控:自动跑 IFD/多样性/污染检测
- 配方管理:可视化管理三轴配方
- A/B 对比:版本间对比评测
20.3.3 溯源索引
# 每条数据都有溯源元数据
{
"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 个微调数据集做了大规模法律+专家标注审计,结论是:
| 发现 | 数字 | 说明 |
|---|---|---|
| 许可未指定率 | >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)——这套卡片格式可以直接作为 20.3.3 溯源元数据的字段设计参考。
20.4 典型案例拆解
20.4.1 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 人全职团队)
20.4.2 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 的核心
20.4.3 Qwen:多语言数据
Qwen 系列:
- Qwen-2.5:18T tokens 预训练
- 多语言:29 种语言
- 数据工程亮点:
- 中文数据占比 30%(最大中文模型之一)
- 多语言均衡,避免英文主导
- 代码与数学加强
关键经验:
- 多语言数据要”按比例配”,不能英文主导
- 中文场景需要专门的清洗规则(如繁简转换、标点归一化)
20.4.4 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 精度下的数据工程(如量化感知训练的数据配方设计)成为新的研究课题。待技术报告充分公开后,其数据配比和合��数据策略值得深入拆解。
20.5 未来展望
20.5.1 合成数据规模化
趋势:合成数据占比从 30% → 70%+
⚠️ 这个”占比”数字在引用前必须先问清口径(2026-08-31 补充):
“合成数据占比”至少有四种互不等价的算法——按 token 数还是按样本数?只算后训练还是包含预训练?合成改写(真实文本经模型润色)算合成还是算真实?蒸馏自其他模型的输出算不算?
后训练阶段的合成占比本来就天然很高(Magpie 这类零种子合成几乎全是合成数据),因此”占比 70%+“如果统计的是后训练样本,含金量远低于它统计预训练 token 时的含金量。不同来源给出的预测数字差异,绝大多数来自口径差异,而非判断分歧。因此在引用任何具体百分比前,先确认它统计的是哪一层;跨来源直接比较这些数字是没有意义的。
代表:
- Microsoft Phi 系列:合成数据为主
- NVIDIA Nemotron:合成数据 + 真实数据混合
- Anthropic Claude:合成 Constitutional 数据
关键挑战:
- 合成数据的”模型偏置”如何消除
- 合成数据的”能力上限”如何突破
- 合成数据的法律风险(OpenAI ToS 禁止用 GPT 输出训练竞品)
20.5.2 主动学习
思想:让模型主动”要”它需要的数据。
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% 标注成本,达到同样效果。
20.5.3 自适应数据工程
思想:根据模型当前能力动态调整数据配方。
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))
趋势:从”静态配方”到”动态配方”,数据工程变成”持续优化”。
20.5.4 多模态数据工程
趋势:从纯文本到图文音视频混合。
新挑战:
- 多模态对齐数据稀缺
- 视频数据的”时间维度”处理
- 跨模态去重
- 多模态 PII(人脸、声音)
代表:
- GPT-4V:图文混合训练
- Gemini:原生多模态
- Qwen-VL:开源多模态
20.5.5 数据法律与版权
趋势:数据合规从”事后审查”变成”前置约束”。
已生效的硬时间线(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) |
罚则:最高为上一财年全球营业额的 3% 或 1500 万欧元,取较高者。
对数据工程的直接含义:公开摘要模版把数据来源分成六类——公开数据集、第三方非公开数据集、网络爬取数据、用户数据、合成数据、其他。其中对数据工程约束最硬的两条是:
- 大型数据集须披露名称与链接:某一模态下、单个公开数据集的数据量占所有公开数据集该模态总量 3% 以上即属”大型”,需公开可识别特征/名称与链接。
- 网络爬取数据须披露域名清单:按数据量列出前 10% 的域名(中小企业为前 5%,且不超过 1000 个),并尽量覆盖所有模态的代表性数据。披露粒度是域名而非 URL,这是立法者对企业商业秘密的让步。
换句话说,“我们爬了网页”不再是可接受的合规答案——你需要能回答”爬了哪些域名、各占多少比例”。这恰好是 20.3.3 溯源索引要解决的问题:如果 source 字段里只记了 type: "web" 而没有域名维度的聚合统计,到填模版时就得临时回扫全部原始数据。因此建议在溯源索引的设计阶段就预留按域名/按数据集的 token 量聚合视图,而不是等到合规审计时再补。
⚠️ 执法强度的现实预期:欧盟 AI 办公室已明确表示不会对摘要做逐一评估(work-by-work assessment),也不会逐条比对训练数据;与权利人之间的具体纠纷鼓励走调解等替代性争议解决机制。这意味着模版合规的下限是”如实填写”,而非”经第三方核验”。把摘要当作对外沟通文档认真写,比把它当作法务免责文件应付了事更划算。
关键问题:
- 网页数据的版权如何处理
- 合成数据的版权归属
- 用户数据的隐私边界
- 训练数据的”被遗忘权”
应对:
- 建立数据来源白名单
- 实现”数据撤回”机制
- 跟踪数据使用许可(CC-BY/CC0/Commercial)
- 定期合规审计
20.5.6 扩散语言模型
趋势:扩散解码作为自回归的替代范式进入工业探索。
Nemotron TwoTower(NVIDIA, 2026-07)证明:持有自回归检查点的实验室可以仅训练第二个去噪器网络实现扩散并行生成,仅需原数据预算的一小部分,推理吞吐提升 2.42x,质量保持 98.7%。这意味着数据工程可能迎来新的需求——扩散专用训练数据格式、噪声调度设计等。
20.5.7 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 化正在加速。
20.5.8 管线编排层与算子层的分工
前文 20.1.1 的工具栈表格列的是算子(分词器、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 + 参数快照”,否则 20.3.3 的溯源索引只能记到数据集粒度,记不到样本粒度。
- CPU 与 GPU 的边界:文本抽取、正则清洗这类逐字节操作放 GPU 上收益有限;MinHash 去重、嵌入排序、模型打标(分类器推理)才是 GPU 加速的主战场。盲目全栈 GPU 化往往只是把瓶颈从 CPU 挪到 PCIe 带宽。
- 失败是常态:上游源里混入的超长行、编码错误、空文件,在 TB 级数据上必然出现。编排层必须默认”每一步都会有一小部分数据失败”,并提供失败样本隔离而非整体中断的机制。
⚠️ 避免把「全栈 GPU 化」当目标:GPU 加速解决的是吞吐,不解决正确性。NeMo Curator 之类的加速只有在算子语义与 CPU 版本严格对齐时才有意义——去重阈值、分类器阈值在不同实现下的细微差异,会在 TB 级数据上放大成配方漂移。加速前应先固化 CPU 基线的产物指纹,作为加速版的对齐基准。
20.6 数据工程师的能力图谱
20.6.1 T 型能力
工业级 AI 数据工程师需要 T 型能力:
横向(广度):
- 数据采集(爬虫/API/合成)
- 数据清洗(去重/过滤/脱敏)
- 数据评估(质量/多样性/污染)
- 数据配比(三轴配方/课程化)
- 数据闭环(归因/调整/再训练)
纵向(深度):
- 至少在一个领域(如数学/代码/多语言)深入
- 至少在一个阶段(如预训练/后训练)深入
20.6.2 工程能力清单
- Python 工程能力:能写生产级代码
- 分布式计算:Spark/Ray 实操经验
- 深度学习框架:PyTorch/HuggingFace 熟练
- 数据管道:Airflow/Prefect 经验
- 评测能力:能设计评测集、分析结果
- 业务理解:理解模型上线后的用户场景
20.6.3 持续学习方向
- 论文追踪:每周读 1-2 篇数据相关论文
- 开源贡献:参与 datasketch、OpenRLHF 等项目
- 社区交流:HuggingFace Forums、paperswithcode
- 实战迭代:每季度做一次端到端数据工程实战
20.7 全书总结
20.7.1 核心观点回顾
- 数据是上限:模型能力的天花板由数据决定,算法只是逼近天花板
- 质量 >> 数量:精选 1 万胜过粗制 10 万(Deita 实证)
- 闭环是关键:数据-训练-评估的闭环是工业级团队的分水岭
- 多样性是生命线:4-gram ≥ 0.6,InsTag ≥ 1000
- 可验证性优先:RLVR 的 0/1 奖励是后训练最锋利的工具
20.7.2 数据工程的”道”
技术会过时,工具会更新,但数据工程的”道”不变:
- 敬畏数据:每条数据都在塑造模型行为
- 闭环思维:没有评估的数据工程是盲修
- 多源对冲:单一来源必然偏置
- 持续迭代:数据工程是”养”出来的,不是”造”出来的
20.7.3 后训练数据工程的未来
未来 3 年,后训练数据工程将出现三大变化:
- 从”造数据”到”养数据”:自适应数据工程成为主流
- 从”人工标注”到”合成 + 验证”:合成数据占比 70%+
- 从”单模态”到”多模态”:图文音视频混合数据工程
掌握本书的方法论,你就能在这个快速演进的领域中持续创造价值。
20.8 推荐学习路径
入门级
- 读完本书第 1-3 章,理解数据工程全貌
- 跑通 HuggingFace datasets + TRL 的 SFT 示例
- 用 Magpie 生成 10K 数据,训练一个小模型
进阶级
- 深入第 11-15 章,掌握后训练三大阶段
- 复现 Tulu-3 流程(SFT → DPO → RLVR)
- 参与一个开源数据项目(如 OpenHermes)
专家级
- 深入第 16-19 章,掌握质量评估与闭环
- 独立设计一个数据工程流水线
- 在 NeurIPS/ICML 等会议发表数据相关论文
数据工程是 AI 的”深水区”——愿本书成为你的潜水指南。
全书完