LLM 应用的效果很大程度上取决于输入数据的质量。无论是 RAG 检索增强、微调训练还是提示词工程,数据准备都是容易被低估但影响深远的环节。本文整理一份工程化的检查清单,帮助团队在项目早期建立规范。
数据清洗:去除噪声与冗余
原始数据往往包含大量对 LLM 无意义甚至有害的内容。清洗阶段需要关注:
格式噪声清理
HTML 标签、PDF 提取出的页眉页脚、OCR 产生的乱码字符、重复的空白行——这些都会占用 token 预算并干扰语义理解。建议使用专门的文档解析库(如 unstructured 或 pypdf)而非简单的字符串替换,它们能更好地保留文档结构。
去重与版本控制
同一份文档的多个版本、重复抓取的网页内容会导致检索结果偏向某些片段。可以用文档指纹(如 SHA-256 哈希)或模糊匹配(MinHash、SimHash)识别近似重复。假设一个企业知识库包含历史邮件归档,未去重可能让同一个通知的三个转发版本都进入检索候选集,浪费上下文窗口。
敏感信息脱敏
在将数据送入外部 API 前,必须检查是否包含个人身份信息、密钥、内部 IP 等。正则表达式可以覆盖常见模式(邮箱、电话),但复杂场景建议结合命名实体识别(NER)工具。
格式标准化:统一结构便于处理
不同来源的数据往往格式各异。标准化能让后续流程更稳定:
编码与换行符
统一使用 UTF-8 编码,将 Windows 风格的 \r\n 和 Mac 旧格式的 \r 都转为 \n。看似细节,但混用会导致分块边界计算错误。
元数据提取与保留
文档标题、作者、创建时间、章节层级这些元数据在检索时非常有用。解析时应将它们结构化存储,而不是丢弃或混入正文。例如 Markdown 的 ## 标题 应该被识别为 heading 而非普通段落,这样分块时可以按语义边界切分。
表格与代码块处理
表格如果直接转成纯文本会丢失列对齐关系,建议保留为 Markdown 表格或 JSON 格式。代码块需要保留语言标识符和缩进,否则 LLM 难以理解上下文。
分块策略:平衡语义完整性与检索粒度
分块(chunking)是 RAG 系统的核心环节,直接影响检索召回率和答案质量。
固定长度 vs 语义边界
按固定 token 数切分实现简单,但会把句子切断。更好的做法是按段落、章节或句子边界分块,确保每个 chunk 是语义完整的单元。对于技术文档,可以用标题层级作为主要分割点。
重叠窗口(overlap)
相邻 chunk 之间保留 10-20% 的重叠内容,避免关键信息恰好落在边界被切断。假设一个 500 token 的 chunk,可以让下一个 chunk 从第 400 个 token 开始,这样跨边界的句子会在两个 chunk 中都出现。
动态调整 chunk 大小
不同类型内容适合不同粒度:FAQ 问答对适合小 chunk(100-200 token),长篇技术文档适合大 chunk(500-1000 token)。可以根据文档类型元数据自动选择策略。
质量检查:建立可量化的验证指标
数据准备完成后,需要验证质量:
采样人工审查
随机抽取 50-100 个 chunk,检查是否有截断、乱码、格式错误。这是最直接的质量保障手段。
统计分布检查
绘制 chunk 长度分布直方图,异常的长尾(如某些 chunk 只有几个字)往往暗示清洗问题。计算平均 token 数、去重率、空 chunk 比例等指标,建立基线用于后续对比。
检索测试
准备 10-20 个典型问题,用预处理后的数据跑检索,看 top-k 结果是否包含预期文档。如果核心文档频繁漏检,说明分块或元数据提取有问题。
工程化建议
将上述流程封装成可复用的 pipeline:
- 用配置文件(YAML/JSON)管理清洗规则和分块参数,避免硬编码
- 记录每个处理步骤的输入输出样本,便于调试
- 对大规模数据集使用增量处理,只重新处理变更部分
- 版本化存储处理后的数据,支持 A/B 测试不同策略
数据准备看似繁琐,但投入的时间会在后续迭代中以更稳定的效果和更低的调试成本回报。如果你的团队在 LLM 应用开发中遇到数据工程挑战,欢迎联系 Taylent Labs 探讨定制化解决方案。