突破界限:LangChain 引领 AI 应用构建的新时代

前言

上一篇文章中我们对 ChatWithPDF 的方案设计进行了整体的概览,现在细化下整体流程,如下图所示:

针对上面的流程,我们思考🤔一下会面临的问题:

  1. 如何读取 PDF 中的内容?(肯定和直接读文本不一样)
  2. 如何切割文本块才能保证一定的语义和上下文的连贯性?(随意切割文本肯定会导致上下文的丢失)
  3. 如何对文本进行 Embedding,这个 Embedding 算法怎么实现?
  4. 请求 AI 大模型的格式是什么,响应的内容如何解析?
  5. 向量数据库如何增删查改?
  6. 如果想替换向量数据库的类型,想替换大模型 ChatGPT 成 ChatGLM 怎么办?

如果从头实现上面的所有功能,想想都头大😵‍💫,真的是从入门到放弃。LangChain 的出现让 AI 应用的构建变得简单。

LangChain 的功能进行归类总结下:

为了加速和简化构建 AI 应用的工作,LangChain 将是本系列的一个核心内容,但由于 LangChain 的版本迭代比较快,并且文档有点混乱,本篇的目的就是让大家更加轻松掌握 LangChain ,为后续 ChatWithPDF 的开发打下基础。

Chains 是什么?

Chains 中文是链的意思,它是 AI 应用开发中的一个重要概念,让我们用一个简单的例子来说明 Chains 的应用。比如开发一个自动生成代码的功能,输入的参数是两个 languagetasklanguage 表示编程语言(如 Python),task 是需要生成代码的说明,因此大致流程如下:

由于 token 数量的限制,建议使用英文作为 Prompt (提示语),最终通过与 AI 大模型 ChatGPT 的交互之后,可以得到相对应的 Python 代码。

通过 LangChain 我们可以轻易的替换所使用的 AI 大模型(ChatGPT、Llama、Claude 对应不同的大模型),而不需要改动其他模块的代码。

此时,我们再增加一个需求:对生成的代码进行代码审查,检查生成的代码是否有 Bug,并且需要用另外一个大模型完成这个功能。最简单的办法就是重新改写上面的 Prompt (提示语),让 AI 大模型先生成代码,然后在对代码进行审查。

但在 LangChain 中有个更灵活的方式,再构建一个流程,然后将上个流程的输出作为下一个流程的输入,具体情况如下图所示:

这个思想是不是有点熟悉?没错,就是 unix pipeline,比如统计包含 "aa" 日志的条目数: cat test.log | grep aa | wc -l。每个程序都实现单一的功能,然后通过 pipeline 将它们组合起来完成更复杂的功能。

LangChain 也是同样的,你可以通过 LangChain 构建不同的 Chain,然后将每个 Chain 串联起来完成复杂的工作,如下图:

相信通过上面的示例,大家对于 LangChainChain 的设计与使用有了更加深刻的理解,接下来我们通过一个具体示例来演示 LangChain 的使用。

AI 聊天机器人(easychat)

本节我们将使用 LangChain 构建一个 AI 聊天机器人,使用的 AI 大模型是 AzureOpenAI,具体申请方式请参考上一篇文章

完整的代码已经上传 github 仓库:github.com/betnevs/lan...

环境初始化

Python 作为本地开发环境,要解决的第一个问题就是包依赖的问题,随着本地 Python 环境引入的包越来越多,依赖管理也会越来越复杂,所以需要解决这个问题。

本系列采用 Python 官方的 venv 创建虚拟的 Python 环境解决依赖问题,感兴趣的可以阅读:docs.python.org/3/library/v...

本文示例是基于 macOS 进行开发演示,Windows 代码基本一样,注意 Windows 使用 venv 的初始化命令不一样,请参考官方文档。

  1. 创建本地目录 easychat
bash 复制代码
mkdir easychat && cd easychat
  1. 初始化虚拟环境

    python -m venv .venv

  2. 激活虚拟环境

bash 复制代码
source .venv/bin/activate

建立主框架

主框架就是不断获取用户的输入,然后做业务逻辑的处理,最后将响应的内容显示到屏幕上。另外,当用户输入 exit 时,程序退出。代码很简单,如下所示:

逐步完善功能

在与 AI 大模型交互的时候,一般涉及三个角色:

  • system:设置 AI 大模型的角色
  • user:使用的用户,对应用户的输入
  • assistant:AI 大模型,对应大模型的输出

真正与大模型的交互就是靠调用 API 去实现,但如果不借助 LangChain作为开发者需要去阅读每个 AI 大模型的 API 文档,并且切换不同的大模型还需要修改相对应的代码,这些是比较繁琐的事情 ,有了 LangChain 就可以简化流程。

接下来,让我们逐步完善功能:

1、先安装相应的 LangChain

复制代码
pip install python-dotenv langchain langchain-core langchain-community langchain-openai 

2、Azure OpenAI 密钥和接口配置

bash 复制代码
touch .env

根据自己账号下的配置填写配置文件

.env 复制代码
AZURE_OPENAI_API_KEY=(请求key)
AZURE_OPENAI_ENDPOINT=(请求API)
OPENAI_API_VERSION=2024-02-01
AZURE_CHAT_MODEL=gpt-35-turbo

3、通过 load_dotenv 引入配置文件中的内容至环境变量

csharp 复制代码
from dotenv import load_dotenv

load_dotenv()

通过以上操作,可以避免 Azure OpenAI 的相关配置写死在代码中。

4、构建提示语模板

python 复制代码
prompt = ChatPromptTemplate(
    input_variables=["content"],
    messages=[
        HumanMessagePromptTemplate.from_template("{content}"),
    ],
)

这个代码非常简单,利用 ChatPromptTemplate 定义提示语的模板,将用户的输入定义为 content,然后通过 HumanMessagePromptTemplate.from_template("{content}") 将用户的输入直接构建成提示语。

5、初始化 AI 模型

python 复制代码
chat = AzureChatOpenAI(
    azure_deployment=os.getenv("AZURE_CHAT_MODEL"),
)

6、定义响应解析器

ini 复制代码
output_parser = StrOutputParser()

7、构建 Chains

ini 复制代码
chain = prompt | chat | output_parser

这里再次印证了上面说的 chainunix pipeline 思路一样 ,使用方式都基本一致。

8、传入用户输入,调用 chain

css 复制代码
# 5. 调用 chain,这里 `content` 就是构建填充到提示语模板中的 `content`
result = chain.invoke({"content": content})

最终完整代码:

python 复制代码
import os

from dotenv import load_dotenv
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain.schema import StrOutputParser
from langchain_openai import AzureChatOpenAI

load_dotenv()

# 1. 定义提示语模板
prompt = ChatPromptTemplate(
    input_variables=["content"],
    messages=[
        HumanMessagePromptTemplate.from_template("{content}"),
    ],
)

# 2. 初始化 AI 模型
chat = AzureChatOpenAI(
    azure_deployment=os.getenv("AZURE_CHAT_MODEL"),
)

# 3. 定义响应解析器
output_parser = StrOutputParser()

# 4. 构建 chains
chain = prompt | chat | output_parser

while True:
    content = input(">> ")

    if content.strip() == "exit":
        break

    # 5. 调用 chain,这里 `content` 就是构建填充到提示语模板中的 `content`
    result = chain.invoke({"content": content})

    print("AI Answer: ", result)

效果展示

直接执行 python main.py 运行程序,问几个问题,看看效果:

效果还是ok的,大家可以自己运行体验下。但是这个 easychat 的机器人有个问题,就是没有记忆功能,让我们做个功能测试:

  1. 告诉它我们的名字叫做"开发者语"
  2. 再问它我们的名字,看看效果

为什么会出现这种情况呢?因为调用 AI 大模型是没有记忆功能,也就是说调用 AI 大模型是一种无状态的调用,它并不会记忆你上次问的内容,那如何解决这个问题让 AI 机器人拥有记忆的能力,下一篇文章将详细介绍,敬请期待~😉

总结

本篇是《从零构建生产级 AI 应用 ChatWithPDF》的第二篇,主要介绍了 LangChain 这个框架的核心思想以及 Chain 的原理和使用,下一篇我们将针对 AI 大模型没有记忆能力的问题逐步完善 easychat 的功能,在实战中介绍更多的 LangChain 用法。

相关推荐
张祥6422889042 小时前
误差理论与测量平差基础笔记十
笔记·算法·机器学习
阿杰学AI3 小时前
AI核心知识70——大语言模型之Context Engineering(简洁且通俗易懂版)
人工智能·ai·语言模型·自然语言处理·aigc·数据处理·上下文工程
imbackneverdie5 小时前
近年来,我一直在用的科研工具
人工智能·自然语言处理·aigc·论文·ai写作·学术·ai工具
春日见5 小时前
自动驾驶规划控制决策知识点扫盲
linux·运维·服务器·人工智能·机器学习·自动驾驶
hjs_deeplearning6 小时前
文献阅读篇#14:自动驾驶中的基础模型:场景生成与场景分析综述(5)
人工智能·机器学习·自动驾驶
创业之路&下一个五年11 小时前
以教为学:在赋能他人中完成自我跃升
机器学习·自然语言处理·数据挖掘
机 _ 长11 小时前
YOLO26 改进 | 训练策略 | 知识蒸馏 (Response + Feature + Relation)
python·深度学习·yolo·目标检测·机器学习·计算机视觉
szcsun512 小时前
机器学习(二)-线性回归实战
人工智能·机器学习·线性回归
力学与人工智能13 小时前
“高雷诺数湍流数据库的构建及湍流机器学习集成研究”湍流重大研究计划集成项目顺利结题
数据库·人工智能·机器学习·高雷诺数·湍流·重大研究计划·项目结题
康谋自动驾驶14 小时前
高校自动驾驶研究新基建:“实测 - 仿真” 一体化数据采集与验证平台
人工智能·机器学习·自动驾驶·科研·数据采集·时间同步·仿真平台