AIGC检测的现实困境
随着AI生成内容质量逼近人类写作,区分AI和人类内容变得越来越难。检测技术与生成技术的军备竞赛正在加速——而检测方天然处于劣势。
统计检测方法
困惑度检测
AI生成文本的困惑度(perplexity)通常低于人类文本:
class PerplexityDetector:
def __init__(self, reference_model):
self.model = reference_model
def detect(self, text):
# 计算困惑度
ppl = self._compute_perplexity(text)
# 困惑度低 → 更可能是AI生成
# 困惑度高 → 更可能是人类写作
threshold = 30 # 需要根据具体场景校准
return {
"ai_probability": max(0, 1 - ppl / threshold),
"perplexity": ppl,
"classification": "AI" if ppl < threshold else "Human"
}
def _compute_perplexity(self, text):
tokens = self.model.tokenize(text)
log_prob = self.model.compute_log_prob(tokens)
return math.exp(-log_prob / len(tokens))
局限:经过轻微改写(同义词替换、句式调整)就可以大幅提高困惑度,绕过检测。
Burstiness检测
人类写作的句子长短变化大(高burstiness),AI写作更均匀(低burstiness):
def burstiness_score(text):
sentences = split_sentences(text)
lengths = [len(s.split()) for s in sentences]
mean_len = np.mean(lengths)
std_len = np.std(lengths)
# 变异系数
cv = std_len / mean_len
# 人类通常CV > 0.5,AI通常 < 0.3
return cv
词汇多样性分析
AI倾向于使用更有限的词汇集:
def lexical_diversity(text):
tokens = text.lower().split()
unique = set(tokens)
# Type-Token Ratio
ttr = len(unique) / len(tokens)
# Yule's K(更鲁棒的多样性指标)
k = compute_yules_k(tokens)
return {"ttr": ttr, "yules_k": k}
水印技术
文本水印:绿色token法
在生成过程中对token选择施加统计偏移,留下不可见水印:
class WatermarkedGenerator:
def __init__(self, model, green_ratio=0.5, delta=2.0):
self.model = model
self.green_ratio = green_ratio # 绿色token比例
self.delta = delta # 偏移强度
def generate(self, prompt, max_tokens=100):
# 为每个位置随机分配绿/红token集
tokens = []
for _ in range(max_tokens):
logits = self.model.next_logits(prompt + tokens)
# 基于前一个token的hash确定绿/红集
if tokens:
green_set = self._get_green_set(tokens[-1])
else:
green_set = self._get_green_set(0)
# 给绿色token加bias
for token_id in green_set:
logits[token_id] += self.delta
# 采样
next_token = sample(logits)
tokens.append(next_token)
return tokens
def detect(self, text, threshold=0.05):
tokens = self.model.tokenize(text)
green_count = 0
for i in range(1, len(tokens)):
green_set = self._get_green_set(tokens[i-1])
if tokens[i] in green_set:
green_count += 1
expected_green = len(tokens) * self.green_ratio
actual_green = green_count / len(tokens)
# 统计检验
z_score = (actual_green - self.green_ratio) / math.sqrt(
self.green_ratio * (1 - self.green_ratio) / len(tokens)
)
return {
"watermarked": z_score > 1.65, # 95%置信度
"z_score": z_score,
"green_ratio": actual_green
}
图像水印
不可见水印:在频域中嵌入水印信息:
import cv2
import numpy as np
def embed_watermark(image, watermark_text):
# DCT变换
dct = cv2.dct(np.float32(image))
# 在中频系数中嵌入水印
watermark_bits = text_to_bits(watermark_text)
for i, bit in enumerate(watermark_bits):
row, col = i // 8 + 50, i % 8 + 50 # 中频区域
if bit:
dct[row, col] = abs(dct[row, col]) | 1
else:
dct[row, col] = abs(dct[row, col]) & ~1
# IDCT回到空域
watermarked = cv2.idct(dct)
return watermarked.astype(np.uint8)
C2PA标准:内容来源认证联盟提出的标准,在元数据中记录内容来源和编辑历史:
{
"c2pa_manifest": {
"claim_generator": "AI-Model-v2.1",
"signature": "...",
"assertions": [
{"type": "ai_generated", "model": "DALL-E-3"},
{"type": "edited", "tool": "Photoshop", "actions": ["crop"]}
]
}
}
对抗攻防
检测绕过攻击
改写攻击:用另一个模型改写AI文本以改变统计特征:
def paraphrase_attack(ai_text, paraphrase_model):
prompt = f"""改写以下文本,保持原意但改变表达方式:
{ai_text}
要求:
- 使用不同的句式
- 替换部分词汇
- 调整句子长度变化"""
return paraphrase_model.generate(prompt)
混合攻击:将AI文本与人类文本混合:
def mixed_attack(ai_text, human_text, ratio=0.5):
# 交替使用AI和人类段落
ai_paragraphs = split_paragraphs(ai_text)
human_paragraphs = split_paragraphs(human_text)
mixed = []
for i in range(max(len(ai_paragraphs), len(human_paragraphs))):
if i % 2 == 0 and i < len(human_paragraphs):
mixed.append(human_paragraphs[i])
if i % 2 == 1 and i < len(ai_paragraphs):
mixed.append(ai_paragraphs[i])
return "\n\n".join(mixed)
水印移除攻击
token替换:替换部分token改变绿色token比例:
def watermark_removal(text, model, threshold=0.05):
tokens = model.tokenize(text)
# 检测水印
detector = WatermarkedGenerator(model)
# 替换可疑的绿色token
for i in range(1, len(tokens)):
green_set = detector._get_green_set(tokens[i-1])
if tokens[i] in green_set:
# 用同义词替换
synonyms = get_synonyms(tokens[i])
for syn in synonyms:
if syn not in green_set:
tokens[i] = syn
break
return model.detokenize(tokens)
检测方的反制
鲁棒水印:设计对token替换鲁棒的水印方案:
- 使用多个前缀token的hash确定绿/红集,增加替换难度
- 在语义不变的空间中嵌入水印
多模态检测:结合文本、图像、元数据多维度检测:
class MultiModalDetector:
def __init__(self):
self.text_detector = StatisticalTextDetector()
self.image_detector = ImageArtifactDetector()
self.metadata_checker = MetadataChecker()
def detect(self, content):
text_score = self.text_detector.detect(content.text)
image_score = self.image_detector.detect(content.image)
meta_score = self.metadata_checker.check(content.metadata)
# 加权融合
final_score = (
0.4 * text_score +
0.3 * image_score +
0.3 * meta_score
)
return {
"ai_probability": final_score,
"text_analysis": text_score,
"image_analysis": image_score,
"metadata_analysis": meta_score
}
各检测方案的效果对比
| 方法 | 准确率 | 抗改写 | 实时性 | 适用场景 |
|---|---|---|---|---|
| 困惑度 | 75% | 低 | 快 | 初筛 |
| Burstiness | 70% | 中 | 快 | 辅助证据 |
| 绿色token水印 | 99%* | 中 | 快 | 生成方配合 |
| C2PA元数据 | 100%* | 低* | 快 | 正规渠道 |
| 多模态融合 | 85% | 高 | 中 | 综合检测 |
*前提:生成方主动嵌入水印/元数据
结语
AI内容检测是一场不对称的战争——检测方需要识别所有AI内容,而生成方只需绕过检测即可。长期来看,水印+元数据认证是最可靠的方案,但需要全行业协作。纯粹基于统计特征的检测在对抗中会持续落后。未来,“可信内容"可能不再通过检测来识别,而是通过来源认证来保证——就像我们信任有签名的信件而非匿名信。