mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into pr/Cohee1207/2711
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
"openrouter_force_instruct": false,
|
"openrouter_force_instruct": false,
|
||||||
"openrouter_group_models": false,
|
"openrouter_group_models": false,
|
||||||
"openrouter_sort_models": "alphabetically",
|
"openrouter_sort_models": "alphabetically",
|
||||||
"ai21_model": "j2-ultra",
|
"ai21_model": "jamba-1.5-large",
|
||||||
"mistralai_model": "mistral-large-latest",
|
"mistralai_model": "mistral-large-latest",
|
||||||
"custom_model": "",
|
"custom_model": "",
|
||||||
"custom_url": "",
|
"custom_url": "",
|
||||||
@ -19,7 +19,6 @@
|
|||||||
"temperature": 1,
|
"temperature": 1,
|
||||||
"frequency_penalty": 0,
|
"frequency_penalty": 0,
|
||||||
"presence_penalty": 0,
|
"presence_penalty": 0,
|
||||||
"count_penalty": 0,
|
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_a": 0,
|
"top_a": 0,
|
||||||
@ -233,8 +232,6 @@
|
|||||||
"assistant_prefill": "",
|
"assistant_prefill": "",
|
||||||
"assistant_impersonation": "",
|
"assistant_impersonation": "",
|
||||||
"human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.",
|
"human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.",
|
||||||
"use_ai21_tokenizer": false,
|
|
||||||
"use_google_tokenizer": false,
|
|
||||||
"claude_use_sysprompt": false,
|
"claude_use_sysprompt": false,
|
||||||
"use_alt_scale": false,
|
"use_alt_scale": false,
|
||||||
"squash_system_messages": false,
|
"squash_system_messages": false,
|
||||||
|
@ -196,7 +196,15 @@
|
|||||||
"enableLabMode": false,
|
"enableLabMode": false,
|
||||||
"enableZenSliders": false,
|
"enableZenSliders": false,
|
||||||
"ui_mode": 1,
|
"ui_mode": 1,
|
||||||
"forbid_external_media": true
|
"forbid_external_media": true,
|
||||||
|
"stscript": {
|
||||||
|
"parser": {
|
||||||
|
"flags": {
|
||||||
|
"1": true,
|
||||||
|
"2": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"extension_settings": {
|
"extension_settings": {
|
||||||
"apiUrl": "http://localhost:5100",
|
"apiUrl": "http://localhost:5100",
|
||||||
@ -452,7 +460,6 @@
|
|||||||
"temp_openai": 1.0,
|
"temp_openai": 1.0,
|
||||||
"freq_pen_openai": 0,
|
"freq_pen_openai": 0,
|
||||||
"pres_pen_openai": 0,
|
"pres_pen_openai": 0,
|
||||||
"count_pen": 0,
|
|
||||||
"top_p_openai": 1,
|
"top_p_openai": 1,
|
||||||
"top_k_openai": 0,
|
"top_k_openai": 0,
|
||||||
"stream_openai": true,
|
"stream_openai": true,
|
||||||
@ -614,7 +621,7 @@
|
|||||||
"wi_format": "{0}",
|
"wi_format": "{0}",
|
||||||
"openai_model": "gpt-4-turbo",
|
"openai_model": "gpt-4-turbo",
|
||||||
"claude_model": "claude-3-5-sonnet-20240620",
|
"claude_model": "claude-3-5-sonnet-20240620",
|
||||||
"ai21_model": "j2-ultra",
|
"ai21_model": "jamba-1.5-large",
|
||||||
"windowai_model": "",
|
"windowai_model": "",
|
||||||
"openrouter_model": "OR_Website",
|
"openrouter_model": "OR_Website",
|
||||||
"jailbreak_system": true,
|
"jailbreak_system": true,
|
||||||
@ -625,7 +632,6 @@
|
|||||||
"show_external_models": false,
|
"show_external_models": false,
|
||||||
"proxy_password": "",
|
"proxy_password": "",
|
||||||
"assistant_prefill": "",
|
"assistant_prefill": "",
|
||||||
"assistant_impersonation": "",
|
"assistant_impersonation": ""
|
||||||
"use_ai21_tokenizer": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<title>SillyTavern</title>
|
<title>SillyTavern</title>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="darkreader-lock">
|
<meta name="darkreader-lock">
|
||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
@ -436,7 +436,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq">
|
<div data-newbie-hidden class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq">
|
||||||
<div class="range-block-title" data-i18n="Frequency Penalty">
|
<div class="range-block-title" data-i18n="Frequency Penalty">
|
||||||
Frequency Penalty
|
Frequency Penalty
|
||||||
</div>
|
</div>
|
||||||
@ -449,7 +449,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq">
|
<div data-newbie-hidden class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq">
|
||||||
<div class="range-block-title" data-i18n="Presence Penalty">
|
<div class="range-block-title" data-i18n="Presence Penalty">
|
||||||
Presence Penalty
|
Presence Penalty
|
||||||
</div>
|
</div>
|
||||||
@ -462,20 +462,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-newbie-hidden class="range-block" data-source="ai21">
|
<div data-newbie-hidden class="range-block" data-source="claude,openrouter,makersuite,cohere,perplexity">
|
||||||
<div class="range-block-title" data-i18n="Count Penalty">
|
|
||||||
Count Penalty
|
|
||||||
</div>
|
|
||||||
<div class="range-block-range-and-counter">
|
|
||||||
<div class="range-block-range">
|
|
||||||
<input type="range" id="count_pen" name="volume" min="0" max="1" step="0.01">
|
|
||||||
</div>
|
|
||||||
<div class="range-block-counter">
|
|
||||||
<input type="number" min="0" max="1" step="0.01" data-for="count_pen" id="count_pen_counter">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div data-newbie-hidden class="range-block" data-source="claude,openrouter,ai21,makersuite,cohere,perplexity">
|
|
||||||
<div class="range-block-title" data-i18n="Top K">
|
<div class="range-block-title" data-i18n="Top K">
|
||||||
Top K
|
Top K
|
||||||
</div>
|
</div>
|
||||||
@ -1291,6 +1278,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div data-newbie-hidden data-tg-type="koboldcpp" id="xtc_block" class="wide100p">
|
||||||
|
<h4 class="wide100p textAlignCenter">
|
||||||
|
<label data-i18n="Exclude Top Choices (XTC)">Exclude Top Choices (XTC)</label>
|
||||||
|
<a href="https://github.com/oobabooga/text-generation-webui/pull/6335" target="_blank">
|
||||||
|
<div class=" fa-solid fa-circle-info opacity50p"></div>
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
<div class="flex-container flexFlowRow gap10px flexShrink">
|
||||||
|
<div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0">
|
||||||
|
<small data-i18n="Threshold">Threshold</small>
|
||||||
|
<input class="neo-range-slider" type="range" id="xtc_threshold_textgenerationwebui" name="volume" min="0" max="0.5" step="0.01" />
|
||||||
|
<input class="neo-range-input" type="number" min="0" max="0.5" step="0.01" data-for="xtc_threshold_textgenerationwebui" id="xtc_threshold_counter_textgenerationwebui">
|
||||||
|
</div>
|
||||||
|
<div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0">
|
||||||
|
<small data-i18n="Probability">Probability</small>
|
||||||
|
<input class="neo-range-slider" type="range" id="xtc_probability_textgenerationwebui" name="volume" min="0" max="1" step="0.01" />
|
||||||
|
<input class="neo-range-input" type="number" min="0" max="1" step="0.01" data-for="xtc_probability_textgenerationwebui" id="xtc_probability_counter_textgenerationwebui">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Enable for llama.cpp when the PR is merged: https://github.com/ggerganov/llama.cpp/pull/6839 -->
|
<!-- Enable for llama.cpp when the PR is merged: https://github.com/ggerganov/llama.cpp/pull/6839 -->
|
||||||
<div data-newbie-hidden data-tg-type="ooba, koboldcpp" id="dryBlock" class="wide100p">
|
<div data-newbie-hidden data-tg-type="ooba, koboldcpp" id="dryBlock" class="wide100p">
|
||||||
<h4 class="wide100p textAlignCenter" title="DRY penalizes tokens that would extend the end of the input into a sequence that has previously occurred in the input. Set multiplier to 0 to disable." data-i18n="[title]DRY_Repetition_Penalty_desc">
|
<h4 class="wide100p textAlignCenter" title="DRY penalizes tokens that would extend the end of the input into a sequence that has previously occurred in the input. Set multiplier to 0 to disable." data-i18n="[title]DRY_Repetition_Penalty_desc">
|
||||||
@ -1484,11 +1493,11 @@
|
|||||||
<div id="banned_tokens_block_ooba" data-newbie-hidden class="wide100p">
|
<div id="banned_tokens_block_ooba" data-newbie-hidden class="wide100p">
|
||||||
<hr data-newbie-hidden class="width100p">
|
<hr data-newbie-hidden class="width100p">
|
||||||
<h4 class="range-block-title justifyCenter">
|
<h4 class="range-block-title justifyCenter">
|
||||||
<span data-i18n="Banned Tokens">Banned Tokens</span>
|
<span data-i18n="Banned Tokens">Banned Tokens/Strings</span>
|
||||||
<div class="margin5 fa-solid fa-circle-info opacity50p " data-i18n="[title]LLaMA / Mistral / Yi models only" title="LLaMA / Mistral / Yi models only. Make sure to select an appropriate tokenizer first. Sequences you don't want to appear in the output. One per line. Text or [token ids]. Most tokens have a leading space. Use token counter if unsure."></div>
|
<div class="margin5 fa-solid fa-circle-info opacity50p " data-i18n="[title]LLaMA / Mistral / Yi models only" title="Enter sequences you don't want to appear in the output. Unquoted text will be tokenized in the back end and banned as tokens. [token ids] will be banned as-is. Most tokens have a leading space. Use token counter (with the correct tokenizer selected first!) if you are unsure. Enclose text in double quotes to ban the entire string as a set. Quoted Strings and [Token ids] must be on their own line."></div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="wide100p">
|
<div class="wide100p">
|
||||||
<textarea id="banned_tokens_textgenerationwebui" class="text_pole textarea_compact" name="banned_tokens_textgenerationwebui" rows="3" data-i18n="[placeholder]Example: some text [42, 69, 1337]" placeholder="Example: some text [42, 69, 1337]"></textarea>
|
<textarea id="banned_tokens_textgenerationwebui" class="text_pole textarea_compact" name="banned_tokens_textgenerationwebui" rows="3" data-i18n="[placeholder]Example: some text [42, 69, 1337]" placeholder='some text as tokens [420, 69, 1337] "Some verbatim string"'></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block wide100p">
|
<div class="range-block wide100p">
|
||||||
@ -1791,22 +1800,6 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block" data-source="ai21">
|
|
||||||
<label for="use_ai21_tokenizer" title="Use AI21 Tokenizer" data-i18n="[title]Use AI21 Tokenizer" class="checkbox_label widthFreeExpand">
|
|
||||||
<input id="use_ai21_tokenizer" type="checkbox" /><span data-i18n="Use AI21 Tokenizer">Use AI21 Tokenizer</span>
|
|
||||||
</label>
|
|
||||||
<div class="toggle-description justifyLeft">
|
|
||||||
<span data-i18n="Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.">Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="range-block" data-source="makersuite">
|
|
||||||
<label for="use_google_tokenizer" title="Use Google Tokenizer" data-i18n="[title]Use Google Tokenizer" class="checkbox_label widthFreeExpand">
|
|
||||||
<input id="use_google_tokenizer" type="checkbox" /><span data-i18n="Use Google Tokenizer">Use Google Tokenizer</span>
|
|
||||||
</label>
|
|
||||||
<div class="toggle-description justifyLeft">
|
|
||||||
<span data-i18n="Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.">Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="range-block" data-source="makersuite">
|
<div class="range-block" data-source="makersuite">
|
||||||
<label for="use_makersuite_sysprompt" class="checkbox_label widthFreeExpand">
|
<label for="use_makersuite_sysprompt" class="checkbox_label widthFreeExpand">
|
||||||
<input id="use_makersuite_sysprompt" type="checkbox" />
|
<input id="use_makersuite_sysprompt" type="checkbox" />
|
||||||
@ -1852,7 +1845,7 @@
|
|||||||
<div class="fa-solid fa-clock-rotate-left"></div>
|
<div class="fa-solid fa-clock-rotate-left"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<textarea id="claude_human_sysprompt_textarea" class="text_pole textarea_compact" rows="4" maxlength="10000" data-i18n="[placeholder]Human message" placeholder="Human message, instruction, etc. Adds nothing when empty, i.e. requires a new prompt with the role 'user'."></textarea>
|
<textarea id="claude_human_sysprompt_textarea" class="text_pole textarea_compact" rows="4" data-i18n="[placeholder]Human message" placeholder="Human message, instruction, etc. Adds nothing when empty, i.e. requires a new prompt with the role 'user'."></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -2791,10 +2784,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<h4 data-i18n="AI21 Model">AI21 Model</h4>
|
<h4 data-i18n="AI21 Model">AI21 Model</h4>
|
||||||
<select id="model_ai21_select">
|
<select id="model_ai21_select">
|
||||||
<optgroup label="Latest">
|
<optgroup label="Jamba 1.5">
|
||||||
<option value="j2-ultra">j2-ultra</option>
|
<option value="jamba-1.5-mini">jamba-1.5-mini</option>
|
||||||
<option value="j2-mid">j2-mid</option>
|
<option value="jamba-1.5-large">jamba-1.5-large</option>
|
||||||
<option value="j2-light">j2-light</option>
|
</optgroup>
|
||||||
|
<optgroup label="Jamba-Instruct (Deprecated)">
|
||||||
|
<option value="jamba-instruct-preview">jamba-instruct-preview</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -2824,8 +2819,11 @@
|
|||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Subversions">
|
<optgroup label="Subversions">
|
||||||
<option value="gemini-1.5-pro-exp-0801">Gemini 1.5 Pro Experiment 2024-08-01</option>
|
<option value="gemini-1.5-pro-exp-0801">Gemini 1.5 Pro Experiment 2024-08-01</option>
|
||||||
|
<option value="gemini-1.5-pro-exp-0827">Gemini 1.5 Pro Experiment 2024-08-27</option>
|
||||||
<option value="gemini-1.5-pro-latest">Gemini 1.5 Pro [latest]</option>
|
<option value="gemini-1.5-pro-latest">Gemini 1.5 Pro [latest]</option>
|
||||||
<option value="gemini-1.5-pro-001">Gemini 1.5 Pro [001]</option>
|
<option value="gemini-1.5-pro-001">Gemini 1.5 Pro [001]</option>
|
||||||
|
<option value="gemini-1.5-flash-exp-0827">Gemini 1.5 Flash Experiment 2024-08-27</option>
|
||||||
|
<option value="gemini-1.5-flash-8b-exp-0827">Gemini 1.5 Flash 8B Experiment 2024-08-27</option>
|
||||||
<option value="gemini-1.5-flash-latest">Gemini 1.5 Flash [latest]</option>
|
<option value="gemini-1.5-flash-latest">Gemini 1.5 Flash [latest]</option>
|
||||||
<option value="gemini-1.5-flash-001">Gemini 1.5 Flash [001]</option>
|
<option value="gemini-1.5-flash-001">Gemini 1.5 Flash [001]</option>
|
||||||
<option value="gemini-1.0-pro-latest">Gemini 1.0 Pro [latest]</option>
|
<option value="gemini-1.0-pro-latest">Gemini 1.0 Pro [latest]</option>
|
||||||
@ -2955,6 +2953,8 @@
|
|||||||
<option value="command">command</option>
|
<option value="command">command</option>
|
||||||
<option value="command-r">command-r</option>
|
<option value="command-r">command-r</option>
|
||||||
<option value="command-r-plus">command-r-plus</option>
|
<option value="command-r-plus">command-r-plus</option>
|
||||||
|
<option value="command-r-08-2024">command-r-08-2024</option>
|
||||||
|
<option value="command-r-plus-08-2024">command-r-plus-08-2024</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Nightly">
|
<optgroup label="Nightly">
|
||||||
<option value="command-light-nightly">command-light-nightly</option>
|
<option value="command-light-nightly">command-light-nightly</option>
|
||||||
@ -4012,7 +4012,7 @@
|
|||||||
<input id="movingUImode" type="checkbox" />
|
<input id="movingUImode" type="checkbox" />
|
||||||
<small data-i18n="Movable UI Panels">MovingUI <i class="fa-solid fa-desktop"></i></small>
|
<small data-i18n="Movable UI Panels">MovingUI <i class="fa-solid fa-desktop"></i></small>
|
||||||
</label>
|
</label>
|
||||||
<div data-newbie-hidden id="movingUIreset" title="Reset MovingUI panel sizes/locations." class="menu_button margin0" data-i18n="[title]Reset MovingUI panel sizes/locations."><i class=" fa-solid fa-recycle margin-r5"></i> Reset</div>
|
<div data-newbie-hidden id="movingUIreset" title="Reset MovingUI panel sizes/locations." class="menu_button margin0" data-i18n="[title]Reset MovingUI panel sizes/locations."><i class=" fa-solid fa-recycle margin-r5"></i> <span data-i18n="mui_reset">Reset</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div data-newbie-hidden id="MovingUI-presets-block" class="flex-container alignitemscenter">
|
<div data-newbie-hidden id="MovingUI-presets-block" class="flex-container alignitemscenter">
|
||||||
<div class="flex-container alignItemsFlexEnd">
|
<div class="flex-container alignItemsFlexEnd">
|
||||||
@ -4503,6 +4503,7 @@
|
|||||||
<div data-newbie-hidden>
|
<div data-newbie-hidden>
|
||||||
<label for="persona_description_position" data-i18n="Position:">Position:</label>
|
<label for="persona_description_position" data-i18n="Position:">Position:</label>
|
||||||
<select id="persona_description_position">
|
<select id="persona_description_position">
|
||||||
|
<option value="9" data-i18n="None (disabled)">None (disabled)</option>
|
||||||
<option value="0" data-i18n="In Story String / Prompt Manager">In Story String / Prompt Manager</option>
|
<option value="0" data-i18n="In Story String / Prompt Manager">In Story String / Prompt Manager</option>
|
||||||
<option value="2" data-i18n="Top of Author's Note">Top of Author's Note</option>
|
<option value="2" data-i18n="Top of Author's Note">Top of Author's Note</option>
|
||||||
<option value="3" data-i18n="Bottom of Author's Note">Bottom of Author's Note</option>
|
<option value="3" data-i18n="Bottom of Author's Note">Bottom of Author's Note</option>
|
||||||
@ -6488,6 +6489,7 @@
|
|||||||
<script src="lib/jquery-cookie-1.4.1.min.js"></script>
|
<script src="lib/jquery-cookie-1.4.1.min.js"></script>
|
||||||
<script src="lib/jquery.ui.touch-punch.min.js"></script>
|
<script src="lib/jquery.ui.touch-punch.min.js"></script>
|
||||||
<script src="lib/showdown.min.js"></script>
|
<script src="lib/showdown.min.js"></script>
|
||||||
|
<script src="lib/showdown-patch.js"></script>
|
||||||
<script src="lib/showdown-katex.min.js"></script>
|
<script src="lib/showdown-katex.min.js"></script>
|
||||||
<script src="lib/popper.js"></script>
|
<script src="lib/popper.js"></script>
|
||||||
<script src="lib/purify.min.js"></script>
|
<script src="lib/purify.min.js"></script>
|
||||||
|
24
public/lib/showdown-patch.js
Normal file
24
public/lib/showdown-patch.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
|
||||||
|
'use strict';
|
||||||
|
text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
|
||||||
|
|
||||||
|
for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
|
||||||
|
var repText = globals.gHtmlSpans[i],
|
||||||
|
// limiter to prevent infinite loop (assume 10 as limit for recurse)
|
||||||
|
limit = 0;
|
||||||
|
|
||||||
|
while (/¨C(\d+)C/.test(repText)) {
|
||||||
|
var num = RegExp.$1;
|
||||||
|
repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
|
||||||
|
if (limit === 10000) {
|
||||||
|
console.error('maximum nesting of 10000 spans reached!!!');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++limit;
|
||||||
|
}
|
||||||
|
text = text.replace('¨C' + i + 'C', repText);
|
||||||
|
}
|
||||||
|
|
||||||
|
text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
|
||||||
|
return text;
|
||||||
|
});
|
@ -43,7 +43,7 @@
|
|||||||
"Smoothing Factor": "Коэффициент сглаживания",
|
"Smoothing Factor": "Коэффициент сглаживания",
|
||||||
"No Repeat Ngram Size": "Размер no_repeat_ngram",
|
"No Repeat Ngram Size": "Размер no_repeat_ngram",
|
||||||
"Min Length": "Мин. длина",
|
"Min Length": "Мин. длина",
|
||||||
"Alternative server URL (leave empty to use the default value).": "Альтернативный URL сервера (оставьте пустым для стандартного значения)",
|
"Alternative server URL (leave empty to use the default value).": "URL альтернативного сервера (оставьте пустым для стандартного значения)",
|
||||||
"Remove your real OAI API Key from the API panel BEFORE typing anything into this box": "Удалите свой личный OAI API Key из панели API, и ТОЛЬКО ПОСЛЕ ЭТОГО вводите что-то сюда",
|
"Remove your real OAI API Key from the API panel BEFORE typing anything into this box": "Удалите свой личный OAI API Key из панели API, и ТОЛЬКО ПОСЛЕ ЭТОГО вводите что-то сюда",
|
||||||
"We cannot provide support for problems encountered while using an unofficial OpenAI proxy": "Мы не сможем предоставить помощь с проблемами, с которыми вы столкнетесь при использовании неофициальных прокси для OpenAI",
|
"We cannot provide support for problems encountered while using an unofficial OpenAI proxy": "Мы не сможем предоставить помощь с проблемами, с которыми вы столкнетесь при использовании неофициальных прокси для OpenAI",
|
||||||
"Context Size (tokens)": "Размер контекста (в токенах)",
|
"Context Size (tokens)": "Размер контекста (в токенах)",
|
||||||
@ -186,7 +186,7 @@
|
|||||||
"Generate only one line per request": "Генерировать одну строку на запрос",
|
"Generate only one line per request": "Генерировать одну строку на запрос",
|
||||||
"Misc. Settings": "Доп. настройки",
|
"Misc. Settings": "Доп. настройки",
|
||||||
"Auto-Continue": "Авто-продолжение",
|
"Auto-Continue": "Авто-продолжение",
|
||||||
"Collapse Consecutive Newlines": "Сворачивать последовательные новые строки",
|
"Collapse Consecutive Newlines": "Сворачивать неск. новых строк в одну",
|
||||||
"Allow for Chat Completion APIs": "Разрешить для Chat Completion API",
|
"Allow for Chat Completion APIs": "Разрешить для Chat Completion API",
|
||||||
"Target length (tokens)": "Целевая длина (в токенах)",
|
"Target length (tokens)": "Целевая длина (в токенах)",
|
||||||
"World Info": "Информация о мире",
|
"World Info": "Информация о мире",
|
||||||
@ -373,7 +373,7 @@
|
|||||||
"Prefer Character Card Prompt": "Приоритет промпту из карточки персонажа",
|
"Prefer Character Card Prompt": "Приоритет промпту из карточки персонажа",
|
||||||
"Prefer Character Card Jailbreak": "Приоритет джейлбрейку из карточки персонажа",
|
"Prefer Character Card Jailbreak": "Приоритет джейлбрейку из карточки персонажа",
|
||||||
"Press Send to continue": "Кнопка отправки продолжает сообщение",
|
"Press Send to continue": "Кнопка отправки продолжает сообщение",
|
||||||
"Quick 'Continue' button": "Кнопка быстрого продолжения",
|
"Quick 'Continue' button": "Быстрое продолжение",
|
||||||
"Log prompts to console": "Выводить промпты в консоль",
|
"Log prompts to console": "Выводить промпты в консоль",
|
||||||
"Never resize avatars": "Не менять размер аватарок",
|
"Never resize avatars": "Не менять размер аватарок",
|
||||||
"Show avatar filenames": "Показывать названия файлов аватарок",
|
"Show avatar filenames": "Показывать названия файлов аватарок",
|
||||||
@ -495,7 +495,7 @@
|
|||||||
"(Write a comma-separated list of tags)": "(Список тегов через запятую)",
|
"(Write a comma-separated list of tags)": "(Список тегов через запятую)",
|
||||||
"(A brief description of the personality)": "(Краткое описание личности)",
|
"(A brief description of the personality)": "(Краткое описание личности)",
|
||||||
"(Circumstances and context of the interaction)": "(Обстоятельства и контекст этого диалога)",
|
"(Circumstances and context of the interaction)": "(Обстоятельства и контекст этого диалога)",
|
||||||
"(Examples of chat dialog. Begin each example with START on a new line.)": "(Примеры диалога. Начинайте каждый пример с START или новой линией.)",
|
"(Examples of chat dialog. Begin each example with START on a new line.)": "(Примеры диалога. Начинайте каждый пример с START или новой строкой.)",
|
||||||
"Type here...": "Пишите здесь...",
|
"Type here...": "Пишите здесь...",
|
||||||
"Comma separated (required)": "Через запятую (обязательное поле)",
|
"Comma separated (required)": "Через запятую (обязательное поле)",
|
||||||
"What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно",
|
"What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно",
|
||||||
@ -552,7 +552,7 @@
|
|||||||
"Click to set a new User Name": "Нажмите, чтобы задать новое имя пользователя.",
|
"Click to set a new User Name": "Нажмите, чтобы задать новое имя пользователя.",
|
||||||
"Click to lock your selected persona to the current chat. Click again to remove the lock.": "Нажмите, чтобы закрепить выбранную персону для текущего чата. Нажмите еще раз, чтобы открепить.",
|
"Click to lock your selected persona to the current chat. Click again to remove the lock.": "Нажмите, чтобы закрепить выбранную персону для текущего чата. Нажмите еще раз, чтобы открепить.",
|
||||||
"Click to set user name for all messages": "Нажмите, чтобы задать имя пользователя для всех сообщений.",
|
"Click to set user name for all messages": "Нажмите, чтобы задать имя пользователя для всех сообщений.",
|
||||||
"Create a dummy persona": "Создать персону-болванку",
|
"Create a dummy persona": "Создать пустую персону",
|
||||||
"Character Management": "Управление персонажами",
|
"Character Management": "Управление персонажами",
|
||||||
"Locked = Character Management panel will stay open": "Закреплено = Панель управление персонажами останется открытой",
|
"Locked = Character Management panel will stay open": "Закреплено = Панель управление персонажами останется открытой",
|
||||||
"Select/Create Characters": "Выбрать/Создать персонажа",
|
"Select/Create Characters": "Выбрать/Создать персонажа",
|
||||||
@ -625,7 +625,7 @@
|
|||||||
"Automatically select a background based on the chat context": "Автоматический выбор фона в зависимости от контекста чата",
|
"Automatically select a background based on the chat context": "Автоматический выбор фона в зависимости от контекста чата",
|
||||||
"Filter": "Фильтр",
|
"Filter": "Фильтр",
|
||||||
"Exclude message from prompts": "Исключить сообщение из промпта",
|
"Exclude message from prompts": "Исключить сообщение из промпта",
|
||||||
"Include message in prompts": "Включить сообщение в подсказки",
|
"Include message in prompts": "Включить сообщение в промпт",
|
||||||
"Create checkpoint": "Создать чекпоинт",
|
"Create checkpoint": "Создать чекпоинт",
|
||||||
"Create Branch": "Создать ветку",
|
"Create Branch": "Создать ветку",
|
||||||
"Embed file or image": "Вставить файл или изображение",
|
"Embed file or image": "Вставить файл или изображение",
|
||||||
@ -1661,5 +1661,52 @@
|
|||||||
"ext_regex_ai_output_desc": "Сообщения, полученные от API",
|
"ext_regex_ai_output_desc": "Сообщения, полученные от API",
|
||||||
"ext_regex_sts_desc": "Сообщения, отправленные с помощью команд STscript",
|
"ext_regex_sts_desc": "Сообщения, отправленные с помощью команд STscript",
|
||||||
"ext_regex_wi_desc": "Содержимое лорбуков и миров. Для работы требует включения флажка \"Только промпт\"!",
|
"ext_regex_wi_desc": "Содержимое лорбуков и миров. Для работы требует включения флажка \"Только промпт\"!",
|
||||||
"ext_regex_only_format_display_desc": "История чата не изменится, замена будет осуществляться только в отображаемом сообщении (в UI)"
|
"ext_regex_only_format_display_desc": "История чата не изменится, замена будет осуществляться только в отображаемом сообщении (в UI)",
|
||||||
|
"Prefer Character Card Instructions": "Приоритет инструкциям из карточек",
|
||||||
|
"If checked and the character card contains a Post-History Instructions override, use that instead": "Если в карточке персонажа имеется собственная инструкция после истории, в промпт попадёт именно она",
|
||||||
|
"Auto-select Input Text": "Автовыделение вводимого текста",
|
||||||
|
"Enable auto-select of input text in some text fields when clicking/selecting them. Applies to popup input textboxes, and possible other custom input fields.": "Автоматически выделять вводимый текст в некоторых текстовых полях при клике/выборе. Работает для вспл. окон и различных кастомных полей ввода.",
|
||||||
|
"Reset MovingUI panel sizes/locations.": "Сбросить расположение и размеры панелей MovingUI.",
|
||||||
|
"mui_reset": "Сброс",
|
||||||
|
"Quick 'Impersonate' button": "Быстрое перевоплощение",
|
||||||
|
"Show a button in the input area to ask the AI to impersonate your character for a single message": "Показать в поле ввода кнопку, по нажатии на которую ИИ сгенерирует одно сообщение от лица вашего персонажа.",
|
||||||
|
"Separators as Stop Strings": "Разделители как стоп-строки",
|
||||||
|
"Names as Stop Strings": "Имена как стоп-строки",
|
||||||
|
"Add Character and User names to a list of stopping strings.": "Добавлять имена персонажа и пользователя в список стоп-строк.",
|
||||||
|
"Allow Post-History Instructions": "Разрешить инструкции после истории",
|
||||||
|
"context_allow_post_history_instructions": "Добавлять в конец промпта инструкции после истории. Работает только при наличии таких инструкций в карточке И при включенной опции ''Приоритет инструкциям из карточек''.\nНЕ РЕКОМЕНДУЕТСЯ ДЛЯ МОДЕЛЕЙ TEXT COMPLETION, МОЖЕТ ПОРТИТЬ ВЫХОДНОЙ ТЕКСТ.",
|
||||||
|
"First User Prefix": "Первый префикс пользователя",
|
||||||
|
"Inserted before the first User's message.": "Вставляется перед первым сообщением пользователя.",
|
||||||
|
"Last User Prefix": "Последний префикс пользователя",
|
||||||
|
"instruct_last_input_sequence": "Вставляется перед последним сообщением пользователя.",
|
||||||
|
"Inserted before a User message and as a last prompt line when impersonating.": "Вставляется перед сообщением пользователя в качестве последней строки промпта при перевоплощении.",
|
||||||
|
"Inserted before a System (added by slash commands or extensions) message.": "Вставляется перед сообщением системы (может быть добавлено слэш-командой или расширением).",
|
||||||
|
"Load Asset List": "Загрузить список ресурсов",
|
||||||
|
"Never add character names.": "Не вставлять имя персонажа.",
|
||||||
|
"Don't add character names unless necessary.": "Вставлять имя персонажа только когда это необходимо.",
|
||||||
|
"character_names_none": "Не добавлять имена персонажей в качестве префикса. Может повредить качеству ответов в групповых чатах, используйте с осторожностью.",
|
||||||
|
"Auxiliary": "Вспомогательный",
|
||||||
|
"Post-History Instructions": "Инструкции после истории",
|
||||||
|
"Current persona updated": "Текущая персона изменена",
|
||||||
|
"Your messages will now be sent as ${0}": "Ваши сообщения будут отправляться от лица ${0}",
|
||||||
|
"Copied!": "Скопировано!",
|
||||||
|
"Are you sure you want to delete this message?": "Вы точно хотите удалить это сообщение?",
|
||||||
|
"Delete Message": "Удалить сообщение",
|
||||||
|
"Delete Swipe": "Удалить свайп",
|
||||||
|
"Could not get a reply from API. Check your connection settings / API key and try again.": "Не удалось получить ответ от API. Проверьте настройки соединения и API-ключ и повторите попытку.",
|
||||||
|
"Connecting To Proxy": "Подключение к прокси",
|
||||||
|
"Are you sure you want to connect to the following proxy URL?": "Вы точно хотите соединиться с прокси по этому адресу?",
|
||||||
|
"API connection successful!": "Соединение с API установлено!",
|
||||||
|
"Proxy Saved": "Прокси сохранена",
|
||||||
|
"Proxy Deleted": "Прокси удалена",
|
||||||
|
"Could not find proxy with name '${0}'": "Не удалось найти прокси с названием '${0}'",
|
||||||
|
"Proxy preset '${0}' not found in proxies array.": "Пресет с названием '${0}' не найден в списке прокси.",
|
||||||
|
"Please wait for the previous request to complete.": "Пожалуйста, дождитесь окончания обработки предыдущего запроса.",
|
||||||
|
"Start new chat?": "Начать новый чат?",
|
||||||
|
"If necessary, you can later restore this chat file from the /backups folder": "При необходимости этот чат можно будет восстановить из папки /backups",
|
||||||
|
"Also delete the current chat file": "Также удалить текущий чат",
|
||||||
|
"chat_rename_1": "Введите новое имя чата:",
|
||||||
|
"chat_rename_2": "!!Не используйте имя уже существующего файла, это приведёт к ошибке!!",
|
||||||
|
"chat_rename_3": "Будут разрушены связи между чатами-чекпоинтами.",
|
||||||
|
"chat_rename_4": "Расширение '.jsonl' дописывать не нужно."
|
||||||
}
|
}
|
||||||
|
153
public/script.js
153
public/script.js
@ -488,14 +488,6 @@ let default_user_name = 'User';
|
|||||||
export let name1 = default_user_name;
|
export let name1 = default_user_name;
|
||||||
export let name2 = 'SillyTavern System';
|
export let name2 = 'SillyTavern System';
|
||||||
export let chat = [];
|
export let chat = [];
|
||||||
let safetychat = [
|
|
||||||
{
|
|
||||||
name: systemUserName,
|
|
||||||
is_user: false,
|
|
||||||
create_date: 0,
|
|
||||||
mes: 'You deleted a character/chat and arrived back here for safety reasons! Pick another character!',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
let chatSaveTimeout;
|
let chatSaveTimeout;
|
||||||
let importFlashTimeout;
|
let importFlashTimeout;
|
||||||
export let isChatSaving = false;
|
export let isChatSaving = false;
|
||||||
@ -594,6 +586,17 @@ export const extension_prompt_roles = {
|
|||||||
|
|
||||||
export const MAX_INJECTION_DEPTH = 1000;
|
export const MAX_INJECTION_DEPTH = 1000;
|
||||||
|
|
||||||
|
const SAFETY_CHAT = [
|
||||||
|
{
|
||||||
|
name: systemUserName,
|
||||||
|
force_avatar: system_avatar,
|
||||||
|
is_system: true,
|
||||||
|
is_user: false,
|
||||||
|
create_date: 0,
|
||||||
|
mes: 'You deleted a character/chat and arrived back here for safety reasons! Pick another character!',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export let system_messages = {};
|
export let system_messages = {};
|
||||||
|
|
||||||
async function getSystemMessages() {
|
async function getSystemMessages() {
|
||||||
@ -2192,7 +2195,7 @@ export function addCopyToCodeBlocks(messageElement) {
|
|||||||
codeBlocks.get(i).appendChild(copyButton);
|
codeBlocks.get(i).appendChild(copyButton);
|
||||||
copyButton.addEventListener('pointerup', function (event) {
|
copyButton.addEventListener('pointerup', function (event) {
|
||||||
navigator.clipboard.writeText(codeBlocks.get(i).innerText);
|
navigator.clipboard.writeText(codeBlocks.get(i).innerText);
|
||||||
toastr.info('Copied!', '', { timeOut: 2000 });
|
toastr.info(t`Copied!`, '', { timeOut: 2000 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2705,7 +2708,7 @@ function addPersonaDescriptionExtensionPrompt() {
|
|||||||
const INJECT_TAG = 'PERSONA_DESCRIPTION';
|
const INJECT_TAG = 'PERSONA_DESCRIPTION';
|
||||||
setExtensionPrompt(INJECT_TAG, '', extension_prompt_types.IN_PROMPT, 0);
|
setExtensionPrompt(INJECT_TAG, '', extension_prompt_types.IN_PROMPT, 0);
|
||||||
|
|
||||||
if (!power_user.persona_description) {
|
if (!power_user.persona_description || power_user.persona_description_position === persona_description_positions.NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2826,7 +2829,7 @@ export function getCharacterCardFields() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isStreamingEnabled() {
|
export function isStreamingEnabled() {
|
||||||
const noStreamSources = [chat_completion_sources.SCALE, chat_completion_sources.AI21];
|
const noStreamSources = [chat_completion_sources.SCALE];
|
||||||
return ((main_api == 'openai' && oai_settings.stream_openai && !noStreamSources.includes(oai_settings.chat_completion_source) && !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison')))
|
return ((main_api == 'openai' && oai_settings.stream_openai && !noStreamSources.includes(oai_settings.chat_completion_source) && !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison')))
|
||||||
|| (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)
|
|| (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)
|
||||||
|| (main_api == 'novel' && nai_settings.streaming_novel)
|
|| (main_api == 'novel' && nai_settings.streaming_novel)
|
||||||
@ -3726,7 +3729,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
const storyStringParams = {
|
const storyStringParams = {
|
||||||
description: description,
|
description: description,
|
||||||
personality: personality,
|
personality: personality,
|
||||||
persona: persona,
|
persona: power_user.persona_description_position == persona_description_positions.IN_PROMPT ? persona : '',
|
||||||
scenario: scenario,
|
scenario: scenario,
|
||||||
system: isInstruct ? system : '',
|
system: isInstruct ? system : '',
|
||||||
char: name2,
|
char: name2,
|
||||||
@ -3760,7 +3763,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
let examplesString = '';
|
let examplesString = '';
|
||||||
let chatString = '';
|
let chatString = addChatsPreamble(addChatsSeparator(''));
|
||||||
let cyclePrompt = '';
|
let cyclePrompt = '';
|
||||||
|
|
||||||
async function getMessagesTokenCount() {
|
async function getMessagesTokenCount() {
|
||||||
@ -3769,10 +3772,10 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
storyString,
|
storyString,
|
||||||
afterScenarioAnchor,
|
afterScenarioAnchor,
|
||||||
examplesString,
|
examplesString,
|
||||||
chatString,
|
|
||||||
quiet_prompt,
|
|
||||||
cyclePrompt,
|
|
||||||
userAlignmentMessage,
|
userAlignmentMessage,
|
||||||
|
chatString,
|
||||||
|
modifyLastPromptLine(''),
|
||||||
|
cyclePrompt,
|
||||||
].join('').replace(/\r/gm, '');
|
].join('').replace(/\r/gm, '');
|
||||||
return getTokenCountAsync(encodeString, power_user.token_padding);
|
return getTokenCountAsync(encodeString, power_user.token_padding);
|
||||||
}
|
}
|
||||||
@ -3803,8 +3806,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
tokenCount += await getTokenCountAsync(item.replace(/\r/gm, ''));
|
tokenCount += await getTokenCountAsync(item.replace(/\r/gm, ''));
|
||||||
chatString = item + chatString;
|
|
||||||
if (tokenCount < this_max_context) {
|
if (tokenCount < this_max_context) {
|
||||||
|
chatString = chatString + item;
|
||||||
arrMes[index] = item;
|
arrMes[index] = item;
|
||||||
lastAddedIndex = Math.max(lastAddedIndex, index);
|
lastAddedIndex = Math.max(lastAddedIndex, index);
|
||||||
} else {
|
} else {
|
||||||
@ -3830,8 +3833,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
tokenCount += await getTokenCountAsync(item.replace(/\r/gm, ''));
|
tokenCount += await getTokenCountAsync(item.replace(/\r/gm, ''));
|
||||||
chatString = item + chatString;
|
|
||||||
if (tokenCount < this_max_context) {
|
if (tokenCount < this_max_context) {
|
||||||
|
chatString = chatString + item;
|
||||||
arrMes[i] = item;
|
arrMes[i] = item;
|
||||||
lastAddedIndex = Math.max(lastAddedIndex, i);
|
lastAddedIndex = Math.max(lastAddedIndex, i);
|
||||||
} else {
|
} else {
|
||||||
@ -4028,15 +4031,16 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
async function checkPromptSize() {
|
async function checkPromptSize() {
|
||||||
console.debug('---checking Prompt size');
|
console.debug('---checking Prompt size');
|
||||||
setPromptString();
|
setPromptString();
|
||||||
|
const jointMessages = mesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join('');
|
||||||
const prompt = [
|
const prompt = [
|
||||||
beforeScenarioAnchor,
|
beforeScenarioAnchor,
|
||||||
storyString,
|
storyString,
|
||||||
afterScenarioAnchor,
|
afterScenarioAnchor,
|
||||||
mesExmString,
|
mesExmString,
|
||||||
mesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join(''),
|
addChatsPreamble(addChatsSeparator(jointMessages)),
|
||||||
'\n',
|
'\n',
|
||||||
|
modifyLastPromptLine(''),
|
||||||
generatedPromptCache,
|
generatedPromptCache,
|
||||||
quiet_prompt,
|
|
||||||
].join('').replace(/\r/gm, '');
|
].join('').replace(/\r/gm, '');
|
||||||
let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding);
|
let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding);
|
||||||
|
|
||||||
@ -4302,7 +4306,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
padding: power_user.token_padding,
|
padding: power_user.token_padding,
|
||||||
main_api: main_api,
|
main_api: main_api,
|
||||||
instruction: isInstruct ? substituteParams(power_user.prefer_character_prompt && system ? system : power_user.instruct.system_prompt) : '',
|
instruction: isInstruct ? substituteParams(power_user.prefer_character_prompt && system ? system : power_user.instruct.system_prompt) : '',
|
||||||
userPersona: (power_user.persona_description || ''),
|
userPersona: (power_user.persona_description_position == persona_description_positions.IN_PROMPT ? (persona || '') : ''),
|
||||||
};
|
};
|
||||||
|
|
||||||
//console.log(additionalPromptStuff);
|
//console.log(additionalPromptStuff);
|
||||||
@ -5080,7 +5084,7 @@ async function promptItemize(itemizedPrompts, requestedMesId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
navigator.clipboard.writeText(rawPromptValues);
|
navigator.clipboard.writeText(rawPromptValues);
|
||||||
toastr.info('Copied!');
|
toastr.info(t`Copied!`);
|
||||||
});
|
});
|
||||||
|
|
||||||
popup.dlg.querySelector('#showRawPrompt').addEventListener('click', function () {
|
popup.dlg.querySelector('#showRawPrompt').addEventListener('click', function () {
|
||||||
@ -5679,7 +5683,7 @@ export function resetChatState() {
|
|||||||
// replaces deleted charcter name with system user since it will be displayed next.
|
// replaces deleted charcter name with system user since it will be displayed next.
|
||||||
name2 = systemUserName;
|
name2 = systemUserName;
|
||||||
// sets up system user to tell user about having deleted a character
|
// sets up system user to tell user about having deleted a character
|
||||||
chat = [...safetychat];
|
chat.splice(0, chat.length, ...SAFETY_CHAT);
|
||||||
// resets chat metadata
|
// resets chat metadata
|
||||||
chat_metadata = {};
|
chat_metadata = {};
|
||||||
// resets the characters array, forcing getcharacters to reset
|
// resets the characters array, forcing getcharacters to reset
|
||||||
@ -6310,7 +6314,7 @@ export function setUserName(value) {
|
|||||||
console.log(`User name changed to ${name1}`);
|
console.log(`User name changed to ${name1}`);
|
||||||
$('#your_name').val(name1);
|
$('#your_name').val(name1);
|
||||||
if (power_user.persona_show_notifications) {
|
if (power_user.persona_show_notifications) {
|
||||||
toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
|
toastr.success(t`Your messages will now be sent as ${name1}`, t`Current persona updated`);
|
||||||
}
|
}
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
@ -8840,72 +8844,74 @@ export async function handleDeleteCharacter(this_chid, delete_chats) {
|
|||||||
/**
|
/**
|
||||||
* Deletes a character completely, including associated chats if specified
|
* Deletes a character completely, including associated chats if specified
|
||||||
*
|
*
|
||||||
* @param {string} characterKey - The key (avatar) of the character to be deleted
|
* @param {string|string[]} characterKey - The key (avatar) of the character to be deleted
|
||||||
* @param {Object} [options] - Optional parameters for the deletion
|
* @param {Object} [options] - Optional parameters for the deletion
|
||||||
* @param {boolean} [options.deleteChats=true] - Whether to delete associated chats or not
|
* @param {boolean} [options.deleteChats=true] - Whether to delete associated chats or not
|
||||||
* @return {Promise<void>} - A promise that resolves when the character is successfully deleted
|
* @return {Promise<void>} - A promise that resolves when the character is successfully deleted
|
||||||
*/
|
*/
|
||||||
export async function deleteCharacter(characterKey, { deleteChats = true } = {}) {
|
export async function deleteCharacter(characterKey, { deleteChats = true } = {}) {
|
||||||
const character = characters.find(x => x.avatar == characterKey);
|
if (!Array.isArray(characterKey)) {
|
||||||
if (!character) {
|
characterKey = [characterKey];
|
||||||
toastr.warning(`Character ${characterKey} not found. Cannot be deleted.`);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const chid = characters.indexOf(character);
|
for (const key of characterKey) {
|
||||||
const pastChats = await getPastCharacterChats(chid);
|
const character = characters.find(x => x.avatar == key);
|
||||||
|
if (!character) {
|
||||||
const msg = { avatar_url: character.avatar, delete_chats: deleteChats };
|
toastr.warning(`Character ${key} not found. Skipping deletion.`);
|
||||||
|
continue;
|
||||||
const response = await fetch('/api/characters/delete', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: getRequestHeaders(),
|
|
||||||
body: JSON.stringify(msg),
|
|
||||||
cache: 'no-cache',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Failed to delete character: ${response.status} ${response.statusText}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
await removeCharacterFromUI(character.name, character.avatar);
|
|
||||||
|
|
||||||
if (deleteChats) {
|
|
||||||
for (const chat of pastChats) {
|
|
||||||
const name = chat.file_name.replace('.jsonl', '');
|
|
||||||
await eventSource.emit(event_types.CHAT_DELETED, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chid = characters.indexOf(character);
|
||||||
|
const pastChats = await getPastCharacterChats(chid);
|
||||||
|
|
||||||
|
const msg = { avatar_url: character.avatar, delete_chats: deleteChats };
|
||||||
|
|
||||||
|
const response = await fetch('/api/characters/delete', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: getRequestHeaders(),
|
||||||
|
body: JSON.stringify(msg),
|
||||||
|
cache: 'no-cache',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
toastr.error(`${response.status} ${response.statusText}`, 'Failed to delete character');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete tag_map[character.avatar];
|
||||||
|
select_rm_info('char_delete', character.name);
|
||||||
|
|
||||||
|
if (deleteChats) {
|
||||||
|
for (const chat of pastChats) {
|
||||||
|
const name = chat.file_name.replace('.jsonl', '');
|
||||||
|
await eventSource.emit(event_types.CHAT_DELETED, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await eventSource.emit(event_types.CHARACTER_DELETED, { id: chid, character: character });
|
||||||
}
|
}
|
||||||
|
|
||||||
eventSource.emit(event_types.CHARACTER_DELETED, { id: this_chid, character: characters[this_chid] });
|
await removeCharacterFromUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to delete a character from UI after character deletion API success.
|
* Function to delete a character from UI after character deletion API success.
|
||||||
* It manages necessary UI changes such as closing advanced editing popup, unsetting
|
* It manages necessary UI changes such as closing advanced editing popup, unsetting
|
||||||
* character ID, resetting characters array and chat metadata, deselecting character's tab
|
* character ID, resetting characters array and chat metadata, deselecting character's tab
|
||||||
* panel, removing character name from navigation tabs, clearing chat, removing character's
|
* panel, removing character name from navigation tabs, clearing chat, fetching updated list of characters.
|
||||||
* avatar from tag_map, fetching updated list of characters and updating the 'deleted
|
|
||||||
* character' message.
|
|
||||||
* It also ensures to save the settings after all the operations.
|
* It also ensures to save the settings after all the operations.
|
||||||
*
|
|
||||||
* @param {string} name - The name of the character to be deleted.
|
|
||||||
* @param {string} avatar - The avatar URL of the character to be deleted.
|
|
||||||
* @param {boolean} reloadCharacters - Whether the character list should be refreshed after deletion.
|
|
||||||
*/
|
*/
|
||||||
async function removeCharacterFromUI(name, avatar, reloadCharacters = true) {
|
async function removeCharacterFromUI() {
|
||||||
await clearChat();
|
await clearChat();
|
||||||
$('#character_cross').click();
|
$('#character_cross').click();
|
||||||
this_chid = undefined;
|
this_chid = undefined;
|
||||||
characters.length = 0;
|
characters.length = 0;
|
||||||
name2 = systemUserName;
|
name2 = systemUserName;
|
||||||
chat = [...safetychat];
|
chat.splice(0, chat.length, ...SAFETY_CHAT);
|
||||||
chat_metadata = {};
|
chat_metadata = {};
|
||||||
$(document.getElementById('rm_button_selected_ch')).children('h2').text('');
|
$(document.getElementById('rm_button_selected_ch')).children('h2').text('');
|
||||||
this_chid = undefined;
|
this_chid = undefined;
|
||||||
delete tag_map[avatar];
|
await getCharacters();
|
||||||
if (reloadCharacters) await getCharacters();
|
|
||||||
select_rm_info('char_delete', name);
|
|
||||||
await printMessages();
|
await printMessages();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
@ -9532,11 +9538,7 @@ jQuery(async function () {
|
|||||||
const oldFileNameFull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text();
|
const oldFileNameFull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text();
|
||||||
const oldFileName = oldFileNameFull.replace('.jsonl', '');
|
const oldFileName = oldFileNameFull.replace('.jsonl', '');
|
||||||
|
|
||||||
const popupText = `<h3>Enter the new name for the chat:<h3>
|
const popupText = await renderTemplateAsync('chatRename');
|
||||||
<small>!!Using an existing filename will produce an error!!<br>
|
|
||||||
This will break the link between checkpoint chats.<br>
|
|
||||||
No need to add '.jsonl' at the end.<br>
|
|
||||||
</small>`;
|
|
||||||
const newName = await callPopup(popupText, 'input', oldFileName);
|
const newName = await callPopup(popupText, 'input', oldFileName);
|
||||||
|
|
||||||
if (!newName || newName == oldFileName) {
|
if (!newName || newName == oldFileName) {
|
||||||
@ -9744,12 +9746,7 @@ jQuery(async function () {
|
|||||||
else if (id == 'option_start_new_chat') {
|
else if (id == 'option_start_new_chat') {
|
||||||
if ((selected_group || this_chid !== undefined) && !is_send_press) {
|
if ((selected_group || this_chid !== undefined) && !is_send_press) {
|
||||||
let deleteCurrentChat = false;
|
let deleteCurrentChat = false;
|
||||||
const result = await Popup.show.confirm('Start new chat?', `
|
const result = await Popup.show.confirm(t`Start new chat?`, await renderTemplateAsync('newChatConfirm'), {
|
||||||
<label for="del_chat_checkbox" class="checkbox_label justifyCenter"
|
|
||||||
title="If necessary, you can later restore this chat file from the /backups folder">
|
|
||||||
<input type="checkbox" id="del_chat_checkbox" />
|
|
||||||
<small>Also delete the current chat file</small>
|
|
||||||
</label>`, {
|
|
||||||
onClose: () => deleteCurrentChat = !!$('#del_chat_checkbox').prop('checked'),
|
onClose: () => deleteCurrentChat = !!$('#del_chat_checkbox').prop('checked'),
|
||||||
});
|
});
|
||||||
if (!result) {
|
if (!result) {
|
||||||
@ -10261,10 +10258,10 @@ jQuery(async function () {
|
|||||||
|
|
||||||
let deleteOnlySwipe = false;
|
let deleteOnlySwipe = false;
|
||||||
if (power_user.confirm_message_delete && fromSlashCommand !== true) {
|
if (power_user.confirm_message_delete && fromSlashCommand !== true) {
|
||||||
const result = await callGenericPopup('Are you sure you want to delete this message?', POPUP_TYPE.CONFIRM, null, {
|
const result = await callGenericPopup(t`Are you sure you want to delete this message?`, POPUP_TYPE.CONFIRM, null, {
|
||||||
okButton: canDeleteSwipe ? 'Delete Swipe' : 'Delete Message',
|
okButton: canDeleteSwipe ? t`Delete Swipe` : t`Delete Message`,
|
||||||
cancelButton: 'Cancel',
|
cancelButton: 'Cancel',
|
||||||
customButtons: canDeleteSwipe ? ['Delete Message'] : null,
|
customButtons: canDeleteSwipe ? [t`Delete Message`] : null,
|
||||||
});
|
});
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
|
@ -108,14 +108,12 @@ class CharacterContextMenu {
|
|||||||
* Delete one or more characters,
|
* Delete one or more characters,
|
||||||
* opens a popup.
|
* opens a popup.
|
||||||
*
|
*
|
||||||
* @param {number} characterId
|
* @param {string|string[]} characterKey
|
||||||
* @param {boolean} [deleteChats]
|
* @param {boolean} [deleteChats]
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
static delete = async (characterId, deleteChats = false) => {
|
static delete = async (characterKey, deleteChats = false) => {
|
||||||
const character = CharacterContextMenu.#getCharacter(characterId);
|
await deleteCharacter(characterKey, { deleteChats: deleteChats });
|
||||||
|
|
||||||
await deleteCharacter(character.avatar, { deleteChats: deleteChats });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static #getCharacter = (characterId) => characters[characterId] ?? null;
|
static #getCharacter = (characterId) => characters[characterId] ?? null;
|
||||||
@ -344,7 +342,7 @@ class BulkTagPopupHandler {
|
|||||||
const mutualTags = this.getMutualTags();
|
const mutualTags = this.getMutualTags();
|
||||||
|
|
||||||
for (const characterId of this.characterIds) {
|
for (const characterId of this.characterIds) {
|
||||||
for(const tag of mutualTags) {
|
for (const tag of mutualTags) {
|
||||||
removeTagFromMap(tag.id, characterId);
|
removeTagFromMap(tag.id, characterId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -599,8 +597,7 @@ class BulkEditOverlay {
|
|||||||
|
|
||||||
this.container.removeEventListener('mouseup', cancelHold);
|
this.container.removeEventListener('mouseup', cancelHold);
|
||||||
this.container.removeEventListener('touchend', cancelHold);
|
this.container.removeEventListener('touchend', cancelHold);
|
||||||
},
|
}, BulkEditOverlay.longPressDelay);
|
||||||
BulkEditOverlay.longPressDelay);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleLongPressEnd = (event) => {
|
handleLongPressEnd = (event) => {
|
||||||
@ -847,11 +844,14 @@ class BulkEditOverlay {
|
|||||||
const deleteChats = document.getElementById('del_char_checkbox').checked ?? false;
|
const deleteChats = document.getElementById('del_char_checkbox').checked ?? false;
|
||||||
|
|
||||||
showLoader();
|
showLoader();
|
||||||
toastr.info('We\'re deleting your characters, please wait...', 'Working on it');
|
const toast = toastr.info('We\'re deleting your characters, please wait...', 'Working on it');
|
||||||
return Promise.allSettled(characterIds.map(async characterId => CharacterContextMenu.delete(characterId, deleteChats)))
|
const avatarList = characterIds.map(id => characters[id]?.avatar).filter(a => a);
|
||||||
.then(() => getCharacters())
|
return CharacterContextMenu.delete(avatarList, deleteChats)
|
||||||
.then(() => this.browseState())
|
.then(() => this.browseState())
|
||||||
.finally(() => hideLoader());
|
.finally(() => {
|
||||||
|
toastr.clear(toast);
|
||||||
|
hideLoader();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// At this moment the popup is already changed in the dom, but not yet closed/resolved. We build the avatar list here
|
// At this moment the popup is already changed in the dom, but not yet closed/resolved. We build the avatar list here
|
||||||
|
@ -45,8 +45,11 @@
|
|||||||
<option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
<option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option>
|
||||||
<option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option>
|
<option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option>
|
||||||
<option data-type="google" value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
|
<option data-type="google" value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option>
|
||||||
|
<option data-type="google" value="gemini-1.5-flash-exp-0827">gemini-1.5-flash-exp-0827</option>
|
||||||
|
<option data-type="google" value="gemini-1.5-flash-8b-exp-0827">gemini-1.5-flash-8b-exp-0827</option>
|
||||||
<option data-type="google" value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option>
|
<option data-type="google" value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option>
|
||||||
<option data-type="google" value="gemini-1.5-pro-exp-0801">gemini-1.5-pro-exp-0801</option>
|
<option data-type="google" value="gemini-1.5-pro-exp-0801">gemini-1.5-pro-exp-0801</option>
|
||||||
|
<option data-type="google" value="gemini-1.5-pro-exp-0827">gemini-1.5-pro-exp-0827</option>
|
||||||
<option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option>
|
<option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option>
|
||||||
<option data-type="openrouter" value="openai/gpt-4o">openai/gpt-4o</option>
|
<option data-type="openrouter" value="openai/gpt-4o">openai/gpt-4o</option>
|
||||||
<option data-type="openrouter" value="openai/gpt-4-turbo">openai/gpt-4-turbo</option>
|
<option data-type="openrouter" value="openai/gpt-4-turbo">openai/gpt-4-turbo</option>
|
||||||
|
@ -421,7 +421,7 @@ function completeTtsJob() {
|
|||||||
async function tts(text, voiceId, char) {
|
async function tts(text, voiceId, char) {
|
||||||
async function processResponse(response) {
|
async function processResponse(response) {
|
||||||
// RVC injection
|
// RVC injection
|
||||||
if (extension_settings.rvc.enabled && typeof window['rvcVoiceConversion'] === 'function')
|
if (typeof window['rvcVoiceConversion'] === 'function' && extension_settings.rvc.enabled)
|
||||||
response = await window['rvcVoiceConversion'](response, char, text);
|
response = await window['rvcVoiceConversion'](response, char, text);
|
||||||
|
|
||||||
await addAudioJob(response, char);
|
await addAudioJob(response, char);
|
||||||
|
@ -78,6 +78,19 @@ export function getKayraMaxContextTokens() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getKayraMaxResponseTokens() {
|
||||||
|
switch (novel_data?.tier) {
|
||||||
|
case 1:
|
||||||
|
return 100;
|
||||||
|
case 2:
|
||||||
|
return 100;
|
||||||
|
case 3:
|
||||||
|
return 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maximum_output_length;
|
||||||
|
}
|
||||||
|
|
||||||
export function getNovelTier() {
|
export function getNovelTier() {
|
||||||
return nai_tiers[novel_data?.tier] ?? 'no_connection';
|
return nai_tiers[novel_data?.tier] ?? 'no_connection';
|
||||||
}
|
}
|
||||||
@ -438,12 +451,14 @@ export function getNovelGenerationData(finalPrompt, settings, maxLength, isImper
|
|||||||
console.log(finalPrompt);
|
console.log(finalPrompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const adjustedMaxLength = nai_settings.model_novel.includes('kayra') ? getKayraMaxResponseTokens() : maximum_output_length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'input': finalPrompt,
|
'input': finalPrompt,
|
||||||
'model': nai_settings.model_novel,
|
'model': nai_settings.model_novel,
|
||||||
'use_string': true,
|
'use_string': true,
|
||||||
'temperature': Number(nai_settings.temperature),
|
'temperature': Number(nai_settings.temperature),
|
||||||
'max_length': maxLength < maximum_output_length ? maxLength : maximum_output_length,
|
'max_length': maxLength < adjustedMaxLength ? maxLength : adjustedMaxLength,
|
||||||
'min_length': Number(nai_settings.min_length),
|
'min_length': Number(nai_settings.min_length),
|
||||||
'tail_free_sampling': Number(nai_settings.tail_free_sampling),
|
'tail_free_sampling': Number(nai_settings.tail_free_sampling),
|
||||||
'repetition_penalty': Number(nai_settings.repetition_penalty),
|
'repetition_penalty': Number(nai_settings.repetition_penalty),
|
||||||
|
@ -74,6 +74,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashComma
|
|||||||
import { renderTemplateAsync } from './templates.js';
|
import { renderTemplateAsync } from './templates.js';
|
||||||
import { SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';
|
import { SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';
|
||||||
import { Popup, POPUP_RESULT } from './popup.js';
|
import { Popup, POPUP_RESULT } from './popup.js';
|
||||||
|
import { t } from './i18n.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
openai_messages_count,
|
openai_messages_count,
|
||||||
@ -132,13 +133,9 @@ const max_2mil = 2000 * 1000;
|
|||||||
const scale_max = 8191;
|
const scale_max = 8191;
|
||||||
const claude_max = 9000; // We have a proper tokenizer, so theoretically could be larger (up to 9k)
|
const claude_max = 9000; // We have a proper tokenizer, so theoretically could be larger (up to 9k)
|
||||||
const claude_100k_max = 99000;
|
const claude_100k_max = 99000;
|
||||||
let ai21_max = 9200; //can easily fit 9k gpt tokens because j2's tokenizer is efficient af
|
const unlocked_max = max_2mil;
|
||||||
const unlocked_max = max_200k;
|
|
||||||
const oai_max_temp = 2.0;
|
const oai_max_temp = 2.0;
|
||||||
const claude_max_temp = 1.0; //same as j2
|
const claude_max_temp = 1.0;
|
||||||
const j2_max_topk = 10.0;
|
|
||||||
const j2_max_freq = 5.0;
|
|
||||||
const j2_max_pres = 5.0;
|
|
||||||
const openrouter_website_model = 'OR_Website';
|
const openrouter_website_model = 'OR_Website';
|
||||||
const openai_max_stop_strings = 4;
|
const openai_max_stop_strings = 4;
|
||||||
|
|
||||||
@ -218,25 +215,11 @@ const sensitiveFields = [
|
|||||||
'custom_include_headers',
|
'custom_include_headers',
|
||||||
];
|
];
|
||||||
|
|
||||||
function getPrefixMap() {
|
|
||||||
return selected_group ? {
|
|
||||||
assistant: '',
|
|
||||||
user: '',
|
|
||||||
system: 'OOC: ',
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
assistant: '{{char}}:',
|
|
||||||
user: '{{user}}:',
|
|
||||||
system: '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const default_settings = {
|
const default_settings = {
|
||||||
preset_settings_openai: 'Default',
|
preset_settings_openai: 'Default',
|
||||||
temp_openai: 1.0,
|
temp_openai: 1.0,
|
||||||
freq_pen_openai: 0,
|
freq_pen_openai: 0,
|
||||||
pres_pen_openai: 0,
|
pres_pen_openai: 0,
|
||||||
count_pen: 0.0,
|
|
||||||
top_p_openai: 1.0,
|
top_p_openai: 1.0,
|
||||||
top_k_openai: 0,
|
top_k_openai: 0,
|
||||||
min_p_openai: 0,
|
min_p_openai: 0,
|
||||||
@ -264,7 +247,7 @@ const default_settings = {
|
|||||||
openai_model: 'gpt-4-turbo',
|
openai_model: 'gpt-4-turbo',
|
||||||
claude_model: 'claude-3-5-sonnet-20240620',
|
claude_model: 'claude-3-5-sonnet-20240620',
|
||||||
google_model: 'gemini-1.5-pro',
|
google_model: 'gemini-1.5-pro',
|
||||||
ai21_model: 'j2-ultra',
|
ai21_model: 'jamba-1.5-large',
|
||||||
mistralai_model: 'mistral-large-latest',
|
mistralai_model: 'mistral-large-latest',
|
||||||
cohere_model: 'command-r-plus',
|
cohere_model: 'command-r-plus',
|
||||||
perplexity_model: 'llama-3.1-70b-instruct',
|
perplexity_model: 'llama-3.1-70b-instruct',
|
||||||
@ -294,8 +277,6 @@ const default_settings = {
|
|||||||
assistant_prefill: '',
|
assistant_prefill: '',
|
||||||
assistant_impersonation: '',
|
assistant_impersonation: '',
|
||||||
human_sysprompt_message: default_claude_human_sysprompt_message,
|
human_sysprompt_message: default_claude_human_sysprompt_message,
|
||||||
use_ai21_tokenizer: false,
|
|
||||||
use_google_tokenizer: false,
|
|
||||||
claude_use_sysprompt: false,
|
claude_use_sysprompt: false,
|
||||||
use_makersuite_sysprompt: true,
|
use_makersuite_sysprompt: true,
|
||||||
use_alt_scale: false,
|
use_alt_scale: false,
|
||||||
@ -317,7 +298,6 @@ const oai_settings = {
|
|||||||
temp_openai: 1.0,
|
temp_openai: 1.0,
|
||||||
freq_pen_openai: 0,
|
freq_pen_openai: 0,
|
||||||
pres_pen_openai: 0,
|
pres_pen_openai: 0,
|
||||||
count_pen: 0.0,
|
|
||||||
top_p_openai: 1.0,
|
top_p_openai: 1.0,
|
||||||
top_k_openai: 0,
|
top_k_openai: 0,
|
||||||
min_p_openai: 0,
|
min_p_openai: 0,
|
||||||
@ -345,7 +325,7 @@ const oai_settings = {
|
|||||||
openai_model: 'gpt-4-turbo',
|
openai_model: 'gpt-4-turbo',
|
||||||
claude_model: 'claude-3-5-sonnet-20240620',
|
claude_model: 'claude-3-5-sonnet-20240620',
|
||||||
google_model: 'gemini-1.5-pro',
|
google_model: 'gemini-1.5-pro',
|
||||||
ai21_model: 'j2-ultra',
|
ai21_model: 'jamba-1.5-large',
|
||||||
mistralai_model: 'mistral-large-latest',
|
mistralai_model: 'mistral-large-latest',
|
||||||
cohere_model: 'command-r-plus',
|
cohere_model: 'command-r-plus',
|
||||||
perplexity_model: 'llama-3.1-70b-instruct',
|
perplexity_model: 'llama-3.1-70b-instruct',
|
||||||
@ -375,8 +355,6 @@ const oai_settings = {
|
|||||||
assistant_prefill: '',
|
assistant_prefill: '',
|
||||||
assistant_impersonation: '',
|
assistant_impersonation: '',
|
||||||
human_sysprompt_message: default_claude_human_sysprompt_message,
|
human_sysprompt_message: default_claude_human_sysprompt_message,
|
||||||
use_ai21_tokenizer: false,
|
|
||||||
use_google_tokenizer: false,
|
|
||||||
claude_use_sysprompt: false,
|
claude_use_sysprompt: false,
|
||||||
use_makersuite_sysprompt: true,
|
use_makersuite_sysprompt: true,
|
||||||
use_alt_scale: false,
|
use_alt_scale: false,
|
||||||
@ -425,7 +403,7 @@ async function validateReverseProxy() {
|
|||||||
const rememberKey = `Proxy_SkipConfirm_${getStringHash(oai_settings.reverse_proxy)}`;
|
const rememberKey = `Proxy_SkipConfirm_${getStringHash(oai_settings.reverse_proxy)}`;
|
||||||
const skipConfirm = localStorage.getItem(rememberKey) === 'true';
|
const skipConfirm = localStorage.getItem(rememberKey) === 'true';
|
||||||
|
|
||||||
const confirmation = skipConfirm || await Popup.show.confirm('Connecting To Proxy', `<span>Are you sure you want to connect to the following proxy URL?</span><var>${DOMPurify.sanitize(oai_settings.reverse_proxy)}</var>`);
|
const confirmation = skipConfirm || await Popup.show.confirm(t`Connecting To Proxy`, await renderTemplateAsync('proxyConnectionWarning', { proxyURL: DOMPurify.sanitize(oai_settings.reverse_proxy) }));
|
||||||
|
|
||||||
if (!confirmation) {
|
if (!confirmation) {
|
||||||
toastr.error('Update or remove your reverse proxy settings.');
|
toastr.error('Update or remove your reverse proxy settings.');
|
||||||
@ -1148,7 +1126,6 @@ function preparePromptsForChatCompletion({ Scenario, charPersonality, name2, wor
|
|||||||
{ role: 'system', content: charDescription, identifier: 'charDescription' },
|
{ role: 'system', content: charDescription, identifier: 'charDescription' },
|
||||||
{ role: 'system', content: charPersonalityText, identifier: 'charPersonality' },
|
{ role: 'system', content: charPersonalityText, identifier: 'charPersonality' },
|
||||||
{ role: 'system', content: scenarioText, identifier: 'scenario' },
|
{ role: 'system', content: scenarioText, identifier: 'scenario' },
|
||||||
{ role: 'system', content: personaDescription, identifier: 'personaDescription' },
|
|
||||||
// Unordered prompts without marker
|
// Unordered prompts without marker
|
||||||
{ role: 'system', content: impersonationPrompt, identifier: 'impersonate' },
|
{ role: 'system', content: impersonationPrompt, identifier: 'impersonate' },
|
||||||
{ role: 'system', content: quietPrompt, identifier: 'quietPrompt' },
|
{ role: 'system', content: quietPrompt, identifier: 'quietPrompt' },
|
||||||
@ -1395,6 +1372,11 @@ function tryParseStreamingError(response, decoded) {
|
|||||||
toastr.error(data.error.message || response.statusText, 'Chat Completion API');
|
toastr.error(data.error.message || response.statusText, 'Chat Completion API');
|
||||||
throw new Error(data);
|
throw new Error(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.message) {
|
||||||
|
toastr.error(data.message, 'Chat Completion API');
|
||||||
|
throw new Error(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
// No JSON. Do nothing.
|
// No JSON. Do nothing.
|
||||||
@ -1802,7 +1784,6 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|||||||
const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE;
|
const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE;
|
||||||
const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER;
|
const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER;
|
||||||
const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE;
|
const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE;
|
||||||
const isAI21 = oai_settings.chat_completion_source == chat_completion_sources.AI21;
|
|
||||||
const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE;
|
const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE;
|
||||||
const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI;
|
const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI;
|
||||||
const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI;
|
const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI;
|
||||||
@ -1815,7 +1796,7 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|||||||
const isQuiet = type === 'quiet';
|
const isQuiet = type === 'quiet';
|
||||||
const isImpersonate = type === 'impersonate';
|
const isImpersonate = type === 'impersonate';
|
||||||
const isContinue = type === 'continue';
|
const isContinue = type === 'continue';
|
||||||
const stream = oai_settings.stream_openai && !isQuiet && !isScale && !isAI21 && !(isGoogle && oai_settings.google_model.includes('bison'));
|
const stream = oai_settings.stream_openai && !isQuiet && !isScale && !(isGoogle && oai_settings.google_model.includes('bison'));
|
||||||
const useLogprobs = !!power_user.request_token_probabilities;
|
const useLogprobs = !!power_user.request_token_probabilities;
|
||||||
const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom);
|
const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom);
|
||||||
|
|
||||||
@ -1824,15 +1805,6 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|||||||
replaceItemizedPromptText(messageId, messages);
|
replaceItemizedPromptText(messageId, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAI21) {
|
|
||||||
const joinedMsgs = messages.reduce((acc, obj) => {
|
|
||||||
const prefix = getPrefixMap()[obj.role];
|
|
||||||
return acc + (prefix ? (selected_group ? '\n' : prefix + ' ') : '') + obj.content + '\n';
|
|
||||||
}, '');
|
|
||||||
messages = substituteParams(joinedMsgs) + (isImpersonate ? `${name1}:` : `${name2}:`);
|
|
||||||
replaceItemizedPromptText(messageId, messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're using the window.ai extension, use that instead
|
// If we're using the window.ai extension, use that instead
|
||||||
// Doesn't support logit bias yet
|
// Doesn't support logit bias yet
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) {
|
||||||
@ -1931,12 +1903,6 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|||||||
generate_data['use_makersuite_sysprompt'] = oai_settings.use_makersuite_sysprompt;
|
generate_data['use_makersuite_sysprompt'] = oai_settings.use_makersuite_sysprompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAI21) {
|
|
||||||
generate_data['top_k'] = Number(oai_settings.top_k_openai);
|
|
||||||
generate_data['count_pen'] = Number(oai_settings.count_pen);
|
|
||||||
generate_data['stop_tokens'] = [name1 + ':', substituteParams(oai_settings.new_chat_prompt), substituteParams(oai_settings.new_group_chat_prompt)];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMistral) {
|
if (isMistral) {
|
||||||
generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future.
|
generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future.
|
||||||
}
|
}
|
||||||
@ -3008,7 +2974,6 @@ function loadOpenAISettings(data, settings) {
|
|||||||
oai_settings.temp_openai = settings.temp_openai ?? default_settings.temp_openai;
|
oai_settings.temp_openai = settings.temp_openai ?? default_settings.temp_openai;
|
||||||
oai_settings.freq_pen_openai = settings.freq_pen_openai ?? default_settings.freq_pen_openai;
|
oai_settings.freq_pen_openai = settings.freq_pen_openai ?? default_settings.freq_pen_openai;
|
||||||
oai_settings.pres_pen_openai = settings.pres_pen_openai ?? default_settings.pres_pen_openai;
|
oai_settings.pres_pen_openai = settings.pres_pen_openai ?? default_settings.pres_pen_openai;
|
||||||
oai_settings.count_pen = settings.count_pen ?? default_settings.count_pen;
|
|
||||||
oai_settings.top_p_openai = settings.top_p_openai ?? default_settings.top_p_openai;
|
oai_settings.top_p_openai = settings.top_p_openai ?? default_settings.top_p_openai;
|
||||||
oai_settings.top_k_openai = settings.top_k_openai ?? default_settings.top_k_openai;
|
oai_settings.top_k_openai = settings.top_k_openai ?? default_settings.top_k_openai;
|
||||||
oai_settings.top_a_openai = settings.top_a_openai ?? default_settings.top_a_openai;
|
oai_settings.top_a_openai = settings.top_a_openai ?? default_settings.top_a_openai;
|
||||||
@ -3080,10 +3045,12 @@ function loadOpenAISettings(data, settings) {
|
|||||||
oai_settings.names_behavior = character_names_behavior.COMPLETION;
|
oai_settings.names_behavior = character_names_behavior.COMPLETION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oai_settings.ai21_model.startsWith('j2-')) {
|
||||||
|
oai_settings.ai21_model = 'jamba-1.5-large';
|
||||||
|
}
|
||||||
|
|
||||||
if (settings.wrap_in_quotes !== undefined) oai_settings.wrap_in_quotes = !!settings.wrap_in_quotes;
|
if (settings.wrap_in_quotes !== undefined) oai_settings.wrap_in_quotes = !!settings.wrap_in_quotes;
|
||||||
if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model;
|
if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model;
|
||||||
if (settings.use_ai21_tokenizer !== undefined) { oai_settings.use_ai21_tokenizer = !!settings.use_ai21_tokenizer; oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200; }
|
|
||||||
if (settings.use_google_tokenizer !== undefined) oai_settings.use_google_tokenizer = !!settings.use_google_tokenizer;
|
|
||||||
if (settings.claude_use_sysprompt !== undefined) oai_settings.claude_use_sysprompt = !!settings.claude_use_sysprompt;
|
if (settings.claude_use_sysprompt !== undefined) oai_settings.claude_use_sysprompt = !!settings.claude_use_sysprompt;
|
||||||
if (settings.use_makersuite_sysprompt !== undefined) oai_settings.use_makersuite_sysprompt = !!settings.use_makersuite_sysprompt;
|
if (settings.use_makersuite_sysprompt !== undefined) oai_settings.use_makersuite_sysprompt = !!settings.use_makersuite_sysprompt;
|
||||||
if (settings.use_alt_scale !== undefined) { oai_settings.use_alt_scale = !!settings.use_alt_scale; updateScaleForm(); }
|
if (settings.use_alt_scale !== undefined) { oai_settings.use_alt_scale = !!settings.use_alt_scale; updateScaleForm(); }
|
||||||
@ -3133,8 +3100,6 @@ function loadOpenAISettings(data, settings) {
|
|||||||
$('#jailbreak_system').prop('checked', oai_settings.jailbreak_system);
|
$('#jailbreak_system').prop('checked', oai_settings.jailbreak_system);
|
||||||
$('#openai_show_external_models').prop('checked', oai_settings.show_external_models);
|
$('#openai_show_external_models').prop('checked', oai_settings.show_external_models);
|
||||||
$('#openai_external_category').toggle(oai_settings.show_external_models);
|
$('#openai_external_category').toggle(oai_settings.show_external_models);
|
||||||
$('#use_ai21_tokenizer').prop('checked', oai_settings.use_ai21_tokenizer);
|
|
||||||
$('#use_google_tokenizer').prop('checked', oai_settings.use_google_tokenizer);
|
|
||||||
$('#claude_use_sysprompt').prop('checked', oai_settings.claude_use_sysprompt);
|
$('#claude_use_sysprompt').prop('checked', oai_settings.claude_use_sysprompt);
|
||||||
$('#use_makersuite_sysprompt').prop('checked', oai_settings.use_makersuite_sysprompt);
|
$('#use_makersuite_sysprompt').prop('checked', oai_settings.use_makersuite_sysprompt);
|
||||||
$('#scale-alt').prop('checked', oai_settings.use_alt_scale);
|
$('#scale-alt').prop('checked', oai_settings.use_alt_scale);
|
||||||
@ -3170,9 +3135,6 @@ function loadOpenAISettings(data, settings) {
|
|||||||
$('#pres_pen_openai').val(oai_settings.pres_pen_openai);
|
$('#pres_pen_openai').val(oai_settings.pres_pen_openai);
|
||||||
$('#pres_pen_counter_openai').val(Number(oai_settings.pres_pen_openai).toFixed(2));
|
$('#pres_pen_counter_openai').val(Number(oai_settings.pres_pen_openai).toFixed(2));
|
||||||
|
|
||||||
$('#count_pen').val(oai_settings.count_pen);
|
|
||||||
$('#count_pen_counter').val(Number(oai_settings.count_pen).toFixed(2));
|
|
||||||
|
|
||||||
$('#top_p_openai').val(oai_settings.top_p_openai);
|
$('#top_p_openai').val(oai_settings.top_p_openai);
|
||||||
$('#top_p_counter_openai').val(Number(oai_settings.top_p_openai).toFixed(2));
|
$('#top_p_counter_openai').val(Number(oai_settings.top_p_openai).toFixed(2));
|
||||||
|
|
||||||
@ -3392,7 +3354,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
|
|||||||
temperature: settings.temp_openai,
|
temperature: settings.temp_openai,
|
||||||
frequency_penalty: settings.freq_pen_openai,
|
frequency_penalty: settings.freq_pen_openai,
|
||||||
presence_penalty: settings.pres_pen_openai,
|
presence_penalty: settings.pres_pen_openai,
|
||||||
count_penalty: settings.count_pen,
|
|
||||||
top_p: settings.top_p_openai,
|
top_p: settings.top_p_openai,
|
||||||
top_k: settings.top_k_openai,
|
top_k: settings.top_k_openai,
|
||||||
top_a: settings.top_a_openai,
|
top_a: settings.top_a_openai,
|
||||||
@ -3427,8 +3388,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
|
|||||||
assistant_prefill: settings.assistant_prefill,
|
assistant_prefill: settings.assistant_prefill,
|
||||||
assistant_impersonation: settings.assistant_impersonation,
|
assistant_impersonation: settings.assistant_impersonation,
|
||||||
human_sysprompt_message: settings.human_sysprompt_message,
|
human_sysprompt_message: settings.human_sysprompt_message,
|
||||||
use_ai21_tokenizer: settings.use_ai21_tokenizer,
|
|
||||||
use_google_tokenizer: settings.use_google_tokenizer,
|
|
||||||
claude_use_sysprompt: settings.claude_use_sysprompt,
|
claude_use_sysprompt: settings.claude_use_sysprompt,
|
||||||
use_makersuite_sysprompt: settings.use_makersuite_sysprompt,
|
use_makersuite_sysprompt: settings.use_makersuite_sysprompt,
|
||||||
use_alt_scale: settings.use_alt_scale,
|
use_alt_scale: settings.use_alt_scale,
|
||||||
@ -3799,7 +3758,6 @@ function onSettingsPresetChange() {
|
|||||||
temperature: ['#temp_openai', 'temp_openai', false],
|
temperature: ['#temp_openai', 'temp_openai', false],
|
||||||
frequency_penalty: ['#freq_pen_openai', 'freq_pen_openai', false],
|
frequency_penalty: ['#freq_pen_openai', 'freq_pen_openai', false],
|
||||||
presence_penalty: ['#pres_pen_openai', 'pres_pen_openai', false],
|
presence_penalty: ['#pres_pen_openai', 'pres_pen_openai', false],
|
||||||
count_penalty: ['#count_pen', 'count_pen', false],
|
|
||||||
top_p: ['#top_p_openai', 'top_p_openai', false],
|
top_p: ['#top_p_openai', 'top_p_openai', false],
|
||||||
top_k: ['#top_k_openai', 'top_k_openai', false],
|
top_k: ['#top_k_openai', 'top_k_openai', false],
|
||||||
top_a: ['#top_a_openai', 'top_a_openai', false],
|
top_a: ['#top_a_openai', 'top_a_openai', false],
|
||||||
@ -3856,8 +3814,6 @@ function onSettingsPresetChange() {
|
|||||||
assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false],
|
assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false],
|
||||||
assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false],
|
assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false],
|
||||||
human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false],
|
human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false],
|
||||||
use_ai21_tokenizer: ['#use_ai21_tokenizer', 'use_ai21_tokenizer', true],
|
|
||||||
use_google_tokenizer: ['#use_google_tokenizer', 'use_google_tokenizer', true],
|
|
||||||
claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true],
|
claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true],
|
||||||
use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true],
|
use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true],
|
||||||
use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true],
|
use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true],
|
||||||
@ -4028,6 +3984,11 @@ async function onModelChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($(this).is('#model_ai21_select')) {
|
if ($(this).is('#model_ai21_select')) {
|
||||||
|
if (value === '' || value.startsWith('j2-')) {
|
||||||
|
value = 'jamba-1.5-large';
|
||||||
|
$('#model_ai21_select').val(value);
|
||||||
|
}
|
||||||
|
|
||||||
console.log('AI21 model changed to', value);
|
console.log('AI21 model changed to', value);
|
||||||
oai_settings.ai21_model = value;
|
oai_settings.ai21_model = value;
|
||||||
}
|
}
|
||||||
@ -4230,7 +4191,7 @@ async function onModelChange() {
|
|||||||
else if (['command-light-nightly', 'command-nightly'].includes(oai_settings.cohere_model)) {
|
else if (['command-light-nightly', 'command-nightly'].includes(oai_settings.cohere_model)) {
|
||||||
$('#openai_max_context').attr('max', max_8k);
|
$('#openai_max_context').attr('max', max_8k);
|
||||||
}
|
}
|
||||||
else if (['command-r', 'command-r-plus'].includes(oai_settings.cohere_model)) {
|
else if (oai_settings.cohere_model.includes('command-r')) {
|
||||||
$('#openai_max_context').attr('max', max_128k);
|
$('#openai_max_context').attr('max', max_128k);
|
||||||
}
|
}
|
||||||
else if (['c4ai-aya-23'].includes(oai_settings.cohere_model)) {
|
else if (['c4ai-aya-23'].includes(oai_settings.cohere_model)) {
|
||||||
@ -4305,33 +4266,13 @@ async function onModelChange() {
|
|||||||
if (oai_settings.chat_completion_source == chat_completion_sources.AI21) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.AI21) {
|
||||||
if (oai_settings.max_context_unlocked) {
|
if (oai_settings.max_context_unlocked) {
|
||||||
$('#openai_max_context').attr('max', unlocked_max);
|
$('#openai_max_context').attr('max', unlocked_max);
|
||||||
} else {
|
} else if (oai_settings.ai21_model.includes('jamba-1.5') || oai_settings.ai21_model.includes('jamba-instruct')) {
|
||||||
$('#openai_max_context').attr('max', ai21_max);
|
$('#openai_max_context').attr('max', max_256k);
|
||||||
}
|
}
|
||||||
|
|
||||||
oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max')));
|
oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
|
||||||
$('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
|
$('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
|
||||||
|
$('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
|
||||||
oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai);
|
|
||||||
$('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input');
|
|
||||||
|
|
||||||
oai_settings.freq_pen_openai = Math.min(j2_max_freq, oai_settings.freq_pen_openai < 0 ? 0 : oai_settings.freq_pen_openai);
|
|
||||||
$('#freq_pen_openai').attr('min', 0).attr('max', j2_max_freq).val(oai_settings.freq_pen_openai).trigger('input');
|
|
||||||
|
|
||||||
oai_settings.pres_pen_openai = Math.min(j2_max_pres, oai_settings.pres_pen_openai < 0 ? 0 : oai_settings.pres_pen_openai);
|
|
||||||
$('#pres_pen_openai').attr('min', 0).attr('max', j2_max_pres).val(oai_settings.pres_pen_openai).trigger('input');
|
|
||||||
|
|
||||||
oai_settings.top_k_openai = Math.min(j2_max_topk, oai_settings.top_k_openai);
|
|
||||||
$('#top_k_openai').attr('max', j2_max_topk).val(oai_settings.top_k_openai).trigger('input');
|
|
||||||
} else if (oai_settings.chat_completion_source != chat_completion_sources.AI21) {
|
|
||||||
oai_settings.freq_pen_openai = Math.min(2.0, oai_settings.freq_pen_openai);
|
|
||||||
$('#freq_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.freq_pen_openai).trigger('input');
|
|
||||||
|
|
||||||
oai_settings.pres_pen_openai = Math.min(2.0, oai_settings.pres_pen_openai);
|
|
||||||
$('#pres_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.pres_pen_openai).trigger('input');
|
|
||||||
|
|
||||||
oai_settings.top_k_openai = Math.min(200, oai_settings.top_k_openai);
|
|
||||||
$('#top_k_openai').attr('max', 200).val(oai_settings.top_k_openai).trigger('input');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) {
|
||||||
@ -4388,6 +4329,16 @@ async function onModelChange() {
|
|||||||
$('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
|
$('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) {
|
||||||
|
oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1);
|
||||||
|
$('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input');
|
||||||
|
oai_settings.freq_pen_openai = Math.min(Math.max(0, oai_settings.freq_pen_openai), 1);
|
||||||
|
$('#freq_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.freq_pen_openai).trigger('input');
|
||||||
|
} else {
|
||||||
|
$('#pres_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.pres_pen_openai).trigger('input');
|
||||||
|
$('#freq_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.freq_pen_openai).trigger('input');
|
||||||
|
}
|
||||||
|
|
||||||
$('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max')));
|
$('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max')));
|
||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
@ -4673,17 +4624,17 @@ function toggleChatCompletionForms() {
|
|||||||
async function testApiConnection() {
|
async function testApiConnection() {
|
||||||
// Check if the previous request is still in progress
|
// Check if the previous request is still in progress
|
||||||
if (is_send_press) {
|
if (is_send_press) {
|
||||||
toastr.info('Please wait for the previous request to complete.');
|
toastr.info(t`Please wait for the previous request to complete.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const reply = await sendOpenAIRequest('quiet', [{ 'role': 'user', 'content': 'Hi' }]);
|
const reply = await sendOpenAIRequest('quiet', [{ 'role': 'user', 'content': 'Hi' }]);
|
||||||
console.log(reply);
|
console.log(reply);
|
||||||
toastr.success('API connection successful!');
|
toastr.success(t`API connection successful!`);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
toastr.error('Could not get a reply from API. Check your connection settings / API key and try again.');
|
toastr.error(t`Could not get a reply from API. Check your connection settings / API key and try again.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4752,11 +4703,14 @@ export function isImageInliningSupported() {
|
|||||||
'gemini-1.5-flash',
|
'gemini-1.5-flash',
|
||||||
'gemini-1.5-flash-latest',
|
'gemini-1.5-flash-latest',
|
||||||
'gemini-1.5-flash-001',
|
'gemini-1.5-flash-001',
|
||||||
|
'gemini-1.5-flash-exp-0827',
|
||||||
|
'gemini-1.5-flash-8b-exp-0827',
|
||||||
'gemini-1.0-pro-vision-latest',
|
'gemini-1.0-pro-vision-latest',
|
||||||
'gemini-1.5-pro',
|
'gemini-1.5-pro',
|
||||||
'gemini-1.5-pro-latest',
|
'gemini-1.5-pro-latest',
|
||||||
'gemini-1.5-pro-001',
|
'gemini-1.5-pro-001',
|
||||||
'gemini-1.5-pro-exp-0801',
|
'gemini-1.5-pro-exp-0801',
|
||||||
|
'gemini-1.5-pro-exp-0827',
|
||||||
'gemini-pro-vision',
|
'gemini-pro-vision',
|
||||||
'claude-3',
|
'claude-3',
|
||||||
'claude-3-5',
|
'claude-3-5',
|
||||||
@ -4837,7 +4791,7 @@ function onProxyPresetChange() {
|
|||||||
if (selectedPreset) {
|
if (selectedPreset) {
|
||||||
setProxyPreset(selectedPreset.name, selectedPreset.url, selectedPreset.password);
|
setProxyPreset(selectedPreset.name, selectedPreset.url, selectedPreset.password);
|
||||||
} else {
|
} else {
|
||||||
console.error(`Proxy preset "${value}" not found in proxies array.`);
|
console.error(t`Proxy preset '${value}' not found in proxies array.`);
|
||||||
}
|
}
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
@ -4849,7 +4803,7 @@ $('#save_proxy').on('click', async function () {
|
|||||||
|
|
||||||
setProxyPreset(presetName, reverseProxy, proxyPassword);
|
setProxyPreset(presetName, reverseProxy, proxyPassword);
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
toastr.success('Proxy Saved');
|
toastr.success(t`Proxy Saved`);
|
||||||
if ($('#openai_proxy_preset').val() !== presetName) {
|
if ($('#openai_proxy_preset').val() !== presetName) {
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.text = presetName;
|
option.text = presetName;
|
||||||
@ -4883,9 +4837,9 @@ $('#delete_proxy').on('click', async function () {
|
|||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
$('#openai_proxy_preset').val(selected_proxy.name);
|
$('#openai_proxy_preset').val(selected_proxy.name);
|
||||||
toastr.success('Proxy Deleted');
|
toastr.success(t`Proxy Deleted`);
|
||||||
} else {
|
} else {
|
||||||
toastr.error(`Could not find proxy with name "${presetName}"`);
|
toastr.error(t`Could not find proxy with name '${presetName}'`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -4953,12 +4907,6 @@ $(document).ready(async function () {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#count_pen').on('input', function () {
|
|
||||||
oai_settings.count_pen = Number($(this).val());
|
|
||||||
$('#count_pen_counter').val(Number($(this).val()).toFixed(2));
|
|
||||||
saveSettingsDebounced();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#top_p_openai').on('input', function () {
|
$('#top_p_openai').on('input', function () {
|
||||||
oai_settings.top_p_openai = Number($(this).val());
|
oai_settings.top_p_openai = Number($(this).val());
|
||||||
$('#top_p_counter_openai').val(Number($(this).val()).toFixed(2));
|
$('#top_p_counter_openai').val(Number($(this).val()).toFixed(2));
|
||||||
@ -5017,20 +4965,6 @@ $(document).ready(async function () {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#use_ai21_tokenizer').on('change', function () {
|
|
||||||
oai_settings.use_ai21_tokenizer = !!$('#use_ai21_tokenizer').prop('checked');
|
|
||||||
oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200;
|
|
||||||
oai_settings.openai_max_context = Math.min(ai21_max, oai_settings.openai_max_context);
|
|
||||||
$('#openai_max_context').attr('max', ai21_max).val(oai_settings.openai_max_context).trigger('input');
|
|
||||||
$('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max')));
|
|
||||||
saveSettingsDebounced();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#use_google_tokenizer').on('change', function () {
|
|
||||||
oai_settings.use_google_tokenizer = !!$('#use_google_tokenizer').prop('checked');
|
|
||||||
saveSettingsDebounced();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#claude_use_sysprompt').on('change', function () {
|
$('#claude_use_sysprompt').on('change', function () {
|
||||||
oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked');
|
oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked');
|
||||||
$('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt);
|
$('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt);
|
||||||
|
@ -107,6 +107,7 @@ export const persona_description_positions = {
|
|||||||
TOP_AN: 2,
|
TOP_AN: 2,
|
||||||
BOTTOM_AN: 3,
|
BOTTOM_AN: 3,
|
||||||
AT_DEPTH: 4,
|
AT_DEPTH: 4,
|
||||||
|
NONE: 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
let power_user = {
|
let power_user = {
|
||||||
|
6
public/scripts/templates/chatRename.html
Normal file
6
public/scripts/templates/chatRename.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<h3 data-i18n="chat_rename_1">Enter the new name for the chat:</h3>
|
||||||
|
<small>
|
||||||
|
<span data-i18n="chat_rename_2">!!Using an existing filename will produce an error!!</span><br>
|
||||||
|
<span data-i18n="chat_rename_3">This will break the link between checkpoint chats.</span><br>
|
||||||
|
<span data-i18n="chat_rename_4">No need to add '.jsonl' at the end.</span><br>
|
||||||
|
</small>
|
4
public/scripts/templates/newChatConfirm.html
Normal file
4
public/scripts/templates/newChatConfirm.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<label for="del_chat_checkbox" class="checkbox_label justifyCenter" data-i18n="[title]If necessary, you can later restore this chat file from the /backups folder" title="If necessary, you can later restore this chat file from the /backups folder">
|
||||||
|
<input type="checkbox" id="del_chat_checkbox" />
|
||||||
|
<small data-i18n="Also delete the current chat file">Also delete the current chat file</small>
|
||||||
|
</label>
|
1
public/scripts/templates/proxyConnectionWarning.html
Normal file
1
public/scripts/templates/proxyConnectionWarning.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<span data-i18n="Are you sure you want to connect to the following proxy URL?">Are you sure you want to connect to the following proxy URL?</span><var>{{proxyURL}}</var>
|
@ -188,6 +188,8 @@ const settings = {
|
|||||||
custom_model: '',
|
custom_model: '',
|
||||||
bypass_status_check: false,
|
bypass_status_check: false,
|
||||||
openrouter_allow_fallbacks: true,
|
openrouter_allow_fallbacks: true,
|
||||||
|
xtc_threshold: 0.1,
|
||||||
|
xtc_probability: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
export let textgenerationwebui_banned_in_macros = [];
|
export let textgenerationwebui_banned_in_macros = [];
|
||||||
@ -263,6 +265,8 @@ export const setting_names = [
|
|||||||
'custom_model',
|
'custom_model',
|
||||||
'bypass_status_check',
|
'bypass_status_check',
|
||||||
'openrouter_allow_fallbacks',
|
'openrouter_allow_fallbacks',
|
||||||
|
'xtc_threshold',
|
||||||
|
'xtc_probability',
|
||||||
];
|
];
|
||||||
|
|
||||||
const DYNATEMP_BLOCK = document.getElementById('dynatemp_block_ooba');
|
const DYNATEMP_BLOCK = document.getElementById('dynatemp_block_ooba');
|
||||||
@ -718,6 +722,8 @@ jQuery(function () {
|
|||||||
'dry_multiplier_textgenerationwebui': 0,
|
'dry_multiplier_textgenerationwebui': 0,
|
||||||
'dry_base_textgenerationwebui': 1.75,
|
'dry_base_textgenerationwebui': 1.75,
|
||||||
'dry_penalty_last_n_textgenerationwebui': 0,
|
'dry_penalty_last_n_textgenerationwebui': 0,
|
||||||
|
'xtc_threshold_textgenerationwebui': 0.1,
|
||||||
|
'xtc_probability_textgenerationwebui': 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [id, value] of Object.entries(inputs)) {
|
for (const [id, value] of Object.entries(inputs)) {
|
||||||
@ -1156,6 +1162,8 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
|||||||
'api_server': getTextGenServer(),
|
'api_server': getTextGenServer(),
|
||||||
'legacy_api': settings.legacy_api && (settings.type === OOBA || settings.type === APHRODITE),
|
'legacy_api': settings.legacy_api && (settings.type === OOBA || settings.type === APHRODITE),
|
||||||
'sampler_order': settings.type === textgen_types.KOBOLDCPP ? settings.sampler_order : undefined,
|
'sampler_order': settings.type === textgen_types.KOBOLDCPP ? settings.sampler_order : undefined,
|
||||||
|
'xtc_threshold': settings.xtc_threshold,
|
||||||
|
'xtc_probability': settings.xtc_probability,
|
||||||
};
|
};
|
||||||
const nonAphroditeParams = {
|
const nonAphroditeParams = {
|
||||||
'rep_pen': settings.rep_pen,
|
'rep_pen': settings.rep_pen,
|
||||||
|
@ -27,6 +27,7 @@ export const tokenizers = {
|
|||||||
CLAUDE: 11,
|
CLAUDE: 11,
|
||||||
LLAMA3: 12,
|
LLAMA3: 12,
|
||||||
GEMMA: 13,
|
GEMMA: 13,
|
||||||
|
JAMBA: 14,
|
||||||
BEST_MATCH: 99,
|
BEST_MATCH: 99,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ export const SENTENCEPIECE_TOKENIZERS = [
|
|||||||
tokenizers.YI,
|
tokenizers.YI,
|
||||||
tokenizers.LLAMA3,
|
tokenizers.LLAMA3,
|
||||||
tokenizers.GEMMA,
|
tokenizers.GEMMA,
|
||||||
|
tokenizers.JAMBA,
|
||||||
// uncomment when NovelAI releases Kayra and Clio weights, lol
|
// uncomment when NovelAI releases Kayra and Clio weights, lol
|
||||||
//tokenizers.NERD,
|
//tokenizers.NERD,
|
||||||
//tokenizers.NERD2,
|
//tokenizers.NERD2,
|
||||||
@ -98,6 +100,11 @@ const TOKENIZER_URLS = {
|
|||||||
decode: '/api/tokenizers/gemma/decode',
|
decode: '/api/tokenizers/gemma/decode',
|
||||||
count: '/api/tokenizers/gemma/encode',
|
count: '/api/tokenizers/gemma/encode',
|
||||||
},
|
},
|
||||||
|
[tokenizers.JAMBA]: {
|
||||||
|
encode: '/api/tokenizers/jamba/encode',
|
||||||
|
decode: '/api/tokenizers/jamba/decode',
|
||||||
|
count: '/api/tokenizers/jamba/encode',
|
||||||
|
},
|
||||||
[tokenizers.API_TEXTGENERATIONWEBUI]: {
|
[tokenizers.API_TEXTGENERATIONWEBUI]: {
|
||||||
encode: '/api/tokenizers/remote/textgenerationwebui/encode',
|
encode: '/api/tokenizers/remote/textgenerationwebui/encode',
|
||||||
count: '/api/tokenizers/remote/textgenerationwebui/encode',
|
count: '/api/tokenizers/remote/textgenerationwebui/encode',
|
||||||
@ -164,7 +171,7 @@ export function getAvailableTokenizers() {
|
|||||||
tokenizerId: Number(tokenizerOption.value),
|
tokenizerId: Number(tokenizerOption.value),
|
||||||
tokenizerKey: Object.entries(tokenizers).find(([_, value]) => value === Number(tokenizerOption.value))[0].toLocaleLowerCase(),
|
tokenizerKey: Object.entries(tokenizers).find(([_, value]) => value === Number(tokenizerOption.value))[0].toLocaleLowerCase(),
|
||||||
tokenizerName: tokenizerOption.text,
|
tokenizerName: tokenizerOption.text,
|
||||||
}))
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -280,6 +287,12 @@ export function getTokenizerBestMatch(forApi) {
|
|||||||
if (model.includes('gemma')) {
|
if (model.includes('gemma')) {
|
||||||
return tokenizers.GEMMA;
|
return tokenizers.GEMMA;
|
||||||
}
|
}
|
||||||
|
if (model.includes('yi')) {
|
||||||
|
return tokenizers.YI;
|
||||||
|
}
|
||||||
|
if (model.includes('jamba')) {
|
||||||
|
return tokenizers.JAMBA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokenizers.LLAMA;
|
return tokenizers.LLAMA;
|
||||||
@ -497,6 +510,7 @@ export function getTokenizerModel() {
|
|||||||
const mistralTokenizer = 'mistral';
|
const mistralTokenizer = 'mistral';
|
||||||
const yiTokenizer = 'yi';
|
const yiTokenizer = 'yi';
|
||||||
const gemmaTokenizer = 'gemma';
|
const gemmaTokenizer = 'gemma';
|
||||||
|
const jambaTokenizer = 'jamba';
|
||||||
|
|
||||||
// Assuming no one would use it for different models.. right?
|
// Assuming no one would use it for different models.. right?
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) {
|
||||||
@ -562,12 +576,19 @@ export function getTokenizerModel() {
|
|||||||
else if (oai_settings.openrouter_model.includes('GPT-NeoXT')) {
|
else if (oai_settings.openrouter_model.includes('GPT-NeoXT')) {
|
||||||
return gpt2Tokenizer;
|
return gpt2Tokenizer;
|
||||||
}
|
}
|
||||||
|
else if (oai_settings.openrouter_model.includes('jamba')) {
|
||||||
|
return jambaTokenizer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) {
|
||||||
return gemmaTokenizer;
|
return gemmaTokenizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oai_settings.chat_completion_source == chat_completion_sources.AI21) {
|
||||||
|
return jambaTokenizer;
|
||||||
|
}
|
||||||
|
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {
|
||||||
return claudeTokenizer;
|
return claudeTokenizer;
|
||||||
}
|
}
|
||||||
@ -626,16 +647,7 @@ export function getTokenizerModel() {
|
|||||||
* @deprecated Use countTokensOpenAIAsync instead.
|
* @deprecated Use countTokensOpenAIAsync instead.
|
||||||
*/
|
*/
|
||||||
export function countTokensOpenAI(messages, full = false) {
|
export function countTokensOpenAI(messages, full = false) {
|
||||||
const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer;
|
const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
|
||||||
const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer;
|
|
||||||
let tokenizerEndpoint = '';
|
|
||||||
if (shouldTokenizeAI21) {
|
|
||||||
tokenizerEndpoint = '/api/tokenizers/ai21/count';
|
|
||||||
} else if (shouldTokenizeGoogle) {
|
|
||||||
tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}&reverse_proxy=${oai_settings.reverse_proxy}&proxy_password=${oai_settings.proxy_password}`;
|
|
||||||
} else {
|
|
||||||
tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
|
|
||||||
}
|
|
||||||
const cacheObject = getTokenCacheObject();
|
const cacheObject = getTokenCacheObject();
|
||||||
|
|
||||||
if (!Array.isArray(messages)) {
|
if (!Array.isArray(messages)) {
|
||||||
@ -647,7 +659,7 @@ export function countTokensOpenAI(messages, full = false) {
|
|||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
const model = getTokenizerModel();
|
const model = getTokenizerModel();
|
||||||
|
|
||||||
if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) {
|
if (model === 'claude') {
|
||||||
full = true;
|
full = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,16 +699,7 @@ export function countTokensOpenAI(messages, full = false) {
|
|||||||
* @returns {Promise<number>} Token count.
|
* @returns {Promise<number>} Token count.
|
||||||
*/
|
*/
|
||||||
export async function countTokensOpenAIAsync(messages, full = false) {
|
export async function countTokensOpenAIAsync(messages, full = false) {
|
||||||
const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer;
|
const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
|
||||||
const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer;
|
|
||||||
let tokenizerEndpoint = '';
|
|
||||||
if (shouldTokenizeAI21) {
|
|
||||||
tokenizerEndpoint = '/api/tokenizers/ai21/count';
|
|
||||||
} else if (shouldTokenizeGoogle) {
|
|
||||||
tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}`;
|
|
||||||
} else {
|
|
||||||
tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
|
|
||||||
}
|
|
||||||
const cacheObject = getTokenCacheObject();
|
const cacheObject = getTokenCacheObject();
|
||||||
|
|
||||||
if (!Array.isArray(messages)) {
|
if (!Array.isArray(messages)) {
|
||||||
@ -708,7 +711,7 @@ export async function countTokensOpenAIAsync(messages, full = false) {
|
|||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
const model = getTokenizerModel();
|
const model = getTokenizerModel();
|
||||||
|
|
||||||
if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) {
|
if (model === 'claude') {
|
||||||
full = true;
|
full = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4777,8 +4777,10 @@ jQuery(() => {
|
|||||||
world_info_min_activations = Number($(this).val());
|
world_info_min_activations = Number($(this).val());
|
||||||
$('#world_info_min_activations_counter').val(world_info_min_activations);
|
$('#world_info_min_activations_counter').val(world_info_min_activations);
|
||||||
|
|
||||||
if (world_info_min_activations !== 0) {
|
if (world_info_min_activations !== 0 && world_info_max_recursion_steps !== 0) {
|
||||||
$('#world_info_max_recursion_steps').val(0).trigger('input');
|
$('#world_info_max_recursion_steps').val(0).trigger('input');
|
||||||
|
flashHighlight($('#world_info_max_recursion_steps').parent()); // flash the other control to show it has changed
|
||||||
|
console.info('[WI] Max recursion steps set to 0, as min activations is set to', world_info_min_activations);
|
||||||
} else {
|
} else {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
@ -4840,8 +4842,10 @@ jQuery(() => {
|
|||||||
$('#world_info_max_recursion_steps').on('input', function () {
|
$('#world_info_max_recursion_steps').on('input', function () {
|
||||||
world_info_max_recursion_steps = Number($(this).val());
|
world_info_max_recursion_steps = Number($(this).val());
|
||||||
$('#world_info_max_recursion_steps_counter').val(world_info_max_recursion_steps);
|
$('#world_info_max_recursion_steps_counter').val(world_info_max_recursion_steps);
|
||||||
if (world_info_max_recursion_steps !== 0) {
|
if (world_info_max_recursion_steps !== 0 && world_info_min_activations !== 0) {
|
||||||
$('#world_info_min_activations').val(0).trigger('input');
|
$('#world_info_min_activations').val(0).trigger('input');
|
||||||
|
flashHighlight($('#world_info_min_activations').parent()); // flash the other control to show it has changed
|
||||||
|
console.info('[WI] Min activations set to 0, as max recursion steps is set to', world_info_max_recursion_steps);
|
||||||
} else {
|
} else {
|
||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
@ -2421,7 +2421,6 @@ input[type="file"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#rm_print_characters_block .text_block {
|
#rm_print_characters_block .text_block {
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
margin: 0 auto 1px auto;
|
margin: 0 auto 1px auto;
|
||||||
|
126
src/cohere-stream.js
Normal file
126
src/cohere-stream.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
const DATA_PREFIX = 'data:';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Borrowed from Cohere SDK (MIT License)
|
||||||
|
* https://github.com/cohere-ai/cohere-typescript/blob/main/src/core/streaming-fetcher/Stream.ts
|
||||||
|
* Copyright (c) 2021 Cohere
|
||||||
|
*/
|
||||||
|
class CohereStream {
|
||||||
|
/** @type {ReadableStream} */
|
||||||
|
stream;
|
||||||
|
/** @type {string} */
|
||||||
|
prefix;
|
||||||
|
/** @type {string} */
|
||||||
|
messageTerminator;
|
||||||
|
/** @type {string|undefined} */
|
||||||
|
streamTerminator;
|
||||||
|
/** @type {AbortController} */
|
||||||
|
controller = new AbortController();
|
||||||
|
|
||||||
|
constructor({ stream, eventShape }) {
|
||||||
|
this.stream = stream;
|
||||||
|
if (eventShape.type === 'sse') {
|
||||||
|
this.prefix = DATA_PREFIX;
|
||||||
|
this.messageTerminator = '\n';
|
||||||
|
this.streamTerminator = eventShape.streamTerminator;
|
||||||
|
} else {
|
||||||
|
this.messageTerminator = eventShape.messageTerminator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async *iterMessages() {
|
||||||
|
const stream = readableStreamAsyncIterable(this.stream);
|
||||||
|
let buf = '';
|
||||||
|
let prefixSeen = false;
|
||||||
|
let parsedAnyMessages = false;
|
||||||
|
for await (const chunk of stream) {
|
||||||
|
buf += this.decodeChunk(chunk);
|
||||||
|
|
||||||
|
let terminatorIndex;
|
||||||
|
// Parse the chunk into as many messages as possible
|
||||||
|
while ((terminatorIndex = buf.indexOf(this.messageTerminator)) >= 0) {
|
||||||
|
// Extract the line from the buffer
|
||||||
|
let line = buf.slice(0, terminatorIndex + 1);
|
||||||
|
buf = buf.slice(terminatorIndex + 1);
|
||||||
|
|
||||||
|
// Skip empty lines
|
||||||
|
if (line.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip the chunk until the prefix is found
|
||||||
|
if (!prefixSeen && this.prefix != null) {
|
||||||
|
const prefixIndex = line.indexOf(this.prefix);
|
||||||
|
if (prefixIndex === -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
prefixSeen = true;
|
||||||
|
line = line.slice(prefixIndex + this.prefix.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the stream terminator is present, return
|
||||||
|
if (this.streamTerminator != null && line.includes(this.streamTerminator)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, yield message from the prefix to the terminator
|
||||||
|
const message = JSON.parse(line);
|
||||||
|
yield message;
|
||||||
|
prefixSeen = false;
|
||||||
|
parsedAnyMessages = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parsedAnyMessages && buf.length > 0) {
|
||||||
|
try {
|
||||||
|
yield JSON.parse(buf);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error parsing message:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async *[Symbol.asyncIterator]() {
|
||||||
|
for await (const message of this.iterMessages()) {
|
||||||
|
yield message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeChunk(chunk) {
|
||||||
|
const decoder = new TextDecoder('utf8');
|
||||||
|
return decoder.decode(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readableStreamAsyncIterable(stream) {
|
||||||
|
if (stream[Symbol.asyncIterator]) {
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = stream.getReader();
|
||||||
|
return {
|
||||||
|
async next() {
|
||||||
|
try {
|
||||||
|
const result = await reader.read();
|
||||||
|
if (result?.done) {
|
||||||
|
reader.releaseLock();
|
||||||
|
} // release lock when stream becomes closed
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
reader.releaseLock(); // release lock when stream becomes errored
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async return() {
|
||||||
|
const cancelPromise = reader.cancel();
|
||||||
|
reader.releaseLock();
|
||||||
|
await cancelPromise;
|
||||||
|
return { done: true, value: undefined };
|
||||||
|
},
|
||||||
|
[Symbol.asyncIterator]() {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CohereStream;
|
@ -1,11 +1,11 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const fetch = require('node-fetch').default;
|
const fetch = require('node-fetch').default;
|
||||||
const Readable = require('stream').Readable;
|
|
||||||
|
|
||||||
const { jsonParser } = require('../../express-common');
|
const { jsonParser } = require('../../express-common');
|
||||||
const { CHAT_COMPLETION_SOURCES, GEMINI_SAFETY, BISON_SAFETY, OPENROUTER_HEADERS } = require('../../constants');
|
const { CHAT_COMPLETION_SOURCES, GEMINI_SAFETY, BISON_SAFETY, OPENROUTER_HEADERS } = require('../../constants');
|
||||||
const { forwardFetchResponse, getConfigValue, tryParse, uuidv4, mergeObjectWithYaml, excludeKeysByYaml, color } = require('../../util');
|
const { forwardFetchResponse, getConfigValue, tryParse, uuidv4, mergeObjectWithYaml, excludeKeysByYaml, color } = require('../../util');
|
||||||
const { convertClaudeMessages, convertGooglePrompt, convertTextCompletionPrompt, convertCohereMessages, convertMistralMessages, convertCohereTools } = require('../../prompt-converters');
|
const { convertClaudeMessages, convertGooglePrompt, convertTextCompletionPrompt, convertCohereMessages, convertMistralMessages, convertCohereTools, convertAI21Messages } = require('../../prompt-converters');
|
||||||
|
const CohereStream = require('../../cohere-stream');
|
||||||
|
|
||||||
const { readSecret, SECRET_KEYS } = require('../secrets');
|
const { readSecret, SECRET_KEYS } = require('../secrets');
|
||||||
const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sentencepieceTokenizers, TEXT_COMPLETION_MODELS } = require('../tokenizers');
|
const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sentencepieceTokenizers, TEXT_COMPLETION_MODELS } = require('../tokenizers');
|
||||||
@ -19,6 +19,7 @@ const API_GROQ = 'https://api.groq.com/openai/v1';
|
|||||||
const API_MAKERSUITE = 'https://generativelanguage.googleapis.com';
|
const API_MAKERSUITE = 'https://generativelanguage.googleapis.com';
|
||||||
const API_01AI = 'https://api.01.ai/v1';
|
const API_01AI = 'https://api.01.ai/v1';
|
||||||
const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1';
|
const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1';
|
||||||
|
const API_AI21 = 'https://api.ai21.com/studio/v1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a post-processing step to the generated messages.
|
* Applies a post-processing step to the generated messages.
|
||||||
@ -40,52 +41,30 @@ function postProcessPrompt(messages, type, charName, userName) {
|
|||||||
/**
|
/**
|
||||||
* Ollama strikes back. Special boy #2's steaming routine.
|
* Ollama strikes back. Special boy #2's steaming routine.
|
||||||
* Wrap this abomination into proper SSE stream, again.
|
* Wrap this abomination into proper SSE stream, again.
|
||||||
* @param {import('node-fetch').Response} jsonStream JSON stream
|
* @param {Response} jsonStream JSON stream
|
||||||
* @param {import('express').Request} request Express request
|
* @param {import('express').Request} request Express request
|
||||||
* @param {import('express').Response} response Express response
|
* @param {import('express').Response} response Express response
|
||||||
* @returns {Promise<any>} Nothing valuable
|
* @returns {Promise<any>} Nothing valuable
|
||||||
*/
|
*/
|
||||||
async function parseCohereStream(jsonStream, request, response) {
|
async function parseCohereStream(jsonStream, request, response) {
|
||||||
try {
|
try {
|
||||||
let partialData = '';
|
const stream = new CohereStream({ stream: jsonStream.body, eventShape: { type: 'json', messageTerminator: '\n' } });
|
||||||
jsonStream.body.on('data', (data) => {
|
|
||||||
const chunk = data.toString();
|
for await (const json of stream.iterMessages()) {
|
||||||
partialData += chunk;
|
if (json.message) {
|
||||||
while (true) {
|
const message = json.message || 'Unknown error';
|
||||||
let json;
|
const chunk = { error: { message: message } };
|
||||||
try {
|
response.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
||||||
json = JSON.parse(partialData);
|
} else if (json.event_type === 'text-generation') {
|
||||||
} catch (e) {
|
const text = json.text || '';
|
||||||
break;
|
const chunk = { choices: [{ text }] };
|
||||||
}
|
response.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
||||||
if (json.message) {
|
|
||||||
const message = json.message || 'Unknown error';
|
|
||||||
const chunk = { error: { message: message } };
|
|
||||||
response.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
|
||||||
partialData = '';
|
|
||||||
break;
|
|
||||||
} else if (json.event_type === 'text-generation') {
|
|
||||||
const text = json.text || '';
|
|
||||||
const chunk = { choices: [{ text }] };
|
|
||||||
response.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
|
||||||
partialData = '';
|
|
||||||
} else {
|
|
||||||
partialData = '';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
request.socket.on('close', function () {
|
console.log('Streaming request finished');
|
||||||
if (jsonStream.body instanceof Readable) jsonStream.body.destroy();
|
response.write('data: [DONE]\n\n');
|
||||||
response.end();
|
response.end();
|
||||||
});
|
|
||||||
|
|
||||||
jsonStream.body.on('end', () => {
|
|
||||||
console.log('Streaming request finished');
|
|
||||||
response.write('data: [DONE]\n\n');
|
|
||||||
response.end();
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('Error forwarding streaming response:', error);
|
console.log('Error forwarding streaming response:', error);
|
||||||
if (!response.headersSent) {
|
if (!response.headersSent) {
|
||||||
@ -233,7 +212,7 @@ async function sendScaleRequest(request, response) {
|
|||||||
|
|
||||||
if (!generateResponse.ok) {
|
if (!generateResponse.ok) {
|
||||||
console.log(`Scale API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`);
|
console.log(`Scale API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`);
|
||||||
return response.status(generateResponse.status).send({ error: true });
|
return response.status(500).send({ error: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const generateResponseJson = await generateResponse.json();
|
const generateResponseJson = await generateResponse.json();
|
||||||
@ -413,6 +392,16 @@ async function sendAI21Request(request, response) {
|
|||||||
request.socket.on('close', function () {
|
request.socket.on('close', function () {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
});
|
});
|
||||||
|
const convertedPrompt = convertAI21Messages(request.body.messages, request.body.char_name, request.body.user_name);
|
||||||
|
const body = {
|
||||||
|
messages: convertedPrompt,
|
||||||
|
model: request.body.model,
|
||||||
|
max_tokens: request.body.max_tokens,
|
||||||
|
temperature: request.body.temperature,
|
||||||
|
top_p: request.body.top_p,
|
||||||
|
stop: request.body.stop,
|
||||||
|
stream: request.body.stream,
|
||||||
|
};
|
||||||
const options = {
|
const options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -420,59 +409,35 @@ async function sendAI21Request(request, response) {
|
|||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
Authorization: `Bearer ${readSecret(request.user.directories, SECRET_KEYS.AI21)}`,
|
Authorization: `Bearer ${readSecret(request.user.directories, SECRET_KEYS.AI21)}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify(body),
|
||||||
numResults: 1,
|
|
||||||
maxTokens: request.body.max_tokens,
|
|
||||||
minTokens: 0,
|
|
||||||
temperature: request.body.temperature,
|
|
||||||
topP: request.body.top_p,
|
|
||||||
stopSequences: request.body.stop_tokens,
|
|
||||||
topKReturn: request.body.top_k,
|
|
||||||
frequencyPenalty: {
|
|
||||||
scale: request.body.frequency_penalty * 100,
|
|
||||||
applyToWhitespaces: false,
|
|
||||||
applyToPunctuations: false,
|
|
||||||
applyToNumbers: false,
|
|
||||||
applyToStopwords: false,
|
|
||||||
applyToEmojis: false,
|
|
||||||
},
|
|
||||||
presencePenalty: {
|
|
||||||
scale: request.body.presence_penalty,
|
|
||||||
applyToWhitespaces: false,
|
|
||||||
applyToPunctuations: false,
|
|
||||||
applyToNumbers: false,
|
|
||||||
applyToStopwords: false,
|
|
||||||
applyToEmojis: false,
|
|
||||||
},
|
|
||||||
countPenalty: {
|
|
||||||
scale: request.body.count_pen,
|
|
||||||
applyToWhitespaces: false,
|
|
||||||
applyToPunctuations: false,
|
|
||||||
applyToNumbers: false,
|
|
||||||
applyToStopwords: false,
|
|
||||||
applyToEmojis: false,
|
|
||||||
},
|
|
||||||
prompt: request.body.messages,
|
|
||||||
}),
|
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch(`https://api.ai21.com/studio/v1/${request.body.model}/complete`, options)
|
console.log('AI21 request:', body);
|
||||||
.then(r => r.json())
|
|
||||||
.then(r => {
|
|
||||||
if (r.completions === undefined) {
|
|
||||||
console.log(r);
|
|
||||||
} else {
|
|
||||||
console.log(r.completions[0].data.text);
|
|
||||||
}
|
|
||||||
const reply = { choices: [{ 'message': { 'content': r.completions?.[0]?.data?.text } }] };
|
|
||||||
return response.send(reply);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(err);
|
|
||||||
return response.send({ error: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
const generateResponse = await fetch(API_AI21 + '/chat/completions', options);
|
||||||
|
if (request.body.stream) {
|
||||||
|
forwardFetchResponse(generateResponse, response);
|
||||||
|
} else {
|
||||||
|
if (!generateResponse.ok) {
|
||||||
|
const errorText = await generateResponse.text();
|
||||||
|
console.log(`AI21 API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`);
|
||||||
|
const errorJson = tryParse(errorText) ?? { error: true };
|
||||||
|
return response.status(500).send(errorJson);
|
||||||
|
}
|
||||||
|
const generateResponseJson = await generateResponse.json();
|
||||||
|
console.log('AI21 response:', generateResponseJson);
|
||||||
|
return response.send(generateResponseJson);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error communicating with AI21 API: ', error);
|
||||||
|
if (!response.headersSent) {
|
||||||
|
response.send({ error: true });
|
||||||
|
} else {
|
||||||
|
response.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -531,10 +496,10 @@ async function sendMistralAIRequest(request, response) {
|
|||||||
forwardFetchResponse(generateResponse, response);
|
forwardFetchResponse(generateResponse, response);
|
||||||
} else {
|
} else {
|
||||||
if (!generateResponse.ok) {
|
if (!generateResponse.ok) {
|
||||||
console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`);
|
const errorText = await generateResponse.text();
|
||||||
// a 401 unauthorized response breaks the frontend auth, so return a 500 instead. prob a better way of dealing with this.
|
console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`);
|
||||||
// 401s are already handled by the streaming processor and dont pop up an error toast, that should probably be fixed too.
|
const errorJson = tryParse(errorText) ?? { error: true };
|
||||||
return response.status(generateResponse.status === 401 ? 500 : generateResponse.status).send({ error: true });
|
return response.status(500).send(errorJson);
|
||||||
}
|
}
|
||||||
const generateResponseJson = await generateResponse.json();
|
const generateResponseJson = await generateResponse.json();
|
||||||
console.log('MistralAI response:', generateResponseJson);
|
console.log('MistralAI response:', generateResponseJson);
|
||||||
@ -607,6 +572,11 @@ async function sendCohereRequest(request, response) {
|
|||||||
search_queries_only: false,
|
search_queries_only: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const canDoSafetyMode = String(request.body.model).endsWith('08-2024');
|
||||||
|
if (canDoSafetyMode) {
|
||||||
|
requestBody.safety_mode = 'NONE';
|
||||||
|
}
|
||||||
|
|
||||||
console.log('Cohere request:', requestBody);
|
console.log('Cohere request:', requestBody);
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
@ -623,15 +593,15 @@ async function sendCohereRequest(request, response) {
|
|||||||
const apiUrl = API_COHERE + '/chat';
|
const apiUrl = API_COHERE + '/chat';
|
||||||
|
|
||||||
if (request.body.stream) {
|
if (request.body.stream) {
|
||||||
const stream = await fetch(apiUrl, config);
|
const stream = await global.fetch(apiUrl, config);
|
||||||
parseCohereStream(stream, request, response);
|
parseCohereStream(stream, request, response);
|
||||||
} else {
|
} else {
|
||||||
const generateResponse = await fetch(apiUrl, config);
|
const generateResponse = await fetch(apiUrl, config);
|
||||||
if (!generateResponse.ok) {
|
if (!generateResponse.ok) {
|
||||||
console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`);
|
const errorText = await generateResponse.text();
|
||||||
// a 401 unauthorized response breaks the frontend auth, so return a 500 instead. prob a better way of dealing with this.
|
console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`);
|
||||||
// 401s are already handled by the streaming processor and dont pop up an error toast, that should probably be fixed too.
|
const errorJson = tryParse(errorText) ?? { error: true };
|
||||||
return response.status(generateResponse.status === 401 ? 500 : generateResponse.status).send({ error: true });
|
return response.status(500).send(errorJson);
|
||||||
}
|
}
|
||||||
const generateResponseJson = await generateResponse.json();
|
const generateResponseJson = await generateResponse.json();
|
||||||
console.log('Cohere response:', generateResponseJson);
|
console.log('Cohere response:', generateResponseJson);
|
||||||
|
@ -6,6 +6,7 @@ const { readAllChunks, extractFileFromZipBuffer, forwardFetchResponse } = requir
|
|||||||
const { jsonParser } = require('../express-common');
|
const { jsonParser } = require('../express-common');
|
||||||
|
|
||||||
const API_NOVELAI = 'https://api.novelai.net';
|
const API_NOVELAI = 'https://api.novelai.net';
|
||||||
|
const TEXT_NOVELAI = 'https://text.novelai.net';
|
||||||
const IMAGE_NOVELAI = 'https://image.novelai.net';
|
const IMAGE_NOVELAI = 'https://image.novelai.net';
|
||||||
|
|
||||||
// Ban bracket generation, plus defaults
|
// Ban bracket generation, plus defaults
|
||||||
@ -155,7 +156,7 @@ router.post('/generate', jsonParser, async function (req, res) {
|
|||||||
'repetition_penalty_slope': req.body.repetition_penalty_slope,
|
'repetition_penalty_slope': req.body.repetition_penalty_slope,
|
||||||
'repetition_penalty_frequency': req.body.repetition_penalty_frequency,
|
'repetition_penalty_frequency': req.body.repetition_penalty_frequency,
|
||||||
'repetition_penalty_presence': req.body.repetition_penalty_presence,
|
'repetition_penalty_presence': req.body.repetition_penalty_presence,
|
||||||
'repetition_penalty_whitelist': isNewModel ? repPenaltyAllowList : null,
|
'repetition_penalty_whitelist': isNewModel ? repPenaltyAllowList.flat() : null,
|
||||||
'top_a': req.body.top_a,
|
'top_a': req.body.top_a,
|
||||||
'top_p': req.body.top_p,
|
'top_p': req.body.top_p,
|
||||||
'top_k': req.body.top_k,
|
'top_k': req.body.top_k,
|
||||||
@ -178,9 +179,7 @@ router.post('/generate', jsonParser, async function (req, res) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Tells the model to stop generation at '>'
|
// Tells the model to stop generation at '>'
|
||||||
if ('theme_textadventure' === req.body.prefix &&
|
if ('theme_textadventure' === req.body.prefix && isNewModel) {
|
||||||
(true === req.body.model.includes('clio') ||
|
|
||||||
true === req.body.model.includes('kayra'))) {
|
|
||||||
data.parameters.eos_token_id = 49405;
|
data.parameters.eos_token_id = 49405;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +192,8 @@ router.post('/generate', jsonParser, async function (req, res) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = req.body.streaming ? `${API_NOVELAI}/ai/generate-stream` : `${API_NOVELAI}/ai/generate`;
|
const baseURL = req.body.model.includes('kayra') ? TEXT_NOVELAI : API_NOVELAI;
|
||||||
|
const url = req.body.streaming ? `${baseURL}/ai/generate-stream` : `${baseURL}/ai/generate`;
|
||||||
const response = await fetch(url, { method: 'POST', timeout: 0, ...args });
|
const response = await fetch(url, { method: 'POST', timeout: 0, ...args });
|
||||||
|
|
||||||
if (req.body.streaming) {
|
if (req.body.streaming) {
|
||||||
|
@ -144,6 +144,7 @@ const spp_nerd_v2 = new SentencePieceTokenizer('src/tokenizers/nerdstash_v2.mode
|
|||||||
const spp_mistral = new SentencePieceTokenizer('src/tokenizers/mistral.model');
|
const spp_mistral = new SentencePieceTokenizer('src/tokenizers/mistral.model');
|
||||||
const spp_yi = new SentencePieceTokenizer('src/tokenizers/yi.model');
|
const spp_yi = new SentencePieceTokenizer('src/tokenizers/yi.model');
|
||||||
const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model');
|
const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model');
|
||||||
|
const spp_jamba = new SentencePieceTokenizer('src/tokenizers/jamba.model');
|
||||||
const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json');
|
const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json');
|
||||||
const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json');
|
const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json');
|
||||||
|
|
||||||
@ -154,6 +155,7 @@ const sentencepieceTokenizers = [
|
|||||||
'mistral',
|
'mistral',
|
||||||
'yi',
|
'yi',
|
||||||
'gemma',
|
'gemma',
|
||||||
|
'jamba',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -186,6 +188,10 @@ function getSentencepiceTokenizer(model) {
|
|||||||
return spp_gemma;
|
return spp_gemma;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.includes('jamba')) {
|
||||||
|
return spp_jamba;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -322,6 +328,10 @@ function getTokenizerModel(requestModel) {
|
|||||||
return 'gemma';
|
return 'gemma';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestModel.includes('jamba')) {
|
||||||
|
return 'jamba';
|
||||||
|
}
|
||||||
|
|
||||||
// default
|
// default
|
||||||
return 'gpt-3.5-turbo';
|
return 'gpt-3.5-turbo';
|
||||||
}
|
}
|
||||||
@ -537,59 +547,13 @@ function createWebTokenizerDecodingHandler(tokenizer) {
|
|||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.post('/ai21/count', jsonParser, async function (req, res) {
|
|
||||||
if (!req.body) return res.sendStatus(400);
|
|
||||||
const key = readSecret(req.user.directories, SECRET_KEYS.AI21);
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
accept: 'application/json',
|
|
||||||
'content-type': 'application/json',
|
|
||||||
Authorization: `Bearer ${key}`,
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ text: req.body[0].content }),
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('https://api.ai21.com/studio/v1/tokenize', options);
|
|
||||||
const data = await response.json();
|
|
||||||
return res.send({ 'token_count': data?.tokens?.length || 0 });
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return res.send({ 'token_count': 0 });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post('/google/count', jsonParser, async function (req, res) {
|
|
||||||
if (!req.body) return res.sendStatus(400);
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
accept: 'application/json',
|
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ contents: convertGooglePrompt(req.body, String(req.query.model)).contents }),
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
const reverseProxy = req.query.reverse_proxy?.toString() || '';
|
|
||||||
const proxyPassword = req.query.proxy_password?.toString() || '';
|
|
||||||
const apiKey = reverseProxy ? proxyPassword : readSecret(req.user.directories, SECRET_KEYS.MAKERSUITE);
|
|
||||||
const apiUrl = new URL(reverseProxy || API_MAKERSUITE);
|
|
||||||
const response = await fetch(`${apiUrl.origin}/v1beta/models/${req.query.model}:countTokens?key=${apiKey}`, options);
|
|
||||||
const data = await response.json();
|
|
||||||
return res.send({ 'token_count': data?.totalTokens || 0 });
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return res.send({ 'token_count': 0 });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post('/llama/encode', jsonParser, createSentencepieceEncodingHandler(spp_llama));
|
router.post('/llama/encode', jsonParser, createSentencepieceEncodingHandler(spp_llama));
|
||||||
router.post('/nerdstash/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd));
|
router.post('/nerdstash/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd));
|
||||||
router.post('/nerdstash_v2/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2));
|
router.post('/nerdstash_v2/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2));
|
||||||
router.post('/mistral/encode', jsonParser, createSentencepieceEncodingHandler(spp_mistral));
|
router.post('/mistral/encode', jsonParser, createSentencepieceEncodingHandler(spp_mistral));
|
||||||
router.post('/yi/encode', jsonParser, createSentencepieceEncodingHandler(spp_yi));
|
router.post('/yi/encode', jsonParser, createSentencepieceEncodingHandler(spp_yi));
|
||||||
router.post('/gemma/encode', jsonParser, createSentencepieceEncodingHandler(spp_gemma));
|
router.post('/gemma/encode', jsonParser, createSentencepieceEncodingHandler(spp_gemma));
|
||||||
|
router.post('/jamba/encode', jsonParser, createSentencepieceEncodingHandler(spp_jamba));
|
||||||
router.post('/gpt2/encode', jsonParser, createTiktokenEncodingHandler('gpt2'));
|
router.post('/gpt2/encode', jsonParser, createTiktokenEncodingHandler('gpt2'));
|
||||||
router.post('/claude/encode', jsonParser, createWebTokenizerEncodingHandler(claude_tokenizer));
|
router.post('/claude/encode', jsonParser, createWebTokenizerEncodingHandler(claude_tokenizer));
|
||||||
router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llama3_tokenizer));
|
router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llama3_tokenizer));
|
||||||
@ -599,6 +563,7 @@ router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandl
|
|||||||
router.post('/mistral/decode', jsonParser, createSentencepieceDecodingHandler(spp_mistral));
|
router.post('/mistral/decode', jsonParser, createSentencepieceDecodingHandler(spp_mistral));
|
||||||
router.post('/yi/decode', jsonParser, createSentencepieceDecodingHandler(spp_yi));
|
router.post('/yi/decode', jsonParser, createSentencepieceDecodingHandler(spp_yi));
|
||||||
router.post('/gemma/decode', jsonParser, createSentencepieceDecodingHandler(spp_gemma));
|
router.post('/gemma/decode', jsonParser, createSentencepieceDecodingHandler(spp_gemma));
|
||||||
|
router.post('/jamba/decode', jsonParser, createSentencepieceDecodingHandler(spp_jamba));
|
||||||
router.post('/gpt2/decode', jsonParser, createTiktokenDecodingHandler('gpt2'));
|
router.post('/gpt2/decode', jsonParser, createTiktokenDecodingHandler('gpt2'));
|
||||||
router.post('/claude/decode', jsonParser, createWebTokenizerDecodingHandler(claude_tokenizer));
|
router.post('/claude/decode', jsonParser, createWebTokenizerDecodingHandler(claude_tokenizer));
|
||||||
router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llama3_tokenizer));
|
router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llama3_tokenizer));
|
||||||
@ -637,6 +602,11 @@ router.post('/openai/encode', jsonParser, async function (req, res) {
|
|||||||
return handler(req, res);
|
return handler(req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (queryModel.includes('jamba')) {
|
||||||
|
const handler = createSentencepieceEncodingHandler(spp_jamba);
|
||||||
|
return handler(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
const model = getTokenizerModel(queryModel);
|
const model = getTokenizerModel(queryModel);
|
||||||
const handler = createTiktokenEncodingHandler(model);
|
const handler = createTiktokenEncodingHandler(model);
|
||||||
return handler(req, res);
|
return handler(req, res);
|
||||||
@ -680,6 +650,11 @@ router.post('/openai/decode', jsonParser, async function (req, res) {
|
|||||||
return handler(req, res);
|
return handler(req, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (queryModel.includes('jamba')) {
|
||||||
|
const handler = createSentencepieceDecodingHandler(spp_jamba);
|
||||||
|
return handler(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
const model = getTokenizerModel(queryModel);
|
const model = getTokenizerModel(queryModel);
|
||||||
const handler = createTiktokenDecodingHandler(model);
|
const handler = createTiktokenDecodingHandler(model);
|
||||||
return handler(req, res);
|
return handler(req, res);
|
||||||
@ -731,6 +706,11 @@ router.post('/openai/count', jsonParser, async function (req, res) {
|
|||||||
return res.send({ 'token_count': num_tokens });
|
return res.send({ 'token_count': num_tokens });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model === 'jamba') {
|
||||||
|
num_tokens = await countSentencepieceArrayTokens(spp_jamba, req.body);
|
||||||
|
return res.send({ 'token_count': num_tokens });
|
||||||
|
}
|
||||||
|
|
||||||
const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;
|
const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;
|
||||||
const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3;
|
const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3;
|
||||||
const tokensPadding = 3;
|
const tokensPadding = 3;
|
||||||
|
@ -110,27 +110,27 @@ router.post('/google', jsonParser, async (request, response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post('/yandex', jsonParser, async (request, response) => {
|
router.post('/yandex', jsonParser, async (request, response) => {
|
||||||
const chunks = request.body.chunks;
|
|
||||||
const lang = request.body.lang;
|
|
||||||
|
|
||||||
if (!chunks || !lang) {
|
|
||||||
return response.sendStatus(400);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reconstruct original text to log
|
|
||||||
let inputText = '';
|
|
||||||
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
for (const chunk of chunks) {
|
|
||||||
params.append('text', chunk);
|
|
||||||
inputText += chunk;
|
|
||||||
}
|
|
||||||
params.append('lang', lang);
|
|
||||||
const ucid = uuidv4().replaceAll('-', '');
|
|
||||||
|
|
||||||
console.log('Input text: ' + inputText);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const chunks = request.body.chunks;
|
||||||
|
const lang = request.body.lang;
|
||||||
|
|
||||||
|
if (!chunks || !lang) {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reconstruct original text to log
|
||||||
|
let inputText = '';
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
for (const chunk of chunks) {
|
||||||
|
params.append('text', chunk);
|
||||||
|
inputText += chunk;
|
||||||
|
}
|
||||||
|
params.append('lang', lang);
|
||||||
|
const ucid = uuidv4().replaceAll('-', '');
|
||||||
|
|
||||||
|
console.log('Input text: ' + inputText);
|
||||||
|
|
||||||
const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, {
|
const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: params,
|
body: params,
|
||||||
|
@ -267,10 +267,13 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = '
|
|||||||
'gemini-1.5-flash',
|
'gemini-1.5-flash',
|
||||||
'gemini-1.5-flash-latest',
|
'gemini-1.5-flash-latest',
|
||||||
'gemini-1.5-flash-001',
|
'gemini-1.5-flash-001',
|
||||||
|
'gemini-1.5-flash-exp-0827',
|
||||||
|
'gemini-1.5-flash-8b-exp-0827',
|
||||||
'gemini-1.5-pro',
|
'gemini-1.5-pro',
|
||||||
'gemini-1.5-pro-latest',
|
'gemini-1.5-pro-latest',
|
||||||
'gemini-1.5-pro-001',
|
'gemini-1.5-pro-001',
|
||||||
'gemini-1.5-pro-exp-0801',
|
'gemini-1.5-pro-exp-0801',
|
||||||
|
'gemini-1.5-pro-exp-0827',
|
||||||
'gemini-1.0-pro-vision-latest',
|
'gemini-1.0-pro-vision-latest',
|
||||||
'gemini-pro-vision',
|
'gemini-pro-vision',
|
||||||
];
|
];
|
||||||
@ -367,6 +370,78 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = '
|
|||||||
return { contents: contents, system_instruction: system_instruction };
|
return { contents: contents, system_instruction: system_instruction };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert AI21 prompt. Classic: system message squash, user/assistant message merge.
|
||||||
|
* @param {object[]} messages Array of messages
|
||||||
|
* @param {string} charName Character name
|
||||||
|
* @param {string} userName User name
|
||||||
|
*/
|
||||||
|
function convertAI21Messages(messages, charName = '', userName = '') {
|
||||||
|
if (!Array.isArray(messages)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all the system messages up until the first instance of a non-system message, and then remove them from the messages array.
|
||||||
|
let i = 0, systemPrompt = '';
|
||||||
|
|
||||||
|
for (i = 0; i < messages.length; i++) {
|
||||||
|
if (messages[i].role !== 'system') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Append example names if not already done by the frontend (e.g. for group chats).
|
||||||
|
if (userName && messages[i].name === 'example_user') {
|
||||||
|
if (!messages[i].content.startsWith(`${userName}: `)) {
|
||||||
|
messages[i].content = `${userName}: ${messages[i].content}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (charName && messages[i].name === 'example_assistant') {
|
||||||
|
if (!messages[i].content.startsWith(`${charName}: `)) {
|
||||||
|
messages[i].content = `${charName}: ${messages[i].content}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
systemPrompt += `${messages[i].content}\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.splice(0, i);
|
||||||
|
|
||||||
|
// Prevent erroring out if the messages array is empty.
|
||||||
|
if (messages.length === 0) {
|
||||||
|
messages.unshift({
|
||||||
|
role: 'user',
|
||||||
|
content: '[Start a new chat]',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (systemPrompt) {
|
||||||
|
messages.unshift({
|
||||||
|
role: 'system',
|
||||||
|
content: systemPrompt.trim(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doesn't support completion names, so prepend if not already done by the frontend (e.g. for group chats).
|
||||||
|
messages.forEach(msg => {
|
||||||
|
if ('name' in msg) {
|
||||||
|
if (msg.role !== 'system' && !msg.content.startsWith(`${msg.name}: `)) {
|
||||||
|
msg.content = `${msg.name}: ${msg.content}`;
|
||||||
|
}
|
||||||
|
delete msg.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Since the messaging endpoint only supports alternating turns, we have to merge messages with the same role if they follow each other
|
||||||
|
let mergedMessages = [];
|
||||||
|
messages.forEach((message) => {
|
||||||
|
if (mergedMessages.length > 0 && mergedMessages[mergedMessages.length - 1].role === message.role) {
|
||||||
|
mergedMessages[mergedMessages.length - 1].content += '\n\n' + message.content;
|
||||||
|
} else {
|
||||||
|
mergedMessages.push(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return mergedMessages;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a prompt from the ChatML objects to the format used by MistralAI.
|
* Convert a prompt from the ChatML objects to the format used by MistralAI.
|
||||||
* @param {object[]} messages Array of messages
|
* @param {object[]} messages Array of messages
|
||||||
@ -520,4 +595,5 @@ module.exports = {
|
|||||||
convertCohereMessages,
|
convertCohereMessages,
|
||||||
convertMistralMessages,
|
convertMistralMessages,
|
||||||
convertCohereTools,
|
convertCohereTools,
|
||||||
|
convertAI21Messages,
|
||||||
};
|
};
|
||||||
|
BIN
src/tokenizers/jamba.model
Normal file
BIN
src/tokenizers/jamba.model
Normal file
Binary file not shown.
@ -34,8 +34,9 @@ function getConfig() {
|
|||||||
CACHED_CONFIG = config;
|
CACHED_CONFIG = config;
|
||||||
return config;
|
return config;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to read config.yaml');
|
console.error(color.red('FATAL: Failed to read config.yaml. Please check the file for syntax errors.'));
|
||||||
return {};
|
console.error(error.message);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,8 +299,8 @@ const color = {
|
|||||||
* @returns {string} A UUIDv4 string
|
* @returns {string} A UUIDv4 string
|
||||||
*/
|
*/
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
if ('randomUUID' in crypto) {
|
if ('crypto' in global && 'randomUUID' in global.crypto) {
|
||||||
return crypto.randomUUID();
|
return global.crypto.randomUUID();
|
||||||
}
|
}
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
const r = Math.random() * 16 | 0;
|
const r = Math.random() * 16 | 0;
|
||||||
|
Reference in New Issue
Block a user