diff --git a/public/index.html b/public/index.html
index 3e0a84bb2..4b50f1477 100644
--- a/public/index.html
+++ b/public/index.html
@@ -582,7 +582,7 @@
Wraps activated World Info entries before inserting into the prompt. Use
- {0} to mark a place where the content is inserted.
+ {0}
to mark a place where the content is inserted.
@@ -596,7 +596,7 @@
- Use {{scenario}} to mark a place where the content is inserted.
+ Use {{scenario}}
to mark a place where the content is inserted.
@@ -610,7 +610,7 @@
- Use {{personality}} to mark a place where the content is inserted.
+ Use {{personality}}
to mark a place where the content is inserted.
@@ -1516,7 +1516,7 @@
-
+
Send inline images
@@ -1797,7 +1797,7 @@
oobabooga/text-generation-webui
- Make sure you run it with --api flag
+ Make sure you run it with --api
flag
@@ -2231,7 +2231,7 @@
- Custom API Key
+
+ Custom API Key
+ (Optional)
+
@@ -2254,9 +2257,7 @@
Available Models
-
- -- Connect to the API --
-
+
diff --git a/public/scripts/RossAscends-mods.js b/public/scripts/RossAscends-mods.js
index 1827b1b26..7a0c648f3 100644
--- a/public/scripts/RossAscends-mods.js
+++ b/public/scripts/RossAscends-mods.js
@@ -399,7 +399,7 @@ function RA_autoconnect(PrevApi) {
|| (secret_state[SECRET_KEYS.AI21] && oai_settings.chat_completion_source == chat_completion_sources.AI21)
|| (secret_state[SECRET_KEYS.MAKERSUITE] && oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE)
|| (secret_state[SECRET_KEYS.MISTRALAI] && oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI)
- || (secret_state[SECRET_KEYS.CUSTOM] && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM)
+ || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM)
) {
$('#api_button_openai').trigger('click');
}
diff --git a/public/scripts/extensions/caption/index.js b/public/scripts/extensions/caption/index.js
index ec126fcda..ca31ac0a3 100644
--- a/public/scripts/extensions/caption/index.js
+++ b/public/scripts/extensions/caption/index.js
@@ -277,6 +277,7 @@ jQuery(function () {
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'google' && secret_state[SECRET_KEYS.MAKERSUITE]) ||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'ollama' && textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) ||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'llamacpp' && textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) ||
+ (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'custom') ||
extension_settings.caption.source === 'local' ||
extension_settings.caption.source === 'horde';
@@ -345,6 +346,7 @@ jQuery(function () {
OpenAI
OpenRouter
Google MakerSuite
+ Custom (OpenAI-compatible)
@@ -358,6 +360,7 @@ jQuery(function () {
bakllava:latest
llava:latest
[Currently loaded]
+ [Currently selected]
diff --git a/public/scripts/extensions/shared.js b/public/scripts/extensions/shared.js
index 4947f9b32..a59f5d7b5 100644
--- a/public/scripts/extensions/shared.js
+++ b/public/scripts/extensions/shared.js
@@ -24,6 +24,7 @@ export async function getMultimodalCaption(base64Img, prompt) {
const isGoogle = extension_settings.caption.multimodal_api === 'google';
const isOllama = extension_settings.caption.multimodal_api === 'ollama';
const isLlamaCpp = extension_settings.caption.multimodal_api === 'llamacpp';
+ const isCustom = extension_settings.caption.multimodal_api === 'custom';
const base64Bytes = base64Img.length * 0.75;
const compressionLimit = 2 * 1024 * 1024;
if (['google', 'openrouter'].includes(extension_settings.caption.multimodal_api) && base64Bytes > compressionLimit) {
@@ -68,6 +69,11 @@ export async function getMultimodalCaption(base64Img, prompt) {
requestBody.server_url = textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP];
}
+ if (isCustom) {
+ requestBody.server_url = oai_settings.custom_url;
+ requestBody.model = oai_settings.custom_model || 'gpt-4-vision-preview';
+ }
+
function getEndpointUrl() {
switch (extension_settings.caption.multimodal_api) {
case 'google':
@@ -119,4 +125,8 @@ function throwIfInvalidModel() {
if (extension_settings.caption.multimodal_api === 'llamacpp' && !textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) {
throw new Error('LlamaCPP server URL is not set.');
}
+
+ if (extension_settings.caption.multimodal_api === 'custom' && !oai_settings.custom_url) {
+ throw new Error('Custom API URL is not set.');
+ }
}
diff --git a/public/scripts/openai.js b/public/scripts/openai.js
index d189e9f57..dbfc66416 100644
--- a/public/scripts/openai.js
+++ b/public/scripts/openai.js
@@ -1333,6 +1333,23 @@ function saveModelList(data) {
$('#model_openai_select').val(model).trigger('change');
}
}
+
+ if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) {
+ $('#model_custom_select').empty();
+ $('#model_custom_select').append('None ');
+ model_list.forEach((model) => {
+ $('#model_custom_select').append(
+ $('', {
+ value: model.id,
+ text: model.id,
+ selected: model.id == oai_settings.custom_model,
+ }));
+ });
+
+ if (!oai_settings.custom_model && model_list.length > 0) {
+ $('#model_custom_select').val(model_list[0].id).trigger('change');
+ }
+ }
}
function appendOpenRouterOptions(model_list, groupModels = false, sort = false) {
@@ -1461,6 +1478,7 @@ async function sendOpenAIRequest(type, messages, signal) {
const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE;
const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI;
const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI;
+ const isCustom = oai_settings.chat_completion_source == chat_completion_sources.CUSTOM;
const isTextCompletion = (isOAI && textCompletionModels.includes(oai_settings.openai_model)) || (isOpenRouter && oai_settings.openrouter_force_instruct && power_user.instruct.enabled);
const isQuiet = type === 'quiet';
const isImpersonate = type === 'impersonate';
@@ -1572,7 +1590,11 @@ async function sendOpenAIRequest(type, messages, signal) {
generate_data['safe_mode'] = false; // already defaults to false, but just incase they change that in the future.
}
- if ((isOAI || isOpenRouter || isMistral) && oai_settings.seed >= 0) {
+ if (isCustom) {
+ generate_data['custom_url'] = oai_settings.custom_url;
+ }
+
+ if ((isOAI || isOpenRouter || isMistral || isCustom) && oai_settings.seed >= 0) {
generate_data['seed'] = oai_settings.seed;
}
@@ -2478,7 +2500,8 @@ async function getStatusOpen() {
}
if (oai_settings.chat_completion_source === chat_completion_sources.CUSTOM) {
- custom_url: oai_settings.custom_url;
+ $('#model_custom_select').empty();
+ data.custom_url = oai_settings.custom_url;
}
const canBypass = (oai_settings.chat_completion_source === chat_completion_sources.OPENAI && oai_settings.bypass_status_check) || oai_settings.chat_completion_source === chat_completion_sources.CUSTOM;
@@ -3525,7 +3548,7 @@ export function isImageInliningSupported() {
const gpt4v = 'gpt-4-vision';
const geminiProV = 'gemini-pro-vision';
- const llava13b = 'llava-13b';
+ const llava = 'llava';
if (!oai_settings.image_inlining) {
return false;
@@ -3537,7 +3560,9 @@ export function isImageInliningSupported() {
case chat_completion_sources.MAKERSUITE:
return oai_settings.google_model.includes(geminiProV);
case chat_completion_sources.OPENROUTER:
- return oai_settings.openrouter_model.includes(gpt4v) || oai_settings.openrouter_model.includes(llava13b);
+ return !oai_settings.openrouter_force_instruct && (oai_settings.openrouter_model.includes(gpt4v) || oai_settings.openrouter_model.includes(llava));
+ case chat_completion_sources.CUSTOM:
+ return oai_settings.custom_model.includes(gpt4v) || oai_settings.custom_model.includes(llava) || oai_settings.custom_model.includes(geminiProV);
default:
return false;
}
diff --git a/src/endpoints/openai.js b/src/endpoints/openai.js
index cb98cf274..f2042281d 100644
--- a/src/endpoints/openai.js
+++ b/src/endpoints/openai.js
@@ -24,7 +24,11 @@ router.post('/caption-image', jsonParser, async (request, response) => {
key = request.body.proxy_password;
}
- if (!key && !request.body.reverse_proxy) {
+ if (request.body.api === 'custom') {
+ key = readSecret(SECRET_KEYS.CUSTOM);
+ }
+
+ if (!key && !request.body.reverse_proxy && request.body.api !== 'custom') {
console.log('No key found for API', request.body.api);
return response.sendStatus(400);
}
@@ -69,6 +73,10 @@ router.post('/caption-image', jsonParser, async (request, response) => {
apiUrl = `${request.body.reverse_proxy}/chat/completions`;
}
+ if (request.body.api === 'custom') {
+ apiUrl = `${request.body.server_url}/chat/completions`;
+ }
+
const result = await fetch(apiUrl, {
method: 'POST',
headers: {