当前位置: 首页 > news >正文

「LangChain 学习笔记」LangChain大模型应用开发:模型链(Chains)

目录

1. 大语言模型链

2. 简单顺序链

3. 多输入/输出顺序链

4. 路由链(Router Chain)

4.1 路由链流程


链(Chains)通常将大语言模型(LLM)与提示(Prompt)结合在一起,基于此,我们可以对文本或数据进行一系列操作。链(Chains)可以一次性接受多个输入。

例如,我们可以创建一个链,该链接受用户输入,使用提示模板对其进行格式化,然后将格式化的响应传递给 LLM 。我们可以通过将多个链组合在一起,或者通过将链与其他组件组合在一起来构建更复杂的链。

1. 大语言模型链

LLMChain 类已在 LangChain 0.1.17 弃用,未来将被移除。所以这里使用 prompt | llm 替换 LLMChain,主要是管道符" | "。详细请参考:【LangChain】LLMChain 迁移至 RunnableSequence_langchaindeprecationwarning: the class `llmchain` -CSDN博客

大语言模型链(LLMChain)是一个简单但非常强大的链,也是后面我们将要介绍的许多链的基础。

大语言模型(LLM)提示(Prompt)组合成链。这个大语言模型链非常简单,可以让我们以一种顺序的方式去通过运行提示并且结合到大语言模型中。通过使用chain.invoke将其通过这个链运行。下面是一个简单的例子

from langchain_openai import ChatOpenAI  # OpenAI 的语言模型支持
from langchain.prompts import ChatPromptTemplatellm = ChatOpenAI(api_key="你的API key",base_url="https://qianfan.baidubce.com/v2",model="ernie-3.5-8k",temperature=0
)prompt = ChatPromptTemplate.from_template(   "描述制造{product}的一个公司的最佳名称是什么?"
)
chain = prompt | llm
product = "大号床单套装"result = chain.invoke(product)
print(result.content)
为一家制造大号床单套装的公司起名时,我们需要考虑名称的易记性、与产品特性的关联性、市场定位以及潜在的文化含义。以下是我为这类公司精心挑选的五个名称,每个都附有起名的理由:1. **巨梦家纺**:结合了“巨大”和“梦境”两个概念,暗示着大号床单能带来宽敞舒适的睡眠体验。
2. **宽逸居品**:“宽”字直接体现了床单套装的尺寸特点,而“逸居”则传达了家居生活的轻松惬意。
3. **悦眠巨幕**:将床单比作“巨幕”,形象地表达了其大尺寸的特点,同时“悦眠”强调了优质的睡眠体验。
4. **舒域家纺**:“舒域”结合了舒适和领域两个词汇,寓意着公司在大号床单领域的专业性和顾客的舒适感受。
5. **梦澜宽庭**:“梦澜”寓意着梦境中的波澜,象征着美好的睡眠体验,“宽庭”则强调了空间的宽敞感。这些名称都旨在体现公司产品的核心特点——大号和舒适,同时易于记忆和发音,符合中文文化背景。请注意,这些建议是基于创意和通用性,建议在最终确定前进行商标和名称的可用性检查,以确保不与现有公司或品牌重名。

2. 简单顺序链

顺序链(SequentialChains)是按预定义顺序执行其链接的链。具体来说,我们将使用管道操作符(" | ")构建简单顺序链,这是顺序链的最简单类型,其中每个步骤都有一个输入/输出,一个步骤的输出是下一个步骤的输入。


first_prompt = ChatPromptTemplate.from_template(   "为一家主营{product}的公司起一个最好的中文品牌名称,只要一个名称不需要多余的,也不需要任何描述。"
)
chain_one = first_prompt | llmsecond_prompt = ChatPromptTemplate.from_template(   "写一个20字的描述对于下面这个\公司的品牌:{company_name}"
)chain_two = second_prompt | llmsimple_chain = chain_one | chain_twoproduct = "大号床单套装"
result1 =  chain_one.invoke(product)
result2 =  chain_two.invoke(result1)
print("第一条链的结果:" + result1.content)
print("第二条链的结果:" + result2.content)result = simple_chain.invoke(product)
print("整体链的结果:" + result.content)
第一条链的结果:巨梦床单
第二条链的结果:巨梦床单,编织梦幻家居的温馨之选。
整体链的结果:巨梦床单,编织梦幻家居的温馨之选。

3. 多输入/输出顺序链

当只有一个输入和一个输出时,简单顺序链即可实现。当有多个输入或多个输出时,我们则需要使用 RunnableSequence来实现。

from langchain_core.runnables import RunnableSequence
from langchain_core.prompts import ChatPromptTemplate# 假设 llm 已定义
# 步骤 1:分析用户输入的餐厅偏好
gather_preferences_prompt = ChatPromptTemplate.from_template("用户输入了一些餐厅偏好:{preferences}\n""请将用户的偏好总结为清晰的需求:"
)
gather_preferences_chain = gather_preferences_prompt | llm | (lambda x: {"summarized_preferences": x.content})# 步骤 2:根据需求推荐餐厅
recommend_restaurants_prompt = ChatPromptTemplate.from_template("基于用户需求:{summarized_preferences}\n""请推荐 3 家适合的餐厅,并说明推荐理由:"
)
recommend_restaurants_chain = recommend_restaurants_prompt | llm | (lambda x: {"recommendations": x.content})# 步骤 3:总结推荐内容供用户快速参考
summarize_recommendations_prompt = ChatPromptTemplate.from_template("以下是餐厅推荐和推荐理由:\n{recommendations}\n""请总结成 2-3 句话,供用户快速参考:"
)
summarize_recommendations_chain = summarize_recommendations_prompt | llm# 创建 RunnableSequence
restaurant_chain = RunnableSequence(gather_preferences_chain,recommend_restaurants_chain,summarize_recommendations_chain
)
restaurant_chain2 = gather_preferences_chain | recommend_restaurants_chain | summarize_recommendations_chain# 示例输入数据
input_data = {"preferences": "我喜欢安静的环境,最好有素食选项,并且价格适中。"}# 执行链条
result = restaurant_chain.invoke(input_data)
result2 = restaurant_chain2.invoke(input_data)# 输出最终结果
print(result.content)
print(result2.content)
推荐三家安静且提供丰富素食选项的餐厅:静谧素食轩、悠然素食馆和绿野仙踪素食餐厅。这些餐厅均拥有适中的价格定位,是性价比很高的用餐选择,适合寻求安静用餐环境的素食爱好者。
推荐三家安静且提供丰富素食选项的餐厅:静谧素食轩、悠然素食馆和绿野仙踪素食餐厅。这些餐厅均拥有适中的价格定位,是性价比很高的用餐选择,适合寻求安静用餐环境的素食爱好者。

gather_preferences_chain = gather_preferences_prompt | llm | (lambda x: {"summarized_preferences": x.content})代码解释:

  • gather_preferences_prompt:一个 ChatPromptTemplate,用于格式化用户输入(如“我喜欢安静的环境...”)。
  • | llm:把格式化后的提示传给大语言模型(如 ChatOpenAI),让模型生成总结。
  • | (lambda x: {"summarized_preferences": x.content}):对模型的输出做后处理,把输出内容包装成字典,key 为 "summarized_preferences"value 为模型输出的内容(x.content)。

RunnableSequence方法:显式方式组织链路;等价于使用管道符 |,可以看出上面结果一致。

4. 路由链(Router Chain)

到目前为止,我们已经学习了大语言模型链和顺序链。但是,如果我们想做一些更复杂的事情怎么办?

一个相当常见但基本的操作是根据输入将其路由到一条链,具体取决于该输入到底是什么(也就是不同的输入对应不同的链)。如果你有多个子链,每个子链都专门用于特定类型的输入,那么可以组成一个路由链,它首先决定将它传递给哪个子链,然后将它传递给那个链。

from langchain_core.runnables import RouterRunnable, RunnableLambda, RunnableSequence# Step 1: 定义各领域的任务模板
# 定义物理任务模板
physics_template = ChatPromptTemplate.from_template("你是一位物理学教授,擅长用简洁易懂的方式回答物理问题。以下是问题内容:{input}"
)# 定义数学任务模板
math_template = ChatPromptTemplate.from_template("你是一位数学家,擅长分步骤解决数学问题,并提供详细的解决过程。以下是问题内容:{input}"
)# 定义历史任务模板
history_template = ChatPromptTemplate.from_template("你是一位历史学家,对历史事件和背景有深入研究。以下是问题内容:{input}"
)# 定义计算机科学任务模板
computerscience_template = ChatPromptTemplate.from_template("你是一位计算机科学专家,擅长算法、数据结构和编程问题。以下是问题内容:{input}"
)# Step 2: 将模板与语言模型结合,形成任务链
physics_chain = physics_template | llm
math_chain = math_template | llm
history_chain = history_template | llm
computerscience_chain = computerscience_template | llm# Step 3: 定义动态路由逻辑
def route(input):if "物理" in input["input"]:print("路由到物理任务")return {"key": "physics", "input": input["input"]}elif "数学" in input["input"]:print("路由到数学任务")return {"key": "math", "input": input["input"]}elif "历史" in input["input"]:print("路由到历史任务")return {"key": "history", "input": input["input"]}elif "计算机" in input["input"]:print("路由到计算机任务")   return {"key": "computer_science", "input": input["input"]}else:print("路由到默认任务")return {"key": "default", "input": input["input"]}# 创建路由逻辑的 Runnable
route_runnable = RunnableLambda(route)# 定义默认处理链
default_chain = ChatPromptTemplate.from_template("输入内容无法归类,请直接回答:{input}"
) | llm# Step 4: 创建 RouterRunnable
router = RouterRunnable(runnables={"physics": physics_chain,"math": math_chain,"history": history_chain,"computer_science": computerscience_chain,"default": default_chain}
)# Step 5: 创建完整的 Router Chain
router_chain = RunnableSequence(route_runnable, router)# Step 6: 测试 Router Chain
# 定义示例输入
inputs = [{"input": "物理:什么是黑体辐射?"},  # 物理问题{"input": "数学:计算 2 + 2 的结果。"},  # 数学问题{"input": "历史:介绍一次世界大战的背景。"},  # 历史问题{"input": "计算机:如何实现快速排序算法?"}  # 计算机科学问题
]# 执行 Router Chain 并输出结果
for inp in inputs:result = router_chain.invoke(inp)print(f"问题:{inp['input']}\n回答:{result.content}\n")


 

以上代码参考 :全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南_routerrunnable-CSDN博客

,虽然代码流程看懂了但是我觉得还是自己沉淀一下,等沉淀完了重新回来补上心得。

4.1 路由链流程

流程步骤描述使用的 API
1️⃣ 定义任务模板为各领域设计 promptChatPromptTemplate.from_template
2️⃣ 创建任务链模板 + LLM → 可执行链管道符 " | "
3️⃣ 定义路由逻辑判断输入所属领域Python 函数 + RunnableLambda
4️⃣RouterRunnable根据 key 选择链执行RouterRunnable
5️⃣Router Chain路由逻辑 + 多分支路由串联RunnableSequence
6️⃣ 执行测试调用整个链生成回答router_chain.invoke(input)
http://www.dtcms.com/a/352940.html

相关文章:

  • 外汇中高频 CTA 风控策略回测案例
  • 宝塔面板零基础搭建 WordPress 个人博客与外贸网站 | 新手10分钟上手指南
  • 国内股指期货合约的最小变动价位是多少?
  • 大语言模型的“引擎室”:深入剖析现代计算与算法优化
  • 企业落地版 AutoGen 工程示例:自动化市场分析报告生成系统
  • 代码随想录刷题Day42
  • 【芯片低功耗设计中的UPF:从理论到实践详解】
  • windows 子系统 wsl 命令的用法
  • lvgl(一)
  • Java全栈工程师面试实录:从基础到实战的深度技术探索
  • 集成电路学习:什么是YOLO一次性检测器
  • nginx结合lua做转发,负载均衡
  • 解决VSCode中Cline插件的Git锁文件冲突问题
  • 第三章 UI框架设定 流程逻辑
  • 测试分类(超详解)
  • 网络编程-TCP的并发服务器构建
  • FactoryBean接口作用
  • 基于高德地图的怀化旅发精品路线智能规划导航之旅
  • 排放情报平台:驱动绿色未来的技术引擎
  • 优选算法-常见位运算总结
  • 分布式系统架构设计与一致性协议深度解析
  • 深入解析 Chromium Mojo IPC:跨进程通信原理与源码实战
  • 【Qt开发】常用控件(七)-> styleSheet
  • 激活函数只是“非线性开关”?ReLU、Sigmoid、Leaky ReLU的区别与选择
  • Linux 的 git 更换项目仓库源地址
  • 数据对话的“通用语法”:SQL与KingbaseES的智能处理艺术
  • 高并发内存池(11)-PageCache获取Span(下)
  • 【Hadoop】Zookeeper、HBase、Sqoop
  • 寄存器的原理
  • 边缘计算:一场由物理定律发起的“计算革命”