-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathReActmain.py
More file actions
113 lines (97 loc) · 4.4 KB
/
Copy pathReActmain.py
File metadata and controls
113 lines (97 loc) · 4.4 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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import re
from typing import Any, Optional
from ReAct.tool import ToolExecutor, search
from HelloAgentsLLM import HelloAgentsLLM
REACT_PROMPT_TEMPLATE = """
请注意,你是一个有能力调用外部工具的智能助手。
可用工具如下:
{tools}
请严格按照以下格式进行回应:
Thought: 你的思考过程,用于分析问题、拆解任务和规划下一步行动。
Action: 你决定采取的行动,必须是以下格式之一:
- {{tool_name}}[{{tool_input}}]:调用一个可用工具。
- Finish[最终答案]:当你认为已经获得最终答案时。
现在,请开始解决以下问题:
Question: {question}
History: {history}
"""
class ReActAgent:
def __init__(self, llm_client: Any, tool_executor: ToolExecutor, max_steps: int = 10):
self.llm_client = llm_client
self.tool_executor = tool_executor
self.max_steps = max_steps
self.history: list[str] = []
def run(self, question: str) -> Optional[str]:
"""运行 ReAct 智能体来回答一个问题。"""
self.history = []
current_step = 0
while current_step < self.max_steps:
current_step += 1
print(f"--- 第 {current_step} 步 ---")
# 1. 格式化提示词
tools_desc = self.tool_executor.get_available_tools()
history_str = "\n".join(self.history)
prompt = REACT_PROMPT_TEMPLATE.format(
tools=tools_desc,
question=question,
history=history_str,
)
# 2. 调用 LLM 进行思考
messages = [{"role": "user", "content": prompt}]
response_text = self.llm_client.think(messages=messages)
if not response_text:
print("错误: LLM 未能返回有效响应。")
break
# 3. 解析 LLM 的输出
thought, action = self._parse_output(response_text)
if thought:
print(f"思考: {thought}")
if not action:
print("警告: 未能解析出有效的 Action,流程终止。")
break
# 4. 执行 Action
if action.startswith("Finish"):
m = re.match(r"Finish\[(.*)\]", action)
final_answer = m.group(1) if m else action
print(f"🎉 最终答案: {final_answer}")
return final_answer
tool_name, tool_input = self._parse_action(action)
if not tool_name:
print("警告: Action 格式不正确,跳过本轮。")
continue
print(f"🎬 行动: {tool_name}[{tool_input}]")
tool_function = self.tool_executor.get_tool(tool_name)
if not tool_function:
observation = f"错误: 未找到名为 '{tool_name}' 的工具。"
else:
try:
observation = tool_function(tool_input)
except Exception as e:
observation = f"执行工具时发生错误: {e}"
print(f"👀 观察: {observation}")
self.history.append(f"Action: {action}")
self.history.append(f"Observation: {observation}")
else:
print("已达到最大步数,流程终止。")
return None
def _parse_output(self, text: str):
"""解析 LLM 的输出,提取 Thought 和 Action。"""
thought_match = re.search(r"Thought:\s*(.*?)(?=\nAction:|$)", text, re.DOTALL)
action_match = re.search(r"Action:\s*(.*?)$", text, re.DOTALL)
thought = thought_match.group(1).strip() if thought_match else None
action = action_match.group(1).strip() if action_match else None
return thought, action
def _parse_action(self, action_text: str):
"""解析 Action 字符串,提取工具名称和输入。"""
match = re.match(r"(\w+)\[(.*)\]", action_text, re.DOTALL)
if match:
return match.group(1), match.group(2)
return None, None
if __name__ == '__main__':
llm = HelloAgentsLLM()
tool_executor = ToolExecutor()
search_desc = "一个网页搜索引擎。当你需要回答关于时事、事实以及在你的知识库中找不到的信息时,应使用此工具。"
tool_executor.register_tool("Search", search_desc, search)
agent = ReActAgent(llm_client=llm, tool_executor=tool_executor)
question = "你能做什么?"
agent.run(question)