Merge branch 'staging' into neo-server

This commit is contained in:
Cohee 2024-04-10 21:41:03 +03:00
commit bd4d8847ce
13 changed files with 410 additions and 99 deletions

View File

@ -208,6 +208,7 @@
#cfgConfig,
#logprobsViewer,
#movingDivs > div {
/* 100vh are fallback units for browsers that don't support svh */
height: calc(100vh - 45px);
height: calc(100svh - 45px);
min-width: 100% !important;
@ -223,6 +224,10 @@
backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2));
}
#right-nav-panel {
padding-right: 15px;
}
#floatingPrompt,
#cfgConfig,
#logprobsViewer,

View File

@ -99,7 +99,7 @@
#bulkTagsList,
#tagList.tags {
margin: 2px 0;
margin: 5px 0;
}
#bulkTagsList,

View File

@ -2405,16 +2405,20 @@
</optgroup>
<optgroup label="GPT-4">
<option value="gpt-4">gpt-4</option>
<option value="gpt-4-turbo-preview">gpt-4-turbo-preview</option>
<option value="gpt-4-vision-preview">gpt-4-vision-preview</option>
<option value="gpt-4-0125-preview">gpt-4-0125-preview (2024)</option>
<option value="gpt-4-1106-preview">gpt-4-1106-preview (2023)</option>
<option value="gpt-4-0613">gpt-4-0613 (2023)</option>
<option value="gpt-4-0314">gpt-4-0314 (2023)</option>
<option value="gpt-4-32k">gpt-4-32k</option>
<option value="gpt-4-32k-0613">gpt-4-32k-0613 (2023)</option>
<option value="gpt-4-32k-0314">gpt-4-32k-0314 (2023)</option>
</optgroup>
<optgroup label="GPT-4 Turbo">
<option value="gpt-4-turbo">gpt-4-turbo</option>
<option value="gpt-4-turbo-2024-04-09">gpt-4-turbo-2024-04-09</option>
<option value="gpt-4-turbo-preview">gpt-4-turbo-preview</option>
<option value="gpt-4-vision-preview">gpt-4-vision-preview</option>
<option value="gpt-4-0125-preview">gpt-4-0125-preview (2024)</option>
<option value="gpt-4-1106-preview">gpt-4-1106-preview (2023)</option>
</optgroup>
<optgroup label="Other">
<option value="text-davinci-003">text-davinci-003</option>
<option value="text-davinci-002">text-davinci-002</option>
@ -2730,6 +2734,11 @@
<div class="flex-container">
<select id="model_custom_select" class="text_pole"></select>
</div>
<h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4>
<select id="custom_prompt_post_processing" class="text_pole" title="Applies additional processing to the prompt before sending it to the API.">
<option value="">None</option>
<option value="claude">Claude</option>
</select>
</form>
<div class="flex-container flex">
<div id="api_button_openai" class="api_button menu_button menu_button_icon" type="submit" data-i18n="Connect">Connect</div>
@ -4165,7 +4174,7 @@
<div class="right_menu_button fa-solid fa-list-ul" id="rm_button_characters" title="Select/Create Characters" data-i18n="[title]Select/Create Characters"></div>
</div>
<div id="HotSwapWrapper" class="alignitemscenter flex-container margin0auto wide100p">
<div class="hotswap avatars_inline flex-container"></div>
<div class="hotswap avatars_inline flex-container expander"></div>
</div>
</div>
<hr>
@ -4202,76 +4211,74 @@
Tokens: <span data-token-counter="character_name_pole" data-token-permanent="true">counting...</span>
</div>
</div>
<div id="avatar_div" class="avatar_div alignitemsflexstart justifySpaceBetween flexnowrap flexGap5">
<label id="avatar_div_div" class="add_avatar avatar" for="add_avatar_button" title="Click to select a new avatar for this character" data-i18n="[title]Click to select a new avatar for this character">
<img id="avatar_load_preview" src="img/ai4.png" alt="avatar">
<input hidden type="file" id="add_avatar_button" name="avatar" accept="image/*">
</label>
<div class="flex-container flexFlowColumn">
<div class="flex-container flexFlowColumn">
<div class="flex-container justifyContentFlexEnd flexFlowColumn">
<div class="form_create_bottom_buttons_block">
<div id="rm_button_back" class="menu_button fa-solid fa-left-long "></div>
<!-- <div id="renameCharButton" class="menu_button fa-solid fa-user-pen" title="Rename Character"></div> -->
<div id="favorite_button" class="menu_button fa-solid fa-star" title="Add to Favorites" data-i18n="[title]Add to Favorites"></div>
<input type="hidden" id="fav_checkbox" name="fav" />
<div id="advanced_div" class="menu_button fa-solid fa-book " title="Advanced Definitions" data-i18n="[title]Advanced Definition"></div>
<div id="world_button" class="menu_button fa-solid fa-globe" title="Character Lore" data-i18n="[title]Character Lore"></div>
<div class="chat_lorebook_button menu_button fa-solid fa-passport" title="Chat Lore" data-i18n="[title]Chat Lore"></div>
<div id="export_button" class="menu_button fa-solid fa-file-export " title="Export and Download" data-i18n="[title]Export and Download"></div>
<!-- <div id="set_chat_scenario" class="menu_button fa-solid fa-scroll" title="Set a chat scenario override"></div> -->
<!-- <div id="set_character_world" class="menu_button fa-solid fa-globe" title="Set a character World Info / Lorebook"></div> -->
<div id="dupe_button" class="menu_button fa-solid fa-clone " title="Duplicate Character" data-i18n="[title]Duplicate Character"></div>
<label for="create_button" id="create_button_label" class="menu_button fa-solid fa-user-check" title="Create Character" data-i18n="[title]Create Character">
<input type="submit" id="create_button" name="create_button">
</label>
<div id="delete_button" class="menu_button fa-solid fa-skull " title="Delete Character" data-i18n="[title]Delete Character"></div>
</div>
<label class="flex1" for="char-management-dropdown">
<select id="char-management-dropdown">
<option value="default" disabled selected data-i18n="More...">More...</option>
<option id="set_character_world" data-i18n="Link to World Info">
Link to World Info
</option>
<option id="import_character_info" data-i18n="Import Card Lore">
Import Card Lore
</option>
<option id="set_chat_scenario" data-i18n="Scenario Override">
Scenario Override
</option>
<option id="convert_to_persona" data-i18n="Convert to Persona">
Convert to Persona
</option>
<option id="renameCharButton" data-i18n="Rename">
Rename
</option>
<option id="character_source" data-i18n="Link to Source">
Link to Source
</option>
<option id="replace_update" data-i18n="Replace / Update">
Replace / Update
</option>
<!--<option id="dupe_button">
Duplicate
</option>
<option id="export_button">
Export
</option>
<option id="delete_button">
Delete
</option>-->
</select>
<div class="flex-container flexFlowColumn expander flexNoGap">
<div id="avatar_div" class="avatar_div alignitemsflexstart justifySpaceBetween flexnowrap">
<label id="avatar_div_div" class="add_avatar avatar" for="add_avatar_button" title="Click to select a new avatar for this character" data-i18n="[title]Click to select a new avatar for this character">
<img id="avatar_load_preview" src="img/ai4.png" alt="avatar">
<input hidden type="file" id="add_avatar_button" name="avatar" accept="image/*">
</label>
<div class="flex-container" id="avatar_controls">
<div class="form_create_bottom_buttons_block">
<div id="rm_button_back" class="menu_button fa-solid fa-left-long "></div>
<!-- <div id="renameCharButton" class="menu_button fa-solid fa-user-pen" title="Rename Character"></div> -->
<div id="favorite_button" class="menu_button fa-solid fa-star" title="Add to Favorites" data-i18n="[title]Add to Favorites"></div>
<input type="hidden" id="fav_checkbox" name="fav" />
<div id="advanced_div" class="menu_button fa-solid fa-book " title="Advanced Definitions" data-i18n="[title]Advanced Definition"></div>
<div id="world_button" class="menu_button fa-solid fa-globe" title="Character Lore" data-i18n="[title]Character Lore"></div>
<div class="chat_lorebook_button menu_button fa-solid fa-passport" title="Chat Lore" data-i18n="[title]Chat Lore"></div>
<div id="export_button" class="menu_button fa-solid fa-file-export " title="Export and Download" data-i18n="[title]Export and Download"></div>
<!-- <div id="set_chat_scenario" class="menu_button fa-solid fa-scroll" title="Set a chat scenario override"></div> -->
<!-- <div id="set_character_world" class="menu_button fa-solid fa-globe" title="Set a character World Info / Lorebook"></div> -->
<div id="dupe_button" class="menu_button fa-solid fa-clone " title="Duplicate Character" data-i18n="[title]Duplicate Character"></div>
<label for="create_button" id="create_button_label" class="menu_button fa-solid fa-user-check" title="Create Character" data-i18n="[title]Create Character">
<input type="submit" id="create_button" name="create_button">
</label>
<div id="delete_button" class="menu_button fa-solid fa-skull " title="Delete Character" data-i18n="[title]Delete Character"></div>
</div>
<div id="tags_div">
<div class="tag_controls">
<input id="tagInput" class="text_pole textarea_compact tag_input wide100p margin0" data-i18n="[placeholder]Search / Create Tags" placeholder="Search / Create tags" maxlength="50" />
<div class="tags_view menu_button fa-solid fa-tags" title="View all tags" data-i18n="[title]View all tags"></div>
</div>
<div id="tagList" class="tags"></div>
</div>
<label class="flex1 height100p" for="char-management-dropdown">
<select id="char-management-dropdown" class="text_pole">
<option value="default" disabled selected data-i18n="More...">More...</option>
<option id="set_character_world" data-i18n="Link to World Info">
Link to World Info
</option>
<option id="import_character_info" data-i18n="Import Card Lore">
Import Card Lore
</option>
<option id="set_chat_scenario" data-i18n="Scenario Override">
Scenario Override
</option>
<option id="convert_to_persona" data-i18n="Convert to Persona">
Convert to Persona
</option>
<option id="renameCharButton" data-i18n="Rename">
Rename
</option>
<option id="character_source" data-i18n="Link to Source">
Link to Source
</option>
<option id="replace_update" data-i18n="Replace / Update">
Replace / Update
</option>
<!--<option id="dupe_button">
Duplicate
</option>
<option id="export_button">
Export
</option>
<option id="delete_button">
Delete
</option>-->
</select>
</label>
</div>
</div>
<div id="tags_div">
<div class="tag_controls">
<input id="tagInput" class="text_pole textarea_compact tag_input wide100p margin0" data-i18n="[placeholder]Search / Create Tags" placeholder="Search / Create tags" maxlength="50" />
<div class="tags_view menu_button fa-solid fa-tags" title="View all tags" data-i18n="[title]View all tags"></div>
</div>
<div id="tagList" class="tags"></div>
</div>
</div>
</div>
<hr>
@ -5007,8 +5014,8 @@
<div class="world_entry_form_control flex1">
<label for="content ">
<small>
<span data-i18n="Content" class="alignitemscenter flex-container flexnowrap wide100p justifySpaceBetween">
<span class="alignitemscenter flex-container flexNoGap">
<span class="alignitemscenter flex-container flexnowrap wide100p justifySpaceBetween">
<span data-i18n="Content" class="alignitemscenter flex-container flexNoGap">
Content
</span>
<span>

View File

@ -30,7 +30,7 @@ function migrateSettings() {
if (extension_settings.caption.source === 'openai') {
extension_settings.caption.source = 'multimodal';
extension_settings.caption.multimodal_api = 'openai';
extension_settings.caption.multimodal_model = 'gpt-4-vision-preview';
extension_settings.caption.multimodal_model = 'gpt-4-turbo';
}
if (!extension_settings.caption.multimodal_api) {
@ -38,7 +38,7 @@ function migrateSettings() {
}
if (!extension_settings.caption.multimodal_model) {
extension_settings.caption.multimodal_model = 'gpt-4-vision-preview';
extension_settings.caption.multimodal_model = 'gpt-4-turbo';
}
if (!extension_settings.caption.prompt) {
@ -369,6 +369,7 @@ jQuery(function () {
<label for="caption_multimodal_model">Model</label>
<select id="caption_multimodal_model" class="flex1 text_pole">
<option data-type="openai" value="gpt-4-vision-preview">gpt-4-vision-preview</option>
<option data-type="openai" value="gpt-4-turbo">gpt-4-turbo</option>
<option data-type="anthropic" value="claude-3-opus-20240229">claude-3-opus-20240229</option>
<option data-type="anthropic" value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</option>
<option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>

View File

@ -56,7 +56,7 @@ export async function getMultimodalCaption(base64Img, prompt) {
if (!isGoogle) {
requestBody.api = extension_settings.caption.multimodal_api || 'openai';
requestBody.model = extension_settings.caption.multimodal_model || 'gpt-4-vision-preview';
requestBody.model = extension_settings.caption.multimodal_model || 'gpt-4-turbo';
requestBody.reverse_proxy = proxyUrl;
requestBody.proxy_password = proxyPassword;
}
@ -83,7 +83,7 @@ export async function getMultimodalCaption(base64Img, prompt) {
if (isCustom) {
requestBody.server_url = oai_settings.custom_url;
requestBody.model = oai_settings.custom_model || 'gpt-4-vision-preview';
requestBody.model = oai_settings.custom_model || 'gpt-4-turbo';
requestBody.custom_include_headers = oai_settings.custom_include_headers;
requestBody.custom_include_body = oai_settings.custom_include_body;
requestBody.custom_exclude_body = oai_settings.custom_exclude_body;

View File

@ -48,6 +48,7 @@ const sources = {
comfy: 'comfy',
togetherai: 'togetherai',
drawthings: 'drawthings',
pollinations: 'pollinations',
};
const generationMode = {
@ -254,6 +255,10 @@ const defaultSettings = {
// ComyUI settings
comfy_url: 'http://127.0.0.1:8188',
comfy_workflow: 'Default_Comfy_Workflow.json',
// Pollinations settings
pollinations_enhance: false,
pollinations_refine: false,
};
function processTriggers(chat, _, abort) {
@ -383,6 +388,8 @@ async function loadSettings() {
$('#sd_novel_sm').prop('checked', extension_settings.sd.novel_sm);
$('#sd_novel_sm_dyn').prop('checked', extension_settings.sd.novel_sm_dyn);
$('#sd_novel_sm_dyn').prop('disabled', !extension_settings.sd.novel_sm);
$('#sd_pollinations_enhance').prop('checked', extension_settings.sd.pollinations_enhance);
$('#sd_pollinations_refine').prop('checked', extension_settings.sd.pollinations_refine);
$('#sd_horde').prop('checked', extension_settings.sd.horde);
$('#sd_horde_nsfw').prop('checked', extension_settings.sd.horde_nsfw);
$('#sd_horde_karras').prop('checked', extension_settings.sd.horde_karras);
@ -828,6 +835,16 @@ function onNovelSmDynInput() {
saveSettingsDebounced();
}
function onPollinationsEnhanceInput() {
extension_settings.sd.pollinations_enhance = !!$('#sd_pollinations_enhance').prop('checked');
saveSettingsDebounced();
}
function onPollinationsRefineInput() {
extension_settings.sd.pollinations_refine = !!$('#sd_pollinations_refine').prop('checked');
saveSettingsDebounced();
}
function onHordeNsfwInput() {
extension_settings.sd.horde_nsfw = !!$(this).prop('checked');
saveSettingsDebounced();
@ -1023,7 +1040,7 @@ async function onModelChange() {
extension_settings.sd.model = $('#sd_model').find(':selected').val();
saveSettingsDebounced();
const cloudSources = [sources.horde, sources.novel, sources.openai, sources.togetherai];
const cloudSources = [sources.horde, sources.novel, sources.openai, sources.togetherai, sources.pollinations];
if (cloudSources.includes(extension_settings.sd.source)) {
return;
@ -1188,6 +1205,9 @@ async function loadSamplers() {
case sources.togetherai:
samplers = ['N/A'];
break;
case sources.pollinations:
samplers = ['N/A'];
break;
}
for (const sampler of samplers) {
@ -1368,6 +1388,9 @@ async function loadModels() {
case sources.togetherai:
models = await loadTogetherAIModels();
break;
case sources.pollinations:
models = await loadPollinationsModels();
break;
}
for (const model of models) {
@ -1384,6 +1407,55 @@ async function loadModels() {
}
}
async function loadPollinationsModels() {
return [
{
value: 'pixart',
text: 'PixArt-αlpha',
},
{
value: 'playground',
text: 'Playground v2',
},
{
value: 'dalle3xl',
text: 'DALL•E 3 XL',
},
{
value: 'formulaxl',
text: 'FormulaXL',
},
{
value: 'dreamshaper',
text: 'DreamShaper',
},
{
value: 'deliberate',
text: 'Deliberate',
},
{
value: 'dpo',
text: 'SDXL-DPO',
},
{
value: 'swizz8',
text: 'Swizz8',
},
{
value: 'juggernaut',
text: 'Juggernaut',
},
{
value: 'turbo',
text: 'SDXL Turbo',
},
{
value: 'realvis',
text: 'Realistic Vision',
},
];
}
async function loadTogetherAIModels() {
if (!secret_state[SECRET_KEYS.TOGETHERAI]) {
console.debug('TogetherAI API key is not set.');
@ -1641,6 +1713,9 @@ async function loadSchedulers() {
case sources.togetherai:
schedulers = ['N/A'];
break;
case sources.pollinations:
schedulers = ['N/A'];
break;
case sources.comfy:
schedulers = await loadComfySchedulers();
break;
@ -1706,6 +1781,9 @@ async function loadVaes() {
case sources.togetherai:
vaes = ['N/A'];
break;
case sources.pollinations:
vaes = ['N/A'];
break;
case sources.comfy:
vaes = await loadComfyVaes();
break;
@ -2135,6 +2213,9 @@ async function sendGenerationRequest(generationType, prompt, characterName = nul
case sources.togetherai:
result = await generateTogetherAIImage(prefixedPrompt, negativePrompt);
break;
case sources.pollinations:
result = await generatePollinationsImage(prefixedPrompt, negativePrompt);
break;
}
if (!result.data) {
@ -2181,6 +2262,30 @@ async function generateTogetherAIImage(prompt, negativePrompt) {
}
}
async function generatePollinationsImage(prompt, negativePrompt) {
const result = await fetch('/api/sd/pollinations/generate', {
method: 'POST',
headers: getRequestHeaders(),
body: JSON.stringify({
prompt: prompt,
negative_prompt: negativePrompt,
model: extension_settings.sd.model,
width: extension_settings.sd.width,
height: extension_settings.sd.height,
enhance: extension_settings.sd.pollinations_enhance,
refine: extension_settings.sd.pollinations_refine,
}),
});
if (result.ok) {
const data = await result.json();
return { format: 'jpg', data: data?.image };
} else {
const text = await result.text();
throw new Error(text);
}
}
/**
* Generates an "extras" image using a provided prompt and other settings.
*
@ -2775,6 +2880,8 @@ function isValidState() {
return true;
case sources.togetherai:
return secret_state[SECRET_KEYS.TOGETHERAI];
case sources.pollinations:
return true;
}
}
@ -2922,6 +3029,8 @@ jQuery(async () => {
$('#sd_novel_view_anlas').on('click', onViewAnlasClick);
$('#sd_novel_sm').on('input', onNovelSmInput);
$('#sd_novel_sm_dyn').on('input', onNovelSmDynInput);
$('#sd_pollinations_enhance').on('input', onPollinationsEnhanceInput);
$('#sd_pollinations_refine').on('input', onPollinationsRefineInput);
$('#sd_comfy_validate').on('click', validateComfyUrl);
$('#sd_comfy_url').on('input', onComfyUrlInput);
$('#sd_comfy_workflow').on('change', onComfyWorkflowChange);

View File

@ -32,14 +32,15 @@
</label>
<label for="sd_source">Source</label>
<select id="sd_source">
<option value="extras">Extras API (local / remote)</option>
<option value="horde">Stable Horde</option>
<option value="auto">Stable Diffusion Web UI (AUTOMATIC1111)</option>
<option value="vlad">SD.Next (vladmandic)</option>
<option value="comfy">ComfyUI</option>
<option value="drawthings">DrawThings HTTP API</option>
<option value="extras">Extras API (local / remote)</option>
<option value="novel">NovelAI Diffusion</option>
<option value="openai">OpenAI (DALL-E)</option>
<option value="comfy">ComfyUI</option>
<option value="pollinations">Pollinations</option>
<option value="vlad">SD.Next (vladmandic)</option>
<option value="auto">Stable Diffusion Web UI (AUTOMATIC1111)</option>
<option value="horde">Stable Horde</option>
<option value="togetherai">TogetherAI</option>
</select>
<div data-sd-source="auto">
@ -158,6 +159,25 @@
</div>
</div>
</div>
<div data-sd-source="pollinations">
<p>
<a href="https://pollinations.ai">Pollinations.ai</a>
</p>
<div class="flex-container">
<label class="flex1 checkbox_label" for="sd_pollinations_enhance">
<input id="sd_pollinations_enhance" type="checkbox" />
<span data-i18n="Enhance">
Enhance
</span>
</label>
<label class="flex1 checkbox_label" for="sd_pollinations_refine">
<input id="sd_pollinations_refine" type="checkbox" />
<span data-i18n="Refine">
Refine
</span>
</label>
</div>
</div>
<label for="sd_scale">CFG Scale (<span id="sd_scale_value"></span>)</label>
<input id="sd_scale" type="range" min="{{scale_min}}" max="{{scale_max}}" step="{{scale_step}}" value="{{scale}}" />
<label for="sd_steps">Sampling steps (<span id="sd_steps_value"></span>)</label>

View File

@ -186,6 +186,11 @@ const continue_postfix_types = {
DOUBLE_NEWLINE: '\n\n',
};
const custom_prompt_post_processing_types = {
NONE: '',
CLAUDE: 'claude',
};
const prefixMap = selected_group ? {
assistant: '',
user: '',
@ -262,6 +267,7 @@ const default_settings = {
continue_prefill: false,
names_behavior: character_names_behavior.NONE,
continue_postfix: continue_postfix_types.SPACE,
custom_prompt_post_processing: custom_prompt_post_processing_types.NONE,
seed: -1,
n: 1,
};
@ -331,6 +337,7 @@ const oai_settings = {
continue_prefill: false,
names_behavior: character_names_behavior.NONE,
continue_postfix: continue_postfix_types.SPACE,
custom_prompt_post_processing: custom_prompt_post_processing_types.NONE,
seed: -1,
n: 1,
};
@ -1743,6 +1750,7 @@ async function sendOpenAIRequest(type, messages, signal) {
generate_data['custom_include_body'] = oai_settings.custom_include_body;
generate_data['custom_exclude_body'] = oai_settings.custom_exclude_body;
generate_data['custom_include_headers'] = oai_settings.custom_include_headers;
generate_data['custom_prompt_post_processing'] = oai_settings.custom_prompt_post_processing;
}
if (isCohere) {
@ -2625,6 +2633,7 @@ function loadOpenAISettings(data, settings) {
oai_settings.custom_include_body = settings.custom_include_body ?? default_settings.custom_include_body;
oai_settings.custom_exclude_body = settings.custom_exclude_body ?? default_settings.custom_exclude_body;
oai_settings.custom_include_headers = settings.custom_include_headers ?? default_settings.custom_include_headers;
oai_settings.custom_prompt_post_processing = settings.custom_prompt_post_processing ?? default_settings.custom_prompt_post_processing;
oai_settings.google_model = settings.google_model ?? default_settings.google_model;
oai_settings.chat_completion_source = settings.chat_completion_source ?? default_settings.chat_completion_source;
oai_settings.api_url_scale = settings.api_url_scale ?? default_settings.api_url_scale;
@ -2770,6 +2779,8 @@ function loadOpenAISettings(data, settings) {
$('#chat_completion_source').val(oai_settings.chat_completion_source).trigger('change');
$('#oai_max_context_unlocked').prop('checked', oai_settings.max_context_unlocked);
$('#custom_prompt_post_processing').val(oai_settings.custom_prompt_post_processing);
$(`#custom_prompt_post_processing option[value="${oai_settings.custom_prompt_post_processing}"]`).attr('selected', true);
}
function setNamesBehaviorControls() {
@ -2924,6 +2935,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
custom_include_body: settings.custom_include_body,
custom_exclude_body: settings.custom_exclude_body,
custom_include_headers: settings.custom_include_headers,
custom_prompt_post_processing: settings.custom_prompt_post_processing,
google_model: settings.google_model,
temperature: settings.temp_openai,
frequency_penalty: settings.freq_pen_openai,
@ -3313,6 +3325,7 @@ function onSettingsPresetChange() {
custom_include_body: ['#custom_include_body', 'custom_include_body', false],
custom_exclude_body: ['#custom_exclude_body', 'custom_exclude_body', false],
custom_include_headers: ['#custom_include_headers', 'custom_include_headers', false],
custom_prompt_post_processing: ['#custom_prompt_post_processing', 'custom_prompt_post_processing', false],
google_model: ['#model_google_select', 'google_model', false],
openai_max_context: ['#openai_max_context', 'openai_max_context', false],
openai_max_tokens: ['#openai_max_tokens', 'openai_max_tokens', false],
@ -4025,12 +4038,13 @@ export function isImageInliningSupported() {
'gemini-1.0-pro-vision-latest',
'gemini-1.5-pro-latest',
'gemini-pro-vision',
'claude-3'
'claude-3',
'gpt-4-turbo',
];
switch (oai_settings.chat_completion_source) {
case chat_completion_sources.OPENAI:
return visionSupportedModels.some(model => oai_settings.openai_model.includes(model));
return visionSupportedModels.some(model => oai_settings.openai_model.includes(model) && !oai_settings.openai_model.includes('gpt-4-turbo-preview'));
case chat_completion_sources.MAKERSUITE:
return visionSupportedModels.some(model => oai_settings.google_model.includes(model));
case chat_completion_sources.CLAUDE:
@ -4493,6 +4507,11 @@ $(document).ready(async function () {
saveSettingsDebounced();
});
$('#custom_prompt_post_processing').on('change', function () {
oai_settings.custom_prompt_post_processing = String($(this).val());
saveSettingsDebounced();
});
$('#names_behavior').on('input', function () {
oai_settings.names_behavior = Number($(this).val());
setNamesBehaviorControls();

View File

@ -568,7 +568,7 @@ jQuery(function () {
const json_schema_string = String($(this).val());
try {
settings.json_schema = JSON.parse(json_schema_string ?? '{}');
settings.json_schema = JSON.parse(json_schema_string || '{}');
} catch {
// Ignore errors from here
}

View File

@ -986,9 +986,7 @@ body.reduced-motion #bg_custom {
}
.avatars_inline .avatar {
margin-top: calc(var(--avatar-base-border-radius));
margin-left: calc(var(--avatar-base-border-radius));
margin-bottom: calc(var(--avatar-base-border-radius));
margin: calc(var(--avatar-base-border-radius));
}
.avatars_inline .avatar:last-of-type {
@ -1101,8 +1099,8 @@ select {
@media screen and (min-width: 1001px) {
#description_textarea {
height: 30vh;
height: 30svh;
height: 29vh;
height: 29svh;
}
#firstmessage_textarea {
@ -1189,7 +1187,7 @@ input[type="file"] {
#right-nav-panel-tabs {
display: flex;
align-items: center;
gap: 10px;
gap: 5px;
overflow: hidden;
width: 100%;
}
@ -1199,7 +1197,7 @@ input[type="file"] {
align-items: center;
flex-wrap: wrap;
gap: 10px;
padding: 0 5px;
padding: 0px 10px 0px 5px;
}
#right-nav-panel-tabs .right_menu_button,
@ -1653,6 +1651,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
.missing-avatar.inline_avatar {
padding: unset;
border-radius: var(--avatar-base-border-radius-round);
width: fit-content;
}
/*applies to char list and mes_text char display name*/
@ -2001,6 +2000,19 @@ grammarly-extension {
justify-content: center;
align-items: center;
align-self: center !important;
width: 100%;
height: 100%;
/* Avoids cutting off the box shadow on the avatar*/
margin: 10px;
}
#avatar_controls {
height: 100%;
width: 100%;
flex-grow: 1;
justify-content: flex-end;
flex-flow: column;
padding: 5px 5px 10px 0;
}
#description_div,
@ -2211,11 +2223,11 @@ grammarly-extension {
font-weight: bold;
padding: 5px;
margin: 0;
height: 26px;
filter: grayscale(0.5);
text-align: center;
font-size: 17px;
aspect-ratio: 1 / 1;
flex: 0.075;
}
.menu_button:hover,
@ -2634,7 +2646,11 @@ input[type="range"]::-webkit-slider-thumb {
color: var(--SmartThemeBodyColor);
}
#char-management-dropdown,
#char-management-dropdown {
height: auto;
margin-bottom: 0;
}
#tagInput {
height: 26px;
margin-bottom: 0;

View File

@ -15,6 +15,23 @@ const API_CLAUDE = 'https://api.anthropic.com/v1';
const API_MISTRAL = 'https://api.mistral.ai/v1';
const API_COHERE = 'https://api.cohere.ai/v1';
/**
* Applies a post-processing step to the generated messages.
* @param {object[]} messages Messages to post-process
* @param {string} type Prompt conversion type
* @param {string} charName Character name
* @param {string} userName User name
* @returns
*/
function postProcessPrompt(messages, type, charName, userName) {
switch (type) {
case 'claude':
return convertClaudeMessages(messages, '', false, '', charName, userName).messages;
default:
return messages;
}
}
/**
* Ollama strikes back. Special boy #2's steaming routine.
* Wrap this abomination into proper SSE stream, again.
@ -524,9 +541,8 @@ async function sendMistralAIRequest(request, response) {
/**
* Sends a request to Cohere API.
* @param {import('express').Request} request
* @param {import('express').Response} response
* @returns {Promise<any>}
* @param {express.Request} request Express request
* @param {express.Response} response Express response
*/
async function sendCohereRequest(request, response) {
const apiKey = readSecret(request.user.directories, SECRET_KEYS.COHERE);
@ -856,6 +872,15 @@ router.post('/generate', jsonParser, function (request, response) {
mergeObjectWithYaml(bodyParams, request.body.custom_include_body);
mergeObjectWithYaml(headers, request.body.custom_include_headers);
if (request.body.custom_prompt_post_processing) {
console.log('Applying custom prompt post-processing of type', request.body.custom_prompt_post_processing);
request.body.messages = postProcessPrompt(
request.body.messages,
request.body.custom_prompt_post_processing,
request.body.char_name,
request.body.user_name);
}
} else {
console.log('This chat completion source is not supported yet.');
return response.status(400).send({ error: true });

View File

@ -473,6 +473,76 @@ llamacpp.post('/caption-image', jsonParser, async function (request, response) {
}
});
llamacpp.post('/props', jsonParser, async function (request, response) {
try {
if (!request.body.server_url) {
return response.sendStatus(400);
}
console.log('LlamaCpp props request:', request.body);
const baseUrl = trimV1(request.body.server_url);
const fetchResponse = await fetch(`${baseUrl}/props`, {
method: 'GET',
timeout: 0,
});
if (!fetchResponse.ok) {
console.log('LlamaCpp props error:', fetchResponse.status, fetchResponse.statusText);
return response.status(500).send({ error: true });
}
const data = await fetchResponse.json();
console.log('LlamaCpp props response:', data);
return response.send(data);
} catch (error) {
console.error(error);
return response.status(500);
}
});
llamacpp.post('/slots', jsonParser, async function (request, response) {
try {
if (!request.body.server_url) {
return response.sendStatus(400);
}
if (!/^\d+$/.test(request.body.id_slot)) {
return response.sendStatus(400);
}
if (!/^(erase|restore|save)$/.test(request.body.action)) {
return response.sendStatus(400);
}
console.log('LlamaCpp slots request:', request.body);
const baseUrl = trimV1(request.body.server_url);
const fetchResponse = await fetch(`${baseUrl}/slots/${request.body.id_slot}?action=${request.body.action}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
timeout: 0,
body: JSON.stringify({
filename: `${request.body.filename}`,
}),
});
if (!fetchResponse.ok) {
console.log('LlamaCpp slots error:', fetchResponse.status, fetchResponse.statusText);
return response.status(500).send({ error: true });
}
const data = await fetchResponse.json();
console.log('LlamaCpp slots response:', data);
return response.send(data);
} catch (error) {
console.error(error);
return response.status(500);
}
});
router.use('/ollama', ollama);
router.use('/llamacpp', llamacpp);

View File

@ -709,8 +709,47 @@ drawthings.post('/generate', jsonParser, async (request, response) => {
}
});
const pollinations = express.Router();
pollinations.post('/generate', jsonParser, async (request, response) => {
try {
const promptUrl = new URL(`https://image.pollinations.ai/prompt/${encodeURIComponent(request.body.prompt)}`);
const params = new URLSearchParams({
model: String(request.body.model),
negative_prompt: String(request.body.negative_prompt),
seed: String(Math.floor(Math.random() * 10_000_000)),
enhance: String(request.body.enhance ?? false),
refine: String(request.body.refine ?? false),
width: String(request.body.width ?? 1024),
height: String(request.body.height ?? 1024),
nologo: String(true),
nofeed: String(true),
referer: 'sillytavern',
});
promptUrl.search = params.toString();
console.log('Pollinations request URL:', promptUrl.toString());
const result = await fetch(promptUrl);
if (!result.ok) {
console.log('Pollinations returned an error.', result.status, result.statusText);
throw new Error('Pollinations request failed.');
}
const buffer = await result.buffer();
const base64 = buffer.toString('base64');
return response.send({ image: base64 });
} catch (error) {
console.log(error);
return response.sendStatus(500);
}
});
router.use('/comfy', comfy);
router.use('/together', together);
router.use('/drawthings', drawthings);
router.use('/pollinations', pollinations);
module.exports = { router };