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}
相关推荐
晚霞的不甘41 分钟前
Flutter for OpenHarmony构建全功能视差侧滑菜单系统:从动效设计到多页面导航的完整实践
前端·学习·flutter·microsoft·前端框架·交互
恋猫de小郭1 小时前
Flutter 在 Android 出现随机字体裁剪?其实是图层合并时的边界计算问题
android·flutter·ios
tiger1191 小时前
FPGA 在大模型推理中的应用
人工智能·llm·fpga·大模型推理
AndrewHZ2 小时前
【AI黑话日日新】什么是大模型的test-time scaling?
人工智能·深度学习·大模型·llm·推理加速·测试时缩放
2501_944448002 小时前
Flutter for OpenHarmony 衣橱管家App实战 - 智能推荐实现
flutter
菜鸟小芯2 小时前
【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现
flutter·harmonyos
灰灰勇闯IT2 小时前
Flutter for OpenHarmony:悬浮按钮(FloatingActionButton)最佳实践 —— 强化核心操作,提升用户效率
flutter·华为·交互
雨季6663 小时前
Flutter 三端应用实战:OpenHarmony “心流之泉”——在碎片洪流中,为你筑一眼专注的清泉
开发语言·前端·flutter·交互
一起养小猫3 小时前
Flutter for OpenHarmony 进阶:表达式解析算法与计算器核心实现
算法·flutter·harmonyos
GPUStack3 小时前
vLLM、SGLang 融资背后,AI 推理正在走向系统化与治理
大模型·llm·vllm·模型推理·sglang·高性能推理