7.LCEL 五大核心Runnable组件

LCEL 五大核心Runnable组件

前置统一依赖与环境配置

1. 安装依赖

pip install langchain langchain-core langchain-openai loguru python-dotenv

2. .env 文件配置(项目根目录新建)

aliQwen-api=你的阿里云通义千问API Key

3. 公共基础封装(每个文件开头引入)

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os
from langchain.chat_models import init_chat_model
from loguru import logger

# 统一初始化通义千问兼容接口模型
model = init_chat_model(
    model="qwen3.5:9b",
    model_provider="openai",
    base_url="http://localhost:11434/v1"
)
parser = StrOutputParser()

一、LCEL基础顺序链 RunnableSequence

核心概念

| 管道符底层是 RunnableSequence,串行执行,上游输出作为下游输入;标准链路:Prompt | Model | Parser。

代码

import os
from dotenv import load_dotenv
from loguru import logger
from langchain.chat_models import init_chat_model
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

# 1. 定义带占位符提示词
chat_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是专业AI助手,回答控制在100字以内"),
    ("human", "{question}")
])

# 方式1:分步手动执行(调试用)
def run_step_by_step():
    prompt_msg = chat_prompt.invoke({"question": "什么是LCEL?"})
    logger.info("【分步-完整提示词】", prompt_msg)
    ai_msg = model.invoke(prompt_msg)
    text = parser.invoke(ai_msg)
    logger.info("【分步-最终文本结果】", text)

# 方式2:管道链一键执行(业务标准写法)
chain = chat_prompt | model | parser
def run_pipeline():
    res = chain.invoke({"question": "什么是LCEL?"})
    logger.info("【管道链执行结果】", res)

if __name__ == "__main__":
    run_step_by_step()
    print("-" * 50)
    run_pipeline()
  1. 分步执行:拆分模板填充、模型调用、文本解析三步,适合排查每一层原始数据;
  2. 管道链 |:自动封装顺序执行器,仅传入原始参数字典即可完成全流程;
  3. StrOutputParser:剥离模型返回的 AIMessage 对象,提取纯字符串文本。

二、多步串行复合链(多轮模型调用)

核心概念

连续调用2次及以上大模型,上游输出是纯文本,下游模板需要指定key入参,用 lambda 做字典格式转换。

代码

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os
from langchain.chat_models import init_chat_model
from loguru import logger


model = init_chat_model(
    model="qwen3.5:9b",
    model_provider="openai",
    base_url="http://localhost:11434/v1"
)
parser = StrOutputParser()

# 子链1:根据topic生成中文简介
prompt_cn = ChatPromptTemplate.from_messages([
    ("system", "简短中文介绍,50字内"),
    ("human", "介绍:{topic}")
])
chain_cn = prompt_cn | model | parser

# 子链2:将中文文本翻译英文
prompt_en = ChatPromptTemplate.from_messages([
    ("system", "直译英文,简洁"),
    ("human", "{input_text}")
])
chain_en = prompt_en | model | parser

# 组合链路:中文生成 → lambda包装字段 → 英文翻译
full_chain = chain_cn | (lambda text: {"input_text": text}) | chain_en

if __name__ == "__main__":
    result = full_chain.invoke({"topic": "LangChain LCEL"})
    logger.info("多轮串行最终翻译结果:", result)
  1. 两条独立子链入参key不同,无法直接串联;
  2. lambda接收上游纯文本,封装为下游需要的 {"input_text": xxx}
  3. 执行链路:{"topic":xxx} → chain_cn输出文本 → lambda转换字典 → chain_en翻译。

三、自定义函数节点 RunnableLambda

核心概念

RunnableLambda 将任意Python普通函数包装为可接入管道的执行单元,用于日志打印、数据清洗、参数转换。

代码

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os
from langchain.chat_models import init_chat_model
from langchain_core.runnables import RunnableLambda

model = init_chat_model(
    model="qwen3.5:9b",
    model_provider="openai",
    base_url="http://localhost:11434/v1"
)
parser = StrOutputParser()

# 自定义中间处理函数:打印中间数据并转换格式
def debug_handle(x):
    print(f"【Lambda中间节点原始数据】{x}")
    return {"content": x}

# 包装为Runnable节点
debug_node = RunnableLambda(debug_handle)

# 子链
prompt_ask = ChatPromptTemplate.from_messages([("human", "简单解释{subject}")])
chain_ask = prompt_ask | model | parser
prompt_trans = ChatPromptTemplate.from_messages([("human", "把下面内容转英文:{content}")])
chain_trans = prompt_trans | model | parser

# 插入自定义节点的完整链路
full_chain = chain_ask | debug_node | chain_trans

if __name__ == "__main__":
    res = full_chain.invoke({"subject": "RunnableLambda"})
    logger.info("最终输出:", res)
  1. RunnableLambda(func) 把普通函数转为管道可识别组件;
  2. 函数入参=上游链路输出,返回值=下游链路输入;
  3. 适用场景:调试打印、文本过滤、字段映射、自定义校验。

四、并行多任务 RunnableParallel

核心概念

多条子链共用同一输入,并发执行,全部完成后以字典聚合结果,互不阻塞,适合同一输入多风格/多语言生成。

完整可运行代码

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os
from langchain.chat_models import init_chat_model
from langchain_core.runnables import RunnableLambda, RunnableParallel

model = init_chat_model(
    model="qwen3.5:9b",
    model_provider="openai",
    base_url="http://localhost:11434/v1"
)
parser = StrOutputParser()

# 子链1:中文简介
prompt_cn = ChatPromptTemplate.from_messages([("human", "中文简短介绍{topic}")])
chain_cn = prompt_cn | model | parser

# 子链2:英文简介
prompt_en = ChatPromptTemplate.from_messages([("human", "English brief intro {topic}")])
chain_en = prompt_en | model | parser

# 构建并行链,key为结果标识
parallel_chain = RunnableParallel({
    "zh_content": chain_cn,
    "en_content": chain_en
})

if __name__ == "__main__":
    output = parallel_chain.invoke({"topic": "RunnableParallel"})
    logger.info("并行聚合结果:", output)
    # 打印链路可视化图
    parallel_chain.get_graph().print_ascii()
  1. 并行链内所有子链共享输入参数 {"topic": xxx}
  2. 返回字典结构 {"zh_content": "中文结果", "en_content": "英文结果"}
  3. get_graph().print_ascii() 打印链路拓扑,用于复杂流程可视化调试。

五、条件路由分支 RunnableBranch

核心概念

类似if-elif-else路由,根据输入自定义判断逻辑,匹配对应子链执行,兜底分支处理未匹配场景。

代码

from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
import os
from langchain.chat_models import init_chat_model
from langchain_core.runnables import RunnableLambda, RunnableParallel, RunnableBranch

model = init_chat_model(
    model="qwen3.5:9b",
    model_provider="openai",
    base_url="http://localhost:11434/v1"
)
parser = StrOutputParser()

# 三套翻译提示词
prompt_jp = ChatPromptTemplate.from_messages([("system", "日语翻译专家"), ("human", "{query}")])
prompt_kr = ChatPromptTemplate.from_messages([("system", "韩语翻译专家"), ("human", "{query}")])
prompt_en = ChatPromptTemplate.from_messages([("system", "英语翻译专家"), ("human", "{query}")])

# 自定义路由判断函数
def detect_language(inputs):
    q = inputs["query"]
    if "日语" in q:
        return "jp"
    elif "韩语" in q:
        return "kr"
    else:
        return "en"

# 构建分支路由链
branch_chain = RunnableBranch(
    # 条件1:匹配日语分支
    (lambda x: detect_language(x) == "jp", prompt_jp | model | parser),
    # 条件2:匹配韩语分支
    (lambda x: detect_language(x) == "kr", prompt_kr | model | parser),
    # 默认兜底英语分支
    prompt_en | model | parser
)

# 批量测试
test_list = [
    {"query": "用日语翻译:你好"},
    {"query": "用韩语翻译:你好"},
    {"query": "翻译:你好"}
]

if __name__ == "__main__":
    for item in test_list:
        lang_tag = detect_language(item)
        logger.info(f"检测语种标识:{lang_tag},输入:{item}")
        res = branch_chain.invoke(item)
        logger.info(f"分支输出:{res}\n")
  1. RunnableBranch 入参格式:(判断lambda, 对应子链), (判断lambda, 子链), 默认子链
  2. 判断lambda接收完整输入字典,调用自定义函数识别关键词;
  3. 业务场景:意图分流、多语种路由、客服问答分类。

五大Runnable核心对比总结

组件实现方式 核心类 执行逻辑 典型业务场景
基础管道 自动生成RunnableSequence 顺序串行,单流程 简单问答、单次翻译
多轮串行 管道+lambda转换 多次模型串行,格式转换 生成内容→润色→翻译
自定义函数 RunnableLambda 插入自定义Python逻辑 中间调试、数据清洗
并发多任务 RunnableParallel 多子链并行,结果聚合 多语言输出、多风格文案
条件路由 RunnableBranch 输入匹配分支,动态路由 语种分流、用户意图分发
posted @ 2026-08-17 21:28  _丑小鸭  阅读(1)  评论(0)    收藏  举报