理解函数调用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)多了以后,管理很麻烦。

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

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

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

相关推荐
positive_zpc2 小时前
计算机网络——网络层(二)
服务器·网络·计算机网络
花无缺就是我2 小时前
内网穿透哪个好,之神卓互联Linux版Arm安装教程2026最新
linux·运维·arm开发
indexsunny2 小时前
互联网大厂Java求职面试实战:Spring Boot微服务在电商场景中的应用与挑战
java·spring boot·redis·面试·kafka·oauth2·microservices
of Watermelon League2 小时前
SQL server配置ODBC数据源(本地和服务器)
运维·服务器·github
RATi GORI2 小时前
SQL中的DISTINCT、SQL DISTINCT详解、DISTINCT的用法、DISTINCT注意事项
java·数据库·sql
莫逸风2 小时前
【java-core-collections】B+ 树深度解析
android·java·开发语言
Wenzar_2 小时前
**发散创新:基于算子融合的深度学习推理优化实战**在现代AI推理场景中,模型性能瓶颈往往不是由单一算子决定的,而是多个连续算子之间数
java·人工智能·深度学习
小陈99cyh2 小时前
安装NVIDIA Container Toolkit,让gpu容器环境跑通
运维·pytorch·docker·nvidia
我命由我123452 小时前
Android 开发问题:无法从存储库 “D:\keys\MyNotifications.jks“ 中读取密钥 MyNotifications.
android·java·java-ee·android studio·android jetpack·android-studio·android runtime