• agent工作模式之ReAct实战


    前言

    本文主要描述agent开发中的ReAct模式,并且使用一个demo,彻底搞懂怎么在实际工作中使用ReAct模式

    话不多说,我们开始

    代码解析

    代码地址

    .
    ├── main.py
    └── data_sources.py
    
    • main.py:ReAct agent 主流程,负责让大模型思考、选择工具、接收观察结果
    • data_sources.py:工具层,负责模拟告警平台、nginx 日志、业务日志、prometheus 查询

    所谓 ReAct,就是:

    Reasoning + Acting
    
    先想一下 → 决定查什么 → 调工具查数据 → 根据结果继续想 → 最后给结论
    

    在代码里,它被明确约束成下面这个格式:

    Thought: 当前思考
    Action: 要调用哪个工具
    Observation: 工具返回结果
    Final Answer: 最终排查报告
    

    这就是典型的 ReAct 执行链路

    关键提示词

    约束模型的关键提示词:

    你必须严格按照以下格式输出:
    
    Thought: 你的思考过程,分析当前情况并决定下一步做什么
    Action: 要调用的工具和参数,例如:check_alarm_platform(service="order-service")
    Observation: (工具返回的结果,不需要你输出)
    
    或者,当你认为已经收集到足够信息时:
    
    Thought: 我已经收集到足够的信息,可以得出结论了
    Final Answer: 完整的故障排查报告,包括故障现象、根因定位、解决方案
    
    • 告诉模型的角色:线上故障排查专家
    • 告诉模型它有哪些工具可以用
    • 强制模型按 ReAct 格式输出

    这就是显式 ReAct 的特点,用 prompt 规范输出格式

    循环约束

    ReAct 模式天然是循环结构,如果没有最大轮次限制,模型一旦陷入“继续查询、继续分析、继续查询”的死循环,必须加上最大轮次的限制:max_rounds = 8

    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 内容,然后调用对应工具

    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 日志:

    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)
    

    业务日志:

    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

    工具执行完以后,代码会把结果打印出来,并继续塞回对话历史:

    print(f"Observation: {observation}\n")
    
    messages.append({"role": "assistant", "content": reply})
    messages.append({"role": "user", "content": f"Observation: {observation}"})
    

    这一步就是 ReAct 的闭环,模型上一轮说:

    Thought: 我应该先查一下告警平台
    Action: check_alarm_platform(service="order-service")
    

    程序执行工具获取数据后,把结果作为 Observation 回给模型:

    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 但是真正落地时,至少要注意下面这些点

    • 工具必须白名单化,不要让模型随便执行任意命令,模型只能从这几个工具里选:
      check_alarm_platform(service)
      nginx_log_query(status, path, limit)
      get_business_logs(service, keyword)
      
      • 当然还可以更加的精细化,当然这是工程化的项目了:
        • 工具白名单
        • 参数白名单
        • 只读工具优先
        • 高危动作必须人工确认
        • 所有调用要有审计日志
        • ...
    • observation 必须是真实反应线上状态。ReAct 的价值在于模型能基于 observation 继续推理。如果工具返回的数据本身就是错的、脏的、过期的,那 模型分析得再漂亮也没用
    • 敏感数据加密,这就不多解释了,非常重要。发给外部llm的数据必须经过脱敏、加密等步骤
    • 每一轮只能做一个 action,prompt 里有一个约束非常关键:
      每轮只输出一个 Thought + Action 或 Thought + Final Answer
      
    • 要限制最大轮次和成本
      max_rounds = 8
      
    • 低温度更适合排障
      temperature=0.1
      
    • 工具结果要控制长度,nginx_log_query 里有个参数:
      limit: int = 10
      
      这也是好习惯,不要把几万行日志直接塞给模型。更合理的做法是:
      • 先用程序侧过滤、聚合、排序
      • 把关键片段给模型
      • 让模型基于摘要做判断
      • 必要时再继续下钻
    • final answer 要包含证据链,prompt 里要求最终报告包含
      故障现象、根因定位、解决方案
      
      或者:
      1)故障现象
      2)影响范围
      3)关键证据
      4)根因判断
      5)临时止血方案
      6)长期修复建议
      7)不确定项 / 需要继续确认的点
      
    • 真实生产环境要加审计,如果 agent 真要接线上系统,建议每次运行都记录:

    总结

    这段代码是一个很典型的显式 ReAct demo:模型负责思考和选择工具,程序负责执行工具和回填 observation,最后由模型基于证据链生成排障报告

    真正使用 ReAct 时,基础的prompt是固定的,重要的是把工具边界、参数校验、最大轮次、成本控制、审计日志和证据链做好

    联系我

    • 联系我,做深入的交流

    至此,本文结束

    在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

  • 相关阅读:
    【LINUX】PS1 alias
    和数集团着重发力 区块链发展潜力再获认可
    网络安全防御体系建设-防守实例
    如何使用 Xcode 13+ 新的列断点(Column Breakpoints)让中断位置更加精确制导
    Markdown
    Oracle 创建表语句
    「Python条件结构」显示学号及提示信息
    explain 实战-----查看hive sql执行计划
    第十四章·享元模式
    【C++】继承 -- 详解
  • 原文地址:https://www.cnblogs.com/MrVolleyball/p/20182572