本文 对《LangChain》一文中的 Chain 与 LCEL 部分的示例进行详细的展示。

先回顾下 在LangChain框架中,Chain(链) 和 LCEL(LangChain Expression Language) 是两个密切相关但本质不同的概念。

Chain(链): 是LangChain中处理流程的抽象概念,指将多个组件(模型、工具、逻辑)串联成一个可执行的任务序列。

LangChain Expression Language(LCEL)是一种声明式语言,可轻松组合不同的调用顺序构成 Chain。LCEL 自创立之初就被设计为能够支持将原型投入生产环境,无需代码更改,从最简单的“提示+LLM”链到最复杂的链(已有用户成功在生产环境中运行包含数百个步骤的 LCEL Chain)。

在本文中 LCEL 产生的对象,被叫做 runnable 或 chain,经常两种叫法混用。本质就是一个自定义调用流程。

1、Pipeline 式调用 PromptTemplate, LLM 和 OutputParser

from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from pydantic import BaseModel, Field, validator
from typing import List, Dict, Optional
from enum import Enum
import json
# 输出结构
class SortEnum(str, Enum):
data = 'data'
price = 'price' class OrderingEnum(str, Enum):
ascend = 'ascend'
descend = 'descend' class Semantics(BaseModel):
name: Optional[str] = Field(description="套餐名称", default=None)
price_lower: Optional[int] = Field(description="价格下限", default=None)
price_upper: Optional[int] = Field(description="价格上限", default=None)
data_lower: Optional[int] = Field(description="流量下限", default=None)
data_upper: Optional[int] = Field(description="流量上限", default=None)
sort_by: Optional[SortEnum] = Field(description="按价格或流量排序", default=None)
ordering: Optional[OrderingEnum] = Field(description="升序或降序排列", default=None) # Prompt 模板
prompt = ChatPromptTemplate.from_messages(
[
("system", "你是一个语义解析器。你的任务是将用户的输入解析成JSON表示。不要回答用户的问题。"),
("human", "{text}"),
]
) # 模型
llm = ChatOpenAI(model="gpt-4o", temperature=0) structured_llm = llm.with_structured_output(Semantics) # LCEL 表达式
runnable = (
{"text": RunnablePassthrough()} | prompt | structured_llm
) # 直接运行
ret = runnable.invoke("不超过100元的流量大的套餐有哪些")
print(
json.dumps(
ret.dict(),
indent = 4,
ensure_ascii=False
)
)

输出结果如下:

流式输出,就是那种一个字一个字蹦的输出,大家可以用下面代码体验一下玩一玩

prompt = PromptTemplate.from_template("讲个关于{topic}的笑话")

runnable = (
{"topic": RunnablePassthrough()} | prompt | llm | StrOutputParser()
) # 流式输出
for s in runnable.stream("李华"):
print(s, end="", flush=True)

2、用LECL实现RAG

我们通过分割一个 pdf 文件形成向量库,示例如下:

from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain_community.document_loaders import PyMuPDFLoader # 加载文档
loader = PyMuPDFLoader("llama2.pdf")
pages = loader.load_and_split() # 文档切分
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=300,
chunk_overlap=100,
length_function=len,
add_start_index=True,
) texts = text_splitter.create_documents(
[page.page_content for page in pages[:4]]
) # 灌库
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
db = FAISS.from_documents(texts, embeddings) # 检索 top-2 结果
retriever = db.as_retriever(search_kwargs={"k": 2})
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough # Prompt模板
template = """Answer the question based only on the following context:
{context} Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template) # Chain
rag_chain = (
{"question": RunnablePassthrough(), "context": retriever}
| prompt
| llm
| StrOutputParser()
) rag_chain.invoke("Llama 2有多少参数")

输出结果如下:

3、LECL 的意义是什么

在 LangChain 框架中,LCEL(LangChain Expression Language)的意义主要体现在增强模块间的解耦能力、提升流程编排的灵活性,并为复杂的 LLM(大语言模型)应用构建提供标准化的逻辑表达工具。以下是具体分析:

一、LangChain 中的模块解耦需求

LangChain 的核心目标是通过组合不同的组件(如 LLMs、Prompt 模板、工具调用、内存管理等)构建复杂的应用流程。例如:

  • 组件类型:LLM 调用、工具(如计算器、数据库查询)、内存(对话历史存储)、Prompt 模板、链(Chain,如 SequentialChain、RouterChain)等。

  • 解耦痛点

    传统方式下,组件间的交互逻辑(如条件分支、数据转换、循环控制)可能硬编码在链的代码中,导致:

    • 链的逻辑难以复用或动态调整;
    • 组件更换(如从 OpenAI 切换到 Anthropic)时,需修改链的控制逻辑;
    • 复杂流程(如多轮工具调用、动态路由)的编排缺乏标准化表达。

二、LCEL 的核心意义:作为模块间的 “逻辑中介”

LCEL 是 LangChain 设计的一套声明式表达式语言,用于描述组件间的数据流动和逻辑控制。其核心价值体现在以下方面:

1. 分离逻辑控制与组件实现

  • 传统硬编码问题

    例如,在链中通过 Python 代码实现条件判断:

    if result.score > 0.8:
    return llm.predict(prompt.format(data=result))
    else:
    return tool.query(data=result)

    此时,条件逻辑与链的代码强耦合,难以复用或动态修改。

  • LCEL 的解耦作用

    将条件逻辑抽象为 LCEL 表达式,存储在配置中:

    condition: "{{ score > 0.8 }}"
    then:
    action: llm.predict
    params:
    prompt: "用户输入:{{ input }}"
    else:
    action: tool.query
    params:
    data: "{{ input }}"
    • 链的代码仅负责解析 LCEL 表达式,根据结果调用组件;
    • 逻辑变更时只需修改表达式,无需调整链的代码,实现 “逻辑外置”。

2. 标准化组件交互协议

LCEL 定义了一套统一的语法规则(如变量引用、运算符、函数调用),作为不同组件间的 “通信语言”:

  • 数据传递:通过 {{ variable }} 引用上游组件的输出(如 LLM 的返回结果、工具的查询数据)。
  • 逻辑操作:支持算术运算(+-)、条件判断(if-else)、集合操作(mapfilter)等,避免不同组件自定义逻辑语法。
  • 函数扩展:可注册自定义函数(如 format_date()calculate_score()),供表达式调用,实现跨组件的逻辑复用。

示例

通过 LCEL 表达式编排多步流程:

from langchain.lcel import LCELChain

expression = """
let score = tool.calculate_score(input.data);
if (score > 0.6) {
return llm.generate(prompt: "高分结果:{{ score }}");
} else {
return tool.analyze(input.data);
}
""" chain = LCELChain.from_expression(expression, components={
"tool": MyCustomTool(),
"llm": OpenAI(temperature=0.1)
})
  • 组件(toolllm)仅需按约定输出数据字段,无需关心流程逻辑;
  • 链通过 LCEL 表达式动态调度组件,解耦组件与流程控制。

3. 支持动态流程编排与热更新

在 LangChain 中,复杂应用(如智能客服、数据分析助手)常需根据实时数据调整流程。LCEL 的声明式特性使其适合动态场景:

  • 场景 1:AB 测试

    通过后端配置不同的 LCEL 表达式,控制 A/B 组用户的流程分支(如优先调用工具 A 或工具 B),无需重启服务。
  • 场景 2:低代码平台

    用户通过可视化界面配置 LCEL 表达式(如拖拽生成 {{ order.amount > 1000 ? "大客户" : "普通客户" }}),快速生成定制化链,降低开发门槛。
  • 场景 3:实时策略调整

    在金融风控场景中,通过动态修改 LCEL 表达式(如调整风险评分阈值 score > 0.7 → score > 0.75),实时更新风控流程,而无需修改代码。

4. 提升组件复用性与可测试性

  • 组件复用

    标准化的 LCEL 接口使组件可插拔。例如,替换 LLM 提供商时,只需修改组件实例(如从 OpenAI 改为 Cohere),LCEL 表达式无需变更。

  • 独立测试

    可单独测试 LCEL 表达式的逻辑正确性,如:

    from langchain.lcel import evaluate
    
    # 测试条件表达式
    result = evaluate("{{ score > 0.8 ? 'pass' : 'fail' }}", context={"score": 0.9})
    assert result == "pass"

    无需启动完整的链或依赖外部服务,提升测试效率。

5. 适配多模态与复杂工具调用

LangChain 常需集成多种工具(如 SQL 查询、API 调用、文件解析),LCEL 可简化多模态数据的处理逻辑:

  • 示例:处理结构化数据

    expression = """
    let data = sql_tool.query("SELECT * FROM orders WHERE amount > {{ threshold }}");
    let summary = llm.summarize(text: json.stringify(data.rows));
    return summary;
    """
    • 通过 LCEL 链式调用 SQL 工具和 LLM,解耦数据查询与摘要生成逻辑;
    • 表达式清晰描述数据流动路径,避免代码层面的嵌套回调。

三、LCEL 与 LangChain 架构的协同

LCEL 的设计与 LangChain 的模块化架构深度协同,目标是构建 **“表达式驱动的智能应用”**:

  1. 底层组件层:提供标准化接口(如 call()parse()),供 LCEL 表达式调用;
  2. LCEL 层:作为逻辑编排层,通过表达式描述组件交互规则;
  3. 应用层:通过配置文件、API 动态注入 LCEL 表达式,快速组装不同功能的链。

这种分层设计使 LangChain 既能保持代码的简洁性,又能通过 LCEL 灵活应对复杂业务需求,尤其适合需要频繁调整逻辑的生成式 AI 场景(如智能文档处理、对话系统流程控制等)。

你应该懂的AI 大模型(五)之 LangChain 之 LCEL的更多相关文章

  1. AI大模型学习了解

    # 百度文心 上线时间:2019年3月 官方介绍:https://wenxin.baidu.com/ 发布地点: 参考资料: 2600亿!全球最大中文单体模型鹏城-百度·文心发布 # 华为盘古 上线时 ...

  2. 华为高级研究员谢凌曦:下一代AI将走向何方?盘古大模型探路之旅

    摘要:为了更深入理解千亿参数的盘古大模型,华为云社区采访到了华为云EI盘古团队高级研究员谢凌曦.谢博士以非常通俗的方式为我们娓娓道来了盘古大模型研发的"前世今生",以及它背后的艰难 ...

  3. 保姆级教程:用GPU云主机搭建AI大语言模型并用Flask封装成API,实现用户与模型对话

    导读 在当今的人工智能时代,大型AI模型已成为获得人工智能应用程序的关键.但是,这些巨大的模型需要庞大的计算资源和存储空间,因此搭建这些模型并对它们进行交互需要强大的计算能力,这通常需要使用云计算服务 ...

  4. 得益于AI,这五个行业岗位需求将呈现显著增长趋势

    得益于AI,这五个行业岗位需求将呈现显著增长趋势 人工智能与人类工作是当下许多人津津乐道的一个话题,而讨论的重点大多是围绕在"未来人工智能会不会抢走我们的工作"这个方面.本文作者 ...

  5. HBase实践案例:知乎 AI 用户模型服务性能优化实践

    用户模型简介 知乎 AI 用户模型服务于知乎两亿多用户,主要为首页.推荐.广告.知识服务.想法.关注页等业务场景提供数据和服务, 例如首页个性化 Feed 的召回和排序.相关回答等用到的用户长期兴趣特 ...

  6. zz独家专访AI大神贾扬清:我为什么选择加入阿里巴巴?

    独家专访AI大神贾扬清:我为什么选择加入阿里巴巴? Natalie.Cai 拥有的都是侥幸,失去的都是人生 ​关注她 5 人赞同了该文章 本文由 「AI前线」原创,原文链接:独家专访AI大神贾扬清:我 ...

  7. 阿里开源新一代 AI 算法模型,由达摩院90后科学家研发

    最炫的技术新知.最热门的大咖公开课.最有趣的开发者活动.最实用的工具干货,就在<开发者必读>! 每日集成开发者社区精品内容,你身边的技术资讯管家. 每日头条 阿里开源新一代 AI 算法模型 ...

  8. 看完它,你就全懂了十大Wifi芯片原厂!

    看完它,你就全懂了十大Wifi芯片原厂!   来源:全球物联网观察 概要:不知不觉中,WiFi几乎已攻占了整个世界.现在只要你上网,可能就离不开WiFi了. 2014年是物联网WiFi市场关键的转折期 ...

  9. 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展

    经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...

  10. 文心一言,通营销之学,成一家之言,百度人工智能AI大数据模型文心一言Python3.10接入

    "文心"取自<文心雕龙>一书的开篇,作者刘勰在书中引述了一个古代典故:春秋时期,鲁国有一位名叫孔文子的大夫,他在学问上非常有造诣,但是他的儿子却不学无术,孔文子非常痛心 ...

随机推荐

  1. mac、windows 配置python国内镜像源

    前言 我们在使用python pip安装第三方库时,经常会发生超时报错,这是可以指定临近的镜像源快速更新. mac中 在用户目录下建立一个".pip"目录,到目录里新建一个文件&q ...

  2. Golang json转换时间格式

    在开发中,将时间转换成json时,默认是把时间转换为 RFC3339 格式 2018-01-14T21:45:54+08:00 这个貌似是GO的诞生的时间 先来看看time包中对格式的常量定义 con ...

  3. go mod 安装bee 报错

    报错信息 go: github.com/beego/bee imports github.com/beego/bee/cmd imports github.com/beego/bee/cmd/comm ...

  4. PIL或Pillow学习1

    PIL( Python Imaging Library)是 Python 的第三方图像处理库,由于其功能丰富,API 简洁易用,因此深受好评. 自 2011 年以来,由于 PIL 库更新缓慢,目前仅支 ...

  5. 实现领域驱动设计 - 使用ABP框架 - 聚合

    这是本指南的关键部分.我们将通过实例介绍和解释一些明确的规则.在实现领域驱动设计时,您可以遵循这些规则并将其应用到您的解决方案中 领域案例 这些例子将使用GitHub中使用的一些概念,比如Issue, ...

  6. 常见的 AI 模型格式

    来源:博客链接 过去两年,开源 AI 社区一直在热烈讨论新 AI 模型的开发.每天都有越来越多的模型在 Hugging Face 上发布,并被用于实际应用中.然而,开发者在使用这些模型时面临的一个挑战 ...

  7. 超简单电脑本地部署deepseek,另附”一键使用脚本“撰写与联网使用方法

    在电脑上部署deepseek,总共分三步 1.打开ollama官网点击Download按钮 2.在ollama官网搜索deepseek-r1模型,选择对应规模,并复制ollama命令,比如这里,我的o ...

  8. DevOps系列——Gitlab私服

    Gitlab/GitHub是两兄弟,但GitHub本着共享技术的精神,私有库是要钱滴,而且代码放别人家里,晚上总是有点睡不踏实, 来个代码泄露或者突然被区别对待,比如GitHub断供来自伊朗.叙利亚的 ...

  9. Global.asax 转

    备忘: 项目中的Global.asax文件里通常包含这5个方法: Application_Start – web 应用程序最初启动时执行 Application_End – 应用程序关闭时运行 App ...

  10. Linux终端居然也可以做文件浏览器?

    大家好,我是良许. 在抖音上做直播已经整整 5 个月了,我很自豪我一路坚持到了现在[笑脸] 最近我在做直播的时候,也开始学习鱼皮大佬,直播写代码.当然我不懂 Java 后端,因此就写写自己擅长的 Sh ...