feat(openrouter): add model quantizations setting (#5080) * feat(openrouter): add model quantizations setting * Remove bogus setting * Simplify nullish coalescing assignment --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -2441,6 +2441,20 @@ | ||
| 2441 | 2441 | <span data-i18n="Allow fallback providers">Allow fallback providers</span> |
| 2442 | 2442 | </label> |
| 2443 | 2443 | </div> |
| 2444 | + <div> | |
| 2445 | + <h4 data-i18n="Model Quantizations">Model Quantizations</h4> | |
| 2446 | + <select id="openrouter_quantizations_text" class="openrouter_quantizations" multiple> | |
| 2447 | + <option data-i18n="Integer (4 bit)" value="int4">Integer (4 bit)</option> | |
| 2448 | + <option data-i18n="Integer (8 bit)" value="int8">Integer (8 bit)</option> | |
| 2449 | + <option data-i18n="Floating point (4 bit)" value="fp4">Floating point (4 bit)</option> | |
| 2450 | + <option data-i18n="Floating point (6 bit)" value="fp6">Floating point (6 bit)</option> | |
| 2451 | + <option data-i18n="Floating point (8 bit)" value="fp8">Floating point (8 bit)</option> | |
| 2452 | + <option data-i18n="Floating point (16 bit)" value="fp16">Floating point (16 bit)</option> | |
| 2453 | + <option data-i18n="Brain floating point (16 bit)" value="bf16">Brain floating point (16 bit)</option> | |
| 2454 | + <option data-i18n="Floating point (32 bit)" value="fp32">Floating point (32 bit)</option> | |
| 2455 | + <option data-i18n="Unknown" value="unknown">Unknown</option> | |
| 2456 | + </select> | |
| 2457 | + </div> | |
| 2444 | 2458 | </div> |
| 2445 | 2459 | <div data-tg-type="infermaticai" class="flex-container flexFlowColumn"> |
| 2446 | 2460 | <h4 data-i18n="InfermaticAI API Key">InfermaticAI API Key</h4> |
| @@ -3183,6 +3197,20 @@ | ||
| 3183 | 3197 | <i class="fa-solid fa-lightbulb"></i> |
| 3184 | 3198 | <span data-i18n="To use instruct formatting, switch to OpenRouter under Text Completion API.">To use instruct formatting, switch to OpenRouter under Text Completion API.</span> |
| 3185 | 3199 | </small> |
| 3200 | + <div> | |
| 3201 | + <h4 data-i18n="Model Quantizations">Model Quantizations</h4> | |
| 3202 | + <select id="openrouter_quantizations_chat" class="openrouter_quantizations" multiple> | |
| 3203 | + <option data-i18n="Integer (4 bit)" value="int4">Integer (4 bit)</option> | |
| 3204 | + <option data-i18n="Integer (8 bit)" value="int8">Integer (8 bit)</option> | |
| 3205 | + <option data-i18n="Floating point (4 bit)" value="fp4">Floating point (4 bit)</option> | |
| 3206 | + <option data-i18n="Floating point (6 bit)" value="fp6">Floating point (6 bit)</option> | |
| 3207 | + <option data-i18n="Floating point (8 bit)" value="fp8">Floating point (8 bit)</option> | |
| 3208 | + <option data-i18n="Floating point (16 bit)" value="fp16">Floating point (16 bit)</option> | |
| 3209 | + <option data-i18n="Brain floating point (16 bit)" value="bf16">Brain floating point (16 bit)</option> | |
| 3210 | + <option data-i18n="Floating point (32 bit)" value="fp32">Floating point (32 bit)</option> | |
| 3211 | + <option data-i18n="Unknown" value="unknown">Unknown</option> | |
| 3212 | + </select> | |
| 3213 | + </div> | |
| 3186 | 3214 | </form> |
| 3187 | 3215 | <form id="ai21_form" data-source="ai21" action="javascript:void(null);" method="post" enctype="multipart/form-data"> |
| 3188 | 3216 | <h4 data-i18n="AI21 API Key">AI21 API Key</h4> |
| @@ -290,6 +290,8 @@ | ||
| 290 | 290 | "View Remaining Credits": "Afficher les crédits restants", |
| 291 | 291 | "OpenRouter Model": "Modèle OpenRouter", |
| 292 | 292 | "Model Providers": "Fournisseurs de modèles", |
| 293 | + "Model Quantizations": "Quantifications du modèle", | |
| 294 | + "Select quantizations. No selection = all quantizations.": "Sélectionnez les quantifications. Aucune sélection = toutes les quantifications.", | |
| 293 | 295 | "InfermaticAI API Key": "Clé API InfermaticAI", |
| 294 | 296 | "InfermaticAI Model": "Modèle InfermaticAI", |
| 295 | 297 | "DreamGen API key": "Clé API DreamGen", |
| @@ -288,6 +288,7 @@ export const settingsToUpdate = { | ||
| 288 | 288 | openrouter_group_models: ['#openrouter_group_models', 'openrouter_group_models', false, true], |
| 289 | 289 | openrouter_sort_models: ['#openrouter_sort_models', 'openrouter_sort_models', false, true], |
| 290 | 290 | openrouter_providers: ['#openrouter_providers_chat', 'openrouter_providers', false, true], |
| 291 | + openrouter_quantizations: ['#openrouter_quantizations_chat', 'openrouter_quantizations', false, true], | |
| 291 | 292 | openrouter_allow_fallbacks: ['#openrouter_allow_fallbacks', 'openrouter_allow_fallbacks', true, true], |
| 292 | 293 | openrouter_middleout: ['#openrouter_middleout', 'openrouter_middleout', false, true], |
| 293 | 294 | ai21_model: ['#model_ai21_select', 'ai21_model', false, true], |
| @@ -434,6 +435,7 @@ const default_settings = { | ||
| 434 | 435 | openrouter_group_models: false, |
| 435 | 436 | openrouter_sort_models: 'alphabetically', |
| 436 | 437 | openrouter_providers: [], |
| 438 | + openrouter_quantizations: [], | |
| 437 | 439 | openrouter_allow_fallbacks: true, |
| 438 | 440 | openrouter_middleout: openrouter_middleout_types.ON, |
| 439 | 441 | reverse_proxy: '', |
| @@ -2628,6 +2630,7 @@ export async function createGenerationParameters(settings, model, type, messages | ||
| 2628 | 2630 | generate_data.top_a = Number(settings.top_a_openai); |
| 2629 | 2631 | generate_data.use_fallback = settings.openrouter_use_fallback; |
| 2630 | 2632 | generate_data.provider = settings.openrouter_providers; |
| 2633 | + generate_data.quantizations = settings.openrouter_quantizations; | |
| 2631 | 2634 | generate_data.allow_fallbacks = settings.openrouter_allow_fallbacks; |
| 2632 | 2635 | generate_data.middleout = settings.openrouter_middleout; |
| 2633 | 2636 | } |
| @@ -4048,6 +4051,7 @@ function loadOpenAISettings(data, settings) { | ||
| 4048 | 4051 | setContinuePostfixControls(); |
| 4049 | 4052 | |
| 4050 | 4053 | $('#openrouter_providers_chat').trigger('change'); |
| 4054 | + $('#openrouter_quantizations_chat').trigger('change'); | |
| 4051 | 4055 | $('#chat_completion_source').trigger('change'); |
| 4052 | 4056 | } |
| 4053 | 4057 | |
| @@ -4676,6 +4680,7 @@ function onSettingsPresetChange() { | ||
| 4676 | 4680 | if (oai_settings.bind_preset_to_connection) { |
| 4677 | 4681 | $('#chat_completion_source').trigger('change'); |
| 4678 | 4682 | $('#openrouter_providers_chat').trigger('change'); |
| 4683 | + $('#openrouter_quantizations_chat').trigger('change'); | |
| 4679 | 4684 | } |
| 4680 | 4685 | |
| 4681 | 4686 | $('#openai_logit_bias_preset').trigger('change'); |
| @@ -6805,6 +6810,19 @@ export function initOpenAI() { | ||
| 6805 | 6810 | saveSettingsDebounced(); |
| 6806 | 6811 | }); |
| 6807 | 6812 | |
| 6813 | + $('#openrouter_quantizations_chat').on('change', function () { | |
| 6814 | + const selectedQuantizations = $(this).val(); | |
| 6815 | + | |
| 6816 | + // Not a multiple select? | |
| 6817 | + if (!Array.isArray(selectedQuantizations)) { | |
| 6818 | + return; | |
| 6819 | + } | |
| 6820 | + | |
| 6821 | + oai_settings.openrouter_quantizations = selectedQuantizations; | |
| 6822 | + | |
| 6823 | + saveSettingsDebounced(); | |
| 6824 | + }); | |
| 6825 | + | |
| 6808 | 6826 | $('#bind_preset_to_connection').on('input', function () { |
| 6809 | 6827 | oai_settings.bind_preset_to_connection = !!$(this).prop('checked'); |
| 6810 | 6828 | saveSettingsDebounced(); |
| @@ -712,6 +712,7 @@ class PresetManager { | ||
| 712 | 712 | 'featherless_model', |
| 713 | 713 | 'max_tokens_second', |
| 714 | 714 | 'openrouter_providers', |
| 715 | + 'openrouter_quantizations', | |
| 715 | 716 | 'openrouter_allow_fallbacks', |
| 716 | 717 | 'tabby_model', |
| 717 | 718 | 'derived', |
| @@ -1065,6 +1065,13 @@ export function initTextGenModels() { | ||
| 1065 | 1065 | width: '100%', |
| 1066 | 1066 | templateResult: getAphroditeModelTemplate, |
| 1067 | 1067 | }); |
| 1068 | + $('.openrouter_quantizations').select2({ | |
| 1069 | + closeOnSelect: false, | |
| 1070 | + placeholder: t`Select quantizations. No selection = all quantizations.`, | |
| 1071 | + searchInputCssClass: 'text_pole', | |
| 1072 | + searchInputPlaceholder: t`Search quantizations...`, | |
| 1073 | + width: '100%', | |
| 1074 | + }); | |
| 1068 | 1075 | providersSelect.select2({ |
| 1069 | 1076 | sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)), |
| 1070 | 1077 | placeholder: t`Select providers. No selection = all providers.`, |
| @@ -211,6 +211,7 @@ export const textgenerationwebui_settings = { | ||
| 211 | 211 | ollama_model: '', |
| 212 | 212 | openrouter_model: 'openrouter/auto', |
| 213 | 213 | openrouter_providers: [], |
| 214 | + openrouter_quantizations: [], | |
| 214 | 215 | vllm_model: '', |
| 215 | 216 | aphrodite_model: '', |
| 216 | 217 | dreamgen_model: 'lucid-v1-extra-large/text', |
| @@ -590,6 +591,7 @@ export async function loadTextGenSettings(data, loadedSettings) { | ||
| 590 | 591 | |
| 591 | 592 | $('#textgen_type').val(textgenerationwebui_settings.type); |
| 592 | 593 | $('#openrouter_providers_text').val(textgenerationwebui_settings.openrouter_providers).trigger('change'); |
| 594 | + $('#openrouter_quantizations_text').val(textgenerationwebui_settings.openrouter_quantizations).trigger('change'); | |
| 593 | 595 | showSamplerControls(textgenerationwebui_settings.type); |
| 594 | 596 | BIAS_CACHE.delete(BIAS_KEY); |
| 595 | 597 | displayLogitBias(textgenerationwebui_settings.logit_bias, BIAS_KEY); |
| @@ -1073,6 +1075,19 @@ export function initTextGenSettings() { | ||
| 1073 | 1075 | saveSettingsDebounced(); |
| 1074 | 1076 | }); |
| 1075 | 1077 | |
| 1078 | + $('#openrouter_quantizations_text').on('change', function () { | |
| 1079 | + const selectedQuantizations = $(this).val(); | |
| 1080 | + | |
| 1081 | + // Not a multiple select? | |
| 1082 | + if (!Array.isArray(selectedQuantizations)) { | |
| 1083 | + return; | |
| 1084 | + } | |
| 1085 | + | |
| 1086 | + textgenerationwebui_settings.openrouter_quantizations = selectedQuantizations; | |
| 1087 | + | |
| 1088 | + saveSettingsDebounced(); | |
| 1089 | + }); | |
| 1090 | + | |
| 1076 | 1091 | $('#api_button_textgenerationwebui').on('click', async function (e) { |
| 1077 | 1092 | const keys = [ |
| 1078 | 1093 | { id: 'api_key_mancer', secret: SECRET_KEYS.MANCER }, |
| @@ -1735,6 +1750,7 @@ export function createTextGenGenerationData(settings, model, finalPrompt = null, | ||
| 1735 | 1750 | |
| 1736 | 1751 | if (settings.type === OPENROUTER) { |
| 1737 | 1752 | params.provider = settings.openrouter_providers; |
| 1753 | + params.quantizations = settings.openrouter_quantizations; | |
| 1738 | 1754 | params.allow_fallbacks = settings.openrouter_allow_fallbacks; |
| 1739 | 1755 | } |
| 1740 | 1756 | |
| @@ -2097,6 +2097,11 @@ router.post('/generate', async function (request, response) { | ||
| 2097 | 2097 | }; |
| 2098 | 2098 | } |
| 2099 | 2099 | |
| 2100 | + if (Array.isArray(request.body.quantizations) && request.body.quantizations.length > 0) { | |
| 2101 | + bodyParams['provider'] ??= {}; | |
| 2102 | + bodyParams['provider']['quantizations'] = request.body.quantizations; | |
| 2103 | + } | |
| 2104 | + | |
| 2100 | 2105 | if (request.body.use_fallback) { |
| 2101 | 2106 | bodyParams['route'] = 'fallback'; |
| 2102 | 2107 | } |
| @@ -367,6 +367,12 @@ router.post('/generate', async function (request, response) { | ||
| 367 | 367 | } else { |
| 368 | 368 | delete request.body.provider; |
| 369 | 369 | } |
| 370 | + | |
| 371 | + if (Array.isArray(request.body.quantizations) && request.body.quantizations.length > 0) { | |
| 372 | + request.body.provider ??= {}; | |
| 373 | + request.body.provider.quantizations = request.body.quantizations; | |
| 374 | + } | |
| 375 | + | |
| 370 | 376 | request.body = _.pickBy(request.body, (_, key) => OPENROUTER_KEYS.includes(key)); |
| 371 | 377 | args.body = JSON.stringify(request.body); |
| 372 | 378 | } |