从零开始构建ReAct:无框架的思考、行动、暂停与观察
手动构建一个极小的 Groq ReAct 循环——先进行人工观察,再通过正则表达式触发工具调用——以此了解现代智能体框架为何会呈现这样的特性。
简介
可以询问通俗语言模型Nvidia的实时股价,以及10万美元能购买多少股股票。在没有工具辅助的情况下,它会从训练数据中找出过时的报价,然后对错误的输入进行错误的分算。它没有内置“我不知道——请查询”的功能,因为查询并非一次简单的向前传播过程。
随着响应质量的提升,这些模型被证明适用于一次性推理任务。但仅靠规划仍无法实现自主性。定义智能体的关键问题包括:模型知识之外的是什么、何种行动能够获取这些知识、如何产生结果、如何调整计划以及何时停止。决策→行动→检查→重新规划构成一个循环,而非直线过程。正是这个循环催生了现代人工智能智能体。ReAct(推理+行动)模式为此奠定了基础。最初的演示并非LangChain应用——它实际上是由一个大型语言模型、结构化的提示语,以及执行动作并反馈观察结果的人类(或后来的脚本)共同构成的。
ReAct登场:推理与行动的结合
以下是一个逐步演示的实际案例:
from groq import Groq
import re
from dotenv import load_dotenv
_ = load_dotenv()
client = Groq()
message = client.chat.completions.create(
model="openai/gpt-oss-120b", # free, fast open-weight model hosted on Groq
max_tokens=1000,
messages=[
{"role": "user", "content": "Hello, GPT!"}
],
)
print(message.choices[0].message.content) # Check the client
class Agent:
def __init__(self, system=""):
self.system = system
self.messages = []
if self.system:
self.messages.append({"role": "system", "content": system})
def __call__(self, message):
self.messages.append({"role": "user", "content": message})
result = self.execute()
self.messages.append({"role": "assistant", "content": result})
return result
def execute(self):
response = client.chat.completions.create(
model="openai/gpt-oss-120b",
max_tokens=1000,
messages=self.messages,
).choices[0].message.content
return response
prompt = """
You run in a loop of Thought, Action, PAUSE, Observation.
At the end of the loop you output an Answer
Use Thought to describe your thoughts about the question you have been asked.
Use Action to run one of the actions available to you - then return PAUSE.
Observation will be the result of running those actions.
Your available actions are:
calculate:
e.g. calculate: 4 * 7 / 3
Runs a calculation and returns the number - uses Python so be sure to use floating point syntax if necessary
fish_weight:
e.g. fish_weight: Shark
returns weight of a fish when given the breed
Example session:
Question: How much does a shark weigh?
Thought: I should look the fish weight using fish_weight
Action: fish_weight: Shark
PAUSE
You will be called again with this:
Observation: A Great white shark weights 41000 lbs
You then output:
Answer: A Great white shark weights 41000 lbs
""".strip()
def calculate(expression):
return eval(expression)
def fish_weight(name):
if "Shark" in name:
return("Great white shark weighs 41000 lbs")
elif "Puffer" in name:
return("A puffer fish weighs 20 lbs")
else:
return("A fish can weight upto 47000 lbs")
known_actions = {
"calculate": calculate,
"fish_weight": fish_weight
}
abot = Agent(prompt)
result = abot("How much does a Shark weigh?")
print(result)
result = fish_weight("Shark")
result
next_prompt = "Observation: {}".format(result)
abot(next_prompt)
abot.messages # View the list of messages containing the conversation
# Present a compund query
abot = Agent(prompt)
# New query
question = """I have 2 fishes, a Shark and a puffer fish. \
What is their combined weight"""
abot(question)
next_prompt = "Observation: {}".format(fish_weight("Shark"))
print(next_prompt)
abot(next_prompt)
next_prompt = "Observation: {}".format(fish_weight("Puffer fish"))
print(next_prompt)
abot(next_prompt)
next_prompt = "Observation: {}".format(eval("41000 + 20"))
print(next_prompt)
abot(next_prompt)
## Add loop (automate the reasoning + act process)
action_re = re.compile('^Action: (\w+): (.*)