深入解析Dify中的文本清洗处理器:CleanProcessor详解
深入解析Dify中的文本清洗处理器:CleanProcessor详解
- 一、CleanProcessor概述
- 二、代码结构分析
- 三、核心功能详解
- 1. 基础清洗(默认清洗)
- 2. 规则化处理
- 2.1 移除多余空格(remove_extra_spaces)
- 2.2 移除URL和邮箱(remove_urls_emails)
- 四、处理流程分析
- 五、技术亮点
- 1. 正则表达式的巧妙应用
- 2. 闭包在正则替换中的应用
- 3. 配置驱动的处理逻辑
- 六、应用场景
在构建RAG(检索增强生成)系统时,文本预处理是一个至关重要的环节。今天我们来深入分析Dify项目中的CleanProcessor
类,这是一个专门用于文本清洗的处理器,它能够根据配置规则对文本进行预处理,为后续的向量化和检索做好准备。
一、CleanProcessor概述
CleanProcessor
类位于dify/api/core/rag/cleaner/clean_processor.py
文件中,是Dify项目RAG系统的核心组件之一。它主要负责根据预定义的规则对文本进行清洗和预处理。
二、代码结构分析
import reclass CleanProcessor:@classmethoddef clean(cls, text: str, process_rule: dict) -> str:# default clean# remove invalid symboltext = re.sub(r"<\|", "<", text)text = re.sub(r"\|>", ">", text)text = re.sub(r"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\xEF\xBF\xBE]", "", text)# Unicode U+FFFEtext = re.sub("\ufffe", "", text)rules = process_rule["rules"] if process_rule else {}if "pre_processing_rules" in rules:pre_processing_rules = rules["pre_processing_rules"]for pre_processing_rule in pre_processing_rules:if pre_processing_rule["id"] == "remove_extra_spaces" and pre_processing_rule["enabled"] is True:# Remove extra spacespattern = r"\n{3,}"text = re.sub(pattern, "\n\n", text)pattern = r"[\t\f\r\x20\u00a0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]{2,}"text = re.sub(pattern, " ", text)elif pre_processing_rule["id"] == "remove_urls_emails" and pre_processing_rule["enabled"] is True:# Remove emailpattern = r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"text = re.sub(pattern, "", text)# Remove URL but keep Markdown image URLs# First, temporarily replace Markdown image URLs with a placeholdermarkdown_image_pattern = r"!\[.*?\]\((https?://[^\s)]+)\)"placeholders: list[str] = []def replace_with_placeholder(match, placeholders=placeholders):url = match.group(1)placeholder = f"__MARKDOWN_IMAGE_URL_{len(placeholders)}__"placeholders.append(url)return f""text = re.sub(markdown_image_pattern, replace_with_placeholder, text)# Now remove all remaining URLsurl_pattern = r"https?://[^\s)]+"text = re.sub(url_pattern, "", text)# Finally, restore the Markdown image URLsfor i, url in enumerate(placeholders):text = text.replace(f"__MARKDOWN_IMAGE_URL_{i}__", url)return textdef filter_string(self, text):return text
三、核心功能详解
1. 基础清洗(默认清洗)
无论是否提供了处理规则,CleanProcessor
都会执行以下基础清洗操作:
# 移除特殊标记
text = re.sub(r"<\|", "<", text)
text = re.sub(r"\|>", ">", text)
# 移除控制字符和特殊Unicode字符
text = re.sub(r"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\xEF\xBF\xBE]", "", text)
# 移除Unicode U+FFFE字符
text = re.sub("\ufffe", "", text)
这些操作主要是为了:
- 移除可能干扰文本处理的特殊标记(如
<|
和|>
) - 清除不可见的控制字符(ASCII码0-31范围内的字符)
- 移除特殊的Unicode字符(如U+FFFE,这是一个非法的Unicode字符)
2. 规则化处理
CleanProcessor
支持根据配置的规则进行更复杂的文本处理。目前实现了两种预处理规则:
2.1 移除多余空格(remove_extra_spaces)
当启用此规则时,会执行以下操作:
# 将3个或更多连续的换行符替换为2个换行符
pattern = r"\n{3,}"
text = re.sub(pattern, "\n\n", text)
# 将2个或更多连续的空白字符(包括各种Unicode空白)替换为1个空格
pattern = r"[\t\f\r\x20\u00a0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]{2,}"
text = re.sub(pattern, " ", text)
这个规则的目的是:
- 规范化文本中的空行(最多保留一个空行)
- 将连续的空白字符(包括制表符、换页符、回车符和各种Unicode空白字符)替换为单个空格
2.2 移除URL和邮箱(remove_urls_emails)
当启用此规则时,会执行以下操作:
# 移除邮箱地址
pattern = r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"
text = re.sub(pattern, "", text)# 移除URL但保留Markdown图片URL
这个规则的处理逻辑比较复杂,特别是在处理URL时:
- 首先识别并保存Markdown格式的图片URL
- 然后移除所有其他URL
- 最后恢复之前保存的Markdown图片URL
这样做的目的是保留文档中的图片引用,同时移除其他可能不相关的URL链接。
四、处理流程分析
整个文本清洗的流程可以概括为:
- 输入:原始文本和处理规则配置
- 基础清洗:移除特殊标记和控制字符
- 规则处理:根据配置的规则进行特定处理
- 如果启用了
remove_extra_spaces
,则规范化空白字符 - 如果启用了
remove_urls_emails
,则移除邮箱和URL(保留Markdown图片URL)
- 如果启用了
- 输出:返回处理后的文本
五、技术亮点
1. 正则表达式的巧妙应用
CleanProcessor
大量使用了正则表达式来处理文本,这些正则表达式设计得非常精巧:
- 使用字符类
[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\xEF\xBF\xBE]
匹配各种控制字符 - 使用
[\t\f\r\x20\u00a0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]
匹配各种空白字符,包括Unicode空白 - 使用
([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)
匹配邮箱地址 - 使用
!\[.*?\]\((https?://[^\s)]+)\)
匹配Markdown格式的图片URL
2. 闭包在正则替换中的应用
在处理Markdown图片URL时,使用了一个内部函数和闭包来保存匹配到的URL:
def replace_with_placeholder(match, placeholders=placeholders):url = match.group(1)placeholder = f"__MARKDOWN_IMAGE_URL_{len(placeholders)}__"placeholders.append(url)return f""text = re.sub(markdown_image_pattern, replace_with_placeholder, text)
这种方式允许在正则替换的过程中收集和保存匹配到的信息,非常巧妙。
3. 配置驱动的处理逻辑
整个清洗过程是由配置驱动的,这使得系统非常灵活:
rules = process_rule["rules"] if process_rule else {}
if "pre_processing_rules" in rules:pre_processing_rules = rules["pre_processing_rules"]for pre_processing_rule in pre_processing_rules:if pre_processing_rule["id"] == "remove_extra_spaces" and pre_processing_rule["enabled"] is True:# 处理逻辑...
用户可以通过配置来启用或禁用特定的处理规则,而不需要修改代码。
六、应用场景
CleanProcessor
在Dify项目中主要用于以下场景:
- 数据集导入:在导入文档到数据集时,对文本进行预处理
- 文本分段前的清洗:在将文本分割成段落前,先进行清洗以提高分段质量
- 向量化前的标准化:在生成文本向量前,对文本进行标准化处理
完结!