LangChain框架的核心是“链(Chains)”的概念 —— 一系列按特定顺序执行任务的相互连接的组件。但这些链(Chains)到底是什么,它们又是如何提升语言模型的能力的呢?在本文中,我们将深入 LangChain 的世界,探索其核心概念、基础链类型和实际应用。
从将复杂任务分解为可管理的步骤到在多次调用间保持上下文,LangChain 提供了一个强大的框架来构建复杂的语言应用程序。
一、什么是 LangChain 中的链?
用一句话来说:链是一个端到端的包装器,包含多个单独组件按定义的顺序执行。
链是 LangChain 的核心概念之一。链允许超越对语言模型的单个 API 调用,而是将多个调用逻辑地串联起来。这样,允许开发人员组合多个组件来创建一个连贯的应用程序。
使用链的一些原因包括:
将复杂任务分解为可以由不同模型或工具顺序处理的较小步骤。这允许我们利用不同系统的不同优势。
在调用间添加状态和内存。一个调用的输出可以作为下一个调用的输入,以提供上下文和状态。
在调用间添加额外的处理、过滤或验证逻辑。
更容易地调试和检测一系列调用。
二、LangChain 中的基础链类型
LLMChain、RouterChain、SimpleSequentialChain 和 TransformChain 被认为是许多其他更复杂链的基础构建块。它们提供了基本的模式,如串联大语言模型、条件逻辑、顺序工作流和数据转换。
LLMChain:串联对大语言模型的多个调用,适用于分解复杂提示。
RouterChain:允许基于逻辑条件性地路由到不同的链,启用分支逻辑。
SimpleSequentialChain:顺序串联多个链,适用于线性工作流。
TransformChain:在链间应用数据转换,有助于数据整理和预处理。
其他关键链类型如 Agents 和 RetrievalChain 在这些基础上构建,以实现更高级的用例,如目标导向的对话和基于知识的生成。
然而,这四个基础提供了 LangChain 中链构造的基本模式。
三、LLMChain
最常用的链类型是 LLMChain。
LLMChain 由一个提示模板、一个大语言模型和一个可选的输出解析器组成。例如,可以创建一个链,它接收用户输入,用提示模板格式化它,然后将格式化后的响应传递给一个大语言模型。可以通过组合多个链,或将链与其他组件组合来构建更复杂的链。
使用 LLMChain 与直接向大语言模型传递提示的主要区别在于:
LLMChain 允许将多个提示串联在一起,而直接传递提示只允许一个。使用 LLMChain,可以将复杂提示分解为多个更简单的提示并将它们串联起来。
LLMChain 在提示间保持状态和内存。一个提示的输出可以作为下一个提示的输入来提供上下文。直接传递提示缺乏这种记忆。
LLMChain 使得在提示间添加预处理逻辑、验证和检测更容易。这有助于调试和质量控制。
LLMChain 提供了一些便利方法,如 apply 和 generate,使运行链变得简单。
四、创建一个 LLMChain
要创建一个 LLMChain,需要指定:
要使用的语言模型
提示模板
这段代码定义了一个提示模板,并使用 OpenAI 模型创建了一个 LLMChain 实例。通过调用 LLMChain 并传入具体参数,可以获得生成的有趣短故事。
代码示例如下:
from langchain import PromptTemplate, OpenAI, LLMChain# 初始化 OpenAI 模型llm = OpenAI(temperature=0)# 定义提示模板prompt_template = "像一个喜剧演员一样,写一个超级有趣的两句关于{thing}的短篇故事?"# 创建 LLM 链llm_chain = LLMChain( llm=llm, prompt=PromptTemplate.from_template(prompt_template))# 调用 LLM 链并传入具体参数result = llm_chain("一个小孩把他爸爸的笔记本电脑藏了起来")print(result)
执行上述代码,会产生如下提示信息:
LangChainDeprecationWarning: The class `LLMChain` was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use RunnableSequence, e.g., `prompt | llm` instead.
意思是类 LLMChain 在LangChain 0.1.17中已弃用,并将在1.0中删除。
输出结果:
使用新版的LangChain 0.2.x 框架,可以使用如下示例代码:
from langchain_core.prompts import PromptTemplatefrom langchain_openai import ChatOpenAI# 初始化 ChatOpenAI 模型llm = ChatOpenAI(model_name=OPENAI_MODEL, temperature=0)# 定义提示模板prompt_template = "像一个喜剧演员一样,写一个超级有趣的两句关于{thing}的短篇故事?"prompt = PromptTemplate.from_template(prompt_template)# 创建 LLM 链llm_chain = prompt | llm# 调用 LLM 链并传入具体参数result = llm_chain.invoke("一个小孩把他爸爸的笔记本电脑藏了起来")print(result)
输出结果:
代码说明:
(1)导入必要的库:
PromptTemplate:用于定义提示模板。
ChatOpenAI:用于初始化 ChatOpenAI 模型。
(2)初始化 ChatOpenAI 模型:
llm = ChatOpenAI(model_name=OPENAI_MODEL, temperature=0):创建一个 ChatOpenAI 模型实例,设置模型名称为 OPENAI_MODEL,温度为 0,以获得更确定性的输出。
(3)定义提示模板:
prompt_template:定义一个提示模板字符串,内容为 "像一个喜剧演员一样,写一个超级有趣的两句关于{thing}的短篇故事?"。其中 {thing} 是占位符,将在后续调用中替换为具体参数。
prompt = PromptTemplate.from_template(prompt_template):使用 PromptTemplate 类从模板字符串创建提示模板对象。
(4)创建 LLM 链:
llm_chain = prompt | llm:使用管道符号 (|) 创建一个 LLM 链,将提示模板和 ChatOpenAI 模型连接起来。
(5)调用 LLM 链并传入具体参数:
result = llm_chain.invoke("一个小孩把他爸爸的笔记本电脑藏了起来"):调用 llm_chain 的 invoke 方法,并传入具体参数 "一个小孩把他爸爸的笔记本电脑藏了起来",获取生成的结果。
print(result):打印生成的结果。
这段代码定义了一个提示模板,并使用 ChatOpenAI 模型创建了一个 LLM 链。通过调用 llm_chain.invoke 并传入具体参数,可以获得生成的有趣短故事。
当有一个输入列表并希望让大语言模型为每个输入生成文本时,它将为列表中的每个输入字典运行 LLMChain 并返回一个输出列表。
五、批处理
首先,在批量中,如果你需要提出多个问题或命令,可以通过将提示列表保存在 Python 列表中,然后使用批量调用,而不是循环。
这段代码的目的是批量处理一系列文本输入项,并展示每个输入项对应的处理结果。
# 输入列表input_list = [ {"thing": "女生喜欢大叔"}, {"thing": "失明的眼科医生"}, {"thing": "一个不会做数学的数据科学家"}]# 调用 batch 方法outputs = llm_chain.batch(input_list)# 遍历 outputs 列表,该列表包含了 batch 方法对每个输入项的处理结果for index, output in enumerate(outputs): # 使用 enumerate 函数获取索引和值,并将索引转换为从1开始的序号,以便与输入列表的序号对应 print(f"Input {index + 1}: {input_list[index]['thing']}") print(f"Output: {output} ")
llm_chain.batch(input_list)这行代码调用了llm_chain对象的batch方法,并传入input_list作为参数。这个batch方法是用来批量处理input_list中的每一个输入项(即每个字典中的'thing'值)。
输出结果: