diff --git a/public/css/select2-overrides.css b/public/css/select2-overrides.css index 01577846e..47d9746ac 100644 --- a/public/css/select2-overrides.css +++ b/public/css/select2-overrides.css @@ -15,8 +15,13 @@ z-index: 40000; } -.select2-selection__clear { +.select2-container .select2-selection .select2-selection__clear { color: var(--SmartThemeBodyColor); + font-size: 24px; + padding: 0; + position: absolute; + right: 5px; + top: 0; } .select2-container .select2-search__field { diff --git a/public/index.html b/public/index.html index 81639044c..21f1b0fb2 100644 --- a/public/index.html +++ b/public/index.html @@ -1905,11 +1905,11 @@
@@ -2335,8 +2335,7 @@

- Ollama Model -

+ Ollama Model + + +
+ + +   + inline_model_loading: True + + must be set in Tabby's config.yml to switch models. + + + Use an admin API key. + + +
diff --git a/public/script.js b/public/script.js index 060a10ec7..95806394b 100644 --- a/public/script.js +++ b/public/script.js @@ -224,7 +224,7 @@ import { import { getBackgrounds, initBackgrounds, loadBackgroundSettings, background_settings } from './scripts/backgrounds.js'; import { hideLoader, showLoader } from './scripts/loader.js'; import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay.js'; -import { loadFeatherlessModels, loadMancerModels, loadOllamaModels, loadTogetherAIModels, loadInfermaticAIModels, loadOpenRouterModels, loadVllmModels, loadAphroditeModels, loadDreamGenModels, initTextGenModels } from './scripts/textgen-models.js'; +import { loadFeatherlessModels, loadMancerModels, loadOllamaModels, loadTogetherAIModels, loadInfermaticAIModels, loadOpenRouterModels, loadVllmModels, loadAphroditeModels, loadDreamGenModels, initTextGenModels, loadTabbyModels } from './scripts/textgen-models.js'; import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags, isExternalMediaAllowed, getCurrentEntityId } from './scripts/chats.js'; import { initPresetManager } from './scripts/preset-manager.js'; import { MacrosParser, evaluateMacros, getLastMessageId } from './scripts/macros.js'; @@ -1214,6 +1214,9 @@ async function getStatusTextgen() { } else if (textgen_settings.type === FEATHERLESS) { loadFeatherlessModels(data?.data); setOnlineStatus(textgen_settings.featherless_model); + } else if (textgen_settings.type === TABBY) { + loadTabbyModels(data?.data); + setOnlineStatus(textgen_settings.tabby_model || data?.result); } else { setOnlineStatus(data?.result); } diff --git a/public/scripts/preset-manager.js b/public/scripts/preset-manager.js index 896de485e..c32719ea4 100644 --- a/public/scripts/preset-manager.js +++ b/public/scripts/preset-manager.js @@ -338,6 +338,7 @@ class PresetManager { 'max_tokens_second', 'openrouter_providers', 'openrouter_allow_fallbacks', + 'tabby_model', ]; const settings = Object.assign({}, getSettingsByApiId(this.apiId)); diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index dfee15768..299211ba8 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -3426,6 +3426,7 @@ function getModelOptions(quiet) { { id: 'vllm_model', api: 'textgenerationwebui', type: textgen_types.VLLM }, { id: 'aphrodite_model', api: 'textgenerationwebui', type: textgen_types.APHRODITE }, { id: 'ollama_model', api: 'textgenerationwebui', type: textgen_types.OLLAMA }, + { id: 'tabby_model', api: 'textgenerationwebui', type: textgen_types.TABBY }, { id: 'model_openai_select', api: 'openai', type: chat_completion_sources.OPENAI }, { id: 'model_claude_select', api: 'openai', type: chat_completion_sources.CLAUDE }, { id: 'model_windowai_select', api: 'openai', type: chat_completion_sources.WINDOWAI }, diff --git a/public/scripts/textgen-models.js b/public/scripts/textgen-models.js index d35f2b724..a72ec07cb 100644 --- a/public/scripts/textgen-models.js +++ b/public/scripts/textgen-models.js @@ -12,6 +12,7 @@ let dreamGenModels = []; let vllmModels = []; let aphroditeModels = []; let featherlessModels = []; +let tabbyModels = []; export let openRouterModels = []; /** @@ -66,6 +67,30 @@ export async function loadOllamaModels(data) { } } +export async function loadTabbyModels(data) { + if (!Array.isArray(data)) { + console.error('Invalid Tabby models data', data); + return; + } + + tabbyModels = data; + tabbyModels.sort((a, b) => a.id.localeCompare(b.id)); + tabbyModels.unshift({ id: '' }); + + if (!tabbyModels.find(x => x.id === textgen_settings.tabby_model)) { + textgen_settings.tabby_model = tabbyModels[0]?.id || ''; + } + + $('#tabby_model').empty(); + for (const model of tabbyModels) { + const option = document.createElement('option'); + option.value = model.id; + option.text = model.id; + option.selected = model.id === textgen_settings.tabby_model; + $('#tabby_model').append(option); + } +} + export async function loadTogetherAIModels(data) { if (!Array.isArray(data)) { console.error('Invalid Together AI models data', data); @@ -310,6 +335,12 @@ function onOllamaModelSelect() { $('#api_button_textgenerationwebui').trigger('click'); } +function onTabbyModelSelect() { + const modelId = String($('#tabby_model').val()); + textgen_settings.tabby_model = modelId; + $('#api_button_textgenerationwebui').trigger('click'); +} + function onOpenRouterModelSelect() { const modelId = String($('#openrouter_model').val()); textgen_settings.openrouter_model = modelId; @@ -641,6 +672,7 @@ export function initTextGenModels() { $('#aphrodite_model').on('change', onAphroditeModelSelect); $('#featherless_model').on('change', onFeatherlessModelSelect); $('#tabby_download_model').on('click', downloadTabbyModel); + $('#tabby_model').on('change', onTabbyModelSelect); const providersSelect = $('.openrouter_providers'); for (const provider of OPENROUTER_PROVIDERS) { @@ -671,6 +703,13 @@ export function initTextGenModels() { searchInputCssClass: 'text_pole', width: '100%', }); + $('#tabby_model').select2({ + placeholder: '[Currently loaded]', + searchInputPlaceholder: 'Search models...', + searchInputCssClass: 'text_pole', + width: '100%', + allowClear: true, + }); $('#model_infermaticai_select').select2({ placeholder: 'Select a model', searchInputPlaceholder: 'Search models...', diff --git a/public/scripts/textgen-settings.js b/public/scripts/textgen-settings.js index 4d0fc8213..b3d8dea5b 100644 --- a/public/scripts/textgen-settings.js +++ b/public/scripts/textgen-settings.js @@ -180,6 +180,7 @@ const settings = { vllm_model: '', aphrodite_model: '', dreamgen_model: 'opus-v1-xl/text', + tabby_model: '', legacy_api: false, sampler_order: KOBOLDCPP_ORDER, logit_bias: [], @@ -995,7 +996,7 @@ function tryParseStreamingError(response, decoded) { // No JSON. Do nothing. } - const message = data?.error?.message || data?.message; + const message = data?.error?.message || data?.message || data?.detail; if (message) { toastr.error(message, 'Text Completion API'); @@ -1047,6 +1048,11 @@ export function getTextGenModel() { return settings.featherless_model; case HUGGINGFACE: return 'tgi'; + case TABBY: + if (settings.tabby_model) { + return settings.tabby_model; + } + break; default: return undefined; }