提交 c2c63647 authored 作者: songchuancai's avatar songchuancai

增加会话名称自动生成

上级 0f950dc7
......@@ -39,12 +39,15 @@ class HomePage extends StatefulWidget {
final bool hideNavigation;
final OpenAIService? openAIService;
const HomePage({
super.key,
this.customTitle,
this.customDescription,
this.customImageUrl,
this.hideNavigation = false,
this.openAIService,
});
@override
......@@ -58,7 +61,7 @@ class _HomePageState extends State<HomePage> {
String lastWords = '';
final OpenAIService openAIService = OpenAIService();
late OpenAIService openAIService;
String? generatedContent;
......@@ -103,6 +106,8 @@ class _HomePageState extends State<HomePage> {
initSpeechToText();
_initTts();
openAIService = widget.openAIService ?? OpenAIService();
}
Future<void> _initializeStorage() async {
......@@ -113,15 +118,23 @@ class _HomePageState extends State<HomePage> {
_conversations = await _storageService.getConversations();
// 每次进入应用创建一个新的会话
_createNewConversation();
// if (_conversations.isEmpty) {
// _createNewConversation();
// } else {
// _currentConversation = _conversations.first;
// setState(() {
// messages = _currentConversation.messages;
// });
// }
}
......@@ -168,27 +181,34 @@ class _HomePageState extends State<HomePage> {
_hasSpeechPermission = await speechToText.initialize(
onStatus: (status) {
print('语音状态: $status');
if (status == 'notListening') {
setState(() => _isListeningPressed = false);
}
},
onError: (error) {
print('语音错误: $error');
setState(() => _isListeningPressed = false);
_showErrorDialog('语音初始化失败,请检查麦克风权限');
},
);
} catch (e) {
print('语音初始化错误: $e');
_hasSpeechPermission = false;
}
setState(() {});
}
Future<void> startListening() async {
if (!_hasSpeechPermission) {
_showErrorDialog('请先授予麦克风权限');
setState(() => _isListeningPressed = false);
return;
}
......@@ -202,7 +222,9 @@ class _HomePageState extends State<HomePage> {
);
} catch (e) {
print('开始录音失败: $e');
setState(() => _isListeningPressed = false);
_showErrorDialog('启动语音识别失败,请重试');
}
}
......@@ -409,27 +431,36 @@ class _HomePageState extends State<HomePage> {
onTap: () async {
if (!_isListeningPressed) {
// 开始录音
setState(() {
_isListeningPressed = true;
_currentVoiceText = '';
});
await startListening();
} else {
// 停止录音
setState(() => _isListeningPressed = false);
await stopListening();
// 确保有语音文本才处理
if (_currentVoiceText.isNotEmpty) {
setState(() {
messages.add(ChatMessage(
text: _currentVoiceText,
isUserMessage: true,
));
_isLoading = true;
});
await _processAIResponse(_currentVoiceText);
}
setState(() => _currentVoiceText = '');
}
},
......@@ -454,7 +485,9 @@ class _HomePageState extends State<HomePage> {
const SizedBox(width: 8),
Text(
_isListeningPressed
? (_currentVoiceText.isEmpty ? '点击停止' : _currentVoiceText)
? (_currentVoiceText.isEmpty
? '点击停止'
: _currentVoiceText)
: '点击说话',
textAlign: TextAlign.center,
style: TextStyle(
......@@ -904,4 +937,3 @@ class _HomePageState extends State<HomePage> {
);
}
}
\ No newline at end of file
......@@ -6,6 +6,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import '../models/app_item.dart';
import '../services/chat_service.dart';
import '../services/storage_service.dart';
import '../home_page.dart';
......@@ -22,6 +23,8 @@ class ChatPage extends ConsumerStatefulWidget {
}
class _ChatPageState extends ConsumerState<ChatPage> {
final OpenAIService openAIService = OpenAIService();
@override
void initState() {
super.initState();
......@@ -46,6 +49,12 @@ class _ChatPageState extends ConsumerState<ChatPage> {
}
@override
void dispose() {
openAIService.clearConversation();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
......@@ -78,6 +87,7 @@ class _ChatPageState extends ConsumerState<ChatPage> {
customDescription: widget.app.description,
customImageUrl: widget.app.iconUrl,
hideNavigation: true,
openAIService: openAIService,
),
);
}
......
......@@ -8,6 +8,32 @@ class OpenAIService {
// final String apiKey = 'sk-OVjS7VE9mT68Uvg7kSFoMnbU6EU836FO';
// final String appKey = 'app-FRP2s2wSx01rsE67';
String? conversationId;
bool _isFirstMessage = true;
Future<void> _generateConversationName() async {
if (conversationId == null) return;
var prefs = await SharedPreferences.getInstance();
var storageService = StorageService(prefs);
String appKey = storageService.getWorkbenchToken() ?? '';
try {
final response = await http.post(
Uri.parse('$baseUrl/api/conversations/$conversationId/name'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $appKey',
},
body: jsonEncode({"auto_generate": true}),
);
if (response.statusCode != 200) {
print('生成会话名称失败: ${response.statusCode}');
}
} catch (e) {
print('生成会话名称异常: $e');
}
}
Stream<String> chatGPTAPI(String message) async* {
final client = http.Client();
......@@ -85,11 +111,16 @@ class OpenAIService {
} catch (e) {
throw Exception(e.toString());
} finally {
if (_isFirstMessage && conversationId != null) {
await _generateConversationName();
_isFirstMessage = false;
}
client.close();
}
}
void clearConversation() {
conversationId = null;
_isFirstMessage = true;
}
}
......@@ -9,12 +9,12 @@ import audioplayers_darwin
import flutter_tts
import path_provider_foundation
import shared_preferences_foundation
import speech_to_text_macos
import speech_to_text
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SpeechToTextMacosPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextMacosPlugin"))
SpeechToTextPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextPlugin"))
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论