mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'dev' of github.com:Cohee1207/SillyTavern into dev
This commit is contained in:
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -30,6 +30,7 @@ Providing the logs from the browser DevTools console (opened by pressing the F12
|
||||
**Desktop (please complete the following information):**
|
||||
- OS/Device: [e.g. Windows 11]
|
||||
- Environment: [cloud, local]
|
||||
- Node.js version (if applicable): [run `node --version` in cmd]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Generation API [e.g. KoboldAI, OpenAI]
|
||||
- Branch [main, dev]
|
||||
|
40
package-lock.json
generated
40
package-lock.json
generated
@@ -1,15 +1,16 @@
|
||||
{
|
||||
"name": "sillytavern",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sillytavern",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.3",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"@zeldafan0225/ai_horde": "^4.0.1",
|
||||
"axios": "^1.3.4",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
@@ -34,6 +35,7 @@
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"uniqolor": "^1.1.0",
|
||||
"webp-converter": "2.3.2",
|
||||
"ws": "^8.13.0",
|
||||
"yargs": "^17.7.1"
|
||||
@@ -417,6 +419,11 @@
|
||||
"regenerator-runtime": "^0.13.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@thunder04/supermap": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@thunder04/supermap/-/supermap-3.0.2.tgz",
|
||||
"integrity": "sha512-SjlUrfe45mwiAgKZHRRhh+oHRwXsjrCg6NI2HJxymTJt+9SwJw422yse/A5lr5WBpTky6qEce+H6Ec1sytm93A=="
|
||||
},
|
||||
"node_modules/@tokenizer/token": {
|
||||
"version": "0.3.0",
|
||||
"license": "MIT"
|
||||
@@ -433,6 +440,16 @@
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@zeldafan0225/ai_horde": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@zeldafan0225/ai_horde/-/ai_horde-4.0.1.tgz",
|
||||
"integrity": "sha512-mf1cknnBYzKCvgH4KAkdVY3J7sLkR2b79W6I9ZEA2aJCyua28bpZzNaCDSHKKyaNj+0wyHViC+L53X32jw9pMg==",
|
||||
"dependencies": {
|
||||
"@thunder04/supermap": "^3.0.2",
|
||||
"centra": "^2.5.0",
|
||||
"esbuild": "^0.12.28"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
"license": "MIT",
|
||||
@@ -620,6 +637,11 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/centra": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/centra/-/centra-2.6.0.tgz",
|
||||
"integrity": "sha512-dgh+YleemrT8u85QL11Z6tYhegAs3MMxsaWAq/oXeAmYJ7VxL3SI9TZtnfaEvNDMAPolj25FXIb3S+HCI4wQaQ=="
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"license": "ISC",
|
||||
@@ -871,6 +893,15 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.12.29",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.29.tgz",
|
||||
"integrity": "sha512-w/XuoBCSwepyiZtIRsKsetiLDUVGPVw1E/R3VTFSecIy8UR7Cq3SOtwKHJMFoVqqVG36aGkzh4e8BvpO1Fdc7g==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"license": "MIT",
|
||||
@@ -1935,6 +1966,11 @@
|
||||
"version": "0.0.6",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/uniqolor": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uniqolor/-/uniqolor-1.1.0.tgz",
|
||||
"integrity": "sha512-j2XyokF24fsj+L5u6fbu4rM3RQc6VWJuAngYM2k0ZdG3yiVxt0smLkps2GmQIYqK8VkELGdM9vFU/HfOkK/zoQ=="
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
|
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"@zeldafan0225/ai_horde": "^4.0.1",
|
||||
"axios": "^1.3.4",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
@@ -25,6 +26,7 @@
|
||||
"png-chunks-extract": "^1.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"uniqolor": "^1.1.0",
|
||||
"webp-converter": "2.3.2",
|
||||
"ws": "^8.13.0",
|
||||
"yargs": "^17.7.1"
|
||||
@@ -40,7 +42,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/Cohee1207/SillyTavern.git"
|
||||
},
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.3",
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
|
15
public/TextGen Settings/LLaMa-Precise.settings
Normal file
15
public/TextGen Settings/LLaMa-Precise.settings
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"temp": 0.7,
|
||||
"top_p": 0.1,
|
||||
"top_k": 40,
|
||||
"typical_p": 1,
|
||||
"rep_pen": 1.18,
|
||||
"no_repeat_ngram_size": 0,
|
||||
"penalty_alpha": 0,
|
||||
"num_beams": 1,
|
||||
"length_penalty": 1,
|
||||
"min_length": 200,
|
||||
"encoder_rep_pen": 1,
|
||||
"do_sample": true,
|
||||
"early_stopping": false
|
||||
}
|
@@ -366,6 +366,15 @@
|
||||
<input id="openai_reverse_proxy" type="text" class="text_pole" placeholder="https://api.openai.com/v1" maxlength="100" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<label for="oai_breakdown" class="checkbox_label widthFreeExpand">
|
||||
<input id="oai_breakdown" type="checkbox" />
|
||||
Token Breakdown
|
||||
</label>
|
||||
<div class="toggle-description justifyLeft">
|
||||
Display a breakdown of the tokens used in the request.
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title">
|
||||
Context Size (tokens)
|
||||
@@ -1176,7 +1185,7 @@
|
||||
|
||||
<div id="advanced-formatting-button" class="drawer">
|
||||
<div class="drawer-toggle">
|
||||
<div class="drawer-icon fa-solid fa-font closedIcon" title="AI Reponse Formatting"></div>
|
||||
<div class="drawer-icon fa-solid fa-font closedIcon" title="AI Response Formatting"></div>
|
||||
</div>
|
||||
<div class="drawer-content">
|
||||
<h3>Advanced Formatting
|
||||
@@ -1207,6 +1216,15 @@
|
||||
<input id="disable-start-formatting-checkbox" type="checkbox" />
|
||||
Disable chat start formatting
|
||||
</label>
|
||||
<label class="checkbox_label" for="trim_sentences_checkbox">
|
||||
<input id="trim_sentences_checkbox" type="checkbox" />
|
||||
Trim Incomplete Sentences
|
||||
</label>
|
||||
<!-- Add margin since this is a child of above -->
|
||||
<label style="margin-left: 1em;" class="checkbox_label" for="include_newline_checkbox">
|
||||
<input id="include_newline_checkbox" type="checkbox" />
|
||||
Include Newline
|
||||
</label>
|
||||
<div>
|
||||
<h4>
|
||||
Custom Chat Separator
|
||||
@@ -1346,24 +1364,22 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="anchors-block">
|
||||
<div id="context-templates-block" style="display:none">
|
||||
<h4>
|
||||
Anchors Order
|
||||
<a href="/notes#anchors" class="notes-link" target="_blank">
|
||||
<span class="note-link-span">?</span>
|
||||
</a>
|
||||
Context Templates
|
||||
</h4>
|
||||
<select id="anchor_order">
|
||||
<option value="0">Character then Style</option>
|
||||
<option value="1">Style then Character</option>
|
||||
</select>
|
||||
<div id="anchor_checkbox">
|
||||
<label for="character_anchor"><input id="character_anchor" type="checkbox" />
|
||||
Character Anchor
|
||||
</label>
|
||||
<label for="style_anchor"><input id="style_anchor" type="checkbox" />
|
||||
Style Anchor
|
||||
</label>
|
||||
<div>
|
||||
<label>Presets:</label>
|
||||
<div class="flex-container flexGap5">
|
||||
<select id="prompt_template" class="flex1 margin0">
|
||||
<option value="None">None</option>
|
||||
<option value="Classic">Classic</option>
|
||||
<option value="Pygmalion">Pygmalion</option>
|
||||
</select>
|
||||
<div id="context_template_edit" class="menu_button fa-solid fa-pencil margin0" title="Edit"></div>
|
||||
<div id="context_template_new" class="menu_button fa-solid fa-plus margin0" title="Add new"></div>
|
||||
<div id="context_template_delete" class="menu_button fa-solid fa-trash-can margin0" title="Delete"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1373,12 +1389,20 @@
|
||||
|
||||
<div id="WI-SP-button" class="drawer">
|
||||
<div class="drawer-toggle drawer-header">
|
||||
<div class="drawer-icon fa-solid fa-book-atlas closedIcon " title="World Info & Soft Prompts"></div>
|
||||
<div id="WIDrawerIcon" class="drawer-icon fa-solid fa-book-atlas closedIcon " title="World Info & Soft Prompts"></div>
|
||||
</div>
|
||||
<div class="drawer-content closedDrawer">
|
||||
<div id="WorldInfo" class="drawer-content closedDrawer">
|
||||
<div id="WorldInfoheader" class="fa-solid fa-grip drag-grabber"></div>
|
||||
<div id="WI_panel_pin_div" title="Locked = World Editor will stay open">
|
||||
<input type="checkbox" id="WI_panel_pin">
|
||||
<label for="WI_panel_pin">
|
||||
<div class="unchecked fa-solid fa-lock-open "></div>
|
||||
<div class="checked fa-solid fa-lock "></div>
|
||||
</label>
|
||||
</div>
|
||||
<div id="wi-holder">
|
||||
<h3>
|
||||
World Info
|
||||
World Selector
|
||||
<a href="/notes#worldinfo" class="notes-link" target="_blank">
|
||||
<span class="note-link-span">?</span>
|
||||
</a>
|
||||
@@ -1440,6 +1464,41 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="world_popup">
|
||||
<hr>
|
||||
<div id="world_popup_text">
|
||||
<!-- <div id="world_cross" class="fa-solid fa-circle-xmark"></div> -->
|
||||
<div id="world_popup_header" class="flex-container flexGap5">
|
||||
<!-- Consider changing logo to something else -->
|
||||
<div class="world_popup_logo_block">
|
||||
<!-- <img src="img/book2.png" id="world_logo"> -->
|
||||
<h3>
|
||||
World Info Editor
|
||||
<a href="/notes#worldinfoentry" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="OpenAllWIEntries" class="menu_button fa-solid fa-expand"></div>
|
||||
<div id="CloseAllWIEntries" class="menu_button fa-solid fa-compress"></div>
|
||||
<!-- <div class="world_popup_expander"> </div> -->
|
||||
<form id="form_rename_world" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
<input id="world_popup_name" name="world_popup_name" class="text_pole" maxlength="99" size="32" value="" autocomplete="off">
|
||||
<input id="world_popup_name_button" class="menu_button" type="submit" value="Rename">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="world_popup_entries_list">
|
||||
</div>
|
||||
|
||||
<div id="world_popup_bottom_holder">
|
||||
<div id="world_popup_new" class="menu_button">New Entry</div>
|
||||
<!-- <span class="world_popup_expander"> </span> -->
|
||||
<div id="world_popup_export" class="menu_button">Export</div>
|
||||
<div id="world_popup_delete" class="menu_button">Delete World</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="softprompt_block">
|
||||
<h4>Soft Prompt</h4>
|
||||
@@ -1663,6 +1722,10 @@
|
||||
<input id="auto_scroll_chat_to_bottom" type="checkbox" />
|
||||
Auto-scroll Chat
|
||||
</label>
|
||||
<label for="console_log_prompts">
|
||||
<input id="console_log_prompts" type="checkbox" />
|
||||
Log prompts to console
|
||||
</label>
|
||||
<label for="render_formulas">
|
||||
<input id="render_formulas" type="checkbox" />
|
||||
Render Formulas
|
||||
@@ -1939,6 +2002,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer wide100p flexFlowColumn">
|
||||
<div id="groupCurrentMemberListToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||
Current Members
|
||||
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div name="Current Group Members" class="flex-container flexFlowColumn overflowYAuto flex1">
|
||||
<div id="rm_group_members" class="overflowYAuto flex-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer wide100p flexFlowColumn">
|
||||
<div id="groupAddMemberListToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||
Add Members
|
||||
@@ -1954,17 +2028,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-drawer wide100p flexFlowColumn">
|
||||
<div id="groupCurrentMemberListToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||
Current Members
|
||||
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div name="Current Group Members" class="flex-container flexFlowColumn overflowYAuto flex1">
|
||||
<div id="rm_group_members" class="overflowYAuto flex-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2036,7 +2099,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 id="character_popup_text_h3"></h3> - Advanced Defininitions
|
||||
<h3 id="character_popup_text_h3"></h3> - Advanced Definitions
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -2061,7 +2124,7 @@
|
||||
|
||||
<div id="talkativeness_div">
|
||||
<h4>Talkativeness</h4>
|
||||
<h5>How often the chracter speaks in <span class="warning">group chats!</span>
|
||||
<h5>How often the character speaks in <span class="warning">group chats!</span>
|
||||
</h5>
|
||||
<input id="talkativeness_slider" name="talkativeness" type="range" min="0" max="1" step="0.05" value="0.5" form="form_create">
|
||||
<div id="talkativeness_hint">
|
||||
@@ -2081,38 +2144,7 @@
|
||||
<div id="character_popup_ok" class="menu_button">Save</div>
|
||||
|
||||
</div>
|
||||
<div id="world_popup">
|
||||
<div id="world_popup_text">
|
||||
<div id="world_cross" class="fa-solid fa-circle-xmark"></div>
|
||||
<div id="world_popup_header">
|
||||
<!-- Consider changing logo to something else -->
|
||||
<div class="world_popup_logo_block">
|
||||
<img src="img/book2.png" id="world_logo">
|
||||
<h3>
|
||||
World Info Editor
|
||||
<a href="/notes#worldinfoentry" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="OpenAllWIEntries" class="menu_button fa-solid fa-expand"></div>
|
||||
<div id="CloseAllWIEntries" class="menu_button fa-solid fa-compress"></div>
|
||||
<div class="world_popup_expander"> </div>
|
||||
<form id="form_rename_world" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
<input id="world_popup_name" name="world_popup_name" class="text_pole" maxlength="99" size="32" value="" autocomplete="off">
|
||||
<input id="world_popup_name_button" class="menu_button" type="submit" value="Rename">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="world_popup_entries_list">
|
||||
</div>
|
||||
|
||||
<div id="world_popup_bottom_holder">
|
||||
<div id="world_popup_new" class="menu_button">New Entry</div>
|
||||
<span class="world_popup_expander"> </span>
|
||||
<div id="world_popup_export" class="menu_button">Export</div>
|
||||
<div id="world_popup_delete" class="menu_button">Delete World</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="shadow_select_chat_popup">
|
||||
<div id="select_chat_popup">
|
||||
<div id="select_chat_import"> <!-- import chat popup header -->
|
||||
@@ -2191,6 +2223,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="entry_edit_template" class="template_element">
|
||||
<div class="world_entry">
|
||||
<form class="world_entry_form">
|
||||
@@ -2200,14 +2233,14 @@
|
||||
<div class="world_entry_form_control">
|
||||
<label for="key">
|
||||
<h4>Keywords</h4>
|
||||
<h5>Separate with commas</h5>
|
||||
<h5>Split by commas</h5>
|
||||
</label>
|
||||
<textarea class="text_pole keyprimarytextpole" name="key" rows="1" placeholder="" maxlength="250"></textarea>
|
||||
</div>
|
||||
<div class="world_entry_form_control keysecondary">
|
||||
<label for="keysecondary">
|
||||
<h4>Secondary Required Keywords</h4>
|
||||
<h5>Separate with commas</h5>
|
||||
<h4>2nd Keywords</h4>
|
||||
<h5>Split by commas</h5>
|
||||
</label>
|
||||
<textarea class="text_pole keysecondarytextpole" name="keysecondary" rows="1" placeholder="(secondary keywords here)" maxlength="250"></textarea>
|
||||
</div>
|
||||
@@ -2341,6 +2374,7 @@
|
||||
<span class="name_text">${characterName}</span>
|
||||
|
||||
<div class="mes_buttons">
|
||||
<div title="Narrate" class="mes_narrate fa-solid fa-bullhorn"></div>
|
||||
<div title="Prompt" class="mes_prompt fa-solid fa-square-poll-horizontal "></div>
|
||||
<div title="Copy" class="mes_copy fa-solid fa-copy "></div>
|
||||
<div title="Edit" class="mes_edit fa-solid fa-pencil "></div>
|
||||
@@ -2436,6 +2470,11 @@
|
||||
<div id="chat">
|
||||
</div>
|
||||
<div id="form_sheld">
|
||||
<div id="token_breakdown" style="display:none;">
|
||||
<div>
|
||||
<!-- Token Breakdown Goes Here -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="dialogue_del_mes">
|
||||
<div id="dialogue_del_mes_ok" class="menu_button">Delete</div>
|
||||
<div id="dialogue_del_mes_cancel" class="menu_button">Cancel</div>
|
||||
@@ -2445,7 +2484,7 @@
|
||||
<textarea id="send_textarea" placeholder="Not connected to API!" name="text"></textarea>
|
||||
<div id="send_but_sheld">
|
||||
<div id="loading_mes">
|
||||
<div alt="" class="fa-solid fa-hourglass-half"></div>
|
||||
<div title="Loading" class="fa-solid fa-hourglass-half"></div>
|
||||
</div>
|
||||
<div id="send_but" class="fa-solid fa-feather-pointed" title="Send a message"></div>
|
||||
</div>
|
||||
@@ -2502,6 +2541,9 @@
|
||||
<div id="avatar_zoom_popupheader" class="fa-solid fa-grip drag-grabber"></div>
|
||||
<img id="zoomed_avatar" src="">
|
||||
</div>
|
||||
<div id="rawPromptPopup" class="list-group">
|
||||
<div id="rawPromptWrapper" class="tokenItemizingSubclass"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@@ -393,26 +393,9 @@ _Lost API keys can't be restored! Make sure to keep it safe!_
|
||||
|
||||
## Anchors
|
||||
|
||||
Anchors are used to increase the length of messages.
|
||||
There are two types of anchors: _Character Anchor_ and _Style Anchor_.
|
||||
This feature is considered obsolete and has been removed.
|
||||
|
||||
_Character Anchor_ - affects the character played by the AI by motivating it to write longer messages.
|
||||
|
||||
Looks like: `[Elaborate speaker]`
|
||||
|
||||
_Style Anchor_ - affects the entire AI model, motivating the AI to write longer messages even when it is not acting as the character.
|
||||
|
||||
Looks like: `[Writing style: very long messages]`
|
||||
|
||||
***
|
||||
|
||||
Anchors Order sets the location of anchors in the prompt, the first anchor in the order is much further back in the context and thus has less influence than second.
|
||||
|
||||
The second anchor is only turned on after 8-12 messages, because when the chat still only has a few messages, the first anchor creates enough effect on its own.
|
||||
|
||||
Sometimes an AI model may not perceive anchors correctly or the AI model already generates sufficiently long messages. For these cases, you can disable the anchors by unchecking their respective boxes.
|
||||
|
||||
_When using Pygmalion models these anchors are automatically disabled, since Pygmalion already generates long enough messages._
|
||||
The use of the Author's Note extension is now a preferred way to add prompt injections of variable depth.
|
||||
|
||||
## Instruct Mode
|
||||
|
||||
@@ -594,6 +577,8 @@ Characters are drafted based on the order they are presented in group members li
|
||||
|
||||
## Multigen
|
||||
|
||||
*This feature provides a pseudo-streaming functionality which conflicts with token streaming. When Multigen is enabled and generation API supports streaming, only Multigen streaming will be used.*
|
||||
|
||||
SillyTavern tries to create faster and longer responses by chaining the generation using smaller batches.
|
||||
|
||||
### Default settings:
|
||||
@@ -614,6 +599,7 @@ Next batches = 30 tokens
|
||||
2. Character starts speaking for You.
|
||||
3. <|endoftext|> token reached.
|
||||
4. No text generated.
|
||||
5. Stop sequence generated. (Instruct mode only)
|
||||
|
||||
## User Settings
|
||||
|
||||
|
809
public/script.js
809
public/script.js
File diff suppressed because it is too large
Load Diff
@@ -30,11 +30,16 @@ import {
|
||||
import { sortByCssOrder } from "./utils.js";
|
||||
|
||||
var NavToggle = document.getElementById("nav-toggle");
|
||||
|
||||
var RPanelPin = document.getElementById("rm_button_panel_pin");
|
||||
var LPanelPin = document.getElementById("lm_button_panel_pin");
|
||||
var SelectedCharacterTab = document.getElementById("rm_button_selected_ch");
|
||||
var WIPanelPin = document.getElementById("WI_panel_pin");
|
||||
|
||||
var RightNavPanel = document.getElementById("right-nav-panel");
|
||||
var LeftNavPanel = document.getElementById("left-nav-panel")
|
||||
var LeftNavPanel = document.getElementById("left-nav-panel");
|
||||
var WorldInfo = document.getElementById("WorldInfo");
|
||||
|
||||
var SelectedCharacterTab = document.getElementById("rm_button_selected_ch");
|
||||
var AdvancedCharDefsPopup = document.getElementById("character_popup");
|
||||
var ConfirmationPopup = document.getElementById("dialogue_popup");
|
||||
var AutoConnectCheckbox = document.getElementById("auto-connect-checkbox");
|
||||
@@ -412,23 +417,18 @@ function OpenNavPanels() {
|
||||
if (LoadLocalBool("NavLockOn") == true && LoadLocalBool("NavOpened") == true) {
|
||||
//console.log("RA -- clicking right nav to open");
|
||||
$("#rightNavDrawerIcon").click();
|
||||
} else {
|
||||
/* console.log('didnt see reason to open right nav on load: R-nav locked? ' +
|
||||
LoadLocalBool("NavLockOn")
|
||||
+ ' R-nav was open before? ' +
|
||||
LoadLocalBool("NavOpened" == true)); */
|
||||
}
|
||||
|
||||
//auto-open L nav if locked and previously open
|
||||
|
||||
if (LoadLocalBool("LNavLockOn") == true && LoadLocalBool("LNavOpened") == true) {
|
||||
console.log("RA -- clicking left nav to open");
|
||||
$("#leftNavDrawerIcon").click();
|
||||
} else {
|
||||
/* console.log('didnt see reason to open left nav on load: L-Nav Locked? ' +
|
||||
LoadLocalBool("LNavLockOn")
|
||||
+ ' L-nav was open before? ' +
|
||||
LoadLocalBool("LNavOpened" == true)); */
|
||||
}
|
||||
|
||||
//auto-open WI if locked and previously open
|
||||
if (LoadLocalBool("WINavLockOn") == true && LoadLocalBool("WINavOpened") == true) {
|
||||
console.log("RA -- clicking WI to open");
|
||||
$("#WIDrawerIcon").click();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +438,7 @@ dragElement(document.getElementById("sheld"));
|
||||
dragElement(document.getElementById("left-nav-panel"));
|
||||
dragElement(document.getElementById("right-nav-panel"));
|
||||
dragElement(document.getElementById("avatar_zoom_popup"));
|
||||
dragElement(document.getElementById("WorldInfo"));
|
||||
|
||||
|
||||
|
||||
@@ -546,6 +547,7 @@ function dragElement(elmnt) {
|
||||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
||||
$(elmnt).css("bottom", "unset");
|
||||
$(elmnt).css("right", "unset");
|
||||
$(elmnt).css("margin", "unset");
|
||||
|
||||
/* console.log(`
|
||||
offsetLeft: ${elmnt.offsetLeft}, offsetTop: ${elmnt.offsetTop}
|
||||
@@ -614,7 +616,7 @@ $("document").ready(function () {
|
||||
|
||||
if ($(RightNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) {
|
||||
$(RightNavPanel).slideToggle(200, "swing");
|
||||
$(rightNavDrawerIcon).toggleClass('openIcon closedIcon');
|
||||
//$(rightNavDrawerIcon).toggleClass('openIcon closedIcon');
|
||||
$(RightNavPanel).toggleClass('openDrawer closedDrawer');
|
||||
}
|
||||
}
|
||||
@@ -630,12 +632,30 @@ $("document").ready(function () {
|
||||
|
||||
if ($(LeftNavPanel).hasClass('openDrawer') && $('.openDrawer').length > 1) {
|
||||
$(LeftNavPanel).slideToggle(200, "swing");
|
||||
$(leftNavDrawerIcon).toggleClass('openIcon closedIcon');
|
||||
//$(leftNavDrawerIcon).toggleClass('openIcon closedIcon');
|
||||
$(LeftNavPanel).toggleClass('openDrawer closedDrawer');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(WIPanelPin).on("click", function () {
|
||||
SaveLocal("WINavLockOn", $(WIPanelPin).prop("checked"));
|
||||
if ($(WIPanelPin).prop("checked") == true) {
|
||||
console.log('adding pin class to WI');
|
||||
$(WorldInfo).addClass('pinnedOpen');
|
||||
} else {
|
||||
console.log('removing pin class from WI');
|
||||
$(WorldInfo).removeClass('pinnedOpen');
|
||||
|
||||
if ($(WorldInfo).hasClass('openDrawer') && $('.openDrawer').length > 1) {
|
||||
console.log('closing WI after lock removal');
|
||||
$(WorldInfo).slideToggle(200, "swing");
|
||||
//$(WorldInfoDrawerIcon).toggleClass('openIcon closedIcon');
|
||||
$(WorldInfo).toggleClass('openDrawer closedDrawer');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// read the state of right Nav Lock and apply to rightnav classlist
|
||||
$(RPanelPin).prop('checked', LoadLocalBool("NavLockOn"));
|
||||
if (LoadLocalBool("NavLockOn") == true) {
|
||||
@@ -657,6 +677,18 @@ $("document").ready(function () {
|
||||
$(LeftNavPanel).addClass('pinnedOpen');
|
||||
}
|
||||
|
||||
// read the state of left Nav Lock and apply to leftnav classlist
|
||||
$(WIPanelPin).prop('checked', LoadLocalBool("WINavLockOn"));
|
||||
if (LoadLocalBool("WINavLockOn") == true) {
|
||||
//console.log('setting pin class via local var');
|
||||
$(WorldInfo).addClass('pinnedOpen');
|
||||
}
|
||||
|
||||
if ($(WIPanelPin).prop('checked' == true)) {
|
||||
console.log('setting pin class via checkbox state');
|
||||
$(WorldInfo).addClass('pinnedOpen');
|
||||
}
|
||||
|
||||
//save state of Right nav being open or closed
|
||||
$("#rightNavDrawerIcon").on("click", function () {
|
||||
if (!$("#rightNavDrawerIcon").hasClass('openIcon')) {
|
||||
@@ -671,6 +703,13 @@ $("document").ready(function () {
|
||||
} else { SaveLocal('LNavOpened', 'false'); }
|
||||
});
|
||||
|
||||
//save state of Left nav being open or closed
|
||||
$("#WorldInfo").on("click", function () {
|
||||
if (!$("#WorldInfo").hasClass('openIcon')) {
|
||||
SaveLocal('WINavOpened', 'true');
|
||||
} else { SaveLocal('WINavOpened', 'false'); }
|
||||
});
|
||||
|
||||
var chatbarInFocus = false;
|
||||
$('#send_textarea').focus(function () {
|
||||
chatbarInFocus = true;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"display_name": "Stable Diffusion",
|
||||
"loading_order": 10,
|
||||
"requires": [
|
||||
"requires": [],
|
||||
"optional": [
|
||||
"sd"
|
||||
],
|
||||
"optional": [],
|
||||
"js": "index.js",
|
||||
"css": "style.css",
|
||||
"author": "Cohee#1207",
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { callPopup, isMultigenEnabled, is_send_press, saveSettingsDebounced } from '../../../script.js'
|
||||
import { callPopup, cancelTtsPlay, isMultigenEnabled, is_send_press, saveSettingsDebounced } from '../../../script.js'
|
||||
import { extension_settings, getContext } from '../../extensions.js'
|
||||
import { getStringHash } from '../../utils.js'
|
||||
import { ElevenLabsTtsProvider } from './elevenlabs.js'
|
||||
@@ -24,9 +24,47 @@ let ttsProviders = {
|
||||
let ttsProvider
|
||||
let ttsProviderName
|
||||
|
||||
async function onNarrateOneMessage() {
|
||||
cancelTtsPlay();
|
||||
const context = getContext();
|
||||
const id = $(this).closest('.mes').attr('mesid');
|
||||
const message = context.chat[id];
|
||||
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentTtsJob = null;
|
||||
audioElement.pause();
|
||||
audioElement.currentTime = 0;
|
||||
ttsJobQueue.splice(0, ttsJobQueue.length);
|
||||
audioJobQueue.splice(0, audioJobQueue.length);
|
||||
ttsJobQueue.push(message);
|
||||
moduleWorker();
|
||||
}
|
||||
|
||||
let isWorkerBusy = false;
|
||||
|
||||
async function moduleWorkerWrapper() {
|
||||
// Don't touch me I'm busy...
|
||||
if (isWorkerBusy) {
|
||||
return;
|
||||
}
|
||||
|
||||
// I'm free. Let's update!
|
||||
try {
|
||||
isWorkerBusy = true;
|
||||
await moduleWorker();
|
||||
}
|
||||
finally {
|
||||
isWorkerBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function moduleWorker() {
|
||||
// Primarily determinign when to add new chat to the TTS queue
|
||||
const enabled = $('#tts_enabled').is(':checked')
|
||||
$('body').toggleClass('tts', enabled);
|
||||
if (!enabled) {
|
||||
return
|
||||
}
|
||||
@@ -296,6 +334,7 @@ function loadSettings() {
|
||||
)
|
||||
$('#tts_narrate_dialogues').prop('checked', extension_settings.tts.narrate_dialogues_only)
|
||||
$('#tts_narrate_quoted').prop('checked', extension_settings.tts.narrate_quoted_only)
|
||||
$('body').toggleClass('tts', extension_settings.tts.enabled);
|
||||
}
|
||||
|
||||
const defaultSettings = {
|
||||
@@ -507,10 +546,11 @@ $(document).ready(function () {
|
||||
$('#tts_provider').append($("<option />").val(provider).text(provider))
|
||||
}
|
||||
$('#tts_provider').on('change', onTtsProviderChange)
|
||||
$(document).on('click', '.mes_narrate', onNarrateOneMessage);
|
||||
}
|
||||
addExtensionControls() // No init dependencies
|
||||
loadSettings() // Depends on Extension Controls and loadTtsProvider
|
||||
loadTtsProvider(extension_settings.tts.currentProvider) // No dependencies
|
||||
addAudioControl() // Depends on Extension Controls
|
||||
setInterval(moduleWorker, UPDATE_INTERVAL) // Init depends on all the things
|
||||
setInterval(moduleWorkerWrapper, UPDATE_INTERVAL) // Init depends on all the things
|
||||
})
|
||||
|
@@ -46,6 +46,7 @@ import {
|
||||
menu_type,
|
||||
select_selected_character,
|
||||
cancelTtsPlay,
|
||||
isMultigenEnabled,
|
||||
} from "../script.js";
|
||||
import { appendTagToList, createTagMapFromList, getTagsList, applyTagsOnCharacterSelect } from './tags.js';
|
||||
|
||||
@@ -426,7 +427,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
let lastMessageText = lastMessage.mes;
|
||||
let activationText = "";
|
||||
let isUserInput = false;
|
||||
let isQuietGenDone = false;
|
||||
let isGenerationDone = false;
|
||||
|
||||
if (userInput && userInput.length && !by_auto_mode) {
|
||||
isUserInput = true;
|
||||
@@ -438,6 +439,23 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
const resolveOriginal = params.resolve;
|
||||
const rejectOriginal = params.reject;
|
||||
|
||||
if (typeof params.resolve === 'function') {
|
||||
params.resolve = function () {
|
||||
isGenerationDone = true;
|
||||
resolveOriginal.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof params.reject === 'function') {
|
||||
params.reject = function () {
|
||||
isGenerationDone = true;
|
||||
rejectOriginal.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
const activationStrategy = Number(group.activation_strategy ?? group_activation_strategy.NATURAL);
|
||||
let activatedMembers = [];
|
||||
|
||||
@@ -450,16 +468,6 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
activatedMembers = activateListOrder(group.members.slice(0, 1));
|
||||
}
|
||||
|
||||
const resolveOriginal = params.resolve;
|
||||
const rejectOriginal = params.reject;
|
||||
params.resolve = function () {
|
||||
isQuietGenDone = true;
|
||||
resolveOriginal.apply(this, arguments);
|
||||
};
|
||||
params.reject = function () {
|
||||
isQuietGenDone = true;
|
||||
rejectOriginal.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
else if (type === "swipe") {
|
||||
activatedMembers = activateSwipe(group.members);
|
||||
@@ -482,13 +490,14 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
|
||||
// now the real generation begins: cycle through every character
|
||||
for (const chId of activatedMembers) {
|
||||
isGenerationDone = false;
|
||||
const generateType = type == "swipe" || type == "impersonate" || type == "quiet" ? type : "group_chat";
|
||||
setCharacterId(chId);
|
||||
setCharacterName(characters[chId].name)
|
||||
|
||||
await Generate(generateType, { automatic_trigger: by_auto_mode, ...(params || {}) });
|
||||
|
||||
if (type !== "swipe" && type !== "impersonate") {
|
||||
if (type !== "swipe" && type !== "impersonate" && !isMultigenEnabled()) {
|
||||
// update indicator and scroll down
|
||||
typingIndicator
|
||||
.find(".typing_indicator_name")
|
||||
@@ -499,9 +508,10 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: This is awful. Refactor this
|
||||
while (true) {
|
||||
// if not swipe - check if message generated already
|
||||
if (type !== "swipe" && chat.length == messagesBefore) {
|
||||
if (type !== "swipe" && !isMultigenEnabled() && chat.length == messagesBefore) {
|
||||
await delay(100);
|
||||
}
|
||||
// if swipe - see if message changed
|
||||
@@ -514,6 +524,13 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (isMultigenEnabled()) {
|
||||
if (isGenerationDone) {
|
||||
break;
|
||||
} else {
|
||||
await delay(100);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (lastMessageText === chat[chat.length - 1].mes) {
|
||||
await delay(100);
|
||||
@@ -532,6 +549,13 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (isMultigenEnabled()) {
|
||||
if (isGenerationDone) {
|
||||
break;
|
||||
} else {
|
||||
await delay(100);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!$("#send_textarea").val() || $("#send_textarea").val() == userInput) {
|
||||
await delay(100);
|
||||
@@ -542,7 +566,15 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
|
||||
}
|
||||
}
|
||||
else if (type === 'quiet') {
|
||||
if (isQuietGenDone) {
|
||||
if (isGenerationDone) {
|
||||
break;
|
||||
} else {
|
||||
await delay(100);
|
||||
}
|
||||
}
|
||||
else if (isMultigenEnabled()) {
|
||||
if (isGenerationDone) {
|
||||
messagesBefore++;
|
||||
break;
|
||||
} else {
|
||||
await delay(100);
|
||||
|
@@ -101,6 +101,7 @@ const default_settings = {
|
||||
openai_model: 'gpt-3.5-turbo',
|
||||
jailbreak_system: false,
|
||||
reverse_proxy: '',
|
||||
oai_breakdown: false,
|
||||
};
|
||||
|
||||
const oai_settings = {
|
||||
@@ -125,6 +126,7 @@ const oai_settings = {
|
||||
openai_model: 'gpt-3.5-turbo',
|
||||
jailbreak_system: false,
|
||||
reverse_proxy: '',
|
||||
oai_breakdown: false,
|
||||
};
|
||||
|
||||
let openai_setting_names;
|
||||
@@ -205,22 +207,10 @@ function setOpenAIMessageExamples(mesExamplesArray) {
|
||||
}
|
||||
}
|
||||
|
||||
function generateOpenAIPromptCache(charPersonality, topAnchorDepth, anchorTop, bottomAnchorThreshold, anchorBottom) {
|
||||
function generateOpenAIPromptCache() {
|
||||
openai_msgs = openai_msgs.reverse();
|
||||
openai_msgs.forEach(function (msg, i, arr) {//For added anchors and others
|
||||
openai_msgs.forEach(function (msg, i, arr) {
|
||||
let item = msg["content"];
|
||||
if (i === openai_msgs.length - topAnchorDepth) {
|
||||
let personalityAndAnchor = [charPersonality, anchorTop].filter(x => x).join(' ');
|
||||
if (personalityAndAnchor) {
|
||||
item = `[${name2} is ${personalityAndAnchor}]\n${item}`;
|
||||
}
|
||||
}
|
||||
if (i === openai_msgs.length - 1 && openai_msgs.length > bottomAnchorThreshold && msg.role === "user") {//For add anchor in end
|
||||
if (anchorBottom) {
|
||||
item = anchorBottom + "\n" + item;
|
||||
}
|
||||
}
|
||||
|
||||
msg["content"] = item;
|
||||
openai_msgs[i] = msg;
|
||||
});
|
||||
@@ -317,16 +307,18 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
let openai_msgs_tosend = [];
|
||||
|
||||
// todo: static value, maybe include in the initial context calculation
|
||||
const handler_instance = new TokenHandler(countTokens);
|
||||
|
||||
let new_chat_msg = { "role": "system", "content": "[Start a new chat]" };
|
||||
let start_chat_count = countTokens([new_chat_msg], true);
|
||||
let start_chat_count = handler_instance.count([new_chat_msg], true, 'start_chat');
|
||||
await delay(1);
|
||||
let total_count = countTokens([prompt_msg], true) + start_chat_count;
|
||||
let total_count = handler_instance.count([prompt_msg], true, 'prompt') + start_chat_count;
|
||||
await delay(1);
|
||||
|
||||
if (bias && bias.trim().length) {
|
||||
let bias_msg = { "role": "system", "content": bias.trim() };
|
||||
openai_msgs.push(bias_msg);
|
||||
total_count += countTokens([bias_msg], true);
|
||||
total_count += handler_instance.count([bias_msg], true, 'bias');
|
||||
await delay(1);
|
||||
}
|
||||
|
||||
@@ -343,13 +335,14 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
openai_msgs.push(group_nudge);
|
||||
|
||||
// add a group nudge count
|
||||
let group_nudge_count = countTokens([group_nudge], true);
|
||||
let group_nudge_count = handler_instance.count([group_nudge], true, 'nudge');
|
||||
await delay(1);
|
||||
total_count += group_nudge_count;
|
||||
|
||||
// recount tokens for new start message
|
||||
total_count -= start_chat_count
|
||||
start_chat_count = countTokens([new_chat_msg], true);
|
||||
handler_instance.uncount(start_chat_count, 'start_chat');
|
||||
start_chat_count = handler_instance.count([new_chat_msg], true);
|
||||
await delay(1);
|
||||
total_count += start_chat_count;
|
||||
}
|
||||
@@ -358,7 +351,7 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
const jailbreakMessage = { "role": "system", "content": substituteParams(oai_settings.jailbreak_prompt) };
|
||||
openai_msgs.push(jailbreakMessage);
|
||||
|
||||
total_count += countTokens([jailbreakMessage], true);
|
||||
total_count += handler_instance.count([jailbreakMessage], true, 'jailbreak');
|
||||
await delay(1);
|
||||
}
|
||||
|
||||
@@ -366,7 +359,7 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
const impersonateMessage = { "role": "system", "content": substituteParams(oai_settings.impersonation_prompt) };
|
||||
openai_msgs.push(impersonateMessage);
|
||||
|
||||
total_count += countTokens([impersonateMessage], true);
|
||||
total_count += handler_instance.count([impersonateMessage], true, 'impersonate');
|
||||
await delay(1);
|
||||
}
|
||||
|
||||
@@ -389,12 +382,12 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
examples_tosend.push(example);
|
||||
}
|
||||
}
|
||||
total_count += countTokens(examples_tosend, true);
|
||||
total_count += handler_instance.count(examples_tosend, true, 'examples');
|
||||
await delay(1);
|
||||
// go from newest message to oldest, because we want to delete the older ones from the context
|
||||
for (let j = openai_msgs.length - 1; j >= 0; j--) {
|
||||
let item = openai_msgs[j];
|
||||
let item_count = countTokens(item, true);
|
||||
let item_count = handler_instance.count(item, true, 'conversation');
|
||||
await delay(1);
|
||||
// If we have enough space for this message, also account for the max assistant reply size
|
||||
if ((total_count + item_count) < (this_max_context - oai_settings.openai_max_tokens)) {
|
||||
@@ -403,13 +396,14 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
}
|
||||
else {
|
||||
// early break since if we still have more messages, they just won't fit anyway
|
||||
handler_instance.uncount(item_count, 'conversation');
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let j = openai_msgs.length - 1; j >= 0; j--) {
|
||||
let item = openai_msgs[j];
|
||||
let item_count = countTokens(item, true);
|
||||
let item_count = handler_instance.count(item, true, 'conversation');
|
||||
await delay(1);
|
||||
// If we have enough space for this message, also account for the max assistant reply size
|
||||
if ((total_count + item_count) < (this_max_context - oai_settings.openai_max_tokens)) {
|
||||
@@ -418,11 +412,12 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
}
|
||||
else {
|
||||
// early break since if we still have more messages, they just won't fit anyway
|
||||
handler_instance.uncount(item_count, 'conversation');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(total_count);
|
||||
//console.log(total_count);
|
||||
|
||||
// each example block contains multiple user/bot messages
|
||||
for (let example_block of openai_msgs_example) {
|
||||
@@ -432,7 +427,7 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
example_block = [new_chat_msg, ...example_block];
|
||||
|
||||
// add the block only if there is enough space for all its messages
|
||||
const example_count = countTokens(example_block, true);
|
||||
const example_count = handler_instance.count(example_block, true, 'examples');
|
||||
await delay(1);
|
||||
if ((total_count + example_count) < (this_max_context - oai_settings.openai_max_tokens)) {
|
||||
examples_tosend.push(...example_block)
|
||||
@@ -440,6 +435,7 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
}
|
||||
else {
|
||||
// early break since more examples probably won't fit anyway
|
||||
handler_instance.uncount(example_count, 'examples');
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -451,10 +447,14 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
openai_msgs_tosend.reverse();
|
||||
openai_msgs_tosend = [prompt_msg, ...examples_tosend, new_chat_msg, ...openai_msgs_tosend]
|
||||
|
||||
console.log("We're sending this:")
|
||||
console.log(openai_msgs_tosend);
|
||||
console.log(`Calculated the total context to be ${total_count} tokens`);
|
||||
return openai_msgs_tosend;
|
||||
//console.log("We're sending this:")
|
||||
//console.log(openai_msgs_tosend);
|
||||
//console.log(`Calculated the total context to be ${total_count} tokens`);
|
||||
handler_instance.log();
|
||||
return [
|
||||
openai_msgs_tosend,
|
||||
oai_settings.oai_breakdown ? handler_instance.counts : false,
|
||||
];
|
||||
}
|
||||
|
||||
function getSystemPrompt(nsfw_toggle_prompt, enhance_definitions_prompt, wiBefore, storyString, wiAfter, extensionPrompt, isImpersonate) {
|
||||
@@ -616,6 +616,39 @@ async function calculateLogitBias() {
|
||||
}
|
||||
}
|
||||
|
||||
class TokenHandler {
|
||||
constructor(countTokenFn) {
|
||||
this.countTokenFn = countTokenFn;
|
||||
this.counts = {
|
||||
'start_chat': 0,
|
||||
'prompt': 0,
|
||||
'bias': 0,
|
||||
'nudge': 0,
|
||||
'jailbreak': 0,
|
||||
'impersonate': 0,
|
||||
'examples': 0,
|
||||
'conversation': 0,
|
||||
};
|
||||
}
|
||||
|
||||
uncount(value, type) {
|
||||
this.counts[type] -= value;
|
||||
}
|
||||
|
||||
count(messages, full, type) {
|
||||
//console.log(messages);
|
||||
const token_count = this.countTokenFn(messages, full);
|
||||
this.counts[type] += token_count;
|
||||
|
||||
return token_count;
|
||||
}
|
||||
|
||||
log() {
|
||||
const total = Object.values(this.counts).reduce((a, b) => a + b);
|
||||
console.table({ ...this.counts, 'total': total });
|
||||
}
|
||||
}
|
||||
|
||||
function countTokens(messages, full = false) {
|
||||
let chatId = 'undefined';
|
||||
|
||||
@@ -705,6 +738,7 @@ function loadOpenAISettings(data, settings) {
|
||||
if (settings.nsfw_first !== undefined) oai_settings.nsfw_first = !!settings.nsfw_first;
|
||||
if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model;
|
||||
if (settings.jailbreak_system !== undefined) oai_settings.jailbreak_system = !!settings.jailbreak_system;
|
||||
if (settings.oai_breakdown !== undefined) oai_settings.oai_breakdown = !!settings.oai_breakdown;
|
||||
|
||||
$('#stream_toggle').prop('checked', oai_settings.stream_openai);
|
||||
|
||||
@@ -720,6 +754,7 @@ function loadOpenAISettings(data, settings) {
|
||||
$('#wrap_in_quotes').prop('checked', oai_settings.wrap_in_quotes);
|
||||
$('#nsfw_first').prop('checked', oai_settings.nsfw_first);
|
||||
$('#jailbreak_system').prop('checked', oai_settings.jailbreak_system);
|
||||
$('#oai_breakdown').prop('checked', oai_settings.oai_breakdown);
|
||||
|
||||
if (settings.main_prompt !== undefined) oai_settings.main_prompt = settings.main_prompt;
|
||||
if (settings.nsfw_prompt !== undefined) oai_settings.nsfw_prompt = settings.nsfw_prompt;
|
||||
@@ -839,6 +874,7 @@ async function saveOpenAIPreset(name, settings) {
|
||||
jailbreak_system: settings.jailbreak_system,
|
||||
impersonation_prompt: settings.impersonation_prompt,
|
||||
bias_preset_selected: settings.bias_preset_selected,
|
||||
oai_breakdown: settings.oai_breakdown,
|
||||
};
|
||||
|
||||
const savePresetSettings = await fetch(`/savepreset_openai?name=${name}`, {
|
||||
@@ -1046,7 +1082,7 @@ async function onDeletePresetClick() {
|
||||
const response = await fetch('/deletepreset_openai', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({name: nameToDelete}),
|
||||
body: JSON.stringify({ name: nameToDelete }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -1097,6 +1133,7 @@ function onSettingsPresetChange() {
|
||||
wrap_in_quotes: ['#wrap_in_quotes', 'wrap_in_quotes', true],
|
||||
nsfw_first: ['#nsfw_first', 'nsfw_first', true],
|
||||
jailbreak_system: ['#jailbreak_system', 'jailbreak_system', true],
|
||||
oai_breakdown: ['#oai_breakdown', 'oai_breakdown', true],
|
||||
main_prompt: ['#main_prompt_textarea', 'main_prompt', false],
|
||||
nsfw_prompt: ['#nsfw_prompt_textarea', 'nsfw_prompt', false],
|
||||
jailbreak_prompt: ['#jailbreak_prompt_textarea', 'jailbreak_prompt', false],
|
||||
@@ -1269,6 +1306,16 @@ $(document).ready(function () {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#oai_breakdown").on('change', function () {
|
||||
oai_settings.oai_breakdown = !!$(this).prop("checked");
|
||||
if (!oai_settings.oai_breakdown) {
|
||||
$("#token_breakdown").css('display', 'none');
|
||||
} else {
|
||||
$("#token_breakdown").css('display', 'flex');
|
||||
}
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// auto-select a preset based on character/group name
|
||||
$(document).on("click", ".character_select", function () {
|
||||
const chid = $(this).attr('chid');
|
||||
@@ -1322,18 +1369,18 @@ $(document).ready(function () {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#api_button_openai").on('click', onConnectButtonClick);
|
||||
$("#openai_reverse_proxy").on('input', onReverseProxyInput);
|
||||
$("#model_openai_select").on('change', onModelChange);
|
||||
$("#settings_perset_openai").on('change', onSettingsPresetChange);
|
||||
$("#new_oai_preset").on('click', onNewPresetClick);
|
||||
$("#delete_oai_preset").on('click', onDeletePresetClick);
|
||||
$("#openai_api_usage").on('click', showApiKeyUsage);
|
||||
$('#openai_logit_bias_preset').on('change', onLogitBiasPresetChange);
|
||||
$('#openai_logit_bias_new_preset').on('click', createNewLogitBiasPreset);
|
||||
$('#openai_logit_bias_new_entry').on('click', createNewLogitBiasEntry);
|
||||
$('#openai_logit_bias_import_file').on('input', onLogitBiasPresetImportFileChange);
|
||||
$('#openai_logit_bias_import_preset').on('click', onLogitBiasPresetImportClick);
|
||||
$('#openai_logit_bias_export_preset').on('click', onLogitBiasPresetExportClick);
|
||||
$('#openai_logit_bias_delete_preset').on('click', onLogitBiasPresetDeleteClick);
|
||||
$("#api_button_openai").on("click", onConnectButtonClick);
|
||||
$("#openai_reverse_proxy").on("input", onReverseProxyInput);
|
||||
$("#model_openai_select").on("change", onModelChange);
|
||||
$("#settings_perset_openai").on("change", onSettingsPresetChange);
|
||||
$("#new_oai_preset").on("click", onNewPresetClick);
|
||||
$("#delete_oai_preset").on("click", onDeletePresetClick);
|
||||
$("#openai_api_usage").on("click", showApiKeyUsage);
|
||||
$("#openai_logit_bias_preset").on("change", onLogitBiasPresetChange);
|
||||
$("#openai_logit_bias_new_preset").on("click", createNewLogitBiasPreset);
|
||||
$("#openai_logit_bias_new_entry").on("click", createNewLogitBiasEntry);
|
||||
$("#openai_logit_bias_import_file").on("input", onLogitBiasPresetImportFileChange);
|
||||
$("#openai_logit_bias_import_preset").on("click", onLogitBiasPresetImportClick);
|
||||
$("#openai_logit_bias_export_preset").on("click", onLogitBiasPresetExportClick);
|
||||
$("#openai_logit_bias_delete_preset").on("click", onLogitBiasPresetDeleteClick);
|
||||
});
|
||||
|
@@ -76,6 +76,8 @@ let power_user = {
|
||||
disable_personality_formatting: false,
|
||||
disable_examples_formatting: false,
|
||||
disable_start_formatting: false,
|
||||
trim_sentences: false,
|
||||
include_newline: false,
|
||||
always_force_name2: false,
|
||||
multigen: false,
|
||||
multigen_first_chunk: 50,
|
||||
@@ -114,6 +116,7 @@ let power_user = {
|
||||
auto_scroll_chat_to_bottom: true,
|
||||
auto_fix_generated_markdown: true,
|
||||
send_on_enter: send_on_enter_options.AUTO,
|
||||
console_log_prompts: false,
|
||||
render_formulas: false,
|
||||
allow_name1_display: false,
|
||||
allow_name2_display: false,
|
||||
@@ -486,6 +489,7 @@ function loadPowerUserSettings(settings, data) {
|
||||
$('#auto_swipe_blacklist').val(power_user.auto_swipe_blacklist.join(", "));
|
||||
$('#auto_swipe_blacklist_threshold').val(power_user.auto_swipe_blacklist_threshold);
|
||||
|
||||
$("#console_log_prompts").prop("checked", power_user.console_log_prompts);
|
||||
$('#auto_fix_generated_markdown').prop("checked", power_user.auto_fix_generated_markdown);
|
||||
$('#auto_scroll_chat_to_bottom').prop("checked", power_user.auto_scroll_chat_to_bottom);
|
||||
$(`#tokenizer option[value="${power_user.tokenizer}"]`).attr('selected', true);
|
||||
@@ -499,6 +503,8 @@ function loadPowerUserSettings(settings, data) {
|
||||
$("#always-force-name2-checkbox").prop("checked", power_user.always_force_name2);
|
||||
$("#disable-examples-formatting-checkbox").prop("checked", power_user.disable_examples_formatting);
|
||||
$('#disable-start-formatting-checkbox').prop("checked", power_user.disable_start_formatting);
|
||||
$("#trim_sentences_checkbox").prop("checked", power_user.trim_sentences);
|
||||
$("#include_newline_checkbox").prop("checked", power_user.include_newline);
|
||||
$('#render_formulas').prop("checked", power_user.render_formulas);
|
||||
$("#custom_chat_separator").val(power_user.custom_chat_separator);
|
||||
$("#fast_ui_mode").prop("checked", power_user.fast_ui_mode);
|
||||
@@ -553,7 +559,7 @@ function loadPowerUserSettings(settings, data) {
|
||||
|
||||
function loadMaxContextUnlocked() {
|
||||
$('#max_context_unlocked').prop('checked', power_user.max_context_unlocked);
|
||||
$('#max_context_unlocked').on('change', function() {
|
||||
$('#max_context_unlocked').on('change', function () {
|
||||
power_user.max_context_unlocked = !!$(this).prop('checked');
|
||||
switchMaxContextSize();
|
||||
saveSettingsDebounced();
|
||||
@@ -779,18 +785,21 @@ function resetMovablePanels() {
|
||||
document.getElementById("sheld").style.right = '';
|
||||
document.getElementById("sheld").style.height = '';
|
||||
document.getElementById("sheld").style.width = '';
|
||||
document.getElementById("sheld").style.margin = '';
|
||||
|
||||
|
||||
document.getElementById("left-nav-panel").style.top = '';
|
||||
document.getElementById("left-nav-panel").style.left = '';
|
||||
document.getElementById("left-nav-panel").style.height = '';
|
||||
document.getElementById("left-nav-panel").style.width = '';
|
||||
document.getElementById("left-nav-panel").style.margin = '';
|
||||
|
||||
document.getElementById("right-nav-panel").style.top = '';
|
||||
document.getElementById("right-nav-panel").style.left = '';
|
||||
document.getElementById("right-nav-panel").style.right = '';
|
||||
document.getElementById("right-nav-panel").style.height = '';
|
||||
document.getElementById("right-nav-panel").style.width = '';
|
||||
document.getElementById("right-nav-panel").style.margin = '';
|
||||
|
||||
document.getElementById("expression-holder").style.top = '';
|
||||
document.getElementById("expression-holder").style.left = '';
|
||||
@@ -798,6 +807,7 @@ function resetMovablePanels() {
|
||||
document.getElementById("expression-holder").style.bottom = '';
|
||||
document.getElementById("expression-holder").style.height = '';
|
||||
document.getElementById("expression-holder").style.width = '';
|
||||
document.getElementById("expression-holder").style.margin = '';
|
||||
|
||||
document.getElementById("avatar_zoom_popup").style.top = '';
|
||||
document.getElementById("avatar_zoom_popup").style.left = '';
|
||||
@@ -805,6 +815,15 @@ function resetMovablePanels() {
|
||||
document.getElementById("avatar_zoom_popup").style.bottom = '';
|
||||
document.getElementById("avatar_zoom_popup").style.height = '';
|
||||
document.getElementById("avatar_zoom_popup").style.width = '';
|
||||
document.getElementById("avatar_zoom_popup").style.margin = '';
|
||||
|
||||
document.getElementById("WorldInfo").style.top = '';
|
||||
document.getElementById("WorldInfo").style.left = '';
|
||||
document.getElementById("WorldInfo").style.right = '';
|
||||
document.getElementById("WorldInfo").style.bottom = '';
|
||||
document.getElementById("WorldInfo").style.height = '';
|
||||
document.getElementById("WorldInfo").style.width = '';
|
||||
document.getElementById("WorldInfo").style.margin = '';
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
@@ -850,6 +869,27 @@ $(document).ready(() => {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
// include newline is the child of trim sentences
|
||||
// if include newline is checked, trim sentences must be checked
|
||||
// if trim sentences is unchecked, include newline must be unchecked
|
||||
$("#trim_sentences_checkbox").change(function() {
|
||||
power_user.trim_sentences = !!$(this).prop("checked");
|
||||
if (!$(this).prop("checked")) {
|
||||
$("#include_newline_checkbox").prop("checked", false);
|
||||
power_user.include_newline = false;
|
||||
}
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#include_newline_checkbox").change(function() {
|
||||
power_user.include_newline = !!$(this).prop("checked");
|
||||
if ($(this).prop("checked")) {
|
||||
$("#trim_sentences_checkbox").prop("checked", true);
|
||||
power_user.trim_sentences = true;
|
||||
}
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#always-force-name2-checkbox").change(function () {
|
||||
power_user.always_force_name2 = !!$(this).prop("checked");
|
||||
saveSettingsDebounced();
|
||||
@@ -1050,6 +1090,11 @@ $(document).ready(() => {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#console_log_prompts").on('input', function () {
|
||||
power_user.console_log_prompts = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#auto_scroll_chat_to_bottom').on("input", function () {
|
||||
power_user.auto_scroll_chat_to_bottom = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
|
303
public/scripts/uniqolor.js
Normal file
303
public/scripts/uniqolor.js
Normal file
@@ -0,0 +1,303 @@
|
||||
const SATURATION_BOUND = [0, 100];
|
||||
const LIGHTNESS_BOUND = [0, 100];
|
||||
|
||||
const pad2 = str => `${str.length === 1 ? '0' : ''}${str}`;
|
||||
|
||||
const clamp = (num, min, max) => Math.max(Math.min(num, max), min);
|
||||
|
||||
const random = (min, max) => Math.floor(Math.random() * ((max - min) + 1)) + min;
|
||||
|
||||
const randomExclude = (min, max, exclude) => {
|
||||
const r = random(min, max);
|
||||
|
||||
for (let i = 0; i < exclude?.length; i++) {
|
||||
const value = exclude[i];
|
||||
|
||||
if (value?.length === 2 && r >= value[0] && r <= value[1]) {
|
||||
return randomExclude(min, max, exclude);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate hashCode
|
||||
* @param {string} str
|
||||
* @return {number}
|
||||
*/
|
||||
const hashCode = str => {
|
||||
const len = str.length;
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
hash = ((hash << 5) - hash) + str.charCodeAt(i);
|
||||
hash &= hash; // Convert to 32bit integer
|
||||
}
|
||||
|
||||
return hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clamps `num` within the inclusive `range` bounds
|
||||
* @param {number} num
|
||||
* @param {number|Array} range
|
||||
* @return {number}
|
||||
*/
|
||||
const boundHashCode = (num, range) => {
|
||||
if (typeof range === 'number') {
|
||||
return range;
|
||||
}
|
||||
|
||||
return (num % Math.abs(range[1] - range[0])) + range[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanitizing the `range`
|
||||
* @param {number|Array} range
|
||||
* @param {Array} bound
|
||||
* @return {number|Array}
|
||||
*/
|
||||
const sanitizeRange = (range, bound) => {
|
||||
if (typeof range === 'number') {
|
||||
return clamp(Math.abs(range), ...bound);
|
||||
}
|
||||
|
||||
if (range.length === 1 || range[0] === range[1]) {
|
||||
return clamp(Math.abs(range[0]), ...bound);
|
||||
}
|
||||
|
||||
return [
|
||||
Math.abs(clamp(range[0], ...bound)),
|
||||
clamp(Math.abs(range[1]), ...bound),
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} p
|
||||
* @param {number} q
|
||||
* @param {number} t
|
||||
* @return {number}
|
||||
*/
|
||||
const hueToRgb = (p, q, t) => {
|
||||
if (t < 0) {
|
||||
t += 1;
|
||||
} else if (t > 1) {
|
||||
t -= 1;
|
||||
}
|
||||
|
||||
if (t < 1 / 6) {
|
||||
return p + ((q - p) * 6 * t);
|
||||
}
|
||||
|
||||
if (t < 1 / 2) {
|
||||
return q;
|
||||
}
|
||||
|
||||
if (t < 2 / 3) {
|
||||
return p + ((q - p) * ((2 / 3) - t) * 6);
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an HSL color to RGB
|
||||
* @param {number} h Hue
|
||||
* @param {number} s Saturation
|
||||
* @param {number} l Lightness
|
||||
* @return {Array}
|
||||
*/
|
||||
const hslToRgb = (h, s, l) => {
|
||||
let r;
|
||||
let g;
|
||||
let b;
|
||||
|
||||
h /= 360;
|
||||
s /= 100;
|
||||
l /= 100;
|
||||
|
||||
if (s === 0) {
|
||||
// achromatic
|
||||
r = g = b = l;
|
||||
} else {
|
||||
const q = l < 0.5
|
||||
? l * (1 + s)
|
||||
: (l + s) - (l * s);
|
||||
const p = (2 * l) - q;
|
||||
|
||||
r = hueToRgb(p, q, h + (1 / 3));
|
||||
g = hueToRgb(p, q, h);
|
||||
b = hueToRgb(p, q, h - (1 / 3));
|
||||
}
|
||||
|
||||
return [
|
||||
Math.round(r * 255),
|
||||
Math.round(g * 255),
|
||||
Math.round(b * 255),
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the RGB color is light or not
|
||||
* http://www.w3.org/TR/AERT#color-contrast
|
||||
* @param {number} r Red
|
||||
* @param {number} g Green
|
||||
* @param {number} b Blue
|
||||
* @param {number} differencePoint
|
||||
* @return {boolean}
|
||||
*/
|
||||
const rgbIsLight = (r, g, b, differencePoint) => ((r * 299) + (g * 587) + (b * 114)) / 1000 >= differencePoint; // eslint-disable-line max-len
|
||||
|
||||
/**
|
||||
* Converts an HSL color to string format
|
||||
* @param {number} h Hue
|
||||
* @param {number} s Saturation
|
||||
* @param {number} l Lightness
|
||||
* @return {string}
|
||||
*/
|
||||
const hslToString = (h, s, l) => `hsl(${h}, ${s}%, ${l}%)`;
|
||||
|
||||
/**
|
||||
* Converts RGB color to string format
|
||||
* @param {number} r Red
|
||||
* @param {number} g Green
|
||||
* @param {number} b Blue
|
||||
* @param {string} format Color format
|
||||
* @return {string}
|
||||
*/
|
||||
const rgbFormat = (r, g, b, format) => {
|
||||
switch (format) {
|
||||
case 'rgb':
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
case 'hex':
|
||||
default:
|
||||
return `#${pad2(r.toString(16))}${pad2(g.toString(16))}${pad2(b.toString(16))}`;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate unique color from `value`
|
||||
* @param {string|number} value
|
||||
* @param {Object} [options={}]
|
||||
* @param {string} [options.format='hex']
|
||||
* The color format, it can be one of `hex`, `rgb` or `hsl`
|
||||
* @param {number|Array} [options.saturation=[50, 55]]
|
||||
* Determines the color saturation, it can be a number or a range between 0 and 100
|
||||
* @param {number|Array} [options.lightness=[50, 60]]
|
||||
* Determines the color lightness, it can be a number or a range between 0 and 100
|
||||
* @param {number} [options.differencePoint=130]
|
||||
* Determines the color brightness difference point. We use it to obtain the `isLight` value
|
||||
* in the output, it can be a number between 0 and 255
|
||||
* @return {Object}
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* uniqolor('Hello world!')
|
||||
* // { color: "#5cc653", isLight: true }
|
||||
*
|
||||
* uniqolor('Hello world!', { format: 'rgb' })
|
||||
* // { color: "rgb(92, 198, 83)", isLight: true }
|
||||
*
|
||||
* uniqolor('Hello world!', {
|
||||
* saturation: 30,
|
||||
* lightness: [70, 80],
|
||||
* })
|
||||
* // { color: "#afd2ac", isLight: true }
|
||||
*
|
||||
* uniqolor('Hello world!', {
|
||||
* saturation: 30,
|
||||
* lightness: [70, 80],
|
||||
* differencePoint: 200,
|
||||
* })
|
||||
* // { color: "#afd2ac", isLight: false }
|
||||
* ```
|
||||
*/
|
||||
const uniqolor = (value, {
|
||||
format = 'hex',
|
||||
saturation = [50, 55],
|
||||
lightness = [50, 60],
|
||||
differencePoint = 130,
|
||||
} = {}) => {
|
||||
const hash = Math.abs(hashCode(String(value)));
|
||||
const h = boundHashCode(hash, [0, 360]);
|
||||
const s = boundHashCode(hash, sanitizeRange(saturation, SATURATION_BOUND));
|
||||
const l = boundHashCode(hash, sanitizeRange(lightness, LIGHTNESS_BOUND));
|
||||
const [r, g, b] = hslToRgb(h, s, l);
|
||||
|
||||
return {
|
||||
color: format === 'hsl'
|
||||
? hslToString(h, s, l)
|
||||
: rgbFormat(r, g, b, format),
|
||||
isLight: rgbIsLight(r, g, b, differencePoint),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate random color
|
||||
* @param {Object} [options={}]
|
||||
* @param {string} [options.format='hex']
|
||||
* The color format, it can be one of `hex`, `rgb` or `hsl`
|
||||
* @param {number|Array} [options.saturation=[50, 55]]
|
||||
* Determines the color saturation, it can be a number or a range between 0 and 100
|
||||
* @param {number|Array} [options.lightness=[50, 60]]
|
||||
* Determines the color lightness, it can be a number or a range between 0 and 100
|
||||
* @param {number} [options.differencePoint=130]
|
||||
* Determines the color brightness difference point. We use it to obtain the `isLight` value
|
||||
* in the output, it can be a number between 0 and 255
|
||||
* @param {Array} [options.excludeHue]
|
||||
* Exclude certain hue ranges. For example to exclude red color range: `[[0, 20], [325, 359]]`
|
||||
* @return {Object}
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* // Generate random color
|
||||
* uniqolor.random()
|
||||
* // { color: "#644cc8", isLight: false }
|
||||
*
|
||||
* // Generate a random color with HSL format
|
||||
* uniqolor.random({ format: 'hsl' })
|
||||
* // { color: "hsl(89, 55%, 60%)", isLight: true }
|
||||
*
|
||||
* // Generate a random color in specific saturation and lightness
|
||||
* uniqolor.random({
|
||||
* saturation: 80,
|
||||
* lightness: [70, 80],
|
||||
* })
|
||||
* // { color: "#c7b9da", isLight: true }
|
||||
*
|
||||
* // Generate a random color but exclude red color range
|
||||
* uniqolor.random({
|
||||
* excludeHue: [[0, 20], [325, 359]],
|
||||
* })
|
||||
* // {color: '#53caab', isLight: true}
|
||||
* ```
|
||||
*/
|
||||
uniqolor.random = ({
|
||||
format = 'hex',
|
||||
saturation = [50, 55],
|
||||
lightness = [50, 60],
|
||||
differencePoint = 130,
|
||||
excludeHue,
|
||||
} = {}) => {
|
||||
saturation = sanitizeRange(saturation, SATURATION_BOUND);
|
||||
lightness = sanitizeRange(lightness, LIGHTNESS_BOUND);
|
||||
|
||||
const h = excludeHue ? randomExclude(0, 359, excludeHue) : random(0, 359);
|
||||
const s = typeof saturation === 'number'
|
||||
? saturation
|
||||
: random(...saturation);
|
||||
const l = typeof lightness === 'number'
|
||||
? lightness
|
||||
: random(...lightness);
|
||||
const [r, g, b] = hslToRgb(h, s, l);
|
||||
|
||||
return {
|
||||
color: format === 'hsl'
|
||||
? hslToString(h, s, l)
|
||||
: rgbFormat(r, g, b, format),
|
||||
isLight: rgbIsLight(r, g, b, differencePoint),
|
||||
};
|
||||
};
|
||||
|
||||
export default uniqolor;
|
@@ -189,3 +189,30 @@ export function sortByCssOrder(a, b) {
|
||||
const _b = Number($(b).css('order'));
|
||||
return _a - _b;
|
||||
}
|
||||
|
||||
export function end_trim_to_sentence(input, include_newline = false) {
|
||||
// inspired from https://github.com/kaihordewebui/kaihordewebui.github.io/blob/06b95e6b7720eb85177fbaf1a7f52955d7cdbc02/index.html#L4853-L4867
|
||||
|
||||
const punctuation = new Set(['.', '!', '?', '*', '"', ')', '}', '`', ']', '$']); // extend this as you see fit
|
||||
let last = -1;
|
||||
|
||||
for (let i = input.length - 1; i >= 0; i--) {
|
||||
const char = input[i];
|
||||
|
||||
if (punctuation.has(char)) {
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (include_newline && char === '\n') {
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (last === -1) {
|
||||
return input.trimEnd();
|
||||
}
|
||||
|
||||
return input.substring(0, last + 1).trimEnd();
|
||||
}
|
||||
|
@@ -311,7 +311,7 @@ function appendWorldEntry(entry) {
|
||||
const value = $(this).prop("checked");
|
||||
world_info_data.entries[uid].disable = value;
|
||||
saveWorldInfo();
|
||||
console.log(`WI #${entry.uid} disabled? ${world_info_data.entries[uid].disable}`);
|
||||
//console.log(`WI #${entry.uid} disabled? ${world_info_data.entries[uid].disable}`);
|
||||
});
|
||||
disableInput.prop("checked", entry.disable).trigger("input");
|
||||
disableInput.siblings(".checkbox_fancy").click(function () {
|
||||
@@ -593,7 +593,8 @@ $(document).ready(() => {
|
||||
await loadWorldInfoData();
|
||||
}
|
||||
|
||||
hideWorldEditor();
|
||||
if (selectedWorld === "None") { hideWorldEditor(); }
|
||||
if (is_world_edit_open && selectedWorld !== "None") { showWorldEditor() };
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
|
155
public/style.css
155
public/style.css
@@ -203,6 +203,16 @@ table.responsiveTable {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mes_narrate,
|
||||
body.tts .mes[is_user="true"] .mes_narrate,
|
||||
body.tts .mes[is_system="true"] .mes_narrate {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.tts .mes_narrate {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Consolas, monospace;
|
||||
white-space: pre-wrap;
|
||||
@@ -385,6 +395,18 @@ code {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#token_breakdown div {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.token_breakdown_segment {
|
||||
min-width: 40px !important;
|
||||
border: solid 2px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
|
||||
#loading_mes {
|
||||
display: none;
|
||||
@@ -889,19 +911,22 @@ input[type="file"] {
|
||||
|
||||
#rm_button_characters,
|
||||
#rm_button_panel_pin_div,
|
||||
#lm_button_panel_pin_div {
|
||||
#lm_button_panel_pin_div,
|
||||
#WI_button_panel_pin_div {
|
||||
font-size: 24px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin_div,
|
||||
#lm_button_panel_pin_div {
|
||||
#lm_button_panel_pin_div,
|
||||
#WI_button_panel_pin_div {
|
||||
opacity: 0.5;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin_div:hover,
|
||||
#lm_button_panel_pin_div:hover {
|
||||
#lm_button_panel_pin_div:hover,
|
||||
#WI_button_panel_pin_div:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -910,32 +935,38 @@ input[type="file"] {
|
||||
}
|
||||
|
||||
#rm_button_panel_pin,
|
||||
#lm_button_panel_pin {
|
||||
#lm_button_panel_pin,
|
||||
#WI_panel_pin {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin:checked+label,
|
||||
#lm_button_panel_pin:checked+label {
|
||||
#lm_button_panel_pin:checked+label,
|
||||
#WI_panel_pin:checked+label {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin:checked+label .checked,
|
||||
#lm_button_panel_pin:checked+label .checked {
|
||||
#lm_button_panel_pin:checked+label .checked,
|
||||
#WI_panel_pin:checked+label .checked {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin:checked+label .unchecked,
|
||||
#lm_button_panel_pin:checked+label .unchecked {
|
||||
#lm_button_panel_pin:checked+label .unchecked,
|
||||
#WI_panel_pin:checked+label .unchecked {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin:not(:checked)+label .checked,
|
||||
#lm_button_panel_pin:not(:checked)+label .checked {
|
||||
#lm_button_panel_pin:not(:checked)+label .checked,
|
||||
#WI_panel_pin:not(:checked)+label .checked {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rm_button_panel_pin:not(:checked)+label .unchecked,
|
||||
#lm_button_panel_pin:not(:checked)+label .unchecked {
|
||||
#lm_button_panel_pin:not(:checked)+label .unchecked,
|
||||
#WI_panel_pin:not(:checked)+label .unchecked {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@@ -1527,6 +1558,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar_div .menu_button,
|
||||
@@ -1647,29 +1679,32 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
|
||||
#world_popup {
|
||||
display: none;
|
||||
background-color: var(--SmartThemeBlurTintColor);
|
||||
backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2));
|
||||
max-width: var(--sheldWidth);
|
||||
height: calc(100% - 40px);
|
||||
position: absolute;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
/* background-color: var(--SmartThemeBlurTintColor);
|
||||
backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2)); */
|
||||
/* max-width: var(--sheldWidth); */
|
||||
/* max-height: calc(100% - 100px); */
|
||||
min-height: 100px;
|
||||
min-width: 100px;
|
||||
/* position: absolute; */
|
||||
/* margin-left: auto;
|
||||
margin-right: auto; */
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 40px;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
||||
padding: 4px;
|
||||
/* top: 40px; */
|
||||
/* box-shadow: 0 0 2px rgba(0, 0, 0, 0.5); */
|
||||
/* padding: 10px; */
|
||||
flex-direction: column;
|
||||
z-index: 3010;
|
||||
border-radius: 0 0 20px 20px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
#world_popup_bottom_holder {
|
||||
padding: 0.5rem 0;
|
||||
margin: 0 18px;
|
||||
/* padding: 0.5rem 0;
|
||||
margin: 0 18px; */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -1688,6 +1723,10 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.world_entry {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.world_entry:not(:last-child)::after {
|
||||
margin-top: 1rem;
|
||||
height: 1px;
|
||||
@@ -1706,7 +1745,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: 18px;
|
||||
/* margin-left: 18px; */
|
||||
}
|
||||
|
||||
#world_popup_header h3 {
|
||||
@@ -1723,7 +1762,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
}
|
||||
|
||||
#form_rename_world {
|
||||
margin-right: 50px;
|
||||
/* margin-right: 50px; */
|
||||
}
|
||||
|
||||
#form_rename_chat {
|
||||
@@ -1752,7 +1791,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
|
||||
#world_popup_entries_list {
|
||||
flex-grow: 1;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#world_popup_entries_list:empty {
|
||||
@@ -1803,7 +1842,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
|
||||
.world_entry_form_control textarea {
|
||||
height: auto;
|
||||
width: auto;
|
||||
/* width: auto; */
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@@ -1811,6 +1850,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.world_entry_form_control input[type=button] {
|
||||
@@ -2143,6 +2183,7 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
}
|
||||
|
||||
.mes_prompt,
|
||||
.mes_narrate,
|
||||
.mes_copy,
|
||||
.mes_edit {
|
||||
cursor: pointer;
|
||||
@@ -2155,11 +2196,13 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
|
||||
.mes_edit:hover,
|
||||
.mes_copy:hover,
|
||||
.mes_narrate:hover,
|
||||
.mes_stop:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.last_mes .mes_copy,
|
||||
.last_mes .mes_narrate,
|
||||
.last_mes .mes_prompt {
|
||||
grid-row-start: 1;
|
||||
position: relative;
|
||||
@@ -2269,8 +2312,10 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-backdrop-filter: blur(calc(var(--SmartThemeBlurStrength)*2));
|
||||
grid-template-rows: 50px 1fr 1fr 1fr 5fr;
|
||||
grid-gap: 10px;
|
||||
min-height: 100px;
|
||||
min-width: 100px;
|
||||
max-width: var(--sheldWidth);
|
||||
height: calc(100svh - 40px);
|
||||
max-height: calc(100svh - 100px);
|
||||
position: absolute;
|
||||
z-index: 3002;
|
||||
margin-left: auto;
|
||||
@@ -2285,6 +2330,7 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
padding-bottom: 30px;
|
||||
border: 1px solid var(--black30a);
|
||||
border-radius: 0 0 20px 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#character_popup h3 {
|
||||
@@ -3147,11 +3193,39 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#export_format_popup {
|
||||
#export_format_popup,
|
||||
#rawPromptPopup {
|
||||
display: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
#rawPromptPopup {
|
||||
inset: 0px auto auto 0px;
|
||||
margin: 0px;
|
||||
transform: translate(909px, 47px);
|
||||
display: block;
|
||||
overflow-wrap: break-word;
|
||||
white-space: normal;
|
||||
max-width: calc(((100svw - 500px) / 2) - 10px);
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
max-height: 90svh;
|
||||
/*unsure why, but this prevents scrollbars*/
|
||||
height: 49svh;
|
||||
|
||||
padding: 5px;
|
||||
overflow-y: auto;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rawPopupWrapper {
|
||||
word-wrap: break-word;
|
||||
width: 100%;
|
||||
text-align: start;
|
||||
overflow-y: auto;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -3453,8 +3527,10 @@ label[for="extensions_autoconnect"] {
|
||||
}
|
||||
|
||||
.fillRight,
|
||||
.fillLeft {
|
||||
.fillLeft,
|
||||
#WorldInfo {
|
||||
min-width: unset;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.fillLeft {
|
||||
@@ -3962,10 +4038,10 @@ body.waifuMode #avatar_zoom_popup {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#world_popup_header {
|
||||
/* #world_popup_header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
} */
|
||||
|
||||
#world_popup_header .world_popup_expander {
|
||||
display: none;
|
||||
@@ -4011,14 +4087,18 @@ body.waifuMode #avatar_zoom_popup {
|
||||
|
||||
#sheld,
|
||||
#character_popup,
|
||||
#world_popup {
|
||||
height: calc(100svh - 45px);
|
||||
.drawer-content
|
||||
|
||||
/* ,
|
||||
#world_popup */
|
||||
{
|
||||
max-height: calc(100svh - 45px);
|
||||
width: 100% !important;
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
left: 0 !important;
|
||||
resize: none;
|
||||
top: 42px;
|
||||
resize: none !important;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
#character_popup,
|
||||
@@ -4027,7 +4107,6 @@ body.waifuMode #avatar_zoom_popup {
|
||||
}
|
||||
|
||||
#character_popup,
|
||||
#world_popup,
|
||||
#send_form {
|
||||
border: 1px solid var(--grey30);
|
||||
backdrop-filter: blur(calc(var(--SmartThemeBlurStrength) * 2));
|
||||
@@ -4049,6 +4128,10 @@ body.waifuMode #avatar_zoom_popup {
|
||||
|
||||
}
|
||||
|
||||
#showRawPrompt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mes-text {
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
59
readme.md
59
readme.md
@@ -168,45 +168,58 @@ In order to enable viewing your keys by clicking a button in the API block:
|
||||
|
||||
## Remote connections
|
||||
|
||||
Most often this is for people who want to use SillyTavern on their mobile phones while at home.
|
||||
If you want to enable other devices to connect to your TAI server, open 'config.conf' in a text editor, and change:
|
||||
Most often this is for people who want to use SillyTavern on their mobile phones while their PC runs the ST server on the same wifi network.
|
||||
|
||||
```
|
||||
const whitelistMode = true;
|
||||
```
|
||||
However, it can be used to allow remote connections from anywhere as well.
|
||||
|
||||
to
|
||||
**IMPORTANT: SillyTavern is a single-user program, so anyone who logs in will be able to see all characters and chats, and be able to change any settings inside the UI.**
|
||||
|
||||
```
|
||||
const whitelistMode = false;
|
||||
```
|
||||
### 1. Managing whitelisted IPs
|
||||
|
||||
Save the file.
|
||||
Restart your TAI server.
|
||||
|
||||
You will now be able to connect from other devices.
|
||||
|
||||
### Managing whitelisted IPs
|
||||
|
||||
You can add or remove whitelisted IPs by editing the `whitelist` array in `config.conf`. You can also provide a `whitelist.txt` file in the same directory as `config.conf` with one IP address per line like:
|
||||
* Create a new text file inside your SillyTavern base install folder called `whitelist.txt`.
|
||||
* Open the file in a text editor, add a list of IPs you want to be allowed to connect.
|
||||
|
||||
*IP ranges are not accepted. Each IP must be listed individually like this:*
|
||||
```txt
|
||||
192.168.0.1
|
||||
192.168.0.2
|
||||
192.168.0.3
|
||||
192.168.0.4
|
||||
```
|
||||
* Save the `whitelist.txt` file.
|
||||
* Restart your TAI server.
|
||||
|
||||
The `whitelist` array in `config.conf` will be ignored if `whitelist.txt` exists.
|
||||
Now devices which have the IP specified in the file will be able to connect.
|
||||
|
||||
***Disclaimer: Anyone else who knows your IP address and TAI port number will be able to connect as well***
|
||||
*Note: `config.conf` also has a `whitelist` array, which you can use in the same way, but this array will be ignored if `whitelist.txt` exists.*
|
||||
|
||||
To connect over wifi you'll need your PC's local wifi IP address
|
||||
### 2. Connecting to ST from a remote device
|
||||
|
||||
* (For Windows: windows button > type 'cmd.exe' in the search bar> type 'ipconfig' in the console, hit Enter > "IPv4" listing)
|
||||
if you want other people on the internet to connect, check [here](https://whatismyipaddress.com/) for 'IPv4'
|
||||
After the whitelist has been setup, to connect over wifi you'll need the IP of the ST-hosting device.
|
||||
|
||||
If the ST-hosting device is on the same wifi network, you will point your remote device's browser to the ST-host's internal wifi IP:
|
||||
|
||||
* For Windows: windows button > type `cmd.exe` in the search bar > type `ipconfig` in the console, hit Enter > look for `IPv4` listing.
|
||||
|
||||
If you (or someone else) wants to connect to your hosted ST while not being on the same network, you will need the public IP of your ST-hosting device.
|
||||
|
||||
While using the ST-hosting device, access [this page](https://whatismyipaddress.com/) and look for for `IPv4`. This is what you would use to connect from the remote device.
|
||||
|
||||
### Opening your ST to all IPs
|
||||
|
||||
We do not reccomend doing this, but you can open `config.conf` and change `whitelist` to `false`.
|
||||
|
||||
You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder, if it exists.
|
||||
|
||||
This is usually an insecure practice, so we require you to set a username and password when you do this.
|
||||
|
||||
The username and password are set in `config.conf`.
|
||||
|
||||
After restarting your ST server, any device will be able to connect to it, regardless of their IP as long as they know the username and password.
|
||||
|
||||
### Still Unable To Connect?
|
||||
|
||||
- Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for portforwarding on your router, otherwise someone could find your chat logs and that's a big no-no.
|
||||
* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for portforwarding on your router, otherwise someone could find your chat logs and that's a big no-no.
|
||||
* Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise you would be unable to connect even with the aforementioned firewall rules.
|
||||
|
||||
## Performance issues?
|
||||
|
94
server.js
94
server.js
@@ -82,6 +82,10 @@ const allowKeysExposure = config.allowKeysExposure;
|
||||
const axios = require('axios');
|
||||
const tiktoken = require('@dqbd/tiktoken');
|
||||
const WebSocket = require('ws');
|
||||
const AIHorde = require("@zeldafan0225/ai_horde");
|
||||
const ai_horde = new AIHorde({
|
||||
client_agent: getVersion()?.agent || 'SillyTavern:UNKNOWN:Cohee#1207',
|
||||
});
|
||||
|
||||
var Client = require('node-rest-client').Client;
|
||||
var client = new Client();
|
||||
@@ -309,27 +313,8 @@ app.get('/deviceinfo', function (request, response) {
|
||||
return response.send(deviceInfo);
|
||||
});
|
||||
app.get('/version', function (_, response) {
|
||||
let pkgVersion, gitRevision, gitBranch;
|
||||
try {
|
||||
const pkgJson = require('./package.json');
|
||||
pkgVersion = pkgJson.version;
|
||||
if (commandExistsSync('git')) {
|
||||
gitRevision = require('child_process')
|
||||
.execSync('git rev-parse --short HEAD', { cwd: __dirname })
|
||||
.toString().trim();
|
||||
|
||||
gitBranch = require('child_process')
|
||||
.execSync('git rev-parse --abbrev-ref HEAD', { cwd: __dirname })
|
||||
.toString().trim();
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// suppress exception
|
||||
}
|
||||
finally {
|
||||
const agent = `SillyTavern:${gitRevision || pkgVersion}:Cohee#1207`;
|
||||
response.send({ agent, pkgVersion, gitRevision, gitBranch });
|
||||
}
|
||||
const data = getVersion();
|
||||
response.send(data);
|
||||
})
|
||||
|
||||
//**************Kobold api
|
||||
@@ -665,6 +650,31 @@ app.post("/setsoftprompt", jsonParser, async function (request, response) {
|
||||
return response.sendStatus(200);
|
||||
});
|
||||
|
||||
function getVersion() {
|
||||
let pkgVersion = 'UNKNOWN';
|
||||
let gitRevision = null;
|
||||
let gitBranch = null;
|
||||
try {
|
||||
const pkgJson = require('./package.json');
|
||||
pkgVersion = pkgJson.version;
|
||||
if (commandExistsSync('git')) {
|
||||
gitRevision = require('child_process')
|
||||
.execSync('git rev-parse --short HEAD', { cwd: __dirname })
|
||||
.toString().trim();
|
||||
|
||||
gitBranch = require('child_process')
|
||||
.execSync('git rev-parse --abbrev-ref HEAD', { cwd: __dirname })
|
||||
.toString().trim();
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// suppress exception
|
||||
}
|
||||
|
||||
const agent = `SillyTavern:${pkgVersion}:Cohee#1207`;
|
||||
return { agent, pkgVersion, gitRevision, gitBranch };
|
||||
}
|
||||
|
||||
function tryParse(str) {
|
||||
try {
|
||||
return json5.parse(str);
|
||||
@@ -2870,8 +2880,9 @@ app.post('/readsecretstate', jsonParser, (_, response) => {
|
||||
}
|
||||
});
|
||||
|
||||
const ANONYMOUS_KEY = "0000000000";
|
||||
|
||||
app.post('/generate_horde', jsonParser, async (request, response) => {
|
||||
const ANONYMOUS_KEY = "0000000000";
|
||||
const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY;
|
||||
const url = 'https://horde.koboldai.net/api/v2/generate/text/async';
|
||||
|
||||
@@ -2914,6 +2925,45 @@ app.post('/viewsecrets', jsonParser, async (_, response) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/horde_generateimage', async (request, response) => {
|
||||
const MAX_ATTEMPTS = 100;
|
||||
const CHECK_INTERVAL = 3000;
|
||||
const api_key_horde = readSecret(SECRET_KEYS.HORDE) || ANONYMOUS_KEY;
|
||||
const generation = await ai_horde.postAsyncImageGenerate(
|
||||
{
|
||||
prompt: `${request.body.prompt_prefix} ${request.body.prompt} ### ${request.body.negative_prompt}`,
|
||||
params:
|
||||
{
|
||||
sampler_name: request.body.sampler,
|
||||
cfg_scale: request.body.scale,
|
||||
steps: request.body.steps,
|
||||
width: request.body.width,
|
||||
height: request.body.height,
|
||||
n: 1,
|
||||
},
|
||||
r2: false,
|
||||
nsfw: request.body.nfsw,
|
||||
models: [request.body.model],
|
||||
},
|
||||
{ token: api_key_horde });
|
||||
|
||||
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
||||
await delay(CHECK_INTERVAL);
|
||||
const check = await ai_horde.getImageGenerationCheck(generation.id);
|
||||
|
||||
if (check.done) {
|
||||
const result = await ai_horde.getImageGenerationStatus(generation.id);
|
||||
return response.send(result.generations[0].img);
|
||||
}
|
||||
|
||||
if (check.faulted) {
|
||||
return response.sendStatus(500);
|
||||
}
|
||||
}
|
||||
|
||||
return response.sendStatus(504);
|
||||
});
|
||||
|
||||
function writeSecret(key, value) {
|
||||
if (!fs.existsSync(SECRETS_FILE)) {
|
||||
const emptyFile = JSON.stringify({});
|
||||
|
5
start.sh
5
start.sh
@@ -10,7 +10,8 @@ then
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
|
||||
source ~/.bashrc
|
||||
nvm install node;;
|
||||
nvm install lts
|
||||
nvm use lts;;
|
||||
n|N )
|
||||
echo "Nodejs and npm will not be installed."
|
||||
exit;;
|
||||
@@ -30,4 +31,4 @@ echo "Installing Node Modules..."
|
||||
npm i
|
||||
|
||||
echo "Entering SillyTavern..."
|
||||
node server.js
|
||||
node "$(dirname "$0")/server.js"
|
Reference in New Issue
Block a user