RAG 中缺失的一步:为什么你的 Vector DB 膨胀(以及如何在本地修复)
Source: Dev.to
引言
我们花费了无数时间来优化 LLM 提示、微调检索参数(k‑NN),以及挑选最佳的嵌入模型。然而我们常常忽视了显而易见的问题:数据质量。
如果你正在使用内部公司数据——日志、工单、文档或邮件——构建 RAG(检索增强生成)流水线,你很可能已经遇到过 语义重复问题。
问题:不同的词语,却表达相同的含义
标准的去重工具(例如 pandas.DataFrame.drop_duplicates() 或 SQL DISTINCT)是基于字符串层面,只寻找完全相同的匹配。
示例日志条目
Error: Connection to database timed out after 3000ms.
DB Connection Failure: Timeout limit reached (3s).
对普通脚本来说,这两行是唯一的两条记录。
对 LLM(以及人类)来说,它们是相同的。
当你将 10,000 条此类记录导入向量数据库(Pinecone、Milvus、Weaviate)时:
- 💸 成本 – 存储冗余向量并非免费。
- 📉 检索质量 – 用户询问 “为什么数据库会失败?” 时会收到多个相同错误的变体,导致其他相关信息被淹没。
- 😵 模型幻觉 – 重复的上下文会降低输出质量。
解决方案:语义去重
去重必须基于 意义(向量),而不仅仅是语法(文本)。
我没有找到一个轻量、隐私优先、无需 Spark 集群或外部 API 调用的本地工具,于是我自己实现了一个:EntropyGuard。
EntropyGuard – 本地优先的 ETL 引擎
EntropyGuard 是一个用 Python 编写的开源 CLI 工具,负责在数据进入向量数据库之前进行清洗。它解决了三个关键问题:
- 语义去重 – 使用
sentence‑transformers和 FAISS 通过余弦相似度找出重复项。 - 数据清洗 – 去除 PII(电子邮件、电话号码)和 HTML 噪声。
- 隐私保护 – 完全在本地 CPU 上运行;不进行数据外泄。
技术栈(硬核技术)
| 组件 | 选型 | 理由 |
|---|---|---|
| 引擎 | Polars LazyFrame | 流式执行;在 16 GB 内存的笔记本上即可处理 10 GB CSV,而无需一次性加载全部数据。 |
| 向量检索 | FAISS(Facebook AI Similarity Search) | 超快的纯 CPU 向量比较。 |
| 分块 | 原生递归分块器(段落 → 句子) | 避免使用 LangChain 等重量框架导致的臃肿。 |
| 导入 | Excel(.xlsx)、Parquet、CSV、JSONL | 原生支持。 |
工作原理(代码实现)
安装
pip install "git+https://github.com/DamianSiuta/entropyguard.git"
运行审计(干运行)
entropyguard \
--input raw_data.jsonl \
--output clean_data.jsonl \
--dedup-threshold 0.85 \
--audit-log audit_report.json
干运行会生成一个 JSON 审计日志,准确展示哪些行会被删除以及原因——这对合规团队至关重要。
内部流程
- 嵌入 – 使用小模型(如
all-MiniLM-L6-v2)在本地生成嵌入。 - 聚类 – 使用 FAISS 对嵌入进行聚类。
- 去重 – 删除余弦相似度超过设定阈值(例如 0.85)的邻居。
基准测试:99.5 % 噪声削减
在一个包含 10,000 条记录的合成数据集(50 条唯一信号,伴随大量噪声:HTML 标签、改写、拼写错误)上进行压力测试,得到:
- 原始数据: 10,000 条记录
- 清洗后数据: 约 50 条记录
- 执行时间: (未指定)
我正在积极寻求数据工程社区的反馈。如果你在处理脏数据的 RAG 数据集时遇到困难,试试 EntropyGuard 并告诉我你的使用体验!