diff --git a/public/script.js b/public/script.js
index e038228d7..88bb3d1aa 100644
--- a/public/script.js
+++ b/public/script.js
@@ -886,6 +886,7 @@ async function getStatus() {
use_mancer: main_api == "textgenerationwebui" ? isMancer() : false,
use_aphrodite: main_api == "textgenerationwebui" ? isAphrodite() : false,
use_ooba: main_api == "textgenerationwebui" ? isOoba() : false,
+ legacy_api: main_api == "textgenerationwebui" ? textgenerationwebui_settings.legacy_api : false,
}),
signal: abortStatusCheck.signal,
});
@@ -2548,6 +2549,12 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
return;
}
+ if (main_api === 'textgenerationwebui' && textgenerationwebui_settings.streaming && textgenerationwebui_settings.legacy_api) {
+ toastr.error('Streaming is not supported for the legacy API schema. Update TextGen WebUI and use --extension openai to enable streaming.', undefined, { timeOut: 10000, preventDuplicates: true, });
+ unblockGeneration();
+ return;
+ }
+
if (isHordeGenerationNotAllowed()) {
unblockGeneration();
return;
diff --git a/public/scripts/textgen-settings.js b/public/scripts/textgen-settings.js
index 2d353eb4d..294019f41 100644
--- a/public/scripts/textgen-settings.js
+++ b/public/scripts/textgen-settings.js
@@ -78,6 +78,7 @@ const textgenerationwebui_settings = {
//prompt_log_probs_aphrodite: 0,
type: textgen_types.OOBA,
mancer_model: 'mytholite',
+ legacy_api: false,
};
export let textgenerationwebui_banned_in_macros = [];
@@ -120,6 +121,7 @@ const setting_names = [
"negative_prompt",
"grammar_string",
"banned_tokens",
+ "legacy_api",
//'n_aphrodite',
//'best_of_aphrodite',
//'ignore_eos_token_aphrodite',
@@ -148,9 +150,8 @@ async function selectPreset(name) {
function formatTextGenURL(value) {
try {
const url = new URL(value);
- if (url.pathname === '/api' && textgenerationwebui_settings.type === textgen_types.OOBA) {
- url.pathname = '/';
- toastr.info(`Legacy API URL detected, please make sure you updated ooba-webui to the latest version.`);
+ if (url.pathname === '/api' && !textgenerationwebui_settings.legacy_api) {
+ toastr.info(`Enable compatibility mode or update ooba-webui to the latest version.`, 'Legacy API URL detected. Generation may fail.');
}
return url.toString();
} catch { } // Just using URL as a validation check
@@ -516,6 +517,7 @@ export function getTextGenGenerationData(finalPrompt, this_amount_gen, isImperso
'use_aphrodite': isAphrodite(),
'use_ooba': isOoba(),
'api_server': isMancer() ? MANCER_SERVER : api_server_textgenerationwebui,
+ 'legacy_api': textgenerationwebui_settings.legacy_api,
//'n': textgenerationwebui_settings.n_aphrodite,
//'best_of': textgenerationwebui_settings.n_aphrodite, //n must always == best_of and vice versa
//'ignore_eos': textgenerationwebui_settings.ignore_eos_token_aphrodite,
diff --git a/public/scripts/tokenizers.js b/public/scripts/tokenizers.js
index c53312631..93e618047 100644
--- a/public/scripts/tokenizers.js
+++ b/public/scripts/tokenizers.js
@@ -1,9 +1,10 @@
-import { api_server, api_server_textgenerationwebui, characters, getAPIServerUrl, main_api, nai_settings, online_status, this_chid } from "../script.js";
+import { characters, getAPIServerUrl, main_api, nai_settings, online_status, this_chid } from "../script.js";
import { power_user, registerDebugFunction } from "./power-user.js";
import { chat_completion_sources, model_list, oai_settings } from "./openai.js";
import { groups, selected_group } from "./group-chats.js";
import { getStringHash } from "./utils.js";
import { kai_flags } from "./kai-settings.js";
+import { textgenerationwebui_settings } from "./textgen-settings.js";
export const CHARACTERS_PER_TOKEN_RATIO = 3.35;
const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown';
@@ -380,6 +381,7 @@ function countTokensRemote(endpoint, str, padding) {
text: str,
api: main_api,
url: getAPIServerUrl(),
+ legacy_api: main_api === 'textgenerationwebui' && textgenerationwebui_settings.legacy_api,
}),
dataType: "json",
contentType: "application/json",
diff --git a/server.js b/server.js
index 8fcd95959..6ebe925b9 100644
--- a/server.js
+++ b/server.js
@@ -496,7 +496,8 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request,
console.log('Trying to connect to API:', request.body);
- const baseUrl = request.body.api_server;
+ // Convert to string + remove trailing slash
+ const baseUrl = String(request.body.api_server).replace(/\/$/, '');
const args = {
headers: { "Content-Type": "application/json" },
@@ -504,18 +505,19 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request,
setAdditionalHeaders(request, args, baseUrl);
- const url = new URL(baseUrl);
+ let url = baseUrl;
- if (request.body.use_ooba) {
- url.pathname = "/v1/models";
+ if (request.body.legacy_api) {
+ url += "/v1/model";
}
-
- if (request.body.use_aphrodite) {
- url.pathname = "/v1/models";
+ else if (request.body.use_ooba) {
+ url += "/v1/models";
}
-
- if (request.body.use_mancer) {
- url.pathname = "/oai/v1/models";
+ else if (request.body.use_aphrodite) {
+ url += "/v1/models";
+ }
+ else if (request.body.use_mancer) {
+ url += "/oai/v1/models";
}
const modelsReply = await fetch(url, args);
@@ -527,6 +529,11 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request,
const data = await modelsReply.json();
+ if (request.body.legacy_api) {
+ console.log('Legacy API response:', data);
+ return response.send({ result: data?.result });
+ }
+
if (!Array.isArray(data.data)) {
console.log('Models response is not an array.')
return response.status(503);
@@ -560,14 +567,17 @@ app.post("/api/textgenerationwebui/generate", jsonParser, async function (reques
controller.abort();
});
- const url = new URL(baseUrl);
+ // Convert to string + remove trailing slash
+ let url = String(baseUrl).replace(/\/$/, '');
- if (request.body.use_aphrodite || request.body.use_ooba) {
- url.pathname = "/v1/completions";
+ if (request.body.legacy_api) {
+ url += "/v1/generate";
}
-
- if (request.body.use_mancer) {
- url.pathname = "/oai/v1/completions";
+ else if (request.body.use_aphrodite || request.body.use_ooba) {
+ url += "/v1/completions";
+ }
+ else if (request.body.use_mancer) {
+ url += "/oai/v1/completions";
}
const args = {
@@ -601,6 +611,13 @@ app.post("/api/textgenerationwebui/generate", jsonParser, async function (reques
if (completionsReply.ok) {
const data = await completionsReply.json();
console.log("Endpoint response:", data);
+
+ // Wrap legacy response to OAI completions format
+ if (request.body.legacy_api) {
+ const text = data?.results[0]?.text;
+ data['choices'] = [{ text }];
+ }
+
return response_generate.send(data);
} else {
const text = await completionsReply.text();
@@ -3323,9 +3340,10 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
if (!request.body) {
return response.sendStatus(400);
}
- const text = request.body.text || '';
- const api = request.body.api;
- const baseUrl = request.body.url;
+ const text = String(request.body.text) || '';
+ const api = String(request.body.api);
+ const baseUrl = String(request.body.url);
+ const legacyApi = Boolean(request.body.legacy_api);
try {
if (api == 'textgenerationwebui') {
@@ -3337,8 +3355,14 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
setAdditionalHeaders(request, args, null);
- const url = new URL(baseUrl);
- url.pathname = '/api/v1/token-count'
+ let url = String(baseUrl).replace(/\/$/, '');
+
+ if (legacyApi) {
+ url += '/v1/token-count';
+
+ } else {
+ url += '/api/v1/token-count';
+ }
const result = await fetch(url, args);
@@ -3358,8 +3382,8 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
headers: { "Content-Type": "application/json" }
};
- const url = new URL(baseUrl);
- url.pathname = '/api/extra/tokencount';
+ let url = String(baseUrl).replace(/\/$/, '');
+ url += '/extra/tokencount';
const result = await fetch(url, args);