From e76c18c104130cf8497cb42afa6930625c1a7c3e Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:13:28 +0200 Subject: [PATCH] Legacy ooba API compatibility shim --- public/i18n.json | 14 +++--- public/index.html | 8 +++- public/script.js | 7 +++ public/scripts/textgen-settings.js | 8 ++-- public/scripts/tokenizers.js | 4 +- server.js | 70 ++++++++++++++++++++---------- 6 files changed, 75 insertions(+), 36 deletions(-) diff --git a/public/i18n.json b/public/i18n.json index 5191c3d74..561181c51 100644 --- a/public/i18n.json +++ b/public/i18n.json @@ -119,7 +119,7 @@ "Novel AI Model": "NovelAI 模型", "No connection": "无连接", "oobabooga/text-generation-webui": "", - "Make sure you run it with": "确保启动时包含 --api 参数", + "Make sure you run it with": "确保启动时包含 --extensions openai 参数", "Blocking API url": "阻塞式 API 地址", "Streaming API url": "流式传输 API 地址", "to get your OpenAI API key.": "获取您的 OpenAI API 密钥。", @@ -672,7 +672,7 @@ "Novel AI Model": "NovelAI モデル", "No connection": "接続なし", "oobabooga/text-generation-webui": "", - "Make sure you run it with": "必ず --api の引数を含めて起動してください", + "Make sure you run it with": "必ず --extensions openai の引数を含めて起動してください", "Blocking API url": "ブロッキング API URL", "Streaming API url": "ストリーミング API URL", "to get your OpenAI API key.": "あなたの OpenAI API キーを取得するために。", @@ -1227,7 +1227,7 @@ "Novel AI Model": "NovelAI 모델", "No connection": "접속 실패", "oobabooga/text-generation-webui": "oobabooga/text-generation-webui", - "Make sure you run it with": "--api 인수를 반드시 사용해야 합니다.", + "Make sure you run it with": "--extensions openai 인수를 반드시 사용해야 합니다.", "Blocking API url": "API URL을 막는 중", "Streaming API url": "API URL에서 스트리밍 중", "OpenAI Model": "OpenAI 모델", @@ -1803,7 +1803,7 @@ "Novel AI Model": "Модель NovelAI", "If you are using:": "Если вы используете:", "oobabooga/text-generation-webui": "", - "Make sure you run it with": "Убедитесь, что при запуске указали аргумент --api", + "Make sure you run it with": "Убедитесь, что при запуске указали аргумент --extensions openai", "Mancer AI": "", "Use API key (Only required for Mancer)": "Нажмите на ячейку (и добавьте свой API ключ!):", "Blocking API url": "Блокирующий API url", @@ -2413,7 +2413,7 @@ "Krake": "Krake", "No connection": "Nessuna connessione", "oobabooga/text-generation-webui": "oobabooga/text-generation-webui", - "Make sure you run it with": "assicurati di farlo partire con", + "Make sure you run it with": "assicurati di farlo partire con --extensions openai", "Blocking API url": "Blocca l'indirizzo API", "Streaming API url": "Streaming dell'indirizzo API", "to get your OpenAI API key.": "per ottenere la tua chiave API di OpenAI.", @@ -3174,7 +3174,7 @@ "Novel AI Model": "NovelAI-model", "No connection": "Geen verbinding", "oobabooga/text-generation-webui": "oobabooga/text-generation-webui", - "Make sure you run it with": "Zorg ervoor dat je het uitvoert met", + "Make sure you run it with": "Zorg ervoor dat je het uitvoert met --extensions openai", "Blocking API url": "Blokkerende API-url", "Streaming API url": "Streaming API-url", "to get your OpenAI API key.": "om je OpenAI API-sleutel te verkrijgen.", @@ -3727,7 +3727,7 @@ "Novel AI Model": "Modelo IA de NovelAI", "No connection": "Desconectado", "oobabooga/text-generation-webui": "oobabooga/text-generation-webui", - "Make sure you run it with": "Asegúrate de usar el argumento --api cuando se ejecute", + "Make sure you run it with": "Asegúrate de usar el argumento --extensions openai cuando se ejecute", "Blocking API url": "API URL", "Streaming API url": "Streaming API URL", "to get your OpenAI API key.": "para conseguir tu clave API de OpenAI", diff --git a/public/index.html b/public/index.html index 34dea2bb7..d6b8d1d3d 100644 --- a/public/index.html +++ b/public/index.html @@ -1805,7 +1805,7 @@ oobabooga/text-generation-webui - Make sure you run it with --api flag + Make sure you run it with --extensions openai flag
@@ -1817,7 +1817,7 @@

Aphrodite API key

@@ -1839,6 +1839,10 @@
+
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);