ChatPDF 和 CustomGPT AI 等人工智能工具对人们非常有用,这是有道理的。你需要翻阅长达 50 页的文档才能找到一个简单答案的时代已经一去不复返了。相反,您可以依靠人工智能来完成繁重的工作。
但是,这些开发人员究竟是如何创建和使用这些工具的呢?其中很多人都在使用一个名为 LangChain 的开源框架。
在本文中,我将向大家介绍 LangChain,并向大家展示如何将其与 OpenAI 的 API 结合使用,来创建这些改变游戏规则的工具。希望我的介绍能给你们带来灵感,创造出属于自己的工具。那么,让我们开始吧!
一、什么是 LangChain?
LangChain 是一个开源框架,允许人工智能开发人员将 GPT-4 等大型语言模型(LLM)与外部数据相结合。它提供 Python 或 JavaScript(TypeScript)软件包。
大家可能知道,GPT 模型是在 2021 年之前的数据上训练出来的,这可能是一个很大的局限。虽然这些模型的常识很不错,但如果能将它们与自定义数据和计算连接起来,就会打开很多大门。这正是 LangChain 所要做的。
从本质上讲,它允许您的 LLM 在得出答案时参考整个数据库。因此,您现在可以让您的 GPT 模型访问报告、文件和网站信息等形式的最新数据。
最近,LangChain 的受欢迎程度大幅上升,尤其是在三月份推出 GPT-4 之后。这要归功于它的多功能性以及与功能强大的 LLM 配对后所带来的多种可能性。
二、LangChain 如何工作?
你可能会觉得 LangChain 听起来很复杂,但实际上它非常容易上手。
简而言之,LangChain 就是将大量数据组成一个 LLM 可以轻松引用的数据链,而且计算能力越低越好。它的工作原理是将大量数据(例如 50 页的 PDF 文件)分解成 "块",然后将这些 "块 "嵌入到矢量存储中。
现在,我们已经有了大型文档的矢量化表示,可以将其与 LLM 结合使用,在创建提示-完成对时,只检索我们需要引用的信息。
当我们在新聊天机器人中插入一个提示时,LangChain 会查询矢量存储库以获取相关信息。把它想象成你文档的迷你谷歌。一旦检索到相关信息,我们就会将其与提示信息一起输入 LLM,生成我们的答案。
LangChain 还允许您创建可以执行操作的应用程序,例如上网、发送电子邮件和完成其他与 API 相关的任务。请查看 AgentGPT,这就是一个很好的例子。
这有许多可能的用例,以下是我想到的几个:
- 个人 AI 电子邮件助理
- 人工智能学习伙伴
- 人工智能数据分析
- 定制公司客户服务聊天机器人
- 社交媒体内容创建助手
这样的例子不胜枚举。我将在今后的文章中介绍正确的构建教程,敬请期待。
三、如何开始使用 LangChain
LangChain 应用程序由 5 个主要部分组成:
- Models (LLM Wrappers)模型
- Prompts提示
- Chains链
- Embeddings and Vector Stores嵌入和向量存储
- Agents代理
我将为您逐一介绍,以便您对 LangChain 的工作原理有一个高层次的了解。今后,您应该能够应用这些概念,开始制作自己的用例并创建自己的应用程序。
我将使用 Rabbitmetrics(Github)的简短代码片段来解释一切。他就这一主题提供了很好的教程。通过这些代码片段,您可以完成所有设置并准备好使用 LangChain。
pip install -r requirements.txt
python-dotenv==1.0.0
langchain==0.0.137
pinecone-client==2.2.1
Pinecone 是我们将与 LangChain 结合使用的向量存储。使用这些工具时,请确保将 OpenAI、Pinecone Environment 和 Pinecone API 的 API 密钥存储到环境文件中。你可以在它们各自的网站上找到这些信息。然后,我们只需在环境文件中加载以下内容即可:
# Load environment variables
from dotenv import load_dotenv,find_dotenv
load_dotenv(find_dotenv())
现在,我们可以开始了!
四、模型(LLM 封装器)
为了与我们的 LLM 进行交互,我们将为 OpenAI 的 GPT 模型实例化一个封装器。在本例中,我们将使用 OpenAI 的 GPT-3.5-turbo,因为它最具成本效益。但如果你有权限,也可以使用功能更强大的 GPT4。
要导入这些数据,我们可以使用以下代码:
# import schema for chat messages and ChatOpenAI in order to query chatmodels GPT-3.5-turbo or GPT-4
from langchain.schema import (
AIMessage,
HumanMessage,
SystemMessage
)
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0.3)
messages = [
SystemMessage(content="You are an expert data scientist"),
HumanMessage(content="Write a Python script that trains a neural network on simulated data ")
]
response=chat(messages)
print(response.content,end='\n')
从本质上讲,SystemMessage 为 GPT-3.5-turbo 模块提供了上下文,它将为每个提示-完成对提供参考。HumanMessage 指的是您在 ChatGPT 界面中输入的内容--您的提示。
但在定制知识聊天机器人中,我们经常会抽象掉提示语中重复的部分。例如,如果我要创建一个 Tweet 生成器应用,我就不会一直输入 "给我写一条关于......的 Tweet"。事实上,简单的人工智能写作工具就是这样开发出来的!
因此,让我们看看如何利用提示模板将其抽象化。
五、提示(Prompts)
LangChain 提供的 PromptTemplates 可以让您根据用户输入动态更改提示,这与 regex 的使用方式类似。
# Import prompt and define PromptTemplate
from langchain import PromptTemplate
template = """
You are an expert data scientist with an expertise in building deep learning models.
Explain the concept of {concept} in a couple of lines
"""
prompt = PromptTemplate(
input_variables=["concept"],
template=template,
)
# Run LLM with PromptTemplate
llm(prompt.format(concept="autoencoder"))
llm(prompt.format(concept="regularization"))
您可以根据自己的使用情况,以不同的方式改变这些功能。如果您熟悉 ChatGPT 的使用方法,应该会很容易上手。
六、链(Chains)
链允许您使用简单的 PromptTemplate 并在其基础上构建功能。从本质上讲,链就像复合函数,可以将 PromptTemplate 和 LLM 整合在一起。
使用前面的封装器和 PromptTemplate,我们可以用一个链来运行相同的提示,该链获取 PromptTemplate 并将其与 LLM 结合在一起:
# Import LLMChain and define chain with language model and prompt as arguments.
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)
# Run the chain only specifying the input variable.
print(chain.run("autoencoder"))
因此,如上类举,我们还可以将这些元素串联起来,创造出更大的组合。
例如,我可以从一个链中获取结果并将其传递到另一个链中。在这个片段中,Rabbitmetrics 从第一条链中获取完成结果,并将其传递到第二条链中,向一个 5 岁的孩子解释。
然后,您可以将这些链组合成一个更大的链并运行。
# Define a second prompt
second_prompt = PromptTemplate(
input_variables=["ml_concept"],
template="Turn the concept description of {ml_concept} and explain it to me like I'm five in 500 words",
)
chain_two = LLMChain(llm=llm, prompt=second_prompt)
# Define a sequential chain using the two chains above: the second chain takes the output of the first chain as input
from langchain.chains import SimpleSequentialChain
overall_chain = SimpleSequentialChain(chains=[chain, chain_two], verbose=True)
# Run the chain specifying only the input variable for the first chain.
explanation = overall_chain.run("autoencoder")
print(explanation)
通过链,你可以创建大量的功能,这就是 LangChain 的多功能性所在。不过,LangChain 真正的亮点在于与前面讨论过的矢量存储库(Vector Store)结合使用。让我们来介绍一下这个组件。
七、嵌入和矢量存储 (Embeddings and Vector Stores)
这就是我们结合 LangChain 的自定义数据方面。如前所述,嵌入和矢量存储背后的理念是将大型数据分割成块,并存储这些块,以便在相关时进行查询。
LangChain 的文本分割器功能可以实现这一目的:
# Import utility for splitting up texts and split up the explanation given above into document chunks
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = 100,
chunk_overlap = 0,
)
texts = text_splitter.create_documents([explanation])
分割文本需要两个参数:一个文本块的大小(chunk_size)和每个文本块的重叠程度(chunk_overlap)。每个文本块之间的重叠度对于帮助识别相关的相邻文本块非常重要。
这些数据块中的每一个都可以被检索到:
texts[0].page_content
有了这些数据块后,我们需要将它们转化为嵌入。这样,矢量存储库就能在查询时找到并返回每个块。为此,我们将使用 OpenAI 的嵌入模型。
# Import and instantiate OpenAI embeddings
from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model_name="ada")
# Turn the first text chunk into a vector with the embedding
query_result = embeddings.embed_query(texts[0].page_content)
print(query_result)
最后,我们需要有一个地方来存储这些矢量化嵌入。如前所述,我们将为此使用 Pinecone。使用之前环境文件中的 API 密钥,我们可以初始化 Pinecone 来存储嵌入式内容。
# Import and initialize Pinecone client
import os
import pinecone
from langchain.vectorstores import Pinecone
pinecone.init(
api_key=os.getenv('PINECONE_API_KEY'),
environment=os.getenv('PINECONE_ENV')
)
# Upload vectors to Pinecone
index_name = "langchain-quickstart"
search = Pinecone.from_documents(texts, embeddings, index_name=index_name)
# Do a simple vector similarity search
query = "What is magical about an autoencoder?"
result = search.similarity_search(query)
print(result)
现在,我们能够从松果矢量存储中查询相关信息了!剩下要做的就是把我们学到的知识结合起来,创建我们的特定用例--这就是我们的专业人工智能 "代理"。
八、代理(Agents)
代理本质上是一种自主的人工智能,它接收输入并按顺序完成这些任务,直至达到最终目标。这就需要我们的人工智能使用其他应用程序接口,从而完成发送电子邮件或做数学题等任务。结合我们的 LLM + 提示链,我们可以串联起一个合适的人工智能应用程序。
现在,要解释这部分内容会很费劲,因此这里有一个简单的例子,说明如何在 LangChain 中使用 Python 代理来解决一个简单的数学问题。本例中的代理通过连接我们的 LLM 来运行 Python 代码,并使用 NumPy 求根来解决问题:
# Import Python REPL tool and instantiate Python agent
from langchain.agents.agent_toolkits import create_python_agent
from langchain.tools.python.tool import PythonREPLTool
from langchain.python import PythonREPL
from langchain.llms.openai import OpenAI
agent_executor = create_python_agent(
llm=OpenAI(temperature=0, max_tokens=1000),
tool=PythonREPLTool(),
verbose=True
)
# Execute the Python agent
agent_executor.run("Find the roots (zeros) if the quadratic function 3 * x**2 + 2*x -1")
定制知识聊天机器人本质上是一个代理,它将查询矢量化存储的提示和操作串联起来,获取结果,并将其与原始问题串联起来!
如果你想了解更多关于人工智能代理的信息,这是一个很好的资源。
九、其他变体
即使你对 LangChain 的功能有了新的基本了解,我相信此时你也会有很多想法。
但到目前为止,我们只研究了一个 OpenAI 模型,那就是基于文本的 GPT-3.5-turbo。OpenAI 有一系列模型可供 LangChain 使用,包括使用 Dall-E 生成图像。应用我们讨论过的相同概念,我们可以创建人工智能艺术生成器代理、网站生成器代理等。
花点时间探索一下人工智能领域,我相信你会有越来越多的想法。
十、结论
我希望你已经对所有这些新人工智能工具的幕后工作有了更多了解。作为一名程序员,了解 LangChain 的工作原理是一项宝贵的技能,它能为你的人工智能开发带来无限可能。