快速入门指南
开始

LangChain 快速入门指南

本教程将简要介绍如何使用 LangChain 构建端到端语言模型应用程序。

安装

首先,使用以下命令安装 LangChain:

pip install langchain
# or
conda install langchain -c conda-forge

环境设定

使用 LangChain 通常需要与一个或多个模型提供程序、数据存储、 API 等集成。

对于这个例子,我们将使用 OpenAI 的 API,所以我们首先需要安装他们的 SDK:

pip install openai

然后我们需要在终端设置环境变量。

export OPENAI_API_KEY="..."

或者,你可以在 Jupiter 教程(或 Python 脚本)内部完成:

import os
os.environ["OPENAI_API_KEY"] = "..."

构建语言模型应用程序: LLM

现在我们已经安装了 LangChain 并设置了我们的环境,我们可以开始构建我们的语言模型应用程序了。

LangChain 提供了许多可用于构建语言模型应用程序的模块。

模块可以组合起来创建更复杂的应用程序,或者单独用于简单的应用程序。

LLM: 从语言模型中获取预测

LangChain 最基本的构建块是对某些输入调用 LLM。

让我们来看一个简单的例子。

我们假设我们正在构建一个基于公司产品生成公司名称的服务。

为此,我们首先需要导入 LLM 包装器。

from langchain.llms import OpenAI

LLM初始化和调用

然后我们可以用任何参数初始化包装器。

在这个例子中,我们可能希望输出更加随机,所以我们将以温度(temperature)初始化它。

llm = OpenAI(temperature=0.9)

我们现在可以根据一些输入调用它!

text = "What would be a good company name for a company that makes colorful socks?"
print(llm(text))
Feetful of Fun

有关如何在 LangChain 中使用 LLM 的详细信息,请参阅 LLM 入门指南。

提示模板(PromptTemplate): 管理 LLM 的提示

调用 LLM 是很好的第一步,但这仅仅是个开始。

通常在应用程序中使用 LLM 时,不会将用户输入直接发送到 LLM。

相反,您可能接受用户输入并构造一个提示符,然后将其发送给 LLM。

例如,在前一个示例中,我们传入的文本被硬编码为询问一家生产彩色袜子的公司的名称。在这个虚构的服务中,我们希望只获取描述公司业务的用户输入,然后用这些信息格式化提示符。

使用LangChain,这个事情变得很简单!

首先让我们定义提示模板:

from langchain.prompts import PromptTemplate
 
prompt = PromptTemplate(
    input_variables=["product"],
    template="What is a good name for a company that makes {product}?",
)

现在让我们看看它是如何工作的!

我们可以调用. format 方法来格式化它。

print(prompt.format(product="colorful socks"))
What is a good name for a company that makes colorful socks?

有关详细信息,请参阅入门指南中的提示。

链: 在多步骤的工作流中组合 LLM 和提示

到目前为止,我们已经自己处理了单独的 PromptTemplateLLM

但是,真正的应用程序不仅仅是一个,而是它们的组合。

在 LangChain,链是由链组成的,可以是 LLM 这样的原始链,也可以是其他链。

最核心的链类型是 LLMChain,它由 PromptTemplateLLM 组成。

扩展前面的示例,我们可以构造一个LLMChain.

它接受用户输入,使用 PromptTemplate 对其进行格式化,然后将格式化后的响应传递给LLM

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
 
llm = OpenAI(temperature=0.9)
prompt = PromptTemplate(
    input_variables=["product"],
    template="What is a good name for a company that makes {product}?",
)

我们现在可以创建一个非常简单的链: 它接受用户输入,用它格式化提示符,然后将它发送到 LLM:

from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)

现在我们可以运行该链,只指定产品!

chain.run("colorful socks")
# -> '\n\nSocktastic!'

这就对了!你有第1个链 —— 1个 LLM 链

这是比较简单的链类型之一,但是了解它的工作原理将为您处理更复杂的链打下良好的基础。

有关更多细节,请查看链接的入门指南。

代理 Agent: 基于用户输入的动态调用链

到目前为止,我们看到的链运行在一个预先确定的顺序。

但是代理不再这样做: 它们使用 LLM 来确定要执行哪些操作以及按照什么顺序执行。

操作可以使用工具并观察其输出,也可以返回给用户。

如果使用得当,效果可以非常强大。

在本教程中,我们将向您展示如何通过最简单、最高级别的 API 轻松使用代理。

为了运好代理,您应该理解以下概念:

  • 工具(tools): 执行特定任务的功能。这可以是: Google 搜索、数据库查找、 Python REPL、其他链。工具的接口目前是一个函数,预计将有一个字符串作为输入,一个字符串作为输出。
  • 大语言模型(LLM): 为代理提供动力的语言模型。
  • 代理(agents): 要使用的代理。这应该是引用支持代理类的字符串。因为本教程主要关注最简单、最高级别的 API,所以它只涉及使用标准支持的代理。如果要实现自定义代理,请参阅自定义代理的文档(即将发布)。

代理(agents) : 有关受支持的 Agent 及其规范的列表,请参见此处

工具(tools) : 有关预定义工具及其规范的列表, 请参见此处.

对于本例,您还需要安装 SerpAPI Python 包。

pip install google-search-results

并设置适当的环境变量。

import os
os.environ["SERPAPI_API_KEY"] = "..."

现在我们可以开始了!

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import OpenAI
 
# First, let's load the language model we're going to use to control the agent.
llm = OpenAI(temperature=0)
 
# Next, let's load some tools to use. Note that the `llm-math` tool uses an LLM, so we need to pass that in.
tools = load_tools(["serpapi", "llm-math"], llm=llm)
 
# Finally, let's initialize an agent with the tools, the language model, and the type of agent we want to use.
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
 
# Now let's test it out!
agent.run("What was the high temperature in SF yesterday in Fahrenheit? What is that number raised to the .023 power?")
> Entering new AgentExecutor chain...
 I need to find the temperature first, then use the calculator to raise it to the .023 power.
Action: Search
Action Input: "High temperature in SF yesterday"
Observation: San Francisco Temperature Yesterday. Maximum temperature yesterday: 57 °F (at 1:56 pm) Minimum temperature yesterday: 49 °F (at 1:56 am) Average temperature ...
Thought: I now have the temperature, so I can use the calculator to raise it to the .023 power.
Action: Calculator
Action Input: 57^.023
Observation: Answer: 1.0974509573251117
Thought: I now know the final answer
Final Answer: The high temperature in SF yesterday in Fahrenheit raised to the .023 power is 1.0974509573251117.
> Finished chain.

内存: 向链和代理添加状态

到目前为止,我们经历过的所有工具和代理都是无状态的的。

但是通常,您可能希望链或代理具有某种“内存”概念,以便它可以记住关于其以前的交互的信息。

最简单明了的例子就是在设计一个聊天机器人时——你想让它记住之前的消息,这样它就可以利用这些消息的上下文来进行更好的对话。

这是一种“短期记忆”。在更复杂的一面,你可以想象一个链条/代理随着时间的推移记住关键信息——这将是一种形式的“长期记忆”。关于后者的更多具体想法,请参阅这篇令人敬畏的论文。 (opens in a new tab)

LangChain 提供了几个专门为此目的创建的链。 本教程使用其中一个链( ConversationChain ) 和两种不同类型的内存来完成操作。

默认情况下,, ConversationChain 有一个简单的内存类型,它记住所有以前的输入/输出,并将它们添加到传递的上下文中。

让我们看一下如何使用这个链(设置 verbose=True,这样我们就可以看到提示符)。

from langchain import OpenAI, ConversationChain
llm = OpenAI(temperature=0)
conversation = ConversationChain(llm=llm, verbose=True)
output = conversation.predict(input="Hi there!")
print(output)
> Entering new chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
Human: Hi there!
AI:
> Finished chain.
' Hello! How are you today?'
output = conversation.predict(input="I'm doing well! Just having a conversation with an AI.")
print(output)
> Entering new chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
Human: Hi there!
AI: Hello! How are you today?
Human: I'm doing well! Just having a conversation with an AI.
AI:
> Finished chain.
" That's great! What would you like to talk about?"

构建语言模型应用程序: 聊天模型

类似地,您可以使用聊天模型而不是 LLM。

聊天模型是语言模型的一种变体。

虽然聊天模型使用的是底层的语言模型,但它们公开的接口有些不同: 它们没有公开“文本输入、文本输出”API,而是公开了一个接口,其中“聊天消息”是输入和输出。

聊天模型 API 是相当新的,所以我们仍然在找出正确的抽象。

从聊天模型获取消息完成

您可以通过向聊天模型传递一条或多条消息来完成聊天。

响应将是一条消息。

LangChain 中当前支持的消息类型是 AIMessage , HumanMessage , SystemMessage , 和 ChatMessageChatMessage 接受任意角色参数。大多数时候,您只需要处理 HumanMessage , AIMessage , 和 SystemMessage .

from langchain.chat_models import ChatOpenAI
from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage
)
chat = ChatOpenAI(temperature=0)

您可以通过传入单个消息来完成。

chat([HumanMessage(content="Translate this sentence from English to French. I love programming.")])
# -> AIMessage(content="J'aime programmer.", additional_kwargs={})

您还可以为 OpenAI 的 gpt-3.5-turbo 和 gpt-4型号传递多条消息。

messages = [
    SystemMessage(content="You are a helpful assistant that translates English to French."),
    HumanMessage(content="Translate this sentence from English to French. I love programming.")
]
chat(messages)
# -> AIMessage(content="J'aime programmer.", additional_kwargs={})

您可以更进一步,使用generate为多组消息生成完成。

这将返回一个带有附加message参数的 LLMResult

batch_messages = [
    [
        SystemMessage(content="You are a helpful assistant that translates English to French."),
        HumanMessage(content="Translate this sentence from English to French. I love programming.")
    ],
    [
        SystemMessage(content="You are a helpful assistant that translates English to French."),
        HumanMessage(content="Translate this sentence from English to French. I love artificial intelligence.")
    ],
]
result = chat.generate(batch_messages)
 
result
# -> LLMResult(generations=[[ChatGeneration(text="J'aime programmer.", generation_info=None, message=AIMessage(content="J'aime programmer.", additional_kwargs={}))], [ChatGeneration(text="J'aime l'intelligence artificielle.", generation_info=None, message=AIMessage(content="J'aime l'intelligence artificielle.", additional_kwargs={}))]], llm_output={'token_usage': {'prompt_tokens': 71, 'completion_tokens': 18, 'total_tokens': 89}})

您可以从这个 LLMResult 中获取字符令牌的使用情况(token_usage):

result.llm_output['token_usage']
# -> {'prompt_tokens': 71, 'completion_tokens': 18, 'total_tokens': 89}
 

聊天提示模板

与 LLM 类似,您可以通过使用 MessagePromptTemplate来使用模板。

可以从一个或多个 MessagePromptTemplate 生成 ChatPromptTemplate

您可以使用 ChatPromptTemplateformat _ tip ——这将返回一个 PromptValue

您可以将其转换为字符串或 Message 对象,具体取决于您是想将格式化的值用作 llm 或聊天模型的输入。

为了方便起见,在模板上公开了一个 from _ template 方法。如果你使用这个模板,它看起来是这样的:

from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
 
chat = ChatOpenAI(temperature=0)
template = "You are a helpful assistant that translates {input_language} to {output_language}."
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
 
# get a chat completion from the formatted messages
chat(chat_prompt.format_prompt(input_language="English", output_language="French", text="I love programming.").to_messages())
 
# -> AIMessage(content="J'aime programmer.", additional_kwargs={})

带聊天模型的链

上一节讨论的 LLMChain也可以用于聊天模型:

from langchain.chat_models import ChatOpenAI
from langchain import LLMChain
from langchain.prompts.chat import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
 
chat = ChatOpenAI(temperature=0)
template = "You are a helpful assistant that translates {input_language} to {output_language}."
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
human_template = "{text}"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
chain = LLMChain(llm=chat, prompt=chat_prompt)
chain.run(input_language="English", output_language="French", text="I love programming.")
 
# -> "J'aime programmer."

具有聊天模型的代理

代理也可以与聊天模型一起使用,您可以使用 AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION作为代理类型来初始化一个聊天模型。

from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
from langchain.llms import OpenAI
 
# First, let's load the language model we're going to use to control the agent.
chat = ChatOpenAI(temperature=0)
 
# Next, let's load some tools to use. Note that the `llm-math` tool uses an LLM, so we need to pass that in.
llm = OpenAI(temperature=0)
tools = load_tools(["serpapi", "llm-math"], llm=llm)
 
# Finally, let's initialize an agent with the tools, the language model, and the type of agent we want to use.
agent = initialize_agent(tools, chat, agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
 
# Now let's test it out!
agent.run("Who is Olivia Wilde's boyfriend? What is his current age raised to the 0.23 power?")
> Entering new AgentExecutor chain...
Thought: I need to use a search engine to find Olivia Wilde's boyfriend and a calculator to raise his age to the 0.23 power.
Action:
{
 "action": "Search",
 "action_input": "Olivia Wilde boyfriend"
}
Observation: Sudeikis and Wilde's relationship ended in November 2020. Wilde was publicly served with court documents regarding child custody while she was presenting Don't Worry Darling at CinemaCon 2022. In January 2021, Wilde began dating singer Harry Styles after meeting during the filming of Don't Worry Darling.
Thought:I need to use a search engine to find Harry Styles' current age.
Action:
{
 "action": "Search",
 "action_input": "Harry Styles age"
}
Observation: 29 years
Thought:Now I need to calculate 29 raised to the 0.23 power.
Action:
{
 "action": "Calculator",
 "action_input": "29^0.23"
}
Observation: Answer: 2.169459462491557
Thought:I now know the final answer.
Final Answer: 2.169459462491557
> Finished chain.
'2.169459462491557'

记忆内存: 向链和代理添加状态

您可以对链使用 Memory,对代理使用聊天模型进行初始化。

这与 LLM 的 Memory 之间的主要区别在于,我们不需要将以前的所有消息压缩成一个字符串,而是可以将它们保留为自己独特的内存对象。

from langchain.prompts import (
    ChatPromptTemplate, 
    MessagesPlaceholder, 
    SystemMessagePromptTemplate, 
    HumanMessagePromptTemplate
)
from langchain.chains import ConversationChain
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory
 
prompt = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template("The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know."),
    MessagesPlaceholder(variable_name="history"),
    HumanMessagePromptTemplate.from_template("{input}")
])
llm = ChatOpenAI(temperature=0)
memory = ConversationBufferMemory(return_messages=True)
conversation = ConversationChain(memory=memory, prompt=prompt, llm=llm)
conversation.predict(input="Hi there!")
 
# -> 'Hello! How can I assist you today?'
conversation.predict(input="I'm doing well! Just having a conversation with an AI.")
 
# -> "That sounds like fun! I'm happy to chat with you. Is there anything specific you'd like to talk about?"
conversation.predict(input="Tell me about yourself.")
 
# -> "Sure! I am an AI language model created by OpenAI. I was trained on a large dataset of text from the internet, which allows me to understand and generate human-like language. I can answer questions, provide information, and even have conversations like this one. Is there anything else you'd like to know about me?"