输入“/”快速插入内容

开发:LangChain应用开发指南-熟用LCEL语法掌握Chain的精髓

2024年1月26日修改
LangChain应用开发指南-熟用LCEL语法掌握Chain的精髓
原创 AI小智 AI小智 2023-12-26 08:05 发表于湖北
引言
LangChain()的核心概念是Chain,它是一种由多个流程构件组成的有向图,可以对输入的文本进行各种转换和处理,输出你想要的结果。LangChain提供了一种专门的表达式语言,叫做LCEL(LangChain Expression Language),它可以让你用简洁和灵活的语法来定义和操作Chain,无需编写复杂的代码。
今天我将带领大家使用LCEL语法来构建和组合Chain,实现强大的LLM应用。
本文为一个系列,之前内容没有看过的小伙伴可以点击链接查看:AI课程合集
LCEL语法基础
LCEL是一个用于构建复杂链式组件的语言,它支持流式处理、并行化、日志记录等功能。LCEL的基本语法规则是使用|符号将不同的组件连接起来,形成一个链式结构。|符号类似于Unix的管道操作符,它将一个组件的输出作为下一个组件的输入,从而实现数据的传递和处理。
LCEL的语法非常简洁和灵活,它可以用于各种场景和任务。例如,我们可以使用LCEL来实现以下功能:
生成一个关于某个主题的笑话:我们可以将一个提示模板和一个语言模型组合起来,形成一个链式结构,如下所示:
代码块
prompt = BasePromptTemplate("tell me a short joke about {topic}")
model = ChatModel()
output_parser = StrOutputParser()
joke = ({"topic": RunnablePassthrough()} | prompt | model | output_parser)
这个链式结构的作用是,首先根据用户输入的主题,生成一个提示,然后将提示传递给语言模型,让它生成一个笑话,最后将笑话转换为字符串,返回给用户。我们可以用以下代码来测试这个链式结构:
joke.invoke("ice cream")
> "Why did the ice cream go to therapy? \n\nBecause it had too many toppings and couldn't find its cone-fidence!"
通过以上案例,我们能够了解如何使用LCEL语言构建一个生成笑话的链式结构。我将为您解释其中的每一步:
首先,我们传入用户想要的主题,例如 "ice cream",作为输入。
通过{"topic": RunnablePassthrough()},将输入转化为字典类型{"topic": "ice cream"}
然后,我们使用提示模板组件,根据用户输入的主题,生成一个提示,例如"tell me a short joke about ice cream",并将其封装为一个PromptValue类型的对象。这个对象可以适用于不同类型的语言模型,因为它可以生成字符串或消息序列。
接着,我们使用大语言模型,会根据提示模板生成的提示,生成一段文本,例如"Why did the ice cream go to therapy?\nBecause it had too many toppings and couldn't cone-trol itself!",并将其封装为一个ChatMessage类型的对象。这个对象包含了生成者、内容和时间等信息。
最后,我们使用输出解析器组件,根据用户的需求,将语言模型生成的文本转换为不同的格式或类型,例如字符串。这样,用户就可以方便地获取和使用生成的内容。
为什么要用LCEL?
LCEL语法的核心思想是:一切皆为对象,一切皆为链。这意味着,LCEL语法中的每一个对象都实现了一个统一的接口:Runnable(),它定义了一系列的调用方法(invoke, batch, stream, ainvoke, …)。这样,你可以用同样的方式调用不同类型的对象,无论它们是模型、函数、数据、配置、条件、逻辑等等。而且,你可以将多个对象链接起来,形成一个链式结构,这个结构本身也是一个对象,也可以被调用。这样,你可以将复杂的功能分解成简单的组件,然后用LCEL语法将它们组合起来,形成一个完整的应用。
LCEL语法还提供了一些组合原语,让你可以更灵活地控制链式结构的行为,例如:
并行化:你可以使用parallel原语将多个对象并行执行,提高效率和性能。
回退:你可以使用fallback原语为某个对象指定一个备选对象,当主对象执行失败时,自动切换到备选对象,保证应用的可用性和稳定性。
动态配置:你可以使用config原语为某个对象指定一个配置对象,根据运行时的输入或条件,动态地修改对象的参数或属性,增加应用的灵活性和适应性。
LCEL语法的优势
为了更好地理解LCEL语法的优势,我们可以将它与传统的编程语言进行对比,看看如果不使用LCEL语法,我们需要做哪些额外的工作。我们仍以上述笑话的生成链为例。
这段代码非常简洁和清晰,只需要几行就可以实现我们想要的功能。而且,这段代码还具有很高的可扩展性和灵活性,例如:
如果我们想要以流式的方式获取笑话,我们只需要改变调用方法,使用stream代替invoke
调用笑话对象,传入一个主题字符串,得到一个笑话字符串的流
joke.stream("dog")
如果我们想要同时处理多个主题,我们只需要改变调用方法,使用batch代替invoke
调用笑话对象,传入一个主题字符串的列表,得到一个笑话字符串的列表
joke.batch(["dog", "cat", "banana"])