diff --git a/lib/data/api/voice_api.dart b/lib/data/api/voice_api.dart index 6fed7b4..31d4eac 100644 --- a/lib/data/api/voice_api.dart +++ b/lib/data/api/voice_api.dart @@ -40,16 +40,20 @@ class VoiceApi { } /// POST WebM/Opus audio bytes and return the transcript string. + /// [context] is optional recent conversation text passed as initial_prompt + /// to Whisper, reducing mishearings of domain-specific words. /// Returns empty string on empty or error response. - Future transcribe(Uint8List audioBytes) async { + Future transcribe(Uint8List audioBytes, {String? context}) async { try { - final formData = FormData.fromMap({ + final fields = { 'audio': MultipartFile.fromBytes( audioBytes, filename: 'audio.m4a', contentType: DioMediaType('audio', 'mp4'), ), - }); + if (context != null && context.isNotEmpty) 'context': context, + }; + final formData = FormData.fromMap(fields); final response = await _dio.post( '/api/voice/transcribe', data: formData, diff --git a/lib/data/repositories/voice_repository.dart b/lib/data/repositories/voice_repository.dart index 7eb9417..cc8329c 100644 --- a/lib/data/repositories/voice_repository.dart +++ b/lib/data/repositories/voice_repository.dart @@ -7,6 +7,7 @@ class VoiceRepository { const VoiceRepository(this._api); Future checkStatus() => _api.checkStatus(); - Future transcribe(Uint8List audioBytes) => _api.transcribe(audioBytes); + Future transcribe(Uint8List audioBytes, {String? context}) => + _api.transcribe(audioBytes, context: context); Future synthesise(String text) => _api.synthesise(text); } diff --git a/lib/providers/voice_provider.dart b/lib/providers/voice_provider.dart index 9d7cf80..26e9d64 100644 --- a/lib/providers/voice_provider.dart +++ b/lib/providers/voice_provider.dart @@ -108,6 +108,10 @@ class VoiceNotifier extends Notifier { int _lastSeenLength = 0; bool _streamComplete = false; + // Last complete assistant response — passed to Whisper as initial_prompt + // to reduce STT mishearings of domain-specific words. + String _lastAssistantContent = ''; + // TTS playback queue final _ttsQueue = Queue(); bool _ttsPlaying = false; @@ -205,6 +209,7 @@ class VoiceNotifier extends Notifier { _dispatchSentences(flush: isComplete); if (isComplete) { + _lastAssistantContent = fullContent; _streamComplete = true; _checkRestartListening(); } @@ -278,8 +283,10 @@ class VoiceNotifier extends Notifier { if (!state.voiceModeActive) return; - final transcript = - await ref.read(voiceRepositoryProvider).transcribe(bytes); + final transcript = await ref.read(voiceRepositoryProvider).transcribe( + bytes, + context: _lastAssistantContent.isNotEmpty ? _lastAssistantContent : null, + ); if (!state.voiceModeActive) return;