根据Function Call实现用大模型来调用方法。以下实现用操作空调。
一、选用大模型
阿里云百炼:筛选具有Function Call能力的模型
讯飞星火大模型:Spark 4.0Ultra、Max 现已支持system 、Function Call功能
二、代码实现(通义千问3-Max)
dart
import 'dart:convert';
import 'package:dio/dio.dart';
class FunctionCallService {
static const String _tag = "FunctionCallService";
static final FunctionCallService instance = FunctionCallService._();
FunctionCallService._();
factory FunctionCallService.getInstance() {
return instance;
}
final List<Map<String, dynamic>> tools = [
{
"type": "function",
"function": {
"name": "controlAirConditioner",
"description": "打开空调并设置参数",
"parameters": {
"type": "object",
"properties": {
"action": {"type": "bool", "description": "打开或关闭"},
"room": {"type": "string", "description": "空调所在房间"},
"name": {"type": "string", "description": "空调名称"},
"temperature": {"type": "number", "description": "目标温度 (16-45摄氏度)"},
"mode": {
"type": "string",
"description": "运行模式",
"enum": ["cool", "heat", "fan", "dry", "auto"]
},
"fan_speed": {
"type": "string",
"description": "风速",
"enum": ["low", "medium", "high", "auto"]
}
},
"required": ["name"]
},
}
}
];
final apiUrl =
"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
// apiKey获取地址:https://bailian.console.aliyun.com/?spm=a2ty02.30268951.0.0.21ae74a17iekVZ&tab=model#/api-key
final apiKey = "sk-xxx";
final model = "qwen3-max";
Future<String> controlAirConditioner(
{required bool action,
String? room,
String? name,
double? temperature,
String? mode,
String? fanSpeed}) async {
// 实际操作
return '操作成功';
}
final Dio _dio = Dio();
void handleFunctionCall() async {
var messages = [];
messages.add({
'role': "system",
"content": "不要假设或猜测传入函数的参数值。如果用户的描述不明确,请要求用户提供必要信息。"
});
messages.add({"role": "user", "content": "打开客厅空调到38度"});
print('$_tag 开始调用模型');
Response response = await _dio.post(apiUrl,
data: {'model': model, 'messages': messages, 'tools': tools},
options: Options(
headers: {'Authorization': 'Bearer $apiKey'},
));
print('$_tag 第一次调用模型的请求参数:$messages');
print('$_tag 第一次调用模型的回答结果:${response.data['choices'][0]['message']}');
messages.add(response.data['choices'][0]['message']);
parseFunctionCall(
response.data['choices'][0]['message']['tool_calls'][0]['function'],
messages);
}
void parseFunctionCall(Map toolCall, List messages) async {
if (toolCall['name'] == 'controlAirConditioner') {
var arguments = toolCall['arguments'];
var args = jsonDecode(arguments);
var content = await controlAirConditioner(
action: args['action'],
room: args['room'],
name: args['name'],
mode: args['mode'],
fanSpeed: args['fan_speed'],
temperature: args['temperature'] != null
? double.parse(args['temperature'].toString())
: null);
messages.add({'role': 'tool', 'content': content});
Response response = await _dio.post(apiUrl,
data: {'model': model, 'messages': messages, 'tools': tools},
options: Options(
headers: {'Authorization': 'Bearer $apiKey'},
));
print('$_tag 第二次调用模型的请求参数:$messages');
print('$_tag 第二次调用模型的回答结果:${response.data['choices'][0]['message']}');
}
}
}
📌 运行结果
dart
I/flutter (23387): FunctionCallService 开始调用模型
I/flutter (23387): FunctionCallService 第一次调用模型的请求参数:[{role: system, content: 不要假设或猜测传入函数的参数值。如果用户的描述不明确,请要求用户提供必要信息。}, {role: user, content: 打开客厅空调到38度}]
I/flutter (23387): FunctionCallService 第一次调用模型的回答结果:{content: , role: assistant, tool_calls: [{function: {arguments: {"name": "客厅空调", "temperature": 38, "action": true}, name: controlAirConditioner}, id: call_58b2365bdd4e4d9da6f65fb1, index: 0, type: function}]}
I/flutter (23387): FunctionCallService 第二次调用模型的请求参数:[{role: system, content: 不要假设或猜测传入函数的参数值。如果用户的描述不明确,请要求用户提供必要信息。}, {role: user, content: 打开客厅空调到38度}, {content: , role: assistant, tool_calls: [{function: {arguments: {"name": "客厅空调", "temperature": 38, "action": true}, name: controlAirConditioner}, id: call_58b2365bdd4e4d9da6f65fb1, index: 0, type: function}]}, {role: tool, content: 操作成功}]
I/flutter (23387): FunctionCallService 第二次调用模型的回答结果:{content: 客厅空调已成功打开,并设置温度为38度。, role: assistant}