From e8de3763d05cde780b2c2f66f1a1574e379de838 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Wed, 23 Apr 2025 16:21:56 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/controllers/chat_controller.dart | 3 +- .../open_ai_service/MCPClient.kt | 2 +- .../spotify_sdk/SpotifySdkService.kt | 41 +++---------------- 3 files changed, 9 insertions(+), 37 deletions(-) diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 4ce3bf80b..997ef0fbb 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -112,8 +112,9 @@ class ChatController extends GetxController { // 获取Agent final Agent? foundAgent = AgentProvider.getAgentById(agentId); if (foundAgent == null) { - Logger.error('无法找到Agent: $agentId'); Get.back(); + Logger.error('无法找到Agent: $agentId'); + return; } diff --git a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/MCPClient.kt b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/MCPClient.kt index b43013e0a..e2796ee85 100644 --- a/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/MCPClient.kt +++ b/local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/MCPClient.kt @@ -168,7 +168,7 @@ class MCPSubClient( private fun processToolsList(toolsResult: ListToolsResult?) { try { // 将MCP工具列表转换为ToolUnion列表 - tools = toolsResult?.tools?.filter { tool -> config.tools == null || config.tools.contains(tool.name) == true + tools = toolsResult?.tools?.filter { tool -> config.tools.isNullOrEmpty() || config.tools.contains(tool.name) }?.map { tool -> // 转换为ToolUnion格式 ToolUnion.ofTool( diff --git a/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt b/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt index 9c97e7545..b5b551219 100644 --- a/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt +++ b/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt @@ -55,8 +55,7 @@ class SpotifySdkService(private val context: Context? = null) { private var spotifyAppRemote: SpotifyAppRemote? = null private var playerApi: PlayerApi? = null - //-- Method implementations - private fun connectToSpotify(clientId: String?, redirectUrl: String?, result: MethodChannel.Result) { + public fun connectToSpotify(clientId: String?, redirectUrl: String?, result: MethodChannel.Result) { if (clientId.isNullOrBlank() || redirectUrl.isNullOrBlank()) { result.error(errorConnecting, "client id or redirectUrl are not set or have invalid format", "") @@ -162,7 +161,7 @@ class SpotifySdkService(private val context: Context? = null) { } } - private fun getAccessToken(clientId: String?, redirectUrl: String?, scope: String?, result: MethodChannel.Result) { + public fun getAccessToken(clientId: String?, redirectUrl: String?, scope: String?, result: MethodChannel.Result) { if (applicationActivity == null) { throw IllegalStateException("getAccessToken needs a foreground activity") } @@ -172,8 +171,6 @@ class SpotifySdkService(private val context: Context? = null) { } else { //Convert String? scope to Array. Delimiter set as comma "," val scopeArray = scope?.split(",")?.toTypedArray() -// methodConnectToSpotify.checkAndSetPendingOperation(result) - val builder = AuthorizationRequest.Builder( clientId, AuthorizationResponse.Type.TOKEN, @@ -190,20 +187,9 @@ class SpotifySdkService(private val context: Context? = null) { } } - private fun disconnectFromSpotify(result: MethodChannel.Result) { + public fun disconnectFromSpotify(result: MethodChannel.Result) { if (spotifyAppRemote != null && spotifyAppRemote!!.isConnected) { SpotifyAppRemote.disconnect(spotifyAppRemote) - - // emit connection terminated event -// connStatusEventChannel( -// ConnectionStatusChannel.ConnectionEvent( -// false, -// "Successfully disconnected from Spotify.", -// null, -// null -// ) -// ) - // method success result.success(true) } else if (!spotifyAppRemote!!.isConnected) { result.error(errorDisconnecting, "could not disconnect spotify remote", "you are not connected, no need to disconnect") @@ -212,16 +198,7 @@ class SpotifySdkService(private val context: Context? = null) { } } - private fun play(spotifyUri: String?){ -// if (playerApi != null && !spotifyUri.isNullOrBlank()) { -// playerApi.play(spotifyUri) -// .setResultCallback { result.success(true) } -// .setErrorCallback { throwable -> result.error(errorPlay, "error when playing uri: $spotifyUri", throwable.toString()) } -// } else if (spotifyUri.isNullOrBlank()) { -// result.error(errorPlay, "spotifyUri has invalid format or is not set", "") -// } else { -// spotifyRemoteAppNotSetError() -// } + public fun play(spotifyUri: String?){ if (playerApi != null && !spotifyUri.isNullOrBlank()) { playerApi!!.play(spotifyUri) } else if (spotifyUri.isNullOrBlank()) { @@ -230,14 +207,8 @@ class SpotifySdkService(private val context: Context? = null) { } } - private fun pause(){ -// if (playerApi != null) { -// playerApi.pause() -// .setResultCallback { result.success(true) } -// .setErrorCallback { throwable -> result.error(errorPause, "error when pausing", throwable.toString()) } -// } else { -// spotifyRemoteAppNotSetError() -// } + + public fun pause(){ if (playerApi != null) { playerApi!!.pause() .setResultCallback {} From eac10a50c05f2916036cbb1957a61dd614cddfc6 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Wed, 23 Apr 2025 17:01:41 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=81=8A=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/controllers/chat_controller.dart | 2 ++ .../views/animated_gradient_background.dart | 6 ++++- lib/modules/chat/views/chat_view.dart | 17 ++++++++----- local_plugins/opus/example/lib/main.dart | 25 +++++++++++-------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 4ce3bf80b..477393d82 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -586,6 +586,8 @@ class ChatController extends GetxController { if (isHoldSpeak.value) return; _voiceInteractionService.pauseVoiceInteraction(); + // 中断当前响应 + _interruptCurrentResponse("发送新消息,中断当前响应"); try { final recognitionStream = await _asrService.startContinuousRecognition(); diff --git a/lib/modules/chat/views/animated_gradient_background.dart b/lib/modules/chat/views/animated_gradient_background.dart index 181295cea..3a96b8bc5 100644 --- a/lib/modules/chat/views/animated_gradient_background.dart +++ b/lib/modules/chat/views/animated_gradient_background.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; class AnimatedGradientBackground extends StatefulWidget { - const AnimatedGradientBackground({super.key}); + final Widget child; + + const AnimatedGradientBackground(this.child, {super.key}); @override State createState() => @@ -58,8 +60,10 @@ class _AnimatedGradientBackgroundState extends State end: _endAnimation.value!, ), ), + child: child, ); }, + child: widget.child, ); } } diff --git a/lib/modules/chat/views/chat_view.dart b/lib/modules/chat/views/chat_view.dart index ed904d4e6..c79c51b20 100644 --- a/lib/modules/chat/views/chat_view.dart +++ b/lib/modules/chat/views/chat_view.dart @@ -513,18 +513,23 @@ class ChatView extends GetView { // 构建语音输入面板 Widget _buildVoiceInputPanel(bool isDarkMode) { - return Container( - decoration: BoxDecoration( - color: isDarkMode ? AppColors.cardBackground : Colors.white, - ), - child: SafeArea( + return AnimatedGradientBackground( + SafeArea( child: Column( children: [ Row( children: [], ), Expanded( - child: AnimatedGradientBackground(), + child: Container( + width: 100.w, + height: 100.w, + decoration: BoxDecoration( + color: + isDarkMode ? Colors.white.withOpacity(0.1) : Colors.white, + shape: BoxShape.circle, + ), + ), ), SizedBox( height: 80.h, diff --git a/local_plugins/opus/example/lib/main.dart b/local_plugins/opus/example/lib/main.dart index 19730f7fe..a73c5a09a 100644 --- a/local_plugins/opus/example/lib/main.dart +++ b/local_plugins/opus/example/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:opus/opus.dart'; + +import '../../lib/opus.dart'; void main() { runApp(const OpusExampleApp()); @@ -92,13 +93,13 @@ class _OpusExamplePageState extends State { const int frequency = 440; // 440Hz - A4音符 const int durationMs = 20; // 20ms,按照常规frameSize=960 const int frameSize = 960; // 对应20ms@48kHz - + // 创建PCM数据缓冲区,16位有符号整数,每采样2字节,双声道 final int samplesToGenerate = (sampleRate * durationMs / 1000).round(); final int bufferSize = samplesToGenerate * channels * 2; // 2字节/样本 - + final byteBuffer = ByteData(bufferSize); - + // 生成正弦波 for (int i = 0; i < samplesToGenerate; i++) { // 计算当前时间点 @@ -107,18 +108,17 @@ class _OpusExamplePageState extends State { final double amplitude = sin(2 * 3.14159265359 * frequency * t); // 缩放到16位有符号整数范围 (-32768 to 32767) final int sample = (amplitude * 32767).round(); - + // 为所有声道写入相同的值 for (int channel = 0; channel < channels; channel++) { final int offset = (i * channels + channel) * 2; byteBuffer.setInt16(offset, sample, Endian.little); } } - + _samplePcmData = Uint8List.fromList( - List.generate(bufferSize, (index) => byteBuffer.getUint8(index)) - ); - + List.generate(bufferSize, (index) => byteBuffer.getUint8(index))); + setState(() { _statusMessage = '已创建${_samplePcmData!.length}字节测试PCM数据'; }); @@ -272,6 +272,9 @@ class _OpusExamplePageState extends State { String _formatBytes(Uint8List data) { final length = data.length > 16 ? 16 : data.length; - return data.sublist(0, length).map((e) => e.toRadixString(16).padLeft(2, '0')).join(' '); + return data + .sublist(0, length) + .map((e) => e.toRadixString(16).padLeft(2, '0')) + .join(' '); } -} \ No newline at end of file +} From c80a7c8c5b90071b4c143725476f5a3c6037f3cd Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Wed, 23 Apr 2025 17:23:20 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E8=AF=AD=E9=9F=B3=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deepsound/VoiceInteractionHandler.kt | 19 ++++++- .../chat/controllers/chat_controller.dart | 7 +-- ...otifySdkService.kt => SpotifySdkHelper.kt} | 51 +++++++------------ 3 files changed, 40 insertions(+), 37 deletions(-) rename local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/{SpotifySdkService.kt => SpotifySdkHelper.kt} (81%) diff --git a/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt b/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt index 881b9dc84..f0a7d6d86 100644 --- a/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt +++ b/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt @@ -12,6 +12,7 @@ import com.yunqiinnovation.azure_speech.AzureAsrHelper import com.yunqiinnovation.azure_speech.AzureTtsHelper import com.yunqiinnovation.open_ai_service.OpenAIService import com.yunqiinnovation.open_ai_service.SystemFunctionHandler +import de.minimalme.spotify_sdk.SpotifySdkHelper /** @@ -38,7 +39,9 @@ class VoiceInteractionHandler( // OpenAI服务 private val openAIService = OpenAIService(context.applicationContext) - + + private var spotifyHelper: SpotifySdkHelper? = null + // 当前用户输入 private var currentUserInput = "" @@ -314,7 +317,19 @@ class VoiceInteractionHandler( notifyStateChanged() } } - + + /* + * 播放音乐。Spotify + * */ + fun playSpotifyMusic(url:String){ + if (spotifyHelper == null){ + spotifyHelper = SpotifySdkHelper(context).apply { + initialize(spotifyclientid,spotifyRedirectUrl) + } + } + spotifyHelper?.play(url) + } + /** * 播放AI回复 */ diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 997ef0fbb..8bd00e873 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -414,7 +414,7 @@ class ChatController extends GetxController { if (chunk['card_spotify'] != null) { play(chunk['card_spotify']); } - } else { + } else if (chunk is String) { fullResponse += chunk; // 更新中间状态的消息内容 @@ -422,7 +422,8 @@ class ChatController extends GetxController { // 如果TTS启用,使用流式处理发送到TTS if (isTtsEnabled.value) { - _ttsService.speakStream(chunk); + String str = chunk.replaceAll('*', ''); + _ttsService.speakStream(str); } } }, @@ -456,7 +457,7 @@ class ChatController extends GetxController { final List> messageHistory = []; // 只取最近的10条消息作为上下文 - final recentMessages = messages.where((m) => !m.isIntermediate).toList(); + final recentMessages = messages.where((m) => m.role == "user").toList(); final startIndex = recentMessages.length > 10 ? recentMessages.length - 10 : 0; diff --git a/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt b/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkHelper.kt similarity index 81% rename from local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt rename to local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkHelper.kt index b5b551219..7ae21f8fe 100644 --- a/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkService.kt +++ b/local_plugins/spotify_sdk/android/src/main/kotlin/de/minimalme/spotify_sdk/SpotifySdkHelper.kt @@ -2,7 +2,6 @@ package de.minimalme.spotify_sdk import android.app.Activity import android.content.Context -import android.content.Intent import android.util.Log import com.spotify.android.appremote.api.ConnectionParams import com.spotify.android.appremote.api.Connector @@ -20,45 +19,33 @@ import com.spotify.android.appremote.api.error.UserNotAuthorizedException import com.spotify.sdk.android.auth.AuthorizationClient import com.spotify.sdk.android.auth.AuthorizationRequest import com.spotify.sdk.android.auth.AuthorizationResponse -import de.minimalme.spotify_sdk.subscriptions.CapabilitiesChannel -import de.minimalme.spotify_sdk.subscriptions.ConnectionStatusChannel -import de.minimalme.spotify_sdk.subscriptions.PlayerContextChannel -import de.minimalme.spotify_sdk.subscriptions.PlayerStateChannel -import de.minimalme.spotify_sdk.subscriptions.UserStatusChannel -import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.embedding.engine.plugins.activity.ActivityAware -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding -import io.flutter.plugin.common.EventChannel -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.PluginRegistry -import kotlinx.event.SetEvent -import kotlinx.event.event -class SpotifySdkService(private val context: Context? = null) { + +class SpotifySdkHelper(private val context: Context? = null) { // application context private var applicationContext : Context? = null private var applicationActivity : Activity? = null // method channel - private lateinit var methodChannel : MethodChannel - private val channelName = "spotify_sdk" - private val loggingTag = "spotify_sdk" + private val loggingTag = "spotify_sdk" - private val errorConnecting = "errorConnecting" - private val errorDisconnecting = "errorDisconnecting" private val errorConnection = "errorConnection" - private val errorAuthenticationToken = "authenticationTokenError" private val requestCodeAuthentication = 1337 private var spotifyAppRemote: SpotifyAppRemote? = null private var playerApi: PlayerApi? = null - public fun connectToSpotify(clientId: String?, redirectUrl: String?, result: MethodChannel.Result) { + fun initialize(clientId: String, redirectUrl: String): Boolean { + getAccessToken(clientId,redirectUrl,""); + connectToSpotify(clientId,redirectUrl) + return true; + } + + public fun connectToSpotify(clientId: String?, redirectUrl: String?) { if (clientId.isNullOrBlank() || redirectUrl.isNullOrBlank()) { - result.error(errorConnecting, "client id or redirectUrl are not set or have invalid format", "") +// result.error(errorConnecting, "client id or redirectUrl are not set or have invalid format", "") } else { val connectionParams = ConnectionParams.Builder(clientId) .setRedirectUri(redirectUrl) @@ -74,7 +61,7 @@ class SpotifySdkService(private val context: Context? = null) { initiallyConnected = true Log.i(loggingTag, "App Remote successfully connected") - result.success(true) +// result.success(true) } override fun onFailure(throwable: Throwable) { @@ -154,20 +141,20 @@ class SpotifySdkService(private val context: Context? = null) { // ) } else { // throw exception as the connect method - result.error(errorCode, errorMessage, errorDetails) +// result.error(errorCode, errorMessage, errorDetails) } } }) } } - public fun getAccessToken(clientId: String?, redirectUrl: String?, scope: String?, result: MethodChannel.Result) { + public fun getAccessToken(clientId: String?, redirectUrl: String?, scope: String?) { if (applicationActivity == null) { throw IllegalStateException("getAccessToken needs a foreground activity") } if (clientId.isNullOrBlank() || redirectUrl.isNullOrBlank()) { - result.error(errorConnecting, "client id or redirectUrl are not set or have invalid format", "") +// result.error(errorConnecting, "client id or redirectUrl are not set or have invalid format", "") } else { //Convert String? scope to Array. Delimiter set as comma "," val scopeArray = scope?.split(",")?.toTypedArray() @@ -187,14 +174,14 @@ class SpotifySdkService(private val context: Context? = null) { } } - public fun disconnectFromSpotify(result: MethodChannel.Result) { + public fun disconnectFromSpotify() { if (spotifyAppRemote != null && spotifyAppRemote!!.isConnected) { SpotifyAppRemote.disconnect(spotifyAppRemote) - result.success(true) +// result.success(true) } else if (!spotifyAppRemote!!.isConnected) { - result.error(errorDisconnecting, "could not disconnect spotify remote", "you are not connected, no need to disconnect") +// result.error(errorDisconnecting, "could not disconnect spotify remote", "you are not connected, no need to disconnect") } else { - result.error(errorDisconnecting, "could not disconnect spotify remote", "spotifyAppRemote is not set") +// result.error(errorDisconnecting, "could not disconnect spotify remote", "spotifyAppRemote is not set") } } From 84e4386e47b34534ad1e0f05c93f05bc3079e6b2 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Wed, 23 Apr 2025 17:31:26 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9C=87=E5=8A=A8?= =?UTF-8?q?=E5=8F=8D=E9=A6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/AndroidManifest.xml | 1 + lib/modules/chat/controllers/chat_controller.dart | 2 ++ pubspec.yaml | 1 + 3 files changed, 4 insertions(+) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 269ff6b20..8b3012b08 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -49,6 +49,7 @@ + Date: Wed, 23 Apr 2025 18:28:26 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8C=89=E4=BD=8F?= =?UTF-8?q?=E8=AF=B4=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/chat/controllers/chat_controller.dart | 5 ++++- lib/modules/chat/views/chat_view.dart | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 89a576ace..e29d580c3 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -620,13 +620,16 @@ class ChatController extends GetxController { _recognitionSubscription?.cancel(); _recognitionSubscription = null; + String sendText = ''; + final intermediateIndex = messages.indexWhere((m) => m.isIntermediate && m.role == 'user'); if (intermediateIndex >= 0) { + sendText = messages[intermediateIndex].content; messages.removeAt(intermediateIndex); } - sendMessage(finalResult); + sendMessage(sendText); recognizedText.value = ''; finalResult = ''; diff --git a/lib/modules/chat/views/chat_view.dart b/lib/modules/chat/views/chat_view.dart index c79c51b20..157536943 100644 --- a/lib/modules/chat/views/chat_view.dart +++ b/lib/modules/chat/views/chat_view.dart @@ -522,8 +522,8 @@ class ChatView extends GetView { ), Expanded( child: Container( - width: 100.w, - height: 100.w, + width: 200.w, + height: 200.w, decoration: BoxDecoration( color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.white, From c8f15f9ac933c9dadb01ebc3bb65a2d811904384 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Wed, 23 Apr 2025 18:55:32 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/services/spotify_service.dart | 12 +++++----- .../chat/controllers/chat_controller.dart | 22 ++++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/data/services/spotify_service.dart b/lib/data/services/spotify_service.dart index 05d439e18..30adbfe97 100644 --- a/lib/data/services/spotify_service.dart +++ b/lib/data/services/spotify_service.dart @@ -20,15 +20,17 @@ class SpotifService { /// 初始化OpenAI服务 Future initialize() async { if (!isInitialized) { - await getAccessToken(); - await connectToSpotifyRemote(); - isInitialized = true; final _env = _storage.read("ENV") as Map; SPOTIFY_CLIENT_ID = _env['SPOTIFY_CLIENT_ID'] ?? ''; SPOTIFY_REDIRECT_URL = _env['SPOTIFY_REDIRECT_URL'] ?? ''; - printInfo(info: "SpotifService----------- initialize"); - } + printInfo( + info: + "SpotifService----------- initialize SPOTIFY_CLIENT_ID:${SPOTIFY_CLIENT_ID} SPOTIFY_REDIRECT_URL:${SPOTIFY_REDIRECT_URL}"); + await getAccessToken(); + await connectToSpotifyRemote(); + isInitialized = true; + } return true; } diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 180e44e2f..a17b22173 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -403,13 +403,18 @@ class ChatController extends GetxController { messages: messageHistory, systemPrompt: agent.systemPrompt, ); - + Logger.info( + 'liwei----------- 发送用户提问 ${text}', + ); // 订阅响应流 _aiResponseSubscription = responseStream.listen( (chunk) { if (_shouldCancelAiResponse) return; Logger.info('chat ${chunk}'); if (chunk is Map) { + Logger.info( + 'liwei-----------收到卡片消息 ${chunk}', + ); _updateIntermediateMessage(meta: chunk); if (chunk['card_spotify'] != null) { play(chunk['card_spotify']); @@ -428,6 +433,9 @@ class ChatController extends GetxController { } }, onDone: () { + Logger.info( + 'liwei-----------结束当前问题 ${text}', + ); if (_shouldCancelAiResponse) return; // 完成响应,将isIntermediate设为false @@ -457,9 +465,13 @@ class ChatController extends GetxController { final List> messageHistory = []; // 只取最近的10条消息作为上下文 - final recentMessages = messages.where((m) => m.role == "user").toList(); + final recentMessages = messages.where((m) => !m.isIntermediate).toList(); final startIndex = recentMessages.length > 10 ? recentMessages.length - 10 : 0; + messageHistory.add({ + 'role': 'user', + 'content': '我当前所在城市是$_city,我的经纬度是$_latLng', + }); for (int i = startIndex; i < recentMessages.length; i++) { final m = recentMessages[i]; @@ -467,12 +479,6 @@ class ChatController extends GetxController { 'role': m.role, 'content': m.content, }); - if (i == recentMessages.length - 2) { - messageHistory.add({ - 'role': 'user', - 'content': '当需要获取我的位置时,我当前在$_city,我的经纬度是$_latLng', - }); - } } return messageHistory; From db8d9e49c616f6353d380e989cfa0f9c76736a1c Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Thu, 24 Apr 2025 11:07:44 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deepsound/VoiceInteractionHandler.kt | 12 ++++++++++++ .../buildOutputCleanup/buildOutputCleanup.lock | Bin 17 -> 17 bytes .../.gradle/buildOutputCleanup/cache.properties | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt b/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt index f0a7d6d86..c31e6c319 100644 --- a/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt +++ b/android/app/src/main/kotlin/com/yunqiinnovation/deepsound/VoiceInteractionHandler.kt @@ -13,6 +13,7 @@ import com.yunqiinnovation.azure_speech.AzureTtsHelper import com.yunqiinnovation.open_ai_service.OpenAIService import com.yunqiinnovation.open_ai_service.SystemFunctionHandler import de.minimalme.spotify_sdk.SpotifySdkHelper +import kotlinx.serialization.json.JsonObject /** @@ -274,6 +275,17 @@ class VoiceInteractionHandler( override fun onFunctionCall(call: JSONObject) { FileLogger.d(TAG, "processWithOpenAI 收到函数调用请求: ${call.getString("name")}") +// Log.e("OpenAIServicePlugin", "context:${call.toString()}") +// val context = call["context"] +// if (call.has("meta")) { +// val meta = call.get("meta") +// val metaJsonObject: JsonObject = meta as JsonObject +// Log.e("OpenAIServicePlugin", "工具调用结果 context:${context} meta:${meta.toString()}") +// if (metaJsonObject.containsKey("card_spotify")) { +// val card_spotify:JsonObject = metaJsonObject.get("card_spotify") as JsonObject +// playSpotifyMusic(card_spotify.get("name") as String) +// } +// } } } ) diff --git a/local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/local_plugins/opus/.gradle/buildOutputCleanup/buildOutputCleanup.lock index fd40a1b74af7568dfb82c03afb8da2f181bd8ea4..a2d8b75c89b15fd04945a85eb2b33d6443b8fcc1 100644 GIT binary patch literal 17 TcmZQ}Dp$CADo{Lz0Ror-DFy>W literal 17 TcmZQ}Dp$CADo{Lz0Ror+DFp*U diff --git a/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties b/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties index 8a9b74646..816b483f3 100644 --- a/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties +++ b/local_plugins/opus/.gradle/buildOutputCleanup/cache.properties @@ -1,2 +1,2 @@ -#Tue Apr 15 09:36:50 IST 2025 -gradle.version=8.10 +#Thu Apr 24 10:52:53 CST 2025 +gradle.version=8.9