Legacy ooba API compatibility shim

This commit is contained in:
Cohee 2023-11-08 10:13:28 +02:00
parent a98c275445
commit e76c18c104
6 changed files with 75 additions and 36 deletions

View File

@ -119,7 +119,7 @@
"Novel AI Model": "NovelAI 模型", "Novel AI Model": "NovelAI 模型",
"No connection": "无连接", "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 地址", "Blocking API url": "阻塞式 API 地址",
"Streaming API url": "流式传输 API 地址", "Streaming API url": "流式传输 API 地址",
"to get your OpenAI API key.": "获取您的 OpenAI API 密钥。", "to get your OpenAI API key.": "获取您的 OpenAI API 密钥。",
@ -672,7 +672,7 @@
"Novel AI Model": "NovelAI モデル", "Novel AI Model": "NovelAI モデル",
"No connection": "接続なし", "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", "Blocking API url": "ブロッキング API URL",
"Streaming API url": "ストリーミング API URL", "Streaming API url": "ストリーミング API URL",
"to get your OpenAI API key.": "あなたの OpenAI API キーを取得するために。", "to get your OpenAI API key.": "あなたの OpenAI API キーを取得するために。",
@ -1227,7 +1227,7 @@
"Novel AI Model": "NovelAI 모델", "Novel AI Model": "NovelAI 모델",
"No connection": "접속 실패", "No connection": "접속 실패",
"oobabooga/text-generation-webui": "oobabooga/text-generation-webui", "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을 막는 중", "Blocking API url": "API URL을 막는 중",
"Streaming API url": "API URL에서 스트리밍 중", "Streaming API url": "API URL에서 스트리밍 중",
"OpenAI Model": "OpenAI 모델", "OpenAI Model": "OpenAI 모델",
@ -1803,7 +1803,7 @@
"Novel AI Model": "Модель NovelAI", "Novel AI Model": "Модель NovelAI",
"If you are using:": "Если вы используете:", "If you are using:": "Если вы используете:",
"oobabooga/text-generation-webui": "", "oobabooga/text-generation-webui": "",
"Make sure you run it with": "Убедитесь, что при запуске указали аргумент --api", "Make sure you run it with": "Убедитесь, что при запуске указали аргумент --extensions openai",
"Mancer AI": "", "Mancer AI": "",
"Use API key (Only required for Mancer)": "Нажмите на ячейку (и добавьте свой API ключ!):", "Use API key (Only required for Mancer)": "Нажмите на ячейку (и добавьте свой API ключ!):",
"Blocking API url": "Блокирующий API url", "Blocking API url": "Блокирующий API url",
@ -2413,7 +2413,7 @@
"Krake": "Krake", "Krake": "Krake",
"No connection": "Nessuna connessione", "No connection": "Nessuna connessione",
"oobabooga/text-generation-webui": "oobabooga/text-generation-webui", "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", "Blocking API url": "Blocca l'indirizzo API",
"Streaming API url": "Streaming dell'indirizzo API", "Streaming API url": "Streaming dell'indirizzo API",
"to get your OpenAI API key.": "per ottenere la tua chiave API di OpenAI.", "to get your OpenAI API key.": "per ottenere la tua chiave API di OpenAI.",
@ -3174,7 +3174,7 @@
"Novel AI Model": "NovelAI-model", "Novel AI Model": "NovelAI-model",
"No connection": "Geen verbinding", "No connection": "Geen verbinding",
"oobabooga/text-generation-webui": "oobabooga/text-generation-webui", "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", "Blocking API url": "Blokkerende API-url",
"Streaming API url": "Streaming API-url", "Streaming API url": "Streaming API-url",
"to get your OpenAI API key.": "om je OpenAI API-sleutel te verkrijgen.", "to get your OpenAI API key.": "om je OpenAI API-sleutel te verkrijgen.",
@ -3727,7 +3727,7 @@
"Novel AI Model": "Modelo IA de NovelAI", "Novel AI Model": "Modelo IA de NovelAI",
"No connection": "Desconectado", "No connection": "Desconectado",
"oobabooga/text-generation-webui": "oobabooga/text-generation-webui", "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", "Blocking API url": "API URL",
"Streaming API url": "Streaming API URL", "Streaming API url": "Streaming API URL",
"to get your OpenAI API key.": "para conseguir tu clave API de OpenAI", "to get your OpenAI API key.": "para conseguir tu clave API de OpenAI",

View File

@ -1805,7 +1805,7 @@
oobabooga/text-generation-webui oobabooga/text-generation-webui
</a> </a>
<span data-i18n="Make sure you run it with"> <span data-i18n="Make sure you run it with">
Make sure you run it with <tt>--api</tt> flag Make sure you run it with <tt>--extensions openai</tt> flag
</span> </span>
</div> </div>
<div class="flex1"> <div class="flex1">
@ -1817,7 +1817,7 @@
<div data-tg-type="aphrodite"> <div data-tg-type="aphrodite">
<div class="flex-container flexFlowColumn"> <div class="flex-container flexFlowColumn">
<a href="https://github.com/PygmalionAI/aphrodite-engine" target="_blank"> <a href="https://github.com/PygmalionAI/aphrodite-engine" target="_blank">
PygmalionAI/aphrodite-engine PygmalionAI/aphrodite-engine (OpenAI API wrapper mode)
</a> </a>
</div> </div>
<h4 data-i18n="Aphrodite API key">Aphrodite API key</h4> <h4 data-i18n="Aphrodite API key">Aphrodite API key</h4>
@ -1839,6 +1839,10 @@
<div id="api_button_textgenerationwebui" class="api_button menu_button" type="submit" data-i18n="Connect" data-server-connect="ooba_blocking,aphrodite">Connect</div> <div id="api_button_textgenerationwebui" class="api_button menu_button" type="submit" data-i18n="Connect" data-server-connect="ooba_blocking,aphrodite">Connect</div>
<div class="api_loading menu_button" data-i18n="Cancel">Cancel</div> <div class="api_loading menu_button" data-i18n="Cancel">Cancel</div>
</div> </div>
<label class="checkbox_label margin-bot-10px" for="legacy_api_textgenerationwebui">
<input type="checkbox" id="legacy_api_textgenerationwebui" />
<span data-i18n="Use Legacy API schema (pre-OAI)">Use Legacy API schema (pre-OAI, no streaming)</span>
</label>
</form> </form>
<div class="online_status"> <div class="online_status">
<div class="online_status_indicator"></div> <div class="online_status_indicator"></div>

View File

@ -886,6 +886,7 @@ async function getStatus() {
use_mancer: main_api == "textgenerationwebui" ? isMancer() : false, use_mancer: main_api == "textgenerationwebui" ? isMancer() : false,
use_aphrodite: main_api == "textgenerationwebui" ? isAphrodite() : false, use_aphrodite: main_api == "textgenerationwebui" ? isAphrodite() : false,
use_ooba: main_api == "textgenerationwebui" ? isOoba() : false, use_ooba: main_api == "textgenerationwebui" ? isOoba() : false,
legacy_api: main_api == "textgenerationwebui" ? textgenerationwebui_settings.legacy_api : false,
}), }),
signal: abortStatusCheck.signal, signal: abortStatusCheck.signal,
}); });
@ -2548,6 +2549,12 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
return; 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()) { if (isHordeGenerationNotAllowed()) {
unblockGeneration(); unblockGeneration();
return; return;

View File

@ -78,6 +78,7 @@ const textgenerationwebui_settings = {
//prompt_log_probs_aphrodite: 0, //prompt_log_probs_aphrodite: 0,
type: textgen_types.OOBA, type: textgen_types.OOBA,
mancer_model: 'mytholite', mancer_model: 'mytholite',
legacy_api: false,
}; };
export let textgenerationwebui_banned_in_macros = []; export let textgenerationwebui_banned_in_macros = [];
@ -120,6 +121,7 @@ const setting_names = [
"negative_prompt", "negative_prompt",
"grammar_string", "grammar_string",
"banned_tokens", "banned_tokens",
"legacy_api",
//'n_aphrodite', //'n_aphrodite',
//'best_of_aphrodite', //'best_of_aphrodite',
//'ignore_eos_token_aphrodite', //'ignore_eos_token_aphrodite',
@ -148,9 +150,8 @@ async function selectPreset(name) {
function formatTextGenURL(value) { function formatTextGenURL(value) {
try { try {
const url = new URL(value); const url = new URL(value);
if (url.pathname === '/api' && textgenerationwebui_settings.type === textgen_types.OOBA) { if (url.pathname === '/api' && !textgenerationwebui_settings.legacy_api) {
url.pathname = '/'; toastr.info(`Enable compatibility mode or update ooba-webui to the latest version.`, 'Legacy API URL detected. Generation may fail.');
toastr.info(`Legacy API URL detected, please make sure you updated ooba-webui to the latest version.`);
} }
return url.toString(); return url.toString();
} catch { } // Just using URL as a validation check } catch { } // Just using URL as a validation check
@ -516,6 +517,7 @@ export function getTextGenGenerationData(finalPrompt, this_amount_gen, isImperso
'use_aphrodite': isAphrodite(), 'use_aphrodite': isAphrodite(),
'use_ooba': isOoba(), 'use_ooba': isOoba(),
'api_server': isMancer() ? MANCER_SERVER : api_server_textgenerationwebui, 'api_server': isMancer() ? MANCER_SERVER : api_server_textgenerationwebui,
'legacy_api': textgenerationwebui_settings.legacy_api,
//'n': textgenerationwebui_settings.n_aphrodite, //'n': textgenerationwebui_settings.n_aphrodite,
//'best_of': textgenerationwebui_settings.n_aphrodite, //n must always == best_of and vice versa //'best_of': textgenerationwebui_settings.n_aphrodite, //n must always == best_of and vice versa
//'ignore_eos': textgenerationwebui_settings.ignore_eos_token_aphrodite, //'ignore_eos': textgenerationwebui_settings.ignore_eos_token_aphrodite,

View File

@ -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 { power_user, registerDebugFunction } from "./power-user.js";
import { chat_completion_sources, model_list, oai_settings } from "./openai.js"; import { chat_completion_sources, model_list, oai_settings } from "./openai.js";
import { groups, selected_group } from "./group-chats.js"; import { groups, selected_group } from "./group-chats.js";
import { getStringHash } from "./utils.js"; import { getStringHash } from "./utils.js";
import { kai_flags } from "./kai-settings.js"; import { kai_flags } from "./kai-settings.js";
import { textgenerationwebui_settings } from "./textgen-settings.js";
export const CHARACTERS_PER_TOKEN_RATIO = 3.35; export const CHARACTERS_PER_TOKEN_RATIO = 3.35;
const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown'; const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown';
@ -380,6 +381,7 @@ function countTokensRemote(endpoint, str, padding) {
text: str, text: str,
api: main_api, api: main_api,
url: getAPIServerUrl(), url: getAPIServerUrl(),
legacy_api: main_api === 'textgenerationwebui' && textgenerationwebui_settings.legacy_api,
}), }),
dataType: "json", dataType: "json",
contentType: "application/json", contentType: "application/json",

View File

@ -496,7 +496,8 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request,
console.log('Trying to connect to API:', request.body); 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 = { const args = {
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
@ -504,18 +505,19 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request,
setAdditionalHeaders(request, args, baseUrl); setAdditionalHeaders(request, args, baseUrl);
const url = new URL(baseUrl); let url = baseUrl;
if (request.body.use_ooba) { if (request.body.legacy_api) {
url.pathname = "/v1/models"; url += "/v1/model";
} }
else if (request.body.use_ooba) {
if (request.body.use_aphrodite) { url += "/v1/models";
url.pathname = "/v1/models";
} }
else if (request.body.use_aphrodite) {
if (request.body.use_mancer) { url += "/v1/models";
url.pathname = "/oai/v1/models"; }
else if (request.body.use_mancer) {
url += "/oai/v1/models";
} }
const modelsReply = await fetch(url, args); const modelsReply = await fetch(url, args);
@ -527,6 +529,11 @@ app.post("/api/textgenerationwebui/status", jsonParser, async function (request,
const data = await modelsReply.json(); 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)) { if (!Array.isArray(data.data)) {
console.log('Models response is not an array.') console.log('Models response is not an array.')
return response.status(503); return response.status(503);
@ -560,14 +567,17 @@ app.post("/api/textgenerationwebui/generate", jsonParser, async function (reques
controller.abort(); 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) { if (request.body.legacy_api) {
url.pathname = "/v1/completions"; url += "/v1/generate";
} }
else if (request.body.use_aphrodite || request.body.use_ooba) {
if (request.body.use_mancer) { url += "/v1/completions";
url.pathname = "/oai/v1/completions"; }
else if (request.body.use_mancer) {
url += "/oai/v1/completions";
} }
const args = { const args = {
@ -601,6 +611,13 @@ app.post("/api/textgenerationwebui/generate", jsonParser, async function (reques
if (completionsReply.ok) { if (completionsReply.ok) {
const data = await completionsReply.json(); const data = await completionsReply.json();
console.log("Endpoint response:", data); 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); return response_generate.send(data);
} else { } else {
const text = await completionsReply.text(); const text = await completionsReply.text();
@ -3323,9 +3340,10 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
if (!request.body) { if (!request.body) {
return response.sendStatus(400); return response.sendStatus(400);
} }
const text = request.body.text || ''; const text = String(request.body.text) || '';
const api = request.body.api; const api = String(request.body.api);
const baseUrl = request.body.url; const baseUrl = String(request.body.url);
const legacyApi = Boolean(request.body.legacy_api);
try { try {
if (api == 'textgenerationwebui') { if (api == 'textgenerationwebui') {
@ -3337,8 +3355,14 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
setAdditionalHeaders(request, args, null); setAdditionalHeaders(request, args, null);
const url = new URL(baseUrl); let url = String(baseUrl).replace(/\/$/, '');
url.pathname = '/api/v1/token-count'
if (legacyApi) {
url += '/v1/token-count';
} else {
url += '/api/v1/token-count';
}
const result = await fetch(url, args); 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" } headers: { "Content-Type": "application/json" }
}; };
const url = new URL(baseUrl); let url = String(baseUrl).replace(/\/$/, '');
url.pathname = '/api/extra/tokencount'; url += '/extra/tokencount';
const result = await fetch(url, args); const result = await fetch(url, args);