📌 核心结论(TL;DR)
-
LCEL 灵魂 :LangChain 表达式语言(LCEL)通过重载管道符
|,将实现了Runnable协议的组件(模型、解析器等)像积木一样串联,实现优雅的链式编程。 -
动态切换 :利用
init_chat_model结合configurable_fields,可以在不修改底层代码的情况下,在运行时动态切换大模型厂商(如 OpenAI 切 DeepSeek)并调整参数。 -
组件解耦 :通过 LCEL 组装,
Prompt、Model、Parser各司其职,极大地提高了代码的复用性和可维护性。
🔍 一、 原理图解与核心概念
1. 什么是 Runnable 协议?
在 LangChain 中,能使用 | 符号连接的前提是,该组件必须实现 Runnable 协议。它规定了组件必须具备的核心能力:
-
invoke:单次同步调用。 -
batch:批量并行调用。 -
stream:流式输出(打字机效果)。大语言模型(ChatOpenAI)、输出解析器(StrOutputParser)、甚至提示词模板(PromptTemplate)全部实现了此协议。
2. LCEL 的链式魔法
python
# 将模型输出直接传给字符串解析器
chain = model | parser
底层相当于调用了 RunnableSequence(first=model, last=parser)。数据像流水线一样,从上游流向下游。
💻 二、 精选核心代码片段
1. 基础链式调用(以 DeepSeek 为例)
python
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.output_parsers import StrOutputParser
model = ChatOpenAI(
model="deepseek-chat",
api_key="your_api_key",
base_url="https://api.deepseek.com", # 注意:目前官方推荐使用根路径,无需 /v1
)
messages = [
SystemMessage(content="请补全一段故事,100个字以内:"),
HumanMessage(content="一只猫正在__?")
]
# 使用 LCEL 构建链
chain = model | StrOutputParser()
print(chain.invoke(messages))
2. 进阶:运行时动态切换模型(DeepSeek 与 Ollama 无缝切换)
通过 configurable_alternatives,实现极高的灵活性,且无需安装额外的模型集成包。
python
from langchain_openai import ChatOpenAI
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage
from langchain_core.runnables import ConfigurableField
# 1. 定义默认的基础模型(云端 DeepSeek)
base_model = ChatOpenAI(
model="deepseek-chat",
api_key="your_deepseek_api_key",
base_url="https://api.deepseek.com",
temperature=0.3
)
# 2. 挂载备选模型(本地 Ollama)
model = base_model.configurable_alternatives(
ConfigurableField(id="llm_provider"),
default_key="deepseek",
ollama=ChatOllama(
model="deepseek-r1:1.5b", # 确保你本地已拉取该模型
base_url="http://127.0.0.1:11434",
temperature=0.3
)
)
messages = [HumanMessage(content="请用一句话介绍你自己。")]
# ==========================================
# 场景一:使用云端 DeepSeek(默认走 default_key)
# ==========================================
print("=== 使用云端 DeepSeek ===")
result_cloud = model.invoke(messages)
print(result_cloud.content)
# ==========================================
# 场景二:动态切换到本地 Ollama
# ==========================================
print("\n=== 动态切换到本地 Ollama ===")
result_local = model.invoke(
messages,
config={
"configurable": {
"llm_provider": "ollama" # 这里指定走备选模型
}
}
)
print(result_local.content)
(完整的包含多轮对话与异常处理的代码已上传至 Gitee 仓库)

⚠️ 三、 踩坑排查排雷
-
报错
UnicodeEncodeError: 'ascii' codec can't encode characters:httpx默认用 ASCII 编码 HTTP 请求头。如果 API Key 里混入了中文空格、全角字符或不可见字符,就会崩溃。排查 :重新复制纯 ASCII 的 Key,或在代码中使用key.encode("ascii", errors="ignore").decode("ascii")清洗。 -
报错
Unsupported model_provider='deepseek':init_chat_model需要安装langchain-deepseek集成包才能识别。排查 :若因 Python 版本限制无法安装,直接用ChatOpenAI并指定base_url即可完美兼容。 -
Connection Error或Timeout:如果你在国内直连 OpenAI 会报错;或者本地 Ollama 服务没有启动。排查 :检查代理设置,或确保终端执行过ollama run <model_name>启动本地服务。 -
链最后输出了
AIMessage对象而非字符串 :忘了在链的最后加StrOutputParser()。大模型原生返回的是包含元数据的AIMessage,解析器负责提取纯文本。
