当前位置: 首页 > article >正文

五、AIGC大模型_09手动实现ReAct_Agent

0、前言

在上一章节中,我们了解到:create_react_agent 是 LangGraph 提供的一个预构建方法(from langgraph.prebuilt import create_react_agent),它可以将语言模型(LLM)和一组工具(Tools)结合起来,创建一个能够根据用户输入自动调用工具的智能代理,这个代理可以根据用户的请求,决定是否需要调用某个工具,并将工具的输出反馈给用户

这个函数如此好用,那么,其实现原理是什么,我们能否自定义方法实现ReAct_Agent呢?

本文基于此问题,介绍如何参考LangGraph的知识体系来手动实现ReAct_Agent

1、LangGraph基本介绍

1.1 定义

LangGraph 是一种基于图结构(Graph)的工作流构建工具,它通过定义节点(Node)、边(Edge)和状态(State)来实现复杂任务的自动化和流程化,这种工具通常用于构建智能代理(Agent)、自动化工作流或复杂任务的调度系统

官网:Home

1.2 相关概念

1.2.1 节点(Node)

节点是工作流中的基本单元,每个节点代表一个具体的动作或操作,节点可以分为以下几种类型:

(1)Tool 节点

  • 功能:调用外部工具或函数
  • 示例
    • 调用一个 API 获取天气信息
    • 调用数据库查询函数

(2)Model 节点

  • 功能:调用预训练的模型(如语言模型、图像识别模型等)
  • 示例
    • 使用 GPT 模型生成文本
    • 使用 YOLO 模型进行目标检测

(3)其他节点

  • 除了上述两种常见节点,还可以根据需求定义其他类型的节点,例如:
    • 条件节点:用于判断逻辑
    • 循环节点:用于重复执行某个操作
    • 输入/输出节点:用于接收用户输入或输出结果

1.2.2 边(Edge)

边是连接节点的纽带,用于表示节点之间的状态转移,边可以分为以下两种类型:

(1)固定边

  • 功能:无论条件如何,始终从一个节点流向另一个节点
  • 示例:从“获取用户输入”节点直接流向“调用模型”节点

(2)条件边

  • 功能:根据特定条件决定是否从一个节点流向另一个节点
  • 示例:如果模型的输出满足某个条件(如置信度大于 0.8),则流向“成功处理”节点;否则流向“错误处理”节点

1.2.3 状态(State)

状态是节点执行过程中存储的信息,通常用于保存中间结果或上下文信息,最常见的状态类型是 Message State,它用于存储消息或数据

  • 示例
    • 在一个对话系统中,Message State 可能存储用户的输入文本、模型的输出文本等
    • 在一个数据处理流程中,Message State 可能存储中间计算结果

1.3 LangGraph构建工作流

基于 LangGraph 构建工作流的过程可以分为以下步骤:

Step1:定义节点:根据任务需求,定义需要执行的动作,并将其封装为节点(如 Tool 节点或 Model 节点)

Step2:连接节点:使用边将节点连接起来,定义节点之间的执行顺序和条件。

Step3:配置状态:在每个节点中配置状态,确保信息可以在节点之间正确传递。

Step4:测试与优化

  • 对工作流进行测试,确保所有节点和边的逻辑正确无误
  • 根据测试结果优化工作流,调整节点和边的配置

这种基于 LangGraph 的工作流构建方式可以应用于多种场景,例如:

  • 智能客服系统:通过定义不同类型的节点(如调用语言模型、调用数据库查询工具)和条件边,实现自动化的问答流程
  • 自动化数据处理:通过定义工具节点和模型节点,实现数据的采集、清洗、分析和输出
  • 复杂任务调度:通过定义循环节点和条件节点,实现复杂任务的自动化调度

2、使用LangGraph手动实现ReAct_Agent

2.1 构建

# 类型 限制
from typing import Annotated, Literal, TypedDict
# 人类消息
from langchain_core.messages import HumanMessage
# 当做装饰器使用,把一个普通的函数变成一个agent可以调用的工具
from langchain_core.tools import tool
# 消息持久化
from langgraph.checkpoint.memory import MemorySaver
# 引入预定义的一些类或工具
from langgraph.graph import END, START, StateGraph, MessagesState
# 引入一个预编译的工具节点
from langgraph.prebuilt import ToolNode
# 引入一个 datetime
from datetime import datetime

"""
    定义获取模型实例的方法(注意DASHSCOPE_API_KEY的环境变量值)
"""
from dotenv import load_dotenv
load_dotenv()

from langchain_community.chat_models import ChatTongyi

def get_chat():
    return ChatTongyi(model="qwen-turbo", temperature=0.1)


"""
    定义外部工具
"""
@tool
def get_current_datetime() -> str:
    """
        查询当前的日期和时间
    """ 
    now = datetime.now()
    formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")
    return formatted_date

@tool
def get_apple_price(model: str) -> int:
    """
        查询苹果手机的价格!
        入参:model 是苹果手机的型号,目前,只有如下3个型号 '4s'、'5s'、'6s',其它型号暂不支持
    """ 
    if model == "4s":
        return 4000
    elif model == "5s":
        return 5000
    elif model == "6s":
        return 6000
    else:
        raise ValueError("model 是苹果手机的型号,目前,只有如下3个型号 '4s'、'5s'、'6s',其它型号暂不支持")


"""
    根据外部方法构建工具节点
"""
call_datetime = ToolNode(tools=[get_current_datetime], name="datetime")
call_apple_price = ToolNode(tools=[get_apple_price], name="apple_price")

# 连接大模型
model = get_chat()
# 绑定工具节点
model_with_tools = model.bind_tools(tools=[get_apple_price, get_current_datetime])

"""
    定义一个条件边
"""
def should_continue(state: MessagesState) -> Literal["datetime", "apple_price", END]:
    # 获取当前的消息
    messages = state['messages']
    # 取出最后一条消息
    last_message = messages[-1]
    # 如果大模型发出工具调用请求,我们就转向 工具节点
    # print(last_message)
    if not last_message.tool_calls:
        return END
    elif last_message.tool_calls[0]["name"] == "get_current_datetime":
        return "datetime"
    else: 
        return "apple_price"

"""
    定义调用模型的函数
"""
def call_model(state: MessagesState):
    # 取出消息列表(所有的历史对话)
    messages = state['messages']
    # 调用大模型
    response = model_with_tools.invoke(messages)
    # 只需要通过列表形式返回当前这一步的消息即可
    # 系统会自动把当前这一步的消息追加到 系统状态中
    return {"messages": [response]}

"""
    搭建工作流
"""
# 定义一个新的图
workflow = StateGraph(MessagesState)
# 添加一个大模型节点
workflow.add_node(node="model", action=call_model)
# 添加一个查询日期和时间的节点
workflow.add_node(node="datetime", action=call_datetime)
# 添加一个查询苹果手机价格节点
workflow.add_node(node="apple_price", action=call_apple_price)
# 添加一条边
workflow.add_edge(start_key=START, end_key="model")
# 添加一个条件边
workflow.add_conditional_edges(source="model", path=should_continue)
# 工具掉完,都转向大模型
workflow.add_edge(start_key="datetime", end_key='model')
workflow.add_edge(start_key="apple_price", end_key='model')
# 消息持久化
checkpointer = MemorySaver()
# 编译整个图
agent = workflow.compile(checkpointer=checkpointer)

2.2 画图

"""
    图形可视化
"""
from IPython.display import Image, display

try:
    display(Image(agent.get_graph().draw_mermaid_png()))
except Exception:
    print(f"无法显示图形:{e}")

2.3 调用

"""
    调用agent
"""
final_state = agent.invoke(input={"messages": [HumanMessage(content="新中国成立多少年,我就买多少部5s,请问我该准备多少钱?")]},
                           config={"configurable": {"thread_id": 42}})
# 只打印最后一条消息
print("--------只打印最后一条消息--------")
final_message = final_state["messages"][-1].content
print(final_message)

# 打印所有消息
print("--------打印所有消息--------")
for msg in final_state["messages"]:
    msg.pretty_print()

3、补充知识

multi-agent-collaboration和plan-and-execute是Agent的两种主流设计思想

  • multi-agent-collaboration官网:Multi-agent network

  • plan-and-execute官网:Plan-and-Execute

3.1 Multi-Agent Collaboration(多智能体协作)

多智能体协作是指多个智能体(如基于大语言模型的智能体)通过分工、协调和合作来共同完成复杂任务,其核心在于通过智能体之间的交互、知识共享和任务分配,实现比单个智能体更高效、更强大的功能

3.1.1 特点

  • 分工合作:复杂任务被分解为多个子任务,每个智能体根据自身专长处理特定子任务

  • 灵活性与可扩展性:可以根据任务需求动态调整智能体的数量和角色

  • 鲁棒性:即使部分智能体失效,系统仍能继续运行

3.1.2 应用场景

  • 复杂任务处理:如在模拟环境中完成多步骤任务
  • 知识共享:多个智能体共同维护和共享知识库
  • 实时交互:适用于需要快速响应的场景,如灾难救援和交通优化

3.2 Plan-and-Execute(计划与执行)

Plan-and-Execute 是一种将任务分解为计划阶段和执行阶段的方法,系统首先制定详细的计划,然后逐步执行每个计划步骤,并在必要时进行重新规划

3.2.1 工作流程

  • 计划阶段:系统根据输入生成一个任务计划,将复杂任务分解为多个步骤

  • 执行阶段:按照计划逐步执行每个步骤,并记录执行结果

  • 重新规划:如果执行过程中出现问题或任务未完成,系统会根据当前状态重新规划

3.2.2 prompt

{instructions}

You have access to the following tools:

{tools}

To use a tool, please use the following format:

        Thought: Do I need to use a tool? Yes
        Action: the action to take, should be one of [{tool_names}]
        Action Input: the input to the action
        Observation: the result of the action

When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:

        Thought: Do I need to use a tool? No
        Final Answer: [your response here]

Do not attach backticks to any of your outputs, including thoughts, tool calls and final answers.

Begin!

New input: {input}

{agent_scratchpad} 

3.2.3 特点

  • 结构化流程:通过明确的计划和执行步骤,提高任务处理的清晰度和效率
  • 动态调整:能够根据执行结果动态调整计划
  • 可扩展性:适用于多领域任务,支持复杂问题的逐步解决

3.2.4 应用场景

  • 问答系统:通过计划和执行步骤逐步解决问题
  • 复杂任务自动化:如在多步骤任务中,通过动态规划和执行提高效率

3.3 两者的区别与联系

  • 区别

    • 多智能体协作侧重于智能体之间的分工与合作,强调通过多个智能体的协同完成任务
    • 计划与执行侧重于任务的分解和逐步执行,更注重任务处理的结构化和动态调整
  • 联系

    • 两者都可以用于解决复杂任务,且在实际应用中可以结合使用(例如,多智能体系统可以通过计划与执行框架来协调智能体的行动)

http://www.kler.cn/a/592224.html

相关文章:

  • linux /bin/bash丢失修复
  • Mac:Maven 下载+安装+环境配置(详细讲解)
  • 动态规划合集——动态规划基本原理
  • 蓝桥杯 - 中等 - 新手引导
  • React初学分享 事件绑定 组价通信 useState useEffect
  • Django 中@login_required 配置详解
  • 【深度学习】多目标融合算法(五):定制门控网络CGC(Customized Gate Control)
  • OpenBMC:BmcWeb添加路由4 设置method
  • MySQL 进阶学习文档
  • gralloc1_perform具体在干什么
  • 大语言模型的多垂类快速评估与 A/B 测试
  • 云原生服务网格:微服务通讯的量子纠缠革命
  • 【实用部署教程】olmOCR智能PDF文本提取系统:从安装到可视化界面实现
  • 计算机网络——总结
  • 分布式的消息流平台之Pulsar
  • 阿里云平台服务器操作以及发布静态项目
  • VBA常见的知识都有哪些,让AI编写的VBA经常 报错,所以VBA的基础还是要学习的
  • 西门子PLC
  • 88页手册上线 | 企业级本地私有化DeepSeek实战指南
  • 个人学习编程(3-19) leetcode刷题