经常使用 ReAct 构建 Claude Agent AI Python 和 3.5
Reason+Act (ReAct) Agent 能够经过将思想链推理与外部工具访问和迭代求解才干相联合,来执行复杂的推理义务。
ReAct Agent的上班原理
ReAct Agent的外围组件是系统揭示,它定义了Agent的全体行为(咱们稍后将看到一个示例)。
处置从用户揭示开局,用户揭示恳求处置某个疑问。系统揭示批示Agent对疑问启动推理,并在适当的时刻选用一个外部工具来协助处置疑问。
Agent调用工具,并在收到照应后选择能否须要进一步处置。假设须要,它可以再次恳求协助。Agent会在推理和执行(调用工具)之间迭代,直到它处置了疑问,而后将结果前往给用户。
下图说明了这个环节。
ReAct Agent环节
案例钻研
兴许,解释 ReAct Agent如何上班的最简双方法是经常使用一个便捷的案例钻研。以下是一个Agent处置便捷算术疑问的示例照应。
咱们从疑问“20 * 15 等于多少”开局,Agent开局“大声思索”。
20 * 15 等于多少
思索: 这是一个便捷的乘法疑问,我可以经常使用 calculate 操作来处置。
执行: calculate: 20 * 15
观察: 300
答案: 20 * 15 的结果是 300。
Agent的照应前面带有 思索 标签,它在其中推理当该做什么。在本例中,它选择经常使用 calculate
下一个照应前面带有 执行 标签,咱们看到Agent经常使用 calculate 工具来失掉答案。之后,咱们看到 观察,这是来自工具的照应。
最后的 答案 是Agent依据原始疑问和 calculate 工具的输入创立的照应的结果。
从外表上看,这里并没有什么特意不寻常的中央——除了Agent经常使用了一个咱们提供的工具。
而这正是 ReAct Agent的主要:Agent经常使用外部工具启动推理,而后采取执行。
迭代
当Agent选择它还没有得出论断,须要经过另一个推理/执行序列时,事情就变得更幽默了。Agent可以迭代推理/执行序列,直到得出有效论断。
上方的例子很便捷,但它向您展现了事情的基本序列。
假设咱们尝试更复杂的查问,咱们可以看到迭代在通常中的运行。
我问了Agent以下疑问:“_篮球队和曲棍球队的球员人数相乘的结果是多少?_”。
为了回答这个疑问,Agent须要找出每项静止的球员人数,而后将它们相乘。它可以经常使用 calculate
上方咱们看到Agent在得出令人满意的答案之前,三次经过了思索-执行-观察序列的模式。
要回答这个疑问,我须要找出篮球队和曲棍球队的球员人数,而后将这些数字相乘。让咱们从篮球开局。
思索: 我将先查阅篮球队的球员人数。
执行: wikipedia: 篮球
观察: 篮球是一项团队静止。每支球队在球场上同时有五名球员,虽然球队或许在替补席上有替补球员。
思索: 如今我知道一支篮球队在球场上同时有 5 名球员,我须要找出曲棍球队的球员人数。
执行: wikipedia: 曲棍球
观察: 曲棍球是一项团队静止,每支球队在球场上同时有 10 名球员:3 名进攻球员、3 名中场球员、3 名防卫球员和 1 名守门员。但是,在不同版本的较量中,人数或许会有所不同。例如,室内曲棍球的球员人数较少。
思索: 如今我曾经知道两种静止的球员人数,我可以计算结果了。
执行: calculate: 5 * 10
观察: 50
答案: 将篮球队的人数(5)乘以曲棍球队的人数(10)的结果是 50。
假设您通读输入内容,您会看到Agent如何在得出结果之行启动推理并咨询工具,并且在这样做的时刻,它会随着期间的推移积攒常识。
代码十分少
成功 ReAct Agent所需的代码出奇地少,由于大局部上班都在揭示中成功。
所以让咱们先看看这个。
prompt = """您在一个 Thought、Action、Observation、Answer 的循环中运转。在循环完结时,您输入一个 Answer经常使用 Thought 形容您对所问疑问的想法。经常使用 Action 运转您可以经常使用的操作之一。Observation 将是运转这些操作的结果。Answer 将是剖析 Observation 的结果。您可以经常使用的操作是:calculate:例如 calculate: 4 * 7 / 3运转计算并前往数字 - 经常使用 Python,因此假设须要,请务必修常使用浮点语法wikipedia:例如 wikipedia: Django从维基百科搜查前往摘要假设您可以经常使用维基百科查找内容,请一直经常使用维基百科启动查找。示例会话:疑问:法国的首都是什么?思索:我应该在维基百科上查找无关法国的信息执行:wikipedia: 法国而后您应该调用适当的操作并从结果中确定答案而后您输入:答案:法国的首都为巴黎"""
揭示的第一局部通知 LLM 如何经过咱们之前看到的标志环节局部来处置疑问,这些局部在循环中运转。
而后形容了 calculate 和 wikipedia
这个揭示是一个便捷的示例,当然仅用于演示目标。很显著,该揭示是为这个特定运行程序设计的:工具的形容是硬编码的,而在消费系统中,您宿愿能够以编程模式裁减它们。(咱们很快就会看到 calculate 是经常使用 Python 函数 eval() 成功的。这是一个相当蹩脚的做法,由于它很容易遭到代码注入攻打。)
代码和揭示的基本结构是 Simon 的,但我对其启动了修正,以便经常使用 Anthropic 的 Claude 3.5 Sonnet LLM,并简化了代码和揭示。
Claude Sonnet 3.5 是 Anthropic 最近颁布的一个版本,在他们的 颁布通告 中,他们申明“Claude 3.5 Sonnet 提高了行业自动规范,在宽泛的评价中优于竞争对手模型和 Claude 3 Opus,具备咱们中端模型 Claude 3 Sonnet 的速度和老本”。
为了说明这一点,Anthropic 领有三个版本的 Claude LLM,从更廉价、更快的 Haiku 模型,到更自动但更低廉的 Opus 模型。Sonnet 是介于两者之间的模型,是惟一在撰写本文时领有 3.5 版本的模型。
我不时想看看 Claude,这仿佛是一个很好的时机。
代码从必要的导入开局:
import anthropicimport reimport httpx
这里没有太多物品。Anthropic,当然,用于 LLM,正则表白式和一个 HTTP 库来访问维基百科。
要运转代码,您当然须要一个 Anthropic 帐户,他们会向您收取经常使用费。不过,它相当廉价:Claude 3.5 sonnet 比之前的版本更廉价,而且更弱小——我曾经在这里运转了代码(以及更多代码),只收取了几美分的费用。
代码首先创立一个客户端,而后定义一个 Python 类来成功聊天机器人。与 OpenAI 不同,Claude 将系统揭示与用户或助手的揭示离开,咱们在实例化 ChatBot 时初始化揭示。__call__ 函数担任存储用户信息和来自聊天机器人的照应,并调用 execute 来运转Agent。
client = anthropic.Anthropic(api_key="YOUR API KEY HERE")class ChatBot:def __init__(self, system=""):self.system = systemself.messages = []def __call__(self, message):self.messages.append({"role": "user", "content": message})result = self.execute()self.messages.append({"role": "assistant", "content": result})return messagedef execute(self):message = client.messages.create(model="claude-3-5-sonnet-20240620",max_tokens=1000,temperature=0,system = self.system,messages = self.messages)return message.content
下一步是定义一个 query() 函数,它经常使用聊天机器人的实例。query 函数成功了一个循环,该循环会不时继续到没有更多操作(或许咱们曾经到达最大迭代次数)为止。该函数检测操作并经常使用正则表白式提取操作的称号。这些操作被调用,当没有更多操作时,聊天机器人信息将被前往。
action_re = re.compile('^Action: (\w+): (.*)$')def query(question, max_turns=5):i = 0bot = ChatBot(prompt)next_prompt = questionwhile i < max_turns:i += 1result = bot(next_prompt)print(result)actions = [action_re.match(a) for a in result.split('\n') if action_re.match(a)]if actions:# 有一个要运转的操作action, action_input = actions[0].groups()if action not in known_actions:raise Exception("Unknown action: {}: {}".format(action, action_input))print(" -- running {} {}".format(action, action_input))observation = known_actions[action](action_input)print("Observation:", observation)next_prompt = "Observation: {}".format(observation)else:return bot.messages
如今咱们须要定义操作函数(工具)wikipedia 和 eval,并将对它们的援用存储在一个字典中。
def wikipedia(q):return httpx.get("https://en.wikipedia.org/w/api.php", params={"action": "query","list": "search","srsearch": q,"format": "json"}).json()["query"]["search"][0]["snippet"]def calculate(what):return eval(what)known_actions = {"wikipedia": wikipedia,"calculate": calculate}
接上去是一个适用程序函数,它打印出由机器人生成的最后一条信息。
def get_last_message():for m in bot.messages[-1]['content'][0].text.split('\n'):print(m)
最后,在成功一切这些步骤后,咱们可以开局经常使用Agent。
query("What is 20 * 15")get_last_message()
上方的代码发生了咱们在文章扫尾看到的第一个例子,上方的代码展现了 ReAct Agent如何迭代地执行各种操作以得出有效论断的另一个例子。
这是一个示例,其中Agent必定迭代调用工具。在本例中,它只经常使用维基百科,但它必定自动地剖析照应才干得出答案。
query("What languages are spoken in Spain that are also spoken in France")get_last_message()
西班牙和法国都经常使用哪些言语?
思索: 为了准确地回答这个疑问,我应该查找无关西班牙和法国经常使用的言语的信息。我将首先审核维基百科以失掉无关西班牙言语的信息。
执行: wikipedia: 西班牙语
观察: 西班牙在边陲外部经常使用多种言语和方言。西班牙的官网言语是西班牙语(也称为卡斯蒂利亚语),大少数西班牙人经常使用这种言语。但是,在各个自治区,有几种独特的官网言语:
加泰罗尼亚语:在加泰罗尼亚、巴利阿里群岛和瓦伦西亚自治区的局部地域经常使用(在那里被称为瓦伦西亚语)。
加利西亚语:在加利西亚经常使用。
巴斯克语:在巴斯克地域和纳瓦拉的局部地域经常使用。
奥克语(阿兰语):在加泰罗尼亚的阿兰谷经常使用。
其余公认的言语包含阿拉贡语和阿斯图里亚斯语。在不同的地域,还经常使用着几种西班牙语方言。
思索: 如今我曾经了解了西班牙的言语,我应该审核一下法国的言语,看看哪些言语堆叠。
执行: wikipedia: 法语
观察: 法国的官网言语是法语,占人口的 88%。但是,法国经常使用着几种地域言语和方言:
奥克语:在法国南部经常使用。
布列塔尼语:一种凯尔特言语,在布列塔尼经常使用。
阿尔萨斯语:一种日耳曼语方言,在阿尔萨斯经常使用。
科西嘉语:在科西嘉岛经常使用。
加泰罗尼亚语:在法国东比利牛斯省经常使用。
巴斯克语:在法国巴斯克地域经常使用。
其余地域言语包含法兰克-普罗旺斯语、洛林弗兰克语和各种油语。
思索: 经过比拟西班牙和法国经常使用的言语,我可以识别出堆叠的言语。
答案: 西班牙和法国都经常使用的言语是:
加泰罗尼亚语:在西班牙的局部地域(加泰罗尼亚、巴利阿里群岛和瓦伦西亚)以及法国的东比利牛斯省经常使用。
巴斯克语:在西班牙的巴斯克地域和纳瓦拉的局部地域经常使用,以及法国的巴斯克地域。
奥克语:在西班牙加泰罗尼亚的阿兰谷被称为阿兰语,并在法国南部经常使用。
这三种言语在两个国度都失掉认可和经常使用,虽然它们在西班牙和法国的官网位置和经常使用人数或许会有所不同。
上方的照应展现了Agent为了得出适宜的答案而经过的正当环节。
我还尝试了更复杂的疑问,Agent仿佛也能很好地处置这些疑问(您可以在下载的代码中看到更多示例)。
论断
本文引见的代码展现了 ReAct Agent的上班模式。它并不强健,也不适宜消费环境。但我宿愿您如今对 ReAct Agent的原理以及如何成功它们有了相当好的了解。
请经常使用更复杂的示例尝试代码,并或许减少更多工具。我很乐意听到您的试验结果。
当然,经常使用 Langchain 和 Llamaindex(例如)有更便捷的处置打算,我或许会在的文章中引见它们。
本文转载自,作者: