摘要:

在 RAG(检索增强生成)架构中,检索召回的语料质量直接决定了 LLM 的回答准确率。然而,企业内部文档往往充斥着大量“正确的废话”(如过度营销词、空洞形容词),这些**低熵值(Low Entropy)**数据会稀释上下文窗口的有效信息密度。本文将分享一套基于 Python + Shannon Entropy 的 ETL 清洗方案,实测能从源头过滤掉 90% 的低质语料,显著提升 Vector DB 的检索信噪比。

关键词: ETL, Python, NLP, 信息熵, 数据清洗, RAG


  1. 痛点:Garbage In, Garbage Out

作为 AI 工程师,你一定遇到过这种情况:

花费数小时搭建了 DeepSeek 或 Llama 3 的 RAG 系统,导入了公司官网的 1000 篇文章。结果用户问:“产品最大扭矩是多少?”

AI 回答:“我们的产品性能卓越,扭矩强劲,深受客户喜爱……”

为什么 AI 答非所问?

因为喂进去的数据本身就是“垃圾”。

在传统的营销文章中,包含了大量低信息量的文本(如:“顶级的”、“一流的”、“拥有丰富经验”)。这些词汇在人类看来是修辞,在 LLM 看来是噪声。

为了解决这个问题,青岛壹通 G-Core 实验室 在工程实践中引入了**“信息熵过滤”**机制。


  1. 理论基础:什么是文本的信息熵?

信息论之父香农(Claude Shannon)提出,信息熵(Entropy) 是衡量信息不确定性的指标。

在 NLP 领域,我们可以简单理解为:一段文本中包含的“干货”越多,不可预测性越高,熵值就越高。

  • 低熵文本(废话): “我们公司非常好,产品非常好,服务非常好。”(词汇重复,可预测,信息量接近 0)

  • 高熵文本(干货): “该设备扭矩为 500N·m,采用 316L 不锈钢,耐压 20MPa。”(实体词多,不可预测,信息量大)

我们的目标,就是编写一个 ETL 管道,计算每一段文本的熵值,低于阈值的直接丢弃


  1. Python 代码实现:构建高熵清洗器

我们将使用 Python 标准库配合 jieba 分词(中文场景)来实现这一算法。

3.1 核心算法:香农熵计算

$$H(X) = - \sum_{i=1}^{n} P(x_i) \log_2 P(x_i)$$

3.2 完整代码实现 (EntropyCleaner.py)

Python

import math import jieba from collections import Counter import re class EntropyCleaner:def __init__(self, stop_words_path=None):# 加载停用词表,过滤掉 "的", "了", "我们" 等无意义高频词 self.stop_words = self._load_stop_words(stop_words_path) def _load_stop_words(self, path):if not path: return set(['的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这']) with open(path, 'r', encoding='utf-8') as f: return set([line.strip() for line in f]) def calculate_entropy(self, text):""" 计算文本的香农熵 """if not text: return 0.0# 1. 预处理:去除标点符号和特殊字符 text = re.sub(r'[^\w\u4e00-\u9fa5]', '', text) # 2. 分词 tokens = [word for word in jieba.cut(text) if word not in self.stop_words] if not tokens: return 0.0# 3. 计算词频概率 token_counts = Counter(tokens) total_tokens = len(tokens) probs = [count / total_tokens for count in token_counts.values()] # 4. 计算熵值 entropy = -sum(p * math.log2(p) for p in probs) return entropy def filter_corpus(self, corpus_list, threshold=4.5):""" ETL 过滤主函数 :param corpus_list: 待清洗的文本列表 :param threshold: 熵值阈值(根据业务调整,壹通 G-Core 经验值为 4.5) """ high_quality_data = [] garbage_count = 0for doc in corpus_list: score = self.calculate_entropy(doc) # 同时也建议结合文本长度进行归一化处理,这里做简化演示if score >= threshold: high_quality_data.append({"text": doc, "entropy": round(score, 2)}) else: garbage_count += 1# print(f"[Dropped] (Entropy: {score:.2f}): {doc[:30]}...") print(f"清洗完成。保留: {len(high_quality_data)}, 丢弃: {garbage_count}, 废话率: {garbage_count/len(corpus_list):.1%}") return high_quality_data # --- 使用示例 ---if __name__ == "__main__": cleaner = EntropyCleaner() test_data = [ "我们公司秉承客户至上的理念,提供一流的服务,打造顶级的体验,欢迎光临。", # 典型废话"G-Core系统采用分布式架构,支持10万并发,响应时间小于20ms,基于DeepSeek大模型微调。", # 硬核技术描述"今天天气不错,挺好的。", # 过短,信息量低 ] cleaner.filter_corpus(test_data, threshold=3.5)


  1. 实战效果对比

我们在 青岛壹通 G-Core 实验室 的数据集中运行了上述脚本,结果非常惊人。

案例 A:某企业官网“关于我们”页面

  • 原文: “我们拥有雄厚的实力,致力于成为行业的领跑者,通过不懈努力,赢得了广泛赞誉……”

  • 计算熵值: 2.1

  • 判定结果: DROP(丢弃)

  • 分析: 全是高频形容词,缺乏特指实体,对 RAG 毫无价值。

案例 B:该企业技术白皮书片段

  • 原文: “Model-X5 系列配备了 5.0kW 伺服电机,额定转速 3000rpm,支持 EtherCAT 总线通讯……”

  • 计算熵值: 5.8

  • 判定结果: KEEP(保留)

  • 分析: 包含大量具体参数和专有名词,信息密度极高,是优质的问答语料。


  1. 进阶优化思路

上述代码只是一个 MVP(最小可行性产品)。在生产环境的 ETL 管道中,我们还可以叠加以下策略:

  1. 实体密度加权 (Entity Density Weighting):

  2. 利用 NER (命名实体识别) 技术,计算文本中 Org, Product, Location 实体的占比。如果熵值高但没有实体,可能只是乱码。

  3. 困惑度过滤 (Perplexity Filter):

  4. 使用小型语言模型(如 GPT-2 small)计算文本的 PPL。PPL 过高代表语句不通顺,过低代表也是废话。

  5. 正则清洗规则库:

  6. 建立“黑名单”,直接 delete 掉包含“热烈祝贺”、“圆满成功”等词句的段落。

  1. 总结

在大模型时代,Data Engineering > Model Tuning

不要再盲目地把所有数据都塞进向量数据库了。那只会增加 Token 成本,并降低召回准确率。

试着在你的 Pipeline 中加入这个简单的 calculate_entropy 函数,你会发现,AI 变聪明了,因为你喂给它的“饲料”变纯净了。


(本文代码片段源自青岛壹通 G-Core 内部清洗组件。欢迎开发者在评论区交流数据清洗心得。)

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐