You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.1 KiB
184 lines
5.1 KiB
import 'dart:async';
|
|
import 'dart:convert';
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
/// OpenAI和MCP集成插件
|
|
class OpenAI {
|
|
/// 插件通道
|
|
static const MethodChannel _channel =
|
|
MethodChannel('com.yunqiinnovation.open_ai');
|
|
|
|
/// 流式输出事件回调
|
|
static final Map<String, StreamCallback> _streamCallbacks = {};
|
|
|
|
/// 构造函数
|
|
OpenAI() {
|
|
_channel.setMethodCallHandler(_handleMethodCall);
|
|
}
|
|
|
|
/// 处理来自原生端的方法调用
|
|
Future<dynamic> _handleMethodCall(MethodCall call) async {
|
|
if (call.method == 'onStreamEvent') {
|
|
final Map<String, dynamic> args = Map<String, dynamic>.from(call.arguments);
|
|
final String streamId = args['streamId'];
|
|
final String type = args['type'];
|
|
|
|
final callback = _streamCallbacks[streamId];
|
|
if (callback != null) {
|
|
switch (type) {
|
|
case 'token':
|
|
callback.onToken(args['data']);
|
|
break;
|
|
case 'complete':
|
|
callback.onComplete();
|
|
_streamCallbacks.remove(streamId);
|
|
break;
|
|
case 'error':
|
|
callback.onError(Exception(args['error']));
|
|
_streamCallbacks.remove(streamId);
|
|
break;
|
|
case 'functionCall':
|
|
final functionCall = jsonDecode(args['data']);
|
|
callback.onFunctionCall(functionCall);
|
|
break;
|
|
case 'functionCallResult':
|
|
final functionCall = jsonDecode(args['functionCall']);
|
|
final functionCallResult = jsonDecode(args['result']);
|
|
callback.onFunctionCallResult(functionCall, functionCallResult);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// 初始化OpenAI服务
|
|
///
|
|
/// [apiKey] OpenAI API密钥
|
|
/// [baseUrl] API基础URL,可选
|
|
/// [model] 模型名称,可选
|
|
/// [mcpServer] MCP服务器URL,可选
|
|
Future<bool> initialize({
|
|
required String apiKey,
|
|
String baseUrl = '',
|
|
String model = '',
|
|
String mcpServer = '',
|
|
}) async {
|
|
final result = await _channel.invokeMethod<bool>('initialize', {
|
|
'apiKey': apiKey,
|
|
'baseUrl': baseUrl,
|
|
'model': model,
|
|
'mcpServer': mcpServer,
|
|
});
|
|
return result ?? false;
|
|
}
|
|
|
|
/// 创建用户消息
|
|
Future<Map<String, dynamic>> createUserMessage(String content) async {
|
|
final result = await _channel.invokeMethod<String>('createUserMessage', {
|
|
'content': content,
|
|
});
|
|
return jsonDecode(result ?? '{}');
|
|
}
|
|
|
|
/// 创建系统消息
|
|
Future<Map<String, dynamic>> createSystemMessage(String content) async {
|
|
final result = await _channel.invokeMethod<String>('createSystemMessage', {
|
|
'content': content,
|
|
});
|
|
return jsonDecode(result ?? '{}');
|
|
}
|
|
|
|
/// 创建助手消息
|
|
Future<Map<String, dynamic>> createAssistantMessage(String content) async {
|
|
final result = await _channel.invokeMethod<String>('createAssistantMessage', {
|
|
'content': content,
|
|
});
|
|
return jsonDecode(result ?? '{}');
|
|
}
|
|
|
|
/// 创建带图片的用户消息
|
|
Future<Map<String, dynamic>> createUserMessageWithImage(
|
|
String text,
|
|
String imageBase64,
|
|
) async {
|
|
final result = await _channel.invokeMethod<String>(
|
|
'createUserMessageWithImage',
|
|
{
|
|
'text': text,
|
|
'imageBase64': imageBase64,
|
|
},
|
|
);
|
|
return jsonDecode(result ?? '{}');
|
|
}
|
|
|
|
/// 发送消息(非流式输出)
|
|
Future<String> sendMessage(List<Map<String, dynamic>> messages) async {
|
|
final messagesJson = jsonEncode(messages);
|
|
return await _channel.invokeMethod('sendMessage', {
|
|
'messages': messagesJson,
|
|
});
|
|
}
|
|
|
|
/// 发送消息(流式输出)
|
|
Future<String> sendMessageStream(
|
|
List<Map<String, dynamic>> messages,
|
|
StreamCallback callback,
|
|
) async {
|
|
final messagesJson = jsonEncode(messages);
|
|
final streamId = DateTime.now().millisecondsSinceEpoch.toString();
|
|
|
|
// 注册回调
|
|
_streamCallbacks[streamId] = callback;
|
|
|
|
final result = await _channel.invokeMethod<String>('sendMessageStream', {
|
|
'messages': messagesJson,
|
|
'streamId': streamId,
|
|
});
|
|
|
|
return result ?? streamId;
|
|
}
|
|
|
|
/// 取消当前流式请求
|
|
Future<bool> cancelCurrentStream() async {
|
|
final result = await _channel.invokeMethod<bool>('cancelCurrentStream');
|
|
return result ?? false;
|
|
}
|
|
|
|
/// 释放资源
|
|
Future<void> dispose() async {
|
|
await _channel.invokeMethod('dispose');
|
|
_streamCallbacks.clear();
|
|
}
|
|
}
|
|
|
|
/// 流式输出回调接口
|
|
class StreamCallback {
|
|
/// 收到令牌
|
|
final void Function(String token) onToken;
|
|
|
|
/// 完成回调
|
|
final void Function() onComplete;
|
|
|
|
/// 错误回调
|
|
final void Function(Exception e) onError;
|
|
|
|
/// 函数调用回调
|
|
final void Function(Map<String, dynamic> functionCall) onFunctionCall;
|
|
|
|
/// 函数调用结果回调
|
|
final void Function(
|
|
Map<String, dynamic> functionCall,
|
|
Map<String, dynamic> functionCallResult,
|
|
) onFunctionCallResult;
|
|
|
|
/// 构造函数
|
|
StreamCallback({
|
|
required this.onToken,
|
|
required this.onComplete,
|
|
required this.onError,
|
|
required this.onFunctionCall,
|
|
required this.onFunctionCallResult,
|
|
});
|
|
}
|