在日常生活中,我们通常致力于构建端到端的应用程序。有许多自动机器学习平台和持续集成/持续交付(CI/CD)流水线可用于自动化我们的机器学习流程。我们还有像 Roboflow 和 Andrew N.G. 的 Landing AI 这样的工具,可以自动化或创建端到端的计算机视觉应用程序。如果我们想要借助 OpenAI 或 Hugging Face 创建基于大语言模型的应用程序,以前我们可能需要手动完成。现在,为了实现相同的目标,我们有两个最著名的库,即 Haystack 和 LangChain,它们可以帮助我们创建基于大语言模型的端到端应用程序或流程。下面让我们深入地了解一下 LangChain。
什么是 LangChain?
LangChain 是一种创新框架,正在彻底改变我们开发由语言模型驱动的应用程序的方式。通过引入先进的原理,LangChain 正在重新定义传统 API 所能实现的限制。此外,LangChain 应用程序具有智能代理的特性,使语言模型能够与环境进行互动和自适应。LangChain 由多个模块组成。正如其名称所示,LangChain 的主要目的是将这些模块进行链式连接。这意味着我们可以将每个模块都串联在一起,并使用这个链式结构一次性调用所有模块。这些模块由以下部分组成:Model正如介绍中所讨论的那样,模型主要涵盖大语言模型(LLM)。大语言模型是指具有大量参数并在大规模无标签文本上进行训练的神经网络模型。科技巨头们推出了各种各样的大型语言模型,比如:
- 谷歌的 BERT
- OpenAI 的 GPT-3
- 谷歌 LaMDA
- 谷歌 PaLM
- Meta AI 的 LLaMA
- OpenAI 的 GPT-4
-
……
借助 LangChain,与大语言模型的交互变得更加便捷。LangChain 提供的接口和功能有助于将 LLM 的强大能力轻松集成到你的工作应用程序中。LangChain 利用 asyncio 库为 LLM 提供异步支持。对于需要同时并发调用多个 LLM 的网络绑定场景,LangChain 还提供了异步支持。通过释放处理请求的线程,服务器可以将其分配给其他任务,直到响应准备就绪,从而最大限度地提高资源利用率。目前,LangChain 支持 OpenAI、PromptLayerOpenAI、ChatOpenAI 和 Anthropic 等模型的异步支持,但在未来的计划中将扩展对其他 LLM 的异步支持。你可以使用 agenerate 方法来异步调用 OpenAI LLM。此外,你还可以编写自定义的 LLM 包装器,而不仅限于 LangChain 所支持的模型。我在我的应用程序中使用了 OpenAI,并主要使用了 Davinci、Babbage、Curie 和 Ada 模型来解决我的问题。每个模型都有其自身的优点、令牌使用量和使用案例。更多关于这些模型的信息请阅读:https://subscription.packtpub.com/book/data/9781800563193/2/ch02lvl1sec07/introducing-davinci-babbage-curie-and-ada
案例 1:
# Importing modules
from langchain.llms import OpenAI
#Here we are using text-ada-001 but you can change it
llm = OpenAI(model_name=“text-ada-001”, n=2, best_of=2)
#Ask anything
llm(“Tell me a joke”)
输出 1:
‘nnWhy did the chicken cross the road?nnTo get to the other side.’
案例 2:
llm_result = llm.generate([“Tell me a poem”]*15)
输出 2:
[Generation(text=“nnWhat if love neverspeechnnWhat if love never endednnWhat if love was only a feelingnnI’ll never know this lovennIt’s not a feelingnnBut it’s what we have for each othernnWe just know that love is something strongnnAnd we can’t help but be happynnWe just feel what love is for usnnAnd we love each other with all our heartnnWe just don’t know hownnHow it will gonnBut we know that love is something strongnnAnd we’ll always have each othernnIn our lives.”),
Generation(text=‘nnOnce upon a timennThere was a love so pure and truennIt lasted for centuriesnnAnd never became stale or drynnIt was moving and alivennAnd the heart of the love-icknnIs still beating strong and true.’)]
Prompt
众所周知,提示(prompt)是我们向系统提供的输入,以便根据我们的使用案例对答案进行精确或特定的调整。许多时候,我们希望得到的不仅仅是文本,还需要更结构化的信息。基于对比预训练和零样本学习的许多新的目标检测和分类算法都将提示作为有效的输入来进行结果预测。举例来说,OpenAI 的 CLIP 和 META 的 Grounding DINO 都使用提示作为预测的输入。在 LangChain 中,我们可以根据需要设置提示模板,并将其与主链相连接以进行输出预测。此外,LangChain 还提供了输出解析器的功能,用于进一步精炼结果。输出解析器的作用是(1)指导模型输出的格式化方式,和(2)将输出解析为所需的格式(包括必要时的重试)。在 LangChain 中,我们可以提供提示模板作为输入。模板指的是我们希望获得答案的具体格式或蓝图。LangChain 提供了预先设计好的提示模板,可以用于生成不同类型任务的提示。然而,在某些情况下,预设的模板可能无法满足你的需求。在这种情况下,我们可以使用自定义的提示模板。
案例:
from langchain import PromptTemplate
# This template will act as a blue print for prompt
template = “””
I want you to act as a naming consultant for new companies.
What is a good name for a company that makes {product}?
“””
prompt = PromptTemplate(
input_variables=[“product”],
template=template,
)
prompt.format(product=“colorful socks”)
# -> I want you to act as a naming consultant for new companies.
# -> What is a good name for a company that makes colorful socks?
Memory
在 LangChain 中,链式和代理默认以无状态模式运行,即它们独立处理每个传入的查询。然而,在某些应用程序(如聊天机器人)中,保留先前的交互记录对于短期和长期都非常重要。这时就需要引入 “内存” 的概念。LangChain 提供两种形式的内存组件。首先,LangChain 提供了辅助工具,用于管理和操作先前的聊天消息,这些工具设计成模块化的,无论用例如何,都能很好地使用。其次,LangChain 提供了一种简单的方法将这些工具集成到链式结构中,使其非常灵活和适应各种情况。
案例:
from langchain.memory import ChatMessageHistory
history = ChatMessageHistory()
history.add_user_message(“hi!”)
history.add_ai_message(“whats up?”)
history.messages
输出:
[HumanMessage(content=‘hi!’, additional_kwargs={}),
AIMessage(content=‘whats up?’, additional_kwargs={})]
Chain
链式(Chain)提供了将各种组件合并成一个统一应用程序的方式。例如,可以创建一个链式,它接收用户的输入,并使用 PromptTemplate 对其进行格式化,然后将格式化后的回复传递给 LLM(大语言模型)。通过将多个链式与其他组件集成,可以生成更复杂的链式结构。LLMChain 被认为是查询 LLM 对象最常用的方法之一。它根据提示模板将提供的输入键值和内存键值(如果存在)进行格式化,然后将格式化后的字符串发送给 LLM,LLM 生成并返回输出结果。
在调用语言模型后,可以按照一系列步骤进行操作,可以进行多个模型调用的序列。这种做法特别有价值,当希望将一个调用的输出作为另一个调用的输入时。在这个链式序列中,每个链式都有一个输入和一个输出,一个步骤的输出作为下一个步骤的输入。
#Here we are chaining everything
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
)
human_message_prompt = HumanMessagePromptTemplate(
prompt=PromptTemplate(
template=“What is a good name for a company that makes {product}?”,
input_variables=[“product”],
)
)
chat_prompt_template = ChatPromptTemplate.from_messages([human_message_prompt])
chat = ChatOpenAI(temperature=0.9)
# Temperature is about randomness in answer more the temp, random the answer
#Final Chain
chain = LLMChain(llm=chat, prompt=chat_prompt_template)
print(chain.run(“colorful socks”))
Agent
某些应用可能需要不仅预定的 LLM(大型语言模型)/其他工具调用顺序,还可能需要根据用户的输入确定不确定的调用顺序。这种情况下涉及到的序列包括一个 “代理(Agent)”,该代理可以访问多种工具。根据用户的输入,代理可能决定是否调用这些工具,并确定调用时的输入。根据文档,代理的高级伪代码大致如下:
- 接收用户输入。
- 代理根据输入决定是否使用某个工具,以及该工具的输入应该是什么。
- 调用该工具,并记录观测结果(即使用该工具和输入调用后得到的输出)。
- 将工具、工具输入和观测结果的历史传递回代理,代理决定下一步应该采取的步骤。
-
重复上述步骤,直到代理决定不再需要使用工具,然后直接向用户作出回应。
这个过程会一直重复,直到代理决定不再需要使用工具,然后直接回应用户。
案例:
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAI
llm = OpenAI(temperature=0)
tools = load_tools([“serpapi”, “llm-math”], llm=llm)
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run(“Who is Leo DiCaprio’s girlfriend? What is her current age raised to the 0.43 power?”)
让我们将所有内容总结在下面这张图中。
理解所有模块和链式操作对于使用 LangChain 构建大语言模型的管道应用程序非常重要。这只是对 LangChain 的简单介绍。
LangChain 的实际应用
废话少说,让我们直接使用 LangChain 构建简单的应用程序。其中最有趣的应用是在自定义数据上创建一个问答机器人。免责声明/警告:这段代码仅用于展示应用程序的构建方式。我并不保证代码的优化,并且根据具体的问题陈述,可能需要进行进一步改进。开始导入模块导入 LangChain 和 OpenAI 用于大语言模型部分。如果你还没有安装它们,请先安装。
# IMPORTS
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.chains import ConversationalRetrievalChain
from langchain.vectorstores import ElasticVectorSearch, Pinecone, Weaviate, FAISS
from PyPDF2 import PdfReader
from langchain import OpenAI, VectorDBQA
from langchain.vectorstores import Chroma
from langchain.prompts import PromptTemplate
from langchain.chains import ConversationChain
from langchain.document_loaders import TextLoader
# from langchain import ConversationalRetrievalChain
from langchain.chains.question_answering import load_qa_chain
from langchain import LLMChain
# from langchain import retrievers
import langchain
from langchain.chains.conversation.memory import ConversationBufferMemory
py2PDF 是用于读取和处理 PDF 文件的工具。此外,还有不同类型的内存,例如 ConversationBufferMemory 和 ConversationBufferWindowMemory,它们具有特定的功能。我将在最后一部分详细介绍有关内存的内容。
设置环境我想你知道如何获取 OpenAI API 密钥,但是我还是想说明一下:
- 前往 OpenAI API 页面,
- 点击 “Create new secret key(创建新的密钥) ”
-
那将是你的 API 密钥。请将其粘贴在下方
import os
os.environ[“OPENAI_API_KEY”] = “sk-YOUR API KEY”
要使用哪个模型?Davinci、Babbage、Curie 还是 Ada?基于 GPT-3、基于 GPT-3.5、还是基于 GPT-4?关于模型有很多问题,所有模型都适用于不同的任务。有些模型价格较低,有些模型更准确。为了简单起见,我们将使用最经济实惠的模型 “gpt-3.5-turbo”。温度是一个参数,它影响答案的随机性。温度值越高,我们得到的答案就越随机。
llm = ChatOpenAI(temperature=0,model_name=<span style="margin: 0px; padding: 0px; outline-style: initial; outline-wid
Keyword: Midjourney