前言
本文主要描述agent开发中的ReAct模式,并且使用一个demo,彻底搞懂怎么在实际工作中使用ReAct模式
话不多说,我们开始
代码解析
css
.
├── main.py
└── data_sources.py
- main.py:ReAct agent 主流程,负责让大模型思考、选择工具、接收观察结果
- data_sources.py:工具层,负责模拟告警平台、nginx 日志、业务日志、prometheus 查询
所谓 ReAct,就是:
Reasoning + Acting
先想一下 → 决定查什么 → 调工具查数据 → 根据结果继续想 → 最后给结论
在代码里,它被明确约束成下面这个格式:
yaml
Thought: 当前思考
Action: 要调用哪个工具
Observation: 工具返回结果
Final Answer: 最终排查报告
这就是典型的 ReAct 执行链路
关键提示词
约束模型的关键提示词:
vbnet
你必须严格按照以下格式输出:
Thought: 你的思考过程,分析当前情况并决定下一步做什么
Action: 要调用的工具和参数,例如:check_alarm_platform(service="order-service")
Observation: (工具返回的结果,不需要你输出)
或者,当你认为已经收集到足够信息时:
Thought: 我已经收集到足够的信息,可以得出结论了
Final Answer: 完整的故障排查报告,包括故障现象、根因定位、解决方案
- 告诉模型的角色:线上故障排查专家
- 告诉模型它有哪些工具可以用
- 强制模型按 ReAct 格式输出
这就是显式 ReAct 的特点,用 prompt 规范输出格式
循环约束
ReAct 模式天然是循环结构,如果没有最大轮次限制,模型一旦陷入"继续查询、继续分析、继续查询"的死循环,必须加上最大轮次的限制:max_rounds = 8
ini
max_rounds = 8
round_count = 0
while round_count < max_rounds:
round_count += 1
print(f"--- [第 {round_count} 轮] ---")
response = client.chat.completions.create(
model=MODEL,
messages=messages,
temperature=0.1
)
action 解析与工具调用
当模型输出 action: 后,代码会解析 action 内容,然后调用对应工具
sql
if "check_alarm_platform" in action_part:
service = "order-service"
if 'service="' in action_part:
start = action_part.find('service="') + 9
end = action_part.find('"', start)
service = action_part[start:end]
observation = check_alarm_platform(service)
Nginx 日志:
lua
elif "nginx_log_query" in action_part:
status: str = ""
if 'status="' in action_part:
start = action_part.find('status="') + 8
end = action_part.find('"', start)
status = action_part[start:end]
observation = nginx_log_query(status=status)
业务日志:
ini
elif "get_business_logs" in action_part:
service = "order-service"
keyword = "error"
...
observation = get_business_logs(service=service, keyword=keyword)
ReAct 里 action 的落地点。模型不负责获取数据,它不能直接连数据库,不能直接 SSH 到机器,不能直接改配置。它应该先提出动作意图,然后由程 序层做白名单校验、参数解析、权限控制和工具调用,这部分可以后面改造到mcp中去
observation
工具执行完以后,代码会把结果打印出来,并继续塞回对话历史:
go
print(f"Observation: {observation}\n")
messages.append({"role": "assistant", "content": reply})
messages.append({"role": "user", "content": f"Observation: {observation}"})
这一步就是 ReAct 的闭环,模型上一轮说:
ini
Thought: 我应该先查一下告警平台
Action: check_alarm_platform(service="order-service")
程序执行工具获取数据后,把结果作为 Observation 回给模型:
ini
Observation: [CRITICAL] 订单服务 5xx 错误率过高...
下一轮模型就可以基于这个事实继续推理,不断循环,直至大模型已经得出排查完成,或者达到最大轮次
demo的执行链路
-
用户输入告警:订单服务接口超时,部分用户报错 504
-
main.py把告警信息发给大模型 -
大模型输出:
- Thought: 需要先查告警平台
- Action: check_alarm_platform(service="order-service")
-
程序解析 Action,调用 check_alarm_platform
-
工具返回 Observation:5xx 高、P99 高、实例数正常
-
大模型继续输出下一步 Action,例如查 Nginx 504 日志
-
程序调用 nginx_log_query(status="504")
-
工具返回大量 /api/orders 504 日志
-
大模型继续查业务日志
-
程序调用 get_business_logs(service="order-service", keyword="error")
-
工具返回 DB timeout、连接池满、SQL 查询超时
-
大模型输出 Final Answer:根因、影响面、处理建议
ReAct 注意事项
ReAct 本质就是 Thought / Action / Observation 但是真正落地时,至少要注意下面这些点
-
工具必须白名单化,不要让模型随便执行任意命令,模型只能从这几个工具里选:
scsscheck_alarm_platform(service) nginx_log_query(status, path, limit) get_business_logs(service, keyword)-
当然还可以更加的精细化,当然这是工程化的项目了:
- 工具白名单
- 参数白名单
- 只读工具优先
- 高危动作必须人工确认
- 所有调用要有审计日志
- ...
-
-
observation 必须是真实反应线上状态。ReAct 的价值在于模型能基于 observation 继续推理。如果工具返回的数据本身就是错的、脏的、过期的,那 模型分析得再漂亮也没用
-
敏感数据加密,这就不多解释了,非常重要。发给外部llm的数据必须经过脱敏、加密等步骤
-
每一轮只能做一个 action,prompt 里有一个约束非常关键:
sql每轮只输出一个 Thought + Action 或 Thought + Final Answer -
要限制最大轮次和成本
inimax_rounds = 8 -
低温度更适合排障
initemperature=0.1 -
工具结果要控制长度,
nginx_log_query里有个参数:inilimit: int = 10这也是好习惯,不要把几万行日志直接塞给模型。更合理的做法是:
- 先用程序侧过滤、聚合、排序
- 把关键片段给模型
- 让模型基于摘要做判断
- 必要时再继续下钻
-
final answer 要包含证据链,prompt 里要求最终报告包含
故障现象、根因定位、解决方案或者:
1)故障现象 2)影响范围 3)关键证据 4)根因判断 5)临时止血方案 6)长期修复建议 7)不确定项 / 需要继续确认的点 -
真实生产环境要加审计,如果 agent 真要接线上系统,建议每次运行都记录:
总结
真正使用 ReAct 时,基础的prompt是固定的,重要的是把工具边界、参数校验、最大轮次、成本控制、审计日志和证据链做好