mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
merging with myself :p
This commit is contained in:
32
package-lock.json
generated
32
package-lock.json
generated
@@ -43,6 +43,7 @@
|
|||||||
"simple-git": "^3.19.1",
|
"simple-git": "^3.19.1",
|
||||||
"uniqolor": "^1.1.0",
|
"uniqolor": "^1.1.0",
|
||||||
"webp-converter": "2.3.2",
|
"webp-converter": "2.3.2",
|
||||||
|
"write-file-atomic": "^5.0.1",
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
"yargs": "^17.7.1",
|
"yargs": "^17.7.1",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0"
|
||||||
@@ -1805,6 +1806,14 @@
|
|||||||
"@types/node": "16.9.1"
|
"@types/node": "16.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/imurmurhash": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
|
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
@@ -3073,6 +3082,17 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/signal-exit": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/simple-concat": {
|
"node_modules/simple-concat": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||||
@@ -3523,6 +3543,18 @@
|
|||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/write-file-atomic": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
|
||||||
|
"dependencies": {
|
||||||
|
"imurmurhash": "^0.1.4",
|
||||||
|
"signal-exit": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.13.0",
|
"version": "8.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dqbd/tiktoken": "^1.0.2",
|
"@agnai/sentencepiece-js": "^1.1.1",
|
||||||
"@agnai/web-tokenizers": "^0.1.3",
|
"@agnai/web-tokenizers": "^0.1.3",
|
||||||
|
"@dqbd/tiktoken": "^1.0.2",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"command-exists": "^1.2.9",
|
"command-exists": "^1.2.9",
|
||||||
"compression": "^1",
|
"compression": "^1",
|
||||||
@@ -30,10 +31,10 @@
|
|||||||
"png-chunks-extract": "^1.0.0",
|
"png-chunks-extract": "^1.0.0",
|
||||||
"response-time": "^2.3.2",
|
"response-time": "^2.3.2",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"@agnai/sentencepiece-js": "^1.1.1",
|
|
||||||
"simple-git": "^3.19.1",
|
"simple-git": "^3.19.1",
|
||||||
"uniqolor": "^1.1.0",
|
"uniqolor": "^1.1.0",
|
||||||
"webp-converter": "2.3.2",
|
"webp-converter": "2.3.2",
|
||||||
|
"write-file-atomic": "^5.0.1",
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
"yargs": "^17.7.1",
|
"yargs": "^17.7.1",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0"
|
||||||
|
@@ -857,7 +857,7 @@
|
|||||||
<small>3</small>
|
<small>3</small>
|
||||||
</div>
|
</div>
|
||||||
<div data-id="4">
|
<div data-id="4">
|
||||||
<span data-i18n="Typical Sampling">Typical Sampling</span>
|
<span data-i18n="Typical Sampling">Typical P Sampling</span>
|
||||||
<small>4</small>
|
<small>4</small>
|
||||||
</div>
|
</div>
|
||||||
<div data-id="5">
|
<div data-id="5">
|
||||||
@@ -901,6 +901,21 @@
|
|||||||
<textarea id="nai_banned_tokens" class="text_pole textarea_compact" name="nai_banned_tokens" rows="2" placeholder=""></textarea>
|
<textarea id="nai_banned_tokens" class="text_pole textarea_compact" name="nai_banned_tokens" rows="2" placeholder=""></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="range-block">
|
||||||
|
<div class="range-block-title title_restorable">
|
||||||
|
<span data-i18n="Logit Bias">Logit Bias</span>
|
||||||
|
<div id="novelai_logit_bias_new_entry" class="menu_button menu_button_icon">
|
||||||
|
<i class="fa-xs fa-solid fa-plus"></i>
|
||||||
|
<small data-i18n="Add">Add</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="toggle-description justifyLeft" data-i18n="Helps to ban or reenforce the usage of certain words">
|
||||||
|
Helps to ban or reinforce the usage of certain tokens.
|
||||||
|
</div>
|
||||||
|
<div class="flex-container flexFlowColumn wide100p">
|
||||||
|
<div class="novelai_logit_bias_list"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="range-block">
|
<div class="range-block">
|
||||||
<div class="range-block-title justifyLeft" data-i18n="CFG Scale">
|
<div class="range-block-title justifyLeft" data-i18n="CFG Scale">
|
||||||
@@ -3783,6 +3798,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="novelai_logit_bias_template" class="template_element">
|
||||||
|
<div class="novelai_logit_bias_form">
|
||||||
|
<input class="novelai_logit_bias_text text_pole" data-i18n="[placeholder]Type here..." placeholder="type here..." />
|
||||||
|
<input class="novelai_logit_bias_value text_pole" type="number" min="-2" value="0" max="2" step="0.01" />
|
||||||
|
<i class="menu_button fa-solid fa-xmark novelai_logit_bias_remove"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="completion_prompt_manager_popup" class="drawer-content" style="display:none;">
|
<div id="completion_prompt_manager_popup" class="drawer-content" style="display:none;">
|
||||||
<div id="completion_prompt_manager_popup_inspect">
|
<div id="completion_prompt_manager_popup_inspect">
|
||||||
<h3>Inspect</h3>
|
<h3>Inspect</h3>
|
||||||
|
@@ -104,6 +104,7 @@ import {
|
|||||||
loadNovelSettings,
|
loadNovelSettings,
|
||||||
nai_settings,
|
nai_settings,
|
||||||
setNovelData,
|
setNovelData,
|
||||||
|
adjustNovelInstructionPrompt,
|
||||||
} from "./scripts/nai-settings.js";
|
} from "./scripts/nai-settings.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -1844,17 +1845,26 @@ function getStoppingStrings(isImpersonate, addSpace) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cohee: oobabooga's textgen always appends newline before the sequence as a stopping string
|
function addInstructSequence(sequence) {
|
||||||
// But it's a problem for Metharme which doesn't use newlines to separate them.
|
// Cohee: oobabooga's textgen always appends newline before the sequence as a stopping string
|
||||||
const wrap = (s) => power_user.instruct.wrap ? '\n' + s : s;
|
// But it's a problem for Metharme which doesn't use newlines to separate them.
|
||||||
|
const wrap = (s) => power_user.instruct.wrap ? '\n' + s : s;
|
||||||
|
// Sequence must be a non-empty string
|
||||||
|
if (typeof sequence === 'string' && sequence.length > 0) {
|
||||||
|
// If sequence is just a whitespace or newline - we don't want to make it a stopping string
|
||||||
|
// User can always add it as a custom stop string if really needed
|
||||||
|
if (sequence.trim().length > 0) {
|
||||||
|
const wrappedSequence = wrap(sequence);
|
||||||
|
// Need to respect "insert macro" setting
|
||||||
|
const stopString = power_user.instruct.macro ? substituteParams(wrappedSequence) : wrappedSequence;
|
||||||
|
result.push(stopString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (power_user.instruct.enabled) {
|
if (power_user.instruct.enabled) {
|
||||||
if (power_user.instruct.input_sequence) {
|
addInstructSequence(power_user.instruct.input_sequence);
|
||||||
result.push(substituteParams(wrap(power_user.instruct.input_sequence), name1, name2));
|
addInstructSequence(power_user.instruct.output_sequence);
|
||||||
}
|
|
||||||
if (power_user.instruct.output_sequence) {
|
|
||||||
result.push(substituteParams(wrap(power_user.instruct.output_sequence), name1, name2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (power_user.custom_stopping_strings) {
|
if (power_user.custom_stopping_strings) {
|
||||||
@@ -2311,6 +2321,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
abortController = new AbortController();
|
abortController = new AbortController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (main_api == 'novel' && quiet_prompt) {
|
||||||
|
quiet_prompt = adjustNovelInstructionPrompt(quiet_prompt);
|
||||||
|
}
|
||||||
|
|
||||||
// OpenAI doesn't need instruct mode. Use OAI main prompt instead.
|
// OpenAI doesn't need instruct mode. Use OAI main prompt instead.
|
||||||
const isInstruct = power_user.instruct.enabled && main_api !== 'openai';
|
const isInstruct = power_user.instruct.enabled && main_api !== 'openai';
|
||||||
const isImpersonate = type == "impersonate";
|
const isImpersonate = type == "impersonate";
|
||||||
|
@@ -6,7 +6,7 @@ TODO:
|
|||||||
|
|
||||||
import { saveSettingsDebounced } from "../../../script.js";
|
import { saveSettingsDebounced } from "../../../script.js";
|
||||||
import { getContext, getApiUrl, extension_settings, doExtrasFetch, ModuleWorkerWrapper, modules } from "../../extensions.js";
|
import { getContext, getApiUrl, extension_settings, doExtrasFetch, ModuleWorkerWrapper, modules } from "../../extensions.js";
|
||||||
export { MODULE_NAME, rvcVoiceConversion};
|
export { MODULE_NAME, rvcVoiceConversion };
|
||||||
|
|
||||||
const MODULE_NAME = 'RVC';
|
const MODULE_NAME = 'RVC';
|
||||||
const DEBUG_PREFIX = "<RVC module> "
|
const DEBUG_PREFIX = "<RVC module> "
|
||||||
@@ -16,25 +16,25 @@ let charactersList = [] // Updated with module worker
|
|||||||
let rvcModelsList = [] // Initialized only once
|
let rvcModelsList = [] // Initialized only once
|
||||||
let rvcModelsReceived = false;
|
let rvcModelsReceived = false;
|
||||||
|
|
||||||
function updateVoiceMapText(){
|
function updateVoiceMapText() {
|
||||||
let voiceMapText = ""
|
let voiceMapText = ""
|
||||||
for(let i in extension_settings.rvc.voiceMap) {
|
for (let i in extension_settings.rvc.voiceMap) {
|
||||||
const voice_settings = extension_settings.rvc.voiceMap[i];
|
const voice_settings = extension_settings.rvc.voiceMap[i];
|
||||||
voiceMapText += i + ":"
|
voiceMapText += i + ":"
|
||||||
+ voice_settings["modelName"] + "("
|
+ voice_settings["modelName"] + "("
|
||||||
+ voice_settings["pitchExtraction"] + ","
|
+ voice_settings["pitchExtraction"] + ","
|
||||||
+ voice_settings["pitchOffset"] + ","
|
+ voice_settings["pitchOffset"] + ","
|
||||||
+ voice_settings["indexRate"] + ","
|
+ voice_settings["indexRate"] + ","
|
||||||
+ voice_settings["filterRadius"] + ","
|
+ voice_settings["filterRadius"] + ","
|
||||||
+ voice_settings["rmsMixRate"] + ","
|
+ voice_settings["rmsMixRate"] + ","
|
||||||
+ voice_settings["protect"]
|
+ voice_settings["protect"]
|
||||||
+ "),\n"
|
+ "),\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
extension_settings.rvc.voiceMapText = voiceMapText;
|
extension_settings.rvc.voiceMapText = voiceMapText;
|
||||||
$('#rvc_voice_map').val(voiceMapText);
|
$('#rvc_voice_map').val(voiceMapText);
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Updated voice map debug text to\n",voiceMapText)
|
console.debug(DEBUG_PREFIX, "Updated voice map debug text to\n", voiceMapText)
|
||||||
}
|
}
|
||||||
|
|
||||||
//#############################//
|
//#############################//
|
||||||
@@ -43,13 +43,13 @@ function updateVoiceMapText(){
|
|||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
model:"",
|
model: "",
|
||||||
pitchOffset:0,
|
pitchOffset: 0,
|
||||||
pitchExtraction:"dio",
|
pitchExtraction: "dio",
|
||||||
indexRate:0.88,
|
indexRate: 0.88,
|
||||||
filterRadius:3,
|
filterRadius: 3,
|
||||||
rmsMixRate:1,
|
rmsMixRate: 1,
|
||||||
protect:0.33,
|
protect: 0.33,
|
||||||
voicMapText: "",
|
voicMapText: "",
|
||||||
voiceMap: {}
|
voiceMap: {}
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ function loadSettings() {
|
|||||||
if (Object.keys(extension_settings.rvc).length === 0) {
|
if (Object.keys(extension_settings.rvc).length === 0) {
|
||||||
Object.assign(extension_settings.rvc, defaultSettings)
|
Object.assign(extension_settings.rvc, defaultSettings)
|
||||||
}
|
}
|
||||||
$('#rvc_enabled').prop('checked',extension_settings.rvc.enabled);
|
$('#rvc_enabled').prop('checked', extension_settings.rvc.enabled);
|
||||||
$('#rvc_model').val(extension_settings.rvc.model);
|
$('#rvc_model').val(extension_settings.rvc.model);
|
||||||
|
|
||||||
$('#rvc_pitch_extraction').val(extension_settings.rvc.pitchExtraction);
|
$('#rvc_pitch_extraction').val(extension_settings.rvc.pitchExtraction);
|
||||||
@@ -135,12 +135,12 @@ async function onApplyClick() {
|
|||||||
const protect = $("#rvc_protect").val();
|
const protect = $("#rvc_protect").val();
|
||||||
|
|
||||||
if (character === "none") {
|
if (character === "none") {
|
||||||
toastr.error("Character not selected.", DEBUG_PREFIX+" voice mapping apply", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error("Character not selected.", DEBUG_PREFIX + " voice mapping apply", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_name == "none") {
|
if (model_name == "none") {
|
||||||
toastr.error("Model not selected.", DEBUG_PREFIX+" voice mapping apply", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error("Model not selected.", DEBUG_PREFIX + " voice mapping apply", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ async function onApplyClick() {
|
|||||||
|
|
||||||
updateVoiceMapText();
|
updateVoiceMapText();
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Updated settings of ",character,":",extension_settings.rvc.voiceMap[character])
|
console.debug(DEBUG_PREFIX, "Updated settings of ", character, ":", extension_settings.rvc.voiceMap[character])
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,12 +164,12 @@ async function onDeleteClick() {
|
|||||||
const character = $("#rvc_character_select").val();
|
const character = $("#rvc_character_select").val();
|
||||||
|
|
||||||
if (character === "none") {
|
if (character === "none") {
|
||||||
toastr.error("Character not selected.", DEBUG_PREFIX+" voice mapping delete", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error("Character not selected.", DEBUG_PREFIX + " voice mapping delete", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete extension_settings.rvc.voiceMap[character];
|
delete extension_settings.rvc.voiceMap[character];
|
||||||
console.debug(DEBUG_PREFIX,"Deleted settings of ",character);
|
console.debug(DEBUG_PREFIX, "Deleted settings of ", character);
|
||||||
updateVoiceMapText();
|
updateVoiceMapText();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
@@ -178,11 +178,11 @@ async function onClickUpload() {
|
|||||||
const url = new URL(getApiUrl());
|
const url = new URL(getApiUrl());
|
||||||
const inputFiles = $("#rvc_model_upload_file").get(0).files;
|
const inputFiles = $("#rvc_model_upload_file").get(0).files;
|
||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
|
|
||||||
for(const file of inputFiles)
|
for (const file of inputFiles)
|
||||||
formData.append(file.name, file);
|
formData.append(file.name, file);
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Sending files:",formData);
|
console.debug(DEBUG_PREFIX, "Sending files:", formData);
|
||||||
url.pathname = '/api/voice-conversion/rvc/upload-models';
|
url.pathname = '/api/voice-conversion/rvc/upload-models';
|
||||||
|
|
||||||
const apiResult = await doExtrasFetch(url, {
|
const apiResult = await doExtrasFetch(url, {
|
||||||
@@ -191,7 +191,7 @@ async function onClickUpload() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
toastr.error(apiResult.statusText, DEBUG_PREFIX+' Check extras console for errors log');
|
toastr.error(apiResult.statusText, DEBUG_PREFIX + ' Check extras console for errors log');
|
||||||
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ $(document).ready(function () {
|
|||||||
`;
|
`;
|
||||||
$('#extensions_settings').append(settingsHtml);
|
$('#extensions_settings').append(settingsHtml);
|
||||||
$("#rvc_enabled").on("click", onEnabledClick);
|
$("#rvc_enabled").on("click", onEnabledClick);
|
||||||
$("#rvc_voice_map").attr("disabled","disabled");;
|
$("#rvc_voice_map").attr("disabled", "disabled");;
|
||||||
$('#rvc_pitch_extraction').on('change', onPitchExtractionChange);
|
$('#rvc_pitch_extraction').on('change', onPitchExtractionChange);
|
||||||
$('#rvc_index_rate').on('input', onIndexRateChange);
|
$('#rvc_index_rate').on('input', onIndexRateChange);
|
||||||
$('#rvc_filter_radius').on('input', onFilterRadiusChange);
|
$('#rvc_filter_radius').on('input', onFilterRadiusChange);
|
||||||
@@ -313,7 +313,7 @@ async function get_models_list(model_id) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
toastr.error(apiResult.statusText, DEBUG_PREFIX+' Check model state request failed');
|
toastr.error(apiResult.statusText, DEBUG_PREFIX + ' Check model state request failed');
|
||||||
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ async function rvcVoiceConversion(response, character) {
|
|||||||
// Check voice map
|
// Check voice map
|
||||||
if (extension_settings.rvc.voiceMap[character] === undefined) {
|
if (extension_settings.rvc.voiceMap[character] === undefined) {
|
||||||
//toastr.error("No model is assigned to character '"+character+"', check RVC voice map in the extension menu.", DEBUG_PREFIX+'RVC Voice map error', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
//toastr.error("No model is assigned to character '"+character+"', check RVC voice map in the extension menu.", DEBUG_PREFIX+'RVC Voice map error', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
console.info(DEBUG_PREFIX,"No RVC model assign in voice map for current character "+character);
|
console.info(DEBUG_PREFIX, "No RVC model assign in voice map for current character " + character);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ async function rvcVoiceConversion(response, character) {
|
|||||||
if (!audioData.type in ['audio/mpeg', 'audio/wav', 'audio/x-wav', 'audio/wave', 'audio/webm']) {
|
if (!audioData.type in ['audio/mpeg', 'audio/wav', 'audio/x-wav', 'audio/wave', 'audio/webm']) {
|
||||||
throw `TTS received HTTP response with invalid data format. Expecting audio/mpeg, got ${audioData.type}`
|
throw `TTS received HTTP response with invalid data format. Expecting audio/mpeg, got ${audioData.type}`
|
||||||
}
|
}
|
||||||
console.log("Audio type received:",audioData.type)
|
console.log("Audio type received:", audioData.type)
|
||||||
|
|
||||||
const voice_settings = extension_settings.rvc.voiceMap[character];
|
const voice_settings = extension_settings.rvc.voiceMap[character];
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ async function rvcVoiceConversion(response, character) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
toastr.error(apiResult.statusText, DEBUG_PREFIX+' RVC Voice Conversion Failed', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(apiResult.statusText, DEBUG_PREFIX + ' RVC Voice Conversion Failed', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,22 +377,22 @@ async function rvcVoiceConversion(response, character) {
|
|||||||
|
|
||||||
async function refreshVoiceList() {
|
async function refreshVoiceList() {
|
||||||
let result = await get_models_list();
|
let result = await get_models_list();
|
||||||
result = await result.json();
|
result = await result.json();
|
||||||
rvcModelsList = result["models_list"]
|
rvcModelsList = result["models_list"]
|
||||||
|
|
||||||
$('#rvc_model_select')
|
$('#rvc_model_select')
|
||||||
.find('option')
|
.find('option')
|
||||||
.remove()
|
.remove()
|
||||||
.end()
|
.end()
|
||||||
.append('<option value="none">Select Voice</option>')
|
.append('<option value="none">Select Voice</option>')
|
||||||
.val('none')
|
.val('none')
|
||||||
|
|
||||||
for(const modelName of rvcModelsList) {
|
for (const modelName of rvcModelsList) {
|
||||||
$("#rvc_model_select").append(new Option(modelName,modelName));
|
$("#rvc_model_select").append(new Option(modelName, modelName));
|
||||||
}
|
}
|
||||||
|
|
||||||
rvcModelsReceived = true
|
rvcModelsReceived = true
|
||||||
console.debug(DEBUG_PREFIX,"Updated model list to:", rvcModelsList);
|
console.debug(DEBUG_PREFIX, "Updated model list to:", rvcModelsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function moduleWorker() {
|
async function moduleWorker() {
|
||||||
@@ -421,10 +421,10 @@ function updateCharactersList() {
|
|||||||
.append('<option value="none">Select Character</option>')
|
.append('<option value="none">Select Character</option>')
|
||||||
.val('none')
|
.val('none')
|
||||||
|
|
||||||
for(const charName of charactersList) {
|
for (const charName of charactersList) {
|
||||||
$("#rvc_character_select").append(new Option(charName,charName));
|
$("#rvc_character_select").append(new Option(charName, charName));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Updated character list to:", charactersList);
|
console.debug(DEBUG_PREFIX, "Updated character list to:", charactersList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,6 @@ TODO:
|
|||||||
- Delete useless call
|
- Delete useless call
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { saveSettingsDebounced } from "../../../script.js"
|
|
||||||
import { doExtrasFetch, extension_settings, getApiUrl, getContext, modules, ModuleWorkerWrapper } from "../../extensions.js"
|
import { doExtrasFetch, extension_settings, getApiUrl, getContext, modules, ModuleWorkerWrapper } from "../../extensions.js"
|
||||||
|
|
||||||
export { CoquiTtsProvider }
|
export { CoquiTtsProvider }
|
||||||
@@ -35,16 +34,16 @@ coquiApiModels format [language][dataset][name]:coqui-api-model-id, example:
|
|||||||
*/
|
*/
|
||||||
const languageLabels = {
|
const languageLabels = {
|
||||||
"multilingual": "Multilingual",
|
"multilingual": "Multilingual",
|
||||||
"en" : "English",
|
"en": "English",
|
||||||
"fr" : "French",
|
"fr": "French",
|
||||||
"es" : "Spanish",
|
"es": "Spanish",
|
||||||
"ja" : "Japanese"
|
"ja": "Japanese"
|
||||||
}
|
}
|
||||||
|
|
||||||
function throwIfModuleMissing() {
|
function throwIfModuleMissing() {
|
||||||
if (!modules.includes('coqui-tts')) {
|
if (!modules.includes('coqui-tts')) {
|
||||||
toastr.error(`Add coqui-tts to enable-modules and restart the Extras API.`, "Coqui TTS module not loaded.", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Add coqui-tts to enable-modules and restart the Extras API.`, "Coqui TTS module not loaded.", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
throw new Error(DEBUG_PREFIX,`Coqui TTS module not loaded.`);
|
throw new Error(DEBUG_PREFIX, `Coqui TTS module not loaded.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +59,7 @@ function updateCharactersList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentcharacters = Array.from(currentcharacters)
|
currentcharacters = Array.from(currentcharacters)
|
||||||
|
|
||||||
if (JSON.stringify(charactersList) !== JSON.stringify(currentcharacters)) {
|
if (JSON.stringify(charactersList) !== JSON.stringify(currentcharacters)) {
|
||||||
charactersList = currentcharacters
|
charactersList = currentcharacters
|
||||||
|
|
||||||
@@ -70,12 +69,12 @@ function updateCharactersList() {
|
|||||||
.end()
|
.end()
|
||||||
.append('<option value="none">Select Character</option>')
|
.append('<option value="none">Select Character</option>')
|
||||||
.val('none')
|
.val('none')
|
||||||
|
|
||||||
for(const charName of charactersList) {
|
for (const charName of charactersList) {
|
||||||
$("#coqui_character_select").append(new Option(charName,charName));
|
$("#coqui_character_select").append(new Option(charName, charName));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Updated character list to:", charactersList);
|
console.debug(DEBUG_PREFIX, "Updated character list to:", charactersList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +87,7 @@ class CoquiTtsProvider {
|
|||||||
|
|
||||||
defaultSettings = {
|
defaultSettings = {
|
||||||
voiceMap: "",
|
voiceMap: "",
|
||||||
voiceMapDict : {}
|
voiceMapDict: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
get settingsHtml() {
|
get settingsHtml() {
|
||||||
@@ -100,7 +99,7 @@ class CoquiTtsProvider {
|
|||||||
<select id="coqui_character_select">
|
<select id="coqui_character_select">
|
||||||
<!-- Populated by JS -->
|
<!-- Populated by JS -->
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<input id="coqui_remove_char_mapping" class="menu_button" type="button" value="Remove from Voice Map" />
|
<input id="coqui_remove_char_mapping" class="menu_button" type="button" value="Remove from Voice Map" />
|
||||||
|
|
||||||
<label for="coqui_model_origin">Models:</label>
|
<label for="coqui_model_origin">Models:</label>
|
||||||
@@ -149,11 +148,11 @@ class CoquiTtsProvider {
|
|||||||
// Only accept keys defined in defaultSettings
|
// Only accept keys defined in defaultSettings
|
||||||
this.settings = this.defaultSettings
|
this.settings = this.defaultSettings
|
||||||
|
|
||||||
for (const key in settings){
|
for (const key in settings) {
|
||||||
if (key in this.settings){
|
if (key in this.settings) {
|
||||||
this.settings[key] = settings[key]
|
this.settings[key] = settings[key]
|
||||||
} else {
|
} else {
|
||||||
throw DEBUG_PREFIX+`Invalid setting passed to extension: ${key}`
|
throw DEBUG_PREFIX + `Invalid setting passed to extension: ${key}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +160,7 @@ class CoquiTtsProvider {
|
|||||||
|
|
||||||
$("#coqui_api_model_div").hide();
|
$("#coqui_api_model_div").hide();
|
||||||
$("#coqui_local_model_div").hide();
|
$("#coqui_local_model_div").hide();
|
||||||
|
|
||||||
$("#coqui_api_language").show();
|
$("#coqui_api_language").show();
|
||||||
$("#coqui_api_model_name").hide();
|
$("#coqui_api_model_name").hide();
|
||||||
$("#coqui_api_model_settings").hide();
|
$("#coqui_api_model_settings").hide();
|
||||||
@@ -169,11 +168,11 @@ class CoquiTtsProvider {
|
|||||||
$("#coqui_api_model_install_button").hide();
|
$("#coqui_api_model_install_button").hide();
|
||||||
|
|
||||||
let that = this
|
let that = this
|
||||||
$("#coqui_model_origin").on("change",function(){that.onModelOriginChange()});
|
$("#coqui_model_origin").on("change", function () { that.onModelOriginChange() });
|
||||||
$("#coqui_api_language").on("change",function(){that.onModelLanguageChange()});
|
$("#coqui_api_language").on("change", function () { that.onModelLanguageChange() });
|
||||||
$("#coqui_api_model_name").on("change",function(){that.onModelNameChange()});
|
$("#coqui_api_model_name").on("change", function () { that.onModelNameChange() });
|
||||||
|
|
||||||
$("#coqui_remove_char_mapping").on("click", function(){that.onRemoveClick()});
|
$("#coqui_remove_char_mapping").on("click", function () { that.onRemoveClick() });
|
||||||
|
|
||||||
// Load characters list
|
// Load characters list
|
||||||
$('#coqui_character_select')
|
$('#coqui_character_select')
|
||||||
@@ -182,9 +181,9 @@ class CoquiTtsProvider {
|
|||||||
.end()
|
.end()
|
||||||
.append('<option value="none">Select Character</option>')
|
.append('<option value="none">Select Character</option>')
|
||||||
.val('none')
|
.val('none')
|
||||||
|
|
||||||
for(const charName of charactersList) {
|
for (const charName of charactersList) {
|
||||||
$("#coqui_character_select").append(new Option(charName,charName));
|
$("#coqui_character_select").append(new Option(charName, charName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load coqui-api settings from json file
|
// Load coqui-api settings from json file
|
||||||
@@ -228,9 +227,9 @@ class CoquiTtsProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVoiceMap(){
|
updateVoiceMap() {
|
||||||
this.settings.voiceMap = "";
|
this.settings.voiceMap = "";
|
||||||
for(let i in this.settings.voiceMapDict) {
|
for (let i in this.settings.voiceMapDict) {
|
||||||
const voice_settings = this.settings.voiceMapDict[i];
|
const voice_settings = this.settings.voiceMapDict[i];
|
||||||
this.settings.voiceMap += i + ":" + voice_settings["model_id"];
|
this.settings.voiceMap += i + ":" + voice_settings["model_id"];
|
||||||
|
|
||||||
@@ -245,9 +244,9 @@ class CoquiTtsProvider {
|
|||||||
$("#tts_voice_map").val(this.settings.voiceMap);
|
$("#tts_voice_map").val(this.settings.voiceMap);
|
||||||
extension_settings.tts.Coqui = this.settings;
|
extension_settings.tts.Coqui = this.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSettingsChange() {
|
onSettingsChange() {
|
||||||
console.debug(DEBUG_PREFIX,"Settings changes",this.settings);
|
console.debug(DEBUG_PREFIX, "Settings changes", this.settings);
|
||||||
extension_settings.tts.Coqui = this.settings;
|
extension_settings.tts.Coqui = this.settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,15 +262,15 @@ class CoquiTtsProvider {
|
|||||||
let model_setting_language = $("#coqui_api_model_settings_language").val();
|
let model_setting_language = $("#coqui_api_model_settings_language").val();
|
||||||
let model_setting_speaker = $("#coqui_api_model_settings_speaker").val();
|
let model_setting_speaker = $("#coqui_api_model_settings_speaker").val();
|
||||||
|
|
||||||
|
|
||||||
if (character === "none") {
|
if (character === "none") {
|
||||||
toastr.error(`Character not selected, please select one.`, DEBUG_PREFIX+" voice mapping character", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Character not selected, please select one.`, DEBUG_PREFIX + " voice mapping character", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateVoiceMap(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_origin == "none") {
|
if (model_origin == "none") {
|
||||||
toastr.error(`Origin not selected, please select one.`, DEBUG_PREFIX+" voice mapping origin", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Origin not selected, please select one.`, DEBUG_PREFIX + " voice mapping origin", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateVoiceMap(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -280,35 +279,35 @@ class CoquiTtsProvider {
|
|||||||
const model_id = $("#coqui_local_model_name").val();
|
const model_id = $("#coqui_local_model_name").val();
|
||||||
|
|
||||||
if (model_name == "none") {
|
if (model_name == "none") {
|
||||||
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX+" voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateVoiceMap(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.settings.voiceMapDict[character] = {model_type: "local", model_id: "local/"+model_id};
|
this.settings.voiceMapDict[character] = { model_type: "local", model_id: "local/" + model_id };
|
||||||
console.debug(DEBUG_PREFIX,"Registered new voice map: ",character,":",this.settings.voiceMapDict[character]);
|
console.debug(DEBUG_PREFIX, "Registered new voice map: ", character, ":", this.settings.voiceMapDict[character]);
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateVoiceMap(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_language == "none") {
|
if (model_language == "none") {
|
||||||
toastr.error(`Language not selected, please select one.`, DEBUG_PREFIX+" voice mapping language", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Language not selected, please select one.`, DEBUG_PREFIX + " voice mapping language", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateVoiceMap(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_name == "none") {
|
if (model_name == "none") {
|
||||||
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX+" voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Model not selected, please select one.`, DEBUG_PREFIX + " voice mapping model", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
this.updateVoiceMap(); // Overide any manual modification
|
this.updateVoiceMap(); // Overide any manual modification
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_setting_language == "none")
|
if (model_setting_language == "none")
|
||||||
model_setting_language = null;
|
model_setting_language = null;
|
||||||
|
|
||||||
if (model_setting_speaker == "none")
|
if (model_setting_speaker == "none")
|
||||||
model_setting_speaker = null;
|
model_setting_speaker = null;
|
||||||
|
|
||||||
const tokens = $('#coqui_api_model_name').val().split("/");
|
const tokens = $('#coqui_api_model_name').val().split("/");
|
||||||
const model_dataset = tokens[0];
|
const model_dataset = tokens[0];
|
||||||
const model_label = tokens[1];
|
const model_label = tokens[1];
|
||||||
@@ -328,28 +327,28 @@ class CoquiTtsProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Current voice map: ",this.settings.voiceMap);
|
console.debug(DEBUG_PREFIX, "Current voice map: ", this.settings.voiceMap);
|
||||||
|
|
||||||
this.settings.voiceMapDict[character] = {model_type: "coqui-api", model_id: model_id, model_language:model_setting_language, model_speaker:model_setting_speaker};
|
this.settings.voiceMapDict[character] = { model_type: "coqui-api", model_id: model_id, model_language: model_setting_language, model_speaker: model_setting_speaker };
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Registered new voice map: ",character,":",this.settings.voiceMapDict[character]);
|
console.debug(DEBUG_PREFIX, "Registered new voice map: ", character, ":", this.settings.voiceMapDict[character]);
|
||||||
|
|
||||||
this.updateVoiceMap();
|
this.updateVoiceMap();
|
||||||
|
|
||||||
let successMsg = character+":"+model_id;
|
let successMsg = character + ":" + model_id;
|
||||||
if (model_setting_language != null)
|
if (model_setting_language != null)
|
||||||
successMsg += "[" + model_setting_language + "]";
|
successMsg += "[" + model_setting_language + "]";
|
||||||
if (model_setting_speaker != null)
|
if (model_setting_speaker != null)
|
||||||
successMsg += "[" + model_setting_speaker + "]";
|
successMsg += "[" + model_setting_speaker + "]";
|
||||||
toastr.info(successMsg, DEBUG_PREFIX+" voice map updated", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.info(successMsg, DEBUG_PREFIX + " voice map updated", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DBG: assume voiceName is correct
|
// DBG: assume voiceName is correct
|
||||||
// TODO: check voice is correct
|
// TODO: check voice is correct
|
||||||
async getVoice(voiceName) {
|
async getVoice(voiceName) {
|
||||||
console.log(DEBUG_PREFIX,"getVoice",voiceName);
|
console.log(DEBUG_PREFIX, "getVoice", voiceName);
|
||||||
const output = {voice_id: voiceName};
|
const output = { voice_id: voiceName };
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,12 +356,12 @@ class CoquiTtsProvider {
|
|||||||
const character = $("#coqui_character_select").val();
|
const character = $("#coqui_character_select").val();
|
||||||
|
|
||||||
if (character === "none") {
|
if (character === "none") {
|
||||||
toastr.error(`Character not selected, please select one.`, DEBUG_PREFIX+" voice mapping character", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(`Character not selected, please select one.`, DEBUG_PREFIX + " voice mapping character", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo erase from voicemap
|
// Todo erase from voicemap
|
||||||
delete(this.settings.voiceMapDict[character]);
|
delete (this.settings.voiceMapDict[character]);
|
||||||
this.updateVoiceMap(); // TODO
|
this.updateVoiceMap(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +418,7 @@ class CoquiTtsProvider {
|
|||||||
|
|
||||||
$("#coqui_api_model_div").show();
|
$("#coqui_api_model_div").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// show local model list
|
// show local model list
|
||||||
if (model_origin == "local") {
|
if (model_origin == "local") {
|
||||||
@@ -435,12 +434,12 @@ class CoquiTtsProvider {
|
|||||||
const model_origin = $('#coqui_model_origin').val();
|
const model_origin = $('#coqui_model_origin').val();
|
||||||
const model_language = $('#coqui_api_language').val();
|
const model_language = $('#coqui_api_language').val();
|
||||||
console.debug(model_language);
|
console.debug(model_language);
|
||||||
|
|
||||||
if (model_language == "none") {
|
if (model_language == "none") {
|
||||||
$("#coqui_api_model_name").hide();
|
$("#coqui_api_model_name").hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#coqui_api_model_name").show();
|
$("#coqui_api_model_name").show();
|
||||||
$('#coqui_api_model_name')
|
$('#coqui_api_model_name')
|
||||||
.find('option')
|
.find('option')
|
||||||
@@ -456,9 +455,9 @@ class CoquiTtsProvider {
|
|||||||
for(let model_dataset in modelDict[model_language])
|
for(let model_dataset in modelDict[model_language])
|
||||||
for(let model_name in modelDict[model_language][model_dataset]) {
|
for(let model_name in modelDict[model_language][model_dataset]) {
|
||||||
const model_id = model_dataset + "/" + model_name
|
const model_id = model_dataset + "/" + model_name
|
||||||
const model_label = model_name + " ("+model_dataset+" dataset)"
|
const model_label = model_name + " (" + model_dataset + " dataset)"
|
||||||
$("#coqui_api_model_name").append(new Option(model_label,model_id));
|
$("#coqui_api_model_name").append(new Option(model_label, model_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async onModelNameChange() {
|
async onModelNameChange() {
|
||||||
@@ -490,15 +489,15 @@ class CoquiTtsProvider {
|
|||||||
$("#coqui_api_model_settings").show();
|
$("#coqui_api_model_settings").show();
|
||||||
$("#coqui_api_model_settings_language").show();
|
$("#coqui_api_model_settings_language").show();
|
||||||
$('#coqui_api_model_settings_language')
|
$('#coqui_api_model_settings_language')
|
||||||
.find('option')
|
.find('option')
|
||||||
.remove()
|
.remove()
|
||||||
.end()
|
.end()
|
||||||
.append('<option value="none">Select language</option>')
|
.append('<option value="none">Select language</option>')
|
||||||
.val('none');
|
.val('none');
|
||||||
|
|
||||||
for(var i = 0; i < model_settings["languages"].length; i++) {
|
for (var i = 0; i < model_settings["languages"].length; i++) {
|
||||||
const language_label = JSON.stringify(model_settings["languages"][i]).replaceAll("\"","");
|
const language_label = JSON.stringify(model_settings["languages"][i]).replaceAll("\"", "");
|
||||||
$("#coqui_api_model_settings_language").append(new Option(language_label,i));
|
$("#coqui_api_model_settings_language").append(new Option(language_label, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -509,15 +508,15 @@ class CoquiTtsProvider {
|
|||||||
$("#coqui_api_model_settings").show();
|
$("#coqui_api_model_settings").show();
|
||||||
$("#coqui_api_model_settings_speaker").show();
|
$("#coqui_api_model_settings_speaker").show();
|
||||||
$('#coqui_api_model_settings_speaker')
|
$('#coqui_api_model_settings_speaker')
|
||||||
.find('option')
|
.find('option')
|
||||||
.remove()
|
.remove()
|
||||||
.end()
|
.end()
|
||||||
.append('<option value="none">Select speaker</option>')
|
.append('<option value="none">Select speaker</option>')
|
||||||
.val('none');
|
.val('none');
|
||||||
|
|
||||||
for(var i = 0; i < model_settings["speakers"].length;i++) {
|
for (var i = 0; i < model_settings["speakers"].length; i++) {
|
||||||
const speaker_label = JSON.stringify(model_settings["speakers"][i]).replaceAll("\"","");
|
const speaker_label = JSON.stringify(model_settings["speakers"][i]).replaceAll("\"", "");
|
||||||
$("#coqui_api_model_settings_speaker").append(new Option(speaker_label,i));
|
$("#coqui_api_model_settings_speaker").append(new Option(speaker_label, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -534,7 +533,7 @@ class CoquiTtsProvider {
|
|||||||
result = await result.json();
|
result = await result.json();
|
||||||
const model_state = result["model_state"];
|
const model_state = result["model_state"];
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX," Model state:", model_state)
|
console.debug(DEBUG_PREFIX, " Model state:", model_state)
|
||||||
|
|
||||||
if (model_state == "installed") {
|
if (model_state == "installed") {
|
||||||
$("#coqui_api_model_install_status").text("Model already installed on extras server");
|
$("#coqui_api_model_install_status").text("Model already installed on extras server");
|
||||||
@@ -548,13 +547,13 @@ class CoquiTtsProvider {
|
|||||||
$("#coqui_api_model_install_status").text("Model found but incomplete try install again (maybe still downloading)"); // (remove and download again)
|
$("#coqui_api_model_install_status").text("Model found but incomplete try install again (maybe still downloading)"); // (remove and download again)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toastr.info("Click download button to install the model "+$("#coqui_api_model_name").find(":selected").text(), DEBUG_PREFIX+" model not installed", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.info("Click download button to install the model " + $("#coqui_api_model_name").find(":selected").text(), DEBUG_PREFIX + " model not installed", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
$("#coqui_api_model_install_status").text("Model not found on extras server");
|
$("#coqui_api_model_install_status").text("Model not found on extras server");
|
||||||
}
|
}
|
||||||
|
|
||||||
const onModelNameChange_pointer = this.onModelNameChange;
|
const onModelNameChange_pointer = this.onModelNameChange;
|
||||||
|
|
||||||
$("#coqui_api_model_install_button").off("click").on("click", async function (){
|
$("#coqui_api_model_install_button").off("click").on("click", async function () {
|
||||||
try {
|
try {
|
||||||
$("#coqui_api_model_install_status").text("Downloading model...");
|
$("#coqui_api_model_install_status").text("Downloading model...");
|
||||||
$("#coqui_api_model_install_button").hide();
|
$("#coqui_api_model_install_button").hide();
|
||||||
@@ -562,33 +561,33 @@ class CoquiTtsProvider {
|
|||||||
let apiResult = await CoquiTtsProvider.installModel(model_id, action);
|
let apiResult = await CoquiTtsProvider.installModel(model_id, action);
|
||||||
apiResult = await apiResult.json();
|
apiResult = await apiResult.json();
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Response:",apiResult);
|
console.debug(DEBUG_PREFIX, "Response:", apiResult);
|
||||||
|
|
||||||
if (apiResult["status"] == "done") {
|
if (apiResult["status"] == "done") {
|
||||||
$("#coqui_api_model_install_status").text("Model installed and ready to use!");
|
$("#coqui_api_model_install_status").text("Model installed and ready to use!");
|
||||||
$("#coqui_api_model_install_button").hide();
|
$("#coqui_api_model_install_button").hide();
|
||||||
onModelNameChange_pointer();
|
onModelNameChange_pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (apiResult["status"] == "downloading") {
|
if (apiResult["status"] == "downloading") {
|
||||||
toastr.error("Check extras console for progress", DEBUG_PREFIX+" already downloading", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error("Check extras console for progress", DEBUG_PREFIX + " already downloading", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
$("#coqui_api_model_install_status").text("Already downloading a model, check extras console!");
|
$("#coqui_api_model_install_status").text("Already downloading a model, check extras console!");
|
||||||
$("#coqui_api_model_install_button").show();
|
$("#coqui_api_model_install_button").show();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
toastr.error(error, DEBUG_PREFIX+" error with model download", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
toastr.error(error, DEBUG_PREFIX + " error with model download", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
onModelNameChange_pointer();
|
onModelNameChange_pointer();
|
||||||
}
|
}
|
||||||
// will refresh model status
|
// will refresh model status
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#coqui_api_model_install_button").show();
|
$("#coqui_api_model_install_button").show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//#############################//
|
//#############################//
|
||||||
// API Calls //
|
// API Calls //
|
||||||
@@ -614,7 +613,7 @@ class CoquiTtsProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
toastr.error(apiResult.statusText, DEBUG_PREFIX+' Check model state request failed');
|
toastr.error(apiResult.statusText, DEBUG_PREFIX + ' Check model state request failed');
|
||||||
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +638,7 @@ class CoquiTtsProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
toastr.error(apiResult.statusText, DEBUG_PREFIX+' Install model '+model_id+' request failed');
|
toastr.error(apiResult.statusText, DEBUG_PREFIX + ' Install model ' + model_id + ' request failed');
|
||||||
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +666,7 @@ class CoquiTtsProvider {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
toastr.error(apiResult.statusText, DEBUG_PREFIX+' Get local model list request failed');
|
toastr.error(apiResult.statusText, DEBUG_PREFIX + ' Get local model list request failed');
|
||||||
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,10 +685,10 @@ class CoquiTtsProvider {
|
|||||||
|
|
||||||
let language = "none"
|
let language = "none"
|
||||||
let speaker = "none"
|
let speaker = "none"
|
||||||
const tokens = voiceId.replaceAll("]","").replaceAll("\"","").split("[");
|
const tokens = voiceId.replaceAll("]", "").replaceAll("\"", "").split("[");
|
||||||
const model_id = tokens[0]
|
const model_id = tokens[0]
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX,"Preparing TTS request for",tokens)
|
console.debug(DEBUG_PREFIX, "Preparing TTS request for", tokens)
|
||||||
|
|
||||||
// First option
|
// First option
|
||||||
if (tokens.length > 1) {
|
if (tokens.length > 1) {
|
||||||
@@ -729,12 +728,12 @@ class CoquiTtsProvider {
|
|||||||
|
|
||||||
// Dirty hack to say not implemented
|
// Dirty hack to say not implemented
|
||||||
async fetchTtsVoiceIds() {
|
async fetchTtsVoiceIds() {
|
||||||
return [{name:"Voice samples not implemented for coqui TTS yet, search for the model samples online", voice_id:"",lang:"",}]
|
return [{ name: "Voice samples not implemented for coqui TTS yet, search for the model samples online", voice_id: "", lang: "", }]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do nothing
|
// Do nothing
|
||||||
previewTtsVoice(id) {
|
previewTtsVoice(id) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchTtsFromHistory(history_item_id) {
|
async fetchTtsFromHistory(history_item_id) {
|
||||||
@@ -753,7 +752,7 @@ async function moduleWorker() {
|
|||||||
return
|
return
|
||||||
|
|
||||||
// Initialized local model once
|
// Initialized local model once
|
||||||
if (!coquiLocalModelsReceived){
|
if (!coquiLocalModelsReceived) {
|
||||||
let result = await CoquiTtsProvider.getLocalModelList();
|
let result = await CoquiTtsProvider.getLocalModelList();
|
||||||
result = await result.json();
|
result = await result.json();
|
||||||
|
|
||||||
@@ -767,8 +766,8 @@ async function moduleWorker() {
|
|||||||
.append('<option value="none">Select model</option>')
|
.append('<option value="none">Select model</option>')
|
||||||
.val('none');
|
.val('none');
|
||||||
|
|
||||||
for(const model_dataset of coquiLocalModels)
|
for (const model_dataset of coquiLocalModels)
|
||||||
$("#coqui_local_model_name").append(new Option(model_dataset,model_dataset));
|
$("#coqui_local_model_name").append(new Option(model_dataset, model_dataset));
|
||||||
|
|
||||||
coquiLocalModelsReceived = true;
|
coquiLocalModelsReceived = true;
|
||||||
}
|
}
|
||||||
@@ -778,4 +777,4 @@ $(document).ready(function () {
|
|||||||
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
||||||
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL);
|
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL);
|
||||||
moduleWorker();
|
moduleWorker();
|
||||||
})
|
})
|
||||||
|
@@ -9,7 +9,10 @@ import {
|
|||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
import { getCfg } from "./extensions/cfg/util.js";
|
import { getCfg } from "./extensions/cfg/util.js";
|
||||||
import { MAX_CONTEXT_DEFAULT, tokenizers } from "./power-user.js";
|
import { MAX_CONTEXT_DEFAULT, tokenizers } from "./power-user.js";
|
||||||
import { getStringHash } from "./utils.js";
|
import {
|
||||||
|
getStringHash,
|
||||||
|
uuidv4
|
||||||
|
} from "./utils.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
nai_settings,
|
nai_settings,
|
||||||
@@ -49,6 +52,7 @@ const nai_settings = {
|
|||||||
cfg_uc: '',
|
cfg_uc: '',
|
||||||
banned_tokens: '',
|
banned_tokens: '',
|
||||||
order: default_order,
|
order: default_order,
|
||||||
|
logit_bias: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const nai_tiers = {
|
const nai_tiers = {
|
||||||
@@ -60,6 +64,7 @@ const nai_tiers = {
|
|||||||
|
|
||||||
let novel_data = null;
|
let novel_data = null;
|
||||||
let badWordsCache = {};
|
let badWordsCache = {};
|
||||||
|
let biasCache = undefined;
|
||||||
|
|
||||||
export function setNovelData(data) {
|
export function setNovelData(data) {
|
||||||
novel_data = data;
|
novel_data = data;
|
||||||
@@ -114,6 +119,7 @@ function loadNovelPreset(preset) {
|
|||||||
nai_settings.cfg_uc = preset.cfg_uc || '';
|
nai_settings.cfg_uc = preset.cfg_uc || '';
|
||||||
nai_settings.banned_tokens = preset.banned_tokens || '';
|
nai_settings.banned_tokens = preset.banned_tokens || '';
|
||||||
nai_settings.order = preset.order || default_order;
|
nai_settings.order = preset.order || default_order;
|
||||||
|
nai_settings.logit_bias = preset.logit_bias || [];
|
||||||
loadNovelSettingsUi(nai_settings);
|
loadNovelSettingsUi(nai_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,6 +153,7 @@ function loadNovelSettings(settings) {
|
|||||||
nai_settings.cfg_uc = settings.cfg_uc || '';
|
nai_settings.cfg_uc = settings.cfg_uc || '';
|
||||||
nai_settings.banned_tokens = settings.banned_tokens || '';
|
nai_settings.banned_tokens = settings.banned_tokens || '';
|
||||||
nai_settings.order = settings.order || default_order;
|
nai_settings.order = settings.order || default_order;
|
||||||
|
nai_settings.logit_bias = settings.logit_bias || [];
|
||||||
loadNovelSettingsUi(nai_settings);
|
loadNovelSettingsUi(nai_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +196,7 @@ function loadNovelSettingsUi(ui_settings) {
|
|||||||
|
|
||||||
$("#streaming_novel").prop('checked', ui_settings.streaming_novel);
|
$("#streaming_novel").prop('checked', ui_settings.streaming_novel);
|
||||||
sortItemsByOrder(ui_settings.order);
|
sortItemsByOrder(ui_settings.order);
|
||||||
|
displayLogitBias(ui_settings.logit_bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sliders = [
|
const sliders = [
|
||||||
@@ -398,6 +406,12 @@ export function getNovelGenerationData(finalPrompt, this_settings, this_amount_g
|
|||||||
const prefix = selectPrefix(nai_settings.prefix, finalPrompt);
|
const prefix = selectPrefix(nai_settings.prefix, finalPrompt);
|
||||||
const cfgSettings = getCfg();
|
const cfgSettings = getCfg();
|
||||||
|
|
||||||
|
let logitBias = [];
|
||||||
|
if (tokenizerType !== tokenizers.NONE && Array.isArray(nai_settings.logit_bias) && nai_settings.logit_bias.length) {
|
||||||
|
logitBias = biasCache || calculateLogitBias();
|
||||||
|
biasCache = logitBias;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"input": finalPrompt,
|
"input": finalPrompt,
|
||||||
"model": nai_settings.model_novel,
|
"model": nai_settings.model_novel,
|
||||||
@@ -418,10 +432,11 @@ export function getNovelGenerationData(finalPrompt, this_settings, this_amount_g
|
|||||||
"mirostat_lr": parseFloat(nai_settings.mirostat_lr),
|
"mirostat_lr": parseFloat(nai_settings.mirostat_lr),
|
||||||
"mirostat_tau": parseFloat(nai_settings.mirostat_tau),
|
"mirostat_tau": parseFloat(nai_settings.mirostat_tau),
|
||||||
"cfg_scale": cfgSettings?.guidanceScale ?? parseFloat(nai_settings.cfg_scale),
|
"cfg_scale": cfgSettings?.guidanceScale ?? parseFloat(nai_settings.cfg_scale),
|
||||||
"cfg_uc": cfgSettings?.negativePrompt ?? nai_settings.cfg_uc ?? "",
|
"cfg_uc": cfgSettings?.negativePrompt ?? nai_settings.cfg_uc ?? "",
|
||||||
"phrase_rep_pen": nai_settings.phrase_rep_pen,
|
"phrase_rep_pen": nai_settings.phrase_rep_pen,
|
||||||
"stop_sequences": stopSequences,
|
"stop_sequences": stopSequences,
|
||||||
"bad_words_ids": badWordIds,
|
"bad_words_ids": badWordIds,
|
||||||
|
"logit_bias_exp": logitBias,
|
||||||
"generate_until_sentence": true,
|
"generate_until_sentence": true,
|
||||||
"use_cache": false,
|
"use_cache": false,
|
||||||
"use_string": true,
|
"use_string": true,
|
||||||
@@ -487,6 +502,88 @@ function saveSamplingOrder() {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function displayLogitBias(logit_bias) {
|
||||||
|
if (!Array.isArray(logit_bias)) {
|
||||||
|
console.log('Logit bias set not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.novelai_logit_bias_list').empty();
|
||||||
|
|
||||||
|
for (const entry of logit_bias) {
|
||||||
|
if (entry) {
|
||||||
|
createLogitBiasListItem(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
biasCache = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNewLogitBiasEntry() {
|
||||||
|
const entry = { id: uuidv4(), text: '', value: 0 };
|
||||||
|
nai_settings.logit_bias.push(entry);
|
||||||
|
biasCache = undefined;
|
||||||
|
createLogitBiasListItem(entry);
|
||||||
|
saveSettingsDebounced();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLogitBiasListItem(entry) {
|
||||||
|
const id = entry.id;
|
||||||
|
const template = $('#novelai_logit_bias_template .novelai_logit_bias_form').clone();
|
||||||
|
template.data('id', id);
|
||||||
|
template.find('.novelai_logit_bias_text').val(entry.text).on('input', function () {
|
||||||
|
entry.text = $(this).val();
|
||||||
|
biasCache = undefined;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
template.find('.novelai_logit_bias_value').val(entry.value).on('input', function () {
|
||||||
|
entry.value = Number($(this).val());
|
||||||
|
biasCache = undefined;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
template.find('.novelai_logit_bias_remove').on('click', function () {
|
||||||
|
$(this).closest('.novelai_logit_bias_form').remove();
|
||||||
|
const index = nai_settings.logit_bias.indexOf(entry);
|
||||||
|
if (index > -1) {
|
||||||
|
nai_settings.logit_bias.splice(index, 1);
|
||||||
|
}
|
||||||
|
biasCache = undefined;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
$('.novelai_logit_bias_list').prepend(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateLogitBias() {
|
||||||
|
const bias_preset = nai_settings.logit_bias;
|
||||||
|
|
||||||
|
if (!Array.isArray(bias_preset) || bias_preset.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const clio = nai_settings.model_novel.includes('clio');
|
||||||
|
const kayra = nai_settings.model_novel.includes('kayra');
|
||||||
|
const tokenizerType = kayra ? tokenizers.NERD2 : (clio ? tokenizers.NERD : tokenizers.NONE);
|
||||||
|
|
||||||
|
return bias_preset.filter(b => b.text?.length > 0).map(bias => ({
|
||||||
|
bias: bias.value,
|
||||||
|
ensure_sequence_finish: false,
|
||||||
|
generate_once: false,
|
||||||
|
sequence: getTextTokens(tokenizerType, bias.text)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms instruction into compatible format for Novel AI.
|
||||||
|
* 1. Instruction must begin and end with curly braces followed and preceded by a space.
|
||||||
|
* 2. Instruction must not contain square brackets as it serves different purpose in NAI.
|
||||||
|
* @param {string} prompt Original instruction prompt
|
||||||
|
* @returns Processed prompt
|
||||||
|
*/
|
||||||
|
export function adjustNovelInstructionPrompt(prompt) {
|
||||||
|
const stripedPrompt = prompt.replace(/[\[\]]/g, '').trim();
|
||||||
|
return `{ ${stripedPrompt} }`;
|
||||||
|
}
|
||||||
|
|
||||||
export async function generateNovelWithStreaming(generate_data, signal) {
|
export async function generateNovelWithStreaming(generate_data, signal) {
|
||||||
const response = await fetch('/generate_novelai', {
|
const response = await fetch('/generate_novelai', {
|
||||||
headers: getRequestHeaders(),
|
headers: getRequestHeaders(),
|
||||||
@@ -590,4 +687,6 @@ $(document).ready(function () {
|
|||||||
console.log('Sampler toggled:', $item.data('id'), !isEnabled);
|
console.log('Sampler toggled:', $item.data('id'), !isEnabled);
|
||||||
saveSamplingOrder();
|
saveSamplingOrder();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#novelai_logit_bias_new_entry").on("click", createNewLogitBiasEntry);
|
||||||
});
|
});
|
||||||
|
@@ -10,6 +10,7 @@ import {
|
|||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
|
||||||
import { selected_group } from "./group-chats.js";
|
import { selected_group } from "./group-chats.js";
|
||||||
|
import { uuidv4 } from "./utils.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
tags,
|
tags,
|
||||||
@@ -24,7 +25,7 @@ export {
|
|||||||
importTags,
|
importTags,
|
||||||
};
|
};
|
||||||
|
|
||||||
const random_id = () => Math.round(Date.now() * Math.random()).toString();
|
const random_id = () => uuidv4();
|
||||||
const TAG_LOGIC_AND = true; // switch to false to use OR logic for combining tags
|
const TAG_LOGIC_AND = true; // switch to false to use OR logic for combining tags
|
||||||
const CHARACTER_SELECTOR = '#rm_print_characters_block > div';
|
const CHARACTER_SELECTOR = '#rm_print_characters_block > div';
|
||||||
const GROUP_MEMBER_SELECTOR = '#rm_group_add_members > div';
|
const GROUP_MEMBER_SELECTOR = '#rm_group_add_members > div';
|
||||||
|
@@ -4590,6 +4590,41 @@ toolcool-color-picker {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.novelai_logit_bias_form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
column-gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.novelai_logit_bias_text,
|
||||||
|
.novelai_logit_bias_value {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.novelai_logit_bias_list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.novelai_logit_bias_list:empty {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.novelai_logit_bias_list:empty::before {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
content: "No items";
|
||||||
|
font-weight: bolder;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.8;
|
||||||
|
min-height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
/*used to fix smallness of certain FontAwesome glyph which break button squareness*/
|
/*used to fix smallness of certain FontAwesome glyph which break button squareness*/
|
||||||
/*currently used on: CharList Import*/
|
/*currently used on: CharList Import*/
|
||||||
|
|
||||||
|
110
server.js
110
server.js
@@ -68,6 +68,8 @@ app.use(compression());
|
|||||||
app.use(responseTime());
|
app.use(responseTime());
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const writeFileAtomicSync = require('write-file-atomic').sync;
|
||||||
|
const writeFileAtomic = require('write-file-atomic');
|
||||||
const readline = require('readline');
|
const readline = require('readline');
|
||||||
const open = require('open');
|
const open = require('open');
|
||||||
|
|
||||||
@@ -551,6 +553,7 @@ app.post("/generate", jsonParser, async function (request, response_generate = r
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log("Endpoint response:", data);
|
||||||
return response_generate.send(data);
|
return response_generate.send(data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -600,18 +603,13 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
const websocket = new WebSocket(streamingUrl);
|
const websocket = new WebSocket(streamingUrl);
|
||||||
|
|
||||||
websocket.on('open', async function () {
|
websocket.on('open', async function () {
|
||||||
console.log('websocket open');
|
console.log('WebSocket opened');
|
||||||
websocket.send(JSON.stringify(request.body));
|
websocket.send(JSON.stringify(request.body));
|
||||||
});
|
});
|
||||||
|
|
||||||
websocket.on('error', (err) => {
|
|
||||||
console.error(err);
|
|
||||||
websocket.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
websocket.on('close', (code, buffer) => {
|
websocket.on('close', (code, buffer) => {
|
||||||
const reason = new TextDecoder().decode(buffer)
|
const reason = new TextDecoder().decode(buffer)
|
||||||
console.log(reason);
|
console.log("WebSocket closed (reason: %o)", reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -620,8 +618,27 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
websocket.close();
|
websocket.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rawMessage = null;
|
||||||
|
try {
|
||||||
|
// This lunacy is because the websocket can fail to connect AFTER we're awaiting 'message'... so 'message' never triggers.
|
||||||
|
// So instead we need to look for 'error' at the same time to reject the promise. And then remove the listener if we resolve.
|
||||||
|
// This is awful.
|
||||||
|
// Welcome to the shenanigan shack.
|
||||||
|
rawMessage = await new Promise(function (resolve, reject) {
|
||||||
|
websocket.once('error', reject);
|
||||||
|
websocket.once('message', (data, isBinary) => {
|
||||||
|
websocket.removeListener('error', reject);
|
||||||
|
resolve(data, isBinary);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
console.error("Socket error:", err);
|
||||||
|
websocket.close();
|
||||||
|
yield "[SillyTavern] Streaming failed:\n" + err;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const rawMessage = await new Promise(resolve => websocket.once('message', resolve));
|
|
||||||
const message = json5.parse(rawMessage);
|
const message = json5.parse(rawMessage);
|
||||||
|
|
||||||
switch (message.event) {
|
switch (message.event) {
|
||||||
@@ -672,11 +689,11 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await postAsync(api_server + "/v1/generate", args);
|
const data = await postAsync(api_server + "/v1/generate", args);
|
||||||
console.log(data);
|
console.log("Endpoint response:", data);
|
||||||
return response_generate.send(data);
|
return response_generate.send(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
retval = { error: true, status: error.status, response: error.statusText };
|
retval = { error: true, status: error.status, response: error.statusText };
|
||||||
console.log(error);
|
console.log("Endpoint error:", error);
|
||||||
try {
|
try {
|
||||||
retval.response = await error.json();
|
retval.response = await error.json();
|
||||||
retval.response = retval.response.result;
|
retval.response = retval.response.result;
|
||||||
@@ -692,7 +709,7 @@ app.post("/savechat", jsonParser, function (request, response) {
|
|||||||
var dir_name = String(request.body.avatar_url).replace('.png', '');
|
var dir_name = String(request.body.avatar_url).replace('.png', '');
|
||||||
let chat_data = request.body.chat;
|
let chat_data = request.body.chat;
|
||||||
let jsonlData = chat_data.map(JSON.stringify).join('\n');
|
let jsonlData = chat_data.map(JSON.stringify).join('\n');
|
||||||
fs.writeFileSync(`${chatsPath + sanitize(dir_name)}/${sanitize(String(request.body.file_name))}.jsonl`, jsonlData, 'utf8');
|
writeFileAtomicSync(`${chatsPath + sanitize(dir_name)}/${sanitize(String(request.body.file_name))}.jsonl`, jsonlData, 'utf8');
|
||||||
return response.send({ result: "ok" });
|
return response.send({ result: "ok" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
response.send(error);
|
response.send(error);
|
||||||
@@ -1217,7 +1234,7 @@ async function charaWrite(img_url, data, target_img, response = undefined, mes =
|
|||||||
chunks.splice(-1, 0, PNGtext.encode('chara', base64EncodedData));
|
chunks.splice(-1, 0, PNGtext.encode('chara', base64EncodedData));
|
||||||
//chunks.splice(-1, 0, text.encode('lorem', 'ipsum'));
|
//chunks.splice(-1, 0, text.encode('lorem', 'ipsum'));
|
||||||
|
|
||||||
fs.writeFileSync(charactersPath + target_img + '.png', new Buffer.from(encode(chunks)));
|
writeFileAtomicSync(charactersPath + target_img + '.png', new Buffer.from(encode(chunks)));
|
||||||
if (response !== undefined) response.send(mes);
|
if (response !== undefined) response.send(mes);
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1429,7 +1446,7 @@ app.post('/deleteuseravatar', jsonParser, function (request, response) {
|
|||||||
|
|
||||||
app.post("/setbackground", jsonParser, function (request, response) {
|
app.post("/setbackground", jsonParser, function (request, response) {
|
||||||
var bg = "#bg1 {background-image: url('../backgrounds/" + request.body.bg + "');}";
|
var bg = "#bg1 {background-image: url('../backgrounds/" + request.body.bg + "');}";
|
||||||
fs.writeFile('public/css/bg_load.css', bg, 'utf8', function (err) {
|
writeFileAtomic('public/css/bg_load.css', bg, 'utf8', function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
response.send(err);
|
response.send(err);
|
||||||
return console.log(err);
|
return console.log(err);
|
||||||
@@ -1530,7 +1547,7 @@ app.post("/downloadbackground", urlencodedParser, function (request, response) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post("/savesettings", jsonParser, function (request, response) {
|
app.post("/savesettings", jsonParser, function (request, response) {
|
||||||
fs.writeFile('public/settings.json', JSON.stringify(request.body, null, 4), 'utf8', function (err) {
|
writeFileAtomic('public/settings.json', JSON.stringify(request.body, null, 4), 'utf8', function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
response.send(err);
|
response.send(err);
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -1538,17 +1555,6 @@ app.post("/savesettings", jsonParser, function (request, response) {
|
|||||||
response.send({ result: "ok" });
|
response.send({ result: "ok" });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*fs.writeFile('public/settings.json', JSON.stringify(request.body), 'utf8', function (err) {
|
|
||||||
if (err) {
|
|
||||||
response.send(err);
|
|
||||||
return console.log(err);
|
|
||||||
//response.send(err);
|
|
||||||
} else {
|
|
||||||
//response.redirect("/");
|
|
||||||
response.send({ result: "ok" });
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function getCharaCardV2(jsonObject) {
|
function getCharaCardV2(jsonObject) {
|
||||||
@@ -1714,7 +1720,7 @@ app.post('/savetheme', jsonParser, (request, response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filename = path.join(directories.themes, sanitize(request.body.name) + '.json');
|
const filename = path.join(directories.themes, sanitize(request.body.name) + '.json');
|
||||||
fs.writeFileSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
|
writeFileAtomicSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
|
||||||
|
|
||||||
return response.sendStatus(200);
|
return response.sendStatus(200);
|
||||||
});
|
});
|
||||||
@@ -1725,7 +1731,7 @@ app.post('/savemovingui', jsonParser, (request, response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filename = path.join(directories.movingUI, sanitize(request.body.name) + '.json');
|
const filename = path.join(directories.movingUI, sanitize(request.body.name) + '.json');
|
||||||
fs.writeFileSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
|
writeFileAtomicSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
|
||||||
|
|
||||||
return response.sendStatus(200);
|
return response.sendStatus(200);
|
||||||
});
|
});
|
||||||
@@ -1736,7 +1742,7 @@ app.post('/savequickreply', jsonParser, (request, response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filename = path.join(directories.quickreplies, sanitize(request.body.name) + '.json');
|
const filename = path.join(directories.quickreplies, sanitize(request.body.name) + '.json');
|
||||||
fs.writeFileSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
|
writeFileAtomicSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
|
||||||
|
|
||||||
return response.sendStatus(200);
|
return response.sendStatus(200);
|
||||||
});
|
});
|
||||||
@@ -1853,7 +1859,7 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
|||||||
const novelai = require('./src/novelai');
|
const novelai = require('./src/novelai');
|
||||||
const isNewModel = (request.body.model.includes('clio') || request.body.model.includes('kayra'));
|
const isNewModel = (request.body.model.includes('clio') || request.body.model.includes('kayra'));
|
||||||
const isKrake = request.body.model.includes('krake');
|
const isKrake = request.body.model.includes('krake');
|
||||||
const badWordsList = isNewModel ? novelai.badWordsList : (isKrake ? novelai.krakeBadWordsList : novelai.euterpeBadWordsList);
|
const badWordsList = (isNewModel ? novelai.badWordsList : (isKrake ? novelai.krakeBadWordsList : novelai.euterpeBadWordsList)).slice();
|
||||||
|
|
||||||
// Add customized bad words for Clio and Kayra
|
// Add customized bad words for Clio and Kayra
|
||||||
if (isNewModel && Array.isArray(request.body.bad_words_ids)) {
|
if (isNewModel && Array.isArray(request.body.bad_words_ids)) {
|
||||||
@@ -1864,6 +1870,13 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add default biases for dinkus and asterism
|
||||||
|
const logit_bias_exp = isNewModel ? novelai.logitBiasExp.slice() : null;
|
||||||
|
|
||||||
|
if (Array.isArray(logit_bias_exp) && Array.isArray(request.body.logit_bias_exp)) {
|
||||||
|
logit_bias_exp.push(...request.body.logit_bias_exp);
|
||||||
|
}
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
"input": request.body.input,
|
"input": request.body.input,
|
||||||
"model": request.body.model,
|
"model": request.body.model,
|
||||||
@@ -1889,9 +1902,8 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
|||||||
"cfg_uc": request.body.cfg_uc,
|
"cfg_uc": request.body.cfg_uc,
|
||||||
"phrase_rep_pen": request.body.phrase_rep_pen,
|
"phrase_rep_pen": request.body.phrase_rep_pen,
|
||||||
"stop_sequences": request.body.stop_sequences,
|
"stop_sequences": request.body.stop_sequences,
|
||||||
//"stop_sequences": {{187}},
|
|
||||||
"bad_words_ids": badWordsList,
|
"bad_words_ids": badWordsList,
|
||||||
"logit_bias_exp": isNewModel ? novelai.logitBiasExp : null,
|
"logit_bias_exp": logit_bias_exp,
|
||||||
//generate_until_sentence = true;
|
//generate_until_sentence = true;
|
||||||
"use_cache": request.body.use_cache,
|
"use_cache": request.body.use_cache,
|
||||||
"use_string": true,
|
"use_string": true,
|
||||||
@@ -2324,7 +2336,7 @@ app.post("/exportcharacter", jsonParser, async function (request, response) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
const exifString = exif.dump(metadata);
|
const exifString = exif.dump(metadata);
|
||||||
fs.writeFileSync(metadataPath, exifString, 'binary');
|
writeFileAtomicSync(metadataPath, exifString, 'binary');
|
||||||
|
|
||||||
await webp.cwebp(filename, inputWebpPath, '-q 95');
|
await webp.cwebp(filename, inputWebpPath, '-q 95');
|
||||||
await webp.webpmux_add(inputWebpPath, outputWebpPath, metadataPath, 'exif');
|
await webp.webpmux_add(inputWebpPath, outputWebpPath, metadataPath, 'exif');
|
||||||
@@ -2406,9 +2418,9 @@ app.post("/importchat", urlencodedParser, function (request, response) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const errors = [];
|
const errors = [];
|
||||||
newChats.forEach(chat => fs.writeFile(
|
newChats.forEach(chat => writeFileAtomic(
|
||||||
`${chatsPath + avatar_url}/${ch_name} - ${humanizedISO8601DateTime()} imported.jsonl`,
|
`${chatsPath + avatar_url}/${ch_name} - ${humanizedISO8601DateTime()} imported.jsonl`,
|
||||||
chat.map(JSON.stringify).join('\n'),
|
chat.map(tryParse).filter(x => x).join('\n'),
|
||||||
'utf8',
|
'utf8',
|
||||||
(err) => err ?? errors.push(err)
|
(err) => err ?? errors.push(err)
|
||||||
)
|
)
|
||||||
@@ -2450,7 +2462,7 @@ app.post("/importchat", urlencodedParser, function (request, response) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(`${chatsPath + avatar_url}/${ch_name} - ${humanizedISO8601DateTime()} imported.jsonl`, chat.map(JSON.stringify).join('\n'), 'utf8');
|
writeFileAtomicSync(`${chatsPath + avatar_url}/${ch_name} - ${humanizedISO8601DateTime()} imported.jsonl`, chat.map(JSON.stringify).join('\n'), 'utf8');
|
||||||
|
|
||||||
response.send({ res: true });
|
response.send({ res: true });
|
||||||
} else {
|
} else {
|
||||||
@@ -2519,7 +2531,7 @@ app.post('/importworldinfo', urlencodedParser, (request, response) => {
|
|||||||
return response.status(400).send('World file must have a name');
|
return response.status(400).send('World file must have a name');
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(pathToNewFile, fileContents);
|
writeFileAtomicSync(pathToNewFile, fileContents);
|
||||||
return response.send({ name: worldName });
|
return response.send({ name: worldName });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2543,7 +2555,7 @@ app.post('/editworldinfo', jsonParser, (request, response) => {
|
|||||||
const filename = `${sanitize(request.body.name)}.json`;
|
const filename = `${sanitize(request.body.name)}.json`;
|
||||||
const pathToFile = path.join(directories.worlds, filename);
|
const pathToFile = path.join(directories.worlds, filename);
|
||||||
|
|
||||||
fs.writeFileSync(pathToFile, JSON.stringify(request.body.data, null, 4));
|
writeFileAtomicSync(pathToFile, JSON.stringify(request.body.data, null, 4));
|
||||||
|
|
||||||
return response.send({ ok: true });
|
return response.send({ ok: true });
|
||||||
});
|
});
|
||||||
@@ -2564,7 +2576,7 @@ app.post('/uploaduseravatar', urlencodedParser, async (request, response) => {
|
|||||||
|
|
||||||
const filename = request.body.overwrite_name || `${Date.now()}.png`;
|
const filename = request.body.overwrite_name || `${Date.now()}.png`;
|
||||||
const pathToNewFile = path.join(directories.avatars, filename);
|
const pathToNewFile = path.join(directories.avatars, filename);
|
||||||
fs.writeFileSync(pathToNewFile, image);
|
writeFileAtomicSync(pathToNewFile, image);
|
||||||
fs.rmSync(pathToUpload);
|
fs.rmSync(pathToUpload);
|
||||||
return response.send({ path: filename });
|
return response.send({ path: filename });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -2641,7 +2653,7 @@ app.post('/creategroup', jsonParser, (request, response) => {
|
|||||||
fs.mkdirSync(directories.groups);
|
fs.mkdirSync(directories.groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(pathToFile, fileData);
|
writeFileAtomicSync(pathToFile, fileData);
|
||||||
return response.send(groupMetadata);
|
return response.send(groupMetadata);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2653,7 +2665,7 @@ app.post('/editgroup', jsonParser, (request, response) => {
|
|||||||
const pathToFile = path.join(directories.groups, `${id}.json`);
|
const pathToFile = path.join(directories.groups, `${id}.json`);
|
||||||
const fileData = JSON.stringify(request.body);
|
const fileData = JSON.stringify(request.body);
|
||||||
|
|
||||||
fs.writeFileSync(pathToFile, fileData);
|
writeFileAtomicSync(pathToFile, fileData);
|
||||||
return response.send({ ok: true });
|
return response.send({ ok: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2707,7 +2719,7 @@ app.post('/savegroupchat', jsonParser, (request, response) => {
|
|||||||
|
|
||||||
let chat_data = request.body.chat;
|
let chat_data = request.body.chat;
|
||||||
let jsonlData = chat_data.map(JSON.stringify).join('\n');
|
let jsonlData = chat_data.map(JSON.stringify).join('\n');
|
||||||
fs.writeFileSync(pathToFile, jsonlData, 'utf8');
|
writeFileAtomicSync(pathToFile, jsonlData, 'utf8');
|
||||||
return response.send({ ok: true });
|
return response.send({ ok: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2906,7 +2918,7 @@ async function generateThumbnail(type, file) {
|
|||||||
buffer = fs.readFileSync(pathToOriginalFile);
|
buffer = fs.readFileSync(pathToOriginalFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(pathToCachedFile, buffer);
|
writeFileAtomicSync(pathToCachedFile, buffer);
|
||||||
}
|
}
|
||||||
catch (outer) {
|
catch (outer) {
|
||||||
return null;
|
return null;
|
||||||
@@ -3467,7 +3479,7 @@ app.post("/save_preset", jsonParser, function (request, response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fullpath = path.join(directory, filename);
|
const fullpath = path.join(directory, filename);
|
||||||
fs.writeFileSync(fullpath, JSON.stringify(request.body.preset, null, 4), 'utf-8');
|
writeFileAtomicSync(fullpath, JSON.stringify(request.body.preset, null, 4), 'utf-8');
|
||||||
return response.send({ name });
|
return response.send({ name });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3502,7 +3514,7 @@ app.post("/savepreset_openai", jsonParser, function (request, response) {
|
|||||||
|
|
||||||
const filename = `${name}.settings`;
|
const filename = `${name}.settings`;
|
||||||
const fullpath = path.join(directories.openAI_Settings, filename);
|
const fullpath = path.join(directories.openAI_Settings, filename);
|
||||||
fs.writeFileSync(fullpath, JSON.stringify(request.body, null, 4), 'utf-8');
|
writeFileAtomicSync(fullpath, JSON.stringify(request.body, null, 4), 'utf-8');
|
||||||
return response.send({ name });
|
return response.send({ name });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3804,7 +3816,7 @@ function migrateSecrets() {
|
|||||||
if (modified) {
|
if (modified) {
|
||||||
console.log('Writing updated settings.json...');
|
console.log('Writing updated settings.json...');
|
||||||
const settingsContent = JSON.stringify(settings);
|
const settingsContent = JSON.stringify(settings);
|
||||||
fs.writeFileSync(SETTINGS_FILE, settingsContent, "utf-8");
|
writeFileAtomicSync(SETTINGS_FILE, settingsContent, "utf-8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
@@ -4175,7 +4187,7 @@ app.post('/upload_sprite_pack', urlencodedParser, async (request, response) => {
|
|||||||
|
|
||||||
// Write sprite buffer to disk
|
// Write sprite buffer to disk
|
||||||
const pathToSprite = path.join(spritesPath, filename);
|
const pathToSprite = path.join(spritesPath, filename);
|
||||||
fs.writeFileSync(pathToSprite, buffer);
|
writeFileAtomicSync(pathToSprite, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove uploaded ZIP file
|
// Remove uploaded ZIP file
|
||||||
@@ -4400,7 +4412,7 @@ function importRisuSprites(data) {
|
|||||||
|
|
||||||
const filename = label + '.png';
|
const filename = label + '.png';
|
||||||
const pathToFile = path.join(spritesPath, filename);
|
const pathToFile = path.join(spritesPath, filename);
|
||||||
fs.writeFileSync(pathToFile, fileBase64, { encoding: 'base64' });
|
writeFileAtomicSync(pathToFile, fileBase64, { encoding: 'base64' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove additionalAssets and emotions from data (they are now in the sprites folder)
|
// Remove additionalAssets and emotions from data (they are now in the sprites folder)
|
||||||
@@ -4414,13 +4426,13 @@ function importRisuSprites(data) {
|
|||||||
function writeSecret(key, value) {
|
function writeSecret(key, value) {
|
||||||
if (!fs.existsSync(SECRETS_FILE)) {
|
if (!fs.existsSync(SECRETS_FILE)) {
|
||||||
const emptyFile = JSON.stringify({});
|
const emptyFile = JSON.stringify({});
|
||||||
fs.writeFileSync(SECRETS_FILE, emptyFile, "utf-8");
|
writeFileAtomicSync(SECRETS_FILE, emptyFile, "utf-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileContents = fs.readFileSync(SECRETS_FILE);
|
const fileContents = fs.readFileSync(SECRETS_FILE);
|
||||||
const secrets = JSON.parse(fileContents);
|
const secrets = JSON.parse(fileContents);
|
||||||
secrets[key] = value;
|
secrets[key] = value;
|
||||||
fs.writeFileSync(SECRETS_FILE, JSON.stringify(secrets), "utf-8");
|
writeFileAtomicSync(SECRETS_FILE, JSON.stringify(secrets), "utf-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
function readSecret(key) {
|
function readSecret(key) {
|
||||||
|
@@ -9,7 +9,8 @@
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const util = require("util");
|
const util = require("util");
|
||||||
const writeFile = util.promisify(fs.writeFile);
|
const writeFileAtomic = require("write-file-atomic");
|
||||||
|
const writeFile = util.promisify(writeFileAtomic);
|
||||||
const readFile = util.promisify(fs.readFile);
|
const readFile = util.promisify(fs.readFile);
|
||||||
const readdir = util.promisify(fs.readdir);
|
const readdir = util.promisify(fs.readdir);
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
|
Reference in New Issue
Block a user