AI回答采集数据清洗:Python实现空回答、拒绝与无关样本识别

问题:采集的AI回答JSON数据中混有空回答、拒绝回答、无关内容及重复样本,如何自动识别并清洗?环境:Python 3.9.7 + pandas 1.3.3,Ubuntu 20.04。读者:AI数据工程师。本文提供可复用的校验函数和验证示例,不涉及多轮对话场景。

环境说明

  • 操作系统:Ubuntu 20.04 LTS

  • Python版本:3.9.7

  • 依赖安装:

    bash 复制代码
    pip install pandas==1.3.3
  • 输入格式:每行一个JSON对象的文本文件,字段包括 query, response, timestamp, model。示例:

    json 复制代码
    {"query": "什么是AI", "response": "人工智能是...", "timestamp": "2025-01-01", "model": "gpt-4"}

校验流程

采集数据中常见的无效样本包括空回答、拒绝回答、无关内容以及重复记录。下面分别处理,最后整合为一个函数。

1. 无效样本识别

无效样本分三类:

  • 空回答response 字段为空或仅含空白字符。
  • 拒绝回答:回答以"抱歉"、"对不起"、"无法回答"等开头,或包含"作为AI"、"我无法"等模式。
  • 无关内容:回答与查询在语义上不相关。这里使用基于词重叠的简单规则,实际项目中可替换为嵌入向量相似度。
python 复制代码
import re

def is_empty_response(response: str) -> bool:
    return not response or response.strip() == ""

def is_refusal_response(response: str) -> bool:
    refusal_patterns = [
        r"^抱歉", r"^对不起", r"^无法回答",
        r"作为AI", r"我无法", r"我不能",
        r"这个问题我无法"
    ]
    for pattern in refusal_patterns:
        if re.search(pattern, response, re.IGNORECASE):
            return True
    return False

def is_irrelevant_response(query: str, response: str, threshold: float = 0.3) -> bool:
    # 简单基于词重叠的相似度,实际可用嵌入模型
    query_words = set(re.findall(r'\w+', query.lower()))
    response_words = set(re.findall(r'\w+', response.lower()))
    if not query_words or not response_words:
        return True
    overlap = len(query_words & response_words) / len(query_words)
    return overlap < threshold

2. 重复样本去重

重复样本指完全相同的 queryresponse 组合。使用MD5哈希快速去重:

python 复制代码
import hashlib

def compute_hash(query: str, response: str) -> str:
    content = f"{query}||{response}"
    return hashlib.md5(content.encode('utf-8')).hexdigest()

def deduplicate(records: list) -> list:
    seen = set()
    unique = []
    for rec in records:
        h = compute_hash(rec['query'], rec['response'])
        if h not in seen:
            seen.add(h)
            unique.append(rec)
    return unique

3. 异常值检测

异常值包括回答长度异常(过短或过长)。使用IQR方法检测,但注意该方法假设数据正态分布,对于偏态分布可能误判。

python 复制代码
import pandas as pd

def detect_outliers_by_length(df: pd.DataFrame, column: str = 'response_length') -> pd.Series:
    Q1 = df[column].quantile(0.25)
    Q3 = df[column].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    return (df[column] < lower_bound) | (df[column] > upper_bound)

完整校验函数

将上述步骤整合,输出清洗后的数据及异常报告:

python 复制代码
def quality_check(records: list) -> (list, dict):
    report = {
        'total': len(records),
        'empty': 0,
        'refusal': 0,
        'irrelevant': 0,
        'duplicate': 0,
        'length_outlier': 0,
        'valid': 0
    }
    
    # Step 1: 无效样本识别
    valid_records = []
    for rec in records:
        if is_empty_response(rec['response']):
            report['empty'] += 1
            continue
        if is_refusal_response(rec['response']):
            report['refusal'] += 1
            continue
        if is_irrelevant_response(rec['query'], rec['response']):
            report['irrelevant'] += 1
            continue
        valid_records.append(rec)
    
    # Step 2: 重复去重
    unique_records = deduplicate(valid_records)
    report['duplicate'] = len(valid_records) - len(unique_records)
    
    # Step 3: 异常值检测
    df = pd.DataFrame(unique_records)
    df['response_length'] = df['response'].apply(len)
    outliers = detect_outliers_by_length(df)
    report['length_outlier'] = outliers.sum()
    
    # 标记异常但保留
    df['is_length_outlier'] = outliers
    final_records = df.to_dict('records')
    report['valid'] = len(final_records) - report['length_outlier']
    
    return final_records, report

验证结果

以下为模拟数据示例,实际使用时请替换为真实采集数据。

python 复制代码
test_records = [
    {'query': '什么是AI', 'response': '人工智能是...', 'timestamp': '2025-01-01', 'model': 'gpt-4'},
    {'query': '天气', 'response': '', 'timestamp': '2025-01-01', 'model': 'gpt-4'},
    {'query': '你好', 'response': '抱歉,我无法回答。', 'timestamp': '2025-01-01', 'model': 'gpt-4'},
    {'query': '什么是AI', 'response': '人工智能是...', 'timestamp': '2025-01-01', 'model': 'gpt-4'},  # 重复
    {'query': '股票', 'response': '今天天气很好。', 'timestamp': '2025-01-01', 'model': 'gpt-4'},  # 无关
    {'query': '写一首诗', 'response': '春眠不觉晓...' * 1000, 'timestamp': '2025-01-01', 'model': 'gpt-4'},  # 长度异常
]

cleaned, report = quality_check(test_records)
print(report)
# 预期输出:{'total': 6, 'empty': 1, 'refusal': 1, 'irrelevant': 1, 'duplicate': 1, 'length_outlier': 1, 'valid': 1}

正常情况下,最终 cleaned 列表包含1条正常记录和1条长度异常记录(被保留但标记)。

常见问题与避坑

  • 无关内容检测的阈值:基于词重叠的方法对短文本有效,但对长文本或同义词不敏感。建议在实际项目中替换为嵌入向量余弦相似度,阈值需根据业务数据调整。
  • 重复去重的粒度 :如果只对 response 去重,可能误删不同查询的相同回答。建议组合 queryresponse 哈希。
  • 异常值边界:IQR方法假设数据正态分布,对于偏态分布可能误判。可改用分位数或业务规则(如回答长度<10字符视为异常)。

总结

本文实现了一套轻量级AI回答数据校验流程,覆盖空回答、拒绝回答、无关内容识别、重复去重和长度异常检测。该方案可直接集成到采集管道中,输出清洗后的数据和质量报告。适用范围:单轮问答场景;对于多轮对话,需调整重复检测逻辑。当前限制:无关检测依赖简单词重叠,高精度场景需引入语义模型。方案整体偏规则,适合快速过滤,但无法处理语义层面的复杂异常。

相关推荐
L同学-AIGC1 天前
【OpenClaw 启动器全流程使用教程 —— 从零部署到生产级 AI 智能体】
人工智能·深度学习
叫我Paul就好1 天前
RAG 入门到精通 - Rerank & Hybrid Search
人工智能·rag
szwyyx1 天前
目前知名的BEL电源分销商哪家性价比高
人工智能·python
爱分享的康康1 天前
aiSim6自动驾驶仿真平台:功能、技术与工程落地完整解析
人工智能·机器学习·自动驾驶
weixin_585951171 天前
CH592F 2.4G 低功耗
c语言·开发语言
华如锦1 天前
【AGENT开发】python学习 Python Level 5
python·学习·elasticsearch
爱研究的小梁1 天前
多链路聚合技术在轨交非安全通信网络整体应用
网络·人工智能·信息与通信
秋田君1 天前
QT_QInputDialog类输入对话框
开发语言·qt
忘路之远近i1 天前
Selenium + 自研小型 Agent:用脚本加简易agent搭建简单数据工作流
人工智能·python
集芯微电科技有限公司1 天前
16V/5A高效率COT模式同步降压转换器集成高低功率MOSFET
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设