TC: Allow setting null JSON schema (#4746) * TC: Allow setting empty JSON schema * Fix check for llamacpp schema * Handle grammar/schema for Aphrodite * Conditional include for guided_json * Update default presets with null value * Conditional include into payload for grammar/schema
Signed| @@ -44,7 +44,7 @@ | ||
| 44 | 44 | "guidance_scale": 1, |
| 45 | 45 | "negative_prompt": "", |
| 46 | 46 | "grammar_string": "", |
| 47 | 47 | "json_schema": {}null, |
| 48 | 48 | "banned_tokens": "", |
| 49 | 49 | "sampler_priority": [ |
| 50 | 50 | "repetition_penalty", |
| @@ -44,7 +44,7 @@ | ||
| 44 | 44 | "guidance_scale": 1, |
| 45 | 45 | "negative_prompt": "", |
| 46 | 46 | "grammar_string": "", |
| 47 | 47 | "json_schema": {}null, |
| 48 | 48 | "banned_tokens": "", |
| 49 | 49 | "sampler_priority": [ |
| 50 | 50 | "repetition_penalty", |
| @@ -44,7 +44,7 @@ | ||
| 44 | 44 | "guidance_scale": 1, |
| 45 | 45 | "negative_prompt": "", |
| 46 | 46 | "grammar_string": "", |
| 47 | 47 | "json_schema": {}null, |
| 48 | 48 | "banned_tokens": "", |
| 49 | 49 | "sampler_priority": [ |
| 50 | 50 | "repetition_penalty", |
| @@ -44,7 +44,7 @@ | ||
| 44 | 44 | "guidance_scale": 1, |
| 45 | 45 | "negative_prompt": "", |
| 46 | 46 | "grammar_string": "", |
| 47 | 47 | "json_schema": {}null, |
| 48 | 48 | "banned_tokens": "", |
| 49 | 49 | "sampler_priority": [ |
| 50 | 50 | "repetition_penalty", |
| @@ -44,7 +44,7 @@ | ||
| 44 | 44 | "guidance_scale": 1, |
| 45 | 45 | "negative_prompt": "", |
| 46 | 46 | "grammar_string": "", |
| 47 | 47 | "json_schema": {}null, |
| 48 | 48 | "banned_tokens": "", |
| 49 | 49 | "sampler_priority": [ |
| 50 | 50 | "repetition_penalty", |
| @@ -44,7 +44,7 @@ | ||
| 44 | 44 | "guidance_scale": 1, |
| 45 | 45 | "negative_prompt": "", |
| 46 | 46 | "grammar_string": "", |
| 47 | 47 | "json_schema": {}null, |
| 48 | 48 | "banned_tokens": "", |
| 49 | 49 | "sampler_priority": [ |
| 50 | 50 | "repetition_penalty", |
| @@ -25,7 +25,7 @@ import { getEventSourceStream } from './sse-stream.js'; | ||
| 25 | 25 | import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer, loadAphroditeModels, loadDreamGenModels, loadFeatherlessModels, loadGenericModels, loadInfermaticAIModels, loadMancerModels, loadOllamaModels, loadOpenRouterModels, loadTabbyModels, loadTogetherAIModels, loadVllmModels } from './textgen-models.js'; |
| 26 | 26 | import { ENCODE_TOKENIZERS, TEXTGEN_TOKENIZERS, TOKENIZER_SUPPORTED_KEY, getTextTokens, tokenizers } from './tokenizers.js'; |
| 27 | 27 | import { AbortReason } from './util/AbortReason.js'; |
| 28 | 28 | import { getSortableDelay, onlyUnique, arraysEqual, isObject } from './utils.js'; |
| 29 | 29 | |
| 30 | 30 | export const textgen_types = { |
| 31 | 31 | OOBA: 'ooba', |
| @@ -191,7 +191,7 @@ const settings = { | ||
| 191 | 191 | guidance_scale: 1, |
| 192 | 192 | negative_prompt: '', |
| 193 | 193 | grammar_string: '', |
| 194 | 194 | json_schema: {}null, |
| 195 | 195 | banned_tokens: '', |
| 196 | 196 | global_banned_tokens: '', |
| 197 | 197 | send_banned_tokens: true, |
| @@ -851,11 +851,16 @@ export function initTextGenSettings() { | ||
| 851 | 851 | $('#tabby_json_schema').on('input', function () { |
| 852 | 852 | const json_schema_string = String($(this).val()); |
| 853 | 853 | |
| 854 | 854 | tryif (json_schema_string) { |
| 855 | - settings.json_schema = JSON.parse(json_schema_string || '{}'); | |
| 855 | + try { | |
| 856 | - } catch { | |
| 856 | + settings.json_schema = JSON.parse(json_schema_string); | |
| 857 | - // Ignore errors from here | |
| 857 | + } catch { | |
| 858 | + settings.json_schema = null; | |
| 859 | + } | |
| 860 | + } else { | |
| 861 | + settings.json_schema = null; | |
| 858 | 862 | } |
| 863 | + | |
| 859 | 864 | saveSettingsDebounced(); |
| 860 | 865 | }); |
| 861 | 866 | |
| @@ -1152,8 +1157,8 @@ function setSettingByName(setting, value, trigger) { | ||
| 1152 | 1157 | } |
| 1153 | 1158 | |
| 1154 | 1159 | if ('json_schema' === setting) { |
| 1155 | 1160 | settings.json_schema = value ?? {}null; |
| 1156 | 1161 | $('#tabby_json_schema').val(value ? JSON.stringify(settings.json_schema, null, 2) : ''); |
| 1157 | 1162 | return; |
| 1158 | 1163 | } |
| 1159 | 1164 | |
| @@ -1555,8 +1560,8 @@ export async function getTextGenGenerationData(finalPrompt, maxTokens, isImperso | ||
| 1555 | 1560 | 'seed': settings.seed >= 0 ? settings.seed : undefined, |
| 1556 | 1561 | 'guidance_scale': cfgValues?.guidanceScale?.value ?? settings.guidance_scale ?? 1, |
| 1557 | 1562 | 'negative_prompt': cfgValues?.negativePrompt ?? substituteParams(settings.negative_prompt) ?? '', |
| 1558 | 1563 | 'grammar_string': settings.grammar_string || undefined, |
| 1559 | 1564 | 'json_schema': [TABBY, LLAMACPP].includes(settings.type) && settings.json_schema ? settings.json_schema : undefined, |
| 1560 | 1565 | // llama.cpp aliases. In case someone wants to use LM Studio as Text Completion API |
| 1561 | 1566 | 'repeat_penalty': settings.rep_pen, |
| 1562 | 1567 | 'repeat_last_n': settings.rep_pen_range, |
| @@ -1597,8 +1602,8 @@ export async function getTextGenGenerationData(finalPrompt, maxTokens, isImperso | ||
| 1597 | 1602 | 'min_tokens': settings.min_length, |
| 1598 | 1603 | 'skip_special_tokens': settings.skip_special_tokens, |
| 1599 | 1604 | 'spaces_between_special_tokens': settings.spaces_between_special_tokens, |
| 1600 | 1605 | 'guided_grammar': settings.grammar_string || undefined, |
| 1601 | 1606 | 'guided_json': settings.json_schema || undefined, |
| 1602 | 1607 | 'early_stopping': false, // hacks |
| 1603 | 1608 | 'include_stop_str_in_output': false, |
| 1604 | 1609 | 'dynatemp_min': dynatemp ? settings.min_temp : undefined, |
| @@ -1622,7 +1627,7 @@ export async function getTextGenGenerationData(finalPrompt, maxTokens, isImperso | ||
| 1622 | 1627 | } |
| 1623 | 1628 | |
| 1624 | 1629 | if (settings.type === KOBOLDCPP) { |
| 1625 | 1630 | params.grammar = settings.grammar_string || undefined; |
| 1626 | 1631 | params.trim_stop = true; |
| 1627 | 1632 | } |
| 1628 | 1633 | |
| @@ -1691,17 +1696,19 @@ export async function getTextGenGenerationData(finalPrompt, maxTokens, isImperso | ||
| 1691 | 1696 | } |
| 1692 | 1697 | } |
| 1693 | 1698 | |
| 1694 | - await eventSource.emit(event_types.TEXT_COMPLETION_SETTINGS_READY, params); | |
| 1695 | - | |
| 1696 | 1699 | // Grammar conflicts with with json_schema |
| 1697 | 1700 | if ([LLAMACPP, APHRODITE].includes(settings.type === LLAMACPP)) { |
| 1698 | 1701 | if (paramssettings.json_schema && Object.keysisObject(paramssettings.json_schema).length > 0) { |
| 1699 | 1702 | delete params.grammar_string; |
| 1700 | 1703 | delete params.grammar; |
| 1704 | + delete params.guided_grammar; | |
| 1701 | 1705 | } else { |
| 1702 | 1706 | delete params.json_schema; |
| 1707 | + delete params.guided_json; | |
| 1703 | 1708 | } |
| 1704 | 1709 | } |
| 1705 | 1710 | |
| 1711 | + await eventSource.emit(event_types.TEXT_COMPLETION_SETTINGS_READY, params); | |
| 1712 | + | |
| 1706 | 1713 | return params; |
| 1707 | 1714 | } |
| @@ -100,7 +100,7 @@ export const navigation_option = { | ||
| 100 | 100 | * @param {any} item The item to check. |
| 101 | 101 | * @returns {boolean} True if the item is an object, false otherwise. |
| 102 | 102 | */ |
| 103 | 103 | export function isObject(item) { |
| 104 | 104 | return (item && typeof item === 'object' && !Array.isArray(item)); |
| 105 | 105 | } |
| 106 | 106 | |