辩论文本中的逻辑谬误往往不是孤立出现的,同一句话可能同时包含对人身的贬损和对论点的曲解。要让机器自动发现这些问题,不能只做整段二分类或简单的多标签分类,还需要在文本中定位具体攻击点,例如被曲解的对方论点、被错误归因的因果关系,或者从个别案例推广到全体的那一处表述。逻辑谬误检测与攻击点识别可以拆成两个相互关联的任务:前者判断发言中是否存在谬误以及属于哪一类型,后者输出可解释的片段位置,说明模型为什么做出该判断。

在实际系统中,这两个任务通常串联运行。先由粗粒度分类器过滤明显无关的文本,再由细粒度定位模型给出证据片段。这样既能降低计算成本,也能让最终输出更接近可解释的论证审查工具。
一、任务定义与数据标注:从粗粒度分类到片段定位
逻辑谬误类型众多,常见的有ad hominem、straw man、false dilemma、slippery slope和appeal to authority等。不同体系对类型的划分并不完全一致,实践中通常会根据语料来源确定一个可标注的子集。数据集构建的第一步是确定标注单元,可以是一段发言、一个句子,也可以是论证图中的一个节点。如果只标注段落级标签,模型很难解释谬误发生在哪里;因此需要在文本中标出触发谬误的最小片段,并同时记录攻击目标片段。比如句子 A 曲解了句子 B 的观点,那么句子 B 中对应的原始观点片段就是攻击点。
标注格式可以采用 JSON 行,每条样本包含文本、说话人、标签列表和片段偏移。片段偏移用字符级的 start 和 end 表示,避免分词不一致带来的麻烦。多标签场景下每个标签还要关联一个 evidence 片段,这样就把分类任务改造成了带有证据定位的阅读理解或序列标注任务。标注质量比标注数量更关键,因为边界不一致会直接降低模型在片段匹配指标上的表现。可以先让标注者进行锚点标注,再由第二个标注者核对类型。
{
"id": "debate_001",
"text": "你连基本数据都没看就说政策无效,这不是典型的稻草人吗?",
"speaker": "A",
"fallacies": [
{
"type": "straw_man",
"attack_span": [0, 9],
"target_span": [10, 16],
"note": "攻击点位于前半句曲解对方观点处"
}
]
}
二、基于编码器的检测模型:融合论证结构信息
单纯把文本送入预训练编码器,取 [CLS] 向量接线性层,可以得到不错的多标签基线。逻辑谬误检测的难点在于许多类型依赖上下文和言外之意,例如反讽句字面意思与真实立场相反。这时可以在输入端加入说话人、对话历史等元数据,用特殊分隔符拼成一段输入,让模型看到更完整的论辩语境。对于中文数据,可以使用中文 RoBERTa 或宏毅等开源模型进行微调。
更进一步的思路是引入论证结构。先做论点识别、前提提取和关系分类,得到论证图,再用图神经网络更新节点表示,最后把图表示与文本表示融合。攻击点识别尤其依赖这种结构:如果模型知道某个节点是对方论点,另一个节点是对它的攻击,那么攻击片段的边界往往可以从关系分类的注意力中推断出来。实践中常用两阶段方法,第一阶段检测段落中是否存在谬误,第二阶段对检测到的样本做片段定位,这样能够降低计算量,也方便分别调优。
还有一类做法是把攻击点识别建模为抽取式问答。将每个待检测的谬误类型转化为一个问题,例如:这段发言攻击了对方的哪个观点?模型需要在原文中预测答案片段。抽取式问答的优势是可以直接输出 start 和 end,不需要预定义长度,而且在少样本类型上表现更稳定。
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
model_name = "hfl/chinese-roberta-wwm-ext"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name, num_labels=6, problem_type="multi_label_classification"
)
text = "你连基本数据都没看就说政策无效,这不是典型的稻草人吗?"
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=256)
outputs = model(**inputs)
logits = outputs.logits
probs = torch.sigmoid(logits)
print(probs)
三、攻击点定位与可解释评估
攻击点定位如果采用序列标注,可以用 BIO 标签标注每个 token 是否属于某个谬误片段。举例来说,文本前半句曲解对方观点,那么这些 token 被标为 B-straw_man 和 I-straw_man,后半句不在攻击点上,标为 O。这样模型结构简单,但无法直接处理嵌套类型。如果同一片段同时属于两个谬误类型,需要使用嵌套标注或多头预测。抽取式问答则天然支持多类型组合,每个问题独立预测答案,适合细粒度识别。
解释性分析不能只看注意力权重,因为注意力本身并不等于归因。更可靠的方法是使用 SHAP 或积分梯度,在微调后的模型上计算每个 token 对最终预测的贡献。对于攻击点任务,还可以比较模型预测片段与人类标注片段的重叠程度,使用精确匹配、字符级 F1 和 IOU 等指标。宏平均 F1 如果只看段落标签,可能掩盖片段边界错位的问题,因此评估时要把分类指标和定位指标分开报告。
实战中有三个建议。第一,优先保证少量类型的标注一致性,而不是追求覆盖大量类型;第二,使用对抗样本和数据增强提升模型对同义改写和反讽的鲁棒性;第三,在上线前用规则引擎兜底常见模式,例如对包含明显人身攻击词的发言先做关键词标记,再交给模型细化类型和边界。攻击点识别输出最好附带置信度和证据片段,方便辩论平台向用户展示解释。
def span_f1(pred_spans, gold_spans):
pred_set = set(pred_spans)
gold_set = set(gold_spans)
tp = len(pred_set & gold_set)
if not pred_set or not gold_set:
return 0.0
precision = tp / len(pred_set)
recall = tp / len(gold_set)
if precision + recall == 0:
return 0.0
return 2 * precision * recall / (precision + recall)
pred = [(0, 9), (20, 28)]
gold = [(0, 10), (21, 28)]
print(span_f1(pred, gold))
综合来看,辩论逻辑谬误检测要真正落地,需要把分类和定位两项能力结合在一起。数据标注阶段最好就保留片段级别的证据,模型阶段兼顾文本特征和论证结构,评估阶段同时报告段落标签指标和片段边界指标。随着对话式 AI 应用进入教育和公共讨论场景,对逻辑谬误的自动识别会越来越强调可解释性,攻击点识别正是让模型从黑箱判断走向可用解释的关键一步。