Skip to main content

摘要 (Summarization)

在Collab中打开

使用案例 (Use case)

假设您有一组文档(PDF、Notion页面、客户问题等),您想要对内容进行总结。

鉴于LLMs在理解和综合文本方面的熟练程度,它们是一个很好的工具。

在本教程中,我们将介绍如何使用LLMs进行文档摘要。

图像描述

概述 (Overview)

构建摘要生成器的一个核心问题是如何将文档传递到LLM的上下文窗口中。有两种常见的方法:

  1. Stuff:将所有文档简单地"stuff"到一个单一的提示中。这是最简单的方法(有关使用此方法的StuffDocumentsChains的更多信息,请参见此处)。

  2. Map-reduce:在"map"步骤中单独对每个文档进行摘要,并将摘要"reduce"为最终摘要(有关使用此方法的MapReduceDocumentsChain的更多信息,请参见此处)。

图像描述

快速入门 (Quickstart)

为了给您一个预览,任何一个流水线都可以包装在一个单一的对象中:load_summarize_chain

假设我们想要对一篇博客文章进行摘要。我们可以用几行代码来实现这个目标。

首先设置环境变量并安装包:

pip install openai tiktoken chromadb langchain

# 设置环境变量 OPENAI_API_KEY 或从 .env 文件中加载
# import dotenv

# dotenv.load_env()

我们可以使用 chain_type="stuff",特别是当使用更大的上下文窗口模型时,比如:

  • 16k 令牌的 OpenAI gpt-3.5-turbo-16k
  • 100k 令牌的 Anthropic Claude-2

我们还可以提供 chain_type="map_reduce"chain_type="refine"(在这里阅读更多信息)。

from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import WebBaseLoader
from langchain.chains.summarize import load_summarize_chain

loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
docs = loader.load()

llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k")
chain = load_summarize_chain(llm, chain_type="stuff")

chain.run(docs)
    '该文章讨论了利用大型语言模型(LLM)构建自主代理的概念。它探讨了这些代理的组成部分,包括规划、记忆和工具使用。文章提供了LLM驱动代理在各个领域的案例研究和概念验证示例。它还强调了在代理系统中使用LLM的挑战和限制。'

选项1. 材料

当我们使用load_summarize_chainchain_type="stuff"时,我们将使用StuffDocumentsChain

该链将接受一个文档列表,将它们全部插入到一个提示中,并将该提示传递给一个LLM:

from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
from langchain.chains.combine_documents.stuff import StuffDocumentsChain

# 定义提示
prompt_template = """对以下内容写一个简洁的摘要:
"{text}"
简洁摘要:"""
prompt = PromptTemplate.from_template(prompt_template)

# 定义LLM链
llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k")
llm_chain = LLMChain(llm=llm, prompt=prompt)

# 定义StuffDocumentsChain
stuff_chain = StuffDocumentsChain(
llm_chain=llm_chain, document_variable_name="text"
)

docs = loader.load()
print(stuff_chain.run(docs))
    本文讨论了利用大型语言模型(LLM)构建自主代理的概念。它探讨了这些代理的组成部分,包括规划、记忆和工具使用。本文提供了概念验证演示的案例研究和示例,突出了LLM驱动代理的挑战和限制。它还包含了相关研究论文的参考文献,并为本文提供了引用。

太棒了!我们可以看到使用load_summarize_chain我们复现了之前的结果。

深入了解

  • 您可以轻松自定义提示。
  • 您可以通过 llm 参数轻松尝试不同的LLM(例如,Claude)。

选项2. Map-Reduce (Option 2. Map-Reduce)

让我们来解析一下Map-Reduce方法。首先,我们将使用LLMChain将每个文档映射到一个单独的摘要。然后,我们将使用ReduceDocumentsChain将这些摘要合并成一个全局摘要。

首先,我们需要指定用于将每个文档映射到单独摘要的LLMChain:

from langchain.chains.mapreduce import MapReduceChain
from langchain.text_splitter import CharacterTextSplitter
from langchain.chains import ReduceDocumentsChain, MapReduceDocumentsChain

llm = ChatOpenAI(temperature=0)

# 映射
map_template = """以下是一组文档
{docs}
根据这些文档,请确定主要主题
有用的答案:"""
map_prompt = PromptTemplate.from_template(map_template)
map_chain = LLMChain(llm=llm, prompt=map_prompt)

ReduceDocumentsChain负责将文档映射结果合并为单个输出。它包装了一个通用的CombineDocumentsChain(如StuffDocumentsChain),但是如果累积大小超过token_max,它还可以在将其传递给CombineDocumentsChain之前折叠文档。在这个例子中,我们实际上可以重用用于合并文档的链条来折叠文档。

因此,如果映射文档中的累积标记数超过4000个标记,那么我们将以小于4000个标记的批次递归地将文档传递给我们的StuffDocumentsChain来创建批次摘要。一旦这些批次摘要的累积标记数小于4000个标记,我们将最后一次将它们全部传递给StuffDocumentsChain来创建最终摘要。

# 合并
reduce_template = """以下是一组摘要:
{doc_summaries}
请将它们提炼成一个最终的、综合的主题摘要。
有用的答案:"""
reduce_prompt = PromptTemplate.from_template(reduce_template)
reduce_chain = LLMChain(llm=llm, prompt=reduce_prompt)

# 接受一个文档列表,将它们合并为一个字符串,并将其传递给LLMChain
combine_documents_chain = StuffDocumentsChain(
llm_chain=reduce_chain, document_variable_name="doc_summaries"
)

# 合并和迭代减少映射的文档
reduce_documents_chain = ReduceDocumentsChain(
# 这是最终调用的链条。
combine_documents_chain=combine_documents_chain,
# 如果文档超过`StuffDocumentsChain`的上下文
collapse_documents_chain=combine_documents_chain,
# 将文档分组的最大标记数。
token_max=4000,
)

将我们的映射和减少链条合并为一个:

# 通过映射链条将文档合并,然后合并结果
map_reduce_chain = MapReduceDocumentsChain(
# 映射链条
llm_chain=map_chain,
# 减少链条
reduce_documents_chain=reduce_documents_chain,
# 将文档放入llm_chain中的变量名
document_variable_name="docs",
# 在输出中返回映射步骤的结果
return_intermediate_steps=False,
)

text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
chunk_size=1000, chunk_overlap=0
)
split_docs = text_splitter.split_documents(docs)
    创建了一个大小为1003的块,超过了指定的1000
print(map_reduce_chain.run(split_docs))
    在提供的文档集中,识别出的主要主题如下:

1. 基于LLM的自主代理系统:文档讨论了使用大型语言模型(LLM)作为核心控制器构建自主代理的概念。它们探索了LLM在内容生成之外的潜力,并将其作为强大的问题解决者。

2. 代理系统的组成部分:文档概述了基于LLM的代理系统的关键组成部分,包括规划、记忆和工具使用。详细描述了每个组件,突出了它在增强代理能力方面的作用。

3. 规划和任务分解:规划组件侧重于任务分解和自我反思。代理将复杂任务分解为较小的子目标,并从过去的行动中学习以改进未来的结果。

4. 记忆和学习:记忆组件包括用于上下文学习的短期记忆和用于在较长时间内保留和回忆信息的长期记忆。还提到了使用外部向量存储进行快速检索。

5. 工具使用和外部API:代理学会利用外部API访问额外的信息、执行代码和专有资源。这增强了代理的知识和问题解决能力。

6. 案例研究和概念验证示例:文档提供了案例研究和示例,以展示LLM驱动的代理在科学发现、生成模拟和其他领域中的应用。这些示例作为代理系统有效性的概念验证。

7. 挑战和限制:文档提到了构建LLM驱动的自主代理所面临的挑战,如有限的上下文长度限制、长期规划的困难以及自然语言界面的可靠性问题。

8. 引用和参考文献:文档包括引用和参考文献部分,以承认讨论的概念的来源和灵感。

总体而言,主要主题围绕LLM驱动的自主代理系统的开发和能力展开,包括其组成部分、规划和任务分解、记忆和学习机制、工具使用和外部API、案例研究和概念验证示例、挑战和限制,以及正确引用和参考的重要性。

深入了解

自定义

  • 如上所示,您可以自定义LLMs和map和reduce阶段的提示。

真实世界的用例

  • 请参阅此博客文章中关于分析用户交互(有关LangChain文档的问题)的案例研究!
  • 该博客文章及其相关的存储库还介绍了聚类作为摘要的一种手段。
  • 这打开了一个超越“stuff”或“map-reduce”方法的第三条路径,值得考虑。

图像描述

选项 3. 优化

Refine 类似于 map-reduce:

优化文档链通过循环遍历输入文档并迭代更新其答案来构建响应。对于每个文档,它将所有非文档输入、当前文档和最新的中间答案传递给 LLM 链,以获得新的答案。

可以通过指定 chain_type="refine" 来轻松运行此链。

chain = load_summarize_chain(llm, chain_type="refine")
chain.run(split_docs)
    'GPT-Engineer 项目旨在创建一个用于特定自然语言指定任务的代码存储库。它将任务分解为较小的组件,并在需要时向用户寻求澄清。该项目强调将架构的每个细节都实现为代码,并提供有关文件组织、代码结构和依赖项的指南。然而,长期规划和任务分解以及自然语言界面的可靠性存在挑战。系统的通信带宽有限,并且在面对意外错误时很难调整计划。模型输出的可靠性值得怀疑,因为可能会出现格式错误和叛逆行为。对话还包括编写代码的说明,包括布置核心类、函数和方法,并以 markdown 代码块格式提供代码。提醒用户确保代码完全功能,并遵循文件命名、导入和类型的最佳实践。该项目由 LLM(Large Language Models)驱动,并结合了来自各种研究论文的提示技术。'

还可以提供提示并返回中间步骤。

prompt_template = """对以下内容写一个简洁的摘要:
{text}
简洁摘要:"""
prompt = PromptTemplate.from_template(prompt_template)

refine_template = (
"你的任务是生成一个最终摘要\n"
"我们已经提供了一个现有摘要,直到某个特定点:{existing_answer}\n"
"我们有机会优化现有摘要(仅在需要时)通过下面的一些更多的上下文。\n"
"------------\n"
"{text}\n"
"------------\n"
"根据新的上下文,优化原始摘要\n"
"如果上下文没有用处,返回原始摘要。"
)
refine_prompt = PromptTemplate.from_template(refine_template)
chain = load_summarize_chain(
llm=llm,
chain_type="refine",
question_prompt=prompt,
refine_prompt=refine_prompt,
return_intermediate_steps=True,
input_key="input_documents",
output_key="output_text",
)
result = chain({"input_documents": split_docs}, return_only_outputs=True)
print(result["output_text"])
    '本文讨论了使用 LLM(large language model)作为核心控制器构建自主代理的概念。文章探讨了由 LLM 驱动的代理系统的不同组件,包括规划、记忆和工具使用。它还提供了一些概念验证演示的示例,并强调了 LLM 作为通用问题解决器的潜力。此外,还介绍了 Chain of Thought、Tree of Thoughts、LLM+P、ReAct 和 Reflexion 等方法,这些方法使自主代理能够进行规划、自省和迭代改进。然而,与上下文长度、长期规划和任务分解相关的挑战仍然存在。此外,LLM 与记忆和工具等外部组件之间的自然语言界面的可靠性是不确定的。尽管如此,将 LLM 用作将请求路由到最合适的专家模块的架构已被提出作为神经符号化代理的架构在 MRKL 系统中。文章引用了多篇深入研究该主题的论文,包括 Chain of Thought、Tree of Thoughts、LLM+P、ReAct、Reflexion 和 MRKL Systems。'
print("\n\n".join(result["intermediate_steps"][:3]))
    '本文讨论了使用 LLM(large language model)作为核心控制器构建自主代理的概念。文章探讨了由 LLM 驱动的代理系统的不同组件,包括规划、记忆和工具使用。它还提供了一些概念验证演示的示例,并强调了 LLM 作为通用问题解决器的潜力。'

'Questo articolo discute del concetto di costruire agenti autonomi utilizzando LLM (large language model) come controller principale. L'articolo esplora i diversi componenti di un sistema di agenti alimentato da LLM, inclusa la pianificazione, la memoria e l'uso degli strumenti. Vengono anche forniti esempi di dimostrazioni di proof-of-concept e si evidenzia il potenziale di LLM come risolutore generale di problemi.'

'Questo articolo discute del concetto di costruire agenti autonomi utilizzando LLM (large language model) come controller principale. L'articolo esplora i diversi componenti di un sistema di agenti alimentato da LLM, inclusa la pianificazione, la memoria e l'uso degli strumenti. Vengono anche forniti esempi di dimostrazioni di proof-of-concept e si evidenzia il potenziale di LLM come risolutore generale di problemi. Il nuovo contesto riguarda l'approccio Chain of Hindsight (CoH) che permette al modello di migliorare autonomamente i propri output attraverso un processo di apprendimento supervisionato. Viene anche presentato l'approccio Algorithm Distillation (AD) che applica lo stesso concetto alle traiettorie di apprendimento per compiti di reinforcement learning.'