菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > AI创作与模型 > Function Calling两轮对话真相:MCP/Skills/A2A四层进化全景
模型技术

Function Calling两轮对话真相:MCP/Skills/A2A四层进化全景

2026-05-30
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

当大模型收到 "查询北京天气 "指令时,它真的会联网搜索吗? 并没有。它从未真正访问任何

当大模型收到"查询北京天气"指令时,它真的会联网搜索吗?

并没有。它从未真正访问任何天气预报数据源。

大模型的核心动作很简单——生成一张JSON格式的"工单",内容为{"city": "北京"},然后等待下游执行。外部结果返回后,它才据此组织回复,营造出"已查询天气"的表象。

这正是Function Calling(FC)的本质:LLM仅负责决定"调用哪个函数、传递什么参数",自身绝不执行实际操作。

亲手实现一次FC代码后,许多底层细节会瞬间清晰。沿着这条线索向前推演,从FC到MCP、Skills再到A2A,四个概念串起一条清晰的主线,揭示了AI工具系统如何从"单机模式"演化为"联邦协作"。

一、Function Calling的真相:两轮交互,LLM只下单不操作

用类比场景可以轻松理解FC的运行机制:

假设你在公司担任项目经理,既不会编码也不会硬件操作,但擅长拆解需求、判断该找谁执行。

  • 你接到的任务:"查询北京天气"
  • 你不会亲自去查——你输出一张工单:"调用get_weather函数,参数city='北京'"
  • 你的下属(代码层)拿着工单实际执行,返回结果"25°C 晴"
  • 下属将结果提交给你,你据此生成最终回复:"北京今天25度,晴天"

整个流程本质上是两轮对话

一个值得注意的能力——LLM可以同时下发多张工单。例如请求"查上海天气并计算25加17",模型会并行返回两个tool_call:一个调用get_weather,一个调用calculate。你的for循环依次执行,结果统一回传,LLM一次性整合输出。这种机制称为并行工具调用(Parallel Tool Calling)

二、手写代码验证:从工具定义到完成闭环

整个实现仅需60行代码即可构造完整的两轮对话。首先定义工具结构,这份定义就是提供给LLM的接口文档:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "查询指定城市的天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,如'北京'、'上海'"
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "执行数学计算,支持加减乘除",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,如'2+3'、'10*5'"
                    }
                },
                "required": ["expression"]
            }
        }
    }
]

自然不能缺少真正的函数实现:

def get_weather(city: str) -> str:
    """模拟天气查询"""
    weather_data = {
        "北京": "25°C,晴天,空气质量良",
        "上海": "28°C,多云,东南风3级",
        "深圳": "32°C,雷阵雨,湿度85%",
    }
    return weather_data.get(city, f"{city}:暂无天气数据")def calculate(expression: str) -> str:
    """安全计算数学表达式"""
    try:
        allowed = set("0123456789+-*/.() ")
        if not all(c in allowed for c in expression):
            return "错误:表达式包含非法字符"
        result = eval(expression)
        return str(result)
    except Exception as e:
        return f"计算错误:{e}"

接下来是核心逻辑——两轮对话的完整闭环:

def chat_with_tools(user_message: str):
    """完整的FC两轮对话"""
    # ===== 第1轮:用户提问 → LLM返回调用意图 =====
    response = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "user", "content": user_message}],
        tools=tools
    )
    
    message = response.choices[0].message
    
    # LLM不需要工具,直接回答
    if not message.tool_calls:
        print(f"LLM直接回答: {message.content}")
        return message.content
    
    # LLM决定调用工具——把意图消息加入对话历史
    messages = [
        {"role": "user", "content": user_message},
        message  # tool_calls消息原样保留
    ]
    
    # 逐个执行LLM要求的工具调用
    for tc in message.tool_calls:
        func_name = tc.function.name
        func_args = json.loads(tc.function.arguments)
        
        if func_name == "get_weather":
            result = get_weather(**func_args)
        elif func_name == "calculate":
            result = calculate(**func_args)
        else:
            result = f"未知函数: {func_name}"
        
        # 结果喂回——必须是tool message格式
        messages.append({
            "role": "tool",
            "tool_call_id": tc.id,  # 绑定到对应的调用ID
            "content": result
        })
    
    # ===== 第2轮:工具结果喂回去 → LLM生成最终回答 =====
    response2 = client.chat.completions.create(
        model=MODEL,
        messages=messages,
        tools=tools
    )
    
    return response2.choices[0].message.content

实测结果清晰直观,四种场景覆盖了所有典型用例:

场景1:天气查询(两轮对话)

用户: 北京今天天气怎么样?
   LLM决定调用: get_weather({'city': '北京'})
   执行结果: 25°C,晴天,空气质量良
   最终回答: 北京今天25°C,晴天,空气质量良,适合外出活动

场景2:数学计算(两轮对话)

用户: 帮我算一下123乘以456
   LLM决定调用: calculate({'expression': '123*456'})
   执行结果: 56088
   最终回答: 123乘以456的结果是56088

场景3:无需工具(直接回答)

用户: 给我讲个冷笑话
LLM直接回答: 为什么企鹅的肚子是白色的?因为企鹅的手太短了,洗澡只能搓到肚子前面 

场景4:并行工具调用(同时下发两张工单)

用户: 帮我查上海天气,再算25加17
   LLM决定调用: get_weather({'city': '上海'})
   执行结果: 28°C,多云,东南风3
   LLM决定调用: calculate({'expression': '25+17'})
   执行结果: 42
   最终回答: 上海28°C多云东南风3级,25+17=42

四个场景全部验证通过,FC的工作机制至此彻底清晰。

三、FC不够用?从单兵作战到团队协作的四层演进

FC存在一个致命缺陷:工具定义与你的应用代码硬绑定,切换项目必须重写一遍。换一个LLM应用,依然要重复同样的工作。

这就像你在自家有一套完整工具箱,到公司却要再买一套——每一个应用都是信息孤岛,开发效率被严重拖累。

沿此问题继续推演,整个AI工具体系经历了四层演进:

第一层:Function Calling——单兵作战

FC本质是LLM与工具之间的一次性合约。你写好tools定义,LLM按照定义发起调用请求。

明显局限:工具定义与应用深度耦合,换应用就得重写。如同你独自拥有一套工具箱,去哪都必须随身携带。

第二层:MCP——供应商入驻

MCP(Model Context Protocol)由Anthropic在2024年底推出,作为开放性标准。核心突破是工具与应用彻底解耦

MCP的架构分为三层:

  • Host:你的LLM应用(例如Claude Desktop、OpenClaw)
  • Client:协议转换层,将LLM的工具调用翻译为标准请求
  • Server:工具的提供方,自行描述"我有哪些工具、参数是什么"

关键演进点——Server自描述能力

FC(你替工具写简历):

  • 每个应用自行定义tools
  • 切换应用 → 重写
  • 工具本身没有话语权

MCP(工具自带简历):

  • Server主动声明自身能力
  • 所有Host自动发现并对接
  • 编写一次,随处可用

类比一下:FC相当于你去超市自行找货;MCP则像电商平台,供应商自主上架产品目录,所有买家自动可见。

MCP还提供三种能力:Tools(函数调用)、Resources(上下文数据)、Prompts(提示词模板)。本文聚焦Tools,其余两个了解即可。

传输层有两种模式:stdio(本地高效,进程间通信)和SSE(HTTP远程方案,Ja va天然擅长)。

第三层:Skills——开源社区插件

Skill并非单个函数,而是能力包。它包含指令(SKILL.md)、实现代码、领域知识,甚至支持Agent自我迭代优化。

与MCP Tool的本质差异:

维度MCP ToolAgent Skill直觉类比
定义单个函数能力包(指令+代码+知识)电钻 vs 木工师傅
粒度单次调用多步骤流程钻一下 vs 整个项目
智能度无状态,调用即结束有状态,能自主判断机器 vs 专家
迭代人工更新自进化(反思后改进)手册 vs 实战经验

身边就有真实案例——OpenClaw的Skill系统。你日常使用的feishu-calendar、feishu-task并非简单函数调用,它们内置SKILL.md(使用指南)、专用工具和错误处理策略。一个Skill能让任何Agent操作飞书日历,无需理解飞书API的细节。

第四层:A2A——联邦协作

A2A(Agent to Agent)是Google在2025年推出的协议。至此,Agent之间的关系不再是"人调用工具",而是对等协作

与前三层本质性区别:

维度FC / MCP / SkillsA2A
关系主人 → 工具同事 → 同事
决策单个(Host)决策多个Agent协商决策
通信单向(调用→返回)双向(委托+汇报+协商)
主体性工具无自主性每个Agent有目标与边界

类比:FC/MCP = 你单干偶尔点外卖;Skills = 你学了新技能不断变强;A2A = 你组建团队,每个人都有专长,互相委托任务。

Google A2A协议的核心三要素:

  • Agent Card(自描述卡片:"我是代码审查Agent,擅长Ja va审查")
  • Task委托("请审查这段代码")
  • 结果推送("审查完成,发现3个问题")

Ja va后端的直觉映射

作为Ja va开发者,这四层可以找到熟悉的对应关系:

概念Ja va对应理解桥梁一句话
FC反射 method.invoke()指定调用哪个方法、传递什么参数你编写调用规则
MCPSPI服务主动注册、自我描述供应商自行上架
SkillsSpring Boot Starter引入依赖即获得能力能力包,引入即用
A2A微服务 RPC/gRPC服务间相互调用团队间互相委托

四、总结:一条主线看清AI工具系统的演进方向

从FC到A2A,演进方向清晰明确:从被动工具走向自主协作

  • FC:LLM下单,你执行——最原始但最实用
  • MCP:工具自带文档,所有应用自动对接——解决复用难题
  • Skills:能力包超越函数,支持Agent自进化——解决智能问题
  • A2A:Agent之间对等协作——解决复杂任务问题

对于Ja va后端工程师,好消息是——MCP的SSE传输基于HTTP,Ja va天然适配;Spring AI已内置FC和MCP Client支持;Skills的概念与Spring Boot Starter完全一致,理解成本几乎为零。

简而言之,这四层演进正是Ja va生态走过的老路:从反射调用 → SPI插件机制 → Starter能力包 → 微服务RPC。换了层外衣,内核完全一致。

演进路线清晰可循,Ja va程序员完全有理由自信——当前AI最前沿的"智能体协作"机制,本质上是在重走Ja va生态早已验证过的路径。理解它,并不比掌握一个RPC框架更难。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多