- 人工智能
- 大模型
- 数据工程
- 数据清洗
- 数据增强
- 数据质检
【免费下载链接】data-juicer
Data processing for and with foundation models! 🍎 🍋 🌽 ➡️ ➡️🍸 🍹 🍷
本文围绕 Data-Juicer 的suffix_filter过滤算子展开,系统讲解它如何依据样本的__dj__suffix__后缀字段精准保留或剔除数据样本,覆盖参数配置、匹配逻辑、与加载/格式化模块的协作方式以及单元测试验证。读完本文,你将掌握 SuffixFilter 在文本(尤其是多来源混合语料)清洗流水线中的配置方法,并能通过源码理解其"无统计量过滤(NON_STATS)"的实现机制与反向过滤的扩展能力。
算子定位:按后缀字段做白名单过滤
suffix_filter是 Data-Juicer 提供的一种filter(过滤)类型算子,标签为cpu,运行在 CPU 上即可完成。它的职责非常聚焦:保留后缀与指定列表匹配的样本,其余样本一律过滤掉。
从 源码注册信息 可以看到,该算子同时注册进了两个注册表:
OP_NAME = "suffix_filter" @NON_STATS_FILTERS.register_module(OP_NAME) @OPERATORS.register_module(OP_NAME) class SuffixFilter(Filter):其中NON_STATS_FILTERS注册表定义于 data_juicer/ops/base_op.py,含义是"无统计量过滤算子"——这类算子不需要在统计阶段预先计算数值型指标(如词数、长度、困惑度),而是直接基于样本已有字段做布尔判断,因此计算开销极小、执行路径更短。
判断依据:__dj__suffix__字段
SuffixFilter 并不读取文本内容本身,而是检查每个样本的suffix 字段,该字段在 data_juicer/utils/constant.py 中统一定义:
suffix = DEFAULT_PREFIX + "suffix__" # 即 "__dj__suffix__"这个字段一般记录样本来源文件的扩展名(如.txt、.pdf、.docx、.py、.html等),由加载/格式化阶段自动填充(详见后文"字段从哪来"一节)。SuffixFilter 的做法就是对sample[Fields.suffix]做一次集合成员判断:
res_bool = sample[Fields.suffix] in self.suffixes匹配则保留,不匹配则过滤;若未配置任何后缀,则全部保留。
参数配置详解
官方文档给出的参数表如下:
| name 参数名 | type 类型 | default 默认值 | desc 说明 |
|---|---|---|---|
suffixes | typing.Union[str, typing.List[str]] | [] | the suffix of text that will be keep. For example: '.txt', 'txt' or ['txt', '.pdf', 'docx'] |
args | '' | extra args | |
kwargs | '' | extra args |
结合 初始化实现,各参数的实际行为如下:
suffixes:允许的后缀白名单。三种取值形态都会被归一化处理:- 传入
None:归一化为空列表[],等价于不过滤,全部样本保留; - 传入单个字符串(如
'.txt'、'txt'):自动包装成单元素列表['.txt']; - 传入字符串列表(如
['txt', '.pdf', 'docx']):直接使用。 - 注意匹配是精确的字符串相等判断,不是子串/通配符匹配,因此
.txt与txt属于两个不同的值,配置时需与样本__dj__suffix__字段的实际取值保持一致。
- 传入
args/kwargs:透传给父类Filter的额外参数,用于承载 Data-Juicer 过滤算子的公共参数。
继承自基类 Filter 的公共参数
SuffixFilter 继承自 data_juicer/ops/base_op.py 中的Filter基类,因此还隐式支持以下公共参数(通过kwargs传入),其中reversed_range对 SuffixFilter 有直接影响:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
reversed_range | bool | False | 是否反转过滤区间/逻辑。为True时,SuffixFilter 会反向过滤:保留"后缀不匹配白名单"的样本,剔除匹配的样本 |
min_closed_interval | bool | True | 区间下界是否闭区间(对数值型过滤算子生效,SuffixFilter 不使用) |
max_closed_interval | bool | True | 区间上界是否闭区间(同上) |
stats_export_path | str/None | None | 统计量导出路径(SuffixFilter 不产出统计量,一般不配置) |
text_key/image_key等 | str | 见具体算子 | 指定待处理字段的 key(文本类算子常用) |
其中reversed_range在process_single中生效的逻辑为(源码 L41-L48):
def process_single(self, sample): if self.suffixes: res_bool = sample[Fields.suffix] in self.suffixes if self.reversed_range: res_bool = not res_bool return res_bool else: return True底层实现原理:无统计量的两阶段框架
Data-Juicer 的过滤算子统一遵循"统计(compute_stats)→ 过滤(process)"两阶段执行框架,基类 Filter.process 会对数据集整体执行map(compute_stats)+filter(process)。SuffixFilter 对这一框架做了最简化的实现:
- 统计阶段为空操作:
compute_stats_single直接原样返回sample(源码 L38-L39)。因为判断所需的__dj__suffix__字段在样本中已存在,无需额外计算中间统计量,这正是它被注册为NON_STATS_FILTERS的原因——不占用统计缓存、不需要stats字段,运行更轻量。 - 过滤阶段做布尔判断:
process_single返回一个布尔值,True保留、False剔除,并在reversed_range=True时取反(见上节代码)。
由于process与compute_stats在基类中被标记为不可被子类覆盖(base_op.py L851-L861),子类只能实现process_single/compute_stats_single或对应的_batched版本,这保证了框架执行路径的一致性;SuffixFilter 本身也未声明 batched 版本,默认走单样本逐条处理路径。
效果演示:两种典型场景
以下效果演示直接取自官方文档 docs/operators/filter/suffix_filter.md,并补充了对应单元测试的验证结果。
场景一:指定后缀白名单
算子配置:
SuffixFilter(suffixes=['.txt', '.pdf'])输入数据(5 条样本):
| # | text 文本 | __dj__suffix__ |
|---|---|---|
| Sample 1 | Today is Sun | .pdf |
| Sample 2 | a v s e c s f e f g a a a | .docx |
| Sample 3 | 中文也是一个字算一个长度 | .txt |
| Sample 4 | ,。、„”“«»1」「《》´∶:?! | .html |
| Sample 5 | dasdasdasdasdasdasdasd | .py |
输出数据(仅 2 条样本被保留):
| # | text 文本 | __dj__suffix__ |
|---|---|---|
| Sample 1 | Today is Sun | .pdf |
| Sample 3 | 中文也是一个字算一个长度 | .txt |
解释:白名单为['.txt', '.pdf'],因此后缀为.pdf与.txt的样本被保留,后缀为.docx、.html、.py的样本被过滤。该用例与单元测试 tests/ops/filter/test_suffix_filter.py 中的test_case完全一致:测试通过dataset.map(op.compute_stats)与dataset.filter(op.process)两段调用复现了与文档完全相同的输入输出。
场景二:不指定后缀(默认行为)
算子配置:
SuffixFilter()输入数据:与场景一相同的 5 条样本(.pdf、.docx、.txt、.html、.py)。
输出数据:与输入数据完全相同——由于没有提供任何后缀,所有样本都被保留,不发生过滤。
解释:这是理解算子默认行为的典型边缘情况。当suffixes为空(默认[],或显式传None)时,process_single直接返回True,等价于一个"恒真"的旁路过滤器,不会误伤任何样本。单元测试中的test_none_case(test_suffix_filter.py L47-L83)与test_none_suffixes(L97-L105)分别验证了不传参数与显式传None两种情形下全部样本保留的行为。
扩展用法:字符串形态与反向过滤
除官方文档演示的两类场景外,单元测试 还覆盖了以下两种值得注意的用法:
1. 传入单个字符串(test_string_suffix,L86-L95):
SuffixFilter(suffixes='.txt')构造器会把字符串自动包装为['.txt'],效果与传入单元素列表一致:只保留后缀为.txt的样本。适合在 YAML 配置中直接写suffixes: '.txt'的简洁用法。
2. 反向过滤(test_reversed_range,L107-L116):
SuffixFilter(suffixes=['.txt'], reversed_range=True)reversed_range=True会取反判断结果,即"保留后缀不在白名单中的样本"。在上面的例子中,输入为['.txt', '.py']两条样本,输出仅保留.py样本。这为"排除某类来源文件"的清洗需求提供了便捷手段,例如"剔除所有.html来源样本"可以写作SuffixFilter(suffixes=['.html'], reversed_range=True)。
实战:在 Data-Juicer 配置中使用 SuffixFilter
按 Data-Juicer 的通用配置约定,过滤算子在 YAML 的process(或filter)列表中按算子名: {参数}的格式声明。一个混合语料"只保留 txt/pdf/docx 来源文本"的配置片段示例:
process: - suffix_filter: suffixes: ['.txt', '.pdf', 'docx'] # 也可写作单个字符串,如 '.txt'若希望做排除式过滤(如丢弃所有来自 html 网页抓取的样本),可加上reversed_range:
process: - suffix_filter: suffixes: ['.html'] reversed_range: true需要注意的前提是:数据集中必须存在__dj__suffix__字段,否则process_single中的sample[Fields.suffix]会因 KeyError 报错。完整算子列表与配置入口可参考 docs/Operators.md。
溯源:__dj__suffix__字段从哪来
SuffixFilter 的正确运行依赖后缀字段被正确填充,仓库中有两条主要来源路径:
- 格式化阶段自动补充:在 data_juicer/format/formatter.py 的
add_suffixes函数中,Data-Juicer 会遍历数据集,为缺少Fields.suffix特征的数据集补上一列,初始值取数据集来源 key 对应的扩展名("." + key)。这意味着按来源文件分别加载(如text/txt、text/pdf等不同 key 的语料)时,每个样本会自动带上与来源匹配的后缀,为后续按来源过滤提供基础。 - 宽松 jsonl 加载器:在 data_juicer/utils/jsonl_lenient_loader.py 中,开启
add_suffix_column选项后,每行解析出的样本会被写入row[Fields.suffix],后缀值取自文件路径。
因此,一个典型的落地链路是:加载时自动生成后缀字段 → SuffixFilter 按白名单过滤 → 输出纯净的指定来源语料。这种"来源感知"的过滤能力,特别适合多来源混合语料(如网页抓取、PDF 扫描件、代码仓库、论文语料混排)的定向清洗场景。
小结
suffix_filter是无统计量的 CPU 过滤算子,依据__dj__suffix__字段做精确后缀白名单匹配;suffixes支持字符串、字符串列表与None三种形态,空列表/None表示不过滤;- 借助基类参数
reversed_range可实现反向过滤(剔除指定后缀); - 源码实现位于 data_juicer/ops/filter/suffix_filter.py,官方文档位于 docs/operators/filter/suffix_filter.md,单元测试位于 tests/ops/filter/test_suffix_filter.py,可直接作为行为契约与使用范例参考。
- 人工智能
- 大模型
- 数据工程
- 数据清洗
- 数据增强
- 数据质检
【免费下载链接】data-juicer
Data processing for and with foundation models! 🍎 🍋 🌽 ➡️ ➡️🍸 🍹 🍷
相关推荐
Data-Juicer 视频时长过滤算子(video_duration_filter)深度解析:参数配置、实现原理与实战用法
Data Juicer 视频时长过滤算子(video_duration_filter)深度解析:参数配置、实现原理与实战用法 视频时长是视频数据质量清洗中最基础
人工智能大模型数据工程数据清洗数据增强数据质检Data-Juicer 视频分辨率过滤算子 video_resolution_filter 完全指南:参数、原理与实战
Data Juicer 视频分辨率过滤算子 video_resolution_filter 完全指南:参数、原理与实战 导读 video_resolution_
人工智能大模型数据工程数据清洗数据增强数据质检data-juicer 文档级 MinHash LSH 去重算子实战:document_minhash_deduplicator 原理、参数与效果详解
data juicer 文档级 MinHash LSH 去重算子实战:document_minhash_deduplicator 原理、参数与效果详解 大模型训
人工智能大模型数据工程数据清洗数据增强数据质检
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考