From 6ab1435f49b83a17c66f994a41ce05303514180d Mon Sep 17 00:00:00 2001 From: Bahamut Date: Sat, 26 Aug 2023 19:53:57 +0300 Subject: [PATCH 1/3] LibreTranslate --- public/scripts/extensions/translate/index.js | 42 ++++++++++++++++++-- server.js | 42 ++++++++++++++++++++ 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/public/scripts/extensions/translate/index.js b/public/scripts/extensions/translate/index.js index bb8b1ddb7..740cc622a 100644 --- a/public/scripts/extensions/translate/index.js +++ b/public/scripts/extensions/translate/index.js @@ -135,12 +135,15 @@ const languageCodes = { 'Zulu': 'zu', }; -const KEY_REQUIRED = ['deepl']; +const KEY_REQUIRED = ['deepl','libre']; +const LOCAL_URL = ['libre']; -function showKeyButton() { +function showKeysButton() { const providerRequiresKey = KEY_REQUIRED.includes(extension_settings.translate.provider); + const providerOptionalUrl = LOCAL_URL.includes(extension_settings.translate.provider); $("#translate_key_button").toggle(providerRequiresKey); $("#translate_key_button").toggleClass('success', Boolean(secret_state[extension_settings.translate.provider])); + $("#translate_url_button").toggle(providerOptionalUrl); } function loadSettings() { @@ -153,7 +156,7 @@ function loadSettings() { $(`#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_auto_mode option[value="${extension_settings.translate.auto_mode}"]`).attr('selected', true); - showKeyButton(); + showKeysButton(); } async function translateImpersonate(text) { @@ -181,6 +184,22 @@ async function translateIncomingMessage(messageId) { updateMessageBlock(messageId, message); } +async function translateProviderLibre(text, lang) { + const response = await fetch('/libre_translate', { + method: 'POST', + headers: getRequestHeaders(), + body: JSON.stringify({ text: text, lang: lang }), + }); + + if (response.ok) { + const result = await response.text(); + return result; + } + + throw new Error(response.statusText); +} + + async function translateProviderGoogle(text, lang) { const response = await fetch('/google_translate', { method: 'POST', @@ -218,6 +237,8 @@ async function translateProviderDeepl(text, lang) { async function translate(text, lang) { try { switch (extension_settings.translate.provider) { + case 'libre': + return await translateProviderLibre(text, lang); case 'google': return await translateProviderGoogle(text, lang); case 'deepl': @@ -364,10 +385,12 @@ jQuery(() => {
+
@@ -399,7 +422,7 @@ jQuery(() => { }); $('#translation_provider').on('change', (event) => { extension_settings.translate.provider = event.target.value; - showKeyButton(); + showKeysButton(); saveSettingsDebounced(); }); $('#translation_target_language').on('change', (event) => { @@ -418,6 +441,17 @@ jQuery(() => { await writeSecret(extension_settings.translate.provider, key); toastr.success('API Key saved'); }); + $('#translate_url_button').on('click', async () => { + const optionText = $('#translation_provider option:selected').text(); + const url = await callPopup(`

${optionText} API URL

`, 'input'); + + if (url == false) { + return; + } + + await writeSecret(extension_settings.translate.provider + "_url", url); + toastr.success('API URL saved'); + }); loadSettings(); diff --git a/server.js b/server.js index 63e122fe4..a99efe9e5 100644 --- a/server.js +++ b/server.js @@ -3734,6 +3734,8 @@ const SECRET_KEYS = { NOVEL: 'api_key_novel', CLAUDE: 'api_key_claude', DEEPL: 'deepl', + LIBRE: 'libre', + LIBRE_URL: 'libre_url', OPENROUTER: 'api_key_openrouter', SCALE: 'api_key_scale', } @@ -3960,6 +3962,46 @@ app.post('/horde_generateimage', jsonParser, async (request, response) => { } }); +app.post('/libre_translate', jsonParser, async (request, response) => { + const key = readSecret(SECRET_KEYS.LIBRE); + const url = readSecret(SECRET_KEYS.LIBRE_URL); + + const text = request.body.text; + const lang = request.body.lang; + + if (!text || !lang) { + return response.sendStatus(400); + } + + console.log('Input text: ' + text); + + try { + const result = await fetch(url, { + method: "POST", + body: JSON.stringify({ + q: text, + source: "auto", + target: lang, + format: "text", + api_key: key + }), + headers: { "Content-Type": "application/json" } + }); + + if (!result.ok) { + return response.sendStatus(result.status); + } + + const json = await result.json(); + console.log('Translated text: ' + json.translatedText); + + return response.send(json.translatedText); + } catch (error) { + console.log("Translation error: " + error.message); + return response.sendStatus(500); + } +}); + app.post('/google_translate', jsonParser, async (request, response) => { const { generateRequestUrl, normaliseResponse } = require('google-translate-api-browser'); From b8531ee75ce64bc04f76e3edeaf387ba3db744e5 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 26 Aug 2023 21:56:41 +0300 Subject: [PATCH 2/3] #1022 Rewrite getstatus endpoint --- server.js | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/server.js b/server.js index a99efe9e5..ed6d7d808 100644 --- a/server.js +++ b/server.js @@ -151,7 +151,6 @@ let main_api = "kobold"; let response_generate_novel; let characters = {}; let response_dw_bg; -let response_getstatus; let first_run = true; @@ -735,14 +734,15 @@ app.post("/getchat", jsonParser, function (request, response) { } }); -app.post("/getstatus", jsonParser, async function (request, response_getstatus = response) { - if (!request.body) return response_getstatus.sendStatus(400); +app.post("/getstatus", jsonParser, async function (request, response) { + if (!request.body) return response.sendStatus(400); api_server = request.body.api_server; main_api = request.body.main_api; if (api_server.indexOf('localhost') != -1) { api_server = api_server.replace('localhost', '127.0.0.1'); } - var args = { + + const args = { headers: { "Content-Type": "application/json" } }; @@ -750,9 +750,10 @@ app.post("/getstatus", jsonParser, async function (request, response_getstatus = args.headers = Object.assign(args.headers, get_mancer_headers()); } - var url = api_server + "/v1/model"; + const url = api_server + "/v1/model"; let version = ''; let koboldVersion = {}; + if (main_api == "kobold") { try { version = (await getAsync(api_server + "/v1/info/version")).result; @@ -770,24 +771,26 @@ app.post("/getstatus", jsonParser, async function (request, response_getstatus = }; } } - client.get(url, args, async function (data, response) { - if (typeof data !== 'object') { + + try { + let data = await getAsync(url, args); + + if (!data || typeof data !== 'object') { data = {}; } - if (response.statusCode == 200) { - data.version = version; - data.koboldVersion = koboldVersion; - if (data.result == "ReadOnly") { - data.result = "no_connection"; - } - } else { - data.response = data.result; + + if (data.result == "ReadOnly") { data.result = "no_connection"; } - response_getstatus.send(data); - }).on('error', function () { - response_getstatus.send({ result: "no_connection" }); - }); + + data.version = version; + data.koboldVersion = koboldVersion; + + return response.send(data); + } catch (error) { + console.log(error); + return response.send({ result: "no_connection" }); + } }); const formatApiUrl = (url) => (url.indexOf('localhost') !== -1) From 3b7ca5e37918ce09896dfd13859843db8e142279 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 24 Aug 2023 03:21:17 +0300 Subject: [PATCH 3/3] Add fallback option for OpenRouter --- public/index.html | 11 +++++++++++ public/scripts/openai.js | 14 +++++++++++++- server.js | 4 ++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 22ece5dd6..d4a3752d8 100644 --- a/public/index.html +++ b/public/index.html @@ -1779,6 +1779,17 @@ Max prompt cost: Unknown USD +
+ +
+ + Automatically chooses an alternative model if the chosen model can't serve your request. + +
+

OpenRouter API Key

diff --git a/public/scripts/openai.js b/public/scripts/openai.js index 8393b4ed2..1e0dfa404 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -135,6 +135,7 @@ const default_settings = { claude_model: 'claude-instant-v1', windowai_model: '', openrouter_model: openrouter_website_model, + openrouter_use_fallback: true, jailbreak_system: false, reverse_proxy: '', legacy_streaming: false, @@ -173,6 +174,7 @@ const oai_settings = { claude_model: 'claude-instant-v1', windowai_model: '', openrouter_model: openrouter_website_model, + openrouter_use_fallback: true, jailbreak_system: false, reverse_proxy: '', legacy_streaming: false, @@ -804,7 +806,8 @@ async function sendOpenAIRequest(type, openai_msgs_tosend, signal) { if (isOpenRouter) { generate_data['use_openrouter'] = true; - generate_data['top_k'] = parseFloat(oai_settings.top_k_openai); + generate_data['top_k'] = Number(oai_settings.top_k_openai); + generate_data['use_fallback'] = oai_settings.openrouter_use_fallback; } if (isScale) { @@ -1130,6 +1133,7 @@ function loadOpenAISettings(data, settings) { oai_settings.claude_model = settings.claude_model ?? default_settings.claude_model; oai_settings.windowai_model = settings.windowai_model ?? default_settings.windowai_model; oai_settings.openrouter_model = settings.openrouter_model ?? default_settings.openrouter_model; + oai_settings.openrouter_use_fallback = settings.openrouter_use_fallback ?? default_settings.openrouter_use_fallback; oai_settings.chat_completion_source = settings.chat_completion_source ?? default_settings.chat_completion_source; oai_settings.api_url_scale = settings.api_url_scale ?? default_settings.api_url_scale; oai_settings.show_external_models = settings.show_external_models ?? default_settings.show_external_models; @@ -1170,6 +1174,7 @@ function loadOpenAISettings(data, settings) { $('#legacy_streaming').prop('checked', oai_settings.legacy_streaming); $('#openai_show_external_models').prop('checked', oai_settings.show_external_models); $('#openai_external_category').toggle(oai_settings.show_external_models); + $('#openrouter_use_fallback').prop('checked', oai_settings.openrouter_use_fallback); if (settings.main_prompt !== undefined) oai_settings.main_prompt = settings.main_prompt; if (settings.nsfw_prompt !== undefined) oai_settings.nsfw_prompt = settings.nsfw_prompt; @@ -1323,6 +1328,7 @@ async function saveOpenAIPreset(name, settings) { claude_model: settings.claude_model, windowai_model: settings.windowai_model, openrouter_model: settings.openrouter_model, + openrouter_use_fallback: settings.openrouter_use_fallback, temperature: settings.temp_openai, frequency_penalty: settings.freq_pen_openai, presence_penalty: settings.pres_pen_openai, @@ -1663,6 +1669,7 @@ function onSettingsPresetChange() { claude_model: ['#model_claude_select', 'claude_model', false], windowai_model: ['#model_windowai_select', 'windowai_model', false], openrouter_model: ['#model_openrouter_select', 'openrouter_model', false], + openrouter_use_fallback: ['#openrouter_use_fallback', 'openrouter_use_fallback', true], openai_max_context: ['#openai_max_context', 'openai_max_context', false], openai_max_tokens: ['#openai_max_tokens', 'openai_max_tokens', false], nsfw_toggle: ['#nsfw_toggle', 'nsfw_toggle', true], @@ -2244,6 +2251,11 @@ $(document).ready(function () { saveSettingsDebounced(); }); + $('#openrouter_use_fallback').on('input', function () { + oai_settings.openrouter_use_fallback = !!$(this).prop('checked'); + saveSettingsDebounced(); + }); + $("#api_button_openai").on("click", onConnectButtonClick); $("#openai_reverse_proxy").on("input", onReverseProxyInput); $("#model_openai_select").on("change", onModelChange); diff --git a/server.js b/server.js index ed6d7d808..49ba5fd77 100644 --- a/server.js +++ b/server.js @@ -3255,6 +3255,10 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op // OpenRouter needs to pass the referer: https://openrouter.ai/docs headers = { 'HTTP-Referer': request.headers.referer }; bodyParams = { 'transforms': ["middle-out"] }; + + if (request.body.use_fallback) { + bodyParams['route'] = 'fallback'; + } } if (!api_key_openai && !request.body.reverse_proxy) {