问题:采集的AI回答JSON数据中混有空回答、拒绝回答、无关内容及重复样本,如何自动识别并清洗?环境:Python 3.9.7 + pandas 1.3.3,Ubuntu 20.04。读者:AI数据工程师。本文提供可复用的校验函数和验证示例,不涉及多轮对话场景。
环境说明
-
操作系统:Ubuntu 20.04 LTS
-
Python版本:3.9.7
-
依赖安装:
bashpip 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. 重复样本去重
重复样本指完全相同的 query 和 response 组合。使用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去重,可能误删不同查询的相同回答。建议组合query和response哈希。 - 异常值边界:IQR方法假设数据正态分布,对于偏态分布可能误判。可改用分位数或业务规则(如回答长度<10字符视为异常)。
总结
本文实现了一套轻量级AI回答数据校验流程,覆盖空回答、拒绝回答、无关内容识别、重复去重和长度异常检测。该方案可直接集成到采集管道中,输出清洗后的数据和质量报告。适用范围:单轮问答场景;对于多轮对话,需调整重复检测逻辑。当前限制:无关检测依赖简单词重叠,高精度场景需引入语义模型。方案整体偏规则,适合快速过滤,但无法处理语义层面的复杂异常。