Merge pull request #3382 from SillyTavern/staging

Staging into reasoning-regex
This commit is contained in:
Cohee
2025-01-29 11:38:50 +02:00
committed by GitHub
8 changed files with 123 additions and 8 deletions

View File

@ -6093,6 +6093,19 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes,
return { type, getMessage }; return { type, getMessage };
} }
export function syncCurrentSwipeInfoExtras() {
if (!chat.length) {
return;
}
const currentMessage = chat[chat.length - 1];
if (currentMessage && Array.isArray(currentMessage.swipe_info) && typeof currentMessage.swipe_id === 'number') {
const swipeInfo = currentMessage.swipe_info[currentMessage.swipe_id];
if (swipeInfo && typeof swipeInfo === 'object') {
swipeInfo.extra = structuredClone(currentMessage.extra);
}
}
}
function saveImageToMessage(img, mes) { function saveImageToMessage(img, mes) {
if (mes && img.image) { if (mes && img.image) {
if (!mes.extra || typeof mes.extra !== 'object') { if (!mes.extra || typeof mes.extra !== 'object') {
@ -8524,6 +8537,9 @@ function swipe_left() { // when we swipe left..but no generation.
streamingProcessor.onStopStreaming(); streamingProcessor.onStopStreaming();
} }
// Make sure ad-hoc changes to extras are saved before swiping away
syncCurrentSwipeInfoExtras();
const swipe_duration = 120; const swipe_duration = 120;
const swipe_range = '700px'; const swipe_range = '700px';
chat[chat.length - 1]['swipe_id']--; chat[chat.length - 1]['swipe_id']--;
@ -8659,6 +8675,9 @@ const swipe_right = () => {
return unblockGeneration(); return unblockGeneration();
} }
// Make sure ad-hoc changes to extras are saved before swiping away
syncCurrentSwipeInfoExtras();
const swipe_duration = 200; const swipe_duration = 200;
const swipe_range = 700; const swipe_range = 700;
//console.log(swipe_range); //console.log(swipe_range);

View File

@ -566,7 +566,7 @@ export function initAuthorsNote() {
namedArgumentList: [], namedArgumentList: [],
unnamedArgumentList: [ unnamedArgumentList: [
new SlashCommandArgument( new SlashCommandArgument(
'position', [ARGUMENT_TYPE.STRING], false, false, null, ['system', 'user', 'assistant'], 'role', [ARGUMENT_TYPE.STRING], false, false, null, ['system', 'user', 'assistant'],
), ),
], ],
helpString: ` helpString: `

View File

@ -30,6 +30,7 @@ const CC_COMMANDS = [
'api-url', 'api-url',
'model', 'model',
'proxy', 'proxy',
'stop-strings',
]; ];
const TC_COMMANDS = [ const TC_COMMANDS = [
@ -43,6 +44,7 @@ const TC_COMMANDS = [
'context', 'context',
'instruct-state', 'instruct-state',
'tokenizer', 'tokenizer',
'stop-strings',
]; ];
const FANCY_NAMES = { const FANCY_NAMES = {
@ -57,6 +59,7 @@ const FANCY_NAMES = {
'instruct': 'Instruct Template', 'instruct': 'Instruct Template',
'context': 'Context Template', 'context': 'Context Template',
'tokenizer': 'Tokenizer', 'tokenizer': 'Tokenizer',
'stop-strings': 'Custom Stopping Strings',
}; };
/** /**
@ -138,6 +141,7 @@ const profilesProvider = () => [
* @property {string} [context] Context Template * @property {string} [context] Context Template
* @property {string} [instruct-state] Instruct Mode * @property {string} [instruct-state] Instruct Mode
* @property {string} [tokenizer] Tokenizer * @property {string} [tokenizer] Tokenizer
* @property {string} [stop-strings] Custom Stopping Strings
* @property {string[]} [exclude] Commands to exclude * @property {string[]} [exclude] Commands to exclude
*/ */

View File

@ -30,6 +30,7 @@ import { GoogleTranslateTtsProvider } from './google-translate.js';
export { talkingAnimation }; export { talkingAnimation };
const UPDATE_INTERVAL = 1000; const UPDATE_INTERVAL = 1000;
const wrapper = new ModuleWorkerWrapper(moduleWorker);
let voiceMapEntries = []; let voiceMapEntries = [];
let voiceMap = {}; // {charName:voiceid, charName2:voiceid2} let voiceMap = {}; // {charName:voiceid, charName2:voiceid2}
@ -120,7 +121,7 @@ async function onNarrateOneMessage() {
} }
resetTtsPlayback(); resetTtsPlayback();
ttsJobQueue.push(message); processAndQueueTtsMessage(message);
moduleWorker(); moduleWorker();
} }
@ -147,7 +148,7 @@ async function onNarrateText(args, text) {
} }
resetTtsPlayback(); resetTtsPlayback();
ttsJobQueue.push({ mes: text, name: name }); processAndQueueTtsMessage({ mes: text, name: name });
await moduleWorker(); await moduleWorker();
// Return back to the chat voices // Return back to the chat voices
@ -220,6 +221,36 @@ function isTtsProcessing() {
return processing; return processing;
} }
/**
* Splits a message into lines and adds each non-empty line to the TTS job queue.
* @param {Object} message - The message object to be processed.
* @param {string} message.mes - The text of the message to be split into lines.
* @param {string} message.name - The name associated with the message.
* @returns {void}
*/
function processAndQueueTtsMessage(message) {
if (!extension_settings.tts.narrate_by_paragraphs) {
ttsJobQueue.push(message);
return;
}
const lines = message.mes.split('\n');
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.length === 0) {
continue;
}
ttsJobQueue.push(
Object.assign({}, message, {
mes: line,
}),
);
}
}
function debugTtsPlayback() { function debugTtsPlayback() {
console.log(JSON.stringify( console.log(JSON.stringify(
{ {
@ -350,7 +381,7 @@ function onAudioControlClicked() {
talkingAnimation(false); talkingAnimation(false);
} else { } else {
// Default play behavior if not processing or playing is to play the last message. // Default play behavior if not processing or playing is to play the last message.
ttsJobQueue.push(context.chat[context.chat.length - 1]); processAndQueueTtsMessage(context.chat[context.chat.length - 1]);
} }
updateUiAudioPlayState(); updateUiAudioPlayState();
} }
@ -376,6 +407,7 @@ function completeCurrentAudioJob() {
currentAudioJob = null; currentAudioJob = null;
talkingAnimation(false); //stop lip animation talkingAnimation(false); //stop lip animation
// updateUiPlayState(); // updateUiPlayState();
wrapper.update();
} }
/** /**
@ -466,7 +498,7 @@ async function processTtsQueue() {
} }
if (extension_settings.tts.skip_tags) { if (extension_settings.tts.skip_tags) {
text = text.replace(/<.*?>.*?<\/.*?>/g, '').trim(); text = text.replace(/<.*?>[\s\S]*?<\/.*?>/g, '').trim();
} }
if (!extension_settings.tts.pass_asterisks) { if (!extension_settings.tts.pass_asterisks) {
@ -569,6 +601,7 @@ function loadSettings() {
$('#tts_narrate_quoted').prop('checked', extension_settings.tts.narrate_quoted_only); $('#tts_narrate_quoted').prop('checked', extension_settings.tts.narrate_quoted_only);
$('#tts_auto_generation').prop('checked', extension_settings.tts.auto_generation); $('#tts_auto_generation').prop('checked', extension_settings.tts.auto_generation);
$('#tts_periodic_auto_generation').prop('checked', extension_settings.tts.periodic_auto_generation); $('#tts_periodic_auto_generation').prop('checked', extension_settings.tts.periodic_auto_generation);
$('#tts_narrate_by_paragraphs').prop('checked', extension_settings.tts.narrate_by_paragraphs);
$('#tts_narrate_translated_only').prop('checked', extension_settings.tts.narrate_translated_only); $('#tts_narrate_translated_only').prop('checked', extension_settings.tts.narrate_translated_only);
$('#tts_narrate_user').prop('checked', extension_settings.tts.narrate_user); $('#tts_narrate_user').prop('checked', extension_settings.tts.narrate_user);
$('#tts_pass_asterisks').prop('checked', extension_settings.tts.pass_asterisks); $('#tts_pass_asterisks').prop('checked', extension_settings.tts.pass_asterisks);
@ -638,6 +671,11 @@ function onPeriodicAutoGenerationClick() {
saveSettingsDebounced(); saveSettingsDebounced();
} }
function onNarrateByParagraphsClick() {
extension_settings.tts.narrate_by_paragraphs = !!$('#tts_narrate_by_paragraphs').prop('checked');
saveSettingsDebounced();
}
function onNarrateDialoguesClick() { function onNarrateDialoguesClick() {
extension_settings.tts.narrate_dialogues_only = !!$('#tts_narrate_dialogues').prop('checked'); extension_settings.tts.narrate_dialogues_only = !!$('#tts_narrate_dialogues').prop('checked');
@ -816,7 +854,12 @@ async function onMessageEvent(messageId, lastCharIndex) {
lastChatId = context.chatId; lastChatId = context.chatId;
console.debug(`Adding message from ${message.name} for TTS processing: "${message.mes}"`); console.debug(`Adding message from ${message.name} for TTS processing: "${message.mes}"`);
ttsJobQueue.push(message);
if (extension_settings.tts.periodic_auto_generation) {
ttsJobQueue.push(message);
} else {
processAndQueueTtsMessage(message);
}
} }
async function onMessageDeleted() { async function onMessageDeleted() {
@ -1156,6 +1199,7 @@ jQuery(async function () {
$('#tts_pass_asterisks').on('click', onPassAsterisksClick); $('#tts_pass_asterisks').on('click', onPassAsterisksClick);
$('#tts_auto_generation').on('click', onAutoGenerationClick); $('#tts_auto_generation').on('click', onAutoGenerationClick);
$('#tts_periodic_auto_generation').on('click', onPeriodicAutoGenerationClick); $('#tts_periodic_auto_generation').on('click', onPeriodicAutoGenerationClick);
$('#tts_narrate_by_paragraphs').on('click', onNarrateByParagraphsClick);
$('#tts_narrate_user').on('click', onNarrateUserClick); $('#tts_narrate_user').on('click', onNarrateUserClick);
$('#playback_rate').on('input', function () { $('#playback_rate').on('input', function () {
@ -1177,7 +1221,6 @@ jQuery(async function () {
loadSettings(); // Depends on Extension Controls and loadTtsProvider loadSettings(); // Depends on Extension Controls and loadTtsProvider
loadTtsProvider(extension_settings.tts.currentProvider); // No dependencies loadTtsProvider(extension_settings.tts.currentProvider); // No dependencies
addAudioControl(); // Depends on Extension Controls addAudioControl(); // Depends on Extension Controls
const wrapper = new ModuleWorkerWrapper(moduleWorker);
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL); // Init depends on all the things setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL); // Init depends on all the things
eventSource.on(event_types.MESSAGE_SWIPED, resetTtsPlayback); eventSource.on(event_types.MESSAGE_SWIPED, resetTtsPlayback);
eventSource.on(event_types.CHAT_CHANGED, onChatChanged); eventSource.on(event_types.CHAT_CHANGED, onChatChanged);

View File

@ -30,6 +30,10 @@
<input type="checkbox" id="tts_periodic_auto_generation"> <input type="checkbox" id="tts_periodic_auto_generation">
<small data-i18n="Narrate by paragraphs (when streaming)">Narrate by paragraphs (when streaming)</small> <small data-i18n="Narrate by paragraphs (when streaming)">Narrate by paragraphs (when streaming)</small>
</label> </label>
<label class="checkbox_label" for="tts_narrate_by_paragraphs">
<input type="checkbox" id="tts_narrate_by_paragraphs">
<small data-i18n="Narrate by paragraphs (when not streaming)">Narrate by paragraphs (when not streaming)</small>
</label>
<label class="checkbox_label" for="tts_narrate_quoted"> <label class="checkbox_label" for="tts_narrate_quoted">
<input type="checkbox" id="tts_narrate_quoted"> <input type="checkbox" id="tts_narrate_quoted">
<small data-i18n="Only narrate quotes">Only narrate "quotes"</small> <small data-i18n="Only narrate quotes">Only narrate "quotes"</small>

View File

@ -4072,4 +4072,45 @@ $(document).ready(() => {
], ],
helpString: 'activates a movingUI preset by name', helpString: 'activates a movingUI preset by name',
})); }));
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'stop-strings',
aliases: ['stopping-strings', 'custom-stopping-strings', 'custom-stop-strings'],
helpString: `
<div>
Sets a list of custom stopping strings. Gets the list if no value is provided.
</div>
<div>
<strong>Examples:</strong>
</div>
<ul>
<li>Value must be a JSON-serialized array: <pre><code class="language-stscript">/stop-strings ["goodbye", "farewell"]</code></pre></li>
<li>Pipe characters must be escaped with a backslash: <pre><code class="language-stscript">/stop-strings ["left\\|right"]</code></pre></li>
</ul>
`,
returns: ARGUMENT_TYPE.LIST,
unnamedArgumentList: [
SlashCommandArgument.fromProps({
description: 'list of strings',
typeList: [ARGUMENT_TYPE.LIST],
acceptsMultiple: false,
isRequired: false,
}),
],
callback: (_, value) => {
if (String(value ?? '').trim()) {
const parsedValue = ((x) => { try { return JSON.parse(x.toString()); } catch { return null; } })(value);
if (!parsedValue || !Array.isArray(parsedValue)) {
throw new Error('Invalid list format. The value must be a JSON-serialized array of strings.');
}
parsedValue.forEach((item, index) => {
parsedValue[index] = String(item);
});
power_user.custom_stopping_strings = JSON.stringify(parsedValue);
$('#custom_stopping_strings').val(power_user.custom_stopping_strings);
saveSettingsDebounced();
}
return power_user.custom_stopping_strings;
},
}));
}); });

View File

@ -147,7 +147,7 @@ function registerReasoningSlashCommands() {
}), }),
], ],
callback: async (args, value) => { callback: async (args, value) => {
const messageId = !isNaN(Number(args[0])) ? Number(args[0]) : chat.length - 1; const messageId = !isNaN(Number(args.at)) ? Number(args.at) : chat.length - 1;
const message = chat[messageId]; const message = chat[messageId];
if (!message?.extra) { if (!message?.extra) {
return ''; return '';

View File

@ -42,6 +42,7 @@ import {
showMoreMessages, showMoreMessages,
stopGeneration, stopGeneration,
substituteParams, substituteParams,
syncCurrentSwipeInfoExtras,
system_avatar, system_avatar,
system_message_types, system_message_types,
this_chid, this_chid,
@ -2814,8 +2815,11 @@ async function addSwipeCallback(args, value) {
const newSwipeId = lastMessage.swipes.length - 1; const newSwipeId = lastMessage.swipes.length - 1;
if (isTrueBoolean(args.switch)) { if (isTrueBoolean(args.switch)) {
// Make sure ad-hoc changes to extras are saved before swiping away
syncCurrentSwipeInfoExtras();
lastMessage.swipe_id = newSwipeId; lastMessage.swipe_id = newSwipeId;
lastMessage.mes = lastMessage.swipes[newSwipeId]; lastMessage.mes = lastMessage.swipes[newSwipeId];
lastMessage.extra = structuredClone(lastMessage.swipe_info?.[newSwipeId]?.extra ?? lastMessage.extra ?? {});
} }
await saveChatConditional(); await saveChatConditional();