天天看點

LangChain中文手冊之快速入門指南

作者:AI讓生活更美好

快速入門指南

本教程讓您快速了解如何使用 LangChain 建構端到端語言模型應用程式。

安裝

首先,使用以下指令安裝 LangChain:

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

環境設定

使用 LangChain 通常需要與一個或多個模型提供者、資料存儲、api 等內建。

對于這個例子,我們将使用 OpenAI 的 API,是以我們首先需要安裝他們的 SDK:

pip install openai
           

然後我們需要在終端中設定環境變量。

export OPENAI_API_KEY="..."
           

或者,您可以從 Jupyter notebook(或 Python 腳本)中執行此操作:

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

如果要動态設定 API 密鑰,可以在啟動 OpenAI 類時使用 openai_api_key 參數——例如,每個使用者的 API 密鑰。

from langchain.llms import OpenAI
llm = OpenAI(openai_api_key="OPENAI_API_KEY")
           

建構語言模型應用程式:LLM

現在我們已經安裝了 LangChain 并設定了我們的環境,我們可以開始建構我們的語言模型應用程式了。

LangChain 提供了很多可以用來建構語言模型應用的子產品。子產品可以組合起來建立更複雜的應用程式,或者單獨用于簡單的應用程式。

LLM:從語言模型中擷取預測

LangChain 最基本的建構塊是在某些輸入上調用 LLM。讓我們通過一個簡單的例子來說明如何做到這一點。為此,假設我們正在建構一項服務,該服務會根據公司的産品生成公司名稱。

為此,我們首先需要導入 LLM 包裝器。

from langchain.llms import OpenAI
           

然後我們可以用任何參數初始化包裝器。在此示例中,我們可能希望輸出更加随機,是以我們将使用高溫對其進行初始化。

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 入門指南。

提示模闆:管理 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?
           

有關更多詳細資訊,請檢視入門指南以擷取提示。

Chains:在多步驟工作流程中結合 LLM 和提示

到目前為止,我們一直在單獨使用 PromptTemplate 和 LLM 原語。但是,當然,真正的應用程式不僅僅是一個原語,而是它們的組合。

LangChain 中的一條鍊由連結組成,連結可以是像 LLM 這樣的原始鍊,也可以是其他鍊。

最核心的鍊類型是 LLMChain,它由 PromptTemplate 和 LLM 組成。

擴充前面的示例,我們可以建構一個 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!'
           

我們開始了!這是第一個鍊 - LLM 鍊。這是一種較簡單的鍊類型,但了解它的工作原理将為您處理更複雜的鍊做好準備。

有關更多詳細資訊,請檢視鍊的入門指南。

代理:基于使用者輸入的動态調用鍊

到目前為止,我們所看到的鍊條以預定的順序運作。

代理人不再這樣做:他們使用 LLM 來确定采取哪些行動以及采取何種順序。動作可以是使用工具并觀察其輸出,也可以是傳回給使用者。

如果使用得當,代理可以非常強大。在本教程中,我們将向您展示如何通過最簡單、最進階别的 API 輕松使用代理。

為了加載代理,您應該了解以下概念:

  • 工具:執行特定任務的功能。這可以是:Google 搜尋、資料庫查找、Python REPL、其他鍊。工具的接口目前是一個函數,期望将字元串作為輸入,将字元串作為輸出。
  • LLM:為代理提供支援的語言模型。
  • 代理:要使用的代理。這應該是一個引用支援代理類的字元串。由于本筆記本側重于最簡單、最進階别的 API,是以僅涵蓋使用标準支援的代理。如果您想實施自定義代理,請參閱自定義代理的文檔(即将推出)。

代理:有關受支援代理及其規範的清單,請參見此處。

工具:有關預定義工具及其規範的清單,請參見此處。

對于此示例,您還需要安裝 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.
           

記憶體:将狀态添加到鍊和代理中

到目前為止,我們所經曆的所有鍊和代理都是無狀态的。但通常,您可能希望鍊或代理具有某種“記憶”概念,以便它可以記住有關其先前互動的資訊。最清晰和簡單的例子是在設計聊天機器人時——您希望它記住以前的消息,以便它可以使用上下文來進行更好的對話。這将是一種“短期記憶”。在更複雜的方面,你可以想象一個鍊/代理随着時間的推移記住關鍵資訊——這将是一種“長期記憶”。有關後者的更具體想法,請參閱這篇很棒的論文。

LangChain 專門為此提供了幾個專門建立的鍊。本筆記本介紹了如何使用這些鍊中的一個 (the 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, 和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 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="I love programming.")
]
chat(messages)
# -> AIMessage(content="J'aime programmer.", additional_kwargs={})
           

您可以更進一步,使用 為多組消息生成補全generate。這将傳回LLMResult帶有附加message參數的 :

batch_messages = [
    [
        SystemMessage(content="You are a helpful assistant that translates English to French."),
        HumanMessage(content="I love programming.")
    ],
    [
        SystemMessage(content="You are a helpful assistant that translates English to French."),
        HumanMessage(content="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': 57, 'completion_tokens': 20, 'total_tokens': 77}})
           

您可以從此 LLMResult 中恢複諸如令牌使用之類的内容:

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

聊天提示模闆

與 LLM 類似,您可以通過使用MessagePromptTemplate. 您可以ChatPromptTemplate從一個或多個MessagePromptTemplates 建構一個。您可以使用ChatPromptTemplate's format_prompt– 這将傳回一個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 for 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 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?"