flutter实现Function Call

根据Function Call实现用大模型来调用方法。以下实现用操作空调。

一、选用大模型

阿里云百炼:筛选具有Function Call能力的模型

讯飞星火大模型Spark 4.0Ultra、Max 现已支持systemFunction 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}
相关推荐
勇气要爆发几秒前
【第五阶段—高级特性和框架】复杂动画案例分析初体验
flutter
智泊AI28 分钟前
何恺明新作:扩散模型+Transformer才是王炸!
llm
勤劳打代码2 小时前
追本溯源 —— SetState 刷新做了什么
flutter·面试·性能优化
casterQ2 小时前
4. Agent Quality ——【Google 5-Day AI Agents】
人工智能·llm·agent·langgraph·adk
组合缺一2 小时前
Solon AI 开发学习11 - chat - 工具调用与定制(Tool Call)
人工智能·学习·ai·chatgpt·llm·solon·toolcall
阿豪Jeremy3 小时前
LlamaFactory微调Qwen3-0.6B大模型步骤
llm
松☆3 小时前
OpenHarmony 后台任务与 Flutter 生命周期协调:构建稳定可靠的混合应用
flutter
松☆3 小时前
Flutter 与 OpenHarmony 深度集成:自定义 MethodChannel 插件开发全指南
flutter·wpf
克喵的水银蛇3 小时前
Flutter 布局实战:掌握 Row/Column/Flex 弹性布局
前端·javascript·flutter
带刺的坐椅3 小时前
Solon AI 开发学习9 - chat - 聊天会话(对话)的记忆与持久化
java·ai·llm·openai·solon·mcp