金字塔思维了解Function Calling
学习路线图

Function Calling 的学习路线结构说明:
Function Calling 是 LLM 与外部世界交互的基础能力,MCP 其实是 Function Calling 的一种标准化和扩展实现。因此,Function Calling 的学习路线应该更侧重于“LLM 如何理解并执行代码逻辑”。 我将按照以下模块构建内容:
定位:Function Calling 是 LLM 将自然语言转化为结构化参数以调用预定义函数的能力,它是 LLM 的“手和脚”,让模型从“只读”变“可执行”。
解决的核心问题:幻觉、数据滞后、无法操作业务系统。
解决方案:外挂工具,模型只负责“决策”和“参数提取”,不负责“执行
构成和设计原理:Prompt Engineering (Few-shot), Schema 定义 (JSON Schema), 解析与执行循环。
工作原理:用户提问 -> LLM 识别意图 -> 输出结构化 JSON -> 代码执行 -> 结果回传 -> LLM 生成回答。
1. 定位
Function Calling 是赋予大模型(LLM)“执行力”的关键技术。
- 定义: 它是一种让 LLM 能够理解预定义的函数(工具),并根据用户指令输出结构化数据(通常是 JSON),以便外部程序执行具体操作的技术机制。
- 类比: 如果 LLM 是大脑,Function Calling 就是神经系统。大脑(LLM)负责思考“做什么”,神经系统(Function Calling)负责将指令传递给手脚(外部 API/代码)去执行。
- 与 MCP 的关系: MCP 是 Function Calling 的标准化协议版本。Function Calling 是通用概念,MCP 是为了解决 Function Calling 碎片化而制定的统一标准。
2. 解决的核心问题
背景
随着大模型普及,用户不再满足于“陪聊”,而是希望 AI 能干活(查天气、订机票、查数据库)。但原生 LLM 存在先天缺陷。
技术角度的核心难题
|
痛点 |
具体表现 |
传统/无 Function Calling 方案缺陷 |
|
1. 知识时效性滞后 |
模型训练数据截止于过去,无法回答“今天北京天气”或“最新股价”。 |
只能依靠模型幻觉瞎编,或需要人工微调(成本高且无法实时更新)。 |
|
2. 缺乏业务执行力 |
模型无法直接操作 ERP、CRM 系统,无法发送邮件或创建工单。 |
用户需复制模型建议,手动去系统操作,体验割裂。 |
|
3. 复杂计算能力弱 |
LLM 擅长语言推理,但不擅长精确数学计算或逻辑运算。 |
直接让 LLM 算数容易出错(如“9.11 和 9.9 谁大”)。 |
|
4. 私有数据隔离 |
模型无法访问企业内部的私有数据库或文档。 |
需将数据上传至公有云微调,存在严重数据泄露风险。 |
解决方案(设计思路)
- 外挂工具箱: 不改变模型权重,通过 Prompt 将可用工具列表告诉模型。
- 结构化输出: 强制模型输出符合特定 Schema(如 JSON Schema)的参数,而非自然语言。
- 执行与回填: 由外部代码执行函数,并将结果作为“新上下文”喂回给模型,让模型基于真实结果回答。
3. 构成和设计原理
核心设计思想
Function Calling 的核心在于“意图识别”与“参数提取”的解耦。
- 意图识别: 判断用户想干什么(调用哪个函数)。
- 参数提取: 从自然语言中提取函数所需的变量。
核心支柱(三元模型)
|
支柱 |
实现载体 |
解决的核心问题 |
|
工具定义 (Schema) |
JSON Schema / Pydantic |
明确告诉 LLM“我能做什么”以及“需要什么参数”,消除歧义。 |
|
推理引擎 (LLM) |
GPT-4 / Claude / Local LLM |
理解用户自然语言,将其映射到工具定义中,生成结构化调用请求。 |
|
执行环境 (Runtime) |
后端代码 |
安全地执行 LLM 生成的函数调用,处理异常,并将结果格式化。 |
架构分层

架构层级说明:
- 用户交互层 (Host): 负责接收用户指令,管理会话状态,发起 FC 请求。
- 模型服务层 (LLM): 负责语义理解,匹配工具,生成参数。
- 工具服务层 (Server): 负责实际业务逻辑执行(这是 MCP 重点解耦的部分)。
- 上下文闭环: 关键在于第 5 步,将执行结果再次发给 LLM,形成闭环。
4. 构成和工作原理

协议基石:JSON Schema
Function Calling 强依赖于 JSON Schema 来定义工具。这是 LLM 理解工具的“说明书”。
- name: 函数名(如
get_weather) - description: 函数描述(告诉 LLM 什么时候该用这个函数)
- parameters: 参数定义(类型、必填项、枚举值)
核心组件
- Tool Registry (工具注册表): 存储所有可用函数的元数据。
- Parser (解析器): 将 LLM 输出的文本(有时包含 Markdown 标记)清洗为纯 JSON 对象。
- Dispatcher (调度器): 根据函数名路由到具体的代码逻辑。
工作原理(动态流程)
Function Calling 是一个“请求 - 响应 - 执行 - 再响应”的闭环过程。
第一步:工具声明 (Setup)
- 开发者在代码中定义函数(如
search_database(query))。 - 将函数的 Schema 描述放入 System Prompt 或 API 的
tools参数中发送给 LLM。
第二步:意图识别与参数提取 (Inference)
- 用户输入:“查一下北京明天的天气”。
- LLM 分析:发现需要查天气,匹配到
get_weather工具。 - LLM 输出(停止生成自然语言,转为工具调用模式):
{
"name": "get_weather",
"arguments": {"location": "北京", "date": "tomorrow"}
}
第三步:外部执行 (Execution)
- 应用程序拦截 LLM 的输出。
- 解析 JSON,在本地或服务器端执行真实的
get_weather("北京", "tomorrow")代码。 - 获取真实结果:
{"temp": 25, "condition": "Sunny"}。
第四步:结果回填与最终回答 (Completion)
- 将执行结果作为一条新的“系统消息”或“工具响应”发送回 LLM。
- LLM 结合结果生成最终自然语言回复:“北京明天天气晴朗,气温 25 度。”
5. 实用场景与面试要求
典型应用场景
- RAG 增强检索: 将“搜索知识库”封装为 Function,让 LLM 自主决定何时检索。
- 数据分析助手: 将“SQL 查询”或“Python 绘图”封装为 Function,实现 Text-to-SQL 或自动图表生成。
- 自动化运维/办公: 调用 Jira、Slack、AWS API 完成工单创建、通知发送、资源扩缩容。
面试中的定位与要求
在 AI 应用开发面试中,Function Calling 是中级到高级的必考点。
- 初级要求: 能调用 OpenAI/Claude 的官方 Function Calling API,会写 JSON Schema。
- 中级要求: 理解 ReAct 模式(Reasoning + Acting),能处理多步工具调用(Chain of Thought),能处理工具调用失败的情况。
- 高级要求:
-
- 安全性: 如何防止 LLM 注入恶意代码?(沙箱执行、权限控制、安全校验)。
- 准确性: 当模型参数提取错误时如何纠错?(Few-shot prompting, 自动重试机制)。
- 架构设计: 如何设计一个支持动态加载插件的 Agent 系统?(参考 MCP 架构思想)。
Java + LangChain4j 实现 Function Calling 完整示例
下面是一个可运行的天气查询 Function Calling 示例,使用 LangChain4j(LangChain 的 Java 版本)。
一、项目依赖配置
Maven (pom.xml)
<dependencies>
<!-- LangChain4j 核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.31.0</version>
</dependency>
<!-- OpenAI 集成 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.31.0</version>
</dependency>
<!-- Lombok (简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
Gradle (build.gradle)
dependencies {
implementation 'dev.langchain4j:langchain4j:0.31.0'
implementation 'dev.langchain4j:langchain4j-open-ai:0.31.0'
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
}
二、完整代码实现
1. 工具类 - 天气服务
package com.example.ai.tools;
import dev.langchain4j.agent.tool.Tool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 天气查询工具 - 演示 Function Calling
*/
@Slf4j
@Component
public class WeatherService {
/**
* 查询天气 - 会被 LLM 自动识别和调用
* @Tool 注解标记这是一个可被调用的函数
*/
@Tool("查询指定城市的当前天气情况")
public String getWeather(
@P("城市名称,例如:北京、上海") String city,
@P("日期,例如:今天、明天") String date
) {
log.info("收到天气查询请求:city={}, date={}", city, date);
// 模拟调用真实天气 API
// 实际项目中这里会调用 和风天气/OpenWeatherMap 等 API
return simulateWeatherAPI(city, date);
}
/**
* 模拟天气 API 返回
*/
private String simulateWeatherAPI(String city, String date) {
// 实际项目中替换为真实 API 调用
return String.format(
"{\"city\":\"%s\",\"date\":\"%s\",\"temperature\":25,\"condition\":\"晴朗\",\"humidity\":60}",
city, date
);
}
}
2. 助手类 - AI 助理
package com.example.ai.assistant;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
/**
* AI 助理接口 - 定义与 LLM 交互的契约
*/
public interface WeatherAssistant {
@SystemMessage("你是一个智能天气助手,可以帮助用户查询天气信息。")
@UserMessage("{{userMessage}}")
String chat(String userMessage);
}
3. 主程序 - Function Calling 调用
package com.example.ai;
import com.example.ai.assistant.WeatherAssistant;
import com.example.ai.tools.WeatherService;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
/**
* Function Calling 主程序入口
*/
public class FunctionCallingDemo {
public static void main(String[] args) {
// 1. 配置 OpenAI 模型 (支持 Function Calling)
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.apiKey("你的 OpenAI API Key") // 从环境变量获取更安全
.modelName("gpt-3.5-turbo-0613") // 或 gpt-4-turbo
.temperature(0.7)
.build();
// 2. 创建工具实例
WeatherService weatherService = new WeatherService();
// 3. 构建 AI 服务 - 自动注册工具函数
WeatherAssistant assistant = AiServices.builder(WeatherAssistant.class)
.chatLanguageModel(chatModel)
.tools(weatherService) // 关键:注册工具
.build();
// 4. 测试场景 1 - 触发 Function Calling
System.out.println("=== 测试场景 1: 查询天气 ===");
String response1 = assistant.chat("北京今天天气怎么样?");
System.out.println("AI 回复:" + response1);
// 5. 测试场景 2 - 多轮对话
System.out.println("\n=== 测试场景 2: 多轮对话 ===");
String response2 = assistant.chat("那上海明天呢?");
System.out.println("AI 回复:" + response2);
// 6. 测试场景 3 - 不需要调用工具
System.out.println("\n=== 测试场景 3: 普通对话 ===");
String response3 = assistant.chat("你好,介绍一下你自己");
System.out.println("AI 回复:" + response3);
}
}
三、执行流程时序图

四、进阶:多工具函数调用
1. 添加更多工具
package com.example.ai.tools;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
@Component
public class CalendarService {
@Tool("查询指定日期的日程安排")
public String getSchedule(
@P("日期,格式:YYYY-MM-DD") String date,
@P("用户 ID") String userId
) {
// 模拟查询日历
return "{\"date\":\"" + date + "\",\"events\":[\"会议\",\"聚餐\"]}";
}
@Tool("创建新的日程提醒")
public String createReminder(
@P("提醒内容") String content,
@P("提醒时间") String time
) {
log.info("创建提醒:content={}, time={}", content, time);
return "{\"status\":\"success\",\"reminderId\":\"REM001\"}";
}
}
2. 注册多个工具
// 在主程序中注册多个工具
WeatherAssistant assistant = AiServices.builder(WeatherAssistant.class)
.chatLanguageModel(chatModel)
.tools(weatherService) // 天气工具
.tools(calendarService) // 日历工具
.tools(emailService) // 邮件工具
.build();
五、安全增强版(参考 MCP 安全设计)
1. 权限校验拦截器
package com.example.ai.security;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 工具调用安全拦截器 - 实现 MCP 式的安全双闸
*/
@Slf4j
@Component
public class SecurityToolExecutor implements ToolExecutor {
private final ToolExecutor delegate;
private final PermissionChecker permissionChecker;
public SecurityToolExecutor(ToolExecutor delegate, PermissionChecker checker) {
this.delegate = delegate;
this.permissionChecker = checker;
}
@Override
public String execute(ToolExecutionRequest request, String memoryId) {
// 第一道闸:用户授权检查
if (!permissionChecker.checkUserPermission(memoryId, request.name())) {
log.warn("用户无权调用工具:{}", request.name());
return "错误:您没有权限执行此操作";
}
// 第二道闸:参数安全校验
if (!permissionChecker.validateParameters(request)) {
log.warn("参数校验失败:{}", request.name());
return "错误:参数不符合安全规范";
}
// 记录审计日志
log.info("工具调用审计:user={}, tool={}, params={}",
memoryId, request.name(), request.arguments());
// 执行实际调用
return delegate.execute(request, memoryId);
}
}
2. 敏感操作二次确认
package com.example.ai.tools;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
@Component
public class SensitiveOperationService {
@Tool("删除用户数据 - 需要二次确认")
public String deleteUserData(
@P("用户 ID") String userId,
@P("确认令牌 - 必须为 CONFIRM") String confirmToken
) {
// 强制要求确认令牌,防止误操作
if (!"CONFIRM".equals(confirmToken)) {
throw new SecurityException("删除操作需要二次确认");
}
// 执行删除逻辑
return "{\"status\":\"deleted\",\"userId\":\"" + userId + "\"}";
}
}
六、常见问题与解决方案
|
问题 |
原因 |
解决方案 |
|
工具未被调用 |
函数描述不够清晰 |
优化 |
|
参数提取错误 |
参数名与 Schema 不匹配 |
确保 |
|
中文乱码 |
编码问题 |
确保项目编码为 UTF-8 |
|
API Key 泄露 |
硬编码在代码中 |
使用环境变量 |
|
调用超时 |
网络或 API 限制 |
增加超时配置 |
七、运行结果示例
=== 测试场景 1: 查询天气 ===
[DEBUG] 收到天气查询请求:city=北京,date=今天
AI 回复:北京今天天气晴朗,气温 25 度,湿度 60%,适合外出活动。
=== 测试场景 2: 多轮对话 ===
[DEBUG] 收到天气查询请求:city=上海,date=明天
AI 回复:上海明天预计多云转晴,气温 23-28 度。
=== 测试场景 3: 普通对话 ===
AI 回复:你好!我是一个智能天气助手,可以帮您查询各地天气信息...
学习路线建议

更多推荐



所有评论(0)