6 changed files with 337 additions and 441 deletions
@ -0,0 +1,302 @@ |
|||
import 'dart:convert'; |
|||
|
|||
import 'package:get/get.dart'; |
|||
import 'package:get_storage/get_storage.dart'; |
|||
import 'package:http/http.dart' as http; |
|||
|
|||
import '../../../core/utils/logger.dart'; |
|||
import '../../../core/utils/synchrodata.dart'; |
|||
import '../../models/appconfig.dart'; |
|||
import '../db/sqflite_api.dart'; |
|||
import '../deapsound_ai_service.dart'; |
|||
import 'meeting_upload_service.dart'; |
|||
|
|||
class MeetingTaskService extends GetxService { |
|||
final GetStorage _storage = GetStorage(); |
|||
|
|||
MeetingUploadService get _uploadService => Get.find<MeetingUploadService>(); |
|||
|
|||
RxList taskList = [].obs; |
|||
|
|||
bool _isTask = false; |
|||
int _handled = 0; |
|||
|
|||
String _systemPrompt = ''; |
|||
String _userId = ''; |
|||
|
|||
final String _appid = '2316081933'; |
|||
final String _token = 'mcJTh6OelBqU_L78lgGd77Nyrc_-5-En'; |
|||
final String _cluster = 'volc_auc_common_flash'; |
|||
final String _serviceUrl = 'https://openspeech.bytedance.com/api/v1/auc'; |
|||
Map<String, String> _headers = {}; |
|||
|
|||
RxList textList = [].obs; |
|||
String allText = ''; |
|||
|
|||
@override |
|||
void onInit() { |
|||
super.onInit(); |
|||
_headers = { |
|||
'Authorization': 'Bearer; $_token', |
|||
'Content-Type': 'application/json', |
|||
}; |
|||
_getAgent(); |
|||
_getTaskList(); |
|||
} |
|||
|
|||
void _getAgent() async { |
|||
Map userInfo = _storage.read("user_info"); |
|||
_userId = userInfo['user']['uid']; |
|||
_systemPrompt = AppConfig.agentsystemPrompt("meet_assistant") ?? ''; |
|||
} |
|||
|
|||
void _getTaskList() { |
|||
taskList.value = _storage.read("meeting_task_list") ?? []; |
|||
_executeTask(); |
|||
} |
|||
|
|||
Future<void> addTask(int id, String audiourl, String taskid) async { |
|||
if (audiourl.isEmpty) { |
|||
Map uploadData = _uploadService.uploadList.firstWhere( |
|||
(element) => element['id'] == id, |
|||
orElse: () => {}, |
|||
); |
|||
if (uploadData.isNotEmpty) { |
|||
if (uploadData['audiourl'].isEmpty) { |
|||
uploadData['isTask'] = true; |
|||
} else { |
|||
await addTaskList(id, uploadData['audiourl'], taskid); |
|||
} |
|||
} |
|||
} else { |
|||
await addTaskList(id, audiourl, taskid); |
|||
} |
|||
} |
|||
|
|||
Future<void> addTaskList(int id, String audiourl, String taskId) async { |
|||
if (taskId.isEmpty) { |
|||
taskId = await _submitTask(audiourl); |
|||
} |
|||
await SqfliteApi.editMeeting(id, {'tasktype': 1, 'taskid': taskId}); |
|||
taskList.add({ |
|||
'id': id, |
|||
'taskid': taskId, |
|||
'tasktype': 1, |
|||
}); |
|||
_storage.write("meeting_task_list", taskList); |
|||
_executeTask(); |
|||
} |
|||
|
|||
void _executeTask() async { |
|||
if (_isTask) return; |
|||
_isTask = true; |
|||
_handled = 0; |
|||
while (_handled < taskList.length) { |
|||
await Future.delayed(const Duration(seconds: 2)); |
|||
|
|||
int completed = 0; |
|||
for (var element in taskList) { |
|||
if (element['tasktype'] == 1) { |
|||
await _fileRecognize(element); |
|||
} else { |
|||
completed++; |
|||
} |
|||
} |
|||
_handled = completed; |
|||
} |
|||
_isTask = false; |
|||
} |
|||
|
|||
void removeTask(int id, {bool isDeleteTask = false}) { |
|||
Map taskData = taskList.firstWhere( |
|||
(element) => element['id'] == id, |
|||
orElse: () => {}, |
|||
); |
|||
if (taskData.isNotEmpty) { |
|||
if (isDeleteTask || taskData['tasktype'] >= 3) { |
|||
taskList.remove(taskData); |
|||
_storage.write("meeting_task_list", taskList); |
|||
if (taskList.isEmpty) { |
|||
_handled = 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
Future<String> _submitTask(String audiourl) async { |
|||
String format = _getFileType(audiourl); |
|||
|
|||
final requestBody = jsonEncode({ |
|||
"app": { |
|||
"appid": _appid, |
|||
"token": _token, |
|||
"cluster": _cluster, |
|||
}, |
|||
"user": { |
|||
"uid": _userId, |
|||
}, |
|||
"audio": { |
|||
"format": format, |
|||
"url": audiourl, |
|||
}, |
|||
"additions": { |
|||
"with_speaker_info": "True", |
|||
} |
|||
}); |
|||
|
|||
try { |
|||
final response = await http.post( |
|||
Uri.parse('$_serviceUrl/submit'), |
|||
headers: _headers, |
|||
body: requestBody, |
|||
); |
|||
|
|||
if (response.statusCode != 200) { |
|||
throw Exception('Submit failed with status: ${response.statusCode}'); |
|||
} |
|||
|
|||
final respDic = jsonDecode(response.body); |
|||
final taskId = respDic['resp']['id'] as String; |
|||
Logger.debug('taskId: $taskId'); |
|||
return taskId; |
|||
} catch (e) { |
|||
Logger.error('Submit error: ${e.toString()}'); |
|||
rethrow; |
|||
} |
|||
} |
|||
|
|||
String _getFileType(String path) { |
|||
List<String> array = path.split('.'); |
|||
return array[array.length - 1]; |
|||
} |
|||
|
|||
Future<Map<String, dynamic>> _queryTask(String taskId) async { |
|||
final queryBody = jsonEncode({ |
|||
"appid": _appid, |
|||
"token": _token, |
|||
"id": taskId, |
|||
"cluster": _cluster, |
|||
}); |
|||
|
|||
try { |
|||
final response = await http.post( |
|||
Uri.parse('$_serviceUrl/query'), |
|||
headers: _headers, |
|||
body: queryBody, |
|||
); |
|||
|
|||
if (response.statusCode != 200) { |
|||
throw Exception('Query failed with status: ${response.statusCode}'); |
|||
} |
|||
|
|||
final respDic = jsonDecode(response.body); |
|||
return respDic; |
|||
} catch (e) { |
|||
Logger.error('Query error: ${e.toString()}'); |
|||
rethrow; |
|||
} |
|||
} |
|||
|
|||
Future<void> _fileRecognize(Map item) async { |
|||
try { |
|||
var respDic = await _queryTask(item['taskid']); |
|||
var code = respDic['resp']['code'] as int; |
|||
|
|||
if (code == 1000) { |
|||
await _addTextList(item, respDic['resp']['utterances']); |
|||
return; |
|||
} else if (code < 2000) { |
|||
Logger.debug("FileRecognize failed"); |
|||
return; |
|||
} |
|||
} catch (e) { |
|||
Logger.error('Error occurred: ${e.toString()}'); |
|||
} |
|||
} |
|||
|
|||
Future<void> _addTextList(Map item, List utterances) async { |
|||
String text = ''; |
|||
String personnel = ''; |
|||
List<Map<String, Object?>> list = []; |
|||
for (var element in utterances) { |
|||
String speaker = ''; |
|||
if (element['additions'].isNotEmpty) { |
|||
speaker = 'Speaker ${element['additions']['speaker']}'; |
|||
text += '[$speaker]: '; |
|||
if (!personnel.contains(speaker)) { |
|||
personnel += '[$speaker] '; |
|||
} |
|||
} |
|||
list.add({ |
|||
'meetingid': item['id'], |
|||
'content': element['text'], |
|||
'starttime': element['start_time'], |
|||
'endtime': element['end_time'], |
|||
'speaker': speaker, |
|||
}); |
|||
text += '${element['text']}\n'; |
|||
} |
|||
var result = await SqfliteApi.insertMeetingSpeaker(list); |
|||
if (result != null) { |
|||
await SqfliteApi.editMeeting( |
|||
item['id'], |
|||
{'tasktype': 2, 'personnel': personnel}, |
|||
); |
|||
List speakerList = await SqfliteApi.getMeetingSpeaker(item['id']); |
|||
textList.value = List.from(speakerList); |
|||
Synchrodata.saveOperationRecord('update', { |
|||
'original': jsonEncode(textList), |
|||
'id': item['id'], |
|||
}); |
|||
item['tasktype'] = 2; |
|||
} |
|||
allText = text; |
|||
_aiServiceMessage(item); |
|||
} |
|||
|
|||
void _aiServiceMessage(Map item) { |
|||
int awaitQuantity = 0; |
|||
String summaryText = ''; |
|||
String overviewText = ''; |
|||
DeapsoundAIService().sendMessage( |
|||
messages: [ |
|||
{ |
|||
'role': 'system', |
|||
'content': |
|||
'您将扮演一名会议总结专家,拥有超强的信息归纳与细分能力。不仅能高效处理各类通用场景会议,精准提炼会议核心内容,为后续思维导图生成奠定坚实基础。若涉及人员,人员名称保留[]。并根据内容只输出对应语言。', |
|||
}, |
|||
{'role': 'user', 'content': allText}, |
|||
], |
|||
).then((value) { |
|||
awaitQuantity++; |
|||
summaryText = value; |
|||
if (awaitQuantity >= 2) { |
|||
_aiServiceValue(item, summaryText, overviewText); |
|||
} |
|||
}); |
|||
DeapsoundAIService().sendMessage( |
|||
messages: [ |
|||
{ |
|||
'role': 'system', |
|||
'content': '您将扮演一名会议事件归纳专家,能准确抓住会议中事件的关键点,并每个事件只需一句话精简总结。', |
|||
}, |
|||
{'role': 'user', 'content': allText}, |
|||
], |
|||
).then((value) { |
|||
awaitQuantity++; |
|||
overviewText = value; |
|||
if (awaitQuantity >= 2) { |
|||
_aiServiceValue(item, summaryText, overviewText); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
void _aiServiceValue(Map item, String summaryText, String overviewText) { |
|||
SqfliteApi.editMeeting(item['id'], { |
|||
'tasktype': 3, |
|||
'summary': summaryText, |
|||
'overview': overviewText, |
|||
}); |
|||
item['tasktype'] = 3; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue