ArcGIS国土三调VCT工具箱V1.2:转换、检查与批处理实战
2026/10/26 0:05:35
记忆组件(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": "刚才我说了什么?"})history由 Chain 内部自动从 Memory 读取、自动写入,属于黑盒逻辑。LLMChain + Memory组合,代码冗余。LCEL 原生链路(prompt | llm)完全无状态、无记忆,通过RunnableWithMessageHistory对已有链路做二次包装,实现记忆能力。原有业务链路代码一行不用改。
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"}} )base_chain可单独使用(无记忆模式);session_id做会话隔离,天然适配多用户、多会话。base_chain即可,无需新建实例;get_history函数,业务链不动。表格
| 对比维度 | 传统 LLMChain + Memory | LCEL +RunnableWithMessageHistory |
|---|---|---|
| 接入位置 | 构造函数参数,创建链时绑定 | 外层包装,链定义完成后追加 |
| 耦合关系 | 强耦合,链与记忆绑定为整体 | 完全解耦,业务链、记忆相互独立 |
| 启用 / 关闭记忆 | 需新建不同实例,无法动态切换 | 切换调用「原链 / 包装后链」即可 |
| 会话隔离 | 手动维护多组 Chain+Memory,繁琐 | 原生session_id隔离,开箱即用 |
| 作用范围 | 整条链统一生效,不支持局部记忆 | 可对单个节点 / 子链路单独加记忆 可任何被包装的链进行记忆。 |
| 记忆读写逻辑 | 内部黑盒,无法干预 | 全流程透明,可自定义拦截、改写 |
| 复用性 | 带记忆的链无法拆分为无记忆链路 | 基础链可反复复用,按需加记忆 |
python
运行
# 无记忆 chain_no_mem = LLMChain(llm=llm, prompt=prompt) # 有记忆 chain_with_mem = LLMChain(llm=llm, prompt=prompt, memory=memory)python
运行
# 无记忆:调用 base_chain base_chain.invoke(...) # 有记忆:调用包装后的链 chain_with_memory.invoke(..., config=...)python
运行
# 整条链路:A → 带记忆的B → C part_b_with_mem = RunnableWithMessageHistory(part_b, get_history) # RunnableWithMessageHistory,被包装后,该链与其他链一同对等,进行组合, full_chain = part_a | part_b_with_mem | part_c