理解函数调用Function Call

为什么我们需要 Function Call? (背景与痛点)

RAG 的局限性:

  • 只能"查"不能"做": 传统 RAG 的工作流是 用户提问 -> 向量检索 -> 生成答案。它只能回答"知识库里有什么"(静态知识)。

  • 无法处理实时/业务数据: 面对"我还剩几天年假?"、"订单 #12345 到哪了?"或"帮我提交报销"这类需求,RAG 无能为力,因为这些数据不在向量数据库中,而是在业务系统的数据库或 API 里。

传统解决方案的弊端:

  • 在 Prompt 里写死规则或兜底回复。

  • 用硬编码的规则匹配意图(如正则匹配),然后调用接口。

  • 后果: 规则写不完,维护成本极高。每增加一个新功能(如查考勤),都要修改代码、加规则、重新部署。


Function Call 的核心概念

定义:

Function Call 是一种让大模型从"只会说话"进化到"能干活"的机制。

  • 核心思想: 将"判断何时调用工具"的逻辑交给模型,将"具体执行工具"的逻辑留给代码。

工作流程(6步闭环):

  1. 定义工具: 开发者定义工具列表(名称、描述、参数 Schema)。

  2. 用户提问: 将用户问题和工具列表一起发给模型。

  3. 模型决策: 模型判断需要调用哪个工具,输出一个 JSON 格式(tool_calls),包含函数名和参数。

  4. 执行代码: 本地程序解析 JSON,执行对应的函数(查库、调接口)。

  5. 返回结果: 将函数执行的结果(如 {"remaining": 5})返回给模型。

  6. 生成回答: 模型结合工具返回的数据,生成最终的自然语言回答。


技术实现:OpenAI 协议详解

目前主流模型(包括 Qwen)都遵循类似的协议标准。

A. 工具定义 (Tools Definition)

我们需要告诉模型有哪些"武器"可用。通常是一个 JSON 数组,包含函数名、描述和参数定义(JSON Schema)。

示例:定义一个查询年假的工具 getUserAnnualLeave ,需要参数 userId

B. 交互协议 (Request & Response)

  • 第一轮请求 (User -> Model):

    • 发送用户问题 + tools 参数 + tool_choice="auto"(让模型自己决定)。
  • 第一轮响应 (Model -> User):

    • 模型不直接回答,而是返回 finish_reason: "tool_calls"

    • 消息体中包含 tool_calls 数组,里面有 id(调用ID)、name(函数名)和 arguments(参数 JSON)。

  • 第二轮请求 (User -> Model):

    • 关键点: 需要把完整的对话历史发回去。

    • 新增一条 role: "tool" 的消息,包含 tool_call_id(对应第一轮的ID)和 content(函数执行的实际结果)。

  • 第二轮响应 (Model -> User):

    • 模型看到工具返回的结果(例如:剩余5天),生成最终回复:"您还剩 5 天年假。"

Function Call 在 RAG 系统中的应用

意图识别:查知识库 vs 调工具

核心思想

将"知识库检索"与"业务工具调用"统一抽象为工具,利用大模型的意图识别能力作为智能路由器,根据用户问题的性质动态选择执行路径,从而实现从"被动问答"到"主动服务"的架构升级。

演进对比

  • 传统 RAG 模式(单一技能):无论用户提问何种类型,系统强制执行知识库检索。这种方式缺乏灵活性,无法处理实时数据或特定业务逻辑,容易导致模型在面对非文档类问题时产生幻觉。

  • 工具化架构模式(智能调度):将"搜索知识库"视为一个工具,将"查询业务系统"视为另一个工具。大模型不再直接生成答案,而是先分析用户意图,判断该问题属于"静态知识查询"还是"动态业务操作",进而自动路由至相应的工具。

Function Call 的局限性与痛点

虽然 Function Call 很强,但目前落地还有坑:

  • 维护成本: 工具定义(Schema)多了以后,管理很麻烦。

  • 集成复杂度: 跨语言、跨系统的调用链路调试困难。

  • 安全性: 权限控制(谁能调什么接口)需要自己在代码层实现,模型本身不管这个。

  • 可观测性: 链路变长了(用户->模型->代码->模型->用户),排查问题不如传统代码直观。

相关推荐
Zella折耳根14 分钟前
复习篇-常用实用类
java
devilnumber6 小时前
Java 递归算法 详解 + 核心要点 + 实战运用 + 避坑指南
java·开发语言·算法
杨浦老苏7 小时前
家庭实验室监控仪表盘HomeLab-Monitor
运维·docker·监控·群晖
回忆2012初秋7 小时前
【Nginx】原理、配置与运维实战(2)
运维·nginx·策略模式
asdfg12589637 小时前
JavaBean是什么?怎么理解?有什么用途?
java·开发语言
Urbano8 小时前
工装外套全制作流程、工序痛点及自动化设备升级方案
运维·自动化
映翰通朱工8 小时前
工业4G网关无公网IP远程运维实战(内网终端异地访问方案)
运维·服务器·网络·安全·智能路由器
洪晓露9 小时前
将 rke2 集群证书延长至 10 年
运维·服务器·数据库
谢平康9 小时前
解决用 rm 报bash: /usr/bin/rm: Argument list too long错
linux·运维·运维开发
摇滚侠9 小时前
SpringMVC 入门到实战 文件上传 75-77
java·后端·spring·maven·intellij-idea