From 42aa7fd316854af8e46189ea94e27171c072176f Mon Sep 17 00:00:00 2001 From: based Date: Sun, 31 Dec 2023 06:21:40 +1000 Subject: [PATCH 1/4] mistral proxy support --- public/index.html | 6 +++--- public/scripts/openai.js | 4 ++-- src/endpoints/backends/chat-completions.js | 11 ++++++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/public/index.html b/public/index.html index 28d41d52d..6366b0992 100644 --- a/public/index.html +++ b/public/index.html @@ -707,8 +707,8 @@ -
-
+
+
OpenAI / Claude Reverse Proxy
@@ -735,7 +735,7 @@
-
+
Proxy Password
diff --git a/public/scripts/openai.js b/public/scripts/openai.js index ffb4a9efe..0de1672fd 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -1562,8 +1562,8 @@ async function sendOpenAIRequest(type, messages, signal) { delete generate_data.stop; } - // Proxy is only supported for Claude and OpenAI - if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI].includes(oai_settings.chat_completion_source)) { + // Proxy is only supported for Claude, OpenAI and Mistral + if (oai_settings.reverse_proxy && [chat_completion_sources.CLAUDE, chat_completion_sources.OPENAI, chat_completion_sources.MISTRALAI].includes(oai_settings.chat_completion_source)) { validateReverseProxy(); generate_data['reverse_proxy'] = oai_settings.reverse_proxy; generate_data['proxy_password'] = oai_settings.proxy_password; diff --git a/src/endpoints/backends/chat-completions.js b/src/endpoints/backends/chat-completions.js index 712ed4485..d95415a70 100644 --- a/src/endpoints/backends/chat-completions.js +++ b/src/endpoints/backends/chat-completions.js @@ -12,7 +12,7 @@ const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sente const API_OPENAI = 'https://api.openai.com/v1'; const API_CLAUDE = 'https://api.anthropic.com/v1'; - +const API_MISTRAL = 'https://api.mistral.ai/v1'; /** * Sends a request to Claude API. * @param {express.Request} request Express request @@ -431,7 +431,8 @@ async function sendAI21Request(request, response) { * @param {express.Response} response Express response */ async function sendMistralAIRequest(request, response) { - const apiKey = readSecret(SECRET_KEYS.MISTRALAI); + const apiUrl = new URL(request.body.reverse_proxy || API_MISTRAL).toString(); + const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(SECRET_KEYS.MISTRALAI); if (!apiKey) { console.log('MistralAI API key is missing.'); @@ -495,7 +496,7 @@ async function sendMistralAIRequest(request, response) { console.log('MisralAI request:', requestBody); - const generateResponse = await fetch('https://api.mistral.ai/v1/chat/completions', config); + const generateResponse = await fetch(apiUrl + '/chat/completions', config); if (request.body.stream) { forwardFetchResponse(generateResponse, response); } else { @@ -538,8 +539,8 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o // OpenRouter needs to pass the referer: https://openrouter.ai/docs headers = { 'HTTP-Referer': request.headers.referer }; } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.MISTRALAI) { - api_url = 'https://api.mistral.ai/v1'; - api_key_openai = readSecret(SECRET_KEYS.MISTRALAI); + api_url = new URL(request.body.reverse_proxy || API_MISTRAL).toString(); + api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(SECRET_KEYS.MISTRALAI); } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.CUSTOM) { api_url = request.body.custom_url; api_key_openai = readSecret(SECRET_KEYS.CUSTOM); From aa976d0de2182538e7b28753e104c478e3cc657f Mon Sep 17 00:00:00 2001 From: based Date: Sat, 27 Jan 2024 06:21:00 +1000 Subject: [PATCH 2/4] implemented proxy preset manager --- public/index.html | 96 ++++++++++++++++++++------------- public/script.js | 9 +++- public/scripts/openai.js | 114 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 38 deletions(-) diff --git a/public/index.html b/public/index.html index 144449edb..9668bb0d1 100644 --- a/public/index.html +++ b/public/index.html @@ -747,47 +747,69 @@

-
-
- OpenAI / Claude Reverse Proxy +
+
+ Reverse Proxy +
-
- - Alternative server URL (leave empty to use the default value).
-
-
- - Remove your real OAI API Key from the API panel BEFORE typing anything - into this box. - -
- - We cannot provide support for problems encountered while using an - unofficial OpenAI proxy. - +
+
+ Proxy Name +
+
+ + This will show up as your saved preset.
+
+
+
+ +
+
+ Proxy Server URL +
+
+ + Alternative server URL (leave empty to use the default value).
+
+
+ + Remove your real OAI API Key from the API panel BEFORE typing anything + into this box. + +
+ + We cannot provide support for problems encountered while using an + unofficial OpenAI proxy. + +
+
+
+ + + Doesn't work? Try adding /v1 at the end! + +
+
+ Proxy Password +
+
+ + Will be used as a password for the proxy instead of API key.
+
+
+
+ + +
+
+ + +
-
- - - Doesn't work? Try adding /v1 at the end! - -
-
-
-
- Proxy Password -
-
- - Will be used as a password for the proxy instead of API key.
-
-
-
- - -
+
Seed diff --git a/public/script.js b/public/script.js index b21443f41..75416fedc 100644 --- a/public/script.js +++ b/public/script.js @@ -93,6 +93,9 @@ import { chat_completion_sources, getChatCompletionModel, isOpenRouterWithInstruct, + proxies, + loadProxyPresets, + selected_proxy, } from './scripts/openai.js'; import { @@ -5650,6 +5653,9 @@ async function getSettings() { // Load background loadBackgroundSettings(settings); + // Load proxy presets + loadProxyPresets(settings); + // Allow subscribers to mutate settings eventSource.emit(event_types.SETTINGS_LOADED_AFTER, settings); @@ -5728,7 +5734,6 @@ async function saveSettings(type) { } //console.log('Entering settings with name1 = '+name1); - return jQuery.ajax({ type: 'POST', url: '/api/settings/save', @@ -5756,6 +5761,8 @@ async function saveSettings(type) { kai_settings: kai_settings, oai_settings: oai_settings, background: background_settings, + proxies: proxies, + selected_proxy: selected_proxy, }, null, 4), beforeSend: function () { }, cache: false, diff --git a/public/scripts/openai.js b/public/scripts/openai.js index fd2db18c2..1cee041e0 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -317,6 +317,15 @@ const oai_settings = { seed: -1, }; +export let proxies = [ + { + name: 'None', + url: '', + password: '', + }, +]; +export let selected_proxy = proxies[0]; + let openai_setting_names; let openai_settings; @@ -3809,6 +3818,110 @@ export function isImageInliningSupported() { } } +/** + * Proxy stuff + */ +export function loadProxyPresets(settings) { + let proxyPresets = settings.proxies; + selected_proxy = settings.selected_proxy || selected_proxy; + if (!Array.isArray(proxyPresets) || proxyPresets.length === 0) { + proxyPresets = proxies; + } else { + proxies = proxyPresets; + } + + $('#openai_proxy_preset').empty(); + + for (const preset of proxyPresets) { + const option = document.createElement('option'); + option.innerText = preset.name; + option.value = preset.name; + option.selected = preset.name === 'None'; + $('#openai_proxy_preset').append(option); + } + $('#openai_proxy_preset').val(selected_proxy.name); + setProxyPreset(selected_proxy.name, selected_proxy.url, selected_proxy.password); +} + +function setProxyPreset(name, url, password) { + const preset = proxies.find(p => p.name === name); + if (preset) { + preset.url = url; + preset.password = password; + selected_proxy = preset; + } else { + let new_proxy = { name, url, password }; + proxies.push(new_proxy); + selected_proxy = new_proxy; + } + + $('#openai_reverse_proxy_name').val(name); + oai_settings.reverse_proxy = url; + $('#openai_reverse_proxy').val(oai_settings.reverse_proxy); + oai_settings.proxy_password = password; + $('#openai_proxy_password').val(oai_settings.proxy_password); + reconnectOpenAi(); +} + +function onProxyPresetChange() { + const value = String($('#openai_proxy_preset').find(':selected').val()); + const selectedPreset = proxies.find(preset => preset.name === value); + + if (selectedPreset) { + setProxyPreset(selectedPreset.name, selectedPreset.url, selectedPreset.password); + } else { + console.error(`Proxy preset "${value}" not found in proxies array.`); + } + saveSettingsDebounced(); +} + +$('#save_proxy').on('click', async function () { + const presetName = $('#openai_reverse_proxy_name').val(); + const reverseProxy = $('#openai_reverse_proxy').val(); + const proxyPassword = $('#openai_proxy_password').val(); + + setProxyPreset(presetName, reverseProxy, proxyPassword); + saveSettingsDebounced(); + toastr.success('Proxy Saved'); + if($('#openai_proxy_preset').val() !== presetName) { + const option = document.createElement('option'); + option.text = presetName; + option.value = presetName; + + $('#openai_proxy_preset').append(option); + } + $('#openai_proxy_preset').val(presetName); +}); + +$('#delete_proxy').on('click', async function () { + const presetName = $('#openai_reverse_proxy_name').val(); + const index = proxies.findIndex(preset => preset.name === presetName); + + if (index !== -1) { + proxies.splice(index, 1); + $('#openai_proxy_preset option[value="' + presetName + '"]').remove(); + + if (proxies.length > 0) { + const newIndex = Math.max(0, index - 1); + selected_proxy = proxies[newIndex]; + } else { + selected_proxy = { name: 'None', url: '', password: '' }; + } + + $('#openai_reverse_proxy_name').val(selected_proxy.name); + oai_settings.reverse_proxy = selected_proxy.url; + $('#openai_reverse_proxy').val(selected_proxy.url); + oai_settings.proxy_password = selected_proxy.password; + $('#openai_proxy_password').val(selected_proxy.password); + + saveSettingsDebounced(); + $('#openai_proxy_preset').val(selected_proxy.name); + toastr.success('Proxy Deleted'); + } else { + toastr.error(`Could not find proxy with name "${presetName}"`); + } +}); + $(document).ready(async function () { $('#test_api_button').on('click', testApiConnection); @@ -4189,4 +4302,5 @@ $(document).ready(async function () { $('#import_oai_preset').on('click', onImportPresetClick); $('#openai_proxy_password_show').on('click', onProxyPasswordShowClick); $('#customize_additional_parameters').on('click', onCustomizeParametersClick); + $('#openai_proxy_preset').on('change', onProxyPresetChange); }); From bf8eb3e7fd715a9e169af79a7fcec054d2025cda Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Mon, 29 Jan 2024 22:07:10 +0200 Subject: [PATCH 3/4] Move proxy UI to API connections panel --- public/index.html | 134 ++++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/public/index.html b/public/index.html index 03bc39fdc..c87371a27 100644 --- a/public/index.html +++ b/public/index.html @@ -746,70 +746,6 @@
-
-
-
- Reverse Proxy -
-
-
-
- Proxy Name -
-
- - This will show up as your saved preset.
-
-
-
- -
-
- Proxy Server URL -
-
- - Alternative server URL (leave empty to use the default value).
-
-
- - Remove your real OAI API Key from the API panel BEFORE typing anything - into this box. - -
- - We cannot provide support for problems encountered while using an - unofficial OpenAI proxy. - -
-
-
- - - Doesn't work? Try adding /v1 at the end! - -
-
- Proxy Password -
-
- - Will be used as a password for the proxy instead of API key.
-
-
-
- - -
-
- - - -
-
-
-
Seed @@ -2095,6 +2031,76 @@ +
+
+ Reverse Proxy +
+
+
+
+ Proxy Presets +
+
+ + Saved addresses and passwords.
+
+
+
+ + + +
+
+ Proxy Name +
+
+ + This will show up as your saved preset.
+
+
+
+ +
+
+ Proxy Server URL +
+
+ + Alternative server URL (leave empty to use the default value).
+
+
+ + Remove your real OAI API Key from the API panel BEFORE typing anything + into this box. + +
+ + We cannot provide support for problems encountered while using an + unofficial OpenAI proxy. + +
+
+
+ + + Doesn't work? Try adding /v1 at the end! + +
+
+ Proxy Password +
+
+ + Will be used as a password for the proxy instead of API key.
+
+
+
+ + +
+
+

OpenAI API key

From afd3f2c1ac841437e252dae56286a6cd05c88384 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Mon, 29 Jan 2024 22:08:38 +0200 Subject: [PATCH 4/4] Make proxy message wider --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index c87371a27..80b27da13 100644 --- a/public/index.html +++ b/public/index.html @@ -2065,7 +2065,7 @@
Proxy Server URL
-
+
Alternative server URL (leave empty to use the default value).