From 43494048ecb34671b18cfa34d045dc0865ff1c40 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Thu, 24 Apr 2025 19:32:20 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E8=AF=8D=E5=92=8C=E5=B1=9E=E6=80=A7=20=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/models/message_model.dart | 2 +- lib/data/services/ai_service.dart | 8 ++-- lib/data/services/deapsound_ai_service.dart | 6 ++- lib/data/services/kouzi_ai_service.dart | 6 ++- .../services/open_ai_service_adapter.dart | 10 +++- lib/data/services/volcano_ai_service.dart | 6 ++- .../open_ai_service/OpenAIServicePlugin.kt | 1 - .../open_ai_service/lib/open_ai_service.dart | 46 ++++++++++++++++++- 8 files changed, 69 insertions(+), 16 deletions(-) diff --git a/lib/data/models/message_model.dart b/lib/data/models/message_model.dart index 6307989ae..94aebc3ac 100644 --- a/lib/data/models/message_model.dart +++ b/lib/data/models/message_model.dart @@ -55,4 +55,4 @@ class Message { isLoading: isLoading ?? this.isLoading, ); } -} \ No newline at end of file +} diff --git a/lib/data/services/ai_service.dart b/lib/data/services/ai_service.dart index a2232b9b5..c815334e8 100644 --- a/lib/data/services/ai_service.dart +++ b/lib/data/services/ai_service.dart @@ -1,16 +1,16 @@ /// AI回复服务接口 abstract class AiService { - - /// 非流式输出方法 Future sendMessage({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }); /// 流式输出方法 Stream sendMessageStream({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }); } diff --git a/lib/data/services/deapsound_ai_service.dart b/lib/data/services/deapsound_ai_service.dart index ba1750407..186116ab4 100644 --- a/lib/data/services/deapsound_ai_service.dart +++ b/lib/data/services/deapsound_ai_service.dart @@ -17,7 +17,8 @@ class DeapsoundAIService implements AiService { @override Future sendMessage({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async { return ''; } @@ -25,7 +26,8 @@ class DeapsoundAIService implements AiService { @override Stream sendMessageStream({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async* { final client = http.Client(); final url = Uri.parse('https://api.deapsound.com/ai/funcchat'); diff --git a/lib/data/services/kouzi_ai_service.dart b/lib/data/services/kouzi_ai_service.dart index a7300a320..cf479ac56 100644 --- a/lib/data/services/kouzi_ai_service.dart +++ b/lib/data/services/kouzi_ai_service.dart @@ -13,7 +13,8 @@ class KouziAIService implements AiService { @override Future sendMessage({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async { return ''; } @@ -21,7 +22,8 @@ class KouziAIService implements AiService { @override Stream sendMessageStream({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async* { final client = http.Client(); final url = Uri.parse('https://api.coze.cn/v3/chat'); diff --git a/lib/data/services/open_ai_service_adapter.dart b/lib/data/services/open_ai_service_adapter.dart index 2aeb2af85..cd3adca7d 100644 --- a/lib/data/services/open_ai_service_adapter.dart +++ b/lib/data/services/open_ai_service_adapter.dart @@ -160,7 +160,8 @@ class OpenAIServiceAdapter implements AiService { @override Future sendMessage({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async { try { // 在方法内直接转换 @@ -170,6 +171,8 @@ class OpenAIServiceAdapter implements AiService { // 发送消息并获取回复 final response = await _openAIService.sendMessage( messages: convertedMessages, + systemPrompt: systemPrompt, + userProperties: userProperties, ); return response; @@ -183,7 +186,8 @@ class OpenAIServiceAdapter implements AiService { @override Stream sendMessageStream({ required List> messages, - required String systemPrompt, + String? systemPrompt, //提示词 + String? userProperties, //用户属性 }) async* { try { // 在方法内直接转换 @@ -231,6 +235,8 @@ class OpenAIServiceAdapter implements AiService { try { started = await _openAIService.sendMessageStream( messages: convertedMessages, + systemPrompt: systemPrompt, + userProperties: userProperties, ); } catch (e) { printError(info: '启动消息流失败: $e'); diff --git a/lib/data/services/volcano_ai_service.dart b/lib/data/services/volcano_ai_service.dart index e998a8270..e84df89d5 100644 --- a/lib/data/services/volcano_ai_service.dart +++ b/lib/data/services/volcano_ai_service.dart @@ -35,7 +35,8 @@ class VolcanoAIService implements AiService { @override Future sendMessage({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async { final url = Uri.parse('$_baseUrl$_chatEndpoint'); @@ -84,7 +85,8 @@ class VolcanoAIService implements AiService { @override Stream sendMessageStream({ required List> messages, - required String systemPrompt, + String? systemPrompt, + String? userProperties, }) async* { final url = Uri.parse('$_baseUrl$_chatEndpoint'); diff --git a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt index 185989ee5..653ccdcef 100644 --- a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt +++ b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt @@ -126,7 +126,6 @@ class OpenAIServicePlugin : FlutterPlugin, MethodCallHandler, StreamHandler { "sendMessageStream" -> { val messagesRaw = call.argument>>("messages") ?: emptyList() - // 检查事件接收器 if (eventSink == null) { result.error("NO_EVENT_SINK", "没有可用的事件流接收器", null) diff --git a/local_plugins/open_ai_service/lib/open_ai_service.dart b/local_plugins/open_ai_service/lib/open_ai_service.dart index 20934fd07..a977cf02b 100644 --- a/local_plugins/open_ai_service/lib/open_ai_service.dart +++ b/local_plugins/open_ai_service/lib/open_ai_service.dart @@ -195,12 +195,33 @@ class OpenAIService { /// [messages] 消息列表 Future sendMessage({ required List> messages, + String? systemPrompt, //提示词 + String? userProperties, //用户属性 }) async { try { + // 构建新的消息列表 + final List> updatedMessages = []; + // 如果有提示词,先添加 system role + if (systemPrompt != null && systemPrompt.isNotEmpty) { + updatedMessages.add({ + 'role': 'system', + 'content': systemPrompt, + }); + } + + // 如果有用户属性,可以作为 user 的一个“隐式指令”传进去 + if (userProperties != null && userProperties.isNotEmpty) { + updatedMessages.add({ + 'role': 'user', + 'content': '【用户属性】$userProperties', + }); + } + // 添加原始消息 + updatedMessages.addAll(messages); final result = await _channel.invokeMethod( 'sendMessage', { - 'messages': messages, + 'messages': updatedMessages, }, ); @@ -221,12 +242,33 @@ class OpenAIService { /// 返回一个布尔值,表示请求是否已开始 Future sendMessageStream({ required List> messages, + String? systemPrompt, //提示词 + String? userProperties, //用户属性 }) async { try { + // 构建新的消息列表 + final List> updatedMessages = []; + // 如果有提示词,先添加 system role + if (systemPrompt != null && systemPrompt.isNotEmpty) { + updatedMessages.add({ + 'role': 'system', + 'content': systemPrompt, + }); + } + + // 如果有用户属性,可以作为 user 的一个“隐式指令”传进去 + if (userProperties != null && userProperties.isNotEmpty) { + updatedMessages.add({ + 'role': 'user', + 'content': '【用户属性】$userProperties', + }); + } + // 添加原始消息 + updatedMessages.addAll(messages); final result = await _channel.invokeMethod( 'sendMessageStream', { - 'messages': messages, + 'messages': updatedMessages, }, ); From c9146f571e09f8b679e0284f91a3946387d5252a Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Thu, 24 Apr 2025 20:00:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E9=9F=B3=E4=B9=90?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/controllers/chat_controller.dart | 33 +++++++++++++++++-- lib/modules/chat/views/chat_music_card.dart | 23 +++++++++++-- lib/modules/chat/views/chat_view.dart | 5 ++- .../open_ai_service/OpenAIServicePlugin.kt | 2 +- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 7776de777..09b3b6b17 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -418,7 +418,10 @@ class ChatController extends GetxController { ); _updateIntermediateMessage(meta: chunk); if (chunk['card_spotify'] != null) { - play(chunk['card_spotify']); + play_spotify(chunk['card_spotify']); + } + if (chunk['card_music'] != null) { + play_music(chunk['card_music']); } } else if (chunk is String) { fullResponse += chunk; @@ -505,7 +508,31 @@ class ChatController extends GetxController { } // 播放音乐 - void play(Map card) async { + void play_music(Map card) async { + try { + isPlay.value = false; + if (audiourl.value != card['url']) { + audiourl.value = ''; + await player.setUrl(card['url']); + audiourl.value = card['url']; + player.play(); + } else { + player.play(); + } + isPlay.value = true; + } catch (e) { + Logger.error('加载异常: $e'); + } + } + +// 播放音乐 + void pause_music() async { + await player.pause(); + isPlay.value = false; + } + +// 播放音乐 + void play_spotify(Map card) async { try { await _spotifService.initialize(); _spotifService.play(card['url'] as String); @@ -517,7 +544,7 @@ class ChatController extends GetxController { } // 暂停播放音乐 - void pause() async { + void pause_spotify() async { try { _spotifService.pause(); isPlay.value = false; diff --git a/lib/modules/chat/views/chat_music_card.dart b/lib/modules/chat/views/chat_music_card.dart index 5fcce956e..10a6ce757 100644 --- a/lib/modules/chat/views/chat_music_card.dart +++ b/lib/modules/chat/views/chat_music_card.dart @@ -5,10 +5,11 @@ import 'package:get/get.dart'; import '../controllers/chat_controller.dart'; class ChatMusicCard extends GetView { + final int type; final Map? data; final bool isDarkMode; - const ChatMusicCard(this.data, this.isDarkMode, {super.key}); + const ChatMusicCard(this.type, this.data, this.isDarkMode, {super.key}); @override Widget build(BuildContext context) { @@ -47,7 +48,15 @@ class ChatMusicCard extends GetView { controller.isPlay.value ? GestureDetector( onTap: () { - controller.pause(); + switch (type) { + case 0: + controller.pause_music(); + break; + case 1: + controller.pause_spotify(); + break; + default: + } }, child: Stack( alignment: Alignment.center, @@ -61,7 +70,15 @@ class ChatMusicCard extends GetView { ) : GestureDetector( onTap: () { - controller.play(data!); + switch (type) { + case 0: + controller.play_music(data!); + break; + case 1: + controller.play_spotify(data!); + break; + default: + } }, child: Container( width: 38.w, diff --git a/lib/modules/chat/views/chat_view.dart b/lib/modules/chat/views/chat_view.dart index 9f4864f0e..4d2bb2aa6 100644 --- a/lib/modules/chat/views/chat_view.dart +++ b/lib/modules/chat/views/chat_view.dart @@ -374,8 +374,11 @@ class ChatView extends GetView { if (message.meta?['card_weather'] != null) { box = WeatherDayCard(message.meta?['card_weather'], isDarkMode); } + if (message.meta?['card_music'] != null) { + box = ChatMusicCard(0, message.meta?['card_music'], isDarkMode); + } if (message.meta?['card_spotify'] != null) { - box = ChatMusicCard(message.meta?['card_spotify'], isDarkMode); + box = ChatMusicCard(1, message.meta?['card_spotify'], isDarkMode); } if (message.meta?['card_navigation'] != null) { box = ChatNavigationCard( diff --git a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt index 653ccdcef..8266a47d3 100644 --- a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt +++ b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt @@ -175,7 +175,7 @@ class OpenAIServicePlugin : FlutterPlugin, MethodCallHandler, StreamHandler { mainHandler.post { eventSink?.success(mapOf("type" to "functionCall", "content" to context,"meta" to meta.toString())) } - if (metaJsonObject.containsKey("card_spotify")) { + if (metaJsonObject.containsKey("card_spotify") || metaJsonObject.containsKey("card_music")) { mainHandler.post { eventSink?.success(mapOf("type" to "complete")) }