学习AI Agent编程-第二天-LangGraph ReAct模式实现

简介: 本文介绍了LangChain中ReAct(推理-行动)模式的实践应用:通过“会议室申请”流程,演示LLM如何循环执行“决策→调用工具→评估结果→调整策略”,实现多步任务自动化。代码涵盖流程定义、工具函数与多轮会话测试,验证了其在空闲检查、报备审批、异常处理等场景的可靠性。(239字)

和DeepSeek聊了一天的技术,不断发散思维,收获不错。
但是剩下的时间已经不够学习更多的东西,所以只好草草学习了下LangGraph的基础 - ReAct模式

一、什么是ReAct模式

ReAct模式就是“决策、执行、评估结果、执行下一步”,即reasoning-action,简称ReAct。一个任务发给llm,llm先进行决策,然后决策执行第一步,执行完后再评估执行结果,然后再决定是否继续下一步,还是修复上一步的错误。
如下图所示:

c0ffb0596fa0254f3393db2bd8dba9d5.jpeg

二、ReAct在LangGraph中的实现

严格来说,是在LangChain中的实现,原本在LangGraph中的实现因版本原因被移进了LangChain包。

我们这一次让llm熟悉一个“会议室申请”的流程:

# 申请会议室流程
1. 查看指定时间会议室是否空闲
   * 如果空闲,执行下一步
   * 如果不空闲,则另找空闲时间
2. 向后勤经理和人事经理报备,获得报备号码
3. 提供以下信息,申请会议
    * 会议名称
    * 会议用途
    * 会议时间
    * 后勤经理和人事经理给的报备号码
4. 申请成功会反回申请号码,请妥善保存号码。

这里个流程涉及三个步骤,其中第一步和第三步的结果是一个逻辑分叉,这是一个很典型的适用于ReAct模式,即思考、执行、观察结果循环。

1. 基本代码和资源文件

我们要准备一些资源文件和基础代码,以供调用。
首先是流程规则文件,这个文件用于定义申请会议室的流程规则,用于prompt中,让llm去遵循。

# 申请会议室流程
1. 查看指定时间会议室是否空闲
   * 如果空闲,执行下一步
   * 如果不空闲,则另找空闲时间
2. 向后勤经理和人事经理报备,获得报备号码
3. 提供以下信息,申请会议
    * 会议名称
    * 会议用途
    * 会议时间
    * 后勤经理和人事经理给的报备号码
4. 申请成功会反回申请号码,请妥善保存号码。

然后就是两个功能函数:

def get_work_flow():
    """
    获得流程规则

    :return: 流程规则
    """
    with open('./work_flow.md', 'r') as f:
        return f.read()

def get_model():
    """
    获得模型客户端

    :return: 模型客户端
    """
    return ChatOpenAI(
        model=os.environ['OPENAI_MODEL_NAME'],
        temperature=0,
        extra_body={
   
            "enable_thinking": False,
            "thinking": {
   
                "type": "disabled"
            }
        }
    )

2. 添加工具函数,用于被llm调用

llm需要调用tool来获取他想要的额外信息或者进行相应的操作。所以我们需要实现这些tool。

这个开发过程一般都是慢慢调的,不同的llm的思维方式不同,有些要求很细,有些则要求很粗,所以尽可能跑多几个不同的模型来补上缺失的tool。

@tool
def check_meeting_room_free(date: datetime.datetime):
    """
    检查会议室是否空闲

    :param date: 会议时间
    :return: 空闲返回true,否则为false
    """
    print(f'checking meeting room free date: {date}')
    if str(date) == '2089-05-25 15:00:00':
        return False
    else:
        return True

@tool
def get_approver_name(position:str):
    """
    获取岗位负责人名字

    :param position: 岗位
    :return: 名字
    """
    if position == '后勤经理':
        return '刘四逼'
    elif position == '人事经理':
        return '脏三疯'
    else:
        return '路人ABC'

@tool
def request_approve(approver: str, date: datetime.datetime, reason: str):
    """
    向上级报备使用会议室

    :param approver: 批准人
    :param date: 会议时间
    :param reason: 使用原因
    :return: 报备号
    """
    print(f'{approver}: handle meeting request for date: {date} - {reason}')
    return str(uuid.uuid4())


@tool
def make_meeting_appointment(name, reason, date: datetime.datetime, codes: list[str]) -> tuple:
    """
    申请会议

    :param name: 名称
    :param reason: 用途
    :param date: 时间
    :param codes: 报备号
    :return: 结果,第一个值是"是否成功",如果成功,第二个值是"申请号码",否则则是“失败原因”
    """
    print(f'handling meeting request: {name} - {date} - {reason} - {codes}')
    if str(date.date()) == '2089-05-26':
        return False, '会议室灯光安排在当日维修,无法使用。'
    else:
        return True, str(uuid.uuid4())

3. 测试代码:

if __name__ == '__main__':
    load_dotenv()
    agent = create_agent(
        # 模型
        model=get_model(),
        # 工具
        tools=[check_meeting_room_free, request_approve, make_meeting_appointment, get_approver_name],
        # 流程规则 - prompt
        system_prompt=get_work_flow(),
        # 实现多轮会话
        checkpointer=MemorySaver(),
    )
    # 实现多轮会话
    config = RunnableConfig(configurable={
   "thread_id": "user_thread_1"})

    # 第一轮会话
    state = {
   
        "messages": [
            ("user", "我要申请下周三(2089年5月25日)下午3点整的会议室,名称是“批头会”,用途“批头大叫”")
        ]
    }
    response = agent.invoke(state, config=config)
    print(response['messages'][-1].content)

    # 第二轮会话
    state = {
   
        "messages": [
            ("user", "那就下周四上午9点。")
        ]
    }
    response = agent.invoke(state, config=config)
    print(response['messages'][-1].content)

    # 第三轮会话
    state = {
   
        "messages": [
            ("user", "那就下周二下午4点?")
        ]
    }
    response = agent.invoke(state, config=config)
    print(response['messages'][-1].content)

    # 第四轮会话
    state = {
   
        "messages": [
            ("user", "谢谢")
        ]
    }
    response = agent.invoke(state, config=config)
    print(response['messages'][-1].content)

这个测试代码共进行了四轮会话:

  1. 第一轮测试无空闲会议室的情况
  2. 第二轮测试有空闲会议室但是却申请不成功的情况
  3. 第三轮是正常通过的情况
  4. 第四轮是与流程无关的消息llm能不能正确处理。

输出日志分析:

# 第一轮,可以看到llm能正确调用tool,并且能正确评估tool结果
checking meeting room free date: 2089-05-25 15:00:00
下周三(2089年5月25日)下午3点整的会议室不空闲,请您另选一个时间再申请。

# 第二轮:可以看到llm能正确调用tool获得岗位主管的名字,并且正确被处理申请和返回申报号,而且最后能识别申请失败的原因,并以自然语言的方式回复。最重要的是,日期正确。
checking meeting room free date: 2089-05-26 09:00:00
刘四逼: handle meeting request for date: 2089-05-26 09:00:00 - 批头大叫
脏三疯: handle meeting request for date: 2089-05-26 09:00:00 - 批头大叫
handling meeting request: 批头会 - 2089-05-26 09:00:00 - 批头大叫 - ['d3558796-d523-4e01-acaa-5023dc85023d', 'e25791d2-a22d-46f9-9862-f4414e0075cc']
很抱歉,虽然下周四上午9点会议室时间空闲且已获得后勤经理和人事经理的报备号,但由于当日会议室灯光安排维修,无法使用。请您另选其他时间再申请。

# 第三轮:正常申请成功的流程。
checking meeting room free date: 2089-05-23 16:00:00
刘四逼: handle meeting request for date: 2089-05-23 16:00:00 - 批头大叫
脏三疯: handle meeting request for date: 2089-05-23 16:00:00 - 批头大叫
handling meeting request: 批头会 - 2089-05-23 16:00:00 - 批头大叫 - ['480fb94e-e142-4b0d-acfd-463c0fc843f5', '9e441bb8-e586-420b-9f44-2b11e1fa3a18']
会议室申请成功!您的申请号码为:2f03df27-2e34-4ad8-a99b-1b7dc3a606e3,请妥善保存。会议时间为下周二(2089年5月23日)下午4点整,名称“批头会”,用途“批头大叫”。

# 第四轮:llm能够正确区分非业务消息并正确客套回复。
不客气!祝您会议顺利,如有其他需要随时联系我。

三、总结

由测试结果可以得出,现在的llm能正确处理三步左右的问题,所以可以将子步骤交由ReAct模式去做。但是,为了正确性,一般顶层任务还是明确执行步骤为上。

目录
相关文章
|
4月前
|
人工智能 开发工具 开发者
学习AI Agent编程-第一天-MCP基础
本文精炼解析MCP(Model Context Protocol):它不是新模型,而是让AI Agent运行时动态增删工具的协议。通过MCP Server(工具实现)、Client(SDK封装)与Host(Agent应用)三组件协作,解决传统`bind_tools`静态绑定的局限。附完整可运行示例,助你快速掌握80%核心用法。(239字)
628 1
|
4月前
|
人工智能 机器人 Shell
【开源】龙虾人工智能 —— 完全本地化的机器人大脑!不联网、不付 API 费、能看能说能理解!
龙虾本地化AI(Lobster AI)是一款完全离线、零成本、零隐私泄露的开源机器人系统,支持文本推理(Gemma4)、多模态视觉理解(桌面/摄像头)、语音识别与合成(Sherpa-ONNX),纯本地运行,不依赖任何云服务。
708 2
【开源】龙虾人工智能 —— 完全本地化的机器人大脑!不联网、不付 API 费、能看能说能理解!
|
4月前
|
人工智能 定位技术 Go
从零搭建 Harness Engineering 框架 :Rule、Skill、Sub-Agent等工程落完整路径
Harness Engineering 是一套让AI在真实项目中稳定、可靠交付的工程系统,涵盖SPEC规范、Rule约束、Skill流程、Sub-Agent分工、Workflow编排、Script校验与MCP集成。它不追求模型更聪明,而是通过结构化机制消除随意性,实现可验证、可维护、可持续的AI协作开发。
1217 1
从零搭建 Harness Engineering 框架 :Rule、Skill、Sub-Agent等工程落完整路径
|
4月前
|
存储 人工智能 自然语言处理
大模型应用:从零构建医疗AI智能体:大模型驱动的医疗辅助系统全流程解析.125
本文系统阐述医疗AI智能体的落地实践:聚焦高敏感、高合规的医疗场景,提出“大模型+专业知识+安全规则”三位一体架构,涵盖需求规划、模型选型、RAG增强、幻觉抑制、五层技术架构及多模态交互设计,强调稳扎稳打、合规优先的工程化路径。
608 2
|
4月前
|
人工智能
AI工作流实践:如何降低内容运营中的接力成本?
AI工作流不替代人决策,而是打通内容运营全链路断点:需求沉淀、资料检索、初稿生成、审核留痕、发布记录、数据复盘。通过结构化任务+知识库+智能体协同,将反复查找、转述、遗漏的“接力成本”大幅降低,让人专注事实判断与质量把关。(239字)
|
1月前
|
人工智能 IDE 开发工具
Pi 突然火了:极简 Coding Agent 到底强在哪里?
本文导读 大多数 Coding Agent 都在继续增加模型、工具和连接器,Pi 却把默认能力压到很小,再由用户按需扩展。本文不按 Star 数下结论,而是分析这种极简设计换来了什么、付出了什么,以及它适合哪类使用者。 AI 编程工具正在走一条很熟悉的路。 模型要更多,工具要更多,MCP 要更多,A
Pi 突然火了:极简 Coding Agent 到底强在哪里?
|
1月前
|
JavaScript Shell API
一文吃透 Pi:10w stars 的极简 Agent harness
今年 AI 编程 Agent 领域卷得不行,Claude Code、Cursor、OpenCode、Codex CLI 都在疯狂堆功能,宠物、sub-agents、plan mode、MCP、扩展市场,恨不得把能想到的东西全塞进去。 不过有个项目却反其道而行之,它就是 Pi,一个主打极简的 Agent Harness。
615 0
|
4月前
|
人工智能 自然语言处理 监控
阿里云百炼千问Qwen3.7-Max全面解析:核心能力、技术特性与订阅使用全指南
在智能应用与AI智能体飞速发展的2026年,大模型的推理能力、长文本处理、多模态理解以及工具调用能力,已经成为企业开发、科研创作、自动化办公的核心刚需。阿里云百炼正式推出**Qwen3.7-Max**旗舰大模型,作为通义千问系列综合实力最强的版本,直接对标国际主流高端闭源大模型,专为复杂逻辑推理、长周期自主任务、多模态分析、企业级业务场景打造。
2169 3
|
6月前
|
人工智能 监控 Kubernetes
LoongCollector + ACS Agent Sandbox:构建 AI Agent 生产级运行平台
文章介绍了阿里云ACSAgentSandbox与LoongCollector协同构建的AIAgent生产级运行平台,通过沙箱隔离保障运行时安全,并以高性能、全链路可观测能力解决Agent行为不可预测和执行风险难题。
3340 96

热门文章

最新文章