Merge branch 'staging' into wi-processing-refactoring

34d6cdfbccd812f46f680f1694b65acb827ca9f0

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

13 files changed, +118 -22Ignore whitespace
default/config.yaml+5 -0
@@ -95,3 +95,8 @@ deepl:
9595 formality: default
9696# -- SERVER PLUGIN CONFIGURATION --
9797enableServerPlugins: false
98+# User session timeout *in seconds* (defaults to 24 hours).
99+## Set to a positive number to expire session after a certain time of inactivity
100+## Set to 0 to expire session when the browser is closed
101+## Set to a negative number to disable session expiration
102+sessionTimeout: 86400
default/content/index.json+8 -0
@@ -678,5 +678,13 @@
678678 {
679679 "filename": "presets/context/ChatML-Names.json",
680680 "type": "context"
681+ },
682+ {
683+ "filename": "presets/context/Gemma 2.json",
684+ "type": "context"
685+ },
686+ {
687+ "filename": "presets/instruct/Gemma 2.json",
688+ "type": "instruct"
681689 }
682690]
default/content/presets/context/Gemma 2.json+12 -0
@@ -0,0 +1,12 @@
1+{
2+ "story_string": "<start_of_turn>user\n{{#if system}}{{system}}\n{{/if}}{{#if wiBefore}}{{wiBefore}}\n{{/if}}{{#if description}}{{description}}\n{{/if}}{{#if personality}}{{char}}'s personality: {{personality}}\n{{/if}}{{#if scenario}}Scenario: {{scenario}}\n{{/if}}{{#if wiAfter}}{{wiAfter}}\n{{/if}}{{#if persona}}{{persona}}\n{{/if}}{{trim}}<end_of_turn>",
3+ "example_separator": "",
4+ "chat_start": "",
5+ "use_stop_strings": false,
6+ "allow_jailbreak": false,
7+ "always_force_name2": true,
8+ "trim_sentences": false,
9+ "include_newline": false,
10+ "single_line": false,
11+ "name": "Gemma 2"
12+}
12 \ No newline at end of file
default/content/presets/instruct/Gemma 2.json+24 -0
@@ -0,0 +1,24 @@
1+{
2+ "system_prompt": "Continue writing this story and portray characters realistically.",
3+ "input_sequence": "<start_of_turn>user",
4+ "output_sequence": "<start_of_turn>model",
5+ "last_output_sequence": "",
6+ "system_sequence": "<start_of_turn>system",
7+ "stop_sequence": "<end_of_turn>",
8+ "wrap": true,
9+ "macro": true,
10+ "names": false,
11+ "names_force_groups": false,
12+ "activation_regex": "",
13+ "system_sequence_prefix": "",
14+ "system_sequence_suffix": "",
15+ "first_output_sequence": "",
16+ "skip_examples": false,
17+ "output_suffix": "<end_of_turn>\n",
18+ "input_suffix": "<end_of_turn>\n",
19+ "system_suffix": "<end_of_turn>\n",
20+ "user_alignment_message": "",
21+ "system_same_as_user": true,
22+ "last_system_sequence": "",
23+ "name": "Gemma 2"
24+}
default/content/settings.json+1 -0
@@ -13,6 +13,7 @@
1313 },
1414 "world_info_depth": 2,
1515 "world_info_budget": 25,
16+ "world_info_include_names": true,
1617 "world_info_recursive": true,
1718 "world_info_overflow_alert": false,
1819 "world_info_case_sensitive": false,
public/index.html+6 -0
@@ -3542,6 +3542,12 @@
35423542 </div>
35433543 </div>
35443544 <div id="wiCheckboxes" class="flex1 flex-container flexFlowColumn">
3545+ <label title="Include names with each message into the context for scanning" data-i18n="[title]Include names with each message into the context for scanning" class="checkbox_label flex1">
3546+ <input id="world_info_include_names" type="checkbox" />
3547+ <small data-i18n="Include Names" class="whitespacenowrap flex1">
3548+ Include Names
3549+ </small>
3550+ </label>
35453551 <label title="Entries can activate other entries by mentioning their keywords" data-i18n="[title]Entries can activate other entries by mentioning their keywords" class="checkbox_label flex1">
35463552 <input id="world_info_recursive" type="checkbox" />
35473553 <small data-i18n="Recursive Scan" class="whitespacenowrap flex1">
public/locales/ja-jp.json+11 -11
@@ -501,7 +501,7 @@
501501 "Active World(s) for all chats": "すべてのチャットのアクティブなワールド",
502502 "-- World Info not found --": "-- ワールド情報が見つかりません --",
503503 "Global World Info/Lorebook activation settings": "グローバルワールド情報/Lorebookの有効化設定",
504504 "Click to expand": "クリックして拡大クリックして展開",
505505 "Scan Depth": "スキャンの深さ",
506506 "Context %": "コンテキスト%",
507507 "Budget Cap": "予算キャップ",
@@ -965,13 +965,13 @@
965965 "After EM": "↓EM",
966966 "Before AN": "著者のメモの前",
967967 "After AN": "著者のメモの後",
968968 "at Depth System": "笑笑笑笑指定深度(システム)",
969969 "at Depth User": "👤 こんばんは指定深度(ユーザー)",
970970 "at Depth AI": "🤖 だめだ指定深度(AI)",
971971 "Depth": "深さ",
972972 "Order:": "順序:",
973973 "Order": "順序:",
974974 "Trigger %:": "引き金発生 %:",
975975 "Probability": "確率",
976976 "Duplicate world info entry": "重複したワールド情報エントリ",
977977 "Delete world info entry": "世界情報エントリを削除",
@@ -981,10 +981,10 @@
981981 "Comma separated list": "カンマ区切りリスト",
982982 "Switch to plaintext mode": "プレーンテキストモードに切り替える",
983983 "Logic": "論理",
984984 "AND ANY": "任意のANDAND ANY",
985985 "AND ALL": "すべてのANDAND ALL",
986986 "NOT ALL": "すべてのNOTNOT ALL",
987987 "NOT ANY": "どれかのNOTNOT ANY",
988988 "(ignored if empty)": "(空の場合は無視されます)",
989989 "Optional Filter": "オプションフィルタ",
990990 "Keywords or Regexes (ignored if empty)": "キーワードまたは正規表現(空の場合は無視されます)",
@@ -1004,7 +1004,7 @@
10041004 "Filter to Character(s)": "キャラクターにフィルター",
10051005 "Character Exclusion": "キャラクターの除外",
10061006 "-- Characters not found --": "-- キャラクターが見つかりません --",
10071007 "Inclusion Group": "含蓋グループ包含グループ",
10081008 "Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.Documentation: World Info - Inclusion Group": "包含グループにより、複数のエントリがトリガーされた場合、一度に 1 つのグループから 1 つのエントリのみがアクティブ化されます。カンマで区切られた複数のグループをサポートします。ドキュメント: World Info - 包含グループ",
10091009 "Prioritize this entry: When checked, this entry is prioritized out of all selections.If multiple are prioritized, the one with the highest 'Order' is chosen.": "このエントリを優先する: チェックすると、このエントリがすべての選択項目の中で優先されます。複数のエントリを優先する場合は、「順序」が最も高いエントリが選択されます。",
10101010 "Only one entry with the same label will be activated": "同じラベルのエントリが1つだけ有効になります",
@@ -1014,7 +1014,7 @@
10141014 "Use Probability": "確率を使用",
10151015 "Add Memo": "メモを追加",
10161016 "Text or token ids": "テキストまたは[トークンID]",
10171017 "close": "近い閉じる",
10181018 "prompt_manager_edit": "編集",
10191019 "prompt_manager_name": "名前",
10201020 "A name for this prompt.": "このプロンプトの名前。",
public/script.js+2 -1
@@ -35,6 +35,7 @@ import {
3535 setWorldInfoButtonClass,
3636 importWorldInfo,
3737 wi_anchor_position,
38+ world_info_include_names,
3839} from './scripts/world-info.js';
3940
4041import {
@@ -3500,7 +3501,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
35003501 // Add WI to prompt (and also inject WI to AN value via hijack)
35013502 // Make quiet prompt available for WIAN
35023503 setExtensionPrompt('QUIET_PROMPT', quiet_prompt || '', extension_prompt_types.IN_PROMPT, 0, true);
35033504 const chatForWI = coreChat.map(x => world_info_include_names ? `${x.name}: ${x.mes}` : x.mes).reverse();
35043505 const { worldInfoString, worldInfoBefore, worldInfoAfter, worldInfoExamples, worldInfoDepth } = await getWorldInfoPrompt(chatForWI, this_max_context, dryRun);
35053506 setExtensionPrompt('QUIET_PROMPT', '', extension_prompt_types.IN_PROMPT, 0, true);
35063507
public/scripts/extensions/stable-diffusion/index.js+8 -3
@@ -30,7 +30,7 @@ import { SlashCommand } from '../../slash-commands/SlashCommand.js';
3030import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
3131import { debounce_timeout } from '../../constants.js';
3232import { SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js';
3333import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js';
3434export { MODULE_NAME };
3535
3636const MODULE_NAME = 'sd';
@@ -3150,7 +3150,12 @@ async function onComfyOpenWorkflowEditorClick() {
31503150 }),
31513151 })).json();
31523152 const editorHtml = $(await $.get('scripts/extensions/stable-diffusion/comfyWorkflowEditor.html'));
3153- const popupResult = callGenericPopup(editorHtml, POPUP_TYPE.CONFIRM, '', { okButton: 'Save', cancelButton: 'Cancel', wide: true, large: true });
3153+ const saveValue = (/** @type {Popup} */ _popup) => {
3154+ workflow = $('#sd_comfy_workflow_editor_workflow').val().toString();
3155+ return true;
3156+ };
3157+ const popup = new Popup(editorHtml, POPUP_TYPE.CONFIRM, '', { okButton: 'Save', cancelButton: 'Cancel', wide: true, large: true, onClosing: saveValue });
3158+ const popupResult = popup.show();
31543159 const checkPlaceholders = () => {
31553160 workflow = $('#sd_comfy_workflow_editor_workflow').val().toString();
31563161 $('.sd_comfy_workflow_editor_placeholder_list > li[data-placeholder]').each(function (idx) {
@@ -3219,7 +3224,7 @@ async function onComfyOpenWorkflowEditorClick() {
32193224 headers: getRequestHeaders(),
32203225 body: JSON.stringify({
32213226 file_name: extension_settings.sd.comfy_workflow,
3222- workflow: $('#sd_comfy_workflow_editor_workflow').val().toString(),
3227+ workflow: workflow,
32233228 }),
32243229 });
32253230 if (!response.ok) {
public/scripts/tokenizers.js+3 -2
@@ -7,7 +7,7 @@ import { kai_flags } from './kai-settings.js';
77import { textgen_types, textgenerationwebui_settings as textgen_settings, getTextGenServer, getTextGenModel } from './textgen-settings.js';
88import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer, openRouterModels } from './textgen-models.js';
99
1010const { OOBA, TABBY, KOBOLDCPP, VLLM, APHRODITE, LLAMACPP, OPENROUTER, DREAMGEN } = textgen_types;
1111
1212export const CHARACTERS_PER_TOKEN_RATIO = 3.35;
1313const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown';
@@ -39,7 +39,7 @@ export const SENTENCEPIECE_TOKENIZERS = [
3939 //tokenizers.NERD2,
4040];
4141
4242export const TEXTGEN_TOKENIZERS = [OOBA, TABBY, KOBOLDCPP, LLAMACPP, VLLM, APHRODITE];
4343
4444const TOKENIZER_URLS = {
4545 [tokenizers.GPT2]: {
@@ -769,6 +769,7 @@ function getTextgenAPITokenizationParams(str) {
769769 api_type: textgen_settings.type,
770770 url: getTextGenServer(),
771771 legacy_api: textgen_settings.legacy_api && (textgen_settings.type === OOBA || textgen_settings.type === APHRODITE),
772+ vllm_model: textgen_settings.vllm_model,
772773 };
773774}
774775
public/scripts/world-info.js+13 -2
@@ -24,6 +24,7 @@ export {
2424 world_info_depth,
2525 world_info_min_activations,
2626 world_info_min_activations_depth_max,
27+ world_info_include_names,
2728 world_info_recursive,
2829 world_info_overflow_alert,
2930 world_info_case_sensitive,
@@ -83,6 +84,7 @@ let world_info_min_activations = 0; // if > 0, will continue seeking chat until
8384let world_info_min_activations_depth_max = 0; // used when (world_info_min_activations > 0)
8485
8586let world_info_budget = 25;
87+let world_info_include_names = true;
8688let world_info_recursive = false;
8789let world_info_overflow_alert = false;
8890let world_info_case_sensitive = false;
@@ -718,6 +720,7 @@ export function getWorldInfoSettings() {
718720 world_info_min_activations,
719721 world_info_min_activations_depth_max,
720722 world_info_budget,
723+ world_info_include_names,
721724 world_info_recursive,
722725 world_info_overflow_alert,
723726 world_info_case_sensitive,
@@ -747,7 +750,7 @@ const worldInfoCache = new Map();
747750
748751/**
749752 * Gets the world info based on chat messages.
750753 * @param {string[]} chat The chat messages to scan, in reverse order.
751754 * @param {number} maxContext The maximum context size of the generation.
752755 * @param {boolean} isDryRun If true, the function will not emit any events.
753756 * @typedef {{worldInfoString: string, worldInfoBefore: string, worldInfoAfter: string, worldInfoExamples: any[], worldInfoDepth: any[]}} WIPromptResult
@@ -784,6 +787,8 @@ function setWorldInfoSettings(settings, data) {
784787 world_info_min_activations_depth_max = Number(settings.world_info_min_activations_depth_max);
785788 if (settings.world_info_budget !== undefined)
786789 world_info_budget = Number(settings.world_info_budget);
790+ if (settings.world_info_include_names !== undefined)
791+ world_info_include_names = Boolean(settings.world_info_include_names);
787792 if (settings.world_info_recursive !== undefined)
788793 world_info_recursive = Boolean(settings.world_info_recursive);
789794 if (settings.world_info_overflow_alert !== undefined)
@@ -833,6 +838,7 @@ function setWorldInfoSettings(settings, data) {
833838 $('#world_info_budget_counter').val(world_info_budget);
834839 $('#world_info_budget').val(world_info_budget);
835840
841+ $('#world_info_include_names').prop('checked', world_info_include_names);
836842 $('#world_info_recursive').prop('checked', world_info_recursive);
837843 $('#world_info_overflow_alert').prop('checked', world_info_overflow_alert);
838844 $('#world_info_case_sensitive').prop('checked', world_info_case_sensitive);
@@ -3542,7 +3548,7 @@ export async function getSortedEntries() {
35423548
35433549/**
35443550 * Performs a scan on the chat and returns the world info activated.
35453551 * @param {string[]} chat The chat messages to scan, in reverse order.
35463552 * @param {number} maxContext The maximum context size of the generation.
35473553 * @param {boolean} isDryRun Whether to perform a dry run.
35483554 * @typedef {{ worldInfoBefore: string, worldInfoAfter: string, EMEntries: any[], WIDepthEntries: any[], allActivatedEntries: Set<any> }} WIActivated
@@ -4637,6 +4643,11 @@ jQuery(() => {
46374643 saveSettings();
46384644 });
46394645
4646+ $('#world_info_include_names').on('input', function () {
4647+ world_info_include_names = !!$(this).prop('checked');
4648+ saveSettings();
4649+ });
4650+
46404651 $('#world_info_recursive').on('input', function () {
46414652 world_info_recursive = !!$(this).prop('checked');
46424653 saveSettings();
server.js+20 -1
@@ -200,11 +200,30 @@ if (enableCorsProxy) {
200200 });
201201}
202202
203+function getSessionCookieAge() {
204+ // Defaults to 24 hours in seconds if not set
205+ const configValue = getConfigValue('sessionTimeout', 24 * 60 * 60);
206+
207+ // Convert to milliseconds
208+ if (configValue > 0) {
209+ return configValue * 1000;
210+ }
211+
212+ // "No expiration" is just 400 days as per RFC 6265
213+ if (configValue < 0) {
214+ return 400 * 24 * 60 * 60 * 1000;
215+ }
216+
217+ // 0 means session cookie is deleted when the browser session ends
218+ // (depends on the implementation of the browser)
219+ return undefined;
220+}
221+
203222app.use(cookieSession({
204223 name: userModule.getCookieSessionName(),
205224 sameSite: 'strict',
206225 httpOnly: true,
207- maxAge: 24 * 60 * 60 * 1000, // 24 hours
226+ maxAge: getSessionCookieAge(),
208227 secret: userModule.getCookieSecret(),
209228}));
210229
src/endpoints/tokenizers.js+5 -2
@@ -784,6 +784,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re
784784 const text = String(request.body.text) || '';
785785 const baseUrl = String(request.body.url);
786786 const legacyApi = Boolean(request.body.legacy_api);
787+ const vllmModel = String(request.body.vllm_model) || '';
787788
788789 try {
789790 const args = {
@@ -814,7 +815,9 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re
814815 args.body = JSON.stringify({ 'content': text });
815816 break;
816817 case TEXTGEN_TYPES.VLLM:
817- return response.send({ error: true });
818+ url += '/tokenize';
819+ args.body = JSON.stringify({ 'model': vllmModel, 'prompt': text });
820+ break;
818821 case TEXTGEN_TYPES.APHRODITE:
819822 url += '/v1/tokenize';
820823 args.body = JSON.stringify({ 'prompt': text });
@@ -834,7 +837,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re
834837 }
835838
836839 const data = await result.json();
837840 const count = legacyApi ? data?.results[0]?.tokens : (data?.length ?? data?.count ?? data?.value ?? data?.tokens?.length);
838841 const ids = legacyApi ? [] : (data?.tokens ?? data?.ids ?? []);
839842
840843 return response.send({ count, ids });