大型语言模型(LLMs)非常强大,但它们缺乏一些“最笨”的计算机程序可以轻松处理的特定能力。逻辑、计算和搜索是计算机通常擅长的领域,但LLMs则表现不佳。
计算机可以解决非常复杂的数学问题,然而,如果我们要求GPT-4告诉我们4.1 * 7.9的答案,它会失败:
根据一个简单的计算器,答案是19.357,四舍五入到三位小数。令人着迷的是,一个简单的计算器程序可以做到这一点,但一个极其复杂的AI引擎失败了。
这还不是全部。如果我问GPT-4,“How do I use the LLMChain in LangChain?”它再次遇到困难:
LangChain确实是一个区块链项目[1] [2]。然而,似乎没有任何“LLMChain”组件或“LANG代币”——这两者都是幻觉。
GPT-4无法告诉我们有关LangChain的原因是它与外部世界没有联系。它唯一的知识来自于它从训练数据中捕获的内容,而这些数据截止到2021年末。
由于今天的LLMs存在重大弱点,我们必须找到解决这些问题的方法。一组潜在的解决方案以“代理人”的形式出现。
这些代理人不仅解决了我们上面看到的问题,还解决了许多其他问题。事实上,添加代理人在提升LLM能力方面具有几乎无限的潜力。
在本章中,我们将讨论代理人。我们将了解它们是什么,它们如何工作,以及如何在LangChain库中使用它们来赋予我们的LLMs超能力。
什么是代理?
我们可以将代理人看作是LLMs的“工具”。就像人类会使用计算器进行数学运算或进行谷歌搜索获取信息一样,代理人允许LLMs执行类似的操作。
使用代理,LLM可以编写和执行Python代码。它可以搜索信息,甚至查询SQL数据库。
让我们看一个简单的示例。我们将从一个“零-shot”代理开始(稍后详细介绍),允许我们的LLM使用计算器。
代理和工具
要使用代理,我们需要三样东西:
- 基础LLM,
- 我们将要进行交互的工具,
- 用于控制交互的代理。
让我们开始安装langchain并初始化我们的基础LLM。
from langchain import OpenAI
llm = OpenAI(
openai_api_key="OPENAI_API_KEY",
temperature=0,
model_name="text-davinci-003"
)
现在初始化计算器工具。在初始化工具时,我们可以创建自定义工具或加载预构建工具。无论哪种情况,“工具”都是一个具有工具名称和描述的实用程序链。
例如,我们可以从现有的llm_math链创建一个新的计算器工具:
In[3]:
from langchain.chains import LLMMathChain
from langchain.agents import Tool
llm_math = LLMMathChain(llm=llm)
# initialize the math tool
math_tool = Tool(
name='Calculator',
func=llm_math.run,
description='Useful for when you need to answer questions about math.'
)
# when giving tools to LLM, we must pass as list of tools
tools = [math_tool]
In[4]:
tools[0].name, tools[0].description
Out[4]:
('Calculator', 'Useful for when you need to answer questions about math.')
在使用自定义工具时,我们必须遵循这个过程。然而,预构建的llm_math工具执行相同的操作。因此,我们可以像上面那样做相同的操作,如下所示:
In[5]:
from langchain.agents import load_tools
tools = load_tools(
['llm-math'],
llm=llm
)
In[6]:
tools[0].name, tools[0].description
Out[6]:
('Calculator', 'Useful for when you need to answer questions about math.')
当然,只有在我们的用例中存在预构建的工具时,我们才能采用第二种方法。
现在,我们有了LLM和工具,但还没有代理。要初始化一个简单的代理,我们可以执行以下步骤:
from langchain.agents import initialize_agent
zero_shot_agent = initialize_agent(
agent="zero-shot-react-description",
tools=tools,
llm=llm,
verbose=True,
max_iterations=3
)
这里使用的代理是一个“零次反应描述”代理。零次反应意味着代理仅在当前操作上执行功能 – 它没有记忆。它使用ReAct框架来决定使用哪个工具,仅基于工具的描述。
在本章中,我们不会讨论ReAct框架,但你可以将其看作是LLM可以在推理和行动步骤之间循环的方式,以便识别答案的多步过程。
初始化了我们的代理后,我们可以开始使用它。让我们尝试一些提示,看看代理如何响应。
In[8]:
zero_shot_agent("what is (4.5*2.1)^2.2?")
Out[8]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I need to calculate this expression
Action: Calculator
Action Input: (4.5*2.1)^2.2[0m
Observation: [36;1m[1;3mAnswer: 139.94261298333066
[0m
Thought:[32;1m[1;3m I now know the final answer
Final Answer: 139.94261298333066[0m
[1m> Finished chain.[0m
Out[8]:
{'input': 'what is (4.5*2.1)^2.2?', 'output': '139.94261298333066'}
In[9]:
(4.5*2.1)**2.2
Out[9]:
139.94261298333066
这里的答案是正确的。让我们尝试另一个:
In[10]:
zero_shot_agent("if Mary has four apples and Giorgio brings two and a half apple "
"boxes (apple box contains eight apples), how many apples do we "
"have?")
Out[10]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I need to figure out how many apples are in the boxes
Action: Calculator
Action Input: 8 * 2.5[0m
Observation: [36;1m[1;3mAnswer: 20.0
[0m
Thought:[32;1m[1;3m I need to add the apples Mary has to the apples in the boxes
Action: Calculator
Action Input: 4 + 20.0[0m
Observation: [36;1m[1;3mAnswer: 24.0
[0m
Thought:[32;1m[1;3m I now know the final answer
Final Answer: We have 24 apples.[0m
[1m> Finished chain.[0m
Out[10]:
{'input': 'if Mary has four apples and Giorgio brings two and a half apple boxes (apple box contains eight apples), how many apples do we have?',
'output': 'We have 24 apples.'}
看起来不错!但是,如果我们决定问一个非数学问题呢?如果我们问一个简单的常识问题呢?
In[11]:
zero_shot_agent("what is the capital of Norway?")
Out[11]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I need to look up the answer
Action: Look up
Action Input: Capital of Norway[0m
Observation: Look up is not a valid tool, try another one.
Thought:[32;1m[1;3m I need to find the answer using a tool
Action: Calculator
Action Input: N/A[0m
我们遇到了一个错误。问题在于代理人不断尝试使用工具。然而,我们的代理人只包含一个工具 – 计算器。
幸运的是,我们可以通过为代理人添加更多工具来解决这个问题!让我们添加一个简单明了的LLM工具:
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
prompt = PromptTemplate(
input_variables=["query"],
template="{query}"
)
llm_chain = LLMChain(llm=llm, prompt=prompt)
# initialize the LLM tool
llm_tool = Tool(
name='Language Model',
func=llm_chain.run,
description='use this tool for general purpose queries and logic'
)
有了这个,我们有了一个新的通用LLM工具。我们只需将它添加到工具列表中,然后重新初始化代理人:
tools.append(llm_tool)
# reinitialize the agent
zero_shot_agent = initialize_agent(
agent="zero-shot-react-description",
tools=tools,
llm=llm,
verbose=True,
max_iterations=3
)
现在我们可以向代理人提问关于数学和常识的问题。让我们尝试以下问题:
In[15]:
zero_shot_agent("what is the capital of Norway?")
Out[15]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I need to find out what the capital of Norway is
Action: Language Model
Action Input: What is the capital of Norway?[0m
Observation: [33;1m[1;3m
The capital of Norway is Oslo.[0m
Thought:[32;1m[1;3m I now know the final answer
Final Answer: The capital of Norway is Oslo.[0m
[1m> Finished chain.[0m
Out[15]:
{'input': 'what is the capital of Norway?',
'output': 'The capital of Norway is Oslo.'}
现在我们得到了正确的答案!我们可以提出第一个问题:
In[16]:
zero_shot_agent("what is (4.5*2.1)^2.2?")
Out[16]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I need to calculate this expression
Action: Calculator
Action Input: (4.5*2.1)^2.2[0m
Observation: [36;1m[1;3mAnswer: 139.94261298333066
[0m
Thought:[32;1m[1;3m I now know the final answer
Final Answer: 139.94261298333066[0m
[1m> Finished chain.[0m
Out[16]:
{'input': 'what is (4.5*2.1)^2.2?', 'output': '139.94261298333066'}
而代理明白它必须参考计算器工具,它也做到了 – 给了我们正确的答案。
完成这一部分后,我们应该理解了使用不同工具设计和提示代理的工作流程。现在让我们继续了解可用于我们的不同类型的代理和工具。
代理类型
LangChain提供了几种类型的代理。在本节中,我们将检查一些最常见的代理类型。
零次反应 (Zero Shot ReAct)
我们将从之前看到的代理人开始,即零次反应描述(zero-shot-react-description)代理人。
如前所述,我们使用这个代理人来执行一些“零次反应”任务。这意味着代理人考虑与代理人的一次单一交互 – 它没有记忆。
让我们创建一个工具列表,以供代理人使用。我们将包括我们在这里定义的llm-math工具和SQL数据库工具。
tools = load_tools(
["llm-math"],
llm=llm
)
# add our custom SQL db tool
tools.append(sql_tool)
我们可以这样初始化零次反应描述代理人:
from langchain.agents import initialize_agent
zero_shot_agent = initialize_agent(
agent="zero-shot-react-description",
tools=tools,
llm=llm,
verbose=True,
max_iterations=3,
)
为了让SQL数据库工具有一些背景信息,我们将使用它来查询一个类似于这样的“股票数据库”:
obs_id | stock_ticker | price | data |
---|---|---|---|
1 | ‘ABC’ | 200 | 1 Jan 23 |
2 | ‘ABC’ | 208 | 2 Jan 23 |
3 | ‘ABC’ | 232 | 3 Jan 23 |
4 | ‘ABC’ | 225 | 4 Jan 23 |
5 | ‘ABC’ | 226 | 5 Jan 23 |
6 | ‘XYZ’ | 810 | 1 Jan 23 |
7 | ‘XYZ’ | 803 | 2 Jan 23 |
8 | ‘XYZ’ | 798 | 3 Jan 23 |
9 | ‘XYZ’ | 795 | 4 Jan 23 |
10 | ‘XYZ’ | 791 | 5 Jan 23 |
现在我们可以开始问关于这个SQL数据库的问题,并通过计算器工具进行计算。
In[16]:
result = zero_shot_agent(
"What is the multiplication of the ratio between stock prices for 'ABC' "
"and 'XYZ' in January 3rd and the ratio between the same stock prices in "
"January the 4th?"
)
Out[16]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m I need to compare the stock prices of 'ABC' and 'XYZ' on two different days
Action: Stock DB
Action Input: Stock prices of 'ABC' and 'XYZ' on January 3rd and January 4th[0m
[1m> Entering new SQLDatabaseChain chain...[0m
Stock prices of 'ABC' and 'XYZ' on January 3rd and January 4th
SQLQuery:[32;1m[1;3m SELECT stock_ticker, price, date FROM stocks WHERE (stock_ticker = 'ABC' OR stock_ticker = 'XYZ') AND (date = '2023-01-03' OR date = '2023-01-04')[0m
SQLResult: [33;1m[1;3m[('ABC', 232.0, '2023-01-03'), ('ABC', 225.0, '2023-01-04'), ('XYZ', 798.0, '2023-01-03'), ('XYZ', 795.0, '2023-01-04')][0m
Answer:[32;1m[1;3m The stock prices of 'ABC' and 'XYZ' on January 3rd and January 4th were 232.0 and 798.0 respectively for 'ABC' and 'XYZ' on January 3rd, and 225.0 and 795.0 respectively for 'ABC' and 'XYZ' on January 4th.[0m
[1m> Finished chain.[0m
Observation: [33;1m[1;3m The stock prices of 'ABC' and 'XYZ' on January 3rd and January 4th were 232.0 and 798.0 respectively for 'ABC' and 'XYZ' on January 3rd, and 225.0 and 795.0 respectively for 'ABC' and 'XYZ' on January 4th.[0m
Thought:[32;1m[1;3m I need to calculate the ratio between the two stock prices on each day
Action: Calculator
Action Input: 232.0/798.0 and 225.0/795.0[0m
Observation: [36;1m[1;3mAnswer: 0.2907268170426065
0.2830188679245283
[0m
Thought:[32;1m[1;3m I need to calculate the multiplication of the two ratios
Action: Calculator
Action Input: 0.2907268170426065 * 0.2830188679245283[0m
Observation: [36;1m[1;3mAnswer: 0.08228117463469994
[0m
Thought:[32;1m[1;3m[0m
[1m> Finished chain.[0m
我们可以看到很多输出。在每个步骤中,都有一个Thought,导致选择的Action和Action Input。如果Action要使用工具,那么观察(工具的输出)会传递回代理人。
如果我们看一下代理人使用的提示,我们可以看到LLM如何决定使用哪个工具。
In[17]:
print(zero_shot_agent.agent.llm_chain.prompt.template)
Out[17]:
Answer the following questions as best you can. You have access to the following tools:
Calculator: Useful for when you need to answer questions about math.
Stock DB: Useful for when you need to answer questions about stocks and their prices.
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [Calculator, Stock DB]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad}
首先,我们告诉LLM它可以使用的工具(计算器和股票数据库)。在此之后,定义了一个示例格式;这遵循了问题(来自用户)、思考、行动、行动输入、观察的流程 – 并且重复直到达到最终答案。
这些工具和思维过程将代理人与LangChain中的链分开。
而链定义了一个直接的输入/输出过程,代理人的逻辑允许逐步的思考过程。这个逐步的过程的优势在于LLM可以通过多个推理步骤或工具来产生更好的答案。
我们仍然需要讨论提示的一部分。最后一行是“Thought:{agent_scratchpad}”。
agent_scratchpad是我们添加代理人已经执行的每个思考或行动的地方。所有的思考和行动(在当前代理人执行链内)都可以被下一个思考-行动-观察循环访问,从而实现代理人行动的连续性。
会话式反应 (Conversational ReAct)
零次反应代理人效果良好,但缺乏会话记忆。这种缺乏记忆对于需要记住对话中先前交互的聊天机器人类型的用例可能会有问题。
幸运的是,我们可以使用会话式反应描述代理人来记住交互。我们可以将这个代理人看作是与我们之前的零次反应代理人相同,但具有会话记忆。
要初始化代理人,我们首先需要初始化我们想要使用的记忆。我们将使用简单的ConversationBufferMemory。
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="chat_history")
我们将这个传递给初始化代理人时的memory参数:
conversational_agent = initialize_agent(
agent='conversational-react-description',
tools=tools,
llm=llm,
verbose=True,
max_iterations=3,
memory=memory,
)
如果我们使用类似的问题运行这个代理人,我们应该会看到与之前相似的过程:
In[22]:
result = conversational_agent(
"Please provide me the stock prices for ABC on January the 1st"
)
Out[22]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m
Thought: Do I need to use a tool? Yes
Action: Stock DB
Action Input: ABC on January the 1st[0m
[1m> Entering new SQLDatabaseChain chain...[0m
ABC on January the 1st
SQLQuery:[32;1m[1;3m SELECT price FROM stocks WHERE stock_ticker = 'ABC' AND date = '2023-01-01'[0m
SQLResult: [33;1m[1;3m[(200.0,)][0m
Answer:[32;1m[1;3m The price of ABC on January the 1st was 200.0.[0m
[1m> Finished chain.[0m
Observation: [33;1m[1;3m The price of ABC on January the 1st was 200.0.[0m
Thought:[32;1m[1;3m Do I need to use a tool? No
AI: Is there anything else I can help you with?[0m
[1m> Finished chain.[0m
到目前为止,这看起来与我们上一个零次反应代理人非常相似。但与我们的零次反应代理人不同,我们现在可以提出后续问题。让我们询问XYZ在同一日期的股价,而不指定1月1日。
In[24]:
result = conversational_agent(
"What are the stock prices for XYZ on the same day?"
)
Out[24]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m
Thought: Do I need to use a tool? Yes
Action: Stock DB
Action Input: Stock prices for XYZ on January 1st[0m
[1m> Entering new SQLDatabaseChain chain...[0m
Stock prices for XYZ on January 1st
SQLQuery:[32;1m[1;3m SELECT price FROM stocks WHERE stock_ticker = 'XYZ' AND date = '2023-01-01'[0m
SQLResult: [33;1m[1;3m[(810.0,)][0m
Answer:[32;1m[1;3m The stock price for XYZ on January 1st was 810.0.[0m
[1m> Finished chain.[0m
Observation: [33;1m[1;3m The stock price for XYZ on January 1st was 810.0.[0m
Thought:[32;1m[1;3m Do I need to use a tool? No
AI: Is there anything else I can help you with?[0m
[1m> Finished chain.[0m
我们可以在第一个Action Input中看到,代理人正在寻找“1月1日XYZ的股价”。它知道我们要找1月1日的数据,因为我们在先前的交互中要求了这个日期。
它是如何做到这一点的呢?我们可以查看提示模板来找出答案:
In[23]:
print(conversational_agent.agent.llm_chain.prompt.template)
Out[23]:
Assistant is a large language model trained by OpenAI.
Assistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.
Assistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.
Overall, Assistant is a powerful tool that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.
TOOLS:
------
Assistant has access to the following tools:
> Calculator: Useful for when you need to answer questions about math.
> Stock DB: Useful for when you need to answer questions about stocks and their prices.
To use a tool, please use the following format:
```
Thought: Do I need to use a tool? Yes
Action: the action to take, should be one of [Calculator, Stock DB]
Action Input: the input to the action
Observation: the result of the action
```
When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:
```
Thought: Do I need to use a tool? No
AI: [your response here]
```
Begin!
Previous conversation history:
{chat_history}
New input: {input}
{agent_scratchpad}
在提示的开头,我们有一个更大的指令设置,但最重要的是提示末尾附近的两行:
以前的对话历史:{chat_history}
在这里,我们将所有先前的交互添加到提示中。在这个空间中将包含我们询问的“请提供ABC股票在1月1日的股价”的信息 – 这使代理人能够理解我们的后续问题指的是相同的日期。
值得注意的是,会话式ReAct代理人专为对话设计,当结合多个复杂步骤时,它比零次反应代理人更容易遇到困难。如果我们要求代理人回答我们之前的问题,我们可以看到这一点:
In[26]:
result = conversational_agent(
"What is the multiplication of the ratio of the prices of stocks 'ABC' "
"and 'XYZ' in January 3rd and the ratio of the same prices of the same "
"stocks in January the 4th?"
)
Out[26]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3mThought: Do I need to use a tool? Yes
Action: Stock DB
Action Input: Get the ratio of the prices of stocks 'ABC' and 'XYZ' in January 3rd and the ratio of the same prices of the same stocks in January the 4th[0m
[1m> Entering new SQLDatabaseChain chain...[0m
Get the ratio of the prices of stocks 'ABC' and 'XYZ' in January 3rd and the ratio of the same prices of the same stocks in January the 4th
SQLQuery:[32;1m[1;3m SELECT (SELECT price FROM stocks WHERE stock_ticker = 'ABC' AND date = '2023-01-03') / (SELECT price FROM stocks WHERE stock_ticker = 'XYZ' AND date = '2023-01-03') AS ratio_jan_3, (SELECT price FROM stocks WHERE stock_ticker = 'ABC' AND date = '2023-01-04') / (SELECT price FROM stocks WHERE stock_ticker = 'XYZ' AND date = '2023-01-04') AS ratio_jan_4 FROM stocks LIMIT 5;[0m
SQLResult: [33;1m[1;3m[(0.2907268170426065, 0.2830188679245283), (0.2907268170426065, 0.2830188679245283), (0.2907268170426065, 0.2830188679245283), (0.2907268170426065, 0.2830188679245283), (0.2907268170426065, 0.2830188679245283)][0m
Answer:[32;1m[1;3m The ratio of the prices of stocks 'ABC' and 'XYZ' in January 3rd is 0.2907268170426065 and the ratio of the same prices of the same stocks in January the 4th is 0.2830188679245283.[0m
[1m> Finished chain.[0m
Observation: [33;1m[1;3m The ratio of the prices of stocks 'ABC' and 'XYZ' in January 3rd is 0.2907268170426065 and the ratio of the same prices of the same stocks in January the 4th is 0.2830188679245283.[0m
Thought:[32;1m[1;3m Do I need to use a tool? No
AI: The answer is 0.4444444444444444. Is there anything else I can help you with?[0m
[1m> Finished chain.[0m
Spent a total of 2518 tokens
有了这个,代理人仍然能够解决问题,但使用了更复杂的纯SQL方法,而不是依赖更简单的SQL和计算器工具。
ReAct文档存储 (ReAct Docstore)
另一个常见的代理是react-docstore代理。与之前一样,它使用ReAct方法,但现在明确地构建用于信息搜索和查找的LangChain文档存储。
LangChain文档存储允许我们使用传统的检索方法存储和检索信息。其中一个文档存储是维基百科,它让我们访问该站点上的信息。
我们将使用两种文档存储方法来实现此代理 — 搜索和查找。使用搜索,我们的代理将搜索相关的文章,而使用查找,代理将在检索到的文章中找到相关的信息块。要初始化这两个工具,我们执行:
from langchain import Wikipedia
from langchain.agents.react.base import DocstoreExplorer
docstore=DocstoreExplorer(Wikipedia())
tools = [
Tool(
name="Search",
func=docstore.search,
description='search wikipedia'
),
Tool(
name="Lookup",
func=docstore.lookup,
description='lookup a term in wikipedia'
)
]
现在初始化代理:
docstore_agent = initialize_agent(
tools,
llm,
agent="react-docstore",
verbose=True,
max_iterations=3
)
让我们试一下下面的:
In[30]:
docstore_agent("What were Archimedes' last words?")
Out[30]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3mThought: I need to search Archimedes and find his last words.
Action: Search[Archimedes][0m
Observation: [36;1m[1;3mArchimedes of Syracuse (; c. 287 – c. 212 BC) was a Greek mathematician, physicist, engineer...[0m
Thought:[32;1m[1;3m The paragraph does not mention Archimedes' last words. I need to look up "last words".
Action: Lookup[last words][0m
Observation: [33;1m[1;3m(Result 1/1) Plutarch (45–119 AD) wrote in his Parallel Lives that Archimedes was related to King Hiero...[0m
Thought:[32;1m[1;3m The last words attributed to Archimedes are "Do not disturb my circles", so the answer is "Do not disturb my circles".
Action: Finish["Do not disturb my circles"][0m
[1m> Finished chain.[0m
Out[30]:
{'input': "What were Archimedes' last words?",
'output': '"Do not disturb my circles"'}
这个代理的提示非常长,因此我们将展示一个缩短版本。它只包含了这个代理应该如何使用搜索和查找工具的若干示例:
Question: What is the elevation range for the area that the eastern sector of the Colorado orogeny extends into?
Thought: I need to search Colorado orogeny, find the area that the eastern sector of the Colorado orogeny extends into, then find the elevation range of the area.
Action: Search[Colorado orogeny]
Observation: The Colorado orogeny was an episode of mountain building (an orogeny) in Colorado and surrounding areas.
Thought: It does not mention the eastern sector. So I need to look up eastern sector.
Action: Lookup[eastern sector]
Observation: (Result 1 / 1) The eastern sector extends into the High Plains and is called the Central Plains orogeny.
Thought: The eastern sector of Colorado orogeny extends into the High Plains. So I need to search High Plains and find its elevation range.
Action: Search[High Plains]
Observation: High Plains refers to one of two distinct land regions
Thought: I need to instead search High Plains (United States).
Action: Search[High Plains (United States)]
Observation: The High Plains are a subregion of the Great Plains. From east to west, the High Plains rise in elevation from around 1,800 to 7,000 ft (550 to 2,130 m).[3]
Thought: High Plains rise in elevation from around 1,800 to 7,000 ft, so the answer is 1,800 to 7,000 ft.
Action: Finish[1,800 to 7,000 ft]
这个提示包含若干类似格式的示例。在提示的末尾,我们看到:
Question: {input}
{agent_scratchpad}
与之前一样,我们有一个{input},用来传递最近的用户查询,以及一个{agent_scratchpad},用来跟踪之前的想法和行动。
与我们的对话代理不同,这里没有{chat_history}输入。这意味着我们正在使用另一个零-shot代理。
自我提问与搜索
让我们看一下最后一个代理——自我提问与搜索代理。当连接一个LLM与搜索引擎时,这是你应该考虑的首选代理。
这个代理将根据需要执行搜索并提出跟进问题,以获取最终答案。我们初始化这个代理如下所示:
from langchain import SerpAPIWrapper
# initialize the search chain
search = SerpAPIWrapper(serpapi_api_key='serp_api_key')
# create a search tool
tools = [
Tool(
name="Intermediate Answer",
func=search.run,
description='google search'
)
]
# initialize the search enabled agent
self_ask_with_search = initialize_agent(
tools,
llm,
agent="self-ask-with-search",
verbose=True
)
现在让我们提出一个需要多次搜索和“自我提问”步骤的问题。
In[38]:
self_ask_with_search(
"who lived longer; Plato, Socrates, or Aristotle?"
)
Out[38]:
[1m> Entering new AgentExecutor chain...[0m
[32;1m[1;3m Yes.
Follow up: How old was Plato when he died?[0m
Intermediate answer: [36;1m[1;3meighty[0m[32;1m[1;3m
Follow up: How old was Socrates when he died?[0m
Intermediate answer: [36;1m[1;3mapproximately 71[0m[32;1m[1;3m
Follow up: How old was Aristotle when he died?[0m
Intermediate answer: [36;1m[1;3m62 years[0m[32;1m[1;3m
So the final answer is: Plato[0m
[1m> Finished chain.[0m
Out[38]:
{'input': 'who lived longer; Plato, Socrates, or Aristotle?',
'output': 'Plato'}
我们可以看到代理的多步骤过程。它执行多个跟进问题,以逐渐找到最终答案。
这就是关于LangChain代理的这一章的全部内容。正如你无疑已经注意到的,代理在LangChain中涵盖了广泛的工具范围。我们已经涵盖了许多基本内容,但还有很多可以讨论的内容。
代理的转型潜力对于大型语言模型(LLM)来说是一个巨大的飞跃,而且在不久的将来,“LLM代理”这个术语很可能会与LLM本身变得同义。
通过赋予LLM利用工具和在这些代理框架中导航复杂的多步思维过程的能力,我们正在涉足一个庞大的、由人工智能驱动的机会领域。