2024年LLM长上下文会议纪要总结工具排行榜
面对动辄数小时的会议录音或数百页的文档,常见的长文本处理需求往往让大模型束手无策。即便标榜支持超长上下文的模型,实际表现也常打折扣。下面这张图直观展示了这个痛点:
上下文过长时,大模型甚至无法准确理解prompt的意图。
针对长文本总结,LangChain的load_summarize_chain内置三种成熟策略,可按需选用:
第一种,Stuff:直接将全部文档打包进一个提示,要求模型上下文窗口足够大(例如OpenAI的gpt-3.5-turbo-1106,16k token;Anthropic的Claude-2,100k token)。通常一个汉字计作一个token,一个英文单词亦然。
第二种,Map-reduce:分为映射与归约两阶段。先对每个文档独立生成摘要,再将所有摘要合并为最终版。逻辑清晰且支持并行计算。
第三种,Refine:采用串行方式,无法并行。从第一个文档生成初步总结,随后逐个文档迭代优化,如同雕琢作品般逐步完善。
此外,聚类方法也常见:先对文本进行主题分类,再逐类总结,速度优势明显。但聚类过程可能遗漏边缘信息,细节易丢失。
实践中常用“分块+多轮总结”框架。将长文本切分为多个片段,分别生成摘要后,将这些摘要作为新输入,重复切分与总结步骤,直至产出精炼的核心纪要。
注意:Qwen-14B的上下文上限为8K token,务必严格遵守此边界。
为控制每轮总结的输出长度,我设计了一个函数:根据当前文本块数动态计算输出长度上限,结合精准提示词,确保每轮总结后token数持续缩减,避免冗余膨胀。
针对会议场景,我额外对原始数据进行了规整。多人会议中,ASR识别率常急剧下降,输出缺少标点和说话人分离,可读性极差。为此,我采用了WhisperX并叠加后处理优化。
其中一个技巧是“合并因说话人分配错误的句子”。判断当前句与上一句是否归属同一说话人,若不同且当前句字数低于阈值,则视为误检,将其合并至上一句。该方法虽不完美,后续可尝试基于前后句动态调整说话人判断,或利用BERT计算is_next_word概率以提升精度。
WhisperX仅支持英文标点恢复,中文则需额外调用Paddle的自动标点模型。使用需注意:输入长度受限,过长需提前分段;不支持粤语(Whisper有时倾向识别粤语字),建议用Opencc转为简体;该模型会移除英文单词间的空格,导致字母粘连。我后来用正则分离中英文,再通过wordninja对英文进行分词。
格式整理完毕后,结合提示词模板生成如下query,直接输入LLM完成最终总结:
请扮演会议纪要整理助手,请您简洁专业地总结以下会议内容(不得超过1000个字,不允许在答案中添加任何编造成分)
<会议内容>
> Speaker0: xxxx
> Speaker1: xxxx
> Speaker2: xxxx
<会议内容>
若会议对话过长,可采用分块策略。若LLM能力足够强,也可不做说话人分离,直接对原始ASR文本进行段落分割后输入。段落分割旨在解决长会议ASR文本缺乏结构的问题,便于语义切块。推荐阿里语音实验室在IEEE ASRU 2021提出的SeqModel:先分句,再对每句分词,融合token、segment、position embedding及发音embedding,输入BERT,最后通过softmax判断每个句子是否为段落边界。
考虑到ASR常出现声学混淆,将每个字的发音信息(通过中文发音表获取)作为增强特征输入,可显著提升效果。此外,该团队提出的自适应滑窗算法,根据模型预测的分割点滑动窗口,大幅提升推理速度。
尽管训练代码未开源,但可直接通过ModelScope调用:
# 段落分割
# https://modelscope.cn/models/iic/nlp_bert_document-segmentation_chinese-base/summary
from modelscope.outputs import OutputKeys
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
p = pipeline(
task=Tasks.document_segmentation,
model='damo/nlp_bert_document-segmentation_chinese-base')
documents = ''.join(annot_dfs['transcription'].astype(str).values.tolist())
result = p(documents=documents)
paragraphs = result[OutputKeys.TEXT]
paragraphs = paragraphs.split('\t')
但不得不承认,即便框架再精巧,若大模型自身的长文本总结能力不足,最终效果仍难以令人满意。如同传声游戏,多次传递后细节丢失甚至被歪曲。何况每轮总结需要融合多个上一轮结果,信息丢失和整体性下滑几乎不可避免。
除更换更强的大模型外,是否存在其他优化路径?这个方向值得深入探索。
未来有机会,我希望研究如何训练支持超长文本的模型。难点主要在于:self-attention算法的优化,以及训练与推理的工程优化。目前已知的技术路线包括:位置编码外推、小模型配合滑动窗口、上下文降采样或稀疏注意力、结合RAG对部分输入进行自注意力计算、上下文分组计算等。相关文献值得系统研读。归根结底,必须从模型底层突破,不能止步于表层封装优化。