LangChain 入门学习笔记

LangChain 是什么

大规模语言模型(LLM)正在成为一种变革性技术,使开发人员能够构建以前不能构建的应用程序。然而,孤立使用这些语言模型通常不足以创建一个真正强大的应用程序 - 真正的力量来自能够将它们与其他计算或知识来源结合使用。

这个库旨在帮助开发这类应用程序。这类应用程序的常见示例包括:

  • 对特定文档进行问题解答
  • 聊天机器人
  • 代理

这个库为开发人员提供:

  • 用于语言模型、链和代理的通用接口。
  • 许多内置实用程序,可以立即使用。
  • 与许多外部工具的集成(例如Notion、Anthropic Constitutional AI等)。
  • 用于常见应用(如问题解答、聊天机器人等)的端到端示例。

总之,LangChain 旨在通过在各种计算资源和知识资源之间构建复杂的交互来实现语言模型的真正潜力。我们希望这个库可以推动新一代更智能、更实用的自然语言应用的开发。

LangChain 设计用于帮助六个主要方面的工作

这些工作按复杂度递增顺序如下:

  1. 语言模型和提示:
    这包括提示管理、提示优化、所有的语言模型的通用接口以及使用语言模型的常用工具。

  2. 链:
    链超越了单个语言模型调用,涉及一系列调用(无论是对语言模型还是其他工具)。LangChain为链提供了一个标准接口,与其他工具的大量集成以及用于常见应用的端到端链。

  3. 数据增强生成:
    数据增强生成涉及到使用外部数据源获取数据,然后在生成步骤中使用这些数据的特定类型链。示例包括长文本的摘要和特定数据源的问答。

  4. 代理:
    代理涉及语言模型做出关于采取什么行动的决定,采取行动,看到观察结果,然后重复此过程直至完成。LangChain为代理提供了一个标准接口,可选择的代理以及端到端代理的示例。

  5. 记忆:
    记忆是指在链/代理调用之间持续状态。LangChain为记忆提供了一个标准接口,一系列记忆实现以及使用记忆的链/代理示例。

  6. 评估:
    [BETA] 生产模型通常很难用传统指标进行评估。评估它们的一种新方法是使用语言模型本身进行评估。LangChain提供了一些提示/链来帮助这方面工作。

快速入门指南

本教程为您提供了有关使用 LangChain 构建端到端语言模型应用程序的快速演练。

安装

要开始使用,请使用以下命令安装 LangChain:

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

环境设置

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

在本例中,我们将使用 OpenAI 的 API,因此我们首先需要安装它们的 SDK:

! pip install openai

然后,我们需要创建一个 .env 文件设置环境变量。

OPENAI_API_KEY=...

如果你是通过 Proxy 访问 OpenAI时,设置下面环境变量。

OPENAI_API_BASE==...

或者,您可以从 Jupyter 笔记本(或 Python 脚本)中执行此操作:

! pip install python-dotenv
import openai
import os

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file

openai.api_key  = os.getenv('OPENAI_API_KEY')
openai.api_base  = os.getenv('OPENAI_API_BASE')

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

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

LangChain提供了许多可用于构建语言模型应用程序的模块。模块可以组合以创建更复杂的应用程序,也可以单独用于简单的应用程序。

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

LangChain 最基本的构建块是在某些输入上调用 LLM。 让我们通过一个简单的示例来说明如何执行此操作。 为此,让我们假设我们正在构建一个服务,该服务根据公司制作的内容生成公司名称。

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

from langchain.llms import OpenAI

然后,我们可以用任何参数初始化包装器。 在这个例子中,我们可能希望输出更加随机,所以我们将使用 temperature 初始化它。

llm = OpenAI(temperature=0.9)

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

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

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

提示词模板:管理 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 和提示词

到目前为止,我们已经单独使用过 PromptTemplate 和 LLM 这两个基本组件。当然,真实的应用程序不仅包含一个基本组件,而是将多个组件组合在一起。

在LangChain中,链由链接组成,链接可以是像语言模型之类的基本组件,也可以是其他链。

最核心的链类型是 LLMChain,它由 PromptTemplate 和语言模型组成。

扩展前面的示例,我们可以构造一个 LLMChain,它接受用户输入,使用 PromptTemplate 格式化响应,然后将格式化的响应传递给语言模型。

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}?",
)

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

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

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

chain.run("colorful socks")
# -> '\n\nRainbow Toes.'

就是这样!这是第一个链 - LLM Chain。这是较简单的链类型之一,但理解它的工作原理将让您很好地准备使用更复杂的链。

有关更多详细信息,请查看链入门指南。

代理:根据用户输入动态调用链

到目前为止,我们已经看到的链按预定顺序运行。

代理不再这样做:他们使用LLM来确定要采取哪些操作以及以什么顺序执行。操作可以使用工具并观察其输出,也可以返回给用户。

如果使用得当,代理可以非常强大。在本教程中,我们将向您展示如何通过最简单、最高级别 API 轻松使用代理。

为了加载代理,您应该了解以下概念:

  • 工具:执行特定职责的功能。这可以是:谷歌搜索,数据库查找,Python REPL,其他链。工具的接口当前是一个函数,该函数应将字符串作为输入,并将字符串作为输出。
  • LLM:为代理提供支持的语言模型。
  • 代理:要使用的代理。这应该是引用支持代理类的字符串。由于本教程重点介绍最简单、最高级别 API,因此仅涵盖使用受支持的标准代理。如果要实现自定义代理,请参阅自定义代理的文档(即将推出)。

代理:有关支持的代理及其规范的列表,请参阅此处

工具:有关预定义工具及其规格的列表,请参阅此处

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

! pip install google-search-results

我们需要修改 .env 文件设置环境变量。。(访问 https://serpapi.com/ 注册,每个月有 100 个免费 API 访问。)

import os
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

from dotenv import load_dotenv, find_dotenv
import os
_ = load_dotenv(find_dotenv()) # read local .env file

# os.environ['SERPAPI_API_KEY']  = os.getenv('SERPAPI_API_KEY')
# 首先,让我们加载我们将用来控制代理的语言模型。
llm = OpenAI(temperature=0)

# 接下来,让我们加载一些工具来使用。请注意,`llm-math` 工具使用 LLM,因此我们需要传递它
tools = load_tools(["serpapi", "llm-math"], llm=llm)


# 最后,让我们使用这些工具、语言模型和我们想要使用的代理类型来初始化一个代理。
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 Dalian 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 Dalian yesterday in Fahrenheit"
Observation: No good search result found
Thought: I should try a different search query
Action: Search
Action Input: "Dalian temperature yesterday in Fahrenheit"
Observation: No good search result found
Thought: I should try a different search query
Action: Search
Action Input: "Dalian weather yesterday in Fahrenheit"
Observation: No good search result found
Thought: I should try a different search query
Action: Search
Action Input: "Dalian temperature yesterday"
Observation: Weather History ; 12:00. 12 °c. Overcast. 9 °c ; 15:00. 12 °c. Patchy rain possible. 9 °c ; 18:00. 12 °c. Light drizzle. 9 °c.
Thought: I should convert the temperature from Celsius to Fahrenheit
Action: Calculator
Action Input: 12 °C to Fahrenheit
Observation: Answer: 53.6
Thought: I now know the temperature
Action: Calculator
Action Input: 53.6 raised to the .023 power
Observation: Answer: 1.0958996548776438
Thought: I now know the final answer
Final Answer: The high temperature in Dalian yesterday in Fahrenheit was 53.6, and that number raised to the .023 power is 1.0958996548776438.

> Finished chain.
'The high temperature in Dalian yesterday in Fahrenheit was 53.6, and that number raised to the .023 power is 1.0958996548776438.'

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

到目前为止,我们经历的所有链条和代理人都是无状态的。但通常,您可能希望链或代理具有一些 “记忆” 概念,以便它可以记住有关其先前交互的信息。最清晰和简单的例子是在设计聊天机器人时 - 您希望它记住以前的消息,以便它可以使用它中的上下文进行更好的对话。这将是一种 “短期记忆”。在更复杂的方面,你可以想象一个链/代理随着时间的推移记住关键信息 - 这将是 “长期记忆” 的一种形式。有关后者的更多具体想法,请参阅这篇很棒的论文。

LangChain为此提供了几个专门创建的链。本教程演示了如何使用其中一种链(ConversationChain)来使用两种不同类型的记忆。

默认情况下,Conversation 具有简单的内存类型,可以记住所有以前的输入/输出,并将它们添加到传递的上下文中。让我们看一下如何使用这个链(设置 Chainverbose=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 ConversationChain 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.
 Hi there! It's nice to meet you. How can I help you today?
output = conversation.predict(input="I'm doing well! Just having a conversation with an AI.")
print(output)
> Entering new ConversationChain 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:  Hi there! It's nice to meet you. How can I help you today?
Human: I'm doing well! Just having a conversation with an AI.
AI:

> Finished chain.
 That's great! It's always nice to have a conversation with someone new. What would you like to talk about?

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

同样地,您可以使用聊天模型而不是 LLM。聊天模型是语言模型的一种变体。虽然聊天模型在底层使用语言模型,但它们公开的接口略有不同:它们不是暴露一个“输入文本,输出文本”的 API,而是暴露一个“聊天消息”作为输入和输出的接口。
聊天模型的 API 相当新,因此我们仍在找出正确的抽象。

从聊天模型获取消息完成

您可以通过向聊天模型传递一个或多个消息来获取聊天完成。响应将是一条消息。

目前在 LangChain 中支持的消息类型有 AIMessage、HumanMessage、SystemMessage 和 ChatMessage - ChatMessage 接受一个任意角色参数。大多数情况下,您只需要处理 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 Chinese. I love programming.")])
# -> AIMessage(content='我喜欢编程。', additional_kwargs={}, example=False)

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

messages = [
    SystemMessage(content="You are a helpful assistant that translates English to Chinese."),
    HumanMessage(content="I love programming.")
]
chat(messages)
# -> AIMessage(content='我喜欢编程。', additional_kwargs={}, example=False)

您可以进一步通过使用 generate 为多组消息生成完成。这将返回一个带有额外消息参数的 LLMResult:

batch_messages = [
    [
        SystemMessage(content="You are a helpful assistant that translates English to Chinese."),
        HumanMessage(content="I love programming.")
    ],
    [
        SystemMessage(content="You are a helpful assistant that translates English to Chinese."),
        HumanMessage(content="I love artificial intelligence.")
    ],
]
result = chat.generate(batch_messages)
result
# -> LLMResult(generations=[[ChatGeneration(text='我喜欢编程。', generation_info=None, message=AIMessage(content='我喜欢编程。', additional_kwargs={}, example=False))], [ChatGeneration(text='我喜欢人工智能。', generation_info=None, message=AIMessage(content='我喜欢人工智能。', additional_kwargs={}, example=False))]], llm_output={'token_usage': {'prompt_tokens': 57, 'completion_tokens': 19, 'total_tokens': 76}, 'model_name': 'gpt-3.5-turbo'})

您可以从这个 LLMResult 中恢复诸如令牌使用情况之类的信息:

result.llm_output['token_usage']
# -> {'prompt_tokens': 57, 'completion_tokens': 19, 'total_tokens': 76}

聊天提示词模板

与 LLM 类似,您可以使用 MessagePromptTemplate 制作模板。您可以从一个或多个 MessagePromptTemplate 构建 ChatPromptTemplate。您可以使用 ChatPromptTemplate 的 format_prompt - 这将返回一个 PromptValue,您可以将其转换为字符串或消息对象,具体取决于您是否想将格式化值用作 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='我喜欢编程。', additional_kwargs={}, example=False)

具有聊天模型的链

上一节中讨论的内容也可以与聊天模型一起使用: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="Chinese", text="I love programming.")
# -> '我喜欢编程。'

具有聊天模型的代理

代理也可以与聊天模型一起使用,您可以使用 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 的记忆的主要区别在于,我们不再尝试将所有先前的消息压缩成一个字符串,而是可以将它们作为自己独特的记忆对象保留。

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 designed to assist with various tasks such as answering questions, generating text, and providing recommendations. I was created using natural language processing techniques and machine learning algorithms, which allow me to understand and respond to human language. I am constantly learning and improving based on the interactions I have with users like you. Is there anything else you'd like to know?"

完结!

猜你喜欢

转载自blog.csdn.net/engchina/article/details/130741443