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

5837f2859977fcdf544f6ed69f67e6c13dc02b99

Cohee <18619528+Cohee1207@users.noreply.github.com>

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