import 'dart:async'; import 'package:get/get.dart'; import 'package:flutter/widgets.dart'; import '../../core/utils/logger.dart'; import '../providers/agent_provider.dart'; import '../models/agent.dart'; import '../../modules/chat/controllers/chat_controller.dart'; import '../../modules/chat/models/message_model.dart'; import 'volcano_asr_api_service.dart'; import 'volcano_ai_service.dart'; import 'azure_flutter_tts_service.dart'; import 'chat_history_service.dart'; /// 后台代理服务,用于在应用处于后台时处理AI交互 class BackgroundAgentService extends GetxService { // 单例实例 static BackgroundAgentService? _instance; // 单例工厂方法 factory BackgroundAgentService() { _instance ??= BackgroundAgentService._internal(); return _instance!; } // 私有构造函数 BackgroundAgentService._internal() { Logger.info('BackgroundAgentService 已创建'); } // 服务实例 final VolcanoAsrApiService _asrService = Get.find(); final VolcanoAIService _aiService = Get.find(); final AzureFlutterTtsService _ttsService = Get.find(); final ChatHistoryService _historyService = Get.find(); // 状态控制 // isProcessing: 表示整个代理交互会话是否处于活跃状态(包括语音识别、AI处理和TTS播放) final RxBool isProcessing = false.obs; final RxString recognizedText = ''.obs; // 流式响应控制 StreamSubscription? _recognitionSubscription; StreamSubscription? _aiResponseSubscription; // 定时器,用于检测无活动超时 Timer? _inactivityTimer; // 当前处理的Agent Agent? _currentAgent; // 本地消息历史备份 final List> _localMessageHistory = []; // 获取消息历史 - 优先从ChatController获取,否则使用本地存储 List> get messageHistory { if (Get.isRegistered()) { final chatController = Get.find(); if (chatController.agent?.id == 'personal_assistant') { return chatController.messages.map((m) => { 'role': m.role, 'content': m.content, }).toList(); } } if (_localMessageHistory.isEmpty) { _loadChatHistory(); } return _localMessageHistory; } // 语音识别是否活跃 bool get isListening => _recognitionSubscription != null; // TTS是否正在播放 bool get isTtsSpeaking => _ttsService.isActuallyPlaying(); @override void onClose() { _cleanupResources(); super.onClose(); } /// 清理所有资源 void _cleanupResources() { _recognitionSubscription?.cancel(); _aiResponseSubscription?.cancel(); if (_ttsService.isActuallyPlaying()) { _ttsService.stop(); } if (isListening) { _asrService.stopRecognition(); } _inactivityTimer?.cancel(); } /// 开始代理交互 Future startAgentInteraction(String agentId) async { // 防止重复处理 if (isProcessing.value) { Logger.warning('已经在处理交互,忽略此次请求'); return; } // 先说"我在听" _ttsService.speak("我在!"); isProcessing.value = true; try { // 获取Agent _currentAgent = AgentProvider.getAgentById(agentId); if (_currentAgent == null) { Logger.error('无法获取Agent: $agentId'); isProcessing.value = false; return; } // 加载该Agent的聊天历史 _loadChatHistory(); // 启动语音识别 await _startVoiceRecognition(); // 启动无活动定时器 _startInactivityTimer(); } catch (e) { Logger.error('启动代理交互失败', e); isProcessing.value = false; } } /// 停止语音识别 Future _stopVoiceRecognition() async { if (!isListening) return; await _recognitionSubscription?.cancel(); _recognitionSubscription = null; _asrService.stopRecognition(); recognizedText.value = ''; } /// 开始语音识别 Future _startVoiceRecognition() async { if (isListening) return; try { final success = await _asrService.startRecognition(); if (success) { _recognitionSubscription = _asrService.recognitionStream.listen( (event) { switch (event.type) { case RecognitionEventType.recognizing: if (event.text.isEmpty) return; recognizedText.value = event.text; Logger.info('处理语音识别中间结果:${event.text}'); // 检测到用户说话时中断当前响应 if (_ttsService.isActuallyPlaying() || _aiResponseSubscription != null) { _interruptCurrentResponse("检测到用户开始讲话,中断当前响应"); } break; case RecognitionEventType.finalResult: if (event.text.isEmpty) return; recognizedText.value = event.text; Logger.info('处理语音识别最终结果:${event.text}'); _processRecognizedText(event.text); recognizedText.value = ''; break; case RecognitionEventType.error: Logger.info('语音识别错误: ${event.error}'); stopInteraction(); break; default: break; } }, onError: (error) { Logger.info('语音识别错误:$error'); stopInteraction(); }, ); } else { Logger.error('启动语音识别失败'); } } catch (e) { Logger.error('启动语音识别失败', e); isProcessing.value = false; } } /// 中断当前响应 void _interruptCurrentResponse(String reason) { Logger.info(reason); if (_ttsService.isActuallyPlaying()) { _ttsService.stop(); } if (_aiResponseSubscription != null) { _aiResponseSubscription!.cancel(); _aiResponseSubscription = null; Logger.info('已中断AI响应流和TTS播放'); } } /// 处理识别到的文本 Future _processRecognizedText(String text) async { if (text.trim().isEmpty || _currentAgent == null) return; try { // 中断任何正在进行的响应 _interruptCurrentResponse("处理新的用户输入,中断当前响应"); // 添加用户消息到历史记录 _addMessageToHistory('user', text); String fullResponse = ''; // 获取AI响应流 final responseStream = _aiService.sendMessageStream( messages: messageHistory, systemPrompt: _currentAgent!.systemPrompt, ); // 订阅响应流 _aiResponseSubscription = responseStream.listen( (chunk) { fullResponse += chunk; _ttsService.speak(chunk); _resetInactivityTimer(); }, onDone: () { _addMessageToHistory('assistant', fullResponse); _aiResponseSubscription = null; }, onError: (error) { Logger.error('AI响应错误', error); const errorMessage = '抱歉,我遇到了一些问题,无法回应您的请求。'; _ttsService.speak(errorMessage); _addMessageToHistory('assistant', errorMessage); _aiResponseSubscription = null; }, ); } catch (e) { Logger.error('处理识别文本失败', e); const errorMessage = '抱歉,我遇到了一些问题,无法回应您的请求。'; _ttsService.speak(errorMessage); _addMessageToHistory('assistant', errorMessage); } } /// 重新启动语音识别 Future _restartVoiceRecognition() async { await _stopVoiceRecognition(); await Future.delayed(Duration(milliseconds: 500)); await _startVoiceRecognition(); } /// 添加消息到历史记录 void _addMessageToHistory(String role, String content) { // 添加到本地历史记录 _localMessageHistory.add({ 'role': role, 'content': content, }); // 保持本地历史记录不超过10条消息 if (_localMessageHistory.length > 10) { _localMessageHistory.removeAt(0); } // 同步消息到ChatController或保存到本地存储 if (Get.isRegistered()) { final chatController = Get.find(); if (chatController.agent?.id == 'personal_assistant') { chatController.addMessage(Message( role: role, content: content, timestamp: DateTime.now(), )); } } else { _saveChatHistory(); } } // 加载聊天历史 void _loadChatHistory() { if (_currentAgent == null) return; try { final messages = _historyService.loadHistory(_currentAgent!.id); _localMessageHistory.clear(); for (final message in messages) { _localMessageHistory.add({ 'role': message.role, 'content': message.content, }); } } catch (e) { Logger.error('加载聊天历史记录失败', e); } } // 保存聊天历史 void _saveChatHistory() { if (_currentAgent == null) return; try { final messages = _localMessageHistory.map((m) => Message( role: m['role']!, content: m['content']!, timestamp: DateTime.now(), )).toList(); _historyService.saveHistory(_currentAgent!.id, messages); } catch (e) { Logger.error('保存聊天历史记录失败', e); } } /// 启动无活动定时器 void _startInactivityTimer() { _inactivityTimer?.cancel(); _inactivityTimer = Timer(Duration(seconds: 30), () { if (!_ttsService.isActuallyPlaying() && isProcessing.value) { Logger.info('检测到30秒内无活动,停止语音识别'); stopInteraction(); } }); } /// 重置无活动定时器 void _resetInactivityTimer() { if (_inactivityTimer != null) { _inactivityTimer!.cancel(); _startInactivityTimer(); } } /// 响应新的媒体事件(双击媒体按钮) Future respondToNewMediaEvent() async { _ttsService.speak("我在!"); if (!isListening) { await _restartVoiceRecognition(); } _resetInactivityTimer(); } /// 停止当前交互 Future stopInteraction() async { try { _saveChatHistory(); _cleanupResources(); isProcessing.value = false; _currentAgent = null; Logger.info('已停止后台代理交互'); } catch (e) { Logger.error('停止交互失败', e); } } }