突破界限: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 用法。

相关推荐
全栈弄潮儿2 小时前
不要先问“用哪个 AI”,先盘点你的开发工作流
aigc·openai·ai编程
杨杨杨大侠3 小时前
大模型的权重到底怎么用?拆开一个 token 的生成过程
aigc·openai·ai编程
知了一笑3 小时前
圈外人焦虑AI吗?
人工智能·ai·aigc
Dawson Zhu4 小时前
从单体到联邦:多Agent架构的必要性与设计哲学
人工智能·语言模型·架构·aigc·agi
ai小陈4 小时前
LoRA微调显存怎么估?32GB GPU训练配置与常见问题排查
人工智能·深度学习·机器学习·ai·gpu算力
政企项目老覃5 小时前
大模型幻觉治理与自动评测:金融风控场景的落地实践
人工智能·算法·机器学习
“AI国潮设计-小江”7 小时前
《Python实战 | SDXL大模型批量生成“英歌舞海浪”蛋糕IP,附核心Prompt控制代码与IP授权变现思路》
人工智能·python·prompt·aigc
倔强的石头_7 小时前
会开完了,活还是没人干?我用 AiiOnly + Workbuddy 做了个「会议行动项助手」
aigc
林墨聊AIGC8 小时前
动漫AI视频创作工具在哪找到的?2026年最新动漫AI视频平台与软件指南
大数据·人工智能·ai作画·aigc·音视频