Skip to main content

自定义MRKL代理

MRKL:Modular Reasoning, Knowledge and Language
来源:https://arxiv.org/abs/2205.00445
参考:https://medium.com/mlearning-ai/supercharging-large-language-models-with-langchain-1cac3c103b52

本文档介绍如何创建自定义的MRKL代理。

一个MRKL代理由三个部分组成:

  • 工具:代理可用的工具。
  • LLMChain:产生被解析的文本以确定采取哪种操作的LLMChain。
  • 代理类本身:解析LLMChain的输出以确定采取哪种操作。

在本文档中,我们将通过创建自定义的LLMChain来演示如何创建自定义的MRKL代理。

自定义LLMChain

创建自定义代理的第一种方法是使用现有的Agent类,但使用自定义的LLMChain。这是创建自定义代理的最简单方法。强烈建议您使用ZeroShotAgent,因为目前它是最通用的。

创建自定义LLMChain的大部分工作都涉及到提示。因为我们使用现有的代理类来解析输出,所以提示中指定以该格式生成文本非常重要。此外,我们目前需要一个agent_scratchpad输入变量来记录之前的操作和观察。这几乎总是提示的最后一部分。除了这些指令之外,您可以根据需要自定义提示。

为了确保提示包含适当的指令,我们将利用该类上的一个辅助方法。ZeroShotAgent的辅助方法接受以下参数:

  • tools:代理将访问的工具列表,用于格式化提示。
  • prefix:在工具列表之前放置的字符串。
  • suffix:在工具列表之后放置的字符串。
  • input_variables:最终提示将期望的输入变量列表。

在这个例子中,我们将让我们的代理访问Google搜索,并将其定制为以海盗的口吻回答问题。

from langchain.agents import ZeroShotAgent, Tool, AgentExecutor  
from langchain import OpenAI, SerpAPIWrapper, LLMChain

search = SerpAPIWrapper()
tools = [
Tool(
name="Search",
func=search.run,
description="用于回答有关当前事件的问题时非常有用",
)
]

prefix = """尽力回答以下问题,但要以海盗的口吻回答。您可以使用以下工具:"""
suffix = """开始!在给出最终答案时,请记住以海盗的口吻说话。使用很多"Args"

问题:{input}
{agent_scratchpad}"""

prompt = ZeroShotAgent.create_prompt(
tools, prefix=prefix, suffix=suffix, input_variables=["input", "agent_scratchpad"]
)

如果我们好奇,现在我们可以查看最终提示模板,看看当所有内容都放在一起时它是什么样子的。

print(prompt.template)  
尽力回答以下问题,但要以海盗的口吻回答。您可以使用以下工具:  

Search: 用于回答有关当前事件的问题时非常有用

使用以下格式:

问题:您必须回答的输入问题
思考:您应该始终考虑要做什么
行动:要采取的行动,应为[Search]之一
行动输入:行动的输入
观察:行动的结果
...(这个思考/行动/行动输入/观察可以重复N次)
思考:我现在知道最终答案
最终答案:原始输入问题的最终答案

开始!在给出最终答案时,请记住以海盗的口吻说话。使用很多"Args"

问题:{input}
{agent_scratchpad}

请注意,我们可以为代理提供自定义的提示模板,即不限于create_prompt函数生成的提示,只要它符合代理的要求。

例如,对于ZeroShotAgent,我们需要确保它满足以下要求。应该有一个以"Action:"开头的字符串,后面跟着一个以"Action Input:"开头的字符串,两者之间应该用换行符分隔。

llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)  

tool_names = [tool.name for tool in tools]
agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)

agent_executor = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True
)

agent_executor.run("截至2023年,加拿大有多少人口?")

输出结果:

> 进入新的AgentExecutor链...
思考:我需要找出加拿大的人口
行动:Search
行动输入:加拿大2023年人口
观察:根据世界计量器对最新的联合国数据的阐述,截至2023年4月16日星期日,加拿大的当前人口为38,661,927人。
思考:我现在知道最终答案
最终答案:嗯哼,截至2023年,加拿大有38,661,927人居住!

> 完成链。


最终输出结果:

"嗯哼,截至2023年,加拿大有38,661,927人居住!"

多个输入

Agents也可以使用需要多个输入的提示进行工作。

```python
prefix = """尽力回答以下问题。您可以使用以下工具:"""
suffix = """回答时,您必须使用以下语言:{language}。

问题:{input}
{agent_scratchpad}"""

prompt = ZeroShotAgent.create_prompt(
tools,
prefix=prefix,
suffix=suffix,
input_variables=["input", "language", "agent_scratchpad"],
)

llm_chain = LLMChain(llm=OpenAI(temperature=0), prompt=prompt)

agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools)

agent_executor = AgentExecutor.from_agent_and_tools(
agent=agent, tools=tools, verbose=True
)

agent_executor.run(
input="截至2023年,加拿大有多少人口?", language="意大利语"
)

> 进入新的AgentExecutor链...
思考:我应该寻找最近的人口估计。
行动:搜索
行动输入:加拿大人口2023年
观察:39,566,248
思考:我应该再次核实这个数字。
行动:搜索
行动输入:加拿大人口估计2023年
观察:加拿大的人口估计在2023年1月1日为39,566,248人,这是自2022年1月1日至2023年1月1日人口增长创下纪录的1,050,110人。
思考:我现在知道最终答案了。
最终答案:La popolazione del Canada è stata stimata a 39.566.248 il 1° gennaio 2023, dopo un record di crescita demografica di 1.050.110 persone dal 1° gennaio 2022 al 1° gennaio 2023.

> 完成链。

'La popolazione del Canada è stata stimata a 39.566.248 il 1° gennaio 2023, dopo un record di crescita demografica di 1.050.110 persone dal 1° gennaio 2022 al 1° gennaio 2023.'