目录
前言
LangChain给自身的定位是:用于开发由大语言模型支持的应用程序的框架。它的做法是:通过提供标准化且丰富的模块抽象,构建大语言模型的输入输出规范,利用其核心概念chains,灵活地连接整个应用开发流程。 这里是LangChain系列的第四篇,主要介绍LangChain的Chain模块。
一、LangChain
1-1、介绍
LangChain是一个框架,用于开发由大型语言模型(LLM)驱动的应用程序。
LangChain 简化了 LLM 应用程序生命周期的每个阶段:
开发:使用LangChain的开源构建块和组件构建应用程序。使用第三方集成和模板开始运行。生产化:使用 LangSmith 检查、监控和评估您的链条,以便您可以自信地持续优化和部署。部署:使用 LangServe 将任何链转换为 API。
总结:LangChain是一个用于开发由LLM支持的应用程序的框架,通过提供标准化且丰富的模块抽象,构建LLM的输入输出规范,主要是利用其核心概念chains,可以灵活地链接整个应用开发流程。(即,其中的每个模块抽象,都是源于对大模型的深入理解和实践经验,由许多开发者提供出来的标准化流程和解决方案的抽象,再通过灵活的模块化组合,才得到了langchain)

1-2、LangChain抽象出来的核心模块
想象一下,如果要组织一个AI应用,开发者一般需要?
提示词模板的构建,不仅仅只包含用户输入!模型调用与返回,参数设置,返回内容的格式化输出。知识库查询,这里会包含文档加载,切割,以及转化为词嵌入(Embedding)向量。其他第三方工具调用,一般包含天气查询、Google搜索、一些自定义的接口能力调用。记忆获取,每一个对话都有上下文,在开启对话之前总得获取到之前的上下文吧?
由上边的内容,引出LangChain抽象的一些核心模块:
LangChain通过模块化的方式去高级抽象LLM在不同场景下的能力,其中LangChain抽象出的最重要的核心模块如下:‘
Model I/O :标准化各个大模型的输入和输出,包含输入模版,模型本身和格式化输出;Retrieval :检索外部数据,然后在执行生成步骤时将其传递到 LLM,包括文档加载、切割、Embedding等;Chains :链条,LangChain框架中最重要的模块,链接多个模块协同构建应用,是实际运作很多功能的高级抽象;Memory : 记忆模块,以各种方式构建历史信息,维护有关实体及其关系的信息;Agents : 目前最热门的Agents开发实践,未来能够真正实现通用人工智能的落地方案;Callbacks :回调系统,允许连接到 LLM 应用程序的各个阶段。用于日志记录、监控、流传输和其他任务;
1-3、特点
LangChain的特点如下:
大语言模型(llm): LangChain为自然语言处理提供了不同类型的模型,这些模型可用于处理非结构化文本数据,并且可以基于用户的查询检索信息
PromptTemplates: 这个特征使开发人员能够使用多个组件为他们的模型构造输入提示。在查询时,开发人员可以使用PromptTemplates为用户查询构造提示模板,之后模板会传递到大模型进行进一步的处理。
链:在LangChain中,链是一系列模型,它们被连接在一起以完成一个特定的目标。聊天机器人应用程序的链实例可能涉及使用LLM来理解用户输入,使用内存组件来存储过去的交互,以及使用决策组件来创建相关响应。
agent: LangChain中的agent与用户输入进行交互,并使用不同的模型进行处理。Agent决定采取何种行动以及以何种顺序来执行行动。例如,CSV Agent可用于从CSV文件加载数据并执行查询,而Pandas Agent可用于从Pandas数据帧加载数据并处理用户查询。可以将代理链接在一起以构建更复杂的应用程序。

1-4、langchain解决的一些行业痛点
在使用大模型的过程中,一些行业痛点:
大模型的使用规范以及基于大模型的开发范式不尽相同,当使用一个新模型时,我们往往需要学习新的模型规范。大模型知识更新的滞后性大模型的外部API调用能力大模型输出的不稳定问题,如何稳定输出?大模型与私有化数据的连接方式?
1-5、安装
二、Chain模块
2-1、介绍
LangChain的chain模块是其框架中用于构建智能对话和任务式应用的核心组件之一,主要负责流程控制和数据传递。以下是chain模块的一些详细介绍:
流程控制:Chains是LangChain中的核心流程控制单元,它们负责串联不同的组件和步骤,定义应用程序的执行逻辑。数据传递:Chains可以传递上下文和数据,使得不同的模块之间能够共享信息。组合与嵌套:Chains支持嵌套和组合,可以构建复杂的流程,例如顺序执行、条件判断和循环等。可重用性:Chains可以被定义为可重用的模块,在不同的应用场景中复用。灵活性:LangChain支持多种类型的Chains,如简单链、索引链、对话链等,以满足不同的需求。
链的创建与组合:
单一链:开发者可以创建一个包含特定功能的单一链,例如文本预处理、模型推理等。自定义链:利用内置的基础链类,开发者可以自定义链的输入、输出和处理逻辑。顺序组合:将多个链按照执行顺序串联起来,前一个链的输出作为下一个链的输入。并行组合:同时执行多个链,将它们的输出合并或选择性地使用。嵌套链:在一个链的内部调用另一个链,实现更复杂的流程控制
核心链类型:
LLMChain:与大型语言模型(LLMs)直接交互的链,用于生成和理解自然语言SimpleSequentialChain:一个简单的顺序执行链,用于按顺序执行一系列步骤SequentialChain:一个顺序链,可以包含多个步骤,每个步骤可以是另一个链RouterChain:用于智能路由决策,根据输入决定执行哪个链TransformChain:用于数据处理,可以对输入数据进行转换或处理
通过这些链的组合和嵌套,LangChain框架能够实现复杂的自然语言处理应用程序,提供高度的扩展性和可维护性
2-2、LLMChain
LLMChain 是 LangChain 中最简单的链,作为其他复杂 Chains 和 Agents 的内部调用,被广泛应用。一个LLMChain由PromptTemplate和语言模型(LLM or Chat Model)组成。它使用直接传入(或 memory 提供)的 key-value 来规范化生成 Prompt Template(提示模板),并将生成的 prompt (格式化后的字符串)传递给大模型,并返回大模型输出。
案例如下:- from langchain_community.chat_models import ChatZhipuAI
- from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
- from langchain.chains import LLMChain
- from langchain.prompts import PromptTemplate
- import os
- os.environ["ZHIPUAI_API_KEY"]=""
- chat = ChatZhipuAI(
- model="glm-4",
- temperature=0.5,)
- prompt = PromptTemplate(
- input_variables=["product"],
- template="给制造{product}的有限公司取10个好名字,并给出完整的公司名称",)
- chain = LLMChain(llm=chat, prompt=prompt)print(chain.invoke({'product':"性能卓越的GPU"}))
复制代码 输出:

设置chain.verbose =True可以给出中间推理过程。

2-3、Sequential Chain(顺序链)
SequentialChain是一种链(Chain)类型,用于定义一系列步骤或组件,这些步骤或组件将按顺序执行。SequentialChain的核心功能是将多个处理步骤串联起来,使得每一步的输出成为下一步的输入,从而形成一个有序的执行流程。顺序链(Sequential Chain )允许用户连接多个链并将它们组合成执行特定场景的流水线(Pipeline)。有两种类型的顺序链:
SimpleSequentialChain:最简单形式的顺序链,每个步骤都具有单一输入/输出,并且一个步骤的输出是下一个步骤的输入。SequentialChain:更通用形式的顺序链,允许多个输入/输出。
SimpleSequentialChain-Demo: 包含参数chains以及参数verbose
chains:列表,包含了要顺序执行的链。前边链的输出作为后边链的输入。verbose:用于控制链的执行是否应该输出详细的日志信息。当设置为 True 时,链在执行过程中会打印出更多的信息,这有助于调试和监控链的执行状态。
- from langchain.llms import OpenAI
- from langchain.chains import LLMChain
- from langchain.prompts import PromptTemplate
- os.environ["ZHIPUAI_API_KEY"]=""
- llm = ChatZhipuAI(
- model="glm-4",
- temperature=0.5,)
- template ="""You are a playwright. Given the title of play, it is your job to write a synopsis for that title.
- Title: {title}
- Playwright: This is a synopsis for the above play:"""
- prompt_template = PromptTemplate(input_variables=["title"], template=template)
- synopsis_chain = LLMChain(llm=llm, prompt=prompt_template)
- template ="""You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.
- Play Synopsis:
- {synopsis}
- Review from a New York Times play critic of the above play:"""
- prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
- review_chain = LLMChain(llm=llm, prompt=prompt_template)from langchain.chains import SimpleSequentialChain
- overall_chain = SimpleSequentialChain(chains=[synopsis_chain, review_chain], verbose=True)
- review = overall_chain.run("Tragedy at sunset on the beach")
复制代码 输出:


SequentialChain-Demo: 通用顺序链,包含多个输入以及输出。参数包括:chains、input_variables、output_variables、verbose
chains: 这是一个列表,包含了要顺序执行的子链。在这个例子中,synopsis_chain 和 review_chain 被包含在列表中,意味着这两个链将按顺序执行。input_variables: 这是一个列表,定义了这个链的输入变量。在这个例子中,SequentialChain 期望接收两个输入变量:era 和 title。这些变量将被传递给链中的第一个子链,通常是用于初始化或配置子链的参数。output_variables: 这是一个列表,定义了这个链的输出变量。在这个例子中,SequentialChain 将返回两个输出变量:synopsis 和 review。这些输出变量分别对应于 synopsis_chain 和 review_chain 的输出,表示这个链的最终结果。verbose: 这是一个布尔值参数,用于控制链的执行是否应该输出详细的日志信息。当设置为 True 时,链在执行过程中会打印出更多的信息,这有助于调试和监控链的执行状态。
- from langchain.llms import OpenAI
- from langchain.chains import LLMChain
- from langchain.prompts import PromptTemplate
- os.environ["ZHIPUAI_API_KEY"]=""
- llm = ChatZhipuAI(
- model="glm-4",
- temperature=0.5,)
- template ="""You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.
- Title: {title}
- Era: {era}
- Playwright: This is a synopsis for the above play:"""
- prompt_template = PromptTemplate(input_variables=["title",'era'], template=template)
- synopsis_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="synopsis")
- template ="""You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.
- Play Synopsis:
- {synopsis}
- Review from a New York Times play critic of the above play:"""
- prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)
- review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review")from langchain.chains import SequentialChain
- overall_chain = SequentialChain(
- chains=[synopsis_chain, review_chain],
- input_variables=["era","title"],# Here we return multiple variables
- output_variables=["synopsis","review"],
- verbose=True)
- overall_chain({"title":"Tragedy at sunset on the beach","era":"Victorian England"})
复制代码 输出:


SequentialChain与SimpleSequentialChain相比,重要的是定义好中间的输入变量以及输出变量(input_variables、output_variables),方便后续输出
2-4、Router Chain
RouterChain: 是LangChain框架中的一个组件,用于构建可以根据输入动态选择下一个执行链条的系统。它主要包含两个部分:RouterChain本身和destination_chains(目标链)。RouterChain负责选择下一个要调用的链条,而destination_chains是RouterChain可以路由到的链条集合
以下是RouterChain的一些关键特点和用途:
动态路由:RouterChain可以根据用户的输入动态选择最合适的处理链条来执行任务。这种动态选择机制使得系统能够更加灵活地处理不同类型的请求。多链条集成:RouterChain可以与多个destination_chains(目标链)一起工作,每个目标链都是一个专门处理特定类型任务的链条。例如,在一个问答系统中,RouterChain可以根据问题的主题将问题路由到不同的专家链条,如物理、数学等。灵活性和扩展性:通过RouterChain,开发者可以轻松地添加或修改destination_chains,从而扩展系统的功能。这种设计使得系统能够适应不断变化的需求和新的应用场景。LLMRouterChain:LangChain提供了LLMRouterChain,这是一种特殊的RouterChain,它使用大型语言模型(LLM)来确定如何路由输入。通过Prompt的形式,LLMRouterChain可以让大语言模型根据用户的输入来选择最合适的destination_chain。MultiPromptChain:这是一种特殊的RouterChain,它可以根据给定的问题选择最相关的提示,并使用该提示回答问题。MultiPromptChain包含router_chain和destination_chains,以及一个默认链default_chain,用于处理无法路由到特定destination_chain的情况。EmbeddingRouterChain:另一种RouterChain,它通过向量搜索的方式,将用户输入映射到最相关的destination_chain。
1、构建目标链 destination_chains: 即RouterChain可以路由到的链条集合。这里创建了一个默认的对话链ConversationChain ,在没有合适chain的情况下,会选择使用默认对话链。- from langchain.chains.router import MultiPromptChain
- from langchain.llms import OpenAI
- from langchain.chains import ConversationChain
- from langchain.chains.llm import LLMChain
- from langchain.prompts import PromptTemplate
- from langchain_community.chat_models import ChatZhipuAI
- physics_template ="""You are a very smart physics professor.
- You are great at answering questions about physics in a concise and easy to understand manner.
- When you don't know the answer to a question you admit that you don't know.
- Here is a question:
- {input}"""
- math_template ="""You are a very good mathematician. You are great at answering math questions.
- You are so good because you are able to break down hard problems into their component parts,
- answer the component parts, and then put them together to answer the broader question.
- Here is a question:
- {input}"""# 主要构建物理、数学两条链,所以这里先构建了相关信息,用于下边构建目标链。
- prompt_infos =[{"name":"physics","description":"Good for answering questions about physics","prompt_template": physics_template,},{"name":"math","description":"Good for answering math questions","prompt_template": math_template,},]
- os.environ["ZHIPUAI_API_KEY"]=""
- llm = ChatZhipuAI(
- model="glm-4",
- temperature=0.5,)# 创建一个空的目标链字典,用于存放根据prompt_infos生成的LLMChain。
- destination_chains ={}# 遍历prompt_infos列表,为每个信息创建一个LLMChain。for p_info in prompt_infos:
- name = p_info["name"]# 提取名称
- prompt_template = p_info["prompt_template"]# 提取模板# 创建PromptTemplate对象
- prompt = PromptTemplate(template=prompt_template, input_variables=["input"])# 使用上述模板和llm对象创建LLMChain对象
- chain = LLMChain(llm=llm, prompt=prompt)# 将新创建的chain对象添加到destination_chains字典中
- destination_chains[name]= chain
- # 创建一个默认的ConversationChain
- default_chain = ConversationChain(llm=llm, output_key="text")
复制代码 输出:

2、使用LLMRouterChain实现条件判断:
destinations_str: 将destinations列表中的所有元素用换行符连接成一个字符串,用于构建路由提示模板。RouterOutputParser:用于解析路由链的输出。MULTI_PROMPT_ROUTER_TEMPLATE:一个预定义的用于构建路由提示的模板。
- from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
- from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE
- destinations =[f"{p['name']}: {p['description']}"for p in prompt_infos]
- destinations_str ="\n".join(destinations)
- router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
- router_prompt = PromptTemplate(
- template=router_template,
- input_variables=["input"],
- output_parser=RouterOutputParser(),)
- router_chain = LLMRouterChain.from_llm(llm, router_prompt)
- chain = MultiPromptChain(
- router_chain=router_chain,
- destination_chains=destination_chains,
- default_chain=default_chain,
- verbose=True,)print(chain.run("What is black body radiation?"))
复制代码 输出:

总结:
1、 用户输入一个问题。
2、 router_chain使用router_prompt处理用户的输入,并根据输出决定将问题路由到哪个destination_chain。
3、 根据router_chain的路由结果,MultiPromptChain将问题发送到相应的destination_chain进行处理。
4、 destination_chain处理问题并生成答案。
5、 如果router_chain无法确定合适的destination_chain,问题将被发送到default_chain进行处理。
这个系统允许根据用户的输入动态选择最合适的处理链,提高了系统的灵活性和准确性。同时,verbose参数可以帮助开发者调试和监控系统的执行过程。
2-4、Transform Chain
Transform Chain: 主要用于对数据进行转换处理,然后再将转换后的结果输出给后续的处理链。
参考文章:
langchain_community.utilities.sql_database.SQLDatabase
[url=https://python.langchain.com.cn/docs/modules/agents/toolkits/json]LangChain |