一架梯子,一头程序猿,仰望星空!
LangChain教程(Python版本) > 内容正文

LangChain 文本摘要任务


AI文本摘要

不同的大语言模型(LLM)对输入提示词长度限制不一样,如果我们需要对一篇上万字的文章进行摘要总结,但文章长度是又超过了模型的最大长度限制,没办法把整篇文章直接投喂给AI模型,针对这种场景LangChain也提供了一些策略和封装,本章节主要介绍LangChain如何解决文本摘要。

数据预处理

首先,我们准备测试数据。在这个例子中,我们加载一个长的文档,然后把文档切片,拆分成多个小的文档片段。

  • 提示:这里加载本地文件数据只是为了举例,你只要了解langchain如何处理长文本的方法就行,实际业务场景,你可能是从自己的数据库里面加载文档数据。
from langchain import OpenAI, PromptTemplate, LLMChain
from langchain.text_splitter import CharacterTextSplitter
from langchain.chains.mapreduce import MapReduceChain
from langchain.prompts import PromptTemplate

# 使用openai模型
llm = OpenAI(temperature=0)

# 定义文档拆分器
text_splitter = CharacterTextSplitter()
# 这里从本地的一个文件中加载一个长文本
with open("../../state_of_the_union.txt") as f:
    state_of_the_union = f.read()
# 使用前面定义的文档拆分器把长文本切割成小的文本片段,得到一个小文本片段数组
texts = text_splitter.split_text(state_of_the_union)
from langchain.docstore.document import Document

# 模拟提取我们想要投喂给AI的文档数据,这里就随便取前3个
docs = [Document(page_content=t) for t in texts[:3]]

快速开始

想要对长文本进行文本摘要最简单的办法就是使用LangChain提供的load_summarize_chain任务,执行文本摘要任务。

from langchain.chains.summarize import load_summarize_chain
# 定义文本摘要chain,就是摘要任务,注意chain_type参数,这里选择map_reduce类型
# langchain chain_type提供了四种类型,后续章节会讲解
chain = load_summarize_chain(llm, chain_type="map_reduce")
# 把前面拆分的文档片段丢给AI,让AI总结文本内容
chain.run(docs)
# AI返回的文章摘要结果,结果内容大家可以不必关心,总之就是会拿到AI返回的文本摘要结果

使用LangChain封装的文本摘要Chain执行摘要任务虽然很简单,但是如果你需要微调一些参数,请参考后面的内容,例如,上面例子使用的是内置的提示词模板,对中文不一定友好,你可以改成自己的提示词模板等等。

Chain_type参数说明

LangChain 针对Chain任务处理提示词超过大模型(LLM)token长度限制的情况,设计了4种处理方式。

chain_type 4中类型如下:

  • stuff
  • map_reduce
  • refine
  • map_rerank

stuff类型

LangChain默认类型,会把所有的 文档内容 一次全部传给 llm 模型进行总结,所以叫填充模式,如果文档内容太长,肯定会超过LLM的token限制。

map_reduce类型

这种方式是先把每一个文档片段先传给LLM模型单独总结,最后在把所有总结合并起来,再给AI归纳总结一下,这个就跟很多编程语言里面的map-reduce函数库的思想类似。

refine类型

这种方式,其实就是归纳的方式生成文本摘要,就是先将第一个文档的内容传给llm模型总结,然后把第一个文档的总结内容 + 第二个文档的内容再发给llm模型总结,以此类推,最后得到一个长文本最终的总结。

map_rerank类型

这个是用在问答任务里面,筛选出跟问题相关度高的文档片段,然后传给llm模型回答问题。

stuff 任务例子

下面是使用stuff类型对文章进行总结的例子,这种方式适合文章内容没有超过LLM的token长度限制的情况

# 就是把chain_type参数改为stuff就行
chain = load_summarize_chain(llm, chain_type="stuff")
# 把需要摘要的文档片段数组传进去,交给LLM处理
chain.run(docs)

自定义提示词

针对stuff类型,下面是自定义提示词的例子

# 自定义提示词模板
prompt_template = """总结下文内容:

{text}

总结内容:"""
# 生成提示词模板
PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
# 通过prompt参数指定我们要使用的提示词模板
chain = load_summarize_chain(llm, chain_type="stuff", prompt=PROMPT)
# 传入文档数组,发给AI模型
chain.run(docs)

map_reduce 任务例子

map_reduce对文章进行总结,当然这种方式会产生多次AI模型调用。

# 修改chain_type就行
chain = load_summarize_chain(llm, chain_type="map_reduce")

# 如果你想观察map_reduce中间多次AI调用的结果,可以设置return_intermediate_steps参数为true
# chain = load_summarize_chain(llm, chain_type="map_reduce", return_intermediate_steps=True)
chain.run(docs)

map_reduce任务自定义提示词

# 定义提示词模板
prompt_template = """总结下文内容:

{text}

总结内容:"""
# 创建提示词模板
PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
# 通过map_prompt和combine_prompt参数设置使用的提示词模板,这里设置成一样的模板,当然你也可以设置成不一样的模板
chain = load_summarize_chain(OpenAI(temperature=0), chain_type="map_reduce", return_intermediate_steps=True, map_prompt=PROMPT, combine_prompt=PROMPT)
# 执行任务
chain({"input_documents": docs}, return_only_outputs=True)

refine 任务例子

chain_type参数改为refine即可

chain = load_summarize_chain(llm, chain_type="refine")

chain.run(docs)

refine任务自定义提示词模板

下面是refine任务自定义题词的例子

# 定义单个文档的总结提示词模板
prompt_template = """总结下文内容:

{text}

总结内容:"""

PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])

# 定义refine合并总结内容的提示词模板
refine_template = (
    "你的工作是负责生成一个最终的文本摘要\n"
    "这是现有的摘要信息: {existing_answer}\n"
    "根据新的背景信息完善现有的摘要"
    "背景信息如下\n"
    "------------\n"
    "{text}\n"
    "------------\n"
    "根据背景信息,完善现有的摘要"
    "如果背景信息没有用,则返回现有的摘要信息。"
)
refine_prompt = PromptTemplate(
    input_variables=["existing_answer", "text"],
    template=refine_template,
)
# 通过question_prompt参数设置首个摘要提示词模板
# 通过refine_prompt参数设置,归纳多个文本片段的提示词模板
chain = load_summarize_chain(OpenAI(temperature=0), chain_type="refine", return_intermediate_steps=True, question_prompt=PROMPT, refine_prompt=refine_prompt)
# 执行摘要任务
chain({"input_documents": docs}, return_only_outputs=True)


关联主题