【AI大模型应用开发】【LangChain系列】实战案例6:利用大模型进行文本总结的方法探索,文本Token超限怎么办?

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
简介: 【AI大模型应用开发】【LangChain系列】实战案例6:利用大模型进行文本总结的方法探索,文本Token超限怎么办?
  • 大家好,我是同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:


假设有一组文档(PDF、Notion页面、客户问题等),你想要总结内容。可以利用大模型来帮你。今天来系统看下利用大模型来对文本进行总结的方法,以LangChain的使用为例。

参考:https://python.langchain.com/docs/use_cases/summarization

0. 方法概述

在利用大模型总结文本的过程中,最主要的工作是如何将文档内容传递给大模型。目前有两种常见的方法:

  1. Stuff方法:简单地将所有文档“填充”到单个提示中。这种方法的主要优点是简单,但缺点是当文档很长或数量很多时,可能会超出模型的上下文窗口限制,导致信息丢失或模型性能下降。
  2. Map-reduce方法:这种方法分为两步。首先,在“map”步骤中,单独对每个文档进行摘要。然后,在“reduce”步骤中,将这些摘要合并成一个最终摘要。这种方法的主要优点是它可以处理大量或长文档,因为它在合并之前先对它们进行了压缩。但是,这种方法可能需要额外的逻辑来确保在“reduce”步骤中生成的最终摘要是有意义和连贯的。

1. 实操练习

1.1 快速开始

1.1.1 代码示例

from langchain.chains.summarize import load_summarize_chain
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import ChatOpenAI
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
docs = loader.load()
llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-1106")
chain = load_summarize_chain(llm, chain_type="stuff")
result = chain.run(docs)
print(result)

代码示例中,使用了 LangChain 的 load_summarize_chain 来总结文本,chain_type="stuff" 表明采用 Stuff 方式。后面会给大家展示load_summarize_chain的部分实现。

1.1.2 运行一下

运行结果如下:

1.2 Stuff方法

这种方法就是直接将全部文本塞给大模型,让大模型直接总结。

1.2.1 StuffDocumentsChain

在上面的示例代码中,我们使用 load_summarize_chain 时,传入的 chain_type="stuff" ,其实底层用的是 LangChain 中的 StuffDocumentsChain

看下直接 StuffDocumentsChain 的使用示例:

from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate
# Define prompt
prompt_template = """Write a concise summary of the following:
"{text}"
CONCISE SUMMARY:"""
prompt = PromptTemplate.from_template(prompt_template)
# Define LLM chain
llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k")
llm_chain = LLMChain(llm=llm, prompt=prompt)
# Define StuffDocumentsChain
stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name="text")
docs = loader.load()
print(stuff_chain.run(docs))

Prompt很简单,一眼就能看出其工作原理,它就是将docs全部扔给了大模型,让大模型给出一个简要的总结:

prompt_template = """Write a concise summary of the following:
"{text}"
CONCISE SUMMARY:"""

1.3 Map-Reduce方法

首先使用LLMChain将每个文档映射到一个单独的摘要。然后,使用ReduceDocumentsChain将这些摘要合并为一个全局摘要。

1.3.1 代码示例

1.3.1.1 文本分块
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=1000, chunk_overlap=0
)
split_docs = text_splitter.split_documents(docs)
1.3.1.2 对分块文本的总结Chain
# Map
map_template = """The following is a set of documents
{docs}
Based on this list of docs, please identify the main themes 
Helpful Answer:"""
map_prompt = PromptTemplate.from_template(map_template)
map_chain = LLMChain(llm=llm, prompt=map_prompt)

重点看Prompt,给定一个文档列表,根据这个文档列表,识别出主题思想。

来看下其执行的结果(输入分割后的一段文本,输出这段文本的主题思想。每段文本都调用一次大模型,执行一次该操作,所以,注意你的API KEY的次数消耗…):

1.3.1.3 ReduceDocumentsChain

有了上面分块的总结,下面的步骤就是根据分块总结合并成一条完整的总结。在LangChain中可以使用 ReduceDocumentsChain 类来实现此步骤。

# Reduce
reduce_template = """The following is set of summaries:
{docs}
Take these and distill it into a final, consolidated summary of the main themes. 
Helpful Answer:"""
reduce_prompt = PromptTemplate.from_template(reduce_template)
# Run chain
reduce_chain = LLMChain(llm=llm, prompt=reduce_prompt, verbose=True)
# Takes a list of documents, combines them into a single string, and passes this to an LLMChain
combine_documents_chain = StuffDocumentsChain(
    llm_chain=reduce_chain, document_variable_name="docs", verbose=True
)
# Combines and iteratively reduces the mapped documents
reduce_documents_chain = ReduceDocumentsChain(
    # This is final chain that is called.
    combine_documents_chain=combine_documents_chain,
    # If documents exceed context for `StuffDocumentsChain`
    collapse_documents_chain=combine_documents_chain,
    # The maximum number of tokens to group documents into.
    token_max=4000,
    verbose=True
)

从代码中可以看到,ReduceDocumentsChain 设置了4个参数,我们分别来解释下。

  • combine_documents_chain:这是最终执行总结的Chain。它的值为 combine_documents_chain。而 combine_documents_chain 定义为一个 StuffDocumentsChain 类型的Chain,也就是简单地将前面分块总结的内容塞给大模型,让它根据分块总结再汇总总结一次。
  • collapse_documents_chain:这个Chain的作用,是来处理塞给大模型的Token超限的情况。如果文本特别多,分块特别多,那分块总结出来的东西也会非常多。单纯的将分块总结内容合并在一起,还是很有可能超过大模型上下文窗口限制。这个Chain,会按设置的最大Token数将内容再次拆分,然后再利用 StuffDocumentsChain 进行分块总结,直到最终各分块总结合并起来能一次塞给大模型才停止。

这是个递归分割总结的过程,注意Token或者调用次数的消耗,都是钱啊…

  • token_max:最大Token数,超过这个Token数执行上面的collapse_documents_chain
  • verbose:开详细日志

来直观感受下它的运行(合并分块总结内容作为输入,输出最终总结结果):

本例中分块总结文本合并后没有超限,所以没用到 collapse_documents_chain

1.3.1.4 Map-Reduce组合Chain: MapReduceDocumentsChain
# Combining documents by mapping a chain over them, then combining results
map_reduce_chain = MapReduceDocumentsChain(
    # Map chain
    llm_chain=map_chain,
    # Reduce chain
    reduce_documents_chain=reduce_documents_chain,
    # The variable name in the llm_chain to put the documents in
    document_variable_name="docs",
    # Return the results of the map steps in the output
    return_intermediate_steps=False,
    verbose=True
)

1.3.2 运行及结果

print(map_reduce_chain.run(split_docs))

2. 部分源码

(1)ReduceDocumentsChain 中,如果Token超限的处理:collapse_documents_chain,直接一个 while 循环压缩Token数。

(2)load_summarize_chain 的封装,在1.1中我们使用了 chain_type = "stuff",它其实也可以使用 “map_reduce” 或 “refine”。

如果chain_type设置为map_reduce,看它的源码,跟我们1.3节中的代码几乎一样。load_summarize_chain 就是对这几种方法的高层封装!

def _load_map_reduce_chain(
    llm: BaseLanguageModel,
    map_prompt: BasePromptTemplate = map_reduce_prompt.PROMPT,
    combine_prompt: BasePromptTemplate = map_reduce_prompt.PROMPT,
    combine_document_variable_name: str = "text",
    map_reduce_document_variable_name: str = "text",
    collapse_prompt: Optional[BasePromptTemplate] = None,
    reduce_llm: Optional[BaseLanguageModel] = None,
    collapse_llm: Optional[BaseLanguageModel] = None,
    verbose: Optional[bool] = None,
    token_max: int = 3000,
    callbacks: Callbacks = None,
    *,
    collapse_max_retries: Optional[int] = None,
    **kwargs: Any,
) -> MapReduceDocumentsChain:
    map_chain = LLMChain(
        llm=llm, prompt=map_prompt, verbose=verbose, callbacks=callbacks
    )
    _reduce_llm = reduce_llm or llm
    reduce_chain = LLMChain(
        llm=_reduce_llm, prompt=combine_prompt, verbose=verbose, callbacks=callbacks
    )
    # TODO: document prompt
    combine_documents_chain = StuffDocumentsChain(
        llm_chain=reduce_chain,
        document_variable_name=combine_document_variable_name,
        verbose=verbose,
        callbacks=callbacks,
    )
    if collapse_prompt is None:
        collapse_chain = None
        if collapse_llm is not None:
            raise ValueError(
                "collapse_llm provided, but collapse_prompt was not: please "
                "provide one or stop providing collapse_llm."
            )
    else:
        _collapse_llm = collapse_llm or llm
        collapse_chain = StuffDocumentsChain(
            llm_chain=LLMChain(
                llm=_collapse_llm,
                prompt=collapse_prompt,
                verbose=verbose,
                callbacks=callbacks,
            ),
            document_variable_name=combine_document_variable_name,
        )
    reduce_documents_chain = ReduceDocumentsChain(
        combine_documents_chain=combine_documents_chain,
        collapse_documents_chain=collapse_chain,
        token_max=token_max,
        verbose=verbose,
        callbacks=callbacks,
        collapse_max_retries=collapse_max_retries,
    )
    return MapReduceDocumentsChain(
        llm_chain=map_chain,
        reduce_documents_chain=reduce_documents_chain,
        document_variable_name=map_reduce_document_variable_name,
        verbose=verbose,
        callbacks=callbacks,
        **kwargs,
    )

3. 总结

本文我们学习和实践了利用 LangChain 进行文本总结的两种方法,知道了其实现原理,所以,我们应该不用 LangChain的这些封装也可以自己实现一套文档总结流程。

其实,LangChain 还有其它的文档总结的Chain,例如 RefineDocumentsChain 和 AnalyzeDocumentsChain,大体原理与本文介绍的两种方式都差不多,主要是封装的差异,感兴趣的也可以去试试。

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是 同学小张,日常分享AI知识和实战案例
  • 欢迎 点赞 + 关注 👏,持续学习持续干货输出
  • 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏

本站文章一览:

相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
27天前
|
存储 人工智能 分布式计算
Parquet 文件格式详解与实战 | AI应用开发
Parquet 是一种列式存储文件格式,专为大规模数据处理设计,广泛应用于 Hadoop 生态系统及其他大数据平台。本文介绍 Parquet 的特点和作用,并演示如何在 Python 中使用 Pandas 库生成和读取 Parquet 文件,包括环境准备、生成和读取文件的具体步骤。【10月更文挑战第13天】
217 60
|
26天前
|
人工智能 资源调度 数据可视化
【AI应用落地实战】智能文档处理本地部署——可视化文档解析前端TextIn ParseX实践
2024长沙·中国1024程序员节以“智能应用新生态”为主题,吸引了众多技术大咖。合合信息展示了“智能文档处理百宝箱”的三大工具:可视化文档解析前端TextIn ParseX、向量化acge-embedding模型和文档解析测评工具markdown_tester,助力智能文档处理与知识管理。
|
1月前
|
机器学习/深度学习 人工智能 开发框架
解锁AI新纪元:LangChain保姆级RAG实战,助你抢占大模型发展趋势红利,共赴智能未来之旅!
【10月更文挑战第4天】本文详细介绍检索增强生成(RAG)技术的发展趋势及其在大型语言模型(LLM)中的应用优势,如知识丰富性、上下文理解和可解释性。通过LangChain框架进行实战演练,演示从知识库加载、文档分割、向量化到构建检索器的全过程,并提供示例代码。掌握RAG技术有助于企业在问答系统、文本生成等领域把握大模型的红利期,应对检索效率和模型融合等挑战。
159 14
|
17天前
|
机器学习/深度学习 人工智能 算法
AI赋能大学计划·大模型技术与应用实战学生训练营——吉林大学站圆满结营
10月30日,由中国软件行业校园招聘与实习公共服务平台携手魔搭社区共同举办的AI赋能大学计划·大模型技术与产业趋势高校行AIGC项目实战营·吉林大学站圆满结营。
|
1月前
|
机器学习/深度学习 数据采集 人工智能
【紧跟AI浪潮】深度剖析:如何在大模型时代精准捕获用户心声——提高召回率的实战秘籍
【10月更文挑战第5天】在深度学习领域,大型模型常面临召回率不足的问题,尤其在信息检索和推荐系统中尤为关键。本文通过具体代码示例,介绍如何提升大模型召回率。首先,利用Pandas进行数据预处理,如清洗和特征工程;其次,选择合适的模型架构,如使用PyTorch构建推荐系统;再者,优化训练策略,采用合适的损失函数及正则化技术;此外,选择恰当的评估指标,如召回率和F1分数;最后,通过后处理优化结果展示。以上方法不仅提升召回率,还增强了模型整体性能。
74 0
|
8天前
|
机器学习/深度学习 人工智能 自然语言处理
当前AI大模型在软件开发中的创新应用与挑战
2024年,AI大模型在软件开发领域的应用正重塑传统流程,从自动化编码、智能协作到代码审查和测试,显著提升了开发效率和代码质量。然而,技术挑战、伦理安全及模型可解释性等问题仍需解决。未来,AI将继续推动软件开发向更高效、智能化方向发展。
|
12天前
|
机器学习/深度学习 人工智能 自然语言处理
AI在医疗领域的应用及其挑战
【10月更文挑战第34天】本文将探讨人工智能(AI)在医疗领域的应用及其面临的挑战。我们将从AI技术的基本概念入手,然后详细介绍其在医疗领域的各种应用,如疾病诊断、药物研发、患者护理等。最后,我们将讨论AI在医疗领域面临的主要挑战,包括数据隐私、算法偏见、法规合规等问题。
35 1
|
14天前
|
存储 XML 人工智能
深度解读AI在数字档案馆中的创新应用:高效识别与智能档案管理
基于OCR技术的纸质档案电子化方案,通过先进的AI能力平台,实现手写、打印、复古文档等多格式高效识别与智能归档。该方案大幅提升了档案管理效率,确保数据安全与隐私,为档案馆提供全面、智能化的电子化管理解决方案。
114 48
|
10天前
|
机器学习/深度学习 人工智能 算法
AI在医疗领域的应用与挑战
本文探讨了人工智能(AI)在医疗领域的应用,包括其在疾病诊断、治疗方案制定、患者管理等方面的优势和潜力。同时,也分析了AI在医疗领域面临的挑战,如数据隐私、伦理问题以及技术局限性等。通过对这些内容的深入分析,旨在为读者提供一个全面了解AI在医疗领域现状和未来发展的视角。
43 10
|
10天前
|
机器学习/深度学习 人工智能 监控
探索AI在医疗领域的应用与挑战
本文深入探讨了人工智能(AI)在医疗领域中的应用现状和面临的挑战。通过分析AI技术如何助力疾病诊断、治疗方案优化、患者管理等方面的创新实践,揭示了AI技术为医疗行业带来的变革潜力。同时,文章也指出了数据隐私、算法透明度、跨学科合作等关键问题,并对未来的发展趋势进行了展望。