目录
- 前言
- 一、LangChain
- 1-1、介绍
- 1-2、LangChain抽象出来的核心模块
- 1-3、特点
- 1-4、langchain解决的一些行业痛点
- 1-5、安装
- 二、Chain模块
- 2-1、介绍
- 2-2、LLMChain
- 2-3、Sequential Chain(顺序链)
- 2-4、Router Chain
- 总结
前言
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、安装
pip install langchain
二、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参数可以帮助开发者调试和监控系统的执行过程。
参考文章:
langchain_community.utilities.sql_database.SQLDatabase
LangChain 🦜️🔗 中文网,跟着LangChain一起学LLM/GPT开发
LangChain官网
Rebuff: 防止提示词注入检测器
未完成:
Build a Question/Answering system over SQL data
langchain101 AI应用开发指南
总结
今天下大雨🤕