diff --git a/lib/modules/meeting/views/ai_bottom_sheet.dart b/lib/modules/meeting/views/ai_bottom_sheet.dart index 3b847c465..c01c74ecb 100644 --- a/lib/modules/meeting/views/ai_bottom_sheet.dart +++ b/lib/modules/meeting/views/ai_bottom_sheet.dart @@ -22,7 +22,7 @@ class _AIBottomSheetState extends State { final _deapsoundAI = DeapsoundAIService(); StreamSubscription? _aiResponseSubscription; - final TextEditingController _texController = TextEditingController(); + final TextEditingController _textController = TextEditingController(); String _allText = ''; @@ -33,6 +33,8 @@ class _AIBottomSheetState extends State { '提取结论', '生成关键指标', ]; + final StringBuffer _buffer = StringBuffer(); + bool _isAdd = true; bool _isLoading = false; @@ -53,7 +55,7 @@ class _AIBottomSheetState extends State { @override void dispose() { - _texController.dispose(); + _textController.dispose(); _scrollController.dispose(); _aiResponseSubscription?.cancel(); super.dispose(); @@ -112,7 +114,7 @@ class _AIBottomSheetState extends State { reverse: true, itemBuilder: (BuildContext context, int index) { Map data = _dataList[index]; - return _item(data); + return _item(index, data); }, ), ) @@ -124,7 +126,12 @@ class _AIBottomSheetState extends State { ); } - Widget _item(Map data) { + Widget _item(int index, Map data) { + List list = []; + if (index == 0 && data['cruxtext'].isNotEmpty) { + list = data['cruxtext'].split(RegExp(r'[??]')); + list = list.where((element) => element.isNotEmpty).toList(); + } return Column( children: [ Container( @@ -152,6 +159,51 @@ class _AIBottomSheetState extends State { data: data['assistant'], ), ), + if (list.isNotEmpty) + Padding( + padding: EdgeInsets.symmetric(vertical: 10.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(bottom: 5.w), + child: Text( + '继续提问', + style: TextStyle( + color: Colors.grey, + fontSize: 13.sp, + fontWeight: FontWeight.bold, + ), + ), + ), + ...List.generate( + list.length, + (int idx) => GestureDetector( + onTap: () { + _sendMessage('${list[idx]}?'); + }, + child: Container( + width: double.infinity, + padding: + EdgeInsets.symmetric(horizontal: 15.w, vertical: 8.w), + margin: EdgeInsets.symmetric(vertical: 5.w), + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(12.r), + border: Border.all( + color: Colors.grey[300]!, + ), + ), + child: Text( + '${list[idx]}?', + style: TextStyle(fontSize: 14.sp), + ), + ), + ), + ), + ], + ), + ), ], ); } @@ -239,7 +291,7 @@ class _AIBottomSheetState extends State { 5.horizontalSpace, Expanded( child: TextField( - controller: _texController, + controller: _textController, style: TextStyle( fontSize: 16.sp, color: Colors.black87, @@ -265,7 +317,7 @@ class _AIBottomSheetState extends State { 10.horizontalSpace, GestureDetector( onTap: () { - _sendMessage(_texController.text); + _sendMessage(_textController.text); }, child: Container( width: 26.w, @@ -288,12 +340,15 @@ class _AIBottomSheetState extends State { void _sendMessage(String value) { if (_isLoading || value.isEmpty) return; - _texController.clear(); + _buffer.clear(); + _isAdd = true; + _textController.clear(); setState(() { _isLoading = true; _dataList.insert(0, { 'user': value, 'assistant': '', + 'cruxtext': '', }); }); if (_dataList.length > 1) { @@ -307,11 +362,27 @@ class _AIBottomSheetState extends State { ); _aiResponseSubscription = responseStream.listen( (chunk) { - setState(() { - _dataList.first['assistant'] += chunk; - }); + _buffer.write(chunk); + final text = _buffer.toString(); + Map item = _dataList.first; + if (_isAdd) { + final index = text.indexOf('@continue_asking@'); + if (index != -1) { + item['assistant'] = text.substring(0, index); + _isAdd = false; + } else { + item['assistant'] = text; + } + setState(() {}); + } }, onDone: () { + final text = _buffer.toString(); + final index = text.indexOf('@continue_asking@'); + if (index != -1) { + _dataList.first['cruxtext'] = + text.substring(index + '@continue_asking@'.length).trim(); + } setState(() { _isLoading = false; }); @@ -325,6 +396,11 @@ class _AIBottomSheetState extends State { 'role': 'system', 'content': '你只能根据这段对话记录回答问题,禁止引入外部知识。对话内容:$_allText', }, + { + 'role': 'system', + 'content': + '请基于对话上下文生成内容。在回复末尾,添加2-4个简短的、旨在继续对话的问题,并放入@continue_asking@后面。', + }, ]; for (int i = _dataList.length - 1; i >= 0; i--) { messages.add({'role': 'user', 'content': _dataList[i]['user']});