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}
相关推荐
LawrenceLan11 小时前
Flutter 零基础入门(十一):空安全(Null Safety)基础
开发语言·flutter·dart
人工干智能12 小时前
OpenAI Assistants API 中 client.beta.threads.messages.create方法,兼谈一星*和两星**解包
python·llm
行者9612 小时前
Flutter与OpenHarmony跨平台分享组件深度实践
flutter·harmonyos·鸿蒙
行者9612 小时前
Flutter跨平台开发在OpenHarmony上的评分组件实现与优化
开发语言·flutter·harmonyos·鸿蒙
cn_mengbei14 小时前
Flutter for OpenHarmony 实战:IconButton 图标按钮详解
flutter
cn_mengbei15 小时前
Flutter for OpenHarmony 实战:OutlinedButton 边框按钮详解
flutter
2501_9159184115 小时前
只有 Flutter IPA 文件,通过多工具组合完成有效混淆与保护
android·flutter·ios·小程序·uni-app·iphone·webview
JasonBoolean16 小时前
EasyDebug v0.0.4 重磅更新:原生 Http 支持 + 全新日志控制台
flutter
cn_mengbei16 小时前
Flutter for OpenHarmony 实战:TextButton 文本按钮详解
flutter