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);