From 280dcf37307d0bf78237c3d75427ecad3a1eac90 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 5 Dec 2025 14:59:51 +0100 Subject: [PATCH] Remove throttling of AI answer after 5 seconds --- .../SearchOrAskAi/AskAi/MessageThrottler.ts | 36 +++++++++++++++++-- .../SearchOrAskAi/AskAi/chat.store.ts | 5 +-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/MessageThrottler.ts b/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/MessageThrottler.ts index a5b05127b..e0593f2f5 100644 --- a/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/MessageThrottler.ts +++ b/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/MessageThrottler.ts @@ -1,12 +1,18 @@ /** * Message throttler for controlling the speed of streaming updates. * Non-React version that can be used in Zustand stores or other non-component code. + * + * Automatically speeds up after a configurable duration to drain buffers faster. */ const DEFAULT_THROTTLE_DELAY_MS = 25 +const DEFAULT_FAST_DELAY_MS = 5 +const DEFAULT_SPEEDUP_AFTER_MS = 5_000 export interface MessageThrottlerOptions { delayInMs?: number + fastDelayInMs?: number + speedupAfterMs?: number onMessage: (message: T) => void } @@ -15,16 +21,42 @@ export class MessageThrottler { private timer: ReturnType | null = null private isProcessing = false private delayInMs: number + private fastDelayInMs: number + private speedupAfterMs: number + private startTime: number | null = null private onMessage: (message: T) => void constructor({ delayInMs = DEFAULT_THROTTLE_DELAY_MS, + fastDelayInMs = DEFAULT_FAST_DELAY_MS, + speedupAfterMs = DEFAULT_SPEEDUP_AFTER_MS, onMessage, }: MessageThrottlerOptions) { this.delayInMs = delayInMs + this.fastDelayInMs = fastDelayInMs + this.speedupAfterMs = speedupAfterMs this.onMessage = onMessage } + /** + * Start the speedup timer. Call this when the first meaningful content arrives. + */ + startSpeedupTimer(): void { + if (this.startTime === null) { + this.startTime = Date.now() + } + } + + private getCurrentDelay(): number { + if (this.startTime === null) { + return this.delayInMs + } + const elapsed = Date.now() - this.startTime + return elapsed >= this.speedupAfterMs + ? this.fastDelayInMs + : this.delayInMs + } + private processNext = () => { if (this.queue.length === 0) { this.isProcessing = false @@ -36,7 +68,7 @@ export class MessageThrottler { this.onMessage(nextMessage) if (this.queue.length > 0) { - this.timer = setTimeout(this.processNext, this.delayInMs) + this.timer = setTimeout(this.processNext, this.getCurrentDelay()) } else { this.isProcessing = false this.timer = null @@ -47,7 +79,7 @@ export class MessageThrottler { this.queue.push(message) if (!this.isProcessing) { this.isProcessing = true - this.timer = setTimeout(this.processNext, this.delayInMs) + this.timer = setTimeout(this.processNext, this.getCurrentDelay()) } } diff --git a/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/chat.store.ts b/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/chat.store.ts index 415febe4c..1adfd4606 100644 --- a/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/chat.store.ts +++ b/src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/chat.store.ts @@ -32,7 +32,6 @@ export interface ChatMessage { } const API_ENDPOINT = '/docs/_api/v1/ask-ai/stream' -const MESSAGE_THROTTLE_MS = 25 interface ActiveStream { controller: AbortController @@ -244,8 +243,8 @@ async function startStream( const controller = new AbortController() // Create a throttler for this stream to control update frequency + // Throttler automatically speeds up after 10 seconds to drain buffers faster const throttler = new MessageThrottler({ - delayInMs: MESSAGE_THROTTLE_MS, onMessage: (event) => handleStreamEvent(messageId, event), }) @@ -368,6 +367,8 @@ function handleStreamEvent(messageId: string, event: AskAiEvent): void { if (event.type === 'conversation_start' && event.conversationId) { actions.setConversationId(event.conversationId) } else if (event.type === 'message_chunk') { + // Start speedup timer on first content chunk + stream.throttler.startSpeedupTimer() stream.content += event.content actions.updateAiMessage(messageId, stream.content, 'streaming') } else if (event.type === 'error') {