2.1 文本预处理基础


文档摘要

2.1 文本预处理基础 为什么预处理至关重要 在RAG系统中,"垃圾进,垃圾出"(Garbage In, Garbage Out)是一个永恒的法则。无论你的向量数据库多么强大、嵌入模型多么先进、LLM多么智能,如果输入的原始文本质量低劣,最终生成的回答也必然无法令人满意。文本预处理是RAG数据管线的第一步,也是最容易被忽视但影响最深远的一环。 文本预处理的目标是将原始、杂乱的文本数据转换为干净、标准化、适合下游处理(分块、向量化、检索)的高质量文本。这一过程虽然不像选择嵌入模型那样"炫技",但往往决定了RAG系统的整体效果上限。 文本清洗的核心步骤 编码规范化 处理来自不同来源的文本时,编码问题是最常见的隐患: 统一为UTF-8编码:确保所有文本使用UTF-8编码处理,避免乱码。

2.1 文本预处理基础

为什么预处理至关重要

在RAG系统中,"垃圾进,垃圾出"(Garbage In, Garbage Out)是一个永恒的法则。无论你的向量数据库多么强大、嵌入模型多么先进、LLM多么智能,如果输入的原始文本质量低劣,最终生成的回答也必然无法令人满意。文本预处理是RAG数据管线的第一步,也是最容易被忽视但影响最深远的一环。

文本预处理的目标是将原始、杂乱的文本数据转换为干净、标准化、适合下游处理(分块、向量化、检索)的高质量文本。这一过程虽然不像选择嵌入模型那样"炫技",但往往决定了RAG系统的整体效果上限。

文本清洗的核心步骤

编码规范化

处理来自不同来源的文本时,编码问题是最常见的隐患:

  • 统一为UTF-8编码:确保所有文本使用UTF-8编码处理,避免乱码。
  • 处理BOM头:UTF-8 BOM(Byte Order Mark)可能在某些系统中引起问题,需要检测并移除。
  • HTML实体解码:从网页抓取的文本常包含 &<  等实体,需要正确解码。
  • 全角/半角统一:中文环境下,英文数字和标点的全角与半角混用会影响检索一致性。
import html import re def normalize_encoding(text): # HTML实体解码 text = html.unescape(text) # 全角转半角(英文和数字) text = re.sub( r'[\uff01-\uff5e]', lambda m: chr(ord(m.group()) - 0xfee0), text ) return text

噪声去除

不同数据源会引入不同类型的噪声:

  • 网页噪声:导航栏、广告、侧边栏、页脚等无关内容;CSS/JavaScript代码片段;HTML标签残留。
  • PDF噪声:页眉页脚、水印文字、页码、目录重复;OCR识别错误(常见于扫描件)。
  • 文档噪声:修订标记、批注、目录链接、交叉引用标记。
  • 结构噪声:多余的空行、制表符混用、不规范的缩进。

噪声去除原则:宁可保守也不要过度清洗。过度清洗可能丢失有价值的上下文信息。建议使用基于规则和基于模型的混合方法——规则方法处理明确的噪声模式(如HTML标签),模型方法处理需要语义判断的情况(如判断某段文字是否为正文还是页脚)。

格式标准化

  • 空白字符处理:连续空格/换行合并为单个空格或换行;行首行尾空白去除。
  • 标点符号标准化:统一引号风格("" vs "")、统一省略号(... vs ⋯⋯)。
  • 列表标准化:将不同风格的列表标记(-*①②③)统一为标准格式。
  • 标题层级识别:通过正则匹配或ML模型识别Markdown标题、编号标题(一、二、三 / 1. 2. 3.)。

文本规范化技术

大小写处理

对于中文为主、英文为辅的场景,大小写处理需要区分对待:

  • 纯中文文本:不受大小写影响,无需处理。
  • 中英混合文本:英文专业术语统一为小写(如 RAGragAPIapi),但在生成阶段保留原始大小写。这一策略可以提升检索的鲁棒性。
  • 英文术语表维护:对于需要保留大小写语义的缩写(如 LLMBERTGPT),维护一个白名单,跳过规范化。

数字与日期标准化

  • 数字格式统一1,00010001.5k150050%0.5
  • 日期格式统一2024年1月15日 / Jan 15, 2024 / 2024-01-15 → 统一为 2024-01-15
  • 单位标准化KB / Kb / kb → 统一表示。

这些标准化处理看似琐碎,但对于RAG检索的一致性至关重要——用户搜索"1.5千"和"1500"应该能命中同一段内容。

停用词与高频噪声词

在RAG语境下,停用词处理需要谨慎:

  • 经典停用词(的、是、了、and、the、is):在分块阶段不应移除,因为它们影响文本的语义完整性。但在构建BM25关键词索引时可以过滤。
  • 文档特有噪声词:如每页都出现的页眉文字("机密文件")、模板固定文本("免责声明:本文内容仅供参考")。这些高频但低信息量的词应被识别并过滤。
def detect_template_noise(documents, threshold=0.8): """检测在超过threshold比例的文档中出现的短语,视为模板噪声""" from collections import Counter phrase_counter = Counter() for doc in documents: phrases = extract_ngrams(doc, n_range=(2, 5)) phrase_counter.update(set(phrases)) total = len(documents) noise = [p for p, c in phrase_counter.items() if c / total > threshold] return noise

语言识别与分流

在多语言文档集合中,预处理管线需要能够:

  1. 语言检测:识别每个文本块的语言(使用 langdetectfasttext 等库)。
  2. 分流处理:不同语言使用不同的预处理规则——中文不需要词干提取(stemming),英文需要。
  3. 跨语言对齐:如果存在同一文档的多语言版本,建立对应关系,支持跨语言检索。

质量评估指标

预处理完成后,需要量化评估清洗质量:

指标 计算方式 目标
字符有效率 有效字符数 / 总字符数 > 95%
编码错误率 含乱码的文档数 / 总文档数 < 1%
平均文档长度 预处理后平均字符数 符合业务预期
信息密度 非模板内容占比 > 80%
处理耗时 单文档平均处理时间 满足SLA要求

建议构建一个预处理质量仪表盘,定期监控上述指标,及时发现数据质量问题。

预处理管线架构设计

一个健壮的预处理管线应具备以下特性:

管道式处理

每个清洗步骤都是独立的处理单元,输入一个文档输出一个文档。步骤之间通过标准数据结构传递。

class PreprocessPipeline: def __init__(self): self.steps = [ EncodingNormalizer(), HtmlCleaner(), WhitespaceNormalizer(), TemplateNoiseRemover(), FormatStandardizer(), QualityChecker() ] def process(self, document): result = document for step in self.steps: result = step.process(result) if result.quality_score < 0.3: result.flag = "low_quality" break return result

幂等性

每个处理步骤都应是幂等的——对同一文档执行多次预处理,结果应保持一致。这保证了管线的可重试性。

可配置性

通过配置文件控制每个步骤的启用/禁用和参数调整,而非硬编码。不同数据源可以使用不同的配置:

pipeline: - name: encoding_normalizer enabled: true params: target_encoding: utf-8 - name: html_cleaner enabled: true params: strip_tags: true remove_scripts: true - name: template_noise_remover enabled: true params: threshold: 0.8 custom_patterns: - "免责声明.*" - "机密.*"

异常处理

对无法处理的文档不应导致管线崩溃,而是标记异常原因并跳过或降级处理。所有异常应有详细的日志记录,便于后续排查。

小结

文本预处理是RAG系统的地基工程。虽然不如嵌入模型和LLM那样引人注目,但它直接决定了整个系统的数据质量上限。核心要点包括:

  1. 编码规范化是一切处理的前提,必须首先解决。
  2. 噪声去除需要针对具体数据源定制策略,不可一概而论。
  3. 格式标准化提升检索一致性,细节决定成败。
  4. 管道式架构确保处理流程的可维护性和可扩展性。
  5. 质量监控是持续优化的基础,不能省略。

在下一节中,我们将讨论文档加载与解析技术,了解如何将各种格式的原始文档高效地转换为结构化的文本数据。


发布者: 作者: 挖出来的都是泥的小龙虾 转发
评论区 (0)
U