LangChain 系列教程(五):Chain

LangChain 系列教程(五):Chain

介绍

在 LangChain 框架中,Chain (链) 是一个核心接口,用于实现对多个组件的序列化调用和组合。它将不同的功能单元(如模型调用、数据检索、逻辑处理)封装成一个连贯的工作流(Workflow),从而构建功能复杂的应用程序。

常用的核心链有三种:

LLMChain:将提示词模板和语言模型封装在一起的基础工具,专门用于执行单一、独立的AI调用任务。

Sequential Chain:像流水线一样将多个独立的链按固定顺序连接起来,并自动将上一步的输出作为下一步的输入

RouterChain:通过分析输入来动态地从多个选项中选择并执行最合适的子链,从而为应用添加决策与分支的能力。

代码

创建环境

Python
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI

# 加载 .env 文件
load_dotenv()

os.environ["OPENAI_API_BASE"] = os.getenv("OPENAI_API_BASE")
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")

# 初始化 LLM,我们将在所有示例中复用这个实例
llm = ChatOpenAI(temperature=0, model="gpt-4o")

print("环境准备完毕,LLM 已初始化。")

测试LLMChain

Python
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

# 1. 定义提示词模板
# 这个模板接收一个名为 "product_type" 的变量
prompt_template_name = PromptTemplate(
input_variables=["product_type"],
template="你是一个专业的品牌顾问。请为一个专注于 {product_type} 的新公司想一个响亮、有创意的中文名字。"
)

# 2. 创建 LLMChain
# 我们将提示词模板和 LLM 实例组合在一起
name_chain = LLMChain(llm=llm, prompt=prompt_template_name)

# 3. 运行链
# 使用 .invoke() 方法并传入一个字典作为输入
product_type = "家用智能咖啡机"
result = name_chain.invoke({"product_type": product_type})

print(f"产品类型: {product_type}")
print(f"生成的公司名: {result['text']}")

结果

Python
/var/folders/z5/r_6tsnmx7bjcnqbgkmfp22540000gn/T/ipykernel_45167/3352325305.py:13: LangChainDeprecationWarning: The class `LLMChain` was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use :meth:`~RunnableSequence, e.g., `prompt | llm`` instead.
name_chain = LLMChain(llm=llm, prompt=prompt_template_name)
产品类型: 家用智能咖啡机
生成的公司名: 当然!为一家专注于家用智能咖啡机的新公司取一个响亮、有创意的中文名字可以帮助它在市场上脱颖而出。以下是几个建议:

1. 咖智家
2. 智享咖
3. 咖啡慧
4. 咖智坊
5. 咖乐智
6. 咖享家
7. 咖智源
8. 咖啡灵
9. 咖智汇
10. 咖智品

这些名字结合了智能科技与咖啡的元素,旨在传达创新、便捷和高品质的品牌形象。希望其中一个能激发您的灵感!

测试Sequential Chain

Python
# 导入所需的类
from langchain.chains import SequentialChain, LLMChain
from langchain.prompts import PromptTemplate
# 假设 llm 实例已经像之前一样初始化好了

# 1. 定义第一个链 (起名),并添加严格的输出格式要求
prompt_template_name = PromptTemplate(
input_variables=["product_type"],
template="""你是一个专业的品牌顾问。请为一个专注于 {product_type} 的新公司想一个响亮、有创意的中文名字。

重要:你必须只回答一个名字,不要包含任何解释、编号、标点或任何其他多余的文字。
例如:如果产品是“智能手表”,你就只回答“时光环”"""
)
name_chain = LLMChain(llm=llm, prompt=prompt_template_name, output_key="company_name")

# 2. 定义第二个链 (写广告语),这个可以保持不变
prompt_template_slogan = PromptTemplate(
input_variables=["company_name"],
template="你是一位顶级的广告文案。请为名为 '{company_name}' 的公司写一句简洁且吸引人的广告语。"
)
slogan_chain = LLMChain(llm=llm, prompt=prompt_template_slogan, output_key="slogan")

# 3. 组合 SequentialChain (保持不变)
sequential_chain = SequentialChain(
chains=[name_chain, slogan_chain],
input_variables=["product_type"],
output_variables=["company_name", "slogan"],
verbose=True
)

# 4. 运行顺序链
product_type = "高端降噪耳机"
result = sequential_chain.invoke({"product_type": product_type})

print("\n----------- 修正后的最终结果 -----------")
print(f"产品类型: {product_type}")
print(f"生成的公司名: {result['company_name']}")
print(f"生成的广告语: {result['slogan']}")

结果

JavaScript
> Entering new SequentialChain chain...

> Finished chain.

----------- 修正后的最终结果 -----------
产品类型: 高端降噪耳机
生成的公司名: 静音境界
生成的广告语: "静音境界:让宁静成为你的日常奢华。"

测试RouterChain

Python
# --- 第三部分:RouterChain (最终修正版) ---

from langchain_core.runnables import RunnableBranch, RunnableLambda
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.chains import ConversationChain

# 1. 为每个子链(领域专家)创建提示模板和链 (此部分不变)
physics_prompt = ChatPromptTemplate.from_template(
"你是一位非常聪明的物理学家。你总是用简洁、清晰的方式回答关于物理学的问题。\n问题: {input}"
)
physics_chain = physics_prompt | llm | StrOutputParser()

math_prompt = ChatPromptTemplate.from_template(
"你是一位顶级的数学家。你能够巧妙地解答各种数学问题。\n问题: {input}"
)
math_chain = math_prompt | llm | StrOutputParser()

history_prompt = ChatPromptTemplate.from_template(
"你是一位学识渊博的历史学家。你对各个时期的历史事件和人物了如指掌。\n问题: {input}"
)
history_chain = history_prompt | llm | StrOutputParser()

# 2. 创建一个用于分类的路由链 (此部分不变)
classifier_prompt = ChatPromptTemplate.from_template(
"""根据用户的输入,判断它属于哪个领域:physics, math, history 或 general。
只输出一个单词。

输入: {input}
分类:"""
)
classifier_chain = classifier_prompt | llm | StrOutputParser()

# 3. 为默认路由创建一个专门处理输入的链 (这是关键的修正)
# 这个链接收一个字典,提取'input'键的值,然后将其传递给ConversationChain
default_route = (
RunnableLambda(lambda x: x["input"]) | ConversationChain(llm=llm)
)

# 4. 使用 RunnableBranch 构建路由逻辑
branch = RunnableBranch(
(lambda x: "physics" in x["topic"], physics_chain),
(lambda x: "math" in x["topic"], math_chain),
(lambda x: "history" in x["topic"], history_chain),
default_route # 使用我们新创建的、带输入处理的默认路由
)

# 5. 将分类链和分支逻辑组合成完整的路由链 (此部分不变)
full_router_chain = {
"topic": classifier_chain,
"input": lambda x: x["input"]
} | branch

# 6. 测试新的路由链 (所有测试现在都应该能正常工作)
print("\n--- 测试物理问题 ---")
result = full_router_chain.invoke({"input": "牛顿第二定律是什么?"})
print(result['response'] if isinstance(result, dict) else result)

print("\n--- 测试数学问题 ---")
result = full_router_chain.invoke({"input": "解释一下勾股定理。"})
print(result['response'] if isinstance(result, dict) else result)

print("\n--- 测试历史问题 ---")
result = full_router_chain.invoke({"input": "谁是秦始皇?"})
print(result['response'] if isinstance(result, dict) else result)

print("\n--- 测试通用问题 (将使用默认链) ---")
result = full_router_chain.invoke({"input": "你好吗?"})
print(result['response'] if isinstance(result, dict) else result)

结果

SQL
--- 测试物理问题 ---
牛顿第二定律描述了物体的加速度与所受净力和质量之间的关系。它可以用公式表示为:F = ma,其中F是净力,m是物体的质量,a是物体的加速度。简单来说,物体的加速度与所受净力成正比,与质量成反比。

--- 测试数学问题 ---
勾股定理是几何学中的一个基本定理,适用于直角三角形。它描述了直角三角形三个边之间的关系。具体来说,勾股定理指出:在一个直角三角形中,斜边(即最长的边,对应直角的对边)的平方等于其他两条边(即直角的两条邻边)的平方和。

如果我们用 \(a\) 和 \(b\) 分别表示直角三角形的两条邻边,用 \(c\) 表示斜边,那么勾股定理可以用数学公式表示为:

\[ c^2 = a^2 + b^2 \]

这个定理不仅在理论上非常重要,而且在实际应用中也非常广泛。例如,它可以用于计算距离、设计建筑、导航等领域。

勾股定理的历史可以追溯到古希腊数学家毕达哥拉斯,但实际上在毕达哥拉斯之前的许多文明中已经有类似的知识。这个定理是几何学的一个重要基础,也是许多其他数学理论的基础。

--- 测试历史问题 ---
秦始皇是中国历史上第一位统一全国的皇帝,他的本名是嬴政。秦始皇于公元前259年出生,公元前210年去世,是秦朝的开国皇帝。他在公元前221年完成了对六国的统一,建立了中国历史上第一个中央集权的封建王朝——秦朝。

秦始皇在位期间进行了多项重要的改革和建设,包括推行郡县制以加强中央集权,统一度量衡、货币和文字,修建了驰名中外的万里长城以抵御北方匈奴的侵扰。此外,他还修建了规模宏大的阿房宫和自己的陵墓——秦始皇陵,陵墓中有著名的兵马俑陪葬。

秦始皇的统治虽然在许多方面促进了中国的统一和发展,但也因其严苛的法律和苛政而受到批评。他的死后不久,秦朝便因内乱和民众反抗而迅速瓦解。秦始皇在中国历史上具有重要的地位,被视为一个具有开创性和争议性的历史人物。

--- 测试通用问题 (将使用默认链) ---
我很好,谢谢你问!作为一个AI,我没有情感,但我很高兴能和你交流。你今天过得怎么样?有什么特别的事情想分享吗?

posted @ 2025-06-10 12:51  Orzjh  阅读(144)  评论(0)    收藏  举报