Merge pull request #3036 from procule/update-token-probabilities Enhancement: Token Probabilities viewer with dynamic prefix adjustment via Ctrl-click

cfd1545b8a0f25c070bccfbaf2946660512029b6

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
1 files changed, +50 -2Ignore whitespace
public/scripts/logprobs.js+50 -2
@@ -88,7 +88,7 @@ function renderAlternativeTokensView() {
88 prefixSpan.text(prefix);88 prefixSpan.text(prefix);
89 prefixSpan.html(prefixSpan.html().replace(/\n/g, '<br>'));89 prefixSpan.html(prefixSpan.html().replace(/\n/g, '<br>'));
90 prefixSpan.addClass('logprobs_output_prefix');90 prefixSpan.addClass('logprobs_output_prefix');
91 prefixSpan.attr('title', 'Select to reroll the last \'Continue\' generation');91 prefixSpan.attr('title', 'Select to reroll the last \'Continue\' generation.\nHold the CTRL key when clicking to reroll from before that word.');
92 prefixSpan.click(onPrefixClicked);92 prefixSpan.click(onPrefixClicked);
93 addKeyboardProps(prefixSpan);93 addKeyboardProps(prefixSpan);
94 tokenSpans.push(...withVirtualWhitespace(prefix, prefixSpan));94 tokenSpans.push(...withVirtualWhitespace(prefix, prefixSpan));
@@ -243,10 +243,50 @@ function onAlternativeClicked(tokenLogprobs, alternative) {
243}243}
244244
245/**245/**
246 * getTextBeforeClickedWord retrieves the portion of text within a span
247 * that appears before the word clicked by the user. Using the x and y
248 * coordinates from a PointerEvent, this function identifies the exact
249 * word clicked and returns the text preceding it within the span.
250 *
251 * If the clicked position does not resolve to a valid word or text node,
252 * the entire span text is returned as a fallback.
253 *
254 * @param {PointerEvent} event - The click event containing the x and y coordinates.
255 * @param {string} spanText - The full text content of the span element.
256 * @returns {string} The text before the clicked word, or the entire span text as fallback.
257 */
258function getTextBeforeClickedWord(event, spanText) {
259 const x = event.clientX;
260 const y = event.clientY;
261 const range = document.caretRangeFromPoint(x, y);
262
263 if (range && range.startContainer.nodeType === Node.TEXT_NODE) {
264 const textNode = range.startContainer;
265 const offset = range.startOffset;
266
267 // Get the full text content of the text node
268 const text = textNode.nodeValue;
269
270 // Find the boundaries of the clicked word
271 const start = text.lastIndexOf(" ", offset - 1) + 1;
272
273 // Return the text before the clicked word
274 return text.slice(0, start);
275 }
276
277 // If we can't determine the exact word, return the full span text as a fallback
278 return spanText;
279}
280
281
282/**
246 * onPrefixClicked is called when the user clicks on the carried-over prefix283 * onPrefixClicked is called when the user clicks on the carried-over prefix
247 * in the token output view. It allows them to reroll the last 'continue'284 * in the token output view. It allows them to reroll the last 'continue'
248 * completion with none of the output generated from it, in case they don't285 * completion with none of the output generated from it, in case they don't
249 * like the results.286 * like the results.
287 *
288 * If the user holds the Ctrl key while clicking, only the portion of text
289 * before the clicked word is retained as the prefix for rerolling
250 */290 */
251function onPrefixClicked() {291function onPrefixClicked() {
252 if (!checkGenerateReady()) {292 if (!checkGenerateReady()) {
@@ -255,7 +295,15 @@ function onPrefixClicked() {
255295
256 const { continueFrom } = getActiveMessageLogprobData();296 const { continueFrom } = getActiveMessageLogprobData();
257 const messageId = chat.length - 1;297 const messageId = chat.length - 1;
258 const prefix = continueFrom || '';298
299 // Check if Ctrl key is pressed during the click
300 let prefix = continueFrom || '';
301 if (event.ctrlKey) {
302 // Ctrl is pressed - use the text before the clicked word
303 prefix = getTextBeforeClickedWord(event, continueFrom);
304 }
305
306 // Use the determined `prefix`
259 createSwipe(messageId, prefix);307 createSwipe(messageId, prefix);
260 $('.swipe_right:last').click();308 $('.swipe_right:last').click();
261 Generate('continue').then(_ => void _);309 Generate('continue').then(_ => void _);