LangChain 提供了多种链类型,,构建和定制自然语言处理任务的工作流。这些链类型有助于将语言模型和其他工具整合到应用程序中,。基本上,链类型就是将一系列任务串联起来,我们将不同的任务链接起来,并将第一个任务的输出传递给下一个任务。管道操作符用于像链条一样连接每个后续任务,将输出从前一个任务传递到下一个任务。
以下是一些LangChain中的重要链路类型:
这段代码展示了如何使用LangChain,一个开源框架,来创建一个简单的流程,用于使用来自OpenAI的语言模型生成笑话的过程。下面是代码中涉及的步骤概述:
- 导入库函数
从 dotenv 导入 load_dotenv
从 langchain.prompts 导入 ChatPromptTemplate
从 langchain.schema.output_parser 导入 StrOutputParser
从 langchain_openai 导入 ChatOpenAI 作为 ChatOpenAI
2. 加载环境变量:
# 从.env文件加载环境变量
load_dotenv()
3. 初始化语言模型:
# 创建一个ChatOpenAI实例
model = ChatOpenAI(model="gpt-4o-mini") # 设置模型为 "gpt-4o-mini"
4. 定义提示模板如下:
# 定义提示模板如下(无需单独的Runnable链)
prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位喜剧演员,讲关于{topic}的笑话。"),
("human", "讲{joke_count}个关于{topic}的笑话给我听。"),
]
)
- 将链和输出解析器结合起来:
# 使用LangChain表达式语言(LCEL)构建的链,包括提示模板、模型和输出解析器。
chain = prompt_template | model | StrOutputParser()
# 仅使用提示模板和模型也可以创建链,但这里增加了输出解析器以确保输出为字符串形式。
6. 执行链条 :
# 运行这条链
result = chain.invoke({"topic": "话题", "joke_count": "笑话数量"})
7. 打印结果:
这是生成结果所需的完整代码。
从 dotenv 导入 load_dotenv()
从 langchain.prompts 导入 ChatPromptTemplate
从 langchain.schema.output_parser 导入 StrOutputParser
从 langchain.chat 导入 ChatOpenAI
# 从 .env 加载环境变量
load_dotenv()
# 创建一个 ChatOpenAI 实例
model = ChatOpenAI(model="gpt-4o-mini")
# 定义提示模板(无需单独的运行链)
prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位喜剧演员,会讲关于 {topic} 的笑话。"),
("human", "给我讲 {joke_count} 个笑话。"),
]
)
# 使用 LangChain 表达式语言 (LCEL) 创建复合链
chain = prompt_template | model | StrOutputParser()
# 运行链
result = chain.invoke({"topic": "律师", "joke_count": 3})
# 输出结果
# 输出结果
print(result)
链在底层是如何运作的?
可运行的Lambda表达式创建方法:
# 定义链中的各个可运行步骤
format_prompt = RunnableLambda(lambda x: prompt_template.format_prompt(**x))
invoke_model = RunnableLambda(lambda x: model.invoke(x.to_messages()))
parse_output = RunnableLambda(lambda x: x.content)
# 创建可运行序列(相当于LCEL链,即链式执行流程)
chain = RunnableSequence(first=format_prompt, middle=[invoke_model], last=parse_output)
它定义了三个 RunnableLambda
实例对象,每个实例对象包含着处理管道中的一个环节。
-
**format_prompt**
:使用提示模板来格式化输入。 -
**invoke_model**
:用格式化的提示来调用语言模型。 **parse_output**
:从模型的响应中解析输出。
创建可执行序列:
RunnableSequence
中的三个参数分别为:第一个参数是单个 Runnable,中间的参数是一个 Runnable 列表,最后一个参数是单个 Runnable。这些参数组合成一个 RunnableSequence
,表示要按顺序执行的操作序列。
包含上述 RunnableLambda
的完整代码已在这里实现。
从 dotenv 导入 load_dotenv
从 langchain.prompts 导入 ChatPromptTemplate
从 langchain.schema.runnable 导入 RunnableLambda, RunnableSequence
从 langchain_openai 导入 ChatOpenAI
# 从 .env 加载环境变量
load_dotenv()
# 创建 ChatOpenAI 模型
model = ChatOpenAI(model="gpt-4o-mini")
# 定义提示模板 # defining prompt template
prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位喜剧演员,讲述有关 {topic} 的笑话。"),
("human", "告诉我 {joke_count} 个笑话。"),
]
)
# 创建单独的可运行步骤
format_prompt = RunnableLambda(lambda x: prompt_template.format_prompt(**x))
invoke_model = RunnableLambda(lambda x: model.invoke(x.to_messages()))
parse_output = RunnableLambda(lambda x: x.content)
# 创建 RunnableSequence (相当于 LCEL 链)
chain = RunnableSequence(first=format_prompt, middle=[invoke_model], last=parse_output)
# 运行链
response = chain.invoke({"topic": "律师", "joke_count": 3})
# 输出
print(response)
输出结果与之前生成的代码(不含可执行部分)完全相同。
让我们仔细看看每种链类型的输出有何不同。
一、链式 — 扩展版:额外的步骤:
### 定义更多的处理步骤使用 RunnableLambda
uppercase_output = RunnableLambda(lambda x: x.upper())
count_words = RunnableLambda(lambda x: f"单词数:{len(x.split())}:\n{x}")
使用 RunnableLambda
来定义额外的处理步骤或流程:
**uppercase_output**
:将输出文本转换为全大写。**count_words**
:计算词数并在文本开头加上。
创建组合链:
# 使用LangChain表达式语言(LCEL)来创建这个组合链。
# 创建一个组合链,包括提示模板、模型、字符串输出解析器、大写输出和计词数
chain = prompt_template | model | StrOutputParser() | uppercase_output | count_words
将提示模板、模型调用、输出解析和其他处理步骤结合成单一链,使用LangChain表达语言(LCEL)进行操作。这条链按顺序对输入数据进行一系列转换处理。
启动连锁反应:
# 运行这条链
result = chain.invoke({"主题": "律师", "笑话数量": 3})
下面是一个完整的代码示例:链式类型扩展。
from dotenv import load_dotenv
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableLambda
from langchain_openai import ChatOpenAI
# 从 .env 文件加载环境变量
load_dotenv()
# 创建一个 ChatOpenAI 实例
model = ChatOpenAI(model="gpt-4o-mini")
# 定义提示模板
prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个喜剧演员,讲关于 {topic} 的笑话。"),
("human", "给我讲 {joke_count} 个笑话。"),
]
)
# 定义额外的处理步骤,使用 RunnableLambda
uppercase_output = RunnableLambda(lambda x: x.upper())
count_words = RunnableLambda(lambda x: f"字数:{len(x.split())}\n{x}")
# 使用 LangChain 表达式语言 (LCEL) 创建组合链
chain = prompt_template | model | StrOutputParser() | uppercase_output | count_words
# 运行组合链
result = chain.invoke({"topic": "律师", "joke_count": 3})
# 打印结果
print(result)
II. 链式 — 并行:
提示模板
# 定义提示模板
prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位专业的评论员。"),
("human", "列出 {product_name} 的主要特点。"),
]
)
定义了一个 ChatPromptTemplate
,用来提示模型描述指定产品的关键特征。
优点和缺点分析:
# 定义优点分析步骤
def analyze_pros(features):
pros_template = ChatPromptTemplate.from_messages(
[
("system", "请从专业评审员的角度..."),
(
"human",
"根据这些功能:{features},列举一下这些功能的优点吧。",
),
]
)
return pros_template.format_prompt(features=features)
# 定义缺点分析步骤
def analyze_cons(features):
cons_template = ChatPromptTemplate.from_messages(
[
("system", "请从专业评审员的角度..."),
(
"human",
"根据这些功能:{features},说说这些功能的缺点吧。",
),
]
)
return cons_template.format_prompt(features=features)
- 定义了两个函数
analyze_pros
和analyze_cons
,分别用于生成产品功能的优点和缺点的提示信息。
综合优缺点:
# 将优缺点合并成最终评论
def combine_pros_cons(pros, cons):
return f"好的地方:\n{pros}\n\n不好的地方:\n{cons}"
用LCEL来定义这些分支:
从langchain.schema.runnable导入RunnableLambda,RunnableParallel
从langchain.schema.output_parser导入StrOutputParser
# 使用LCEL来简化分支
pros_branch_chain = (
RunnableLambda(lambda x: analyze_pros(x)) | model | StrOutputParser()
)
cons_branch_chain = (
RunnableLambda(lambda x: analyze_cons(x)) | model | StrOutputParser()
)
- 使用LangChain表达式语言(LCEL)创建两个分支,每个分支分别使用
RunnableLambda
来应用分析函数和生成响应,并用StrOutputParser
解析模型输出,来处理各自的优势和劣势。
把所有东西连成一条链:
# 使用 LangChain 表达式语言 (LCEL) 生成组合链
chain = (
prompt_template
| model
| StrOutputParser()
| RunnableParallel(branches={"优点": pros_branch_chain, "缺点": 缺点_branch_chain})
| RunnableLambda(lambda x: 合并优点和缺点(x["branches"]["优点"], x["branches"]["缺点"])) # 将优点和缺点结合的 lambda 表达式
)
- 将初始提示、模型调用和并行处理分支整合成一个流程。使用
RunnableParallel
来并行执行正反两个分支,最后将这些结果整合成最终输出。
启动链条:
# 运行这条链
result = chain.调用({"product_name": "MacBook Pro"})
输出结果:
from dotenv import load_dotenv
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableParallel, RunnableLambda
from langchain_openai import ChatOpenAI
# 从 .env 文件中加载环境变量
load_dotenv()
# 创建一个 ChatOpenAI 模型
model = ChatOpenAI(model='gpt-4o-mini')
# 定义提示模板
prompt_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位专家级的产品评论者。"),
("human", "列出产品 {product_name} 的主要功能。"),
]
)
# 定义优点分析步骤
def analyze_pros(features):
pros_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位专家级的产品评论者。"),
(
"human",
"根据这些功能:{features},列出这些功能的优点。",
),
]
)
return pros_template.format_prompt(**{'features': features})
# 定义缺点分析步骤
def analyze_cons(features):
cons_template = ChatPromptTemplate.from_messages(
[
("system", "你是一位专家级的产品评论者。"),
(
"human",
"根据这些功能:{features},列出这些功能的缺点。",
),
]
)
return cons_template.format_prompt(**{'features': features})
# 将优点和缺点合并成最终的评论
def combine_pros_cons(pros, cons):
return f"优点:\n{pros}\n\n缺点:\n{cons}"
# 使用 LCEL 简化分支
pros_branch_chain = (RunnableLambda(lambda x: analyze_pros(x)) | model | StrOutputParser())
cons_branch_chain = (RunnableLambda(lambda x: analyze_cons(x)) | model | StrOutputParser())
# 使用 LangChain 表达式语言 (LCEL) 创建组合链
chain = (
prompt_template
| model
| StrOutputParser()
| RunnableParallel(branches={"pros": pros_branch_chain, "cons": cons_branch_chain})
| RunnableLambda(lambda x: combine_pros_cons(x['branches']['pros'], x['branches']['cons']))
)
# 运行链
result = chain.invoke({'product_name': 'MacBook Pro'})
# 输出结果
print(result) # 输出最终的评论结果
II. 链式及分支型
不同反馈类型的提示模板示例:
# 定义不同反馈类型的提示模板
positive_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是乐于助人的"),
("human",
"感谢一下这条积极的反馈:{feedback}。"),
]
)
negative_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是乐于助人的"),
("human",
"回复一下这条负面的反馈:{feedback}。"),
]
)
neutral_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是乐于助人的"),
(
"human",
"请求更多细节这条中性的反馈:{feedback}。",
),
]
)
escalate_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是乐于助人的"),
(
"human",
"将这条反馈转交给人工客服处理:{feedback}。",
),
]
)
- 定义基于不同反馈类型的模板:积极、消极、中立,还有需要上报的反馈。
反馈分类的模板:
# 定义反馈分类模板
classification_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的好助手。"),
("human",
"请将以下反馈的情感归类为正面、负面、中立或需要上报:{feedback}。"),
]
)
可执行的反馈处理方式如下:
# 定义用于处理反馈的可运行分支
branches = RunnableBranch(
(
lambda x: "positive" in x,
positive_feedback_template | model | StrOutputParser() # 积极的反馈链
),
(
lambda x: "negative" in x,
negative_feedback_template | model | StrOutputParser() # 消极的反馈链
),
(
lambda x: "neutral" in x,
neutral_feedback_template | model | StrOutputParser() # 中性的反馈链
),
escalate_feedback_template | 模型 | StrOutputParser(), # 增加逗号以保持语句一致性
)
- 定义一个名为
RunnableBranch
的,根据分类结果来选择合适的响应生成分支条件。
让我们来看一下带有这个链路——分叉的完整代码。
从dotenv模块导入load_dotenv
从langchain.prompts导入ChatPromptTemplate
从langchain.schema.output_parser导入StrOutputParser
从langchain.schema.runnable导入RunnableBranch
从langchain_openai导入ChatOpenAI
# 从.env文件加载环境变量
load_dotenv()
# 创建一个ChatOpenAI模型
model = ChatOpenAI(model="gpt-4o-mini")
# 定义不同反馈类型的提示模板
positive_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
("human",
"为这条正面反馈生成一封感谢信:{feedback}。"),
]
)
negative_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
("human",
"为这条负面反馈生成一个回应:{feedback}。"),
]
)
neutral_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
("human",
"为这条中立反馈请求更多细节:{feedback}。"),
]
)
escalate_feedback_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
("human",
"为这条反馈生成一个需要转交给客服的信息:{feedback}。"),
]
)
# 定义反馈分类提示模板
classification_template = ChatPromptTemplate.from_messages(
[
("system", "你是一个乐于助人的助手。"),
("human",
"将这条反馈的情感分类为正面、负面、中立或需要转交:{feedback}。"),
]
)
# 定义处理反馈的可运行分支
branches = RunnableBranch(
(
lambda x: "positive" in x,
positive_feedback_template | model | StrOutputParser() # 正面反馈链
),
(
lambda x: "negative" in x,
negative_feedback_template | model | StrOutputParser() # 负面反馈链
),
(
lambda x: "neutral" in x,
neutral_feedback_template | model | StrOutputParser() # 中立反馈链
),
escalate_feedback_template | model | StrOutputParser()
)
# 创建分类链
classification_chain = classification_template | model | StrOutputParser()
# 将分类和响应生成合并为一个链
chain = classification_chain | branches
# 使用示例评论运行链
# 好的评论 - "产品很棒。我非常喜欢使用它,觉得它非常有用。"
# 坏的评论 - "产品很糟糕。才用了几次就坏了,质量非常差。"
# 中立的评论 - "产品还可以。按预期工作,但没有什么特别之处。"
# 默认 - "我对这个产品还不是很确定。你能告诉我更多关于它的功能和好处吗?"
review = "产品很糟糕。才用了几次就坏了,质量非常差。"
result = chain.invoke({"feedback": review})
# 输出结果如下
print(result)
上述代码的输出是:
这个例子说明了如何使用LangChain来自动化情绪分析,并根据上下文生成合适的用户反馈回复,这对客户服务和反馈管理应用非常有用。
使用LangChain链类型的优势- 模块化: 链支持模块化设计,使得更换组件和集成新功能变得简单。
- 可重用性: 链可以在不同的应用程序中重复使用,减少开发时间和精力。
- 可扩展性: 基于链的设计支持可扩展的解决方案,通过将小而易管理的组件组合成更大的流程来实现。
- 定制化: 开发人员可以创建定制链,以满足特定需求,从而实现高度专业化应用。
来点掌声哦 👏,觉得有帮助的话,留言评论一下吧 ❤️🙏
参考文献:-
<https://python.langchain.com/v0.2/docs/concepts/#prompt 模板https://python.langchain.com/v0.2/docs/concepts/#prompt 模板>
- https://python.langchain.com/v0.1/docs/modules/chains/
共同学习,写下你的评论
评论加载中...
作者其他优质文章