|
|
@ -1,6 +1,8 @@ |
|
|
import 'dart:async'; |
|
|
import 'dart:async'; |
|
|
import 'package:get/get.dart'; |
|
|
import 'package:get/get.dart'; |
|
|
import 'package:flutter/widgets.dart'; |
|
|
import 'package:flutter/widgets.dart'; |
|
|
|
|
|
import 'package:get_storage/get_storage.dart'; |
|
|
|
|
|
import '../../../data/services/speech_impl/voice_clone_tts_service.dart'; |
|
|
import '../models/message_model.dart'; |
|
|
import '../models/message_model.dart'; |
|
|
import '../../../core/utils/logger.dart'; |
|
|
import '../../../core/utils/logger.dart'; |
|
|
import '../../../data/services/volcano_ai_service.dart'; |
|
|
import '../../../data/services/volcano_ai_service.dart'; |
|
|
@ -15,10 +17,11 @@ import '../../../data/services/voice_interaction_service.dart'; |
|
|
class ChatController extends GetxController { |
|
|
class ChatController extends GetxController { |
|
|
// 服务 |
|
|
// 服务 |
|
|
final VolcanoAIService _aiService = Get.find<VolcanoAIService>(); |
|
|
final VolcanoAIService _aiService = Get.find<VolcanoAIService>(); |
|
|
final TtsService _ttsService = Get.find<TtsService>(); |
|
|
late TtsService _ttsService; |
|
|
final AsrService _asrService = Get.find<AsrService>(); |
|
|
final AsrService _asrService = Get.find<AsrService>(); |
|
|
final ChatHistoryService _historyService = Get.find<ChatHistoryService>(); |
|
|
final ChatHistoryService _historyService = Get.find<ChatHistoryService>(); |
|
|
final VoiceInteractionService _voiceInteractionService = Get.find<VoiceInteractionService>(); |
|
|
final VoiceInteractionService _voiceInteractionService = |
|
|
|
|
|
Get.find<VoiceInteractionService>(); |
|
|
|
|
|
|
|
|
// 添加ScrollController用于控制列表滚动 |
|
|
// 添加ScrollController用于控制列表滚动 |
|
|
final ScrollController scrollController = ScrollController(); |
|
|
final ScrollController scrollController = ScrollController(); |
|
|
@ -71,10 +74,10 @@ class ChatController extends GetxController { |
|
|
super.onInit(); |
|
|
super.onInit(); |
|
|
Logger.info('ChatController onInit'); |
|
|
Logger.info('ChatController onInit'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 从路由参数获取Agent信息 |
|
|
// 从路由参数获取Agent信息 |
|
|
final Map<String, dynamic> args = Get.arguments ?? {}; |
|
|
final Map<String, dynamic> args = Get.arguments ?? {}; |
|
|
final String agentId = args['agent'] ?? args['agentId'] ?? 'personal_assistant'; |
|
|
final String agentId = |
|
|
|
|
|
args['agent'] ?? args['agentId'] ?? 'personal_assistant'; |
|
|
|
|
|
|
|
|
// 获取Agent |
|
|
// 获取Agent |
|
|
final Agent? foundAgent = AgentProvider.getAgentById(agentId); |
|
|
final Agent? foundAgent = AgentProvider.getAgentById(agentId); |
|
|
@ -86,6 +89,16 @@ class ChatController extends GetxController { |
|
|
|
|
|
|
|
|
agent = foundAgent; |
|
|
agent = foundAgent; |
|
|
|
|
|
|
|
|
|
|
|
final GetStorage storage = GetStorage(); |
|
|
|
|
|
String timbre = storage.read('timbre') ?? '1'; |
|
|
|
|
|
|
|
|
|
|
|
if (timbre == '1') { |
|
|
|
|
|
_ttsService = Get.find<TtsService>(); |
|
|
|
|
|
} else { |
|
|
|
|
|
Get.put(VoiceCloneTtsService()); |
|
|
|
|
|
_ttsService = Get.find<VoiceCloneTtsService>(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
_ttsService.initialize(); |
|
|
_ttsService.initialize(); |
|
|
_asrService.initialize(); |
|
|
_asrService.initialize(); |
|
|
|
|
|
|
|
|
@ -130,7 +143,8 @@ class ChatController extends GetxController { |
|
|
/// 订阅VoiceInteractionService事件 |
|
|
/// 订阅VoiceInteractionService事件 |
|
|
void _subscribeToVoiceInteractionEvents() { |
|
|
void _subscribeToVoiceInteractionEvents() { |
|
|
if (_voiceInteractionService.eventStream != null) { |
|
|
if (_voiceInteractionService.eventStream != null) { |
|
|
_voiceInteractionSubscription = _voiceInteractionService.eventStream.listen((event) { |
|
|
_voiceInteractionSubscription = |
|
|
|
|
|
_voiceInteractionService.eventStream.listen((event) { |
|
|
if (event is RecognitionStartedEvent) { |
|
|
if (event is RecognitionStartedEvent) { |
|
|
// 收到recognitionStarted事件时,停止当前的AI交互、录音和TTS |
|
|
// 收到recognitionStarted事件时,停止当前的AI交互、录音和TTS |
|
|
_stopCurrentInteraction(); |
|
|
_stopCurrentInteraction(); |
|
|
@ -162,7 +176,8 @@ class ChatController extends GetxController { |
|
|
final assistantMsg = Message( |
|
|
final assistantMsg = Message( |
|
|
role: 'assistant', |
|
|
role: 'assistant', |
|
|
content: event.assistantMessage, |
|
|
content: event.assistantMessage, |
|
|
timestamp: DateTime.fromMillisecondsSinceEpoch(event.timestamp + 1), // 助手消息稍后一毫秒 |
|
|
timestamp: |
|
|
|
|
|
DateTime.fromMillisecondsSinceEpoch(event.timestamp + 1), // 助手消息稍后一毫秒 |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
// 防止消息重复 |
|
|
// 防止消息重复 |
|
|
@ -220,7 +235,6 @@ class ChatController extends GetxController { |
|
|
|
|
|
|
|
|
/// 滚动到列表底部方法,添加防抖功能 |
|
|
/// 滚动到列表底部方法,添加防抖功能 |
|
|
void _scrollToBottom() { |
|
|
void _scrollToBottom() { |
|
|
|
|
|
|
|
|
if (scrollController.hasClients && messages.isNotEmpty) { |
|
|
if (scrollController.hasClients && messages.isNotEmpty) { |
|
|
try { |
|
|
try { |
|
|
scrollController.animateTo( |
|
|
scrollController.animateTo( |
|
|
@ -278,7 +292,6 @@ class ChatController extends GetxController { |
|
|
); |
|
|
); |
|
|
messages.add(userMessage); |
|
|
messages.add(userMessage); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清空输入框 |
|
|
// 清空输入框 |
|
|
inputText.value = ''; |
|
|
inputText.value = ''; |
|
|
|
|
|
|
|
|
@ -356,7 +369,8 @@ class ChatController extends GetxController { |
|
|
|
|
|
|
|
|
// 只取最近的10条消息作为上下文 |
|
|
// 只取最近的10条消息作为上下文 |
|
|
final recentMessages = messages.where((m) => !m.isLoading).toList(); |
|
|
final recentMessages = messages.where((m) => !m.isLoading).toList(); |
|
|
final startIndex = recentMessages.length > 10 ? recentMessages.length - 10 : 0; |
|
|
final startIndex = |
|
|
|
|
|
recentMessages.length > 10 ? recentMessages.length - 10 : 0; |
|
|
|
|
|
|
|
|
for (int i = startIndex; i < recentMessages.length; i++) { |
|
|
for (int i = startIndex; i < recentMessages.length; i++) { |
|
|
final m = recentMessages[i]; |
|
|
final m = recentMessages[i]; |
|
|
@ -429,7 +443,6 @@ class ChatController extends GetxController { |
|
|
|
|
|
|
|
|
_voiceInteractionService.pauseVoiceInteraction(); |
|
|
_voiceInteractionService.pauseVoiceInteraction(); |
|
|
try { |
|
|
try { |
|
|
|
|
|
|
|
|
// 启动连续语音识别 |
|
|
// 启动连续语音识别 |
|
|
// 注意:在UI更新后,使用模拟波形动画替代实际麦克风输入的波形数据 |
|
|
// 注意:在UI更新后,使用模拟波形动画替代实际麦克风输入的波形数据 |
|
|
final recognitionStream = await _asrService.startContinuousRecognition(); |
|
|
final recognitionStream = await _asrService.startContinuousRecognition(); |
|
|
@ -694,7 +707,9 @@ class ChatController extends GetxController { |
|
|
return messages.any((m) => |
|
|
return messages.any((m) => |
|
|
m.role == message.role && |
|
|
m.role == message.role && |
|
|
m.content == message.content && |
|
|
m.content == message.content && |
|
|
(m.timestamp.millisecondsSinceEpoch - message.timestamp.millisecondsSinceEpoch).abs() < 5000 |
|
|
(m.timestamp.millisecondsSinceEpoch - |
|
|
); |
|
|
message.timestamp.millisecondsSinceEpoch) |
|
|
|
|
|
.abs() < |
|
|
|
|
|
5000); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|