代码中使用了 Chain.run
方法(例如在 cate_chain.run(city="成都")
中),会触发LangChainDeprecationWarning
,提示该方法在 LangChain 0.1.0 中已被废弃,并将在 1.0 中移除。官方推荐使用 invoke
方法替代。本回答将基于 LangChain 0.3.x,详细解释如何将 Chain.run
迁移到 Chain.invoke
,并提供代码示例。
废弃告警:
LangChainDeprecationWarning: The methodChain.run
was deprecated in langchain 0.1.0 and will be removed in 1.0. Use :meth:~invoke
instead.
cate_chain.run(city =“成都”) ……
为什么需要迁移?
Chain.run
是 LangChain 早期用于简化链式调用的方法,允许以单一输入快速执行链,但存在以下问题:
- 接口不一致:与 LangChain 的新运行时接口(如
invoke
、stream
、batch
)不统一。 - 功能有限:仅支持单一输入(字符串或键值对),无法处理复杂输入(如消息列表或多变量)。
- 灵活性差:不支持现代功能,如结构化输出、工具调用或异步调用。
invoke
方法是推荐的替代方案,优势包括:
- 统一接口:与 LangChain 0.3.x 的运行时 API(
invoke
、stream
、batch
)一致。 - 支持复杂输入:接受字典、消息列表等多种输入格式,适应不同链的需求。
- 功能丰富:支持异步调用、流式输出和工具调用。
- 长期支持:是 LangChain 的标准接口,不会废弃。
迁移步骤
以下是将 Chain.run
迁移到 Chain.invoke
的详细步骤,假设你的链使用 OpenAI 模型,并处理城市相关的查询。
1. 分析原始代码
假设你的代码如下,使用 Chain.run
执行一个链(可能基于 LLMChain
或其他链):
import os
os.environ["OPENAI_API_KEY"] = "Your OpenAI API Key"
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
# 定义提示模板
prompt = PromptTemplate.from_template(
"请描述{city}的美食文化。"
)
# 初始化 LLM
llm = ChatOpenAI(temperature=0, model="gpt-4o-mini")
# 初始化链
cate_chain = LLMChain(prompt=prompt, llm=llm, verbose=True)
# 调用链
response = cate_chain.run(city="成都")
print(response)
输出示例:
成都的美食文化以川菜为核心,麻辣鲜香是其标志性特点。代表菜品包括麻婆豆腐、辣子鸡、火锅和串串香。成都小吃如担担面、龙抄手和钟水饺也深受欢迎,街头巷尾的苍蝇馆子展现了浓厚的市井风情。
问题:
Chain.run
已废弃,需替换为Chain.invoke
。LLMChain
本身也已废弃(在 LangChain 0.1.17 中,推荐使用RunnableSequence
),需一并迁移。run
接受单一输入(如city="成都"
),invoke
要求字典输入(如{"city": "成都"}
)。
2. 安装必要依赖
确保安装 LangChain 0.3.x 和 langchain-openai
:
pip install --upgrade langchain langchain-openai
3. 迁移到 invoke
和 RunnableSequence
以下是迁移后的代码,替换 LLMChain
为 RunnableSequence
,并将 run
改为 invoke
:
import os
os.environ["OPENAI_API_KEY"] = "Your OpenAI API Key"
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
# 定义提示模板
prompt = PromptTemplate.from_template(
"请描述{city}的美食文化。"
)
# 初始化 LLM
llm = ChatOpenAI(temperature=0, model="gpt-4o-mini")
# 创建 RunnableSequence
chain = prompt | llm
# 调用链
response = chain.invoke({"city": "成都"})
print(response.content)
输出示例:
成都的美食文化以川菜为核心,麻辣鲜香是其标志性特点。代表菜品包括麻婆豆腐、辣子鸡、火锅和串串香。成都小吃如担担面、龙抄手和钟水饺也深受欢迎,街头巷尾的苍蝇馆子展现了浓厚的市井风情。
代码说明
- OpenAI API 密钥:
- 通过
os.environ["OPENAI_API_KEY"]
设置,确保 OpenAI 模型正常调用。 - 将
"Your OpenAI API Key"
替换为你的实际密钥。
- 通过
- 提示模板:
- 使用
PromptTemplate
,与原代码一致,接收变量{city}
。
- 使用
- LLM:
- 使用
langchain_openai.ChatOpenAI
,参数(如temperature=0
、model="gpt-4o-mini"
)不变。
- 使用
- RunnableSequence:
- 通过
prompt | llm
创建链,替代LLMChain
。 |
运算符将提示模板的输出传递给 LLM。
- 通过
- 调用方法:
- 替换
cate_chain.run(city="成都")
为chain.invoke({"city": "成都"})
。 - 输入必须是字典,键对应提示模板变量(
city
)。 - 输出为
AIMessage
对象,使用response.content
获取文本(run
直接返回字符串)。
- 替换
4. 使用 ChatPromptTemplate
(推荐)
ChatOpenAI
更适合搭配 ChatPromptTemplate
,以支持消息格式。以下是优化后的代码:
import os
os.environ["OPENAI_API_KEY"] = "Your OpenAI API Key"
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个美食专家。请描述给定城市的美食文化。"),
("human", "请描述{city}的美食文化。")
])
# 初始化 LLM
llm = ChatOpenAI(temperature=0, model="gpt-4o-mini")
# 创建 RunnableSequence
chain = prompt | llm
# 调用链
response = chain.invoke({"city": "成都"})
print(response.content)
输出示例:
成都的美食文化以川菜为核心,麻辣鲜香是其标志性特点。代表菜品包括麻婆豆腐、辣子鸡、火锅和串串香。成都小吃如担担面、龙抄手和钟水饺也深受欢迎,街头巷尾的苍蝇馆子展现了浓厚的市井风情。
说明:
- 使用
ChatPromptTemplate
,定义系统消息和用户消息,适合聊天模型。 - 逻辑与
PromptTemplate
相同,但更结构化,输出为AIMessage
。 - 输入仍为字典(
{"city": "成都"}
)。
5. 添加对话历史(可选)
如果你的链需要支持对话历史,可以结合 RunnableWithMessageHistory
:
import os
os.environ["OPENAI_API_KEY"] = "Your OpenAI API Key"
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个美食专家。请根据对话历史回答问题。"),
MessagesPlaceholder(variable_name="history"),
("human", "{input}")
])
# 初始化 LLM
llm = ChatOpenAI(temperature=0, model="gpt-4o-mini")
# 创建 RunnableSequence
runnable = prompt | llm
# 初始化消息历史存储
store = {}
def get_session_history(session_id: str) -> ChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
# 创建 RunnableWithMessageHistory
chain = RunnableWithMessageHistory(
runnable,
get_session_history,
input_messages_key="input",
history_messages_key="history"
)
# 调用链
session_id = "user1"
response = chain.invoke(
{"input": "请描述成都的美食文化。"},
config={"configurable": {"session_id": session_id}}
)
print(response.content)
response = chain.invoke(
{"input": "有哪些著名的小吃?"},
config={"configurable": {"session_id": session_id}}
)
print(response.content)
输出示例:
成都的美食文化以川菜为核心,麻辣鲜香是其标志性特点。代表菜品包括麻婆豆腐、辣子鸡、火锅和串串香。成都小吃如担担面、龙抄手和钟水饺也深受欢迎,街头巷尾的苍蝇馆子展现了浓厚的市井风情。
成都的著名小吃包括担担面、龙抄手、钟水饺、甜水面、赖汤圆和夫妻肺片。这些小吃以麻辣或鲜香口味为主,深受本地人和游客喜爱。
说明:
- 使用
MessagesPlaceholder
插入对话历史。 RunnableWithMessageHistory
管理历史,ChatMessageHistory
存储消息。session_id
确保会话隔离。- 输入为字典,
input
键对应用户输入。
6. 使用数据库存储(可选)
若需持久化对话历史,使用 SQLChatMessageHistory
:
from langchain_community.chat_message_histories import SQLChatMessageHistory
def get_session_history(session_id: str) -> SQLChatMessageHistory:
return SQLChatMessageHistory(
session_id=session_id,
connection_string="sqlite:///conversation_history.db"
)
替换 get_session_history
函数,历史将保存到 SQLite 数据库。
7. 测试与验证
- 运行迁移后的代码,确认输出与原
run
方法一致。 - 若添加对话历史,测试多轮对话,验证历史保留。
- 检查 OpenAI API 密钥有效性,避免
AuthenticationError
。 - 确保输出访问正确(
response.content
代替直接response
)。
注意事项
- API 密钥安全:
- 避免硬编码密钥,推荐使用
.env
文件和python-dotenv
:from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的 OPENAI_API_KEY
- 确保密钥支持指定模型(如
gpt-4o-mini
)。
- 避免硬编码密钥,推荐使用
- 输入格式:
run
接受单一输入(如city="成都"
)。invoke
要求字典输入(如{"city": "成都"}
),需调整调用方式。
- 输出格式:
run
返回字符串。invoke
返回AIMessage
(ChatOpenAI
)或字符串(非聊天模型),需使用response.content
。
- LLMChain 迁移:
- 原代码使用
LLMChain
,已替换为RunnableSequence
(prompt | llm
)。 - 若链类型不同(如
StuffDocumentsChain
),需确认具体链的输入/输出格式。
- 原代码使用
- 性能:
invoke
与run
性能相当,但RunnableSequence
因 LCEL 优化更高效。- 数据库存储可能增加轻微延迟。
常见问题
Q1:可以继续使用 Chain.run
吗?
A:可以,但不建议。它将在 LangChain 1.0 中移除,且不支持复杂输入。迁移到 invoke
更安全。
Q2:invoke
和 run
有什么区别?
A:invoke
支持字典输入、消息列表等复杂格式,且与现代 API(如 stream
、batch
)一致;run
仅支持单一输入。
Q3:如何处理对话历史?
A:使用 RunnableWithMessageHistory
和 ChatMessageHistory
,如第 5 步所示。
Q4:如果链不是 LLMChain
怎么办?
A:确认链的输入/输出格式,调整为 invoke
的字典输入。大多数链支持 invoke
,但需检查具体文档。
总结
从 Chain.run
迁移到 Chain.invoke
的步骤包括:
- 安装
langchain
和langchain-openai
。 - 替换
LLMChain
为RunnableSequence
(prompt | llm
)。 - 替换
chain.run(city="成都")
为chain.invoke({"city": "成都"})
。 - 调整输出访问方式(
response.content
代替response
)。 - 可选添加
RunnableWithMessageHistory
实现对话历史。 - 设置
OPENAI_API_KEY
确保 OpenAI 模型访问。