












摘要:大语言模型只能聊天不能做事?Function Call 技术让大模型能够调用外部函数、执行实际操作。本文深度解析其核心原理、两种实现方式和生产实践。
假设你问 AI:"订单 20240115001 现在到哪了?"
传统模型的局限:无法访问外部系统,只能回答"我不知道"
Function Call 的突破:
用户:订单 20240115001 到哪了?
大模型 → 调用 trackOrder("20240115001")
→ 返回:"已发货,顺丰 SF1234567890"
→ 回答:"您的订单已发货,顺丰快递 SF1234567890"
Function Call 让大模型在对话中主动识别需要调用的外部函数,自动生成参数,并基于返回结果生成回答。
核心流程:
graph LR A[用户提问] --> B[大模型分析意图] B --> C{需要调用函数?} C -->|是| D[生成函数调用] D --> E[框架执行函数] E --> F[返回结果给大模型] F --> G[生成最终回答] C -->|否| G
框架通过注解将函数转换为大模型能理解的 JSON Schema:
public LogisticsInfo trackOrder(OrderTrackRequest request) {
return logisticsService.query(request.orderId());
}
// 自动生成的 JSON Schema
{
"name": "trackOrder",
"description": "根据订单号查询物流状态",
"parameters": {
"orderId": {
"type": "string",
"description": "订单编号,比如 20240115001"
}
}
}
用户提问 → 框架发送函数描述给大模型
→ 大模型返回函数调用请求
→ 框架执行业务函数
→ 将结果返回大模型
→ 大模型生成最终回答
| 场景 | 问题 | 解决方案 |
|---|---|---|
| 实时数据 | 模型不知道实时汇率 | 调用 API 获取最新数据 |
| 业务集成 | 无法访问订单系统 | 调用企业内部服务 |
| 精确计算 | 大模型数学计算易出错 | 调用计算器函数 |
| 权限控制 | 敏感操作需要验证 | 框架拦截+权限检查 |
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
spring:
ai:
openai:
api-key: your-api-key
base-url: https://dashscope.aliyuncs.com/compatible-mode/
chat:
options:
model: qwen-plus
temperature: 0.7
public record StockQueryRequest(
@JsonProperty(required = true, value = "productName")
@JsonPropertyDescription("商品名称,比如 iPhone 15 Pro")
String productName
) {}
public record StockInfo(int quantity, String warehouse) {}
@Configuration
public class FunctionConfig {
@Bean
@Description("根据商品名称查询库存")
public Function<StockQueryRequest, StockInfo> checkStockFunction(
InventoryService inventoryService) {
return inventoryService::checkProductStock;
}
}
Spring AI 关键点:
@Bean:将函数注册为 Spring Bean@Description:函数描述,Spring AI 会自动转换为 JSON SchemaFunction<Request, Response>:Spring AI 标准函数接口@RestController
@RequestMapping("/function")
public class FunctionCallController {
@Autowired
private OpenAiChatModel chatModel;
@GetMapping("/chat")
public String chat(@RequestParam("query") String query) {
return chatModel.call(
Prompt.builder()
.functions("checkStockFunction") // Spring AI 函数名
.userMessage(query)
.build()
).getContent();
}
}
测试:
curl "http://localhost:8013/function/chat?query=iPhone15Pro库存多少?"
# 输出:iPhone 15 Pro 当前库存 156 台,存放于上海仓。
更简洁的方式,Spring AI 提供了 @Tool 注解:
public class InventoryTools {
@Tool(description = "根据商品名称查询库存")
public String checkStock(
@ToolParam(description = "商品名称,比如 iPhone 15 Pro")
String productName) {
// 查询逻辑
return "库存 " + quantity + " 台,仓库:" + warehouse;
}
}
Spring AI 关键点:
@Tool:Spring AI 工具注解,自动注册为可用函数@ToolParam:参数描述,Spring AI 自动生成 JSON SchemachatModel.call(
Prompt.builder()
.tools(new InventoryTools()) // Spring AI 直接传入工具实例
.userMessage(query)
.build()
).getContent();
| 维度 | 函数注册(@Bean) | 工具注解(@Tool) |
|---|---|---|
| 代码量 | 较多(需 Configuration) | 简洁 |
| 灵活性 | 高(依赖注入) | 中 |
| Spring 集成 | 完全集成 | 部分集成 |
| 适用场景 | 复杂业务 | 简单功能 |
// 注册多个函数,大模型自动选择
@Bean @Description("查询库存")
public Function<StockQueryRequest, StockInfo> checkStock(...) { ... }
@Bean @Description("计算折扣价格")
public Function<PriceRequest, PriceResponse> calculatePrice(...) { ... }
// 用户:"iPhone 15 Pro 有货吗?买 10 台多少钱?"
// 大模型自动调用 checkStock 和 calculatePrice
// 根据用户权限动态注册函数
Prompt.Builder builder = Prompt.builder();
builder.functions("checkStock", "calculatePrice"); // 所有用户
if (user.isAdmin()) {
builder.functions("deleteProduct"); // 仅管理员
}
通过 Prompt 引导模型按格式思考,不依赖原生 Function Call:
Thought: 我需要做什么
Action: 使用什么工具
Action Input: 工具参数
Observation: 工具返回结果
Final Answer: 最终回答
| 维度 | Function Call | ReAct |
|---|---|---|
| 实现复杂度 | 低 | 高 |
| 可靠性 | 高(结构化) | 中 |
| 灵活性 | 中 | 高(任意模型) |
server:
port: 8013
spring:
ai:
openai:
api-key: sk-xxx
base-url: https://dashscope.aliyuncs.com/compatible-mode/
chat:
options:
model: qwen-plus
temperature: 0.7
maxTokens: 5000
// 1. Service 层
@Service
public class InventoryService {
public StockInfo checkProductStock(StockQueryRequest request) {
int quantity = database.queryStock(request.productName());
String warehouse = database.getWarehouseLocation(request.productName());
return new StockInfo(quantity, warehouse);
}
public record StockQueryRequest(
@JsonProperty(required = true, value = "productName")
@JsonPropertyDescription("商品名称,比如 iPhone 15 Pro")
String productName
) {}
public record StockInfo(int quantity, String warehouse) {}
}
// 2. 配置层
@Configuration
public class FunctionConfig {
@Bean
@Description("根据商品名称查询库存")
public Function<StockQueryRequest, StockInfo> checkStockFunction(
InventoryService inventoryService) {
return inventoryService::checkProductStock;
}
}
// 3. 控制器层
@RestController
@RequestMapping("/function")
public class FunctionCallController {
@Autowired
private OpenAiChatModel chatModel;
@GetMapping("/chat")
public String chat(@RequestParam("query") String query) {
return chatModel.call(
Prompt.builder()
.functions("checkStockFunction")
.userMessage(query)
.build()
).getContent();
}
}
@Description("查询库存数量和仓库位置") ❌ @Description("查询库存")@JsonPropertyDescription("商品名,比如 iPhone 15 Pro")Function Call 让大模型从"聊天机器人"进化为"智能助手":
参考资源:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。