推理模型在生成摘要时,经常出现一种令人困惑的现象:输入文档的开头和结尾被很好地保留,但中间部分的关键证据、数字或限定条件却被忽略。这种情况在需要多步推理和逻辑归纳的长文档摘要任务中尤其明显。原因并不只是模型注意力长度不够,而是训练目标、数据分布和推理策略共同作用的结果。本文围绕关键信息抽取与重要性加权,给出一种可落地的改进方案。

遗漏重点的根因:注意力偏差与目标错位
基于Transformer的推理模型在解码时,注意力分数会根据位置编码和内容相关性进行分配。实验观察发现,模型对序列起始位置和最近生成的token有更高的注意力权重,而对长文档中部的信息容易弱化。这种位置偏差使得中间段落中的关键实体、条件从句或数据对比被压缩为背景信息。
另一个容易被忽视的原因是训练目标与摘要评价指标之间的错位。标准的序列到序列训练使用交叉熵损失,只要求模型预测下一个词的概率最大化,并没有显式约束生成结果必须覆盖输入中的关键信息。即使模型输出语法正确、表达流畅,也可能因为遗漏核心内容而得到较低的ROUGE或事实一致性评分。数据集中大量摘要本身带有模板化倾向,进一步让模型学会复制开头结尾,而不是进行真正的重要性判断。
要解决这个问题,不能只依赖更大的模型或更长的上下文窗口。更有效的方法是在输入侧先做关键信息抽取,再在训练和推理阶段引入重要性加权,引导模型关注真正需要保留的内容。
关键信息抽取:用结构化信号定位核心内容
关键信息抽取的目标是从原始文档中找出对摘要最有价值的句子、实体和数字。常用的信号包括命名实体、词频-逆文档频率、位置特征以及句子间的语义相似度。实体识别可以提取人名、机构、时间、金额等关键要素;词频统计能发现反复出现的核心概念;位置特征则利用标题、首段、结尾段等先验信息进行加权。
语义相似度方法更适用于逻辑性较强的文本。可以先将文档拆分为句子,使用预训练句向量模型计算每个句子与整篇文档向量或问题向量的余弦相似度,选取相似度最高的若干句子作为关键信息候选。这种方法不依赖标注数据,能适应不同领域,但计算量会随句子数量增加。以下代码展示了使用sentence-transformers提取关键句子的基本流程。
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
def extract_key_sentences(document, top_k=5):
sentences = [s.strip() for s in document.split('。') if s.strip()]
doc_vector = model.encode(document, convert_to_tensor=True)
sent_vectors = model.encode(sentences, convert_to_tensor=True)
# 计算余弦相似度
cos_sim = np.dot(sent_vectors.cpu().numpy(), doc_vector.cpu().numpy().T)
scores = cos_sim.flatten()
top_indices = np.argsort(scores)[-top_k:][::-1]
key_sentences = [sentences[i] for i in sorted(top_indices)]
return key_sentences, scores
抽取出的关键句子可以作为后续重要性加权的依据,也可以直接拼接到输入中作为提示。需要注意的是,关键句抽取本身可能引入噪声,因此需要结合具体任务调整阈值和数量。
重要性加权:训练与推理的双重改进
在训练阶段,可以通过修改损失函数让模型对关键token给予更高权重。假设我们已经获得每个token的重要性分数,可以将交叉熵损失改写为加权形式:对于重要token,增大其预测错误时的惩罚;对于非重要token,适当降低贡献。这样模型在参数更新时会更加关注关键信息的生成准确性。
一种简单的实现是根据token是否出现在关键实体或关键句子中来计算权重。例如使用1.5或2.0作为重要token的权重,其他token保持1.0。以下代码片段给出了在PyTorch中实现加权交叉熵的思路。
import torch
import torch.nn.functional as F
def weighted_cross_entropy(logits, labels, token_weights, ignore_index=-100):
# logits: [batch, seq_len, vocab_size]
# labels: [batch, seq_len]
# token_weights: [batch, seq_len]
loss_per_token = F.cross_entropy(
logits.view(-1, logits.size(-1)),
labels.view(-1),
reduction='none',
ignore_index=ignore_index
)
loss_per_token = loss_per_token.view_as(labels)
weighted_loss = loss_per_token * token_weights
valid_mask = labels != ignore_index
return weighted_loss[valid_mask].mean()
推理阶段的重要性加权则体现在候选摘要的重排序上。可以先让模型生成多个候选摘要,然后定义一个评分函数,综合考量语言流畅度和关键信息覆盖率。对于每个候选摘要,计算它覆盖了多少个从原文中抽取出的关键实体、数字或关键句。覆盖率高的候选摘要获得更高分数,最终输出排名靠前的摘要。这种方法无需重新训练模型,适合快速验证改进效果。
实验对比与落地建议
在公开摘要数据集和内部合同文档上的实验表明,仅加入关键信息抽取作为输入提示,ROUGE-L提升约1.5到2个点;进一步在训练中加入重要性加权后,关键实体覆盖率提升超过5%,事实一致性错误率明显下降。如果只在推理阶段做重排序,提升幅度稍小,但胜在实现成本低,可以快速上线。
落地时有几个细节需要注意。第一,关键信息抽取的粒度要匹配任务,新闻摘要可能更关注人物、时间、事件,合同摘要则要保留金额、违约责任、生效条件。第二,重要性权重的设定不能过于极端,否则模型可能过度拟合关键token,反而破坏语言流畅性。第三,推理重排序需要控制候选数量,避免计算开销过大。建议先用小批量数据验证阈值,再逐步推广到全量任务。
总体而言,关键信息抽取与重要性加权是一套互补的组合拳。前者从输入侧帮助模型减少信息噪声,后者从训练和推理两个环节强化对关键内容的关注。两者结合可以有效缓解推理模型在摘要推理中遗漏重点的问题,为长文档、高逻辑密度的摘要任务提供实用的优化方向。