面向长文本的多模型协作摘要架构:多LLM文本摘要方法
多LLM摘要框架在每轮对话中包含两个基本步骤:生成和评估。这些步骤在多LLM分散式摘要和集中式摘要中有所不同。在两种策略中,k个不同的LLM都会生成多样化的文本摘要。然而在评估阶段,多LLM集中式摘要方法使用单个LLM来评估摘要并选择最佳摘要,而分散式多LLM摘要则使用k个LLM进行评估。
论文提出的方法旨在处理长文本文档输入,这类文档可能包含数万字,通常超出大多数标准LLM的上下文窗口限制,论文建立了一个两阶段处理流程:首先将源文档分块,独立summarize每个源文档块,然后对连接后的中间结果进行第二轮分块和摘要。在这两个阶段中,两种框架都允许多个LLM协作,最终收敛到一个高质量的完整原始参考文档摘要。
集中式多LLM摘要
单轮处理
每个LLM接收一次提示,生成各自的摘要。然后通过单一评估步骤选择最佳的最终摘要。
在单轮设置中,每个参与模型列表中的LLM都使用相同的提示P独立生成输入文本的摘要。对于每个LLM Mj ∈ M,输出为Sj = Mj(P,S),其中S表示输入文本。对所有Mj运行此步骤会得到一组摘要S = {S1,…,Sk}。从概念上讲,每个模型都贡献其独特的视角,产生多样化的候选摘要池,这对后续评估阶段的稳健摘要选择非常重要。
在收集候选摘要集S后,中央代理C ∈ M对这些摘要进行评估。中央LLM C使用评估提示Pec来评估每个摘要的质量。形式上表示为E = C(Pec, S),其中E是中央LLM对所有候选摘要的评估。这包括选择最佳摘要(以其匿名标识符表示)以及该评估的置信度分数(以0到10的整数表示)。将标识符去匿名化以恢复所选摘要Sj的文本,并将其设置为最终输出S*。在单轮机制中,此时终止流程,不再进行后续迭代。
对话式处理
生成和评估阶段会重复多次。每个生成-评估过程定义为一轮,并定义了流程结束或开始新一轮的条件,直到达到最大轮次。
对话式处理的第一轮与单轮程序相似。每个LLM Mj使用提示P从原始输入文本S生成初始摘要S(1)j:S(1) = Mj(P,S)。如果上一轮评估结果的置信度分数低于阈值,或者LLM未能输出可读的置信度分数,流程将进入下一轮。在第二轮及后续轮次中,使用提示P(i)。后续轮次中的LLM可以访问待摘要文本和上一轮的摘要。具体来说,在第i轮(i > 1):S(i)j = Mj(P(i),S)。
第i轮(i > 1)的评估阶段在概念上与单轮设置相似,但现在是对生成阶段刚刚产生的候选摘要Si = {S1(i), …, Sk(i)}进行操作。中央LLM C使用Pec评估这些候选摘要:E(i) = C(Pec, Si)。如果置信度达到阈值,流程终止,中央LLM选择的摘要被接受为S*。否则,流程进入下一轮摘要生成和评估。
分散式多LLM摘要
单轮处理
生成程序与集中式方法相同。多个LLM独立生成输入文本的摘要,获得摘要列表S = {S1,…,Sk}。
在评估阶段,每个生成摘要的模型都会收到一个新的评估提示,该提示不包含置信度,并收到待摘要文本以及包括自己在内的所有代理生成的摘要。形式上,收集模型偏好E(i),…,E(i),其中每个E(i)代表模型Mj对S(i),…,S(i)中最佳摘要的选择。当大多数模型选择相同的摘要时,即达成收敛。当没有出现多数选择时,在单轮方法(tmax = 1)中,算法选择指定的决胜模型Mt的摘要。
对话式处理
生成遵循与集中式方法相同的方法,产生摘要集S = S1,…,Sk。与单轮方法的一个关键区别在于条件重生成机制:当第一轮未达成共识时,后续轮次使用包含先前评估生成的摘要的新提示。
第一轮评估与单轮方法相同,但在未达成共识时会进入带有新生成提示的额外轮次。在单轮情况下,未达成共识会立即触发决胜模型机制。相比之下,对话式方法会使用更新的提示启动新的生成-评估轮次。这个过程持续进行,直到出现多数共识或达到tmax轮。在tmax轮后仍未达成共识时,算法默认使用决胜机制。
实验设置
实验使用ArXiv和GovReport数据集评估摘要方法。使用ROUGE-1、ROUGE-L、BLEU-1和BLEU-4指标评估LLM生成摘要的质量。为了与多LLM方法进行比较,采用GPT-3.5、GPT-4o、GPT-4o mini和LLaMA3-8B作为基准。所有模型使用4K字符的块大小,最终摘要表示为生成摘要的连接。
评估结果
分散式和集中式多LLM方法的结果。
多LLM方法不同评估和决胜模型的结果。
- 多LLM框架显著优于单一LLM基准,在某些情况下性能提升高达3倍
- 集中式多LLM方法平均提升得分73%,而分散式方法平均提升70%
- 仅使用两个LLM和单轮生成评估就能获得显著的性能提升,表明该方法具有成本效益
- 该框架在不同的中央模型(评估器)和决胜模型中表现稳定
- 超过两个LLM和额外的生成评估轮次并未带来进一步改进
实现代码
fromlangchain_ollamaimportChatOllama
gemma2=ChatOllama(model="gemma2:9b", temperature=0)
llama3=ChatOllama(model="llama3:8b", temperature=0)
llama3_1=ChatOllama(model="llama3.1:8b", temperature=0)
prompt_initial_summary="""
Provide a concise summary of the text in around 160 words.
Output the summary text only and nothing else.
提示词
prompt_initial_summary = """
Provide a concise summary of the text in around 160 words.
Output the summary text only and nothing else.
{text}
""".strip()
prompt_subsequent_summary = """
Given the original text below, along with the summaries of that text by 3 LLMs,
please generate a better summary of the original text in about 160 words.
ORIGINAL:
{text}
Summary by agent_1:
{summary_1}
Summary by agent_2:
{summary_2}
Summary by agent_3:
{summary_3}
""".strip()
prompt_decentralised_evaluation = """
Given the original text below, along with the summaries of that text by 3 agents,
please evaluate the summaries and output the name of the agent that has the best summary.
Output the exact name only and nothing else.
ORIGINAL:
{text}
Summary by agent_1:
{summary_1}
Summary by agent_2:
{summary_2}
Summary by agent_3:
{summary_3}
""".strip()
prompt_centralised_evaluation = """
Given the initial text below, along with the summaries of that text by 3 LLMs,
please evaluate the generated summaries and output the name of the LLM has the best summary.
On a separate line indicate a confidence level between 0 and 10.
ORIGINAL:
{text}
Summary by agent_1:
{summary_1}
Summary by agent_2:
{summary_2}
Summary by agent_3:
{summary_3}
Remember, on a separate line indicate a confidence level between 0 and 10.
""".strip()
prompt_concate = """
Provide a concise summary of the text in around 160 words.
Output the summary text only and nothing else.
{summaries}
""".strip()
汇总
class SingleTurnCentralised():
def __init__(self, models):
self.models = models
def generate(self, text):
summaries = []
for model in self.models:
summaries.append(model.invoke([{"role": "user", "content": prompt_initial_summary.format(text=text)}]).content)
return summaries
def evaluate(self, text, summaries):
response = gemma2.invoke([
{"role": "user", "content": prompt_centralised_evaluation.format(text=text, summary_1=summaries[0], summary_2=summaries[1], summary_3=summaries[2])}
]).content
winner, *_, confidence = response.split()
return winner, confidence
def __call__(self, chunks):
summarised_chunks = []
for chunk in chunks:
summaries = self.generate(chunk)
winner, confidence = self.evaluate(chunk, summaries)
summarised_chunks.append(summaries[int(winner[-1]) -1])
final_summary = gemma2.invoke([{"role": "user", "content": prompt_concate.format(summaries="\n".join(summarised_chunks))}]).content
return final_summary
single_turn_centralised = SingleTurnCentralised([gemma2, llama3, llama3_1])
final_summary = single_turn_centralised(chunks)
论文地址
Multi-LLM Text Summarization
https://avoid.overfit.cn/post/ba136ba242694d68bce4c5499c85c647
作者: Ritvik Rastogi