掘金 人工智能 06月30日 14:03
你应该懂的AI 大模型(五)之 LangChain 之 LCEL
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了LangChain框架中的Chain与LCEL(LangChain Expression Language)的概念及其应用。Chain作为流程抽象,将组件串联成任务序列;而LCEL则是一种声明式语言,用于轻松组合不同的调用顺序构成Chain。文章通过Pipeline式调用、RAG实现等示例,详细展示了LCEL在解耦模块、提升流程编排灵活性方面的优势,并阐述了其在构建复杂LLM应用中的重要性。

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

🗣️ LCEL(LangChain Expression Language)是一种声明式语言,用于组合Chain,可以轻松地定义和调整组件之间的调用关系,实现复杂的逻辑控制,简化了流程编排。

🛠️ LCEL通过分离逻辑控制与组件实现,标准化组件交互协议,支持动态流程编排与热更新,提高了组件的复用性与可测试性,使其更适合复杂的LLM应用场景。

💡 LCEL在LangChain框架中增强了模块间的解耦能力,提升了流程编排的灵活性,并为复杂的LLM应用构建提供了标准化的逻辑表达工具,是构建“表达式驱动的智能应用”的关键。

本文 对《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 ChatOpenAIfrom langchain.prompts import ChatPromptTemplatefrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.runnables import RunnablePassthroughfrom pydantic import BaseModel, Field, validatorfrom typing import List, Dict, Optionalfrom enum import Enumimport 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 OpenAIEmbeddingsfrom langchain_text_splitters import RecursiveCharacterTextSplitterfrom langchain_community.vectorstores import FAISSfrom langchain_openai import ChatOpenAIfrom langchain.chains import RetrievalQAfrom 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 StrOutputParserfrom langchain.schema.runnable import RunnablePassthrough# Prompt模板template = """Answer the question based only on the following context:{context}Question: {question}"""prompt = ChatPromptTemplate.from_template(template)# Chainrag_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 模板、工具调用、内存管理等)构建复杂的应用流程。例如:

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

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

1. 分离逻辑控制与组件实现
2. 标准化组件交互协议

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

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

from langchain.lcel import LCELChainexpression = """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)})
3. 支持动态流程编排与热更新

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

4. 提升组件复用性与可测试性
5. 适配多模态与复杂工具调用

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

三、LCEL 与 LangChain 架构的协同

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

    底层组件层:提供标准化接口(如 call()parse()),供 LCEL 表达式调用;

    LCEL 层:作为逻辑编排层,通过表达式描述组件交互规则;

    应用层:通过配置文件、API 动态注入 LCEL 表达式,快速组装不同功能的链。

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

原文地址:https://www.cnblogs.com/bricheersz/p/18928409

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

LangChain Chain LCEL LLM
相关文章