Langchain学习笔记(十一):Chain构建与组合技巧
注:本文是Langchain框架的学习笔记;不是教程!不是教程!内容可能有所疏漏,欢迎交流指正。后续将持续更新学习笔记,分享我的学习心得和实践经验。
前言
在LangChain的发展过程中,API设计经历了重要的演进。从0.1.17版本开始,传统的Chain类(如LLMChain、SequentialChain等)被标记为已弃用,官方推荐使用更现代的LCEL(LangChain Expression Language)和管道符(|)语法。本文将详细对比新旧两种方式,帮助大家理解这一重要变化
1. Chain的基本概念与版本变化
1.1 什么是Chain?
Chain(链)是LangChain中用于连接多个组件的核心抽象。想象一下工厂的流水线,每个工作站负责一个特定的任务,产品从一个工作站传递到下一个工作站,最终完成整个生产过程。Chain就是这样的概念:
-
输入处理:接收用户的原始输入
-
中间处理:通过多个步骤对数据进行转换和处理
-
输出生成:产生最终的结果
Chain的核心价值在于:
-
模块化设计:将复杂的AI任务分解为多个简单的步骤
-
可重用性:每个组件都可以在不同的场景中重复使用
-
可维护性:便于调试、测试和优化单个环节
-
灵活组合:可以根据需求灵活组合不同的处理步骤
1.2 版本演进的背景
为什么要从传统Chain迁移到LCEL?
传统的Chain类虽然功能强大,但存在一些局限性:
-
性能瓶颈:无法充分利用并行处理能力
-
语法复杂:需要创建多个类实例,代码冗长
-
功能限制:不支持流式处理和高级组合模式
-
维护困难:复杂的继承关系增加了维护成本
LCEL(LangChain Expression Language)的优势:
-
直观语法:使用管道符(|)连接组件,类似Unix管道
-
高性能:原生支持并行、批处理和流式处理
-
类型安全:更好的类型提示和错误检查
-
易于调试:清晰的数据流向,便于问题定位
1.3 新旧版本对比表
功能 | 旧版本(已弃用) | 新版本(推荐) | 说明 |
---|---|---|---|
基础链 | LLMChain | prompt | llm | 最基础的提示词+模型组合 |
顺序链 | SequentialChain | chain1 | chain2 | chain3 | 按顺序执行多个处理步骤 |
执行方法 | chain.run() | chain.invoke() | 单次执行链的方法 |
批量执行 | chain.apply() | chain.batch() | 批量处理多个输入 |
异步执行 | chain.arun() | chain.ainvoke() | 异步执行,提高并发性能 |
流式执行 | 不支持 | chain.stream() | 实时流式输出,改善用户体验 |
2. LLMChain的新旧版本对比
2.1 LLMChain的作用和意义
LLMChain是LangChain中最基础、最常用的链类型。它的作用是将提示词模板(Prompt Template)与大语言模型(LLM)连接起来,形成一个完整的处理单元。
LLMChain的核心功能:
-
模板化输入:使用提示词模板,支持变量替换
-
模型调用:自动调用指定的大语言模型
-
输出处理:可选的输出解析和格式化
-
错误处理:统一的错误处理机制
使用场景:
-
文本生成(如写作助手、内容创作)
-
问答系统(基于提示词的简单问答)
-
文本分析(情感分析、关键词提取等)
-
格式转换(如JSON生成、代码生成)
2.2 基础用法对比
旧版本写法(已弃用)
from langchain_ollama import ChatOllama
from langchain.chains import LLMChain # 已弃用
from langchain.prompts import PromptTemplatellm = ChatOllama(base_url=OLLAMA_BASE_URL,model=MODEL_NAME,temperature=0.1 # 降低温度以获得更确定性的回答
)prompt_template = PromptTemplate(input_variables=["topic"],template="请为我写一篇关于{topic}的简短介绍,大约100字左右。"
)# 构建LLMChain(已弃用)
llm_chain = LLMChain(llm=llm,prompt=prompt_template,verbose=True
)# 使用链(已弃用的方法)
result = llm_chain.run(topic="人工智能") # 弃用警告
print(result)
新版本写法(推荐)
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain_core.output_parsers import StrOutputParserOLLAMA_BASE_URL = "http://192.168.0.118:11434"
MODEL_NAME = "deepseek-r1:1.5b"llm = ChatOllama(base_url=OLLAMA_BASE_URL,model=MODEL_NAME,temperature=0.1 # 降低温度以获得更确定性的回答
)prompt_template = PromptTemplate(input_variables=["topic"],template="请为我写一篇关于{topic}的简短介绍,大约100字左右。"
)# 使用管道符构建链(推荐)
chain = prompt_template | llm | StrOutputParser()# 使用invoke方法执行(推荐)
result = chain.invoke({"topic": "人工智能"})
print(result)# 新版本支持的其他执行方式
# 批量执行
results = chain.batch([{"topic": "人工智能"},{"topic": "机器学习"}
])
print(results)
新版本的优势解析:
-
管道符语法:prompt_template | llm | StrOutputParser() 清晰地表达了数据流向
-
输出解析器:StrOutputParser() 确保输出为字符串格式
-
批量处理:batch() 方法可以高效处理多个输入
-
类型安全:更好的类型提示,减少运行时错误
2.3 带输出解析器的高级用法
输出解析器的作用:
输出解析器(Output Parser)是LangChain中用于处理模型输出的重要组件。它的主要作用包括:
-
格式化输出:将模型的原始输出转换为结构化数据
-
类型转换:确保输出符合预期的数据类型
-
验证检查:验证输出是否符合预定义的格式要求
-
错误处理:处理格式不正确的输出
新版本写法
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain.output_parsers import CommaSeparatedListOutputParserOLLAMA_BASE_URL = "http://192.168.0.118:11434"
MODEL_NAME = "deepseek-r1:1.5b"llm = ChatOllama(base_url=OLLAMA_BASE_URL,model=MODEL_NAME,temperature=0.1 # 降低温度以获得更确定性的回答
)# 新版本
output_parser = CommaSeparatedListOutputParser()list_prompt = PromptTemplate(template="列出5个关于{topic}的关键词,用逗号分隔。\n{format_instructions}",input_variables=["topic"],partial_variables={"format_instructions": output_parser.get_format_instructions()}
)# 使用管道符连接解析器
chain = list_prompt | llm | output_parserkeywords = chain.invoke({"topic": "机器学习"})
print(f"关键词列表: {keywords}")
print(f"类型: {type(keywords)}")
3. SequentialChain
3.1 SequentialChain的概念和作用
SequentialChain(顺序链)是用于按顺序执行多个处理步骤的链类型。它的核心思想是将复杂的任务分解为多个简单的子任务,然后按照特定的顺序依次执行。
SequentialChain的特点:
-
步骤化处理:将复杂任务分解为多个简单步骤
-
数据传递:前一个步骤的输出作为后一个步骤的输入
-
模块化设计:每个步骤都是独立的,便于测试和维护
-
灵活组合:可以根据需要调整步骤的顺序和组合
适用场景:
-
内容创作流程:大纲生成 → 内容写作 → 格式优化
-
数据分析流程:数据收集 → 数据清洗 → 分析报告
-
产品开发流程:需求分析 → 方案设计 → 实施计划
-
客户服务流程:问题识别 → 解决方案 → 回复生成
3.2 简单顺序链
简单顺序链的特点:
-
每个步骤只有一个输入和一个输出
-
前一步的输出直接作为后一步的输入
-
适合线性处理流程
新版本写法
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain_core.output_parsers import StrOutputParserOLLAMA_BASE_URL = "http://192.168.0.118:11434"
MODEL_NAME = "deepseek-r1:1.5b"llm = ChatOllama(base_url=OLLAMA_BASE_URL,model=MODEL_NAME,temperature=0.1 # 降低温度以获得更确定性的回答
)# 新版本
outline_prompt = PromptTemplate(input_variables=["topic"],template="为主题'{topic}'创建一个详细的文章大纲,包含3-5个主要部分。"
)article_prompt = PromptTemplate(input_variables=["outline"],template="根据以下大纲写一篇简短的文章:\n{outline}"
)# 使用管道符构建顺序链
writing_chain = (outline_prompt| llm| StrOutputParser()| (lambda outline: {"outline": outline})| article_prompt| llm| StrOutputParser()
)final_article = writing_chain.invoke({"topic": "可持续发展"})
print(final_article)
3.2 复杂顺序链
复杂顺序链的特点:
-
支持多个输入和输出变量
-
可以在处理过程中保留和传递多个数据
-
支持并行处理某些步骤
-
适合复杂的业务逻辑
新版写法
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableParallelOLLAMA_BASE_URL = "http://192.168.0.118:11434"
MODEL_NAME = "deepseek-r1:1.5b"llm = ChatOllama(base_url=OLLAMA_BASE_URL,model=MODEL_NAME,temperature=0.1 # 降低温度以获得更确定性的回答
)# 新版本
analysis_prompt = PromptTemplate(input_variables=["product_name", "product_description"],template="产品:{product_name}\n描述:{product_description}\n请分析产品特点:"
)slogan_prompt = PromptTemplate(input_variables=["product_name", "product_analysis"],template="产品:{product_name}\n分析:{product_analysis}\n请创建3个营销标语:"
)# 使用RunnableParallel和管道符构建复杂链
product_marketing_chain = (RunnablePassthrough.assign(product_analysis=analysis_prompt | llm | StrOutputParser()) | RunnableParallel(product_analysis=lambda x: x["product_analysis"], marketing_slogans=slogan_prompt | llm | StrOutputParser()
)
)result = product_marketing_chain.invoke({"product_name": "智能语音助手","product_description": "基于AI技术的智能语音助手"
})print("产品分析:", result["product_analysis"])
print("营销标语:", result["marketing_slogans"])
核心组件解析:
-
RunnablePassthrough.assign():
- 作用:在保留原有输入的基础上,添加新的字段
- 这里添加了 product_analysis 字段,包含产品分析结果
-
RunnableParallel():
- 作用:并行执行多个任务,提高处理效率
- 同时输出产品分析和营销标语两个结果
处理流程:
- 输入处理:接收产品名称和描述
- 产品分析:生成产品特点分析,并保留原始输入
- 并行输出:同时生成最终的分析结果和营销标语
4. RouterChain
4.1 RouterChain的概念和作用
RouterChain(路由链)是一种智能分发机制,它可以根据输入内容的特征,自动选择最合适的处理路径。就像交通路口的智能信号灯,根据不同方向的车流量来调整信号,RouterChain根据不同类型的输入来选择最佳的处理方式。
RouterChain的核心价值:
- 智能分类:自动识别输入内容的类型或意图
- 专业处理:为不同类型的问题提供专门的处理逻辑
- 提高效率:避免用通用方法处理所有问题
- 提升质量:专业化处理通常能获得更好的结果
典型应用场景:
-
智能客服系统:根据问题类型路由到不同的处理模块
-
内容分类处理:技术问题、商业问题、创意问题分别处理
-
多语言支持:根据语言类型选择对应的处理器
-
难度分级:简单问题快速回答,复杂问题深度分析
4.2 基础路由链
路由逻辑的设计思路:
- 关键词匹配:通过关键词识别问题类型
- 专业模板:为每种类型设计专门的提示词模板
- 默认处理:为无法分类的问题提供通用处理方式
新版写法
from langchain_core.prompts import PromptTemplate
from langchain_ollama import ChatOllama
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableBranchOLLAMA_BASE_URL = "http://192.168.0.118:11434"
MODEL_NAME = "deepseek-r1:1.5b"llm = ChatOllama(base_url=OLLAMA_BASE_URL,model=MODEL_NAME,temperature=0.1 # 降低温度以获得更确定性的回答
)# 新版本
tech_prompt = PromptTemplate(template="你是技术专家。请回答:{input}",input_variables=["input"]
)business_prompt = PromptTemplate(template="你是商业顾问。请回答:{input}",input_variables=["input"]
)default_prompt = PromptTemplate(template="请回答:{input}",input_variables=["input"]
)# 使用RunnableBranch实现路由逻辑
def route_question(x):question = x["input"].lower()if any(keyword in question for keyword in ["代码", "编程", "技术", "开发"]):return "tech"elif any(keyword in question for keyword in ["商业", "市场", "销售", "管理"]):return "business"else:return "default"router_chain = RunnableBranch((lambda x: route_question(x) == "tech", tech_prompt | llm | StrOutputParser()),(lambda x: route_question(x) == "business", business_prompt | llm | StrOutputParser()),default_prompt | llm | StrOutputParser()
)result = router_chain.invoke({"input": "如何优化Python代码性能?"})
print(result)
核心组件详解:
-
route_question() 函数:
- 作用:分析输入问题,判断问题类型
- 逻辑:通过关键词匹配来识别问题领域
- 返回:问题类型标识(tech/business/default)
-
RunnableBranch:
- 作用:根据条件选择不同的处理分支
- 结构:(条件函数, 处理链) 的元组列表
- 默认:最后一个参数作为默认处理分支
-
专业化提示词:
- tech_prompt:以技术专家身份回答技术问题
- business_prompt:以商业顾问身份回答商业问题
- default_prompt:通用回答模式
总结
LangChain从传统的Chain类向LCEL的迁移代表了框架设计理念的重要演进:
-
API设计更现代化:管道符语法更直观,符合现代编程习惯
-
性能更优秀:原生支持并行、批处理和流式处理
-
功能更强大:更灵活的组合方式,更好的调试工具
-
维护性更好:代码更简洁,逻辑更清晰
虽然旧版本的Chain类仍然可用,但建议在新项目中使用LCEL语法,在现有项目中逐步迁移。这不仅能享受到新版本的性能优势,还能确保代码的长期可维护性
相关文章:
Langchain学习笔记(十一):Chain构建与组合技巧
注:本文是Langchain框架的学习笔记;不是教程!不是教程!内容可能有所疏漏,欢迎交流指正。后续将持续更新学习笔记,分享我的学习心得和实践经验。 前言 在LangChain的发展过程中,API设计经历了重…...
【判断既约分数】2022-4-3
缘由既约分数,除了辗转相除法-编程语言-CSDN问答 void 判断既约分数() {int a 1, b 2020, aa b, y 2, gs 0;while (aa){while (a < b){while (y < a && y < aa)if (a%y 0 && aa%y 0)a, y 2;elsey;if (a < b)gs; else;a, y 2;…...

Windows平台RTSP/RTMP播放器C#接入详解
大牛直播SDK在Windows平台下的RTSP、RTMP播放器模块,基于自研高性能内核,具备极高的稳定性与行业领先的超低延迟表现。相比传统基于FFmpeg或VLC的播放器实现,SmartPlayer不仅支持RTSP TCP/UDP自动切换、401鉴权、断网重连等网络复杂场景自适应…...
深圳SMT贴片工艺优化关键步骤
内容概要 深圳SMT贴片工艺优化作为现代电子制造的核心环节,聚焦于提升生产精度与稳定性。其技术框架围绕三大核心维度展开:温度动态调控、设备协同适配与工艺缺陷预判。通过精密温度曲线控制系统,实现回流焊环节的热能梯度精准匹配ÿ…...

从 JDK 8 到 JDK 17:Swagger 升级迁移指南
点击上方“程序猿技术大咖”,关注并选择“设为星标” 回复“加群”获取入群讨论资格! 随着 Java 生态向 JDK 17 及 Jakarta EE 的演进,许多项目面临从 JDK 8 升级的挑战,其中 Swagger(API 文档工具)的兼容性…...
配置git命令缩写
以下是 Git 命令缩写的配置方法及常用方案,适用于 Linux/macOS/Windows 系统: 🔧 一、配置方法 1. 命令行设置(推荐) # 基础命令缩写 git config --global alias.st status git config --global alias.co che…...
Redis 缓存问题及其解决方案
1. 缓存雪崩 概念:缓存雪崩是指在缓存层出现大范围缓存失效或缓存服务器宕机的情况下,大量请求直接打到数据库,导致数据库压力骤增,甚至可能引发数据库宕机。 影响:缓存雪崩会导致系统性能急剧下降,甚至导…...

使用 Coze 工作流一键生成抖音书单视频:全流程拆解与技术实现
使用 Coze 工作流一键生成抖音书单视频:全流程拆解与技术实现(提供工作流) 摘要:本文基于一段关于使用 Coze 平台构建抖音爆火书单视频的详细讲解,总结出一套完整的 AI 视频自动化制作流程。内容涵盖从思路拆解、节点配…...

【发布实录】云原生+AI,助力企业全球化业务创新
5 月 22 日,在最新一期阿里云「飞天发布时刻」,阿里云云原生应用平台产品负责人李国强重磅揭晓面向 AI 场景的云原生产品体系升级,通过弹性智能的一体化架构、开箱即用的云原生 AI 能力,为中国企业出海提供新一代技术引擎。 发布会…...
vue中的派发事件与广播事件,及广播事件应用于哪些场景和一个表单验证例子
在 Vue 2.X 中,$dispatch 和 $broadcast 方法已经被废弃。官方认为基于组件树结构的事件流方式难以理解,并且在组件结构扩展时容易变得脆弱。因此,Vue 2.X 推荐使用其他方式来实现组件间的通信,例如通过 $emit 和 $on 方法&#x…...
DeepSeek 赋能智能养老:情感陪伴机器人的温暖革新
目录 一、引言二、智能养老情感陪伴机器人的市场现状与需求2.1 市场现状2.2 老年人情感陪伴需求分析 三、DeepSeek 技术详解3.1 DeepSeek 的技术特点3.2 与其他类似技术的对比优势 四、DeepSeek 在智能养老情感陪伴机器人中的具体应用4.1 自然语言处理与对话交互4.2 情感识别与…...

LabVIEW主轴故障诊断案例
LabVIEW 开发主轴机械状态识别与故障诊断系统,适配工业场景主轴振动监测需求。通过整合品牌硬件与软件算法,实现从信号采集到故障定位的全流程自动化,为设备维护提供数据支撑,提升数控机床运行可靠性。 面向精密制造企业数控机…...
gRPC 的四种通信模式完整示例
gRPC 的四种基本通信模式,包括完整的 .proto 文件定义和 Go 语言实现代码: 1. 简单 RPC (Unary RPC) - 请求/响应模式 客户端发送单个请求,服务端返回单个响应 calculator.proto protobuf syntax "proto3";package calculato…...
C#中Struct与IntPtr转换:实用扩展方法
C#中Struct与IntPtr转换:实用扩展方法 在 C# 编程的世界里,我们常常会遇到需要与非托管代码交互,或者进行一些底层内存操作的场景。这时,IntPtr类型就显得尤为重要,它可以表示一个指针或句柄,用来指向非托…...
Web安全:XSS、CSRF等常见漏洞及防御措施
Web安全:XSS、CSRF等常见漏洞及防御措施 一、XSS(跨站脚本攻击) 定义与原理 XSS攻击指攻击者将恶意脚本(如JavaScript、HTML标签)注入到Web页面中,当用户访问该页面时,脚本在浏览器端执行&…...
Java基础之数组(附带Comparator)
文章目录 基础概念可变参数组数组与ListComparator类1,基本概念2,使用Comparator的静态方法(Java 8)3,常用Comparator方法4,例子 排序与查找数组复制其他 基础概念 int[] anArray new int[10];只有创建对象时才会使用new关键字,所以数组是个…...

计算机组成与体系结构:补码数制二(Complementary Number Systems)
目录 4位二进制的减法 补码系统 🧠减基补码 名字解释: 减基补码有什么用? 计算方法 ❓为什么这样就能计算减基补码 💡 原理揭示:按位减法,模拟总减法! 那对于二进制呢?&…...

C#使用MindFusion.Diagramming框架绘制流程图(2):流程图示例
上一节我们初步介绍MindFusion.Diagramming框架 C#使用MindFusion.Diagramming框架绘制流程图(1):基础类型-CSDN博客 这里演示示例程序: 新建Windows窗体应用程序FlowDiagramDemo,将默认的Form1重命名为FormFlowDiagram. 右键FlowDiagramDemo管理NuGet程序包 输入MindFusio…...

【物联网-ModBus-RTU
物联网-ModBus-RTU ■ 优秀博主链接■ ModBus-RTU介绍■(1)帧结构■(2)查询功能码 0x03■(3)修改单个寄存器功能码 0x06■(4)Modbus RTU 串口收发数据分析 ■ 优秀博主链接 Modbus …...

Java应用10(客户端与服务器通信)
Java客户端与服务器通信 Java提供了多种方式来实现客户端与服务器之间的通信,下面我将介绍几种常见的方法: 1. 基于Socket的基本通信 服务器端代码 import java.io.*; import java.net.*;public class SimpleServer {public static void main(String…...
STM32学习之I2C(理论篇)
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
【C/C++】algorithm清单以及适用场景
文章目录 algorithm清单以及适用场景1 算法介绍1.1 分类1.2 非修改序列算法1.3 修改序列算法1.4 排序与堆算法1.5 集合操作算法(要求有序)1.5 查找算法1.6 二分查找算法(有序区间)1.7 去重与分区算法1.8 数值算法 <numeric>…...

Python_day47
作业:对比不同卷积层热图可视化的结果 一、不同卷积层的特征特性 卷积层类型特征类型特征抽象程度对输入的依赖程度低层卷积层(如第 1 - 3 层)边缘、纹理、颜色、简单形状等基础特征低高,直接与输入像素关联中层卷积层(…...

如何在mac上安装podman
安装 Podman 在 macOS 上 在 macOS 上安装 Podman 需要使用 Podman 的桌面客户端工具 Podman Desktop 或通过 Homebrew 安装命令行工具。 使用 Homebrew 安装 Podman: (base) ninjamacninjamacdeMacBook-Air shell % brew install podman > Auto-updating Hom…...

小黑一层层削苹果皮式大模型应用探索:langchain中智能体思考和执行工具的demo
引言 小黑黑通过探索langchain源码,设计了一个关于agent使用工具的一个简化版小demo(代码可以跑通),主要流程: 1.问题输入给大模型。 2.大模型进行思考,输出需要执行的action和相关思考信息。 3.通过代理&…...
CppCon 2015 学习:Intro to the C++ Object Model
这段代码展示了使用 make 工具来编译 C 程序的简单过程。 代码和步骤解析: C 代码(intro.cpp):#include <iostream> int main() { std::cout<<"hello world\n"; } 这是一个简单的 C 程序,它包…...
Go 语言中的 make 函数详解
Go 语言中的 make 函数详解 make 是 Go 语言中的一个内置函数,用于初始化切片(slice)、映射(map)和通道(channel)这些引用类型。这些类型必须在使用前通过 make 初始化&#x…...

阿里云ACP云计算备考笔记 (4)——企业应用服务
目录 第一章 企业应用概览 第二章 云解析 1、云解析基本概念 2、域名管理流程 3、云解析记录类型 4、域名管理 ① 开启注册局安全锁 ② 域名赎回 第二章 内容分发网络CDN 1、CDN概念 2、使用CDN前后对比 3、使用CDN的优势 4、阿里云CDN的优势 5、配置网页性能优化…...
用 NGINX 构建高效 SMTP 代理`ngx_mail_smtp_module`
一、模块定位与作用 协议代理 NGINX 监听指定端口(如 25、587、465 等),接收客户端的 SMTP 会话请求。代理层在会话中透明转发客户端的 EHLO、MAIL FROM、RCPT TO、DATA 等命令到后端 MTA。 认证控制 通过 smtp_auth 指令指定允许的 SASL 认…...
【前端】常用组件的CSS
1. button的样式修改 每个环节有五个不同的状态:link,hover,active,focus和visited. Link是正常的外观,hover当你鼠标悬停时,active是单击它时的状态,focus跟随活动状态,visited是你在最近点击的链接未聚焦时结束的状态。 纯CSS 以下为例子,按下后从浅紫到深紫。注…...