【AI大模型应用开发】【LangChain系列】4. 从Chain到LCEL:探索和实战LangChain的巧妙设计

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
简介: 【AI大模型应用开发】【LangChain系列】4. 从Chain到LCEL:探索和实战LangChain的巧妙设计

大家好,我是【同学小张】。持续学习,持续干货输出,关注我,跟我一起学AI大模型技能。

今天这篇文章我们来学习一下LangChain中的核心思想,也可以说是最核心的价值所在:Chain模块和LCEL语言。

Chain(链)应该是LangChain的核心思想和价值了。

Chain(链)指的是调用序列——无论是对LLM、工具还是数据预处理步骤。目前LangChain内的主要表现形式和实现方式是使用LCEL(LangChain Expression Language,LangChain声明式语言)。

看了上面的介绍可能还是比较懵,下面我们以一个例子来看,LangChain中的链。

0. 从一个例子开始了解LangChain的Chain是什么

import os
# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
from langchain_openai import ChatOpenAI
llm = ChatOpenAI() # 默认是gpt-3.5-turbo
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
prompt_template = """
我的名字叫【{name}】,我的个人介绍是【{description}】。
请根据我的名字和介绍,帮我想一段有吸引力的自我介绍的句子,以此来吸引读者关注和点赞我的账号。
"""
prompt = ChatPromptTemplate.from_template(prompt_template)
output_parser = StrOutputParser()
chain = prompt | llm | output_parser
response = chain.invoke({"name": "同学小张", "description": "热爱AI,持续学习,持续干货输出"})
print(response)

运行结果:

看到代码中的chain = prompt | llm | output_parser这一行了吗?这就是Chain,也是LCEL。| 符号类似于unix管道操作符,它将不同的组件链接在一起,将一个组件的输出作为下一个组件的输入。在以上示例代码中,用户输入传给prompt,prompt组装结果传给llm,llm结果传给output_parser。

1. 用LCEL重写RAG流程

下面我会从我的思考步骤和探索过程,来一步步将RAG用LCEL写出来。

1.1 先将Prompt和llm连起来

因为我们之前已经用LangChain写过RAG,基本元素都有了,所以最简单的,我们先把 prompt模板 和 llm 连起来,prompt模板的输出给llm作为输入(注释中的第5步和第6步)。

import os
# 加载 .env 到环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
from langchain_openai import ChatOpenAI
llm = ChatOpenAI() # 默认是gpt-3.5-turbo
    
## 1. 文档加载
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("D:\GitHub\LEARN_LLM\RAG\如何向 ChatGPT 提问以获得高质量答案:提示技巧工程完全指南.pdf")
pages = loader.load_and_split()
## 2. 文档切分
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,
    chunk_overlap=100,
    length_function=len,
    add_start_index=True,
)
paragraphs = []
for page in pages:
    paragraphs.extend(text_splitter.create_documents([page.page_content]))
## 3. 文档向量化,向量数据库存储
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
db = Chroma.from_documents(paragraphs, OpenAIEmbeddings())
## 4. 向量检索
retriever = db.as_retriever()
docs = retriever.get_relevant_documents("什么是角色提示?")
for doc in docs:
    print(f"{doc.page_content}\n-------\n")
## 5. 组装Prompt模板
prompt_template = """
你是一个问答机器人。
你的任务是根据下述给定的已知信息回答用户问题。
确保你的回复完全依据下述已知信息。不要编造答案。
如果下述已知信息不足以回答用户的问题,请直接回复"我无法回答您的问题"。
已知信息:
{info}
用户问:
{question}
请用中文回答用户问题。
"""
from langchain.prompts import PromptTemplate
template = PromptTemplate.from_template(prompt_template)
# prompt = template.format(info=docs[0].page_content, question='什么是角色提示?')
## 6. 执行chain
chain = template | llm
response = chain.invoke({"info": docs[0].page_content, "question": "什么是角色提示?"}) ## 给template的输入,多个变量,invoke以字典形式
print(response.content)

测试运行可以正常运行和输出结果。然后继续往前连接。

1.2 将retriever加进来

Prompt模板需要的是检索得到的文档块和用户提问。

retriver的输入是用户query。而用户query也需要跨过retriver,直接放到prompt中。

这块代码如下(比较难理解):

...... 其它代码不变 ......
## 4. 向量检索
retriever = db.as_retriever()
...... 其它代码不变 ......
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
setup_and_retrieval = RunnableParallel(
    {"info": retriever, "question": RunnablePassthrough()}
)
## 6. 执行chain
chain = setup_and_retrieval | template | llm
response = chain.invoke("什么是角色提示?") ## 给retriver的输入,以字符串形式
print(response.content)

首先应该重点关注下chain.invoke的输入形式的变化,一个是字典,一个是字符串。

然后,主要是setup_and_retrieval比较难以理解,RunnableParallelRunnablePassthrough都是新词儿~

RunnablePassthrough是LangChain框架中的一个组件,它允许将输入数据不经修改地传递给下一个步骤,这通常与RunnableParallel一起使用。所以,setup_and_retrieval的意思:

  • info字段接收retriver的输出
  • question接收用户的输入,将用户的输入不经修改地传递过来。

这样,我们就把RAG的流程串了起来(前面向量数据库的创建和数据灌入是离线步骤,与这个完全分离开的,不用放到本次的chain里面)。

2. 为什么要有LCEL

LCEL将各个模块和接口统一,并封装了流支持、异步支持、并行执行、重试和回退、访问中间结果等,极大地方便了应用各模块的开发。

LCEL的意义包括:

  • 定义依赖关系:LCEL提供了一种清晰的语言结构,可以用来明确定义模块之间的依赖关系,包括模块的输入、输出和传递规则等。
  • 解耦模块:通过LCEL,可以将模块之间的依赖关系明确地表达出来,有助于解耦模块,使得系统更易于维护和扩展。
  • 可视化依赖:LCEL可以用于生成依赖关系图,帮助开发人员更直观地了解模块之间的依赖关系,从而更好地进行系统设计和优化。
  • 规范化描述:LCEL提供了一种规范化的描述方式,有助于团队成员之间更好地沟通和理解模块之间的依赖关系,减少误解和歧义。

更多好处可参考官方说明:

https://python.langchain.com/docs/expression_language/why

3. 总结

本文我们通过例子来了解了LangChain中的核心思想:Chain和其特有的语法 LCEL。然后通过LCEL重写了RAG流程。最后简单了解了一下LCEL的意义和优点。相信大家通过本文会对Chain和LCEL有一个比较直观的认知。

如果觉得本文对你有帮助,麻烦点个赞和关注呗 ~~~


  • 大家好,我是同学小张
  • 欢迎 点赞 + 关注 👏,促使我持续学习持续干货输出
  • +v: jasper_8017 一起交流💬,一起进步💪。
  • 微信公众号也可搜【同学小张】 🙏
  • 踩坑不易,感谢关注和围观

本站文章一览:

相关实践学习
阿里云百炼xAnalyticDB PostgreSQL构建AIGC应用
通过该实验体验在阿里云百炼中构建企业专属知识库构建及应用全流程。同时体验使用ADB-PG向量检索引擎提供专属安全存储,保障企业数据隐私安全。
AnalyticDB PostgreSQL 企业智能数据中台:一站式管理数据服务资产
企业在数据仓库之上可构建丰富的数据服务用以支持数据应用及业务场景;ADB PG推出全新企业智能数据平台,用以帮助用户一站式的管理企业数据服务资产,包括创建, 管理,探索, 监控等; 助力企业在现有平台之上快速构建起数据服务资产体系
相关文章
|
8月前
|
前端开发 机器人 API
前端大模型入门(一):用 js+langchain 构建基于 LLM 的应用
本文介绍了大语言模型(LLM)的HTTP API流式调用机制及其在前端的实现方法。通过流式调用,服务器可以逐步发送生成的文本内容,前端则实时处理并展示这些数据块,从而提升用户体验和实时性。文章详细讲解了如何使用`fetch`发起流式请求、处理响应流数据、逐步更新界面、处理中断和错误,以及优化用户交互。流式调用特别适用于聊天机器人、搜索建议等应用场景,能够显著减少用户的等待时间,增强交互性。
2121 2
|
4月前
|
人工智能 自然语言处理 数据可视化
AutoAgents:比LangChain更激进的AI开发神器!自然语言生成AI智能体军团,1句话搞定复杂任务
AutoAgents 是基于大型语言模型的自动智能体生成框架,能够根据用户设定的目标自动生成多个专家角色的智能体,通过协作完成复杂任务。支持动态生成智能体、任务规划与执行、多智能体协作等功能。
311 91
|
2月前
|
存储 人工智能 测试技术
Nacos托管LangChain应用Prompts和配置,助力你的AI助手快速进化
AI 应用开发中,总有一些让人头疼的问题:敏感信息(比如 API-KEY)怎么安全存储?模型参数需要频繁调整怎么办?Prompt 模板改来改去,每次都得重启服务,太麻烦了!别急,今天我们就来聊聊如何用 Nacos 解决这些问题。
|
2月前
|
自然语言处理 分布式计算 前端开发
大模型应用开发入门分享
本文是作者给兄弟团队做的大模型入门分享,介绍了基本大模型模式,分享出来希望帮助更多的同学参与到LLM应用建设。
大模型应用开发入门分享
|
4月前
|
人工智能 自然语言处理 架构师
Praison AI:LangChain危险了!这个低代码框架让AI智能体「自主协作」,1行代码搞定任务编排
Praison AI 是一个开源的多智能体框架,支持低代码创建和管理AI代理,提供多种流程类型和集成选项,适用于企业流程自动化、智能客服等场景。
226 18
|
4月前
|
开发框架 前端开发 Go
eino — 基于go语言的大模型应用开发框架(二)
本文介绍了如何使用Eino框架实现一个基本的LLM(大语言模型)应用。Eino中的`ChatModel`接口提供了与不同大模型服务(如OpenAI、Ollama等)交互的统一方式,支持生成完整响应、流式响应和绑定工具等功能。`Generate`方法用于生成完整的模型响应,`Stream`方法以流式方式返回结果,`BindTools`方法为模型绑定工具。此外,还介绍了通过`Option`模式配置模型参数及模板功能,支持基于前端和用户自定义的角色及Prompt。目前主要聚焦于`ChatModel`的`Generate`方法,后续将继续深入学习。
615 7
|
4月前
|
存储 开发框架 Devops
eino — 基于go语言的大模型应用开发框架(一)
Eino 是一个受开源社区优秀LLM应用开发框架(如LangChain和LlamaIndex)启发的Go语言框架,强调简洁性、可扩展性和可靠性。它提供了易于复用的组件、强大的编排框架、简洁明了的API、最佳实践集合及实用的DevOps工具,支持快速构建和部署LLM应用。Eino不仅兼容多种模型库(如OpenAI、Ollama、Ark),还提供详细的官方文档和活跃的社区支持,便于开发者上手使用。
870 8
|
8月前
|
机器学习/深度学习 人工智能 开发框架
解锁AI新纪元:LangChain保姆级RAG实战,助你抢占大模型发展趋势红利,共赴智能未来之旅!
【10月更文挑战第4天】本文详细介绍检索增强生成(RAG)技术的发展趋势及其在大型语言模型(LLM)中的应用优势,如知识丰富性、上下文理解和可解释性。通过LangChain框架进行实战演练,演示从知识库加载、文档分割、向量化到构建检索器的全过程,并提供示例代码。掌握RAG技术有助于企业在问答系统、文本生成等领域把握大模型的红利期,应对检索效率和模型融合等挑战。
453 14
|
8月前
|
人工智能 前端开发 JavaScript
前端大模型入门(二):掌握langchain的核心Runnable接口
Langchain.js 是 Langchain 框架的 JavaScript 版本,专为前端和后端 JavaScript 环境设计。最新 v0.3 版本引入了强大的 Runnable 接口,支持灵活的执行方式和异步操作,方便与不同模型和逻辑集成。本文将详细介绍 Runnable 接口,并通过实现自定义 Runnable 来帮助前端人员快速上手。
283 1
|
Shell Android开发
Android系统 adb shell push/pull 禁止特定文件
Android系统 adb shell push/pull 禁止特定文件
918 1

热门文章

最新文章