从workflow到ReAct提升Agent智能化水平

AI Agent(智能体)是一种‌具备自主决策与执行能力‌的智能实体,能够通过感知环境、动态调整行为以实现预设目标。其本质是通过融合大语言模型(LLM)的推理能力和工具调用机制,将传统AI的被动响应升级为主动任务执行能力。

Agent这个标准定义,是包含了感知环境-思考决策-行动执行的闭环逻辑,也就是要符合ReAct框架(Reasoning+Action),以下说明workflow模式与ReAct框架Agent实现逻辑的不同。

使用workflow模式的Agent

我们先分析之前运维案例中的workflow,它们执行步骤和逻辑是在workflow中预设好的:

img

这不由得让人反思我们这类智能体的“智能”体现在哪里呢?答案是这些Agent中不仅仅有workflow,更关键是其中用到的LLM。

比如在这个运维案例中,是利用LLM的文字生成和整合能力,输出故障的最终解决方案,虽然前序知识检索环节有可能检索到故障对应的答案,但这些答案往往比较简略,还需要LLM根据Prompt指令“按【原因分析】、【影响范围】、【处置建议】结构化输出”,并且指定如果当前序环节没有检索到答案时,还需要LLM能自行分析并生成解决办法。

img

我们再看看笔者之前另外一个[中考小助手案例]中,利用的是LLM进行语义理解和意图识别,要区分用户输入的问题是在问某个学校的分数线,还是在问某个分数能上什么学校,还是其他问题等,然后在workflow中才能根据不同的意图,走不同分支的处理逻辑。

img

所以在我们大多数场景中,用workflow这种模式,再结合LLM的语义理解、意图识别、文字生成和整合能力就能够实现一个较好的Agent。

使用Function Call实现ReAct框架

以上workflow模式的Agent核心是执行逻辑是可预设的,但有些业务场景中业务执行逻辑是不确定的,是要依据前序环节的执行结果,动态决策下一步该怎么做,也就是对应ReAct框架的思考-行动-观察的闭环,如下图所示(源图来自https://react-lm.github.io/):

img

这个图很好地说明了右边ReAct框架相比原有模式的区别,每次要观察observe上一次行动action的结果,也就是将上次调用结果作为输入,再输入给LLM,一起去思考下一步该如何action。

ReAct框架‌(Reasoning + Acting)是一种结合推理与行动的多步骤高阶任务执行范式,而上图中LLM与外部工具/环境ENV交互action的‌基础能力‌,就是依靠Function Call作为底层支撑技术。

Function Call‌是大型语言模型(LLM)通过‌语义理解与结构化输出‌调用外部工具的核心能力,其实现依赖以下关键环节:

img

如图所示整个过程包括:定义函数,生成函数描述Schema,将用户输入和函数描述一起输入调用LLM,解析LLM的输出,如果有输出函数名和参数则执行该函数,再将函数结果反馈给LLM,实现下一轮调用,直至输出最终结果。

这个过程中,大家经常说的通过function call让LLM具备了调用外部工具的能力实际只是一种形象化的表达,真正函数调用或者说工具执行,还是在agent的代码里去实现的,这里LLM‌的作用主要是两点(也就是图中红色块内容):

动态决策‌:根据上下文判断是否需要调用函数(例如回答天气查询时要反馈get_weather()函数)‌。

输出接口:通过JSON等格式输出函数名和对应参数,确保外部工具的可执行性‌。

为了更直观地理解这个过程,我让LLM生成一段Python样例代码,如下:

import openai
import json
from typing import get_type_hints
# 示例函数定义
def get_current_weather(location: str, unit: str = "celsius") -> str:
    """获取指定地区的当前天气情况"""
    # 这里模拟天气数据
    weather_data = {
        "beijing": {"celsius": 22, "fahrenheit": 72},
        "new york": {"celsius": 18, "fahrenheit": 64}
    }
    returnf"{location}天气:{weather_data.get(location.lower(), {}).get(unit, '未知')}°{unit}"
def calculate(expression: str) -> float:
    """执行数学计算(支持加减乘除)"""
    try:
        returneval(expression.replace("^", "**"))
    except:
        return"计算错误"
# 生成函数描述JSON Schema
def generate_function_schema(func):
    hints = get_type_hints(func)
    doc = func.__doc__.split("\n") if func.__doc__ else""
    
    return {
        "name": func.__name__,
        "description": doc,
        "parameters": {
            "type": "object",
            "properties": {
                param: {
                    "type": "string"if hints.get(param) == strelse"number",
                    "description": f"{param}参数"
                } for param inlist(hints.keys())[:-1]  # 排除返回类型
            },
            "required": list(get_type_hints(func).keys())[:-1]
        }
    }
# 可用函数列表
available_functions = {
    "get_current_weather": get_current_weather,
    "calculate": calculate
}
# 生成函数描述列表
functions = [generate_function_schema(func) for func in available_functions.values()]
# 与LLM交互的核心函数
def run_conversation(user_query: str):
    # 第一次LLM调用(选择函数)
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-0613",  # 要选择支持函数调用的模型
        messages=[{"role": "user", "content": user_query}],
        functions=functions,   # 输入函数定义
        function_call="auto"
    )
    
    response_message = response["choices"]["message"]
    
    # 如果LLM选择调用函数,就会在输出response_message中,把要调用的函数和对应参数都输出
    if response_message.get("function_call"):
        function_name = response_message["function_call"]["name"]
        function_args = json.loads(response_message["function_call"]["arguments"])
        
        print(f"LLM选择调用函数: {function_name}")
        print(f"参数: {function_args}")
        
        # 执行对应函数
        if function_name in available_functions:
            function_to_call = available_functions[function_name]
            
            # 参数类型转换
            try:
                args = {k: str(v) for k,v in function_args.items()}  # 统一转为字符串
                if function_name == "calculate":
                    args["expression"] = args["expression"].replace(" ", "")
                # 敲黑板 注意:实际执行函数还是本地代码,并不是LLM直接去调用哈 
                result = function_to_call(**args)  
                returnf"执行结果: {result}"
            except Exception as e:
                returnf"执行错误: {str(e)}"
        else:
            return"未知函数调用"
    else:
        return"未触发函数调用"
# 测试用例
if __name__ == "__main__":
    test_cases = [
        "北京现在的气温是多少?",
        "帮我计算(3 + 5) * 2^3的值",
        "今天纽约的天气怎么样?用华氏度"
    ]
    
    for query in test_cases:
        print(f"\n用户问:{query}")
        print("->", run_conversation(query))
  1. 很多同学用Coze和元器来配置Agent时,可以直接写提示词来说明Agent的处理流程,可以指定插件挂载工具,有同学就问这种算什么模式?我们修改下之前那个中考小助手案例,这次我们不去配置工作流,而是按如下配置:

    img

如果Prompt中把执行步骤描述得很清楚,就应该算是workflow模式,无非它是用文字来表达执行逻辑,同时利用LLM的function call能力,根据预定的执行逻辑调用预设好的插件。

但如果Prompt只是描述目标,没有对执行步骤做详细描述,那应该可以说是ReAct模式,它通过右边的插件设置,将所有可以调用的工具/函数都提前注册进来,运行时和Prompt一起输入给LLM,由LLM自行规划处理路径,中间何时要调用外部插件,都是LLM自行决策的。

无论怎么理解,只能说Coze的这个智能体已经很智能了。

从Function Call到MCP

搞清楚ReAct框架和Function Call的关系以后,我们再看看MCP(Model Context Protocol)大模型上下文协议,去年Anthropic推出的MCP概念,今年以来热度持续上升,尤其是OpenAI也宣布支持MCP以后,似乎一页之间万能手、通用agent等概念都有了落脚点。官网对MCP架构的介绍可以参考这个链接,主要架构图如下(https://modelcontextprotocol.io/introduction):

img

mcp和function call本质上没有太大区别,只是把函数调用的规范做了统一,按统一规范由mcp client发给远程某个MCP Server再执行具体tool。为了更直观地对比在ReAct框架中MCP和function call区别,我们画个图来表示,如下:

img

要实现mcp这种方式的工具调用,首先也是需要将函数/工具的描述信息schema先要输入给LLM,只不过functioncall是在本地生成函数描述的,而mcp则是远程从mcp server中自动拉取的工具描述,远程mcp server端有哪些工具的描述,是基于server端工具在开发时用注解的方式描述函数名、用途和参数信息来自动生成的。

和上文介绍的function call机制一样,LLM本身也不会真的去调用mcp server里的工具,LLM是个语言模型,它的输入输出永远是一段文本,它只是识别需要调用哪个工具,并将要调用的工具名、参数以json格式结构化文本输出,然后是由LLM所在的Host去调用。

这个Host有一个误区,网上看到的各种mcp文章,都是用Claude desktop、cursor或者dify、cherry studio这种工具来举例,很容易让人和mcp client这个概念混淆起来,实际这个host更常见的是Agent所在的代码,是通过在这个代码中引入mcp client包去发给远程mcp server去执行的。

图片

以上就是AI Agent从workflow固化流程到基于Function Call的ReAct框架,再从Function Call到统一标准的MCP的一个发展过程,但AI领域生态发展是飞速向前的。

4.10日Google又发布了开源协议A2A(Agent-to-Agent),使得基于不同底层框架和供应商平台创建的 AI Agent 之间能够实现相互通信,实现多智能体之间的协作,也是Agent这个领域的最近最为火热的发展方向,但本质上如果你将MCP Server后面对接另外一个Agent,实际也能实现多智能体的协作,笔者推测A2A可能也就是对Host Agent中LLM通过mcp client调用mcp server端的另一个Agent的过程做了一个简化封装,当然有待后续实践后再进行详细分享。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值