-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpattern.py
More file actions
47 lines (34 loc) · 1.56 KB
/
Copy pathpattern.py
File metadata and controls
47 lines (34 loc) · 1.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""ReAct — Reason + Act tool loop.
[agent] --THOUGHT--> --ACTION--> [tool] --OBSERVATION--> [agent] ... --FINAL-->
The single most important *single-agent* pattern. The agent interleaves
reasoning with tool calls: it thinks, picks a tool, reads the observation,
and repeats until it can answer. This is the loop underneath almost every
"agent" you've used.
"""
from __future__ import annotations
from core import Message, Role, default_tools, get_llm, get_tracer, parse_action
def run(question: str, max_steps: int = 5) -> str:
llm = get_llm()
tracer = get_tracer()
tools = default_tools()
system = (
"You are a ReAct agent. Work in steps. "
"To use a tool, reply exactly: 'ACTION: <tool> :: <input>'. "
"When you can answer, reply: 'FINAL: <answer>'. "
f"Available tools: {tools.describe()}. [[PROTOCOL:react]]"
)
history = [Message(Role.SYSTEM, system), Message(Role.USER, question)]
for _ in range(max_steps):
reply = llm.chat(history)
tracer.event("react-agent", reply)
history.append(Message(Role.ASSISTANT, reply))
if "FINAL:" in reply:
return reply.split("FINAL:", 1)[1].strip()
if "ACTION:" in reply:
tool, arg = parse_action(reply)
observation = tools.run(tool, arg)
tracer.event(f"tool:{tool}", observation, kind="note")
history.append(Message(Role.TOOL, observation, name=tool))
return "No final answer (reached max steps)."
if __name__ == "__main__":
print("\nFINAL:\n", run("What is 23 * 47 + 19?"))