要安装LangChain,请运行:
pip install langchain
环境设置
使用LangChain通常需要与一个或多个模型提供者、数据存储、API等进行集成。在此示例中,我们将使用OpenAI的模型API。
首先,我们需要安装他们的Python包:
pip install openai
访问API需要一个API密钥,您可以通过创建账户并前往此处获取。获取密钥后,我们将通过运行以下命令将其设置为环境变量:
export OPENAI_API_KEY="您的API密钥"
如果您不想设置环境变量,您可以在初始化OpenAI LLM类时通过openai_api_key命名参数直接传递密钥:
from langchain.llms import OpenAI
llm = OpenAI(openai_api_key="您的API密钥")
构建应用程序
现在我们可以开始构建语言模型应用程序。LangChain提供了许多模块,可用于构建语言模型应用程序。模块可以作为简单应用程序中的独立模块使用,也可以组合在一起以实现更复杂的用例。
LLMs
从语言模型中获取预测
LangChain的基本构建块是LLM,它接收文本并生成更多文本。
举个例子,假设我们正在构建一个根据公司描述生成公司名称的应用程序。为了做到这一点,我们需要初始化一个OpenAI模型包装器。在这种情况下,由于我们希望输出更加随机,我们将使用较高的温度初始化模型。
from langchain.llms import OpenAI
llm = OpenAI(temperature=0.9)
现在我们可以传入文本并获取预测!
llm.predict("一个生产多彩袜子的公司的好公司名称是什么?")
输出结果为:
'欢乐之脚'
Chat模型
Chat模型是语言模型的一种变体。虽然Chat模型在内部使用语言模型,但它们提供的接口有点不同:它们不是提供一个“文本输入,文本输出”的API,而是提供一个接口,其中“聊天消息”是输入和输出。
您可以通过将一个或多个消息传递给Chat模型来获得聊天完成。响应将是一条消息。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.predict_messages([HumanMessage(content="将这句话从英文翻译成法文。我喜欢编程。")])
输出结果为:
AIMessage(content="J'aime programmer.", additional_kwargs={})
了解Chat模型与普通LLM的区别很有用,但有时仅仅将它们视为相同的模型进行交互可能更方便。LangChain通过也提供了一个接口,通过该接口您可以像处理普通LLM一样与Chat模型进行交互。您可以通过predict接口来实现:
chat.predict("将这句话从英文翻译成法文。我喜欢编程。")
输出结果为:
"J'aime programmer."
Prompt模板
大多数LLM应用程序不会直接将用户输入传递给LLM。通常,它们将用户输入添加到一个更大的文本片段中,称为prompt模板,以提供关于特定任务背景的额外上下文信息。
在前面的例子中,我们传递给模型的文本包含了生成公司名称的指示。对于我们的应用程序来说,如果用户只需要提供公司/产品的描述,而无需担心给模型提供指示,那将非常方便。
使用PromptTemplates可以很容易实现这一点!在这种情况下,我们的模板会非常简单:
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template("一个生产{product}的公司的好公司名称是什么?")
prompt.format(product="多彩袜子")
输出结果为:
'一个生产多彩袜子的公司的好公司名称是什么?'
链
现在我们已经有了一个模型和一个prompt模板,我们希望将两者结合起来。链为我们提供了一种将多个基本模块(如模型、prompt和其他链)链接(或串联)在一起的方式。
最简单且最常见的链类型是LLMChain,它首先将输入传递给PromptTemplate,然后再传递给LLM。我们可以从现有的模型和prompt模板构建一个LLM链。
from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)
chain.run("多彩袜子")
输出结果为:
'欢乐之脚'
理解这个简单的链是学习如何处理更复杂链的好基础。
Agents
我们的第一个链运行了一个预先确定的步骤序列。为了处理复杂的工作流,我们需要能够根据输入动态选择操作。
代理正是做到这一点的:它们使用语言模型来确定应采取的操作及其顺序。代理可以访问工具,并重复选择工具、运行工具和观察输出,直到得出最终答案。
要加载代理,您需要选择:
- LLM/Chat模型:驱动代理的语言模型。
- 工具:执行特定任务的函数。可以是谷歌搜索、数据库查询、Python REPL、其他链等。有关预定义工具及其规范的列表,请参阅工具文档。
- 代理名称:引用支持的代理类的字符串。代理类在很大程度上由语言模型用于确定采取哪个动作来参数化。因为这篇文章侧重于最简单的、最高级别的API,所以只涵盖了使用标准支持的代理。如果您想实现自定义代理,请参阅此处。有关支持的代理及其规范的列表,请参阅此处。
对于这个示例,我们将使用SerpAPI来查询搜索引擎。
您需要安装SerpAPI Python包:
pip install google-search-results
并设置SERPAPI_API_KEY环境变量。
from langchain.agents import AgentType, initialize_agent, load_tools
from langchain.llms import OpenAI
# 驱动代理的语言模型
llm = OpenAI(temperature=0)
# 给Agent访问的工具,注意'llm-math'工具使用LLM,因此需要将其传递给load_tools函数
tools = load_tools(["serpapi", "llm-math"], llm=llm)
# 初始化一个代理,包括工具、语言模型和要使用的代理类型
agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
# 测试代理
agent.run("昨天旧金山的最高气温是多少华氏度?将该数字提高到0.023次方是多少?")
输出结果为:
> 进入新的AgentExecutor链...
思考:首先我需要找到温度,然后使用计算器将其提高到0.023次方。
动作:搜索
输入:"昨天旧金山的最高气温"
观察:旧金山昨天的温度。最高温度:57°F(下午1:56) 最低温度:49°F(上午1:56) 平均温度...
思考:现在我有了温度,所以我可以使用计算器将其提高到0.023次方。
动作:计算器
输入:57^0.023
观察:答案:1.0974509573251117
思考:现在我知道最终答案
最终答案:昨天旧金山的最高气温的0.023次方是1.0974509573251117。
> 完成链。
昨天旧金山的最高气温的0.023次方是1.0974509573251117。
Memory
到目前为止,我们看到的链和代理都是无状态的,但对于许多应用程序来说,引用过去的交互是必要的。聊天机器人就是一个明显的例子,您希望它能在过去的消息上下文中理解新的消息。
Memory模块提供了一种维护应用程序状态的方式。基本Memory接口很简单:它允许您根据最新的运行输入和输出更新状态,并且允许您使用存储的状态修改(或上下文化)下一个输入。
有许多内置的Memory系统。其中最简单的是一个缓冲区Memory,它只是将最近几个输入/输出添加到当前输入之前。我们将在下面的示例中使用它。
from langchain import OpenAI, ConversationChain
llm = OpenAI(temperature=0)
conversation = ConversationChain(llm=llm, verbose=True)
conversation.run("你好!")
下面是底层实现:
> 进入新的链...
格式化后的prompt:
以下是人类和AI之间友好对话的内容。AI会健谈,并提供其上下文的许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
当前对话:
人类:你好!
AI:
> 完成链。
>> '你好!你今天好吗?'
现在,如果我们再次运行该链:
conversation.run("我很好!只是与AI聊天。")
我们会看到传递给模型的完整prompt包含我们第一个交互的输入和输出,以及我们最新的输入:
> 进入新的链...
格式化后的prompt:
以下是人类和AI之间友好对话的内容。AI会健谈,并提供其上下文的许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。
当前对话:
人类:你好!
AI:你好!你今天好吗?
人类:我很好!只是与AI聊天。
AI:
> 完成链。
>> '太好了!你想聊什么?'
内存
到目前为止,我们看到的链和代理都是无状态的,但对于许多应用程序来说,引用过去的交互是必要的。聊天机器人就是一个明显的例子,您希望它能在过去的消息上下文中理解新的消息。
Memory模块提供了一种维护应用程序状态的方式。基本Memory接口很简单:它允许您根据最新的运行输入和输出更新状态,并且允许您使用存储的状态修改(或上下文化)下一个输入。
有许多内置的Memory系统。其中最简单的是一个缓冲区Memory,它只是将最近几个输入/输出添加到当前输入之前。我们将在下面的示例中使用它。
from langchain.memory import BufferMemory
memory = BufferMemory(buffer_size=2)
memory.update_state("您好!")
memory.update_state("我很好!只是与AI聊天。")
memory.modify_next_input("这是一条新消息。")
输出结果为:
'这是一条新消息。您好!我很好!只是与AI聊天。'
在上面的示例中,我们首先更新了状态,然后修改了下一个输入,以便在最新的输入之前包含先前的输入和输出。
这只是Memory模块的一个简单示例。根据您的应用程序需求,可以使用不同的内置Memory系统或实现自定义的Memory系统。