mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Split oobabooga/mancer sources. Add aphrodite support
This commit is contained in:
@ -1875,60 +1875,80 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="textgenerationwebui_api" style="display: none;position: relative;">
|
<div id="textgenerationwebui_api" style="display: none;position: relative;">
|
||||||
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||||
<span data-i18n="If you are using:"> If you are using:</span>
|
|
||||||
<div class="flex-container indent20p">
|
|
||||||
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
|
|
||||||
oobabooga/text-generation-webui
|
|
||||||
</a>
|
|
||||||
<span data-i18n="Make sure you run it with">
|
|
||||||
Make sure you run it with <tt>--api</tt> flag
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="flex-container indent20p">
|
|
||||||
<a href="https://mancer.tech/" target="_blank">
|
|
||||||
Mancer AI
|
|
||||||
</a>
|
|
||||||
<label class="checkbox_label" for="use-mancer-api-checkbox">
|
|
||||||
<span data-i18n="Use API key (Only required for Mancer)">
|
|
||||||
Click this box (and add your API key!):
|
|
||||||
</span>
|
|
||||||
<input id="use-mancer-api-checkbox" type="checkbox" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div id="mancer_api_subpanel" class="flex-container flexFlowColumn" style="display:none;">
|
<h4>API Type</h4>
|
||||||
<h4 data-i18n="Mancer API key">Mancer API key</h4>
|
<select id="textgen_type">
|
||||||
<div class="flex-container">
|
<option value="ooba">Default (oobabooga)</option>
|
||||||
<input id="api_key_mancer" name="api_key_mancer" class="text_pole flex1 wide100p" maxlength="500" size="35" type="text" autocomplete="off">
|
<option value="mancer">Mancer</option>
|
||||||
<div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_mancer">
|
<option value="aphrodite">Aphrodite</option>
|
||||||
</div>
|
</select>
|
||||||
</div>
|
|
||||||
<div data-for="api_key_mancer" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page.">
|
|
||||||
For privacy reasons, your API key will be hidden after you reload the page.
|
|
||||||
</div>
|
|
||||||
<div class="flex1">
|
|
||||||
<h4>Mancer Model</h4>
|
|
||||||
<select id="mancer_model"></select>
|
|
||||||
<h4 data-i18n="Mancer API url">Mancer API URL</h4>
|
|
||||||
<small data-i18n="Example: https://neuro.mancer.tech/webui/MODEL/api">Example: https://neuro.mancer.tech/webui/MODEL/api</small>
|
|
||||||
<input id="mancer_api_url_text" name="mancer_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="tgwebui_api_subpanel" class="flex-container flexFlowColumn">
|
|
||||||
<div class="flex1">
|
|
||||||
<h4 data-i18n="Blocking API url">Blocking API URL</h4>
|
|
||||||
<small data-i18n="Example: http://127.0.0.1:5000/api ">Example: http://127.0.0.1:5000/api </small>
|
|
||||||
<input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off" data-server-history="ooba_blocking">
|
|
||||||
</div>
|
|
||||||
<div class="flex1">
|
|
||||||
<h4 data-i18n="Streaming API url">Streaming API URL</h4>
|
|
||||||
<small data-i18n="Example: ws://127.0.0.1:5005/api/v1/stream">Example: ws://127.0.0.1:5005/api/v1/stream </small>
|
|
||||||
<input id="streaming_url_textgenerationwebui" type="text" class="text_pole wide100p" maxlength="500" value="" autocomplete="off" data-server-history="ooba_streaming">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="api_button_textgenerationwebui" class="menu_button" type="submit" data-i18n="Connect" data-server-connect="ooba_blocking,ooba_streaming">Connect</div>
|
|
||||||
<div id="api_loading_textgenerationwebui" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div data-tg-type="mancer" class="flex-container flexFlowColumn">
|
||||||
|
<div class="flex-container flexFlowColumn">
|
||||||
|
<a href="https://mancer.tech/" target="_blank">
|
||||||
|
Mancer AI
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<h4 data-i18n="Mancer API key">Mancer API key</h4>
|
||||||
|
<div class="flex-container">
|
||||||
|
<input id="api_key_mancer" name="api_key_mancer" class="text_pole flex1 wide100p" maxlength="500" size="35" type="text" autocomplete="off">
|
||||||
|
<div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_mancer">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-for="api_key_mancer" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page.">
|
||||||
|
For privacy reasons, your API key will be hidden after you reload the page.
|
||||||
|
</div>
|
||||||
|
<div class="flex1">
|
||||||
|
<h4>Mancer Model</h4>
|
||||||
|
<select id="mancer_model"></select>
|
||||||
|
<h4 data-i18n="Mancer API url">Mancer API URL</h4>
|
||||||
|
<small data-i18n="Example: https://neuro.mancer.tech/webui/MODEL/api">Example: https://neuro.mancer.tech/webui/MODEL/api</small>
|
||||||
|
<input id="mancer_api_url_text" name="mancer_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-tg-type="ooba" class="flex-container flexFlowColumn">
|
||||||
|
<div class="flex-container flexFlowColumn">
|
||||||
|
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
|
||||||
|
oobabooga/text-generation-webui
|
||||||
|
</a>
|
||||||
|
<span data-i18n="Make sure you run it with">
|
||||||
|
Make sure you run it with <tt>--api</tt> flag
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex1">
|
||||||
|
<h4 data-i18n="Blocking API url">Blocking API URL</h4>
|
||||||
|
<small data-i18n="Example: http://127.0.0.1:5000/api ">Example: http://127.0.0.1:5000/api </small>
|
||||||
|
<input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off" data-server-history="ooba_blocking">
|
||||||
|
</div>
|
||||||
|
<div class="flex1">
|
||||||
|
<h4 data-i18n="Streaming API url">Streaming API URL</h4>
|
||||||
|
<small data-i18n="Example: ws://127.0.0.1:5005/api/v1/stream">Example: ws://127.0.0.1:5005/api/v1/stream </small>
|
||||||
|
<input id="streaming_url_textgenerationwebui" type="text" class="text_pole wide100p" maxlength="500" value="" autocomplete="off" data-server-history="ooba_streaming">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-tg-type="aphrodite">
|
||||||
|
<div class="flex-container flexFlowColumn">
|
||||||
|
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
|
||||||
|
PygmalionAI/aphrodite-engine
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<h4 data-i18n="Aphrodite API key">Aphrodite API key</h4>
|
||||||
|
<div class="flex-container">
|
||||||
|
<input id="api_key_aphrodite" name="api_key_aphrodite" class="text_pole flex1 wide100p" maxlength="500" size="35" type="text" autocomplete="off">
|
||||||
|
<div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_aphrodite">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-for="api_key_aphrodite" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page.">
|
||||||
|
For privacy reasons, your API key will be hidden after you reload the page.
|
||||||
|
</div>
|
||||||
|
<div class="flex1">
|
||||||
|
<h4 data-i18n="API url">API URL</h4>
|
||||||
|
<small data-i18n="Example: http://127.0.0.1:5000/api ">Example: http://127.0.0.1:5000/api </small>
|
||||||
|
<input id="aphrodite_api_url_text" class="text_pole wide100p" maxlength="500" value="" autocomplete="off" data-server-history="aphrodite">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="api_button_textgenerationwebui" class="menu_button" type="submit" data-i18n="Connect" data-server-connect="ooba_blocking,ooba_streaming,aphrodite">Connect</div>
|
||||||
|
<div id="api_loading_textgenerationwebui" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
||||||
</form>
|
</form>
|
||||||
<div class="online_status4">
|
<div class="online_status4">
|
||||||
<div class="online_status_indicator4"></div>
|
<div class="online_status_indicator4"></div>
|
||||||
|
@ -16,6 +16,9 @@ import {
|
|||||||
generateTextGenWithStreaming,
|
generateTextGenWithStreaming,
|
||||||
getTextGenGenerationData,
|
getTextGenGenerationData,
|
||||||
formatTextGenURL,
|
formatTextGenURL,
|
||||||
|
getTextGenUrlSourceId,
|
||||||
|
isMancer,
|
||||||
|
isAphrodite,
|
||||||
} from "./scripts/textgen-settings.js";
|
} from "./scripts/textgen-settings.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -178,7 +181,6 @@ import {
|
|||||||
import { applyLocale } from "./scripts/i18n.js";
|
import { applyLocale } from "./scripts/i18n.js";
|
||||||
import { getTokenCount, getTokenizerModel, saveTokenCache } from "./scripts/tokenizers.js";
|
import { getTokenCount, getTokenizerModel, saveTokenCache } from "./scripts/tokenizers.js";
|
||||||
import { initPersonas, selectCurrentPersona, setPersonaDescription } from "./scripts/personas.js";
|
import { initPersonas, selectCurrentPersona, setPersonaDescription } from "./scripts/personas.js";
|
||||||
import { loadMancerModels } from "./scripts/mancer-settings.js";
|
|
||||||
|
|
||||||
//exporting functions and vars for mods
|
//exporting functions and vars for mods
|
||||||
export {
|
export {
|
||||||
@ -632,7 +634,6 @@ let is_get_status = false;
|
|||||||
let is_get_status_novel = false;
|
let is_get_status_novel = false;
|
||||||
let is_api_button_press = false;
|
let is_api_button_press = false;
|
||||||
let is_api_button_press_novel = false;
|
let is_api_button_press_novel = false;
|
||||||
let api_use_mancer_webui = false;
|
|
||||||
|
|
||||||
let is_send_press = false; //Send generation
|
let is_send_press = false; //Send generation
|
||||||
|
|
||||||
@ -771,7 +772,8 @@ async function getStatus() {
|
|||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
api_server: main_api == "kobold" ? api_server : api_server_textgenerationwebui,
|
api_server: main_api == "kobold" ? api_server : api_server_textgenerationwebui,
|
||||||
main_api: main_api,
|
main_api: main_api,
|
||||||
use_mancer: main_api == "textgenerationwebui" ? api_use_mancer_webui : false,
|
use_mancer: main_api == "textgenerationwebui" ? isMancer() : false,
|
||||||
|
use_aphrodite: main_api == "textgenerationwebui" ? isAphrodite() : false,
|
||||||
}),
|
}),
|
||||||
beforeSend: function () { },
|
beforeSend: function () { },
|
||||||
cache: false,
|
cache: false,
|
||||||
@ -3010,7 +3012,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
}
|
}
|
||||||
else if (main_api == 'textgenerationwebui') {
|
else if (main_api == 'textgenerationwebui') {
|
||||||
generate_data = getTextGenGenerationData(finalPrompt, this_amount_gen, isImpersonate, cfgValues);
|
generate_data = getTextGenGenerationData(finalPrompt, this_amount_gen, isImpersonate, cfgValues);
|
||||||
generate_data.use_mancer = api_use_mancer_webui;
|
generate_data.use_mancer = isMancer();
|
||||||
|
generate_data.use_aphrodite = isAphrodite();
|
||||||
}
|
}
|
||||||
else if (main_api == 'novel') {
|
else if (main_api == 'novel') {
|
||||||
const this_settings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
|
const this_settings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
|
||||||
@ -3246,7 +3249,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
//console.log('runGenerate calling showSwipeBtns');
|
//console.log('runGenerate calling showSwipeBtns');
|
||||||
showSwipeButtons();
|
showSwipeButtons();
|
||||||
|
|
||||||
if (main_api == 'textgenerationwebui' && api_use_mancer_webui) {
|
if (main_api == 'textgenerationwebui' && isMancer()) {
|
||||||
const errorText = `<h3>Inferencer endpoint is unhappy!</h3>
|
const errorText = `<h3>Inferencer endpoint is unhappy!</h3>
|
||||||
Returned status <tt>${data.status}</tt> with the reason:<br/>
|
Returned status <tt>${data.status}</tt> with the reason:<br/>
|
||||||
${data.response}`;
|
${data.response}`;
|
||||||
@ -4979,9 +4982,7 @@ async function getSettings(type) {
|
|||||||
api_server_textgenerationwebui = settings.api_server_textgenerationwebui;
|
api_server_textgenerationwebui = settings.api_server_textgenerationwebui;
|
||||||
$("#textgenerationwebui_api_url_text").val(api_server_textgenerationwebui);
|
$("#textgenerationwebui_api_url_text").val(api_server_textgenerationwebui);
|
||||||
$("#mancer_api_url_text").val(api_server_textgenerationwebui);
|
$("#mancer_api_url_text").val(api_server_textgenerationwebui);
|
||||||
api_use_mancer_webui = settings.api_use_mancer_webui
|
$("#aphrodite_api_url_text").val(api_server_textgenerationwebui);
|
||||||
$('#use-mancer-api-checkbox').prop("checked", api_use_mancer_webui);
|
|
||||||
$('#use-mancer-api-checkbox').trigger("change");
|
|
||||||
|
|
||||||
selected_button = settings.selected_button;
|
selected_button = settings.selected_button;
|
||||||
|
|
||||||
@ -5017,7 +5018,6 @@ async function saveSettings(type) {
|
|||||||
active_group: active_group,
|
active_group: active_group,
|
||||||
api_server: api_server,
|
api_server: api_server,
|
||||||
api_server_textgenerationwebui: api_server_textgenerationwebui,
|
api_server_textgenerationwebui: api_server_textgenerationwebui,
|
||||||
api_use_mancer_webui: api_use_mancer_webui,
|
|
||||||
preset_settings: preset_settings,
|
preset_settings: preset_settings,
|
||||||
user_avatar: user_avatar,
|
user_avatar: user_avatar,
|
||||||
amount_gen: amount_gen,
|
amount_gen: amount_gen,
|
||||||
@ -7606,41 +7606,30 @@ jQuery(async function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#use-mancer-api-checkbox").on("change", function (e) {
|
$("#api_button_textgenerationwebui").on('click', async function (e) {
|
||||||
const enabled = $("#use-mancer-api-checkbox").prop("checked");
|
const urlSourceId = getTextGenUrlSourceId();
|
||||||
$("#mancer_api_subpanel").toggle(enabled);
|
|
||||||
$("#tgwebui_api_subpanel").toggle(!enabled);
|
|
||||||
|
|
||||||
api_use_mancer_webui = enabled;
|
if ($(urlSourceId).val() != "") {
|
||||||
saveSettingsDebounced();
|
let value = formatTextGenURL(String($(urlSourceId).val()).trim(), isMancer());
|
||||||
getStatus();
|
|
||||||
|
|
||||||
if (enabled) {
|
|
||||||
loadMancerModels();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#api_button_textgenerationwebui").click(async function (e) {
|
|
||||||
const url_source = api_use_mancer_webui ? "#mancer_api_url_text" : "#textgenerationwebui_api_url_text";
|
|
||||||
if ($(url_source).val() != "") {
|
|
||||||
let value = formatTextGenURL(String($(url_source).val()).trim(), api_use_mancer_webui);
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
callPopup("Please enter a valid URL.<br/>WebUI URLs should end with <tt>/api</tt><br/>Enable 'Relaxed API URLs' to allow other paths.", 'text');
|
callPopup("Please enter a valid URL.<br/>WebUI URLs should end with <tt>/api</tt><br/>Enable 'Relaxed API URLs' to allow other paths.", 'text');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mancer_key = String($("#api_key_mancer").val()).trim();
|
const mancerKey = String($("#api_key_mancer").val()).trim();
|
||||||
if (mancer_key.length) {
|
if (mancerKey.length) {
|
||||||
await writeSecret(SECRET_KEYS.MANCER, mancer_key);
|
await writeSecret(SECRET_KEYS.MANCER, mancerKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(url_source).val(value);
|
const aphroditeKey = String($("#api_key_aphrodite").val()).trim();
|
||||||
|
if (aphroditeKey.length) {
|
||||||
|
await writeSecret(SECRET_KEYS.APHRODITE, aphroditeKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(urlSourceId).val(value);
|
||||||
$("#api_loading_textgenerationwebui").css("display", "inline-block");
|
$("#api_loading_textgenerationwebui").css("display", "inline-block");
|
||||||
$("#api_button_textgenerationwebui").css("display", "none");
|
$("#api_button_textgenerationwebui").css("display", "none");
|
||||||
|
|
||||||
if (api_use_mancer_webui) {
|
|
||||||
textgenerationwebui_settings.streaming_url = value.replace("http", "ws") + "/v1/stream";
|
|
||||||
}
|
|
||||||
api_server_textgenerationwebui = value;
|
api_server_textgenerationwebui = value;
|
||||||
main_api = "textgenerationwebui";
|
main_api = "textgenerationwebui";
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
@ -3,6 +3,7 @@ import { callPopup, getRequestHeaders } from "../script.js";
|
|||||||
export const SECRET_KEYS = {
|
export const SECRET_KEYS = {
|
||||||
HORDE: 'api_key_horde',
|
HORDE: 'api_key_horde',
|
||||||
MANCER: 'api_key_mancer',
|
MANCER: 'api_key_mancer',
|
||||||
|
APHRODITE: 'api_key_aphrodite',
|
||||||
OPENAI: 'api_key_openai',
|
OPENAI: 'api_key_openai',
|
||||||
NOVEL: 'api_key_novel',
|
NOVEL: 'api_key_novel',
|
||||||
CLAUDE: 'api_key_claude',
|
CLAUDE: 'api_key_claude',
|
||||||
@ -24,6 +25,7 @@ const INPUT_MAP = {
|
|||||||
[SECRET_KEYS.AI21]: '#api_key_ai21',
|
[SECRET_KEYS.AI21]: '#api_key_ai21',
|
||||||
[SECRET_KEYS.SCALE_COOKIE]: '#scale_cookie',
|
[SECRET_KEYS.SCALE_COOKIE]: '#scale_cookie',
|
||||||
[SECRET_KEYS.PALM]: '#api_key_palm',
|
[SECRET_KEYS.PALM]: '#api_key_palm',
|
||||||
|
[SECRET_KEYS.APHRODITE]: '#api_key_aphrodite',
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clearSecret() {
|
async function clearSecret() {
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import {
|
import {
|
||||||
|
api_server_textgenerationwebui,
|
||||||
getRequestHeaders,
|
getRequestHeaders,
|
||||||
getStoppingStrings,
|
getStoppingStrings,
|
||||||
max_context,
|
max_context,
|
||||||
saveSettingsDebounced,
|
saveSettingsDebounced,
|
||||||
setGenerationParamsFromPreset,
|
setGenerationParamsFromPreset,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
import { loadMancerModels } from "./mancer-settings.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
power_user,
|
power_user,
|
||||||
} from "./power-user.js";
|
} from "./power-user.js";
|
||||||
import { getTextTokens, tokenizers } from "./tokenizers.js";
|
import { getTextTokens, tokenizers } from "./tokenizers.js";
|
||||||
import { onlyUnique } from "./utils.js";
|
import { delay, onlyUnique } from "./utils.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
textgenerationwebui_settings,
|
textgenerationwebui_settings,
|
||||||
@ -19,6 +21,12 @@ export {
|
|||||||
formatTextGenURL,
|
formatTextGenURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const textgen_types = {
|
||||||
|
OOBA: 'ooba',
|
||||||
|
MANCER: 'mancer',
|
||||||
|
APHRODITE: 'aphrodite',
|
||||||
|
};
|
||||||
|
|
||||||
const textgenerationwebui_settings = {
|
const textgenerationwebui_settings = {
|
||||||
temp: 0.7,
|
temp: 0.7,
|
||||||
top_p: 0.5,
|
top_p: 0.5,
|
||||||
@ -54,6 +62,7 @@ const textgenerationwebui_settings = {
|
|||||||
negative_prompt: '',
|
negative_prompt: '',
|
||||||
grammar_string: '',
|
grammar_string: '',
|
||||||
banned_tokens: '',
|
banned_tokens: '',
|
||||||
|
type: textgen_types.OOBA,
|
||||||
};
|
};
|
||||||
|
|
||||||
export let textgenerationwebui_presets = [];
|
export let textgenerationwebui_presets = [];
|
||||||
@ -173,6 +182,10 @@ function loadTextGenSettings(data, settings) {
|
|||||||
textgenerationwebui_preset_names = data.textgenerationwebui_preset_names ?? [];
|
textgenerationwebui_preset_names = data.textgenerationwebui_preset_names ?? [];
|
||||||
Object.assign(textgenerationwebui_settings, settings.textgenerationwebui_settings ?? {});
|
Object.assign(textgenerationwebui_settings, settings.textgenerationwebui_settings ?? {});
|
||||||
|
|
||||||
|
if (settings.api_use_mancer_webui) {
|
||||||
|
textgenerationwebui_settings.type = textgen_types.MANCER;
|
||||||
|
}
|
||||||
|
|
||||||
for (const name of textgenerationwebui_preset_names) {
|
for (const name of textgenerationwebui_preset_names) {
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = name;
|
option.value = name;
|
||||||
@ -188,9 +201,51 @@ function loadTextGenSettings(data, settings) {
|
|||||||
const value = textgenerationwebui_settings[i];
|
const value = textgenerationwebui_settings[i];
|
||||||
setSettingByName(i, value);
|
setSettingByName(i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('#textgen_type').val(textgenerationwebui_settings.type).trigger('change');
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
export function isMancer() {
|
||||||
|
return textgenerationwebui_settings.type === textgen_types.MANCER;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isAphrodite() {
|
||||||
|
return textgenerationwebui_settings.type === textgen_types.APHRODITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTextGenUrlSourceId() {
|
||||||
|
switch (textgenerationwebui_settings.type) {
|
||||||
|
case textgen_types.MANCER:
|
||||||
|
return "#mancer_api_url_text";
|
||||||
|
case textgen_types.OOBA:
|
||||||
|
return "#textgenerationwebui_api_url_text";
|
||||||
|
case textgen_types.APHRODITE:
|
||||||
|
return "#aphrodite_api_url_text";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery(function () {
|
||||||
|
$('#textgen_type').on('change', function () {
|
||||||
|
const type = String($(this).val());
|
||||||
|
textgenerationwebui_settings.type = type;
|
||||||
|
|
||||||
|
$('[data-tg-type]').each(function () {
|
||||||
|
const tgType = $(this).attr('data-tg-type');
|
||||||
|
if (tgType == type) {
|
||||||
|
$(this).show();
|
||||||
|
} else {
|
||||||
|
$(this).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isMancer()) {
|
||||||
|
loadMancerModels();
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSettingsDebounced();
|
||||||
|
$('#api_button_textgenerationwebui').trigger('click');
|
||||||
|
});
|
||||||
|
|
||||||
$('#settings_preset_textgenerationwebui').on('change', function () {
|
$('#settings_preset_textgenerationwebui').on('change', function () {
|
||||||
const presetName = $(this).val();
|
const presetName = $(this).val();
|
||||||
selectPreset(presetName);
|
selectPreset(presetName);
|
||||||
@ -248,11 +303,21 @@ function setSettingByName(i, value, trigger) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function generateTextGenWithStreaming(generate_data, signal) {
|
async function generateTextGenWithStreaming(generate_data, signal) {
|
||||||
|
let streamingUrl = textgenerationwebui_settings.streaming_url;
|
||||||
|
|
||||||
|
if (isMancer()) {
|
||||||
|
streamingUrl = api_server_textgenerationwebui.replace("http", "ws") + "/v1/stream";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAphrodite()){
|
||||||
|
streamingUrl = api_server_textgenerationwebui;
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch('/generate_textgenerationwebui', {
|
const response = await fetch('/generate_textgenerationwebui', {
|
||||||
headers: {
|
headers: {
|
||||||
...getRequestHeaders(),
|
...getRequestHeaders(),
|
||||||
'X-Response-Streaming': String(true),
|
'X-Response-Streaming': String(true),
|
||||||
'X-Streaming-URL': textgenerationwebui_settings.streaming_url,
|
'X-Streaming-URL': streamingUrl,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(generate_data),
|
body: JSON.stringify(generate_data),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -266,13 +331,43 @@ async function generateTextGenWithStreaming(generate_data, signal) {
|
|||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader.read();
|
const { done, value } = await reader.read();
|
||||||
let response = decoder.decode(value);
|
let response = decoder.decode(value);
|
||||||
getMessage += response;
|
|
||||||
|
|
||||||
if (done) {
|
if (isAphrodite()) {
|
||||||
return;
|
const events = response.split('\n\n');
|
||||||
|
|
||||||
|
for (const event of events) {
|
||||||
|
if (event.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { results } = JSON.parse(event);
|
||||||
|
|
||||||
|
if (Array.isArray(results) && results.length > 0) {
|
||||||
|
getMessage = results[0].text;
|
||||||
|
yield getMessage;
|
||||||
|
|
||||||
|
// unhang UI thread
|
||||||
|
await delay(1);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
getMessage += response;
|
||||||
|
|
||||||
|
if (done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield getMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield getMessage;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
111
server.js
111
server.js
@ -148,9 +148,14 @@ let color = {
|
|||||||
white: (mess) => color.byNum(mess, 37)
|
white: (mess) => color.byNum(mess, 37)
|
||||||
};
|
};
|
||||||
|
|
||||||
function get_mancer_headers() {
|
function getMancerHeaders() {
|
||||||
const api_key_mancer = readSecret(SECRET_KEYS.MANCER);
|
const apiKey = readSecret(SECRET_KEYS.MANCER);
|
||||||
return api_key_mancer ? { "X-API-KEY": api_key_mancer } : {};
|
return apiKey ? { "X-API-KEY": apiKey } : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAphroditeHeaders() {
|
||||||
|
const apiKey = readSecret(SECRET_KEYS.APHRODITE);
|
||||||
|
return apiKey ? { "X-API-KEY": apiKey } : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOverrideHeaders(urlHost) {
|
function getOverrideHeaders(urlHost) {
|
||||||
@ -162,6 +167,26 @@ function getOverrideHeaders(urlHost) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets additional headers for the request.
|
||||||
|
* @param {object} request Original request body
|
||||||
|
* @param {object} args New request arguments
|
||||||
|
* @param {string|null} server API server for new request
|
||||||
|
*/
|
||||||
|
function setAdditionalHeaders(request, args, server) {
|
||||||
|
let headers = {};
|
||||||
|
|
||||||
|
if (request.body.use_mancer) {
|
||||||
|
headers = getMancerHeaders();
|
||||||
|
} else if (request.body.use_aphrodite) {
|
||||||
|
headers = getAphroditeHeaders();
|
||||||
|
} else {
|
||||||
|
headers = server ? getOverrideHeaders((new URL(server))?.host) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
args.headers = Object.assign(args.headers, headers);
|
||||||
|
}
|
||||||
|
|
||||||
function humanizedISO8601DateTime(date) {
|
function humanizedISO8601DateTime(date) {
|
||||||
let baseDate = typeof date === 'number' ? new Date(date) : new Date();
|
let baseDate = typeof date === 'number' ? new Date(date) : new Date();
|
||||||
let humanYear = baseDate.getFullYear();
|
let humanYear = baseDate.getFullYear();
|
||||||
@ -451,6 +476,52 @@ app.post("/generate", jsonParser, async function (request, response_generate) {
|
|||||||
return response_generate.send({ error: true });
|
return response_generate.send({ error: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} streamingUrlString Streaming URL
|
||||||
|
* @param {import('express').Request} request Express request
|
||||||
|
* @param {import('express').Response} response Express response
|
||||||
|
* @param {AbortController} controller Abort controller
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function sendAphroditeStreamingRequest(streamingUrlString, request, response, controller) {
|
||||||
|
request.body['stream'] = true;
|
||||||
|
|
||||||
|
const args = {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(request.body),
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
signal: controller.signal,
|
||||||
|
};
|
||||||
|
|
||||||
|
setAdditionalHeaders(request, args, streamingUrlString);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const generateResponse = await fetch(streamingUrlString + "/v1/generate", args);
|
||||||
|
// Pipe remote SSE stream to Express response
|
||||||
|
generateResponse.body.pipe(response);
|
||||||
|
|
||||||
|
request.socket.on('close', function () {
|
||||||
|
if (generateResponse.body instanceof Readable) generateResponse.body.destroy(); // Close the remote stream
|
||||||
|
response.end(); // End the Express response
|
||||||
|
});
|
||||||
|
|
||||||
|
generateResponse.body.on('end', function () {
|
||||||
|
console.log("Streaming request finished");
|
||||||
|
response.end();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
let value = { error: true, status: error.status, response: error.statusText };
|
||||||
|
console.log("Aphrodite endpoint error:", error);
|
||||||
|
|
||||||
|
if (!response.headersSent) {
|
||||||
|
return response.send(value);
|
||||||
|
} else {
|
||||||
|
return response.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//************** Text generation web UI
|
//************** Text generation web UI
|
||||||
app.post("/generate_textgenerationwebui", jsonParser, async function (request, response_generate) {
|
app.post("/generate_textgenerationwebui", jsonParser, async function (request, response_generate) {
|
||||||
if (!request.body) return response_generate.sendStatus(400);
|
if (!request.body) return response_generate.sendStatus(400);
|
||||||
@ -470,6 +541,10 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
if (streamingUrlHeader === undefined) return response_generate.sendStatus(400);
|
if (streamingUrlHeader === undefined) return response_generate.sendStatus(400);
|
||||||
const streamingUrlString = streamingUrlHeader.replace("localhost", "127.0.0.1");
|
const streamingUrlString = streamingUrlHeader.replace("localhost", "127.0.0.1");
|
||||||
|
|
||||||
|
if (request.body.use_aphrodite) {
|
||||||
|
return sendAphroditeStreamingRequest(streamingUrlString, request, response_generate, controller);
|
||||||
|
}
|
||||||
|
|
||||||
response_generate.writeHead(200, {
|
response_generate.writeHead(200, {
|
||||||
'Content-Type': 'text/plain;charset=utf-8',
|
'Content-Type': 'text/plain;charset=utf-8',
|
||||||
'Transfer-Encoding': 'chunked',
|
'Transfer-Encoding': 'chunked',
|
||||||
@ -482,9 +557,20 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
|
|
||||||
websocket.on('open', async function () {
|
websocket.on('open', async function () {
|
||||||
console.log('WebSocket opened');
|
console.log('WebSocket opened');
|
||||||
|
|
||||||
|
let headers = {};
|
||||||
|
|
||||||
|
if (request.body.use_mancer) {
|
||||||
|
headers = getMancerHeaders();
|
||||||
|
} else if (request.body.use_aphrodite) {
|
||||||
|
headers = getAphroditeHeaders();
|
||||||
|
} else {
|
||||||
|
headers = getOverrideHeaders(streamingUrl?.host);
|
||||||
|
}
|
||||||
|
|
||||||
const combined_args = Object.assign(
|
const combined_args = Object.assign(
|
||||||
{},
|
{},
|
||||||
request.body.use_mancer ? get_mancer_headers() : getOverrideHeaders(streamingUrl?.host),
|
headers,
|
||||||
request.body
|
request.body
|
||||||
);
|
);
|
||||||
console.log(combined_args);
|
console.log(combined_args);
|
||||||
@ -568,11 +654,7 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.body.use_mancer) {
|
setAdditionalHeaders(request, args, api_server);
|
||||||
args.headers = Object.assign(args.headers, get_mancer_headers());
|
|
||||||
} else {
|
|
||||||
args.headers = Object.assign(args.headers, getOverrideHeaders((new URL(api_server))?.host));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await postAsync(api_server + "/v1/generate", args);
|
const data = await postAsync(api_server + "/v1/generate", args);
|
||||||
@ -677,11 +759,7 @@ app.post("/getstatus", jsonParser, async function (request, response) {
|
|||||||
headers: { "Content-Type": "application/json" }
|
headers: { "Content-Type": "application/json" }
|
||||||
};
|
};
|
||||||
|
|
||||||
if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
|
setAdditionalHeaders(request, args, api_server);
|
||||||
args.headers = Object.assign(args.headers, get_mancer_headers());
|
|
||||||
} else {
|
|
||||||
args.headers = Object.assign(args.headers, getOverrideHeaders((new URL(api_server))?.host));
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = api_server + "/v1/model";
|
const url = api_server + "/v1/model";
|
||||||
let version = '';
|
let version = '';
|
||||||
@ -3237,9 +3315,8 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (main_api == 'textgenerationwebui') {
|
if (main_api == 'textgenerationwebui') {
|
||||||
if (request.body.use_mancer) {
|
setAdditionalHeaders(request, args, null);
|
||||||
args.headers = Object.assign(args.headers, get_mancer_headers());
|
|
||||||
}
|
|
||||||
const data = await postAsync(api_server + "/v1/token-count", args);
|
const data = await postAsync(api_server + "/v1/token-count", args);
|
||||||
return response.send({ count: data['results'][0]['tokens'] });
|
return response.send({ count: data['results'][0]['tokens'] });
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ const SECRETS_FILE = path.join(process.cwd(), './secrets.json');
|
|||||||
const SECRET_KEYS = {
|
const SECRET_KEYS = {
|
||||||
HORDE: 'api_key_horde',
|
HORDE: 'api_key_horde',
|
||||||
MANCER: 'api_key_mancer',
|
MANCER: 'api_key_mancer',
|
||||||
|
APHRODITE: 'api_key_aphrodite',
|
||||||
OPENAI: 'api_key_openai',
|
OPENAI: 'api_key_openai',
|
||||||
NOVEL: 'api_key_novel',
|
NOVEL: 'api_key_novel',
|
||||||
CLAUDE: 'api_key_claude',
|
CLAUDE: 'api_key_claude',
|
||||||
|
Reference in New Issue
Block a user