“数据不干净,AI 再聪明也白搭”——聊聊生成式 AI 的数据质量评估与去重那些坑


这两年生成式 AI 火得不行,大模型、RAG、Agent、Copilot,名字一个比一个响。
但说句可能不太讨喜的话:很多生成式 AI 项目,死得不是因为模型不行,而是数据太烂。

我见过不少团队,一上来就问:

要不要换个更大的模型?
要不要再多喂点数据?

但真正该先问的是:

你现在的数据,到底配不配得上生成式 AI?

今天这篇文章,咱不讲太虚的理论,就专门聊两个“脏活累活”,但决定成败的事情:

  • 数据质量评估
  • 数据去重(尤其是语义级去重)

一、先说个扎心的现实:生成式 AI 是“放大器”

生成式 AI 本质上是个概率放大器

  • 好数据 → 放大你的优势
  • 烂数据 → 放大你的缺陷

很多人以为模型会“自动学会甄别垃圾”,但现实是:
模型比你更老实,你喂什么,它就信什么。

举个真实到不能再真实的例子:

  • FAQ 文档里同一个问题,10 种说法
  • 历史工单里,答案前后自相矛盾
  • Wiki 文档三年没更新,但还在被喂给模型

结果就是:

模型回答得“看起来都对”,但每次都不一样

这不是模型“幻觉”,这是数据在打架


二、数据质量评估:别再只看“有没有数据”

很多团队做数据检查,停留在这个阶段:

  • 有没有空值
  • 行数够不够多
  • 字段齐不齐

说句不好听的:
这叫 ETL 检查,不叫生成式 AI 的数据质量评估。

1️⃣ 生成式 AI 更关心什么样的质量?

我一般从四个维度看:

✅ 可读性(Readable)
  • 是否是自然语言
  • 是否有大量乱码、日志、HTML 垃圾
✅ 一致性(Consistent)
  • 同一问题是否出现多种冲突答案
  • 同一术语是否多种叫法
✅ 信息密度(Information Density)
  • 是“废话文学”,还是“一句顶十句”
  • 有没有大量无意义客套话
✅ 时效性(Freshness)
  • 是否过期
  • 是否和当前业务状态匹配

2️⃣ 一个接地气的数据质量打分示例

下面这段代码不是为了“算法多高级”,而是为了让你敢给数据打分

import re

def quality_score(text: str) -> float:
    score = 1.0

    # 1. 过短内容直接扣分
    if len(text) < 30:
        score -= 0.3

    # 2. 垃圾符号过多
    noise_ratio = len(re.findall(r"[^\u4e00-\u9fa5a-zA-Z0-9,。!?]", text)) / max(len(text), 1)
    if noise_ratio > 0.2:
        score -= 0.3

    # 3. 口水话过多(非常粗暴但有效)
    filler_words = ["你好", "谢谢", "请问", "麻烦", "不好意思"]
    if sum(text.count(w) for w in filler_words) > 3:
        score -= 0.2

    return max(score, 0.0)

你会发现一个事实:
这玩意儿一点都不“AI”,但非常有用。

很多团队不是不会用模型,而是不敢给数据下结论


三、去重:不是删掉重复行这么简单

说到去重,很多人第一反应是:

select distinct *

我只能说:
这对生成式 AI 来说,基本等于没做。

1️⃣ 真正要命的是“语义重复”

举几个你肯定见过的例子:

  • “如何重置密码?”
  • “忘记密码怎么办?”
  • “账号密码找回流程”

从数据库角度看:
👉 完全不一样

从模型角度看:
👉 一模一样

你如果全喂进去,模型会学到什么?
同一个问题,有三种不同“措辞权重”。


2️⃣ 用 embedding 做语义去重(实战版)

别怕,我不整复杂的论文公式,就一个实用思路。

from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

def deduplicate_by_embedding(texts, embeddings, threshold=0.9):
    kept = []
    kept_embeddings = []

    for text, emb in zip(texts, embeddings):
        if not kept_embeddings:
            kept.append(text)
            kept_embeddings.append(emb)
            continue

        sims = cosine_similarity([emb], kept_embeddings)[0]
        if max(sims) < threshold:
            kept.append(text)
            kept_embeddings.append(emb)

    return kept

这段代码的精髓只有一句话:

不要问“像不像”,而是问“像到值不值得再留一条”。


四、一个我强烈推荐的组合拳流程

如果你问我:

真正在项目里,怎么把这事落地?

我一般推荐一个“土但稳”的流程:

🧩 Step 1:规则过滤

  • 明显垃圾
  • 超短文本
  • 日志、报错堆栈

🧩 Step 2:质量打分

  • 低于阈值直接淘汰
  • 中间区间人工抽样

🧩 Step 3:语义去重

  • embedding + cosine
  • 同问题只留一个“最干净”的版本

🧩 Step 4:抽样回看

  • 别全自动
  • 每周看 50 条,比你想象中值钱

五、一点个人感受:这是“反 KPI”的工作

说点掏心窝子的。

数据质量治理,是最不讨喜的生成式 AI 工作之一。

  • 不炫技
  • 不好汇报
  • 看不到立竿见影的效果

但你会发现一个神奇现象:

只要数据一干净,
Prompt 变简单了,
模型看起来“突然聪明了”。

这时候,很多人会以为:

是模型调得好

其实真相是:

数据终于不再互相扯后腿了。


六、写在最后

如果你只记住一句话,我希望是这句:

生成式 AI 的上限,不在模型参数量,而在你敢不敢删数据。

数据不嫌少,
垃圾才嫌多。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐