Merge pull request #3610 from bmen25124/time_to_first_token Added time to first token
Signed| @@ -2477,7 +2477,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | ||
| 2477 | 2477 | timestamp: timestamp, |
| 2478 | 2478 | extra: mes.extra, |
| 2479 | 2479 | tokenCount: mes.extra?.token_count ?? 0, |
| 2480 | 2480 | ...formatGenerationTimer(mes.gen_started, mes.gen_finished, mes.extra?.token_count, mes.extra?.reasoning_duration, mes.extra?.time_to_first_token), |
| 2481 | 2481 | }; |
| 2482 | 2482 | |
| 2483 | 2483 | const renderedMessage = getMessageFromTemplate(params); |
| @@ -2598,13 +2598,14 @@ export function formatCharacterAvatar(characterAvatar) { | ||
| 2598 | 2598 | * @param {Date} gen_finished Date when generation was finished |
| 2599 | 2599 | * @param {number} tokenCount Number of tokens generated (0 if not available) |
| 2600 | 2600 | * @param {number?} [reasoningDuration=null] Reasoning duration (null if no reasoning was done) |
| 2601 | + * @param {number?} [timeToFirstToken=null] Time to first token | |
| 2601 | 2602 | * @returns {Object} Object containing the formatted timer value and title |
| 2602 | 2603 | * @example |
| 2603 | 2604 | * const { timerValue, timerTitle } = formatGenerationTimer(gen_started, gen_finished, tokenCount); |
| 2604 | 2605 | * console.log(timerValue); // 1.2s |
| 2605 | 2606 | * console.log(timerTitle); // Generation queued: 12:34:56 7 Jan 2021\nReply received: 12:34:57 7 Jan 2021\nTime to generate: 1.2 seconds\nToken rate: 5 t/s |
| 2606 | 2607 | */ |
| 2607 | 2608 | function formatGenerationTimer(gen_started, gen_finished, tokenCount, reasoningDuration = null, timeToFirstToken = null) { |
| 2608 | 2609 | if (!gen_started || !gen_finished) { |
| 2609 | 2610 | return {}; |
| 2610 | 2611 | } |
| @@ -2618,8 +2619,9 @@ function formatGenerationTimer(gen_started, gen_finished, tokenCount, reasoningD | ||
| 2618 | 2619 | `Generation queued: ${start.format(dateFormat)}`, |
| 2619 | 2620 | `Reply received: ${finish.format(dateFormat)}`, |
| 2620 | 2621 | `Time to generate: ${seconds} seconds`, |
| 2622 | + timeToFirstToken ? `Time to first token: ${timeToFirstToken / 1000} seconds` : '', | |
| 2621 | 2623 | reasoningDuration > 0 ? `Time to think: ${reasoningDuration / 1000} seconds` : '', |
| 2622 | 2624 | tokenCount > 0 ? `Token rate: ${Number(tokenCount / seconds).toFixed(13)} t/s` : '', |
| 2623 | 2625 | ].filter(x => x).join('\n').trim(); |
| 2624 | 2626 | |
| 2625 | 2627 | if (isNaN(seconds) || seconds < 0) { |
| @@ -3158,6 +3160,9 @@ class StreamingProcessor { | ||
| 3158 | 3160 | this.abortController = new AbortController(); |
| 3159 | 3161 | this.firstMessageText = '...'; |
| 3160 | 3162 | this.timeStarted = timeStarted; |
| 3163 | + /** @type {number?} */ | |
| 3164 | + this.timeToFirstToken = null; | |
| 3165 | + this.createdAt = new Date(); | |
| 3161 | 3166 | this.continueMessage = type === 'continue' ? continueMessage : ''; |
| 3162 | 3167 | this.swipes = []; |
| 3163 | 3168 | /** @type {import('./scripts/logprobs.js').TokenLogprobs[]} */ |
| @@ -3249,6 +3254,7 @@ class StreamingProcessor { | ||
| 3249 | 3254 | if (!chat[messageId]['extra']) { |
| 3250 | 3255 | chat[messageId]['extra'] = {}; |
| 3251 | 3256 | } |
| 3257 | + chat[messageId]['extra']['time_to_first_token'] = this.timeToFirstToken; | |
| 3252 | 3258 | |
| 3253 | 3259 | // Update reasoning |
| 3254 | 3260 | await this.reasoningHandler.process(messageId, mesChanged); |
| @@ -3266,7 +3272,12 @@ class StreamingProcessor { | ||
| 3266 | 3272 | |
| 3267 | 3273 | if ((this.type == 'swipe' || this.type === 'continue') && Array.isArray(chat[messageId]['swipes'])) { |
| 3268 | 3274 | chat[messageId]['swipes'][chat[messageId]['swipe_id']] = processedText; |
| 3269 | - chat[messageId]['swipe_info'][chat[messageId]['swipe_id']] = { 'send_date': chat[messageId]['send_date'], 'gen_started': chat[messageId]['gen_started'], 'gen_finished': chat[messageId]['gen_finished'], 'extra': JSON.parse(JSON.stringify(chat[messageId]['extra'])) }; | |
| 3275 | + chat[messageId]['swipe_info'][chat[messageId]['swipe_id']] = { | |
| 3276 | + 'send_date': chat[messageId]['send_date'], | |
| 3277 | + 'gen_started': chat[messageId]['gen_started'], | |
| 3278 | + 'gen_finished': chat[messageId]['gen_finished'], | |
| 3279 | + 'extra': JSON.parse(JSON.stringify(chat[messageId]['extra'])) | |
| 3280 | + }; | |
| 3270 | 3281 | } |
| 3271 | 3282 | |
| 3272 | 3283 | const formattedText = messageFormatting( |
| @@ -3282,7 +3293,7 @@ class StreamingProcessor { | ||
| 3282 | 3293 | this.messageTextDom.innerHTML = formattedText; |
| 3283 | 3294 | } |
| 3284 | 3295 | |
| 3285 | 3296 | const timePassed = formatGenerationTimer(this.timeStarted, currentTime, currentTokenCount, this.reasoningHandler.getDuration(), this.timeToFirstToken); |
| 3286 | 3297 | if (this.messageTimerDom instanceof HTMLElement) { |
| 3287 | 3298 | this.messageTimerDom.textContent = timePassed.timerValue; |
| 3288 | 3299 | this.messageTimerDom.title = timePassed.timerTitle; |
| @@ -3357,7 +3368,12 @@ class StreamingProcessor { | ||
| 3357 | 3368 | if (this.type !== 'swipe' && this.type !== 'impersonate') { |
| 3358 | 3369 | if (Array.isArray(chat[messageId]['swipes']) && chat[messageId]['swipes'].length === 1 && chat[messageId]['swipe_id'] === 0) { |
| 3359 | 3370 | chat[messageId]['swipes'][0] = chat[messageId]['mes']; |
| 3360 | - chat[messageId]['swipe_info'][0] = { 'send_date': chat[messageId]['send_date'], 'gen_started': chat[messageId]['gen_started'], 'gen_finished': chat[messageId]['gen_finished'], 'extra': JSON.parse(JSON.stringify(chat[messageId]['extra'])) }; | |
| 3371 | + chat[messageId]['swipe_info'][0] = { | |
| 3372 | + 'send_date': chat[messageId]['send_date'], | |
| 3373 | + 'gen_started': chat[messageId]['gen_started'], | |
| 3374 | + 'gen_finished': chat[messageId]['gen_finished'], | |
| 3375 | + 'extra': JSON.parse(JSON.stringify(chat[messageId]['extra'])), | |
| 3376 | + }; | |
| 3361 | 3377 | } |
| 3362 | 3378 | } |
| 3363 | 3379 | } |
| @@ -3391,7 +3407,11 @@ class StreamingProcessor { | ||
| 3391 | 3407 | const sw = new Stopwatch(1000 / power_user.streaming_fps); |
| 3392 | 3408 | const timestamps = []; |
| 3393 | 3409 | for await (const { text, swipes, logprobs, toolCalls, state } of this.generator()) { |
| 3394 | 3410 | timestamps.push(const now = Date.now()); |
| 3411 | + timestamps.push(now); | |
| 3412 | + if (!this.timeToFirstToken) { | |
| 3413 | + this.timeToFirstToken = now - this.createdAt.getTime(); | |
| 3414 | + } | |
| 3395 | 3415 | if (this.isStopped || this.abortController.signal.aborted) { |
| 3396 | 3416 | return this.result; |
| 3397 | 3417 | } |
| @@ -8830,7 +8850,12 @@ const swipe_right = () => { | ||
| 8830 | 8850 | chat[chat.length - 1]['swipes'] = []; // empty the array |
| 8831 | 8851 | chat[chat.length - 1]['swipe_info'] = []; |
| 8832 | 8852 | chat[chat.length - 1]['swipes'][0] = chat[chat.length - 1]['mes']; //assign swipe array with last message from chat |
| 8833 | - chat[chat.length - 1]['swipe_info'][0] = { 'send_date': chat[chat.length - 1]['send_date'], 'gen_started': chat[chat.length - 1]['gen_started'], 'gen_finished': chat[chat.length - 1]['gen_finished'], 'extra': JSON.parse(JSON.stringify(chat[chat.length - 1]['extra'])) }; | |
| 8853 | + chat[chat.length - 1]['swipe_info'][0] = { | |
| 8854 | + 'send_date': chat[chat.length - 1]['send_date'], | |
| 8855 | + 'gen_started': chat[chat.length - 1]['gen_started'], | |
| 8856 | + 'gen_finished': chat[chat.length - 1]['gen_finished'], | |
| 8857 | + 'extra': JSON.parse(JSON.stringify(chat[chat.length - 1]['extra'])), | |
| 8858 | + }; | |
| 8834 | 8859 | //assign swipe info array with last message from chat |
| 8835 | 8860 | } |
| 8836 | 8861 | if (chat.length === 1 && chat[0]['swipe_id'] !== undefined && chat[0]['swipe_id'] === chat[0]['swipes'].length - 1) { // if swipe_right is called on the last alternate greeting, loop back around |