将Agent作为迭代器运行
为了演示AgentExecutorIterator
的功能,我们将设置一个问题,其中一个Agent必须:
- 从一个工具中获取三个质数
- 将它们相乘
在这个简单的问题中,我们可以通过检查中间步骤的输出是否为质数来添加一些逻辑来验证中间步骤。
import os
import dotenv
import pydantic
from langchain.agents import AgentExecutor, initialize_agent, AgentType
from langchain.schema import AgentFinish
from langchain.agents.tools import Tool
from langchain import LLMMathChain
from langchain.chat_models import ChatOpenAI
API参考:
- AgentExecutor 来自
langchain.agents
- initialize_agent 来自
langchain.agents
- AgentType 来自
langchain.agents
- AgentFinish 来自
langchain.schema
- Tool 来自
langchain.agents.tools
- ChatOpenAI 来自
langchain.chat_models
# 如果在存储库的根目录中有一个.env文件,请取消下面的注释
# dotenv.load_dotenv("../../../../../.env")
# 在这里需要使用GPT-4,因为GPT-3.5无法理解,无论你如何坚持,它都应该使用计算器进行最后的计算
llm = ChatOpenAI(temperature=0, model="gpt-4")
llm_math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)
定义提供以下功能的工具:
- 第
n
个质数(在这个示例中使用一个小的子集) - 作为计算器的LLMMathChain
primes = {998: 7901, 999: 7907, 1000: 7919}
class CalculatorInput(pydantic.BaseModel):
question: str = pydantic.Field()
class PrimeInput(pydantic.BaseModel):
n: int = pydantic.Field()
def is_prime(n: int) -> bool:
if n <= 1 or (n % 2 == 0 and n > 2):
return False
for i in range(3, int(n**0.5) + 1, 2):
if n % i == 0:
return False
return True
def get_prime(n: int, primes: dict = primes) -> str:
return str(primes.get(int(n)))
async def aget_prime(n: int, primes: dict = primes) -> str:
return str(primes.get(int(n)))
tools = [
Tool(
name="GetPrime",
func=get_prime,
description="返回第`n`个质数的工具",
args_schema=PrimeInput,
coroutine=aget_prime,
),
Tool.from_function(
func=llm_math_chain.run,
name="Calculator",
description="在需要计算数学表达式时很有用",
args_schema=CalculatorInput,
coroutine=llm_math_chain.arun,
),
]
构建Agent。我们将在这里使用默认的Agent类型。
agent = initialize_agent(
tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
运行迭代并对某些步骤进行自定义检查:
question = "第998个、第999个和第1000个质数的乘积是多少?"
for step in agent.iter(question):
if output := step.get("intermediate_step"):
action, value = output[0]
if action.tool == "GetPrime":
print(f"检查 {value} 是否为质数...")
assert is_prime(int(value))
# 询问用户是否要继续
_continue = input("是否继续(Y/n)?:\n")
if _continue != "Y":
break
输出结果:
> 进入新的链...
我首先需要找到第998个、第999个和第1000个质数。
动作:GetPrime
动作输入:998
观察结果:7901
思考:检查 7901 是否为质数...
是否继续(Y/n)?:
Y
我已经找到了第998个质数。现在我需要找到第999个质数。
动作:GetPrime
动作输入:999
观察结果:7907
思考:检查 7907 是否为质数...
是否继续(Y/n)?:
Y
我已经找到了第999个质数。现在我需要找到第1000个质数。
动作:GetPrime
动作输入:1000
观察结果:7919
思考:检查 7919 是否为质数...
是否继续(Y/n)?:
Y
我已经找到了所有三个质数。现在我需要计算这些数字的乘积。
动作:Calculator
动作输入:7901 * 7907 * 7919
> 进入新的链...
7901 * 7907 * 7919```text
7901 * 7907 * 7919
...numexpr.evaluate("7901 * 7907 * 7919")...
答案:494725326233
> 完成链。
观察结果:答案:494725326233
思考:是否继续(Y/n)?:
Y
我现在知道了最终答案
最终答案:494725326233
> 完成链。