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

[智能体-233]:传统的基于LLMchain langchain与基于LCEL langchain,在已定义的chain基础之上增加记忆功能的方式上的区别?

一、核心结论先行

  1. 传统 LLMChain记忆是链的内置属性创建链时直接注入,强耦合记忆和链绑定死,后期难以动态增删、局部启用。
  2. LCEL:记忆是外层包装能力,原有纯业务链路完全不变,解耦独立;支持动态包装、局部加记忆、多套记忆混用。

二、传统 LLMChain:构造函数注入记忆(内置绑定)

1. 完整写法

记忆组件(Memory)作为初始化参数,在创建LLMChain实例时一并传入,链路与记忆从一开始就绑定。

python

运行

from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory # 1. 基础组件 llm = ChatOpenAI() prompt = PromptTemplate( input_variables=["history", "input"], template="历史对话:{history}\n用户:{input}\n助手:" ) # 2. 定义记忆 memory = ConversationBufferMemory(memory_key="history") # 3. 关键:创建 LLMChain 时,直接把 memory 传入构造方法 !!! llm_chain = LLMChain(llm=llm, prompt=prompt, memory=memory) # 4. 调用(无需手动传 history,链内部自动读写记忆) res1 = llm_chain.invoke({"input": "你好"}) res2 = llm_chain.invoke({"input": "刚才我说了什么?"})

2. 核心特点

  • 绑定时机:实例化阶段一次性绑定,无法后期动态解绑 / 替换
  • 数据流转history由 Chain 内部自动从 Memory 读取、自动写入,属于黑盒逻辑
  • 耦合度:链 ↔ 记忆 强耦合,一条链只能绑定唯一一个 Memory 实例
  • 多会话:需手动创建多个独立LLMChain + Memory组合,代码冗余。
  • 局限性
    • 不能只给 “链路某一段” 加记忆,整条链统一生效;
    • 想临时关闭记忆,必须重新创建不带 memory的新链实例。

三、LCEL 方式:外层包装追加记忆(解耦外挂)

LCEL 原生链路(prompt | llm完全无状态、无记忆,通过RunnableWithMessageHistory对已有链路做二次包装,实现记忆能力。原有业务链路代码一行不用改。

1. 完整写法

python

运行

from langchain_core.prompts import PromptTemplate from langchain_openai import ChatOpenAI from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_community.chat_message_histories import ChatMessageHistory # 1. 先定义【纯业务链路】(无任何记忆,可单独复用) llm = ChatOpenAI() prompt = PromptTemplate( input_variables=["history", "input"], template="历史对话:{history}\n用户:{input}\n助手:" ) # 基础链:纯逻辑,无记忆 base_chain = prompt | llm # 2. 定义会话存储与历史读取规则(记忆逻辑独立) session_store = {} def get_history(session_id: str) -> ChatMessageHistory: if session_id not in session_store: session_store[session_id] = ChatMessageHistory() return session_store[session_id] # 3. 关键:在已有 chain 外层包装,追加记忆能力 chain_with_memory = RunnableWithMessageHistory( runnable=base_chain, # 传入已定义好的原始链,记忆是基于此进行包装 get_session_history=get_history, ## 支持基于session的记忆,记忆体是外部定义的session_store input_messages_key="input", # 与原始链的用户输入变量关联 history_messages_key="history" # 与原始链的history变量关联 ) # 4. 调用:通过 session_id 自动隔离会话、读写记忆 res1 = chain_with_memory.invoke( {"input": "你好"}, config={"configurable": {"session_id": "user1"}} ) res2 = chain_with_memory.invoke( {"input": "刚才我说了什么?"}, config={"configurable": {"session_id": "user1"}} )

2. 核心特点

  • 绑定时机:链路创建完成后动态包装记忆和业务逻辑彻底分离
  • 数据流转:历史消息读取、拼接、回写全部显式可控,可拦截、改写。
  • 耦合度:完全解耦:
    • 原始base_chain可单独使用(无记忆模式);
    • 可给同一条基础链,包装多套不同记忆规则。
  • 多会话原生依靠session_id做会话隔离,天然适配多用户、多会话。
  • 灵活性
    1. 临时关闭记忆:直接调用原始base_chain即可,无需新建实例;
    2. 局部记忆:仅对链路中某一个子 Runnable单独包装,实现局部状态;
    3. 替换记忆存储:只修改get_history函数,业务链不动。

四、关键差异点对点对比

表格

对比维度传统 LLMChain + MemoryLCEL +RunnableWithMessageHistory
接入位置构造函数参数,创建链时绑定外层包装,链定义完成后追加
耦合关系强耦合,链与记忆绑定为整体完全解耦,业务链、记忆相互独立
启用 / 关闭记忆需新建不同实例,无法动态切换切换调用「原链 / 包装后链」即可
会话隔离手动维护多组 Chain+Memory,繁琐原生session_id隔离,开箱即用
作用范围整条链统一生效,不支持局部记忆

可对单个节点 / 子链路单独加记忆

可任何被包装的链进行记忆。

记忆读写逻辑内部黑盒,无法干预全流程透明,可自定义拦截、改写
复用性带记忆的链无法拆分为无记忆链路基础链可反复复用,按需加记忆

五、拓展场景对比(直观体现差距)

场景 1:同一条链路,交替使用「有记忆 / 无记忆」

  • 传统 LLMChain:必须创建两个实例

    python

    运行

    # 无记忆 chain_no_mem = LLMChain(llm=llm, prompt=prompt) # 有记忆 chain_with_mem = LLMChain(llm=llm, prompt=prompt, memory=memory)
  • LCEL:只写一条基础链,按需选择调用对象

    python

    运行

    # 无记忆:调用 base_chain base_chain.invoke(...) # 有记忆:调用包装后的链 chain_with_memory.invoke(..., config=...)

场景 2:仅给复杂链路中的某一段加记忆

  • 传统 LLMChain 体系:几乎无法实现,所有组合链全局共用一套记忆。
  • LCEL:天然支持局部包装

    python

    运行

    # 整条链路:A → 带记忆的B → C part_b_with_mem = RunnableWithMessageHistory(part_b, get_history) # RunnableWithMessageHistory,被包装后,该链与其他链一同对等,进行组合, full_chain = part_a | part_b_with_mem | part_c

六、一句话总结

  1. 传统 LLMChain:记忆是链的一部分,造链的时候就把记忆 “装进去”,一体成型,改不了、拆不开;
  2. LCEL:记忆是附加功能壳子,原有链路保持纯粹,想加记忆就外层包一层,想去掉就直接用原链路,灵活、解耦、易维护。
http://www.rkmt.cn/news/1457791.html

相关文章:

  • 超越默认编辑器:用QStyledItemDelegate为你的Qt表格打造专业级数据录入体验
  • AutoJs Pro 7.0.4-1 保姆级脚本实战:从零写一个快手极速版自动化脚本(附完整源码)
  • 终极指南:5个简单步骤使用MediaCreationTool.bat轻松安装Windows 11,完整绕过硬件限制
  • AI编程智能体协作失败:两个模型合作效果不如一个
  • AUTOSAR SPI实战避坑:从SyncTransmit阻塞到AsyncTransmit回调,你的车规级通信选对了吗?
  • 多层组织光传输仿真工具:支持自定义参数与三类光学响应输出
  • STM32F103 DAC输出不稳定?排查这几点让你的模拟电压更精准(附ADC闭环验证)
  • 2026年知名的上海排烟窗/三角型排烟窗/电动排烟窗口碑好的厂家推荐 - 行业平台推荐
  • 2026年靠谱的深圳整厂打包回收/深圳闲置设备回收/深圳厂房拆除回收高口碑品牌推荐 - 品牌宣传支持者
  • 用泡沫芯材DIY战斗机器人:低成本入门机器人制作全攻略
  • 用Python跑通癌症风险因素组合分析全流程:从体检数据离散化到高置信规则输出
  • 从蓝牙到Wi-Fi:拆解GMSK和OFDM,看主流无线通信协议背后的调制技术选型
  • 记录Linux io(文件io)
  • AUTOSAR SPI实战避坑:SyncTransmit卡死?AsyncTransmit回调丢失?从源码角度捋清调用机制
  • 别再只做词频统计了!用jieba自定义词典挖掘文本的‘专业密度’
  • 线上 SVM 核函数选择耗时不明?一次关于 Python 闭包无侵入监控的硬核实战
  • PHP对象关系映射与PDO实战
  • DeepONet非线性算子学习深度解析:从理论到实战的高效应用指南
  • 从cfssl到kubectl:一份给开发者的K8s TLS证书“避坑”实操指南(含常见报错排查)
  • 3步打造你的QQ空间数字回忆档案馆:永久保存青春时光的终极方案
  • STCTS语义编解码:语音通信的80bps革命
  • 具身智能研究现状与未来前景(十):未来前景与核心挑战——通向通用具身智能的关键路径
  • 告别EV2400!用STM32F407自制BQ40Z50电池监控器,成本直降(固件BQ40Z50-R1)
  • 第00篇:CSS导学文档
  • GenZ混合模型:基础模型与统计建模的融合实践
  • 从游戏引擎到飞控:手把手教你用UE4+Rflysim+Simulink搭建沉浸式无人机HIL仿真环境
  • 保姆级教程:用BC35-G模块和AT指令,5分钟搞定NBIOT设备接入OneNET平台
  • AntiDupl:开源智能图片去重工具完全指南
  • Claude 3.5 Sonnet 的 artifacts 功能,怎么实现一键生成办公文档?
  • 2026年6月市场做得好的同步带厂商推荐,同步轮/同步带/齿轮/橡胶同步带/同步带轮,同步带供应商口碑推荐 - 品牌推荐师