Move text completion settings to respective module (#4239)
Signed| @@ -30,10 +30,9 @@ import { | |||
| 30 | generateTextGenWithStreaming, | 30 | generateTextGenWithStreaming, |
| 31 | getTextGenGenerationData, | 31 | getTextGenGenerationData, |
| 32 | textgen_types, | 32 | textgen_types, |
| 33 | getTextGenServer, | ||
| 34 | validateTextGenUrl, | ||
| 35 | parseTextgenLogprobs, | 33 | parseTextgenLogprobs, |
| 36 | parseTabbyLogprobs, | 34 | parseTabbyLogprobs, |
| 35 | initTextGenSettings, | ||
| 37 | } from './scripts/textgen-settings.js'; | 36 | } from './scripts/textgen-settings.js'; |
| 38 | 37 | ||
| 39 | import { | 38 | import { |
| @@ -206,12 +205,7 @@ import { | |||
| 206 | tag_import_setting, | 205 | tag_import_setting, |
| 207 | applyCharacterTagsToMessageDivs, | 206 | applyCharacterTagsToMessageDivs, |
| 208 | } from './scripts/tags.js'; | 207 | } from './scripts/tags.js'; |
| 209 | import { | 208 | import { initSecrets, readSecretState } from './scripts/secrets.js'; |
| 210 | SECRET_KEYS, | ||
| 211 | initSecrets, | ||
| 212 | readSecretState, | ||
| 213 | writeSecret, | ||
| 214 | } from './scripts/secrets.js'; | ||
| 215 | import { EventEmitter } from './lib/eventemitter.js'; | 209 | import { EventEmitter } from './lib/eventemitter.js'; |
| 216 | import { markdownExclusionExt } from './scripts/showdown-exclusion.js'; | 210 | import { markdownExclusionExt } from './scripts/showdown-exclusion.js'; |
| 217 | import { markdownUnderscoreExt } from './scripts/showdown-underscore.js'; | 211 | import { markdownUnderscoreExt } from './scripts/showdown-underscore.js'; |
| @@ -227,14 +221,13 @@ import { | |||
| 227 | formatInstructModePrompt, | 221 | formatInstructModePrompt, |
| 228 | formatInstructModeExamples, | 222 | formatInstructModeExamples, |
| 229 | getInstructStoppingSequences, | 223 | getInstructStoppingSequences, |
| 230 | autoSelectInstructPreset, | ||
| 231 | formatInstructModeSystemPrompt, | 224 | formatInstructModeSystemPrompt, |
| 232 | selectInstructPreset, | 225 | selectInstructPreset, |
| 233 | instruct_presets, | 226 | instruct_presets, |
| 234 | selectContextPreset, | 227 | selectContextPreset, |
| 235 | } from './scripts/instruct-mode.js'; | 228 | } from './scripts/instruct-mode.js'; |
| 236 | import { initLocales, t } from './scripts/i18n.js'; | 229 | import { initLocales, t } from './scripts/i18n.js'; |
| 237 | import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js'; | 230 | import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache } from './scripts/tokenizers.js'; |
| 238 | import { | 231 | import { |
| 239 | user_avatar, | 232 | user_avatar, |
| 240 | getUserAvatars, | 233 | getUserAvatars, |
| @@ -249,20 +242,7 @@ import { | |||
| 249 | import { getBackgrounds, initBackgrounds, loadBackgroundSettings, background_settings } from './scripts/backgrounds.js'; | 242 | import { getBackgrounds, initBackgrounds, loadBackgroundSettings, background_settings } from './scripts/backgrounds.js'; |
| 250 | import { hideLoader, showLoader } from './scripts/loader.js'; | 243 | import { hideLoader, showLoader } from './scripts/loader.js'; |
| 251 | import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay.js'; | 244 | import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay.js'; |
| 252 | import { | 245 | import { initTextGenModels } from './scripts/textgen-models.js'; |
| 253 | loadFeatherlessModels, | ||
| 254 | loadMancerModels, | ||
| 255 | loadOllamaModels, | ||
| 256 | loadTogetherAIModels, | ||
| 257 | loadInfermaticAIModels, | ||
| 258 | loadOpenRouterModels, | ||
| 259 | loadVllmModels, | ||
| 260 | loadAphroditeModels, | ||
| 261 | loadDreamGenModels, | ||
| 262 | initTextGenModels, | ||
| 263 | loadTabbyModels, | ||
| 264 | loadGenericModels, | ||
| 265 | } from './scripts/textgen-models.js'; | ||
| 266 | import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags, isExternalMediaAllowed, preserveNeutralChat, restoreNeutralChat, formatCreatorNotes, initChatUtilities, addDOMPurifyHooks } from './scripts/chats.js'; | 246 | import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags, isExternalMediaAllowed, preserveNeutralChat, restoreNeutralChat, formatCreatorNotes, initChatUtilities, addDOMPurifyHooks } from './scripts/chats.js'; |
| 267 | import { getPresetManager, initPresetManager } from './scripts/preset-manager.js'; | 247 | import { getPresetManager, initPresetManager } from './scripts/preset-manager.js'; |
| 268 | import { evaluateMacros, getLastMessageId, initMacros } from './scripts/macros.js'; | 248 | import { evaluateMacros, getLastMessageId, initMacros } from './scripts/macros.js'; |
| @@ -290,7 +270,6 @@ import { applyBrowserFixes } from './scripts/browser-fixes.js'; | |||
| 290 | import { initServerHistory } from './scripts/server-history.js'; | 270 | import { initServerHistory } from './scripts/server-history.js'; |
| 291 | import { initSettingsSearch } from './scripts/setting-search.js'; | 271 | import { initSettingsSearch } from './scripts/setting-search.js'; |
| 292 | import { initBulkEdit } from './scripts/bulk-edit.js'; | 272 | import { initBulkEdit } from './scripts/bulk-edit.js'; |
| 293 | import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; | ||
| 294 | import { getContext } from './scripts/st-context.js'; | 273 | import { getContext } from './scripts/st-context.js'; |
| 295 | import { extractReasoningFromData, initReasoning, parseReasoningInSwipes, PromptReasoning, ReasoningHandler, removeReasoningFromString, updateReasoningUI } from './scripts/reasoning.js'; | 274 | import { extractReasoningFromData, initReasoning, parseReasoningInSwipes, PromptReasoning, ReasoningHandler, removeReasoningFromString, updateReasoningUI } from './scripts/reasoning.js'; |
| 296 | import { accountStorage } from './scripts/util/AccountStorage.js'; | 275 | import { accountStorage } from './scripts/util/AccountStorage.js'; |
| @@ -880,6 +859,7 @@ async function firstLoadInit() { | |||
| 880 | initDefaultSlashCommands(); | 859 | initDefaultSlashCommands(); |
| 881 | initTextGenModels(); | 860 | initTextGenModels(); |
| 882 | initOpenAI(); | 861 | initOpenAI(); |
| 862 | initTextGenSettings(); | ||
| 883 | initKoboldSettings(); | 863 | initKoboldSettings(); |
| 884 | initNovelAISettings(); | 864 | initNovelAISettings(); |
| 885 | initSystemPrompts(); | 865 | initSystemPrompts(); |
| @@ -993,145 +973,6 @@ async function getStatusHorde() { | |||
| 993 | return resultCheckStatus(); | 973 | return resultCheckStatus(); |
| 994 | } | 974 | } |
| 995 | 975 | ||
| 996 | async function getStatusTextgen() { | ||
| 997 | const url = '/api/backends/text-completions/status'; | ||
| 998 | |||
| 999 | const endpoint = getTextGenServer(); | ||
| 1000 | |||
| 1001 | if (!endpoint) { | ||
| 1002 | console.warn('No endpoint for status check'); | ||
| 1003 | setOnlineStatus('no_connection'); | ||
| 1004 | return resultCheckStatus(); | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | if ([textgen_types.GENERIC, textgen_types.OOBA].includes(textgen_settings.type) && textgen_settings.bypass_status_check) { | ||
| 1008 | setOnlineStatus(t`Status check bypassed`); | ||
| 1009 | return resultCheckStatus(); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | try { | ||
| 1013 | const response = await fetch(url, { | ||
| 1014 | method: 'POST', | ||
| 1015 | headers: getRequestHeaders(), | ||
| 1016 | body: JSON.stringify({ | ||
| 1017 | api_server: endpoint, | ||
| 1018 | api_type: textgen_settings.type, | ||
| 1019 | }), | ||
| 1020 | signal: abortStatusCheck.signal, | ||
| 1021 | }); | ||
| 1022 | |||
| 1023 | const data = await response.json(); | ||
| 1024 | |||
| 1025 | if (textgen_settings.type === textgen_types.MANCER) { | ||
| 1026 | loadMancerModels(data?.data); | ||
| 1027 | setOnlineStatus(textgen_settings.mancer_model); | ||
| 1028 | } else if (textgen_settings.type === textgen_types.TOGETHERAI) { | ||
| 1029 | loadTogetherAIModels(data?.data); | ||
| 1030 | setOnlineStatus(textgen_settings.togetherai_model); | ||
| 1031 | } else if (textgen_settings.type === textgen_types.OLLAMA) { | ||
| 1032 | loadOllamaModels(data?.data); | ||
| 1033 | setOnlineStatus(textgen_settings.ollama_model || t`Connected`); | ||
| 1034 | } else if (textgen_settings.type === textgen_types.INFERMATICAI) { | ||
| 1035 | loadInfermaticAIModels(data?.data); | ||
| 1036 | setOnlineStatus(textgen_settings.infermaticai_model); | ||
| 1037 | } else if (textgen_settings.type === textgen_types.DREAMGEN) { | ||
| 1038 | loadDreamGenModels(data?.data); | ||
| 1039 | setOnlineStatus(textgen_settings.dreamgen_model); | ||
| 1040 | } else if (textgen_settings.type === textgen_types.OPENROUTER) { | ||
| 1041 | loadOpenRouterModels(data?.data); | ||
| 1042 | setOnlineStatus(textgen_settings.openrouter_model); | ||
| 1043 | } else if (textgen_settings.type === textgen_types.VLLM) { | ||
| 1044 | loadVllmModels(data?.data); | ||
| 1045 | setOnlineStatus(textgen_settings.vllm_model); | ||
| 1046 | } else if (textgen_settings.type === textgen_types.APHRODITE) { | ||
| 1047 | loadAphroditeModels(data?.data); | ||
| 1048 | setOnlineStatus(textgen_settings.aphrodite_model); | ||
| 1049 | } else if (textgen_settings.type === textgen_types.FEATHERLESS) { | ||
| 1050 | loadFeatherlessModels(data?.data); | ||
| 1051 | setOnlineStatus(textgen_settings.featherless_model); | ||
| 1052 | } else if (textgen_settings.type === textgen_types.TABBY) { | ||
| 1053 | loadTabbyModels(data?.data); | ||
| 1054 | setOnlineStatus(textgen_settings.tabby_model || data?.result); | ||
| 1055 | } else if (textgen_settings.type === textgen_types.GENERIC) { | ||
| 1056 | loadGenericModels(data?.data); | ||
| 1057 | setOnlineStatus(textgen_settings.generic_model || data?.result || t`Connected`); | ||
| 1058 | } else { | ||
| 1059 | setOnlineStatus(data?.result); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | if (!online_status) { | ||
| 1063 | setOnlineStatus('no_connection'); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | power_user.chat_template_hash = ''; | ||
| 1067 | |||
| 1068 | // Determine instruct mode preset | ||
| 1069 | const autoSelected = autoSelectInstructPreset(online_status); | ||
| 1070 | |||
| 1071 | const supportsTokenization = response.headers.get('x-supports-tokenization') === 'true'; | ||
| 1072 | supportsTokenization ? sessionStorage.setItem(TOKENIZER_SUPPORTED_KEY, 'true') : sessionStorage.removeItem(TOKENIZER_SUPPORTED_KEY); | ||
| 1073 | |||
| 1074 | const wantsInstructDerivation = !autoSelected && (power_user.instruct.enabled && power_user.instruct_derived); | ||
| 1075 | const wantsContextDerivation = !autoSelected && power_user.context_derived; | ||
| 1076 | const wantsContextSize = power_user.context_size_derived; | ||
| 1077 | const supportsChatTemplate = [textgen_types.KOBOLDCPP, textgen_types.LLAMACPP].includes(textgen_settings.type); | ||
| 1078 | |||
| 1079 | if (supportsChatTemplate && (wantsInstructDerivation || wantsContextDerivation || wantsContextSize)) { | ||
| 1080 | const response = await fetch('/api/backends/text-completions/props', { | ||
| 1081 | method: 'POST', | ||
| 1082 | headers: getRequestHeaders(), | ||
| 1083 | body: JSON.stringify({ | ||
| 1084 | api_server: endpoint, | ||
| 1085 | api_type: textgen_settings.type, | ||
| 1086 | }), | ||
| 1087 | }); | ||
| 1088 | |||
| 1089 | if (response.ok) { | ||
| 1090 | const data = await response.json(); | ||
| 1091 | if (data) { | ||
| 1092 | const { chat_template, chat_template_hash } = data; | ||
| 1093 | power_user.chat_template_hash = chat_template_hash; | ||
| 1094 | |||
| 1095 | if (wantsContextSize && 'default_generation_settings' in data) { | ||
| 1096 | const backend_max_context = data['default_generation_settings']['n_ctx']; | ||
| 1097 | const old_value = max_context; | ||
| 1098 | if (max_context !== backend_max_context) { | ||
| 1099 | setGenerationParamsFromPreset({ max_length: backend_max_context }); | ||
| 1100 | } | ||
| 1101 | if (old_value !== max_context) { | ||
| 1102 | console.log(`Auto-switched max context from ${old_value} to ${max_context}`); | ||
| 1103 | toastr.info(`${old_value} ⇒ ${max_context}`, 'Context Size Changed'); | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | console.log(`We have chat template ${chat_template.split('\n')[0]}...`); | ||
| 1107 | const { context, instruct } = await deriveTemplatesFromChatTemplate(chat_template, chat_template_hash); | ||
| 1108 | if (wantsContextDerivation && context) { | ||
| 1109 | selectContextPreset(context, { isAuto: true }); | ||
| 1110 | } | ||
| 1111 | if (wantsInstructDerivation && power_user.instruct.enabled && instruct) { | ||
| 1112 | selectInstructPreset(instruct, { isAuto: true }); | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | // We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress. | ||
| 1119 | if (online_status === 'no_connection' && data.response) { | ||
| 1120 | toastr.error(data.response, t`API Error`, { timeOut: 5000, preventDuplicates: true }); | ||
| 1121 | } | ||
| 1122 | } catch (err) { | ||
| 1123 | if (err instanceof AbortReason) { | ||
| 1124 | console.info('Status check aborted.', err.reason); | ||
| 1125 | } else { | ||
| 1126 | console.error('Error getting status', err); | ||
| 1127 | |||
| 1128 | } | ||
| 1129 | setOnlineStatus('no_connection'); | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | return resultCheckStatus(); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | export function startStatusLoading() { | 976 | export function startStatusLoading() { |
| 1136 | $('.api_loading').show(); | 977 | $('.api_loading').show(); |
| 1137 | $('.api_button').addClass('disabled'); | 978 | $('.api_button').addClass('disabled'); |
| @@ -10636,38 +10477,6 @@ jQuery(async function () { | |||
| 10636 | } | 10477 | } |
| 10637 | }); | 10478 | }); |
| 10638 | 10479 | ||
| 10639 | $('#api_button_textgenerationwebui').on('click', async function (e) { | ||
| 10640 | const keys = [ | ||
| 10641 | { id: 'api_key_mancer', secret: SECRET_KEYS.MANCER }, | ||
| 10642 | { id: 'api_key_vllm', secret: SECRET_KEYS.VLLM }, | ||
| 10643 | { id: 'api_key_aphrodite', secret: SECRET_KEYS.APHRODITE }, | ||
| 10644 | { id: 'api_key_tabby', secret: SECRET_KEYS.TABBY }, | ||
| 10645 | { id: 'api_key_togetherai', secret: SECRET_KEYS.TOGETHERAI }, | ||
| 10646 | { id: 'api_key_ooba', secret: SECRET_KEYS.OOBA }, | ||
| 10647 | { id: 'api_key_infermaticai', secret: SECRET_KEYS.INFERMATICAI }, | ||
| 10648 | { id: 'api_key_dreamgen', secret: SECRET_KEYS.DREAMGEN }, | ||
| 10649 | { id: 'api_key_openrouter-tg', secret: SECRET_KEYS.OPENROUTER }, | ||
| 10650 | { id: 'api_key_koboldcpp', secret: SECRET_KEYS.KOBOLDCPP }, | ||
| 10651 | { id: 'api_key_llamacpp', secret: SECRET_KEYS.LLAMACPP }, | ||
| 10652 | { id: 'api_key_featherless', secret: SECRET_KEYS.FEATHERLESS }, | ||
| 10653 | { id: 'api_key_huggingface', secret: SECRET_KEYS.HUGGINGFACE }, | ||
| 10654 | { id: 'api_key_generic', secret: SECRET_KEYS.GENERIC }, | ||
| 10655 | ]; | ||
| 10656 | |||
| 10657 | for (const key of keys) { | ||
| 10658 | const keyValue = String($(`#${key.id}`).val()).trim(); | ||
| 10659 | if (keyValue.length) { | ||
| 10660 | await writeSecret(key.secret, keyValue); | ||
| 10661 | } | ||
| 10662 | } | ||
| 10663 | |||
| 10664 | validateTextGenUrl(); | ||
| 10665 | startStatusLoading(); | ||
| 10666 | main_api = 'textgenerationwebui'; | ||
| 10667 | saveSettingsDebounced(); | ||
| 10668 | getStatusTextgen(); | ||
| 10669 | }); | ||
| 10670 | |||
| 10671 | 10480 | ||
| 10672 | const button = $('#options_button'); | 10481 | const button = $('#options_button'); |
| 10673 | const menu = $('#options'); | 10482 | const menu = $('#options'); |
| @@ -1,22 +1,30 @@ | |||
| 1 | import { | 1 | import { |
| 2 | abortStatusCheck, | ||
| 2 | eventSource, | 3 | eventSource, |
| 3 | event_types, | 4 | event_types, |
| 4 | getRequestHeaders, | 5 | getRequestHeaders, |
| 5 | getStoppingStrings, | 6 | getStoppingStrings, |
| 6 | main_api, | 7 | main_api, |
| 7 | max_context, | 8 | max_context, |
| 9 | online_status, | ||
| 10 | resultCheckStatus, | ||
| 8 | saveSettingsDebounced, | 11 | saveSettingsDebounced, |
| 9 | setGenerationParamsFromPreset, | 12 | setGenerationParamsFromPreset, |
| 10 | setOnlineStatus, | 13 | setOnlineStatus, |
| 14 | startStatusLoading, | ||
| 11 | substituteParams, | 15 | substituteParams, |
| 12 | } from '../script.js'; | 16 | } from '../script.js'; |
| 17 | import { deriveTemplatesFromChatTemplate } from './chat-templates.js'; | ||
| 13 | import { t } from './i18n.js'; | 18 | import { t } from './i18n.js'; |
| 19 | import { autoSelectInstructPreset, selectContextPreset, selectInstructPreset } from './instruct-mode.js'; | ||
| 14 | import { BIAS_CACHE, createNewLogitBiasEntry, displayLogitBias, getLogitBiasListResult } from './logit-bias.js'; | 20 | import { BIAS_CACHE, createNewLogitBiasEntry, displayLogitBias, getLogitBiasListResult } from './logit-bias.js'; |
| 15 | 21 | ||
| 16 | import { power_user, registerDebugFunction } from './power-user.js'; | 22 | import { power_user, registerDebugFunction } from './power-user.js'; |
| 23 | import { SECRET_KEYS, writeSecret } from './secrets.js'; | ||
| 17 | import { getEventSourceStream } from './sse-stream.js'; | 24 | import { getEventSourceStream } from './sse-stream.js'; |
| 18 | import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer } from './textgen-models.js'; | 25 | import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer, loadAphroditeModels, loadDreamGenModels, loadFeatherlessModels, loadGenericModels, loadInfermaticAIModels, loadMancerModels, loadOllamaModels, loadOpenRouterModels, loadTabbyModels, loadTogetherAIModels, loadVllmModels } from './textgen-models.js'; |
| 19 | import { ENCODE_TOKENIZERS, TEXTGEN_TOKENIZERS, getTextTokens, tokenizers } from './tokenizers.js'; | 26 | import { ENCODE_TOKENIZERS, TEXTGEN_TOKENIZERS, TOKENIZER_SUPPORTED_KEY, getTextTokens, tokenizers } from './tokenizers.js'; |
| 27 | import { AbortReason } from './util/AbortReason.js'; | ||
| 20 | import { getSortableDelay, onlyUnique, arraysEqual } from './utils.js'; | 28 | import { getSortableDelay, onlyUnique, arraysEqual } from './utils.js'; |
| 21 | 29 | ||
| 22 | export const textgen_types = { | 30 | export const textgen_types = { |
| @@ -621,7 +629,146 @@ function sortAphroditeItemsByOrder(orderArray) { | |||
| 621 | }); | 629 | }); |
| 622 | } | 630 | } |
| 623 | 631 | ||
| 624 | jQuery(function () { | 632 | async function getStatusTextgen() { |
| 633 | const url = '/api/backends/text-completions/status'; | ||
| 634 | |||
| 635 | const endpoint = getTextGenServer(); | ||
| 636 | |||
| 637 | if (!endpoint) { | ||
| 638 | console.warn('No endpoint for status check'); | ||
| 639 | setOnlineStatus('no_connection'); | ||
| 640 | return resultCheckStatus(); | ||
| 641 | } | ||
| 642 | |||
| 643 | if ([textgen_types.GENERIC, textgen_types.OOBA].includes(settings.type) && settings.bypass_status_check) { | ||
| 644 | setOnlineStatus(t`Status check bypassed`); | ||
| 645 | return resultCheckStatus(); | ||
| 646 | } | ||
| 647 | |||
| 648 | try { | ||
| 649 | const response = await fetch(url, { | ||
| 650 | method: 'POST', | ||
| 651 | headers: getRequestHeaders(), | ||
| 652 | body: JSON.stringify({ | ||
| 653 | api_server: endpoint, | ||
| 654 | api_type: settings.type, | ||
| 655 | }), | ||
| 656 | signal: abortStatusCheck.signal, | ||
| 657 | }); | ||
| 658 | |||
| 659 | const data = await response.json(); | ||
| 660 | |||
| 661 | if (settings.type === textgen_types.MANCER) { | ||
| 662 | loadMancerModels(data?.data); | ||
| 663 | setOnlineStatus(settings.mancer_model); | ||
| 664 | } else if (settings.type === textgen_types.TOGETHERAI) { | ||
| 665 | loadTogetherAIModels(data?.data); | ||
| 666 | setOnlineStatus(settings.togetherai_model); | ||
| 667 | } else if (settings.type === textgen_types.OLLAMA) { | ||
| 668 | loadOllamaModels(data?.data); | ||
| 669 | setOnlineStatus(settings.ollama_model || t`Connected`); | ||
| 670 | } else if (settings.type === textgen_types.INFERMATICAI) { | ||
| 671 | loadInfermaticAIModels(data?.data); | ||
| 672 | setOnlineStatus(settings.infermaticai_model); | ||
| 673 | } else if (settings.type === textgen_types.DREAMGEN) { | ||
| 674 | loadDreamGenModels(data?.data); | ||
| 675 | setOnlineStatus(settings.dreamgen_model); | ||
| 676 | } else if (settings.type === textgen_types.OPENROUTER) { | ||
| 677 | loadOpenRouterModels(data?.data); | ||
| 678 | setOnlineStatus(settings.openrouter_model); | ||
| 679 | } else if (settings.type === textgen_types.VLLM) { | ||
| 680 | loadVllmModels(data?.data); | ||
| 681 | setOnlineStatus(settings.vllm_model); | ||
| 682 | } else if (settings.type === textgen_types.APHRODITE) { | ||
| 683 | loadAphroditeModels(data?.data); | ||
| 684 | setOnlineStatus(settings.aphrodite_model); | ||
| 685 | } else if (settings.type === textgen_types.FEATHERLESS) { | ||
| 686 | loadFeatherlessModels(data?.data); | ||
| 687 | setOnlineStatus(settings.featherless_model); | ||
| 688 | } else if (settings.type === textgen_types.TABBY) { | ||
| 689 | loadTabbyModels(data?.data); | ||
| 690 | setOnlineStatus(settings.tabby_model || data?.result); | ||
| 691 | } else if (settings.type === textgen_types.GENERIC) { | ||
| 692 | loadGenericModels(data?.data); | ||
| 693 | setOnlineStatus(settings.generic_model || data?.result || t`Connected`); | ||
| 694 | } else { | ||
| 695 | setOnlineStatus(data?.result); | ||
| 696 | } | ||
| 697 | |||
| 698 | if (!online_status) { | ||
| 699 | setOnlineStatus('no_connection'); | ||
| 700 | } | ||
| 701 | |||
| 702 | power_user.chat_template_hash = ''; | ||
| 703 | |||
| 704 | // Determine instruct mode preset | ||
| 705 | const autoSelected = autoSelectInstructPreset(online_status); | ||
| 706 | |||
| 707 | const supportsTokenization = response.headers.get('x-supports-tokenization') === 'true'; | ||
| 708 | supportsTokenization ? sessionStorage.setItem(TOKENIZER_SUPPORTED_KEY, 'true') : sessionStorage.removeItem(TOKENIZER_SUPPORTED_KEY); | ||
| 709 | |||
| 710 | const wantsInstructDerivation = !autoSelected && (power_user.instruct.enabled && power_user.instruct_derived); | ||
| 711 | const wantsContextDerivation = !autoSelected && power_user.context_derived; | ||
| 712 | const wantsContextSize = power_user.context_size_derived; | ||
| 713 | const supportsChatTemplate = [textgen_types.KOBOLDCPP, textgen_types.LLAMACPP].includes(settings.type); | ||
| 714 | |||
| 715 | if (supportsChatTemplate && (wantsInstructDerivation || wantsContextDerivation || wantsContextSize)) { | ||
| 716 | const response = await fetch('/api/backends/text-completions/props', { | ||
| 717 | method: 'POST', | ||
| 718 | headers: getRequestHeaders(), | ||
| 719 | body: JSON.stringify({ | ||
| 720 | api_server: endpoint, | ||
| 721 | api_type: settings.type, | ||
| 722 | }), | ||
| 723 | }); | ||
| 724 | |||
| 725 | if (response.ok) { | ||
| 726 | const data = await response.json(); | ||
| 727 | if (data) { | ||
| 728 | const { chat_template, chat_template_hash } = data; | ||
| 729 | power_user.chat_template_hash = chat_template_hash; | ||
| 730 | |||
| 731 | if (wantsContextSize && 'default_generation_settings' in data) { | ||
| 732 | const backend_max_context = data['default_generation_settings']['n_ctx']; | ||
| 733 | const old_value = max_context; | ||
| 734 | if (max_context !== backend_max_context) { | ||
| 735 | setGenerationParamsFromPreset({ max_length: backend_max_context }); | ||
| 736 | } | ||
| 737 | if (old_value !== max_context) { | ||
| 738 | console.log(`Auto-switched max context from ${old_value} to ${max_context}`); | ||
| 739 | toastr.info(`${old_value} ⇒ ${max_context}`, 'Context Size Changed'); | ||
| 740 | } | ||
| 741 | } | ||
| 742 | console.log(`We have chat template ${chat_template.split('\n')[0]}...`); | ||
| 743 | const { context, instruct } = await deriveTemplatesFromChatTemplate(chat_template, chat_template_hash); | ||
| 744 | if (wantsContextDerivation && context) { | ||
| 745 | selectContextPreset(context, { isAuto: true }); | ||
| 746 | } | ||
| 747 | if (wantsInstructDerivation && power_user.instruct.enabled && instruct) { | ||
| 748 | selectInstructPreset(instruct, { isAuto: true }); | ||
| 749 | } | ||
| 750 | } | ||
| 751 | } | ||
| 752 | } | ||
| 753 | |||
| 754 | // We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress. | ||
| 755 | if (online_status === 'no_connection' && data.response) { | ||
| 756 | toastr.error(data.response, t`API Error`, { timeOut: 5000, preventDuplicates: true }); | ||
| 757 | } | ||
| 758 | } catch (err) { | ||
| 759 | if (err instanceof AbortReason) { | ||
| 760 | console.info('Status check aborted.', err.reason); | ||
| 761 | } else { | ||
| 762 | console.error('Error getting status', err); | ||
| 763 | |||
| 764 | } | ||
| 765 | setOnlineStatus('no_connection'); | ||
| 766 | } | ||
| 767 | |||
| 768 | return resultCheckStatus(); | ||
| 769 | } | ||
| 770 | |||
| 771 | export function initTextGenSettings() { | ||
| 625 | $('#send_banned_tokens_textgenerationwebui').on('change', function () { | 772 | $('#send_banned_tokens_textgenerationwebui').on('change', function () { |
| 626 | const checked = !!$(this).prop('checked'); | 773 | const checked = !!$(this).prop('checked'); |
| 627 | toggleBannedStringsKillSwitch(checked, | 774 | toggleBannedStringsKillSwitch(checked, |
| @@ -877,7 +1024,38 @@ jQuery(function () { | |||
| 877 | 1024 | ||
| 878 | saveSettingsDebounced(); | 1025 | saveSettingsDebounced(); |
| 879 | }); | 1026 | }); |
| 880 | }); | 1027 | |
| 1028 | $('#api_button_textgenerationwebui').on('click', async function (e) { | ||
| 1029 | const keys = [ | ||
| 1030 | { id: 'api_key_mancer', secret: SECRET_KEYS.MANCER }, | ||
| 1031 | { id: 'api_key_vllm', secret: SECRET_KEYS.VLLM }, | ||
| 1032 | { id: 'api_key_aphrodite', secret: SECRET_KEYS.APHRODITE }, | ||
| 1033 | { id: 'api_key_tabby', secret: SECRET_KEYS.TABBY }, | ||
| 1034 | { id: 'api_key_togetherai', secret: SECRET_KEYS.TOGETHERAI }, | ||
| 1035 | { id: 'api_key_ooba', secret: SECRET_KEYS.OOBA }, | ||
| 1036 | { id: 'api_key_infermaticai', secret: SECRET_KEYS.INFERMATICAI }, | ||
| 1037 | { id: 'api_key_dreamgen', secret: SECRET_KEYS.DREAMGEN }, | ||
| 1038 | { id: 'api_key_openrouter-tg', secret: SECRET_KEYS.OPENROUTER }, | ||
| 1039 | { id: 'api_key_koboldcpp', secret: SECRET_KEYS.KOBOLDCPP }, | ||
| 1040 | { id: 'api_key_llamacpp', secret: SECRET_KEYS.LLAMACPP }, | ||
| 1041 | { id: 'api_key_featherless', secret: SECRET_KEYS.FEATHERLESS }, | ||
| 1042 | { id: 'api_key_huggingface', secret: SECRET_KEYS.HUGGINGFACE }, | ||
| 1043 | { id: 'api_key_generic', secret: SECRET_KEYS.GENERIC }, | ||
| 1044 | ]; | ||
| 1045 | |||
| 1046 | for (const key of keys) { | ||
| 1047 | const keyValue = String($(`#${key.id}`).val()).trim(); | ||
| 1048 | if (keyValue.length) { | ||
| 1049 | await writeSecret(key.secret, keyValue); | ||
| 1050 | } | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | validateTextGenUrl(); | ||
| 1054 | startStatusLoading(); | ||
| 1055 | saveSettingsDebounced(); | ||
| 1056 | getStatusTextgen(); | ||
| 1057 | }); | ||
| 1058 | } | ||
| 881 | 1059 | ||
| 882 | function showTypeSpecificControls(type) { | 1060 | function showTypeSpecificControls(type) { |
| 883 | $('[data-tg-type]').each(function () { | 1061 | $('[data-tg-type]').each(function () { |