From b9828bde5d64695f1881f213d8c02f5443345a6b Mon Sep 17 00:00:00 2001 From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com> Date: Sun, 28 Sep 2025 12:32:43 +0530 Subject: [PATCH] refactor: remove streamchunker --- lib/core/services/streaming_helper.dart | 13 +-- lib/core/utils/stream_chunker.dart | 105 ------------------------ openwebui-src | 2 +- 3 files changed, 2 insertions(+), 118 deletions(-) delete mode 100644 lib/core/utils/stream_chunker.dart diff --git a/lib/core/services/streaming_helper.dart b/lib/core/services/streaming_helper.dart index 3cfd9ee..eb2b542 100644 --- a/lib/core/services/streaming_helper.dart +++ b/lib/core/services/streaming_helper.dart @@ -7,7 +7,6 @@ import '../../core/models/chat_message.dart'; import '../../core/services/persistent_streaming_service.dart'; import '../../core/services/socket_service.dart'; import '../../core/utils/inactivity_watchdog.dart'; -import '../../core/utils/stream_chunker.dart'; import '../../core/utils/tool_calls_parser.dart'; import 'navigation_service.dart'; import '../../shared/widgets/themed_dialogs.dart'; @@ -66,22 +65,12 @@ ActiveSocketStream attachUnifiedChunkedStreaming({ required void Function() finishStreaming, required List Function() getMessages, }) { - // Temporarily disable chunking to debug second turn issues - // OpenWebUI doesn't use complex chunking like this - final chunkedStream = StreamChunker.chunkStream( - stream, - enableChunking: false, // Disabled for debugging - minChunkSize: 5, - maxChunkLength: 3, - delayBetweenChunks: const Duration(milliseconds: 15), - ); - // Persistable controller to survive brief app suspensions final persistentController = StreamController.broadcast(); final persistentService = PersistentStreamingService(); final streamId = persistentService.registerStream( - subscription: chunkedStream.listen( + subscription: stream.listen( persistentController.add, onDone: persistentController.close, onError: persistentController.addError, diff --git a/lib/core/utils/stream_chunker.dart b/lib/core/utils/stream_chunker.dart deleted file mode 100644 index 4e307a4..0000000 --- a/lib/core/utils/stream_chunker.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'dart:async'; -import 'dart:math'; - -/// Utility class to chunk large text streams into smaller pieces for smoother UI updates -class StreamChunker { - /// Splits large text chunks into smaller pieces for more fluid streaming - /// Similar to OpenWebUI's approach for better UX - static Stream chunkStream( - Stream inputStream, { - bool enableChunking = true, - int minChunkSize = 16, // increase to reduce UI thrash - int maxChunkLength = 12, // larger chunks improve performance - Duration delayBetweenChunks = const Duration(milliseconds: 8), - }) async* { - final random = Random(); - - await for (final chunk in inputStream) { - if (!enableChunking || chunk.length < minChunkSize) { - // Small chunks pass through as-is - yield chunk; - continue; - } - - // Split large chunks into smaller pieces - String remaining = chunk; - while (remaining.isNotEmpty) { - // Random chunk size between 4 and maxChunkLength characters - // But prefer to break at word boundaries when possible - int chunkSize = min( - max(4, random.nextInt(maxChunkLength) + 1), - remaining.length, - ); - - // Try to find a word boundary (space) within the chunk size - if (chunkSize < remaining.length) { - final nextSpace = remaining.indexOf(' ', chunkSize); - if (nextSpace != -1 && nextSpace <= chunkSize + 2) { - // Include the space in the chunk for natural word breaks - chunkSize = nextSpace + 1; - } - } - - final pieceToYield = remaining.substring(0, chunkSize); - yield pieceToYield; - remaining = remaining.substring(chunkSize); - - // Add small delay between chunks for fluid animation - // Skip delay for last piece to avoid unnecessary wait - if (remaining.isNotEmpty && delayBetweenChunks.inMicroseconds > 0) { - await Future.delayed(delayBetweenChunks); - } - } - } - } - - /// Alternative method that chunks by words instead of characters - static Stream chunkByWords( - Stream inputStream, { - bool enableChunking = true, - int wordsPerChunk = 1, - Duration delayBetweenWords = const Duration(milliseconds: 50), - }) async* { - if (!enableChunking) { - yield* inputStream; - return; - } - - String buffer = ''; - - await for (final chunk in inputStream) { - buffer += chunk; - - // Split by spaces and yield word by word - final words = buffer.split(' '); - - // Keep the last "word" in buffer as it might be incomplete - if (words.length > 1) { - buffer = words.last; - final completeWords = words.sublist(0, words.length - 1); - - for (int i = 0; i < completeWords.length; i++) { - final word = completeWords[i]; - // Add space back except for the first word if buffer was empty - final wordWithSpace = - (i < completeWords.length - 1 || buffer.isNotEmpty) - ? '$word ' - : word; - - yield wordWithSpace; - - // Add delay between words for smooth streaming effect - if (i < completeWords.length - 1 && - delayBetweenWords.inMicroseconds > 0) { - await Future.delayed(delayBetweenWords); - } - } - } - } - - // Yield any remaining buffer content - if (buffer.isNotEmpty) { - yield buffer; - } - } -} diff --git a/openwebui-src b/openwebui-src index 6bc5d33..598282c 160000 --- a/openwebui-src +++ b/openwebui-src @@ -1 +1 @@ -Subproject commit 6bc5d331a27c5106f492213510a763effa316faf +Subproject commit 598282cf75de358215d045c617e70d28bc48929e