Translate impersonate and streaming responses. 4-state auto-mode for translation

This commit is contained in:
SillyLossy
2023-05-28 16:18:30 +03:00
parent 5a678b74c3
commit 8c48843d72
4 changed files with 97 additions and 49 deletions

View File

@ -417,6 +417,7 @@ export const event_types = {
MESSAGE_SWIPED: 'message_swiped', MESSAGE_SWIPED: 'message_swiped',
MESSAGE_SENT: 'message_sent', MESSAGE_SENT: 'message_sent',
MESSAGE_RECEIVED: 'message_received', MESSAGE_RECEIVED: 'message_received',
IMPERSONATE_READY: 'impersonate_ready',
} }
export const eventSource = new EventEmitter(); export const eventSource = new EventEmitter();
@ -1667,6 +1668,10 @@ class StreamingProcessor {
} }
} }
playMessageSound(); playMessageSound();
const eventType = this.type !== 'impersonate' ? event_types.MESSAGE_RECEIVED : event_types.IMPERSONATE_READY;
const eventData = this.type !== 'impersonate' ? this.messageId : text;
eventSource.emit(eventType, eventData);
} }
onErrorStreaming() { onErrorStreaming() {
@ -1831,7 +1836,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
sendSystemMessage(system_message_types.GENERIC, ' ', { bias: messageBias }); sendSystemMessage(system_message_types.GENERIC, ' ', { bias: messageBias });
} }
else { else {
sendMessageAsUser(textareaText, messageBias); await sendMessageAsUser(textareaText, messageBias);
} }
} }
//////////////////////////////////// ////////////////////////////////////
@ -2384,6 +2389,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
if (isImpersonate) { if (isImpersonate) {
$('#send_textarea').val(getMessage).trigger('input'); $('#send_textarea').val(getMessage).trigger('input');
generatedPromtCache = ""; generatedPromtCache = "";
eventSource.emit(event_types.IMPERSONATE_READY, getMessage);
} }
else if (type == 'quiet') { else if (type == 'quiet') {
resolve(getMessage); resolve(getMessage);
@ -2395,15 +2401,14 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
else { else {
({ type, getMessage } = saveReply('appendFinal', getMessage, this_mes_is_name, title)); ({ type, getMessage } = saveReply('appendFinal', getMessage, this_mes_is_name, title));
} }
eventSource.emit(event_types.MESSAGE_RECEIVED, (chat.length - 1));
} }
activateSendButtons(); activateSendButtons();
if (type !== 'quiet') { if (type !== 'quiet') {
playMessageSound(); playMessageSound();
eventSource.emit(event_types.MESSAGE_RECEIVED, (chat.length - 1));
} }
generate_loop_counter = 0; generate_loop_counter = 0;
} else { } else {
++generate_loop_counter; ++generate_loop_counter;
@ -2522,7 +2527,7 @@ export function replaceBiasMarkup(str) {
return (str ?? '').replace(/{{(\*?.*\*?)}}/g, ''); return (str ?? '').replace(/{{(\*?.*\*?)}}/g, '');
} }
function sendMessageAsUser(textareaText, messageBias) { async function sendMessageAsUser(textareaText, messageBias) {
chat[chat.length] = {}; chat[chat.length] = {};
chat[chat.length - 1]['name'] = name1; chat[chat.length - 1]['name'] = name1;
chat[chat.length - 1]['is_user'] = true; chat[chat.length - 1]['is_user'] = true;
@ -2537,7 +2542,9 @@ function sendMessageAsUser(textareaText, messageBias) {
} }
addOneMessage(chat[chat.length - 1]); addOneMessage(chat[chat.length - 1]);
eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1)); // Wait for all handlers to finish before continuing with the prompt
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
console.log('message sent as user');
} }
function getMaxContextSize() { function getMaxContextSize() {

View File

@ -48,7 +48,7 @@ EventEmitter.prototype.removeListener = function (event, listener) {
} }
}; };
EventEmitter.prototype.emit = function (event) { EventEmitter.prototype.emit = async function (event) {
var i, listeners, length, args = [].slice.call(arguments, 1); var i, listeners, length, args = [].slice.call(arguments, 1);
if (typeof this.events[event] === 'object') { if (typeof this.events[event] === 'object') {
@ -56,7 +56,7 @@ EventEmitter.prototype.emit = function (event) {
length = listeners.length; length = listeners.length;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
listeners[i].apply(this, args); await listeners[i].apply(this, args);
} }
} }
}; };
@ -68,4 +68,4 @@ EventEmitter.prototype.once = function (event, listener) {
}); });
}; };
export { EventEmitter } export { EventEmitter }

View File

@ -1,10 +1,18 @@
import { eventSource, event_types, getRequestHeaders, messageFormatting, saveSettingsDebounced } from "../../../script.js"; import { eventSource, event_types, getRequestHeaders, messageFormatting, saveSettingsDebounced } from "../../../script.js";
import { extension_settings, getContext } from "../../extensions.js"; import { extension_settings, getContext } from "../../extensions.js";
const autoModeOptions = {
NONE: 'none',
RESPONSES: 'responses',
INPUT: 'inputs',
BOTH: 'both',
};
const defaultSettings = { const defaultSettings = {
target_language: 'en', target_language: 'en',
internal_language: 'en',
provider: 'google', provider: 'google',
auto: false, auto_mode: autoModeOptions.NONE,
}; };
const languageCodes = { const languageCodes = {
@ -115,13 +123,20 @@ const languageCodes = {
}; };
function loadSettings() { function loadSettings() {
if (Object.keys(extension_settings.translate).length === 0) { for (const key in defaultSettings) {
Object.assign(extension_settings.translate, defaultSettings); if (!extension_settings.translate.hasOwnProperty(key)) {
extension_settings.translate[key] = defaultSettings[key];
}
} }
$(`#translation_provider option[value="${extension_settings.translate.provider}"]`).attr('selected', true); $(`#translation_provider option[value="${extension_settings.translate.provider}"]`).attr('selected', true);
$(`#translation_target_language option[value="${extension_settings.translate.target_language}"]`).attr('selected', true); $(`#translation_target_language option[value="${extension_settings.translate.target_language}"]`).attr('selected', true);
$('#translation_auto').prop('checked', extension_settings.translate.auto); $(`#translation_auto_mode option[value="${extension_settings.translate.auto_mode}"]`).attr('selected', true);
}
async function translateImpersonate(text) {
const translatedText = await translate(text, extension_settings.translate.target_language);
$("#send_textarea").val(translatedText);
} }
async function translateIncomingMessage(messageId) { async function translateIncomingMessage(messageId) {
@ -137,7 +152,7 @@ async function translateIncomingMessage(messageId) {
return; return;
} }
const translation = await translate(message.mes); const translation = await translate(message.mes, extension_settings.translate.target_language);
message.extra.display_text = translation; message.extra.display_text = translation;
$(`#chat .mes[mesid="${messageId}"] .mes_text`).html(messageFormatting(translation, message.name, message.is_system, message.is_user)); $(`#chat .mes[mesid="${messageId}"] .mes_text`).html(messageFormatting(translation, message.name, message.is_system, message.is_user));
@ -145,11 +160,11 @@ async function translateIncomingMessage(messageId) {
context.saveChat(); context.saveChat();
} }
async function translateProviderGoogle(text) { async function translateProviderGoogle(text, lang) {
const response = await fetch('/google_translate', { const response = await fetch('/google_translate', {
method: 'POST', method: 'POST',
headers: getRequestHeaders(), headers: getRequestHeaders(),
body: JSON.stringify({ text: text, lang: extension_settings.translate.target_language }), body: JSON.stringify({ text: text, lang: lang }),
}); });
if (response.ok) { if (response.ok) {
@ -160,11 +175,11 @@ async function translateProviderGoogle(text) {
throw new Error(response.statusText); throw new Error(response.statusText);
} }
async function translate(text) { async function translate(text, lang) {
try { try {
switch (extension_settings.translate.provider) { switch (extension_settings.translate.provider) {
case 'google': case 'google':
return await translateProviderGoogle(text); return await translateProviderGoogle(text, lang);
default: default:
console.error('Unknown translation provider', extension_settings.translate.provider); console.error('Unknown translation provider', extension_settings.translate.provider);
return text; return text;
@ -176,7 +191,31 @@ async function translate(text) {
} }
async function translateOutgoingMessage(messageId) { async function translateOutgoingMessage(messageId) {
alert('translateOutgoingMessage', messageId); const context = getContext();
const message = context.chat[messageId];
if (typeof message.extra !== 'object') {
message.extra = {};
}
const originalText = message.mes;
message.extra.display_text = originalText;
$(`#chat .mes[mesid="${messageId}"] .mes_text`).html(messageFormatting(originalText, message.name, message.is_system, message.is_user));
message.mes = await translate(originalText, extension_settings.translate.internal_language);
console.log('translateOutgoingMessage', messageId);
}
function shouldTranslate(types) {
return types.includes(extension_settings.translate.auto_mode);
}
function createEventHandler(translateFunction, shouldTranslateFunction) {
return async (data) => {
if (shouldTranslateFunction()) {
await translateFunction(data);
}
};
} }
jQuery(() => { jQuery(() => {
@ -188,10 +227,13 @@ jQuery(() => {
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div> <div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div> </div>
<div class="inline-drawer-content"> <div class="inline-drawer-content">
<label for="translation_auto" class="checkbox_label"> <label for="translation_auto_mode" class="checkbox_label">Auto-mode</label>
<input type="checkbox" id="translation_auto" /> <select id="translation_auto_mode">
Auto-mode <option value="none">None</option>
</label> <option value="responses">Translate responses</option>
<option value="inputs">Translate inputs</option>
<option value="both">Translate both</option>
</select>
<label for="translation_provider">Provider</label> <label for="translation_provider">Provider</label>
<select id="translation_provider" name="provider"> <select id="translation_provider" name="provider">
<option value="google">Google</option> <option value="google">Google</option>
@ -203,33 +245,13 @@ jQuery(() => {
</div>`; </div>`;
$('#extensions_settings').append(html); $('#extensions_settings').append(html);
for (const [key, value] of Object.entries(languageCodes)) { for (const [key, value] of Object.entries(languageCodes)) {
$('#translation_target_language').append(`<option value="${value}">${key}</option>`); $('#translation_target_language').append(`<option value="${value}">${key}</option>`);
} }
loadSettings(); $('#translation_auto_mode').on('change', (event) => {
eventSource.on(event_types.MESSAGE_RECEIVED, async (messageId) => { extension_settings.translate.auto_mode = event.target.value;
if (!extension_settings.translate.auto) {
return;
}
await translateIncomingMessage(messageId);
});
eventSource.on(event_types.MESSAGE_SWIPED, async (messageId) => {
if (!extension_settings.translate.auto) {
return;
}
await translateIncomingMessage(messageId);
});
eventSource.on(event_types.MESSAGE_SENT, async (messageId) => {
if (!extension_settings.translate.auto) {
return;
}
await translateOutgoingMessage(messageId);
});
$('#translation_auto').on('input', (event) => {
extension_settings.translate.auto = event.target.checked;
saveSettingsDebounced(); saveSettingsDebounced();
}); });
$('#translation_provider').on('change', (event) => { $('#translation_provider').on('change', (event) => {
@ -244,5 +266,20 @@ jQuery(() => {
const messageId = $(this).closest('.mes').attr('mesid'); const messageId = $(this).closest('.mes').attr('mesid');
translateIncomingMessage(messageId); translateIncomingMessage(messageId);
}); });
loadSettings();
const incomingTypes = [autoModeOptions.RESPONSES, autoModeOptions.BOTH];
const outgoingTypes = [autoModeOptions.INPUT, autoModeOptions.BOTH];
const handleIncomingMessage = createEventHandler(translateIncomingMessage, () => shouldTranslate(incomingTypes));
const handleOutgoingMessage = createEventHandler(translateOutgoingMessage, () => shouldTranslate(outgoingTypes));
const handleImpersonateReady = createEventHandler(translateImpersonate, () => shouldTranslate(incomingTypes));
eventSource.on(event_types.MESSAGE_RECEIVED, handleIncomingMessage);
eventSource.on(event_types.MESSAGE_SWIPED, handleIncomingMessage);
eventSource.on(event_types.MESSAGE_SENT, handleOutgoingMessage);
eventSource.on(event_types.IMPERSONATE_READY, handleImpersonateReady);
document.body.classList.add('translate'); document.body.classList.add('translate');
}); });

View File

@ -4,6 +4,8 @@ import {
chat, chat,
chat_metadata, chat_metadata,
default_avatar, default_avatar,
eventSource,
event_types,
extractMessageBias, extractMessageBias,
getThumbnailUrl, getThumbnailUrl,
replaceBiasMarkup, replaceBiasMarkup,
@ -31,7 +33,7 @@ class SlashCommandParser {
if ([command, ...aliases].some(x => this.commands.hasOwnProperty(x))) { if ([command, ...aliases].some(x => this.commands.hasOwnProperty(x))) {
console.trace('WARN: Duplicate slash command registered!'); console.trace('WARN: Duplicate slash command registered!');
} }
this.commands[command] = fnObj; this.commands[command] = fnObj;
if (Array.isArray(aliases)) { if (Array.isArray(aliases)) {
@ -105,7 +107,7 @@ function setNarratorName(_, text) {
saveChatConditional(); saveChatConditional();
} }
function sendMessageAs(_, text) { async function sendMessageAs(_, text) {
if (!text) { if (!text) {
return; return;
} }
@ -151,10 +153,11 @@ function sendMessageAs(_, text) {
chat.push(message); chat.push(message);
addOneMessage(message); addOneMessage(message);
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
saveChatConditional(); saveChatConditional();
} }
function sendNarratorMessage(_, text) { async function sendNarratorMessage(_, text) {
if (!text) { if (!text) {
return; return;
} }
@ -180,6 +183,7 @@ function sendNarratorMessage(_, text) {
chat.push(message); chat.push(message);
addOneMessage(message); addOneMessage(message);
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
saveChatConditional(); saveChatConditional();
} }
@ -238,4 +242,4 @@ function executeSlashCommands(text) {
const newText = lines.filter(x => linesToRemove.indexOf(x) === -1).join('\n'); const newText = lines.filter(x => linesToRemove.indexOf(x) === -1).join('\n');
return { interrupt, newText }; return { interrupt, newText };
} }