Merge branch 'staging' into pr/Cohee1207/2711
| @@ -8,7 +8,7 @@ | ||
| 8 | 8 | "openrouter_force_instruct": false, |
| 9 | 9 | "openrouter_group_models": false, |
| 10 | 10 | "openrouter_sort_models": "alphabetically", |
| 11 | 11 | "ai21_model": "j2jamba-ultra1.5-large", |
| 12 | 12 | "mistralai_model": "mistral-large-latest", |
| 13 | 13 | "custom_model": "", |
| 14 | 14 | "custom_url": "", |
| @@ -19,7 +19,6 @@ | ||
| 19 | 19 | "temperature": 1, |
| 20 | 20 | "frequency_penalty": 0, |
| 21 | 21 | "presence_penalty": 0, |
| 22 | - "count_penalty": 0, | |
| 23 | 22 | "top_p": 1, |
| 24 | 23 | "top_k": 0, |
| 25 | 24 | "top_a": 0, |
| @@ -233,8 +232,6 @@ | ||
| 233 | 232 | "assistant_prefill": "", |
| 234 | 233 | "assistant_impersonation": "", |
| 235 | 234 | "human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.", |
| 236 | - "use_ai21_tokenizer": false, | |
| 237 | - "use_google_tokenizer": false, | |
| 238 | 235 | "claude_use_sysprompt": false, |
| 239 | 236 | "use_alt_scale": false, |
| 240 | 237 | "squash_system_messages": false, |
| @@ -196,7 +196,15 @@ | ||
| 196 | 196 | "enableLabMode": false, |
| 197 | 197 | "enableZenSliders": false, |
| 198 | 198 | "ui_mode": 1, |
| 199 | 199 | "forbid_external_media": true, |
| 200 | + "stscript": { | |
| 201 | + "parser": { | |
| 202 | + "flags": { | |
| 203 | + "1": true, | |
| 204 | + "2": true | |
| 205 | + } | |
| 206 | + } | |
| 207 | + } | |
| 200 | 208 | }, |
| 201 | 209 | "extension_settings": { |
| 202 | 210 | "apiUrl": "http://localhost:5100", |
| @@ -452,7 +460,6 @@ | ||
| 452 | 460 | "temp_openai": 1.0, |
| 453 | 461 | "freq_pen_openai": 0, |
| 454 | 462 | "pres_pen_openai": 0, |
| 455 | - "count_pen": 0, | |
| 456 | 463 | "top_p_openai": 1, |
| 457 | 464 | "top_k_openai": 0, |
| 458 | 465 | "stream_openai": true, |
| @@ -614,7 +621,7 @@ | ||
| 614 | 621 | "wi_format": "{0}", |
| 615 | 622 | "openai_model": "gpt-4-turbo", |
| 616 | 623 | "claude_model": "claude-3-5-sonnet-20240620", |
| 617 | 624 | "ai21_model": "j2jamba-ultra1.5-large", |
| 618 | 625 | "windowai_model": "", |
| 619 | 626 | "openrouter_model": "OR_Website", |
| 620 | 627 | "jailbreak_system": true, |
| @@ -625,7 +632,6 @@ | ||
| 625 | 632 | "show_external_models": false, |
| 626 | 633 | "proxy_password": "", |
| 627 | 634 | "assistant_prefill": "", |
| 628 | 635 | "assistant_impersonation": "", |
| 629 | - "use_ai21_tokenizer": false | |
| 630 | 636 | } |
| 631 | 637 | } |
| @@ -5,7 +5,7 @@ | ||
| 5 | 5 | <title>SillyTavern</title> |
| 6 | 6 | <base href="/"> |
| 7 | 7 | <meta charset="utf-8"> |
| 8 | 8 | <meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content"> |
| 9 | 9 | <meta name="apple-mobile-web-app-capable" content="yes"> |
| 10 | 10 | <meta name="darkreader-lock"> |
| 11 | 11 | <meta name="robots" content="noindex, nofollow" /> |
| @@ -436,7 +436,7 @@ | ||
| 436 | 436 | </div> |
| 437 | 437 | </div> |
| 438 | 438 | </div> |
| 439 | 439 | <div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq"> |
| 440 | 440 | <div class="range-block-title" data-i18n="Frequency Penalty"> |
| 441 | 441 | Frequency Penalty |
| 442 | 442 | </div> |
| @@ -449,7 +449,7 @@ | ||
| 449 | 449 | </div> |
| 450 | 450 | </div> |
| 451 | 451 | </div> |
| 452 | 452 | <div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq"> |
| 453 | 453 | <div class="range-block-title" data-i18n="Presence Penalty"> |
| 454 | 454 | Presence Penalty |
| 455 | 455 | </div> |
| @@ -462,20 +462,7 @@ | ||
| 462 | 462 | </div> |
| 463 | 463 | </div> |
| 464 | 464 | </div> |
| 465 | 465 | <div data-newbie-hidden class="range-block" data-source="ai21claude,openrouter,makersuite,cohere,perplexity"> |
| 466 | - <div class="range-block-title" data-i18n="Count Penalty"> | |
| 467 | - Count Penalty | |
| 468 | - </div> | |
| 469 | - <div class="range-block-range-and-counter"> | |
| 470 | - <div class="range-block-range"> | |
| 471 | - <input type="range" id="count_pen" name="volume" min="0" max="1" step="0.01"> | |
| 472 | - </div> | |
| 473 | - <div class="range-block-counter"> | |
| 474 | - <input type="number" min="0" max="1" step="0.01" data-for="count_pen" id="count_pen_counter"> | |
| 475 | - </div> | |
| 476 | - </div> | |
| 477 | - </div> | |
| 478 | - <div data-newbie-hidden class="range-block" data-source="claude,openrouter,ai21,makersuite,cohere,perplexity"> | |
| 479 | 466 | <div class="range-block-title" data-i18n="Top K"> |
| 480 | 467 | Top K |
| 481 | 468 | </div> |
| @@ -1291,6 +1278,28 @@ | ||
| 1291 | 1278 | </div> |
| 1292 | 1279 | </div> |
| 1293 | 1280 | </div> |
| 1281 | + | |
| 1282 | + <div data-newbie-hidden data-tg-type="koboldcpp" id="xtc_block" class="wide100p"> | |
| 1283 | + <h4 class="wide100p textAlignCenter"> | |
| 1284 | + <label data-i18n="Exclude Top Choices (XTC)">Exclude Top Choices (XTC)</label> | |
| 1285 | + <a href="https://github.com/oobabooga/text-generation-webui/pull/6335" target="_blank"> | |
| 1286 | + <div class=" fa-solid fa-circle-info opacity50p"></div> | |
| 1287 | + </a> | |
| 1288 | + </h4> | |
| 1289 | + <div class="flex-container flexFlowRow gap10px flexShrink"> | |
| 1290 | + <div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0"> | |
| 1291 | + <small data-i18n="Threshold">Threshold</small> | |
| 1292 | + <input class="neo-range-slider" type="range" id="xtc_threshold_textgenerationwebui" name="volume" min="0" max="0.5" step="0.01" /> | |
| 1293 | + <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"> | |
| 1294 | + </div> | |
| 1295 | + <div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0"> | |
| 1296 | + <small data-i18n="Probability">Probability</small> | |
| 1297 | + <input class="neo-range-slider" type="range" id="xtc_probability_textgenerationwebui" name="volume" min="0" max="1" step="0.01" /> | |
| 1298 | + <input class="neo-range-input" type="number" min="0" max="1" step="0.01" data-for="xtc_probability_textgenerationwebui" id="xtc_probability_counter_textgenerationwebui"> | |
| 1299 | + </div> | |
| 1300 | + </div> | |
| 1301 | + </div> | |
| 1302 | + | |
| 1294 | 1303 | <!-- Enable for llama.cpp when the PR is merged: https://github.com/ggerganov/llama.cpp/pull/6839 --> |
| 1295 | 1304 | <div data-newbie-hidden data-tg-type="ooba, koboldcpp" id="dryBlock" class="wide100p"> |
| 1296 | 1305 | <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 @@ | ||
| 1484 | 1493 | <div id="banned_tokens_block_ooba" data-newbie-hidden class="wide100p"> |
| 1485 | 1494 | <hr data-newbie-hidden class="width100p"> |
| 1486 | 1495 | <h4 class="range-block-title justifyCenter"> |
| 1487 | 1496 | <span data-i18n="Banned Tokens">Banned Tokens/Strings</span> |
| 1488 | 1497 | <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 tokenizerEnter first. Sequencessequences you don't want to appear in the output. OneUnquoted pertext line.will Textbe ortokenized 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> |
| 1489 | 1498 | </h4> |
| 1490 | 1499 | <div class="wide100p"> |
| 1491 | 1500 | <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 as tokens [42420, 69, 1337] "Some verbatim string"'></textarea> |
| 1492 | 1501 | </div> |
| 1493 | 1502 | </div> |
| 1494 | 1503 | <div class="range-block wide100p"> |
| @@ -1791,22 +1800,6 @@ | ||
| 1791 | 1800 | </select> |
| 1792 | 1801 | </div> |
| 1793 | 1802 | </div> |
| 1794 | - <div class="range-block" data-source="ai21"> | |
| 1795 | - <label for="use_ai21_tokenizer" title="Use AI21 Tokenizer" data-i18n="[title]Use AI21 Tokenizer" class="checkbox_label widthFreeExpand"> | |
| 1796 | - <input id="use_ai21_tokenizer" type="checkbox" /><span data-i18n="Use AI21 Tokenizer">Use AI21 Tokenizer</span> | |
| 1797 | - </label> | |
| 1798 | - <div class="toggle-description justifyLeft"> | |
| 1799 | - <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> | |
| 1800 | - </div> | |
| 1801 | - </div> | |
| 1802 | - <div class="range-block" data-source="makersuite"> | |
| 1803 | - <label for="use_google_tokenizer" title="Use Google Tokenizer" data-i18n="[title]Use Google Tokenizer" class="checkbox_label widthFreeExpand"> | |
| 1804 | - <input id="use_google_tokenizer" type="checkbox" /><span data-i18n="Use Google Tokenizer">Use Google Tokenizer</span> | |
| 1805 | - </label> | |
| 1806 | - <div class="toggle-description justifyLeft"> | |
| 1807 | - <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> | |
| 1808 | - </div> | |
| 1809 | - </div> | |
| 1810 | 1803 | <div class="range-block" data-source="makersuite"> |
| 1811 | 1804 | <label for="use_makersuite_sysprompt" class="checkbox_label widthFreeExpand"> |
| 1812 | 1805 | <input id="use_makersuite_sysprompt" type="checkbox" /> |
| @@ -1852,7 +1845,7 @@ | ||
| 1852 | 1845 | <div class="fa-solid fa-clock-rotate-left"></div> |
| 1853 | 1846 | </div> |
| 1854 | 1847 | </div> |
| 1855 | 1848 | <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> |
| 1856 | 1849 | </div> |
| 1857 | 1850 | </div> |
| 1858 | 1851 | </div> |
| @@ -2791,10 +2784,12 @@ | ||
| 2791 | 2784 | <div> |
| 2792 | 2785 | <h4 data-i18n="AI21 Model">AI21 Model</h4> |
| 2793 | 2786 | <select id="model_ai21_select"> |
| 2794 | 2787 | <optgroup label="LatestJamba 1.5"> |
| 2795 | 2788 | <option value="j2jamba-ultra1.5-mini">j2jamba-ultra1.5-mini</option> |
| 2796 | 2789 | <option value="j2jamba-mid1.5-large">j2jamba-mid1.5-large</option> |
| 2797 | - <option value="j2-light">j2-light</option> | |
| 2790 | + </optgroup> | |
| 2791 | + <optgroup label="Jamba-Instruct (Deprecated)"> | |
| 2792 | + <option value="jamba-instruct-preview">jamba-instruct-preview</option> | |
| 2798 | 2793 | </optgroup> |
| 2799 | 2794 | </select> |
| 2800 | 2795 | </div> |
| @@ -2824,8 +2819,11 @@ | ||
| 2824 | 2819 | </optgroup> |
| 2825 | 2820 | <optgroup label="Subversions"> |
| 2826 | 2821 | <option value="gemini-1.5-pro-exp-0801">Gemini 1.5 Pro Experiment 2024-08-01</option> |
| 2822 | + <option value="gemini-1.5-pro-exp-0827">Gemini 1.5 Pro Experiment 2024-08-27</option> | |
| 2827 | 2823 | <option value="gemini-1.5-pro-latest">Gemini 1.5 Pro [latest]</option> |
| 2828 | 2824 | <option value="gemini-1.5-pro-001">Gemini 1.5 Pro [001]</option> |
| 2825 | + <option value="gemini-1.5-flash-exp-0827">Gemini 1.5 Flash Experiment 2024-08-27</option> | |
| 2826 | + <option value="gemini-1.5-flash-8b-exp-0827">Gemini 1.5 Flash 8B Experiment 2024-08-27</option> | |
| 2829 | 2827 | <option value="gemini-1.5-flash-latest">Gemini 1.5 Flash [latest]</option> |
| 2830 | 2828 | <option value="gemini-1.5-flash-001">Gemini 1.5 Flash [001]</option> |
| 2831 | 2829 | <option value="gemini-1.0-pro-latest">Gemini 1.0 Pro [latest]</option> |
| @@ -2955,6 +2953,8 @@ | ||
| 2955 | 2953 | <option value="command">command</option> |
| 2956 | 2954 | <option value="command-r">command-r</option> |
| 2957 | 2955 | <option value="command-r-plus">command-r-plus</option> |
| 2956 | + <option value="command-r-08-2024">command-r-08-2024</option> | |
| 2957 | + <option value="command-r-plus-08-2024">command-r-plus-08-2024</option> | |
| 2958 | 2958 | </optgroup> |
| 2959 | 2959 | <optgroup label="Nightly"> |
| 2960 | 2960 | <option value="command-light-nightly">command-light-nightly</option> |
| @@ -4012,7 +4012,7 @@ | ||
| 4012 | 4012 | <input id="movingUImode" type="checkbox" /> |
| 4013 | 4013 | <small data-i18n="Movable UI Panels">MovingUI <i class="fa-solid fa-desktop"></i></small> |
| 4014 | 4014 | </label> |
| 4015 | 4015 | <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> |
| 4016 | 4016 | </div> |
| 4017 | 4017 | <div data-newbie-hidden id="MovingUI-presets-block" class="flex-container alignitemscenter"> |
| 4018 | 4018 | <div class="flex-container alignItemsFlexEnd"> |
| @@ -4503,6 +4503,7 @@ | ||
| 4503 | 4503 | <div data-newbie-hidden> |
| 4504 | 4504 | <label for="persona_description_position" data-i18n="Position:">Position:</label> |
| 4505 | 4505 | <select id="persona_description_position"> |
| 4506 | + <option value="9" data-i18n="None (disabled)">None (disabled)</option> | |
| 4506 | 4507 | <option value="0" data-i18n="In Story String / Prompt Manager">In Story String / Prompt Manager</option> |
| 4507 | 4508 | <option value="2" data-i18n="Top of Author's Note">Top of Author's Note</option> |
| 4508 | 4509 | <option value="3" data-i18n="Bottom of Author's Note">Bottom of Author's Note</option> |
| @@ -6488,6 +6489,7 @@ | ||
| 6488 | 6489 | <script src="lib/jquery-cookie-1.4.1.min.js"></script> |
| 6489 | 6490 | <script src="lib/jquery.ui.touch-punch.min.js"></script> |
| 6490 | 6491 | <script src="lib/showdown.min.js"></script> |
| 6492 | + <script src="lib/showdown-patch.js"></script> | |
| 6491 | 6493 | <script src="lib/showdown-katex.min.js"></script> |
| 6492 | 6494 | <script src="lib/popper.js"></script> |
| 6493 | 6495 | <script src="lib/purify.min.js"></script> |
| @@ -0,0 +1,24 @@ | ||
| 1 | +showdown.subParser('unhashHTMLSpans', function (text, options, globals) { | |
| 2 | + 'use strict'; | |
| 3 | + text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals); | |
| 4 | + | |
| 5 | + for (var i = 0; i < globals.gHtmlSpans.length; ++i) { | |
| 6 | + var repText = globals.gHtmlSpans[i], | |
| 7 | + // limiter to prevent infinite loop (assume 10 as limit for recurse) | |
| 8 | + limit = 0; | |
| 9 | + | |
| 10 | + while (/¨C(\d+)C/.test(repText)) { | |
| 11 | + var num = RegExp.$1; | |
| 12 | + repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]); | |
| 13 | + if (limit === 10000) { | |
| 14 | + console.error('maximum nesting of 10000 spans reached!!!'); | |
| 15 | + break; | |
| 16 | + } | |
| 17 | + ++limit; | |
| 18 | + } | |
| 19 | + text = text.replace('¨C' + i + 'C', repText); | |
| 20 | + } | |
| 21 | + | |
| 22 | + text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals); | |
| 23 | + return text; | |
| 24 | +}); | |
| @@ -43,7 +43,7 @@ | ||
| 43 | 43 | "Smoothing Factor": "Коэффициент сглаживания", |
| 44 | 44 | "No Repeat Ngram Size": "Размер no_repeat_ngram", |
| 45 | 45 | "Min Length": "Мин. длина", |
| 46 | 46 | "Alternative server URL (leave empty to use the default value).": "Альтернативный URL альтернативного сервера (оставьте пустым для стандартного значения)", |
| 47 | 47 | "Remove your real OAI API Key from the API panel BEFORE typing anything into this box": "Удалите свой личный OAI API Key из панели API, и ТОЛЬКО ПОСЛЕ ЭТОГО вводите что-то сюда", |
| 48 | 48 | "We cannot provide support for problems encountered while using an unofficial OpenAI proxy": "Мы не сможем предоставить помощь с проблемами, с которыми вы столкнетесь при использовании неофициальных прокси для OpenAI", |
| 49 | 49 | "Context Size (tokens)": "Размер контекста (в токенах)", |
| @@ -186,7 +186,7 @@ | ||
| 186 | 186 | "Generate only one line per request": "Генерировать одну строку на запрос", |
| 187 | 187 | "Misc. Settings": "Доп. настройки", |
| 188 | 188 | "Auto-Continue": "Авто-продолжение", |
| 189 | 189 | "Collapse Consecutive Newlines": "Сворачивать последовательныенеск. новыеновых строкистрок в одну", |
| 190 | 190 | "Allow for Chat Completion APIs": "Разрешить для Chat Completion API", |
| 191 | 191 | "Target length (tokens)": "Целевая длина (в токенах)", |
| 192 | 192 | "World Info": "Информация о мире", |
| @@ -373,7 +373,7 @@ | ||
| 373 | 373 | "Prefer Character Card Prompt": "Приоритет промпту из карточки персонажа", |
| 374 | 374 | "Prefer Character Card Jailbreak": "Приоритет джейлбрейку из карточки персонажа", |
| 375 | 375 | "Press Send to continue": "Кнопка отправки продолжает сообщение", |
| 376 | 376 | "Quick 'Continue' button": "Кнопка быстрогоБыстрое продолженияпродолжение", |
| 377 | 377 | "Log prompts to console": "Выводить промпты в консоль", |
| 378 | 378 | "Never resize avatars": "Не менять размер аватарок", |
| 379 | 379 | "Show avatar filenames": "Показывать названия файлов аватарок", |
| @@ -495,7 +495,7 @@ | ||
| 495 | 495 | "(Write a comma-separated list of tags)": "(Список тегов через запятую)", |
| 496 | 496 | "(A brief description of the personality)": "(Краткое описание личности)", |
| 497 | 497 | "(Circumstances and context of the interaction)": "(Обстоятельства и контекст этого диалога)", |
| 498 | 498 | "(Examples of chat dialog. Begin each example with START on a new line.)": "(Примеры диалога. Начинайте каждый пример с START или новой линиейстрокой.)", |
| 499 | 499 | "Type here...": "Пишите здесь...", |
| 500 | 500 | "Comma separated (required)": "Через запятую (обязательное поле)", |
| 501 | 501 | "What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно", |
| @@ -552,7 +552,7 @@ | ||
| 552 | 552 | "Click to set a new User Name": "Нажмите, чтобы задать новое имя пользователя.", |
| 553 | 553 | "Click to lock your selected persona to the current chat. Click again to remove the lock.": "Нажмите, чтобы закрепить выбранную персону для текущего чата. Нажмите еще раз, чтобы открепить.", |
| 554 | 554 | "Click to set user name for all messages": "Нажмите, чтобы задать имя пользователя для всех сообщений.", |
| 555 | 555 | "Create a dummy persona": "Создать пустую персону-болванку", |
| 556 | 556 | "Character Management": "Управление персонажами", |
| 557 | 557 | "Locked = Character Management panel will stay open": "Закреплено = Панель управление персонажами останется открытой", |
| 558 | 558 | "Select/Create Characters": "Выбрать/Создать персонажа", |
| @@ -625,7 +625,7 @@ | ||
| 625 | 625 | "Automatically select a background based on the chat context": "Автоматический выбор фона в зависимости от контекста чата", |
| 626 | 626 | "Filter": "Фильтр", |
| 627 | 627 | "Exclude message from prompts": "Исключить сообщение из промпта", |
| 628 | 628 | "Include message in prompts": "Включить сообщение в подсказкипромпт", |
| 629 | 629 | "Create checkpoint": "Создать чекпоинт", |
| 630 | 630 | "Create Branch": "Создать ветку", |
| 631 | 631 | "Embed file or image": "Вставить файл или изображение", |
| @@ -1661,5 +1661,52 @@ | ||
| 1661 | 1661 | "ext_regex_ai_output_desc": "Сообщения, полученные от API", |
| 1662 | 1662 | "ext_regex_sts_desc": "Сообщения, отправленные с помощью команд STscript", |
| 1663 | 1663 | "ext_regex_wi_desc": "Содержимое лорбуков и миров. Для работы требует включения флажка \"Только промпт\"!", |
| 1664 | 1664 | "ext_regex_only_format_display_desc": "История чата не изменится, замена будет осуществляться только в отображаемом сообщении (в UI)", |
| 1665 | + "Prefer Character Card Instructions": "Приоритет инструкциям из карточек", | |
| 1666 | + "If checked and the character card contains a Post-History Instructions override, use that instead": "Если в карточке персонажа имеется собственная инструкция после истории, в промпт попадёт именно она", | |
| 1667 | + "Auto-select Input Text": "Автовыделение вводимого текста", | |
| 1668 | + "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.": "Автоматически выделять вводимый текст в некоторых текстовых полях при клике/выборе. Работает для вспл. окон и различных кастомных полей ввода.", | |
| 1669 | + "Reset MovingUI panel sizes/locations.": "Сбросить расположение и размеры панелей MovingUI.", | |
| 1670 | + "mui_reset": "Сброс", | |
| 1671 | + "Quick 'Impersonate' button": "Быстрое перевоплощение", | |
| 1672 | + "Show a button in the input area to ask the AI to impersonate your character for a single message": "Показать в поле ввода кнопку, по нажатии на которую ИИ сгенерирует одно сообщение от лица вашего персонажа.", | |
| 1673 | + "Separators as Stop Strings": "Разделители как стоп-строки", | |
| 1674 | + "Names as Stop Strings": "Имена как стоп-строки", | |
| 1675 | + "Add Character and User names to a list of stopping strings.": "Добавлять имена персонажа и пользователя в список стоп-строк.", | |
| 1676 | + "Allow Post-History Instructions": "Разрешить инструкции после истории", | |
| 1677 | + "context_allow_post_history_instructions": "Добавлять в конец промпта инструкции после истории. Работает только при наличии таких инструкций в карточке И при включенной опции ''Приоритет инструкциям из карточек''.\nНЕ РЕКОМЕНДУЕТСЯ ДЛЯ МОДЕЛЕЙ TEXT COMPLETION, МОЖЕТ ПОРТИТЬ ВЫХОДНОЙ ТЕКСТ.", | |
| 1678 | + "First User Prefix": "Первый префикс пользователя", | |
| 1679 | + "Inserted before the first User's message.": "Вставляется перед первым сообщением пользователя.", | |
| 1680 | + "Last User Prefix": "Последний префикс пользователя", | |
| 1681 | + "instruct_last_input_sequence": "Вставляется перед последним сообщением пользователя.", | |
| 1682 | + "Inserted before a User message and as a last prompt line when impersonating.": "Вставляется перед сообщением пользователя в качестве последней строки промпта при перевоплощении.", | |
| 1683 | + "Inserted before a System (added by slash commands or extensions) message.": "Вставляется перед сообщением системы (может быть добавлено слэш-командой или расширением).", | |
| 1684 | + "Load Asset List": "Загрузить список ресурсов", | |
| 1685 | + "Never add character names.": "Не вставлять имя персонажа.", | |
| 1686 | + "Don't add character names unless necessary.": "Вставлять имя персонажа только когда это необходимо.", | |
| 1687 | + "character_names_none": "Не добавлять имена персонажей в качестве префикса. Может повредить качеству ответов в групповых чатах, используйте с осторожностью.", | |
| 1688 | + "Auxiliary": "Вспомогательный", | |
| 1689 | + "Post-History Instructions": "Инструкции после истории", | |
| 1690 | + "Current persona updated": "Текущая персона изменена", | |
| 1691 | + "Your messages will now be sent as ${0}": "Ваши сообщения будут отправляться от лица ${0}", | |
| 1692 | + "Copied!": "Скопировано!", | |
| 1693 | + "Are you sure you want to delete this message?": "Вы точно хотите удалить это сообщение?", | |
| 1694 | + "Delete Message": "Удалить сообщение", | |
| 1695 | + "Delete Swipe": "Удалить свайп", | |
| 1696 | + "Could not get a reply from API. Check your connection settings / API key and try again.": "Не удалось получить ответ от API. Проверьте настройки соединения и API-ключ и повторите попытку.", | |
| 1697 | + "Connecting To Proxy": "Подключение к прокси", | |
| 1698 | + "Are you sure you want to connect to the following proxy URL?": "Вы точно хотите соединиться с прокси по этому адресу?", | |
| 1699 | + "API connection successful!": "Соединение с API установлено!", | |
| 1700 | + "Proxy Saved": "Прокси сохранена", | |
| 1701 | + "Proxy Deleted": "Прокси удалена", | |
| 1702 | + "Could not find proxy with name '${0}'": "Не удалось найти прокси с названием '${0}'", | |
| 1703 | + "Proxy preset '${0}' not found in proxies array.": "Пресет с названием '${0}' не найден в списке прокси.", | |
| 1704 | + "Please wait for the previous request to complete.": "Пожалуйста, дождитесь окончания обработки предыдущего запроса.", | |
| 1705 | + "Start new chat?": "Начать новый чат?", | |
| 1706 | + "If necessary, you can later restore this chat file from the /backups folder": "При необходимости этот чат можно будет восстановить из папки /backups", | |
| 1707 | + "Also delete the current chat file": "Также удалить текущий чат", | |
| 1708 | + "chat_rename_1": "Введите новое имя чата:", | |
| 1709 | + "chat_rename_2": "!!Не используйте имя уже существующего файла, это приведёт к ошибке!!", | |
| 1710 | + "chat_rename_3": "Будут разрушены связи между чатами-чекпоинтами.", | |
| 1711 | + "chat_rename_4": "Расширение '.jsonl' дописывать не нужно." | |
| 1665 | 1712 | } |
| @@ -488,14 +488,6 @@ let default_user_name = 'User'; | ||
| 488 | 488 | export let name1 = default_user_name; |
| 489 | 489 | export let name2 = 'SillyTavern System'; |
| 490 | 490 | export let chat = []; |
| 491 | -let safetychat = [ | |
| 492 | - { | |
| 493 | - name: systemUserName, | |
| 494 | - is_user: false, | |
| 495 | - create_date: 0, | |
| 496 | - mes: 'You deleted a character/chat and arrived back here for safety reasons! Pick another character!', | |
| 497 | - }, | |
| 498 | -]; | |
| 499 | 491 | let chatSaveTimeout; |
| 500 | 492 | let importFlashTimeout; |
| 501 | 493 | export let isChatSaving = false; |
| @@ -594,6 +586,17 @@ export const extension_prompt_roles = { | ||
| 594 | 586 | |
| 595 | 587 | export const MAX_INJECTION_DEPTH = 1000; |
| 596 | 588 | |
| 589 | +const SAFETY_CHAT = [ | |
| 590 | + { | |
| 591 | + name: systemUserName, | |
| 592 | + force_avatar: system_avatar, | |
| 593 | + is_system: true, | |
| 594 | + is_user: false, | |
| 595 | + create_date: 0, | |
| 596 | + mes: 'You deleted a character/chat and arrived back here for safety reasons! Pick another character!', | |
| 597 | + }, | |
| 598 | +]; | |
| 599 | + | |
| 597 | 600 | export let system_messages = {}; |
| 598 | 601 | |
| 599 | 602 | async function getSystemMessages() { |
| @@ -2192,7 +2195,7 @@ export function addCopyToCodeBlocks(messageElement) { | ||
| 2192 | 2195 | codeBlocks.get(i).appendChild(copyButton); |
| 2193 | 2196 | copyButton.addEventListener('pointerup', function (event) { |
| 2194 | 2197 | navigator.clipboard.writeText(codeBlocks.get(i).innerText); |
| 2195 | 2198 | toastr.info('t`Copied!'`, '', { timeOut: 2000 }); |
| 2196 | 2199 | }); |
| 2197 | 2200 | } |
| 2198 | 2201 | } |
| @@ -2705,7 +2708,7 @@ function addPersonaDescriptionExtensionPrompt() { | ||
| 2705 | 2708 | const INJECT_TAG = 'PERSONA_DESCRIPTION'; |
| 2706 | 2709 | setExtensionPrompt(INJECT_TAG, '', extension_prompt_types.IN_PROMPT, 0); |
| 2707 | 2710 | |
| 2708 | 2711 | if (!power_user.persona_description || power_user.persona_description_position === persona_description_positions.NONE) { |
| 2709 | 2712 | return; |
| 2710 | 2713 | } |
| 2711 | 2714 | |
| @@ -2826,7 +2829,7 @@ export function getCharacterCardFields() { | ||
| 2826 | 2829 | } |
| 2827 | 2830 | |
| 2828 | 2831 | export function isStreamingEnabled() { |
| 2829 | 2832 | const noStreamSources = [chat_completion_sources.SCALE, chat_completion_sources.AI21]; |
| 2830 | 2833 | 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'))) |
| 2831 | 2834 | || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming) |
| 2832 | 2835 | || (main_api == 'novel' && nai_settings.streaming_novel) |
| @@ -3726,7 +3729,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3726 | 3729 | const storyStringParams = { |
| 3727 | 3730 | description: description, |
| 3728 | 3731 | personality: personality, |
| 3729 | - persona: persona, | |
| 3732 | + persona: power_user.persona_description_position == persona_description_positions.IN_PROMPT ? persona : '', | |
| 3730 | 3733 | scenario: scenario, |
| 3731 | 3734 | system: isInstruct ? system : '', |
| 3732 | 3735 | char: name2, |
| @@ -3760,7 +3763,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3760 | 3763 | } |
| 3761 | 3764 | |
| 3762 | 3765 | let examplesString = ''; |
| 3763 | 3766 | let chatString = addChatsPreamble(addChatsSeparator('')); |
| 3764 | 3767 | let cyclePrompt = ''; |
| 3765 | 3768 | |
| 3766 | 3769 | async function getMessagesTokenCount() { |
| @@ -3769,10 +3772,10 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3769 | 3772 | storyString, |
| 3770 | 3773 | afterScenarioAnchor, |
| 3771 | 3774 | examplesString, |
| 3775 | + userAlignmentMessage, | |
| 3772 | 3776 | chatString, |
| 3773 | - quiet_prompt, | |
| 3777 | + modifyLastPromptLine(''), | |
| 3774 | 3778 | cyclePrompt, |
| 3775 | - userAlignmentMessage, | |
| 3776 | 3779 | ].join('').replace(/\r/gm, ''); |
| 3777 | 3780 | return getTokenCountAsync(encodeString, power_user.token_padding); |
| 3778 | 3781 | } |
| @@ -3803,8 +3806,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3803 | 3806 | } |
| 3804 | 3807 | |
| 3805 | 3808 | tokenCount += await getTokenCountAsync(item.replace(/\r/gm, '')); |
| 3806 | - chatString = item + chatString; | |
| 3807 | 3809 | if (tokenCount < this_max_context) { |
| 3810 | + chatString = chatString + item; | |
| 3808 | 3811 | arrMes[index] = item; |
| 3809 | 3812 | lastAddedIndex = Math.max(lastAddedIndex, index); |
| 3810 | 3813 | } else { |
| @@ -3830,8 +3833,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3830 | 3833 | } |
| 3831 | 3834 | |
| 3832 | 3835 | tokenCount += await getTokenCountAsync(item.replace(/\r/gm, '')); |
| 3833 | - chatString = item + chatString; | |
| 3834 | 3836 | if (tokenCount < this_max_context) { |
| 3837 | + chatString = chatString + item; | |
| 3835 | 3838 | arrMes[i] = item; |
| 3836 | 3839 | lastAddedIndex = Math.max(lastAddedIndex, i); |
| 3837 | 3840 | } else { |
| @@ -4028,15 +4031,16 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4028 | 4031 | async function checkPromptSize() { |
| 4029 | 4032 | console.debug('---checking Prompt size'); |
| 4030 | 4033 | setPromptString(); |
| 4034 | + const jointMessages = mesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join(''); | |
| 4031 | 4035 | const prompt = [ |
| 4032 | 4036 | beforeScenarioAnchor, |
| 4033 | 4037 | storyString, |
| 4034 | 4038 | afterScenarioAnchor, |
| 4035 | 4039 | mesExmString, |
| 4036 | - mesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join(''), | |
| 4040 | + addChatsPreamble(addChatsSeparator(jointMessages)), | |
| 4037 | 4041 | '\n', |
| 4042 | + modifyLastPromptLine(''), | |
| 4038 | 4043 | generatedPromptCache, |
| 4039 | - quiet_prompt, | |
| 4040 | 4044 | ].join('').replace(/\r/gm, ''); |
| 4041 | 4045 | let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding); |
| 4042 | 4046 | |
| @@ -4302,7 +4306,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4302 | 4306 | padding: power_user.token_padding, |
| 4303 | 4307 | main_api: main_api, |
| 4304 | 4308 | instruction: isInstruct ? substituteParams(power_user.prefer_character_prompt && system ? system : power_user.instruct.system_prompt) : '', |
| 4305 | 4309 | userPersona: (power_user.persona_descriptionpersona_description_position == persona_description_positions.IN_PROMPT ? (persona || '') : ''), |
| 4306 | 4310 | }; |
| 4307 | 4311 | |
| 4308 | 4312 | //console.log(additionalPromptStuff); |
| @@ -5080,7 +5084,7 @@ async function promptItemize(itemizedPrompts, requestedMesId) { | ||
| 5080 | 5084 | } |
| 5081 | 5085 | |
| 5082 | 5086 | navigator.clipboard.writeText(rawPromptValues); |
| 5083 | 5087 | toastr.info('t`Copied!'`); |
| 5084 | 5088 | }); |
| 5085 | 5089 | |
| 5086 | 5090 | popup.dlg.querySelector('#showRawPrompt').addEventListener('click', function () { |
| @@ -5679,7 +5683,7 @@ export function resetChatState() { | ||
| 5679 | 5683 | // replaces deleted charcter name with system user since it will be displayed next. |
| 5680 | 5684 | name2 = systemUserName; |
| 5681 | 5685 | // sets up system user to tell user about having deleted a character |
| 5682 | 5686 | chat.splice(0, =chat.length, [...safetychat]SAFETY_CHAT); |
| 5683 | 5687 | // resets chat metadata |
| 5684 | 5688 | chat_metadata = {}; |
| 5685 | 5689 | // resets the characters array, forcing getcharacters to reset |
| @@ -6310,7 +6314,7 @@ export function setUserName(value) { | ||
| 6310 | 6314 | console.log(`User name changed to ${name1}`); |
| 6311 | 6315 | $('#your_name').val(name1); |
| 6312 | 6316 | if (power_user.persona_show_notifications) { |
| 6313 | 6317 | toastr.success(t`Your messages will now be sent as ${name1}`, 't`Current persona updated'`); |
| 6314 | 6318 | } |
| 6315 | 6319 | saveSettingsDebounced(); |
| 6316 | 6320 | } |
| @@ -8840,16 +8844,21 @@ export async function handleDeleteCharacter(this_chid, delete_chats) { | ||
| 8840 | 8844 | /** |
| 8841 | 8845 | * Deletes a character completely, including associated chats if specified |
| 8842 | 8846 | * |
| 8843 | 8847 | * @param {string|string[]} characterKey - The key (avatar) of the character to be deleted |
| 8844 | 8848 | * @param {Object} [options] - Optional parameters for the deletion |
| 8845 | 8849 | * @param {boolean} [options.deleteChats=true] - Whether to delete associated chats or not |
| 8846 | 8850 | * @return {Promise<void>} - A promise that resolves when the character is successfully deleted |
| 8847 | 8851 | */ |
| 8848 | 8852 | export async function deleteCharacter(characterKey, { deleteChats = true } = {}) { |
| 8849 | - const character = characters.find(x => x.avatar == characterKey); | |
| 8853 | + if (!Array.isArray(characterKey)) { | |
| 8854 | + characterKey = [characterKey]; | |
| 8855 | + } | |
| 8856 | + | |
| 8857 | + for (const key of characterKey) { | |
| 8858 | + const character = characters.find(x => x.avatar == key); | |
| 8850 | 8859 | if (!character) { |
| 8851 | 8860 | toastr.warning(`Character ${characterKeykey} not found. Cannot beSkipping deleteddeletion.`); |
| 8852 | - return; | |
| 8861 | + continue; | |
| 8853 | 8862 | } |
| 8854 | 8863 | |
| 8855 | 8864 | const chid = characters.indexOf(character); |
| @@ -8865,10 +8874,12 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {}) | ||
| 8865 | 8874 | }); |
| 8866 | 8875 | |
| 8867 | 8876 | if (!response.ok) { |
| 8868 | 8877 | throw new Error toastr.error(`Failed to delete character: ${response.status} ${response.statusText}`, 'Failed to delete character'); |
| 8878 | + continue; | |
| 8869 | 8879 | } |
| 8870 | 8880 | |
| 8871 | - await removeCharacterFromUI(character.name, character.avatar); | |
| 8881 | + delete tag_map[character.avatar]; | |
| 8882 | + select_rm_info('char_delete', character.name); | |
| 8872 | 8883 | |
| 8873 | 8884 | if (deleteChats) { |
| 8874 | 8885 | for (const chat of pastChats) { |
| @@ -8877,35 +8888,30 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {}) | ||
| 8877 | 8888 | } |
| 8878 | 8889 | } |
| 8879 | 8890 | |
| 8880 | 8891 | await eventSource.emit(event_types.CHARACTER_DELETED, { id: this_chidchid, character: characters[this_chid]character }); |
| 8892 | + } | |
| 8893 | + | |
| 8894 | + await removeCharacterFromUI(); | |
| 8881 | 8895 | } |
| 8882 | 8896 | |
| 8883 | 8897 | /** |
| 8884 | 8898 | * Function to delete a character from UI after character deletion API success. |
| 8885 | 8899 | * It manages necessary UI changes such as closing advanced editing popup, unsetting |
| 8886 | 8900 | * character ID, resetting characters array and chat metadata, deselecting character's tab |
| 8887 | 8901 | * panel, removing character name from navigation tabs, clearing chat, removingfetching character'supdated list of characters. |
| 8888 | - * avatar from tag_map, fetching updated list of characters and updating the 'deleted | |
| 8889 | - * character' message. | |
| 8890 | 8902 | * It also ensures to save the settings after all the operations. |
| 8891 | - * | |
| 8892 | - * @param {string} name - The name of the character to be deleted. | |
| 8893 | - * @param {string} avatar - The avatar URL of the character to be deleted. | |
| 8894 | - * @param {boolean} reloadCharacters - Whether the character list should be refreshed after deletion. | |
| 8895 | 8903 | */ |
| 8896 | 8904 | async function removeCharacterFromUI(name, avatar, reloadCharacters = true) { |
| 8897 | 8905 | await clearChat(); |
| 8898 | 8906 | $('#character_cross').click(); |
| 8899 | 8907 | this_chid = undefined; |
| 8900 | 8908 | characters.length = 0; |
| 8901 | 8909 | name2 = systemUserName; |
| 8902 | 8910 | chat.splice(0, =chat.length, [...safetychat]SAFETY_CHAT); |
| 8903 | 8911 | chat_metadata = {}; |
| 8904 | 8912 | $(document.getElementById('rm_button_selected_ch')).children('h2').text(''); |
| 8905 | 8913 | this_chid = undefined; |
| 8906 | - delete tag_map[avatar]; | |
| 8914 | + await getCharacters(); | |
| 8907 | - if (reloadCharacters) await getCharacters(); | |
| 8908 | - select_rm_info('char_delete', name); | |
| 8909 | 8915 | await printMessages(); |
| 8910 | 8916 | saveSettingsDebounced(); |
| 8911 | 8917 | } |
| @@ -9532,11 +9538,7 @@ jQuery(async function () { | ||
| 9532 | 9538 | const oldFileNameFull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text(); |
| 9533 | 9539 | const oldFileName = oldFileNameFull.replace('.jsonl', ''); |
| 9534 | 9540 | |
| 9535 | - const popupText = `<h3>Enter the new name for the chat:<h3> | |
| 9541 | + const popupText = await renderTemplateAsync('chatRename'); | |
| 9536 | - <small>!!Using an existing filename will produce an error!!<br> | |
| 9537 | - This will break the link between checkpoint chats.<br> | |
| 9538 | - No need to add '.jsonl' at the end.<br> | |
| 9539 | - </small>`; | |
| 9540 | 9542 | const newName = await callPopup(popupText, 'input', oldFileName); |
| 9541 | 9543 | |
| 9542 | 9544 | if (!newName || newName == oldFileName) { |
| @@ -9744,12 +9746,7 @@ jQuery(async function () { | ||
| 9744 | 9746 | else if (id == 'option_start_new_chat') { |
| 9745 | 9747 | if ((selected_group || this_chid !== undefined) && !is_send_press) { |
| 9746 | 9748 | let deleteCurrentChat = false; |
| 9747 | 9749 | const result = await Popup.show.confirm('t`Start new chat?`, await renderTemplateAsync('newChatConfirm'), `{ |
| 9748 | - <label for="del_chat_checkbox" class="checkbox_label justifyCenter" | |
| 9749 | - title="If necessary, you can later restore this chat file from the /backups folder"> | |
| 9750 | - <input type="checkbox" id="del_chat_checkbox" /> | |
| 9751 | - <small>Also delete the current chat file</small> | |
| 9752 | - </label>`, { | |
| 9753 | 9750 | onClose: () => deleteCurrentChat = !!$('#del_chat_checkbox').prop('checked'), |
| 9754 | 9751 | }); |
| 9755 | 9752 | if (!result) { |
| @@ -10261,10 +10258,10 @@ jQuery(async function () { | ||
| 10261 | 10258 | |
| 10262 | 10259 | let deleteOnlySwipe = false; |
| 10263 | 10260 | if (power_user.confirm_message_delete && fromSlashCommand !== true) { |
| 10264 | 10261 | const result = await callGenericPopup('t`Are you sure you want to delete this message?'`, POPUP_TYPE.CONFIRM, null, { |
| 10265 | 10262 | okButton: canDeleteSwipe ? 't`Delete Swipe'` : 't`Delete Message'`, |
| 10266 | 10263 | cancelButton: 'Cancel', |
| 10267 | 10264 | customButtons: canDeleteSwipe ? ['t`Delete Message'`] : null, |
| 10268 | 10265 | }); |
| 10269 | 10266 | if (!result) { |
| 10270 | 10267 | return; |
| @@ -108,14 +108,12 @@ class CharacterContextMenu { | ||
| 108 | 108 | * Delete one or more characters, |
| 109 | 109 | * opens a popup. |
| 110 | 110 | * |
| 111 | 111 | * @param {numberstring|string[]} characterIdcharacterKey |
| 112 | 112 | * @param {boolean} [deleteChats] |
| 113 | 113 | * @returns {Promise<void>} |
| 114 | 114 | */ |
| 115 | 115 | static delete = async (characterIdcharacterKey, deleteChats = false) => { |
| 116 | - const character = CharacterContextMenu.#getCharacter(characterId); | |
| 116 | + await deleteCharacter(characterKey, { deleteChats: deleteChats }); | |
| 117 | - | |
| 118 | - await deleteCharacter(character.avatar, { deleteChats: deleteChats }); | |
| 119 | 117 | }; |
| 120 | 118 | |
| 121 | 119 | static #getCharacter = (characterId) => characters[characterId] ?? null; |
| @@ -599,8 +597,7 @@ class BulkEditOverlay { | ||
| 599 | 597 | |
| 600 | 598 | this.container.removeEventListener('mouseup', cancelHold); |
| 601 | 599 | this.container.removeEventListener('touchend', cancelHold); |
| 602 | 600 | }, BulkEditOverlay.longPressDelay); |
| 603 | - BulkEditOverlay.longPressDelay); | |
| 604 | 601 | }; |
| 605 | 602 | |
| 606 | 603 | handleLongPressEnd = (event) => { |
| @@ -847,11 +844,14 @@ class BulkEditOverlay { | ||
| 847 | 844 | const deleteChats = document.getElementById('del_char_checkbox').checked ?? false; |
| 848 | 845 | |
| 849 | 846 | showLoader(); |
| 850 | 847 | const toast = toastr.info('We\'re deleting your characters, please wait...', 'Working on it'); |
| 851 | - return Promise.allSettled(characterIds.map(async characterId => CharacterContextMenu.delete(characterId, deleteChats))) | |
| 848 | + const avatarList = characterIds.map(id => characters[id]?.avatar).filter(a => a); | |
| 852 | - .then(() => getCharacters()) | |
| 849 | + return CharacterContextMenu.delete(avatarList, deleteChats) | |
| 853 | 850 | .then(() => this.browseState()) |
| 854 | 851 | .finally(() => hideLoader());{ |
| 852 | + toastr.clear(toast); | |
| 853 | + hideLoader(); | |
| 854 | + }); | |
| 855 | 855 | }); |
| 856 | 856 | |
| 857 | 857 | // 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 @@ | ||
| 45 | 45 | <option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option> |
| 46 | 46 | <option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option> |
| 47 | 47 | <option data-type="google" value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option> |
| 48 | + <option data-type="google" value="gemini-1.5-flash-exp-0827">gemini-1.5-flash-exp-0827</option> | |
| 49 | + <option data-type="google" value="gemini-1.5-flash-8b-exp-0827">gemini-1.5-flash-8b-exp-0827</option> | |
| 48 | 50 | <option data-type="google" value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option> |
| 49 | 51 | <option data-type="google" value="gemini-1.5-pro-exp-0801">gemini-1.5-pro-exp-0801</option> |
| 52 | + <option data-type="google" value="gemini-1.5-pro-exp-0827">gemini-1.5-pro-exp-0827</option> | |
| 50 | 53 | <option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option> |
| 51 | 54 | <option data-type="openrouter" value="openai/gpt-4o">openai/gpt-4o</option> |
| 52 | 55 | <option data-type="openrouter" value="openai/gpt-4-turbo">openai/gpt-4-turbo</option> |
| @@ -421,7 +421,7 @@ function completeTtsJob() { | ||
| 421 | 421 | async function tts(text, voiceId, char) { |
| 422 | 422 | async function processResponse(response) { |
| 423 | 423 | // RVC injection |
| 424 | 424 | if (extension_settings.rvc.enabled && typeof window['rvcVoiceConversion'] === 'function' && extension_settings.rvc.enabled) |
| 425 | 425 | response = await window['rvcVoiceConversion'](response, char, text); |
| 426 | 426 | |
| 427 | 427 | await addAudioJob(response, char); |
| @@ -78,6 +78,19 @@ export function getKayraMaxContextTokens() { | ||
| 78 | 78 | return null; |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | +export function getKayraMaxResponseTokens() { | |
| 82 | + switch (novel_data?.tier) { | |
| 83 | + case 1: | |
| 84 | + return 100; | |
| 85 | + case 2: | |
| 86 | + return 100; | |
| 87 | + case 3: | |
| 88 | + return 150; | |
| 89 | + } | |
| 90 | + | |
| 91 | + return maximum_output_length; | |
| 92 | +} | |
| 93 | + | |
| 81 | 94 | export function getNovelTier() { |
| 82 | 95 | return nai_tiers[novel_data?.tier] ?? 'no_connection'; |
| 83 | 96 | } |
| @@ -438,12 +451,14 @@ export function getNovelGenerationData(finalPrompt, settings, maxLength, isImper | ||
| 438 | 451 | console.log(finalPrompt); |
| 439 | 452 | } |
| 440 | 453 | |
| 454 | + const adjustedMaxLength = nai_settings.model_novel.includes('kayra') ? getKayraMaxResponseTokens() : maximum_output_length; | |
| 455 | + | |
| 441 | 456 | return { |
| 442 | 457 | 'input': finalPrompt, |
| 443 | 458 | 'model': nai_settings.model_novel, |
| 444 | 459 | 'use_string': true, |
| 445 | 460 | 'temperature': Number(nai_settings.temperature), |
| 446 | 461 | 'max_length': maxLength < maximum_output_lengthadjustedMaxLength ? maxLength : maximum_output_lengthadjustedMaxLength, |
| 447 | 462 | 'min_length': Number(nai_settings.min_length), |
| 448 | 463 | 'tail_free_sampling': Number(nai_settings.tail_free_sampling), |
| 449 | 464 | 'repetition_penalty': Number(nai_settings.repetition_penalty), |
| @@ -74,6 +74,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashComma | ||
| 74 | 74 | import { renderTemplateAsync } from './templates.js'; |
| 75 | 75 | import { SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; |
| 76 | 76 | import { Popup, POPUP_RESULT } from './popup.js'; |
| 77 | +import { t } from './i18n.js'; | |
| 77 | 78 | |
| 78 | 79 | export { |
| 79 | 80 | openai_messages_count, |
| @@ -132,13 +133,9 @@ const max_2mil = 2000 * 1000; | ||
| 132 | 133 | const scale_max = 8191; |
| 133 | 134 | const claude_max = 9000; // We have a proper tokenizer, so theoretically could be larger (up to 9k) |
| 134 | 135 | const claude_100k_max = 99000; |
| 135 | -let ai21_max = 9200; //can easily fit 9k gpt tokens because j2's tokenizer is efficient af | |
| 136 | +const unlocked_max = max_2mil; | |
| 136 | -const unlocked_max = max_200k; | |
| 137 | 137 | const oai_max_temp = 2.0; |
| 138 | 138 | const claude_max_temp = 1.0; //same as j2 |
| 139 | -const j2_max_topk = 10.0; | |
| 140 | -const j2_max_freq = 5.0; | |
| 141 | -const j2_max_pres = 5.0; | |
| 142 | 139 | const openrouter_website_model = 'OR_Website'; |
| 143 | 140 | const openai_max_stop_strings = 4; |
| 144 | 141 | |
| @@ -218,25 +215,11 @@ const sensitiveFields = [ | ||
| 218 | 215 | 'custom_include_headers', |
| 219 | 216 | ]; |
| 220 | 217 | |
| 221 | -function getPrefixMap() { | |
| 222 | - return selected_group ? { | |
| 223 | - assistant: '', | |
| 224 | - user: '', | |
| 225 | - system: 'OOC: ', | |
| 226 | - } | |
| 227 | - : { | |
| 228 | - assistant: '{{char}}:', | |
| 229 | - user: '{{user}}:', | |
| 230 | - system: '', | |
| 231 | - }; | |
| 232 | -} | |
| 233 | - | |
| 234 | 218 | const default_settings = { |
| 235 | 219 | preset_settings_openai: 'Default', |
| 236 | 220 | temp_openai: 1.0, |
| 237 | 221 | freq_pen_openai: 0, |
| 238 | 222 | pres_pen_openai: 0, |
| 239 | - count_pen: 0.0, | |
| 240 | 223 | top_p_openai: 1.0, |
| 241 | 224 | top_k_openai: 0, |
| 242 | 225 | min_p_openai: 0, |
| @@ -264,7 +247,7 @@ const default_settings = { | ||
| 264 | 247 | openai_model: 'gpt-4-turbo', |
| 265 | 248 | claude_model: 'claude-3-5-sonnet-20240620', |
| 266 | 249 | google_model: 'gemini-1.5-pro', |
| 267 | 250 | ai21_model: 'j2jamba-ultra1.5-large', |
| 268 | 251 | mistralai_model: 'mistral-large-latest', |
| 269 | 252 | cohere_model: 'command-r-plus', |
| 270 | 253 | perplexity_model: 'llama-3.1-70b-instruct', |
| @@ -294,8 +277,6 @@ const default_settings = { | ||
| 294 | 277 | assistant_prefill: '', |
| 295 | 278 | assistant_impersonation: '', |
| 296 | 279 | human_sysprompt_message: default_claude_human_sysprompt_message, |
| 297 | - use_ai21_tokenizer: false, | |
| 298 | - use_google_tokenizer: false, | |
| 299 | 280 | claude_use_sysprompt: false, |
| 300 | 281 | use_makersuite_sysprompt: true, |
| 301 | 282 | use_alt_scale: false, |
| @@ -317,7 +298,6 @@ const oai_settings = { | ||
| 317 | 298 | temp_openai: 1.0, |
| 318 | 299 | freq_pen_openai: 0, |
| 319 | 300 | pres_pen_openai: 0, |
| 320 | - count_pen: 0.0, | |
| 321 | 301 | top_p_openai: 1.0, |
| 322 | 302 | top_k_openai: 0, |
| 323 | 303 | min_p_openai: 0, |
| @@ -345,7 +325,7 @@ const oai_settings = { | ||
| 345 | 325 | openai_model: 'gpt-4-turbo', |
| 346 | 326 | claude_model: 'claude-3-5-sonnet-20240620', |
| 347 | 327 | google_model: 'gemini-1.5-pro', |
| 348 | 328 | ai21_model: 'j2jamba-ultra1.5-large', |
| 349 | 329 | mistralai_model: 'mistral-large-latest', |
| 350 | 330 | cohere_model: 'command-r-plus', |
| 351 | 331 | perplexity_model: 'llama-3.1-70b-instruct', |
| @@ -375,8 +355,6 @@ const oai_settings = { | ||
| 375 | 355 | assistant_prefill: '', |
| 376 | 356 | assistant_impersonation: '', |
| 377 | 357 | human_sysprompt_message: default_claude_human_sysprompt_message, |
| 378 | - use_ai21_tokenizer: false, | |
| 379 | - use_google_tokenizer: false, | |
| 380 | 358 | claude_use_sysprompt: false, |
| 381 | 359 | use_makersuite_sysprompt: true, |
| 382 | 360 | use_alt_scale: false, |
| @@ -425,7 +403,7 @@ async function validateReverseProxy() { | ||
| 425 | 403 | const rememberKey = `Proxy_SkipConfirm_${getStringHash(oai_settings.reverse_proxy)}`; |
| 426 | 404 | const skipConfirm = localStorage.getItem(rememberKey) === 'true'; |
| 427 | 405 | |
| 428 | 406 | const confirmation = skipConfirm || await Popup.show.confirm('t`Connecting To Proxy', `<span>Are you sure you want to connect, toawait therenderTemplateAsync('proxyConnectionWarning', following{ proxyproxyURL: URL?</span><var>${DOMPurify.sanitize(oai_settings.reverse_proxy) }</var>`)); |
| 429 | 407 | |
| 430 | 408 | if (!confirmation) { |
| 431 | 409 | toastr.error('Update or remove your reverse proxy settings.'); |
| @@ -1148,7 +1126,6 @@ function preparePromptsForChatCompletion({ Scenario, charPersonality, name2, wor | ||
| 1148 | 1126 | { role: 'system', content: charDescription, identifier: 'charDescription' }, |
| 1149 | 1127 | { role: 'system', content: charPersonalityText, identifier: 'charPersonality' }, |
| 1150 | 1128 | { role: 'system', content: scenarioText, identifier: 'scenario' }, |
| 1151 | - { role: 'system', content: personaDescription, identifier: 'personaDescription' }, | |
| 1152 | 1129 | // Unordered prompts without marker |
| 1153 | 1130 | { role: 'system', content: impersonationPrompt, identifier: 'impersonate' }, |
| 1154 | 1131 | { role: 'system', content: quietPrompt, identifier: 'quietPrompt' }, |
| @@ -1395,6 +1372,11 @@ function tryParseStreamingError(response, decoded) { | ||
| 1395 | 1372 | toastr.error(data.error.message || response.statusText, 'Chat Completion API'); |
| 1396 | 1373 | throw new Error(data); |
| 1397 | 1374 | } |
| 1375 | + | |
| 1376 | + if (data.message) { | |
| 1377 | + toastr.error(data.message, 'Chat Completion API'); | |
| 1378 | + throw new Error(data); | |
| 1379 | + } | |
| 1398 | 1380 | } |
| 1399 | 1381 | catch { |
| 1400 | 1382 | // No JSON. Do nothing. |
| @@ -1802,7 +1784,6 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1802 | 1784 | const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE; |
| 1803 | 1785 | const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER; |
| 1804 | 1786 | const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE; |
| 1805 | - const isAI21 = oai_settings.chat_completion_source == chat_completion_sources.AI21; | |
| 1806 | 1787 | const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE; |
| 1807 | 1788 | const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI; |
| 1808 | 1789 | const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI; |
| @@ -1815,7 +1796,7 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1815 | 1796 | const isQuiet = type === 'quiet'; |
| 1816 | 1797 | const isImpersonate = type === 'impersonate'; |
| 1817 | 1798 | const isContinue = type === 'continue'; |
| 1818 | 1799 | const stream = oai_settings.stream_openai && !isQuiet && !isScale && !isAI21 && !(isGoogle && oai_settings.google_model.includes('bison')); |
| 1819 | 1800 | const useLogprobs = !!power_user.request_token_probabilities; |
| 1820 | 1801 | const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom); |
| 1821 | 1802 | |
| @@ -1824,15 +1805,6 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1824 | 1805 | replaceItemizedPromptText(messageId, messages); |
| 1825 | 1806 | } |
| 1826 | 1807 | |
| 1827 | - if (isAI21) { | |
| 1828 | - const joinedMsgs = messages.reduce((acc, obj) => { | |
| 1829 | - const prefix = getPrefixMap()[obj.role]; | |
| 1830 | - return acc + (prefix ? (selected_group ? '\n' : prefix + ' ') : '') + obj.content + '\n'; | |
| 1831 | - }, ''); | |
| 1832 | - messages = substituteParams(joinedMsgs) + (isImpersonate ? `${name1}:` : `${name2}:`); | |
| 1833 | - replaceItemizedPromptText(messageId, messages); | |
| 1834 | - } | |
| 1835 | - | |
| 1836 | 1808 | // If we're using the window.ai extension, use that instead |
| 1837 | 1809 | // Doesn't support logit bias yet |
| 1838 | 1810 | if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) { |
| @@ -1931,12 +1903,6 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1931 | 1903 | generate_data['use_makersuite_sysprompt'] = oai_settings.use_makersuite_sysprompt; |
| 1932 | 1904 | } |
| 1933 | 1905 | |
| 1934 | - if (isAI21) { | |
| 1935 | - generate_data['top_k'] = Number(oai_settings.top_k_openai); | |
| 1936 | - generate_data['count_pen'] = Number(oai_settings.count_pen); | |
| 1937 | - generate_data['stop_tokens'] = [name1 + ':', substituteParams(oai_settings.new_chat_prompt), substituteParams(oai_settings.new_group_chat_prompt)]; | |
| 1938 | - } | |
| 1939 | - | |
| 1940 | 1906 | if (isMistral) { |
| 1941 | 1907 | generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future. |
| 1942 | 1908 | } |
| @@ -3008,7 +2974,6 @@ function loadOpenAISettings(data, settings) { | ||
| 3008 | 2974 | oai_settings.temp_openai = settings.temp_openai ?? default_settings.temp_openai; |
| 3009 | 2975 | oai_settings.freq_pen_openai = settings.freq_pen_openai ?? default_settings.freq_pen_openai; |
| 3010 | 2976 | oai_settings.pres_pen_openai = settings.pres_pen_openai ?? default_settings.pres_pen_openai; |
| 3011 | - oai_settings.count_pen = settings.count_pen ?? default_settings.count_pen; | |
| 3012 | 2977 | oai_settings.top_p_openai = settings.top_p_openai ?? default_settings.top_p_openai; |
| 3013 | 2978 | oai_settings.top_k_openai = settings.top_k_openai ?? default_settings.top_k_openai; |
| 3014 | 2979 | oai_settings.top_a_openai = settings.top_a_openai ?? default_settings.top_a_openai; |
| @@ -3080,10 +3045,12 @@ function loadOpenAISettings(data, settings) { | ||
| 3080 | 3045 | oai_settings.names_behavior = character_names_behavior.COMPLETION; |
| 3081 | 3046 | } |
| 3082 | 3047 | |
| 3048 | + if (oai_settings.ai21_model.startsWith('j2-')) { | |
| 3049 | + oai_settings.ai21_model = 'jamba-1.5-large'; | |
| 3050 | + } | |
| 3051 | + | |
| 3083 | 3052 | if (settings.wrap_in_quotes !== undefined) oai_settings.wrap_in_quotes = !!settings.wrap_in_quotes; |
| 3084 | 3053 | if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model; |
| 3085 | - 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; } | |
| 3086 | - if (settings.use_google_tokenizer !== undefined) oai_settings.use_google_tokenizer = !!settings.use_google_tokenizer; | |
| 3087 | 3054 | if (settings.claude_use_sysprompt !== undefined) oai_settings.claude_use_sysprompt = !!settings.claude_use_sysprompt; |
| 3088 | 3055 | if (settings.use_makersuite_sysprompt !== undefined) oai_settings.use_makersuite_sysprompt = !!settings.use_makersuite_sysprompt; |
| 3089 | 3056 | if (settings.use_alt_scale !== undefined) { oai_settings.use_alt_scale = !!settings.use_alt_scale; updateScaleForm(); } |
| @@ -3133,8 +3100,6 @@ function loadOpenAISettings(data, settings) { | ||
| 3133 | 3100 | $('#jailbreak_system').prop('checked', oai_settings.jailbreak_system); |
| 3134 | 3101 | $('#openai_show_external_models').prop('checked', oai_settings.show_external_models); |
| 3135 | 3102 | $('#openai_external_category').toggle(oai_settings.show_external_models); |
| 3136 | - $('#use_ai21_tokenizer').prop('checked', oai_settings.use_ai21_tokenizer); | |
| 3137 | - $('#use_google_tokenizer').prop('checked', oai_settings.use_google_tokenizer); | |
| 3138 | 3103 | $('#claude_use_sysprompt').prop('checked', oai_settings.claude_use_sysprompt); |
| 3139 | 3104 | $('#use_makersuite_sysprompt').prop('checked', oai_settings.use_makersuite_sysprompt); |
| 3140 | 3105 | $('#scale-alt').prop('checked', oai_settings.use_alt_scale); |
| @@ -3170,9 +3135,6 @@ function loadOpenAISettings(data, settings) { | ||
| 3170 | 3135 | $('#pres_pen_openai').val(oai_settings.pres_pen_openai); |
| 3171 | 3136 | $('#pres_pen_counter_openai').val(Number(oai_settings.pres_pen_openai).toFixed(2)); |
| 3172 | 3137 | |
| 3173 | - $('#count_pen').val(oai_settings.count_pen); | |
| 3174 | - $('#count_pen_counter').val(Number(oai_settings.count_pen).toFixed(2)); | |
| 3175 | - | |
| 3176 | 3138 | $('#top_p_openai').val(oai_settings.top_p_openai); |
| 3177 | 3139 | $('#top_p_counter_openai').val(Number(oai_settings.top_p_openai).toFixed(2)); |
| 3178 | 3140 | |
| @@ -3392,7 +3354,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 3392 | 3354 | temperature: settings.temp_openai, |
| 3393 | 3355 | frequency_penalty: settings.freq_pen_openai, |
| 3394 | 3356 | presence_penalty: settings.pres_pen_openai, |
| 3395 | - count_penalty: settings.count_pen, | |
| 3396 | 3357 | top_p: settings.top_p_openai, |
| 3397 | 3358 | top_k: settings.top_k_openai, |
| 3398 | 3359 | top_a: settings.top_a_openai, |
| @@ -3427,8 +3388,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 3427 | 3388 | assistant_prefill: settings.assistant_prefill, |
| 3428 | 3389 | assistant_impersonation: settings.assistant_impersonation, |
| 3429 | 3390 | human_sysprompt_message: settings.human_sysprompt_message, |
| 3430 | - use_ai21_tokenizer: settings.use_ai21_tokenizer, | |
| 3431 | - use_google_tokenizer: settings.use_google_tokenizer, | |
| 3432 | 3391 | claude_use_sysprompt: settings.claude_use_sysprompt, |
| 3433 | 3392 | use_makersuite_sysprompt: settings.use_makersuite_sysprompt, |
| 3434 | 3393 | use_alt_scale: settings.use_alt_scale, |
| @@ -3799,7 +3758,6 @@ function onSettingsPresetChange() { | ||
| 3799 | 3758 | temperature: ['#temp_openai', 'temp_openai', false], |
| 3800 | 3759 | frequency_penalty: ['#freq_pen_openai', 'freq_pen_openai', false], |
| 3801 | 3760 | presence_penalty: ['#pres_pen_openai', 'pres_pen_openai', false], |
| 3802 | - count_penalty: ['#count_pen', 'count_pen', false], | |
| 3803 | 3761 | top_p: ['#top_p_openai', 'top_p_openai', false], |
| 3804 | 3762 | top_k: ['#top_k_openai', 'top_k_openai', false], |
| 3805 | 3763 | top_a: ['#top_a_openai', 'top_a_openai', false], |
| @@ -3856,8 +3814,6 @@ function onSettingsPresetChange() { | ||
| 3856 | 3814 | assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false], |
| 3857 | 3815 | assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false], |
| 3858 | 3816 | human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false], |
| 3859 | - use_ai21_tokenizer: ['#use_ai21_tokenizer', 'use_ai21_tokenizer', true], | |
| 3860 | - use_google_tokenizer: ['#use_google_tokenizer', 'use_google_tokenizer', true], | |
| 3861 | 3817 | claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true], |
| 3862 | 3818 | use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true], |
| 3863 | 3819 | use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true], |
| @@ -4028,6 +3984,11 @@ async function onModelChange() { | ||
| 4028 | 3984 | } |
| 4029 | 3985 | |
| 4030 | 3986 | if ($(this).is('#model_ai21_select')) { |
| 3987 | + if (value === '' || value.startsWith('j2-')) { | |
| 3988 | + value = 'jamba-1.5-large'; | |
| 3989 | + $('#model_ai21_select').val(value); | |
| 3990 | + } | |
| 3991 | + | |
| 4031 | 3992 | console.log('AI21 model changed to', value); |
| 4032 | 3993 | oai_settings.ai21_model = value; |
| 4033 | 3994 | } |
| @@ -4230,7 +4191,7 @@ async function onModelChange() { | ||
| 4230 | 4191 | else if (['command-light-nightly', 'command-nightly'].includes(oai_settings.cohere_model)) { |
| 4231 | 4192 | $('#openai_max_context').attr('max', max_8k); |
| 4232 | 4193 | } |
| 4233 | 4194 | else if (['command-r', oai_settings.cohere_model.includes('command-r-plus'].includes(oai_settings.cohere_model)) { |
| 4234 | 4195 | $('#openai_max_context').attr('max', max_128k); |
| 4235 | 4196 | } |
| 4236 | 4197 | else if (['c4ai-aya-23'].includes(oai_settings.cohere_model)) { |
| @@ -4305,33 +4266,13 @@ async function onModelChange() { | ||
| 4305 | 4266 | if (oai_settings.chat_completion_source == chat_completion_sources.AI21) { |
| 4306 | 4267 | if (oai_settings.max_context_unlocked) { |
| 4307 | 4268 | $('#openai_max_context').attr('max', unlocked_max); |
| 4308 | - } else { | |
| 4269 | + } else if (oai_settings.ai21_model.includes('jamba-1.5') || oai_settings.ai21_model.includes('jamba-instruct')) { | |
| 4309 | 4270 | $('#openai_max_context').attr('max', ai21_maxmax_256k); |
| 4310 | 4271 | } |
| 4311 | 4272 | |
| 4312 | 4273 | oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); |
| 4313 | 4274 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); |
| 4314 | - | |
| 4275 | + $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | |
| 4315 | - oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai); | |
| 4316 | - $('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input'); | |
| 4317 | - | |
| 4318 | - oai_settings.freq_pen_openai = Math.min(j2_max_freq, oai_settings.freq_pen_openai < 0 ? 0 : oai_settings.freq_pen_openai); | |
| 4319 | - $('#freq_pen_openai').attr('min', 0).attr('max', j2_max_freq).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4320 | - | |
| 4321 | - oai_settings.pres_pen_openai = Math.min(j2_max_pres, oai_settings.pres_pen_openai < 0 ? 0 : oai_settings.pres_pen_openai); | |
| 4322 | - $('#pres_pen_openai').attr('min', 0).attr('max', j2_max_pres).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4323 | - | |
| 4324 | - oai_settings.top_k_openai = Math.min(j2_max_topk, oai_settings.top_k_openai); | |
| 4325 | - $('#top_k_openai').attr('max', j2_max_topk).val(oai_settings.top_k_openai).trigger('input'); | |
| 4326 | - } else if (oai_settings.chat_completion_source != chat_completion_sources.AI21) { | |
| 4327 | - oai_settings.freq_pen_openai = Math.min(2.0, oai_settings.freq_pen_openai); | |
| 4328 | - $('#freq_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4329 | - | |
| 4330 | - oai_settings.pres_pen_openai = Math.min(2.0, oai_settings.pres_pen_openai); | |
| 4331 | - $('#pres_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4332 | - | |
| 4333 | - oai_settings.top_k_openai = Math.min(200, oai_settings.top_k_openai); | |
| 4334 | - $('#top_k_openai').attr('max', 200).val(oai_settings.top_k_openai).trigger('input'); | |
| 4335 | 4276 | } |
| 4336 | 4277 | |
| 4337 | 4278 | if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) { |
| @@ -4388,6 +4329,16 @@ async function onModelChange() { | ||
| 4388 | 4329 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4389 | 4330 | } |
| 4390 | 4331 | |
| 4332 | + if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { | |
| 4333 | + oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1); | |
| 4334 | + $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4335 | + oai_settings.freq_pen_openai = Math.min(Math.max(0, oai_settings.freq_pen_openai), 1); | |
| 4336 | + $('#freq_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4337 | + } else { | |
| 4338 | + $('#pres_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4339 | + $('#freq_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4340 | + } | |
| 4341 | + | |
| 4391 | 4342 | $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max'))); |
| 4392 | 4343 | |
| 4393 | 4344 | saveSettingsDebounced(); |
| @@ -4673,17 +4624,17 @@ function toggleChatCompletionForms() { | ||
| 4673 | 4624 | async function testApiConnection() { |
| 4674 | 4625 | // Check if the previous request is still in progress |
| 4675 | 4626 | if (is_send_press) { |
| 4676 | 4627 | toastr.info('t`Please wait for the previous request to complete.'`); |
| 4677 | 4628 | return; |
| 4678 | 4629 | } |
| 4679 | 4630 | |
| 4680 | 4631 | try { |
| 4681 | 4632 | const reply = await sendOpenAIRequest('quiet', [{ 'role': 'user', 'content': 'Hi' }]); |
| 4682 | 4633 | console.log(reply); |
| 4683 | 4634 | toastr.success('t`API connection successful!'`); |
| 4684 | 4635 | } |
| 4685 | 4636 | catch (err) { |
| 4686 | 4637 | toastr.error('t`Could not get a reply from API. Check your connection settings / API key and try again.'`); |
| 4687 | 4638 | } |
| 4688 | 4639 | } |
| 4689 | 4640 | |
| @@ -4752,11 +4703,14 @@ export function isImageInliningSupported() { | ||
| 4752 | 4703 | 'gemini-1.5-flash', |
| 4753 | 4704 | 'gemini-1.5-flash-latest', |
| 4754 | 4705 | 'gemini-1.5-flash-001', |
| 4706 | + 'gemini-1.5-flash-exp-0827', | |
| 4707 | + 'gemini-1.5-flash-8b-exp-0827', | |
| 4755 | 4708 | 'gemini-1.0-pro-vision-latest', |
| 4756 | 4709 | 'gemini-1.5-pro', |
| 4757 | 4710 | 'gemini-1.5-pro-latest', |
| 4758 | 4711 | 'gemini-1.5-pro-001', |
| 4759 | 4712 | 'gemini-1.5-pro-exp-0801', |
| 4713 | + 'gemini-1.5-pro-exp-0827', | |
| 4760 | 4714 | 'gemini-pro-vision', |
| 4761 | 4715 | 'claude-3', |
| 4762 | 4716 | 'claude-3-5', |
| @@ -4837,7 +4791,7 @@ function onProxyPresetChange() { | ||
| 4837 | 4791 | if (selectedPreset) { |
| 4838 | 4792 | setProxyPreset(selectedPreset.name, selectedPreset.url, selectedPreset.password); |
| 4839 | 4793 | } else { |
| 4840 | 4794 | console.error(t`Proxy preset "'${value}"' not found in proxies array.`); |
| 4841 | 4795 | } |
| 4842 | 4796 | saveSettingsDebounced(); |
| 4843 | 4797 | } |
| @@ -4849,7 +4803,7 @@ $('#save_proxy').on('click', async function () { | ||
| 4849 | 4803 | |
| 4850 | 4804 | setProxyPreset(presetName, reverseProxy, proxyPassword); |
| 4851 | 4805 | saveSettingsDebounced(); |
| 4852 | 4806 | toastr.success('t`Proxy Saved'`); |
| 4853 | 4807 | if ($('#openai_proxy_preset').val() !== presetName) { |
| 4854 | 4808 | const option = document.createElement('option'); |
| 4855 | 4809 | option.text = presetName; |
| @@ -4883,9 +4837,9 @@ $('#delete_proxy').on('click', async function () { | ||
| 4883 | 4837 | |
| 4884 | 4838 | saveSettingsDebounced(); |
| 4885 | 4839 | $('#openai_proxy_preset').val(selected_proxy.name); |
| 4886 | 4840 | toastr.success('t`Proxy Deleted'`); |
| 4887 | 4841 | } else { |
| 4888 | 4842 | toastr.error(t`Could not find proxy with name "'${presetName}"'`); |
| 4889 | 4843 | } |
| 4890 | 4844 | }); |
| 4891 | 4845 | |
| @@ -4953,12 +4907,6 @@ $(document).ready(async function () { | ||
| 4953 | 4907 | saveSettingsDebounced(); |
| 4954 | 4908 | }); |
| 4955 | 4909 | |
| 4956 | - $('#count_pen').on('input', function () { | |
| 4957 | - oai_settings.count_pen = Number($(this).val()); | |
| 4958 | - $('#count_pen_counter').val(Number($(this).val()).toFixed(2)); | |
| 4959 | - saveSettingsDebounced(); | |
| 4960 | - }); | |
| 4961 | - | |
| 4962 | 4910 | $('#top_p_openai').on('input', function () { |
| 4963 | 4911 | oai_settings.top_p_openai = Number($(this).val()); |
| 4964 | 4912 | $('#top_p_counter_openai').val(Number($(this).val()).toFixed(2)); |
| @@ -5017,20 +4965,6 @@ $(document).ready(async function () { | ||
| 5017 | 4965 | saveSettingsDebounced(); |
| 5018 | 4966 | }); |
| 5019 | 4967 | |
| 5020 | - $('#use_ai21_tokenizer').on('change', function () { | |
| 5021 | - oai_settings.use_ai21_tokenizer = !!$('#use_ai21_tokenizer').prop('checked'); | |
| 5022 | - oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200; | |
| 5023 | - oai_settings.openai_max_context = Math.min(ai21_max, oai_settings.openai_max_context); | |
| 5024 | - $('#openai_max_context').attr('max', ai21_max).val(oai_settings.openai_max_context).trigger('input'); | |
| 5025 | - $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max'))); | |
| 5026 | - saveSettingsDebounced(); | |
| 5027 | - }); | |
| 5028 | - | |
| 5029 | - $('#use_google_tokenizer').on('change', function () { | |
| 5030 | - oai_settings.use_google_tokenizer = !!$('#use_google_tokenizer').prop('checked'); | |
| 5031 | - saveSettingsDebounced(); | |
| 5032 | - }); | |
| 5033 | - | |
| 5034 | 4968 | $('#claude_use_sysprompt').on('change', function () { |
| 5035 | 4969 | oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked'); |
| 5036 | 4970 | $('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt); |
| @@ -107,6 +107,7 @@ export const persona_description_positions = { | ||
| 107 | 107 | TOP_AN: 2, |
| 108 | 108 | BOTTOM_AN: 3, |
| 109 | 109 | AT_DEPTH: 4, |
| 110 | + NONE: 9, | |
| 110 | 111 | }; |
| 111 | 112 | |
| 112 | 113 | let power_user = { |
| @@ -0,0 +1,6 @@ | ||
| 1 | +<h3 data-i18n="chat_rename_1">Enter the new name for the chat:</h3> | |
| 2 | +<small> | |
| 3 | + <span data-i18n="chat_rename_2">!!Using an existing filename will produce an error!!</span><br> | |
| 4 | + <span data-i18n="chat_rename_3">This will break the link between checkpoint chats.</span><br> | |
| 5 | + <span data-i18n="chat_rename_4">No need to add '.jsonl' at the end.</span><br> | |
| 6 | +</small> | |
| 6 | \ No newline at end of file | |
| @@ -0,0 +1,4 @@ | ||
| 1 | +<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"> | |
| 2 | + <input type="checkbox" id="del_chat_checkbox" /> | |
| 3 | + <small data-i18n="Also delete the current chat file">Also delete the current chat file</small> | |
| 4 | +</label> | |
| 4 | \ No newline at end of file | |
| @@ -0,0 +1 @@ | ||
| 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> | |
| 1 | \ No newline at end of file | |
| @@ -188,6 +188,8 @@ const settings = { | ||
| 188 | 188 | custom_model: '', |
| 189 | 189 | bypass_status_check: false, |
| 190 | 190 | openrouter_allow_fallbacks: true, |
| 191 | + xtc_threshold: 0.1, | |
| 192 | + xtc_probability: 0, | |
| 191 | 193 | }; |
| 192 | 194 | |
| 193 | 195 | export let textgenerationwebui_banned_in_macros = []; |
| @@ -263,6 +265,8 @@ export const setting_names = [ | ||
| 263 | 265 | 'custom_model', |
| 264 | 266 | 'bypass_status_check', |
| 265 | 267 | 'openrouter_allow_fallbacks', |
| 268 | + 'xtc_threshold', | |
| 269 | + 'xtc_probability', | |
| 266 | 270 | ]; |
| 267 | 271 | |
| 268 | 272 | const DYNATEMP_BLOCK = document.getElementById('dynatemp_block_ooba'); |
| @@ -718,6 +722,8 @@ jQuery(function () { | ||
| 718 | 722 | 'dry_multiplier_textgenerationwebui': 0, |
| 719 | 723 | 'dry_base_textgenerationwebui': 1.75, |
| 720 | 724 | 'dry_penalty_last_n_textgenerationwebui': 0, |
| 725 | + 'xtc_threshold_textgenerationwebui': 0.1, | |
| 726 | + 'xtc_probability_textgenerationwebui': 0, | |
| 721 | 727 | }; |
| 722 | 728 | |
| 723 | 729 | for (const [id, value] of Object.entries(inputs)) { |
| @@ -1156,6 +1162,8 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate, | ||
| 1156 | 1162 | 'api_server': getTextGenServer(), |
| 1157 | 1163 | 'legacy_api': settings.legacy_api && (settings.type === OOBA || settings.type === APHRODITE), |
| 1158 | 1164 | 'sampler_order': settings.type === textgen_types.KOBOLDCPP ? settings.sampler_order : undefined, |
| 1165 | + 'xtc_threshold': settings.xtc_threshold, | |
| 1166 | + 'xtc_probability': settings.xtc_probability, | |
| 1159 | 1167 | }; |
| 1160 | 1168 | const nonAphroditeParams = { |
| 1161 | 1169 | 'rep_pen': settings.rep_pen, |
| @@ -27,6 +27,7 @@ export const tokenizers = { | ||
| 27 | 27 | CLAUDE: 11, |
| 28 | 28 | LLAMA3: 12, |
| 29 | 29 | GEMMA: 13, |
| 30 | + JAMBA: 14, | |
| 30 | 31 | BEST_MATCH: 99, |
| 31 | 32 | }; |
| 32 | 33 | |
| @@ -36,6 +37,7 @@ export const SENTENCEPIECE_TOKENIZERS = [ | ||
| 36 | 37 | tokenizers.YI, |
| 37 | 38 | tokenizers.LLAMA3, |
| 38 | 39 | tokenizers.GEMMA, |
| 40 | + tokenizers.JAMBA, | |
| 39 | 41 | // uncomment when NovelAI releases Kayra and Clio weights, lol |
| 40 | 42 | //tokenizers.NERD, |
| 41 | 43 | //tokenizers.NERD2, |
| @@ -98,6 +100,11 @@ const TOKENIZER_URLS = { | ||
| 98 | 100 | decode: '/api/tokenizers/gemma/decode', |
| 99 | 101 | count: '/api/tokenizers/gemma/encode', |
| 100 | 102 | }, |
| 103 | + [tokenizers.JAMBA]: { | |
| 104 | + encode: '/api/tokenizers/jamba/encode', | |
| 105 | + decode: '/api/tokenizers/jamba/decode', | |
| 106 | + count: '/api/tokenizers/jamba/encode', | |
| 107 | + }, | |
| 101 | 108 | [tokenizers.API_TEXTGENERATIONWEBUI]: { |
| 102 | 109 | encode: '/api/tokenizers/remote/textgenerationwebui/encode', |
| 103 | 110 | count: '/api/tokenizers/remote/textgenerationwebui/encode', |
| @@ -164,7 +171,7 @@ export function getAvailableTokenizers() { | ||
| 164 | 171 | tokenizerId: Number(tokenizerOption.value), |
| 165 | 172 | tokenizerKey: Object.entries(tokenizers).find(([_, value]) => value === Number(tokenizerOption.value))[0].toLocaleLowerCase(), |
| 166 | 173 | tokenizerName: tokenizerOption.text, |
| 167 | 174 | })); |
| 168 | 175 | } |
| 169 | 176 | |
| 170 | 177 | /** |
| @@ -280,6 +287,12 @@ export function getTokenizerBestMatch(forApi) { | ||
| 280 | 287 | if (model.includes('gemma')) { |
| 281 | 288 | return tokenizers.GEMMA; |
| 282 | 289 | } |
| 290 | + if (model.includes('yi')) { | |
| 291 | + return tokenizers.YI; | |
| 292 | + } | |
| 293 | + if (model.includes('jamba')) { | |
| 294 | + return tokenizers.JAMBA; | |
| 295 | + } | |
| 283 | 296 | } |
| 284 | 297 | |
| 285 | 298 | return tokenizers.LLAMA; |
| @@ -497,6 +510,7 @@ export function getTokenizerModel() { | ||
| 497 | 510 | const mistralTokenizer = 'mistral'; |
| 498 | 511 | const yiTokenizer = 'yi'; |
| 499 | 512 | const gemmaTokenizer = 'gemma'; |
| 513 | + const jambaTokenizer = 'jamba'; | |
| 500 | 514 | |
| 501 | 515 | // Assuming no one would use it for different models.. right? |
| 502 | 516 | if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) { |
| @@ -562,12 +576,19 @@ export function getTokenizerModel() { | ||
| 562 | 576 | else if (oai_settings.openrouter_model.includes('GPT-NeoXT')) { |
| 563 | 577 | return gpt2Tokenizer; |
| 564 | 578 | } |
| 579 | + else if (oai_settings.openrouter_model.includes('jamba')) { | |
| 580 | + return jambaTokenizer; | |
| 581 | + } | |
| 565 | 582 | } |
| 566 | 583 | |
| 567 | 584 | if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) { |
| 568 | 585 | return gemmaTokenizer; |
| 569 | 586 | } |
| 570 | 587 | |
| 588 | + if (oai_settings.chat_completion_source == chat_completion_sources.AI21) { | |
| 589 | + return jambaTokenizer; | |
| 590 | + } | |
| 591 | + | |
| 571 | 592 | if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) { |
| 572 | 593 | return claudeTokenizer; |
| 573 | 594 | } |
| @@ -626,16 +647,7 @@ export function getTokenizerModel() { | ||
| 626 | 647 | * @deprecated Use countTokensOpenAIAsync instead. |
| 627 | 648 | */ |
| 628 | 649 | export function countTokensOpenAI(messages, full = false) { |
| 629 | - const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer; | |
| 650 | + const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 630 | - const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer; | |
| 631 | - let tokenizerEndpoint = ''; | |
| 632 | - if (shouldTokenizeAI21) { | |
| 633 | - tokenizerEndpoint = '/api/tokenizers/ai21/count'; | |
| 634 | - } else if (shouldTokenizeGoogle) { | |
| 635 | - tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}&reverse_proxy=${oai_settings.reverse_proxy}&proxy_password=${oai_settings.proxy_password}`; | |
| 636 | - } else { | |
| 637 | - tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 638 | - } | |
| 639 | 651 | const cacheObject = getTokenCacheObject(); |
| 640 | 652 | |
| 641 | 653 | if (!Array.isArray(messages)) { |
| @@ -647,7 +659,7 @@ export function countTokensOpenAI(messages, full = false) { | ||
| 647 | 659 | for (const message of messages) { |
| 648 | 660 | const model = getTokenizerModel(); |
| 649 | 661 | |
| 650 | 662 | if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) { |
| 651 | 663 | full = true; |
| 652 | 664 | } |
| 653 | 665 | |
| @@ -687,16 +699,7 @@ export function countTokensOpenAI(messages, full = false) { | ||
| 687 | 699 | * @returns {Promise<number>} Token count. |
| 688 | 700 | */ |
| 689 | 701 | export async function countTokensOpenAIAsync(messages, full = false) { |
| 690 | - const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer; | |
| 702 | + const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 691 | - const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer; | |
| 692 | - let tokenizerEndpoint = ''; | |
| 693 | - if (shouldTokenizeAI21) { | |
| 694 | - tokenizerEndpoint = '/api/tokenizers/ai21/count'; | |
| 695 | - } else if (shouldTokenizeGoogle) { | |
| 696 | - tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}`; | |
| 697 | - } else { | |
| 698 | - tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 699 | - } | |
| 700 | 703 | const cacheObject = getTokenCacheObject(); |
| 701 | 704 | |
| 702 | 705 | if (!Array.isArray(messages)) { |
| @@ -708,7 +711,7 @@ export async function countTokensOpenAIAsync(messages, full = false) { | ||
| 708 | 711 | for (const message of messages) { |
| 709 | 712 | const model = getTokenizerModel(); |
| 710 | 713 | |
| 711 | 714 | if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) { |
| 712 | 715 | full = true; |
| 713 | 716 | } |
| 714 | 717 | |
| @@ -4777,8 +4777,10 @@ jQuery(() => { | ||
| 4777 | 4777 | world_info_min_activations = Number($(this).val()); |
| 4778 | 4778 | $('#world_info_min_activations_counter').val(world_info_min_activations); |
| 4779 | 4779 | |
| 4780 | 4780 | if (world_info_min_activations !== 0 && world_info_max_recursion_steps !== 0) { |
| 4781 | 4781 | $('#world_info_max_recursion_steps').val(0).trigger('input'); |
| 4782 | + flashHighlight($('#world_info_max_recursion_steps').parent()); // flash the other control to show it has changed | |
| 4783 | + console.info('[WI] Max recursion steps set to 0, as min activations is set to', world_info_min_activations); | |
| 4782 | 4784 | } else { |
| 4783 | 4785 | saveSettings(); |
| 4784 | 4786 | } |
| @@ -4840,8 +4842,10 @@ jQuery(() => { | ||
| 4840 | 4842 | $('#world_info_max_recursion_steps').on('input', function () { |
| 4841 | 4843 | world_info_max_recursion_steps = Number($(this).val()); |
| 4842 | 4844 | $('#world_info_max_recursion_steps_counter').val(world_info_max_recursion_steps); |
| 4843 | 4845 | if (world_info_max_recursion_steps !== 0 && world_info_min_activations !== 0) { |
| 4844 | 4846 | $('#world_info_min_activations').val(0).trigger('input'); |
| 4847 | + flashHighlight($('#world_info_min_activations').parent()); // flash the other control to show it has changed | |
| 4848 | + console.info('[WI] Min activations set to 0, as max recursion steps is set to', world_info_max_recursion_steps); | |
| 4845 | 4849 | } else { |
| 4846 | 4850 | saveSettings(); |
| 4847 | 4851 | } |
| @@ -2421,7 +2421,6 @@ input[type="file"] { | ||
| 2421 | 2421 | } |
| 2422 | 2422 | |
| 2423 | 2423 | #rm_print_characters_block .text_block { |
| 2424 | - height: 100%; | |
| 2425 | 2424 | width: 100%; |
| 2426 | 2425 | opacity: 0.5; |
| 2427 | 2426 | margin: 0 auto 1px auto; |
| @@ -0,0 +1,126 @@ | ||
| 1 | +const DATA_PREFIX = 'data:'; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Borrowed from Cohere SDK (MIT License) | |
| 5 | + * https://github.com/cohere-ai/cohere-typescript/blob/main/src/core/streaming-fetcher/Stream.ts | |
| 6 | + * Copyright (c) 2021 Cohere | |
| 7 | + */ | |
| 8 | +class CohereStream { | |
| 9 | + /** @type {ReadableStream} */ | |
| 10 | + stream; | |
| 11 | + /** @type {string} */ | |
| 12 | + prefix; | |
| 13 | + /** @type {string} */ | |
| 14 | + messageTerminator; | |
| 15 | + /** @type {string|undefined} */ | |
| 16 | + streamTerminator; | |
| 17 | + /** @type {AbortController} */ | |
| 18 | + controller = new AbortController(); | |
| 19 | + | |
| 20 | + constructor({ stream, eventShape }) { | |
| 21 | + this.stream = stream; | |
| 22 | + if (eventShape.type === 'sse') { | |
| 23 | + this.prefix = DATA_PREFIX; | |
| 24 | + this.messageTerminator = '\n'; | |
| 25 | + this.streamTerminator = eventShape.streamTerminator; | |
| 26 | + } else { | |
| 27 | + this.messageTerminator = eventShape.messageTerminator; | |
| 28 | + } | |
| 29 | + } | |
| 30 | + | |
| 31 | + async *iterMessages() { | |
| 32 | + const stream = readableStreamAsyncIterable(this.stream); | |
| 33 | + let buf = ''; | |
| 34 | + let prefixSeen = false; | |
| 35 | + let parsedAnyMessages = false; | |
| 36 | + for await (const chunk of stream) { | |
| 37 | + buf += this.decodeChunk(chunk); | |
| 38 | + | |
| 39 | + let terminatorIndex; | |
| 40 | + // Parse the chunk into as many messages as possible | |
| 41 | + while ((terminatorIndex = buf.indexOf(this.messageTerminator)) >= 0) { | |
| 42 | + // Extract the line from the buffer | |
| 43 | + let line = buf.slice(0, terminatorIndex + 1); | |
| 44 | + buf = buf.slice(terminatorIndex + 1); | |
| 45 | + | |
| 46 | + // Skip empty lines | |
| 47 | + if (line.length === 0) { | |
| 48 | + continue; | |
| 49 | + } | |
| 50 | + | |
| 51 | + // Skip the chunk until the prefix is found | |
| 52 | + if (!prefixSeen && this.prefix != null) { | |
| 53 | + const prefixIndex = line.indexOf(this.prefix); | |
| 54 | + if (prefixIndex === -1) { | |
| 55 | + continue; | |
| 56 | + } | |
| 57 | + prefixSeen = true; | |
| 58 | + line = line.slice(prefixIndex + this.prefix.length); | |
| 59 | + } | |
| 60 | + | |
| 61 | + // If the stream terminator is present, return | |
| 62 | + if (this.streamTerminator != null && line.includes(this.streamTerminator)) { | |
| 63 | + return; | |
| 64 | + } | |
| 65 | + | |
| 66 | + // Otherwise, yield message from the prefix to the terminator | |
| 67 | + const message = JSON.parse(line); | |
| 68 | + yield message; | |
| 69 | + prefixSeen = false; | |
| 70 | + parsedAnyMessages = true; | |
| 71 | + } | |
| 72 | + } | |
| 73 | + | |
| 74 | + if (!parsedAnyMessages && buf.length > 0) { | |
| 75 | + try { | |
| 76 | + yield JSON.parse(buf); | |
| 77 | + } catch (e) { | |
| 78 | + console.error('Error parsing message:', e); | |
| 79 | + } | |
| 80 | + } | |
| 81 | + } | |
| 82 | + | |
| 83 | + async *[Symbol.asyncIterator]() { | |
| 84 | + for await (const message of this.iterMessages()) { | |
| 85 | + yield message; | |
| 86 | + } | |
| 87 | + } | |
| 88 | + | |
| 89 | + decodeChunk(chunk) { | |
| 90 | + const decoder = new TextDecoder('utf8'); | |
| 91 | + return decoder.decode(chunk); | |
| 92 | + } | |
| 93 | +} | |
| 94 | + | |
| 95 | +function readableStreamAsyncIterable(stream) { | |
| 96 | + if (stream[Symbol.asyncIterator]) { | |
| 97 | + return stream; | |
| 98 | + } | |
| 99 | + | |
| 100 | + const reader = stream.getReader(); | |
| 101 | + return { | |
| 102 | + async next() { | |
| 103 | + try { | |
| 104 | + const result = await reader.read(); | |
| 105 | + if (result?.done) { | |
| 106 | + reader.releaseLock(); | |
| 107 | + } // release lock when stream becomes closed | |
| 108 | + return result; | |
| 109 | + } catch (e) { | |
| 110 | + reader.releaseLock(); // release lock when stream becomes errored | |
| 111 | + throw e; | |
| 112 | + } | |
| 113 | + }, | |
| 114 | + async return() { | |
| 115 | + const cancelPromise = reader.cancel(); | |
| 116 | + reader.releaseLock(); | |
| 117 | + await cancelPromise; | |
| 118 | + return { done: true, value: undefined }; | |
| 119 | + }, | |
| 120 | + [Symbol.asyncIterator]() { | |
| 121 | + return this; | |
| 122 | + }, | |
| 123 | + }; | |
| 124 | +} | |
| 125 | + | |
| 126 | +module.exports = CohereStream; | |
| @@ -1,11 +1,11 @@ | ||
| 1 | 1 | const express = require('express'); |
| 2 | 2 | const fetch = require('node-fetch').default; |
| 3 | -const Readable = require('stream').Readable; | |
| 4 | 3 | |
| 5 | 4 | const { jsonParser } = require('../../express-common'); |
| 6 | 5 | const { CHAT_COMPLETION_SOURCES, GEMINI_SAFETY, BISON_SAFETY, OPENROUTER_HEADERS } = require('../../constants'); |
| 7 | 6 | const { forwardFetchResponse, getConfigValue, tryParse, uuidv4, mergeObjectWithYaml, excludeKeysByYaml, color } = require('../../util'); |
| 8 | 7 | const { convertClaudeMessages, convertGooglePrompt, convertTextCompletionPrompt, convertCohereMessages, convertMistralMessages, convertCohereTools, convertAI21Messages } = require('../../prompt-converters'); |
| 8 | +const CohereStream = require('../../cohere-stream'); | |
| 9 | 9 | |
| 10 | 10 | const { readSecret, SECRET_KEYS } = require('../secrets'); |
| 11 | 11 | const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sentencepieceTokenizers, TEXT_COMPLETION_MODELS } = require('../tokenizers'); |
| @@ -19,6 +19,7 @@ const API_GROQ = 'https://api.groq.com/openai/v1'; | ||
| 19 | 19 | const API_MAKERSUITE = 'https://generativelanguage.googleapis.com'; |
| 20 | 20 | const API_01AI = 'https://api.01.ai/v1'; |
| 21 | 21 | const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1'; |
| 22 | +const API_AI21 = 'https://api.ai21.com/studio/v1'; | |
| 22 | 23 | |
| 23 | 24 | /** |
| 24 | 25 | * Applies a post-processing step to the generated messages. |
| @@ -40,52 +41,30 @@ function postProcessPrompt(messages, type, charName, userName) { | ||
| 40 | 41 | /** |
| 41 | 42 | * Ollama strikes back. Special boy #2's steaming routine. |
| 42 | 43 | * Wrap this abomination into proper SSE stream, again. |
| 43 | 44 | * @param {import('node-fetch').Response} jsonStream JSON stream |
| 44 | 45 | * @param {import('express').Request} request Express request |
| 45 | 46 | * @param {import('express').Response} response Express response |
| 46 | 47 | * @returns {Promise<any>} Nothing valuable |
| 47 | 48 | */ |
| 48 | 49 | async function parseCohereStream(jsonStream, request, response) { |
| 49 | 50 | try { |
| 50 | - let partialData = ''; | |
| 51 | + const stream = new CohereStream({ stream: jsonStream.body, eventShape: { type: 'json', messageTerminator: '\n' } }); | |
| 51 | - jsonStream.body.on('data', (data) => { | |
| 52 | + | |
| 52 | - const chunk = data.toString(); | |
| 53 | + for await (const json of stream.iterMessages()) { | |
| 53 | - partialData += chunk; | |
| 54 | - while (true) { | |
| 55 | - let json; | |
| 56 | - try { | |
| 57 | - json = JSON.parse(partialData); | |
| 58 | - } catch (e) { | |
| 59 | - break; | |
| 60 | - } | |
| 61 | 54 | if (json.message) { |
| 62 | 55 | const message = json.message || 'Unknown error'; |
| 63 | 56 | const chunk = { error: { message: message } }; |
| 64 | 57 | response.write(`data: ${JSON.stringify(chunk)}\n\n`); |
| 65 | - partialData = ''; | |
| 66 | - break; | |
| 67 | 58 | } else if (json.event_type === 'text-generation') { |
| 68 | 59 | const text = json.text || ''; |
| 69 | 60 | const chunk = { choices: [{ text }] }; |
| 70 | 61 | response.write(`data: ${JSON.stringify(chunk)}\n\n`); |
| 71 | - partialData = ''; | |
| 72 | - } else { | |
| 73 | - partialData = ''; | |
| 74 | - break; | |
| 75 | 62 | } |
| 76 | 63 | } |
| 77 | - }); | |
| 78 | 64 | |
| 79 | - request.socket.on('close', function () { | |
| 80 | - if (jsonStream.body instanceof Readable) jsonStream.body.destroy(); | |
| 81 | - response.end(); | |
| 82 | - }); | |
| 83 | - | |
| 84 | - jsonStream.body.on('end', () => { | |
| 85 | 65 | console.log('Streaming request finished'); |
| 86 | 66 | response.write('data: [DONE]\n\n'); |
| 87 | 67 | response.end(); |
| 88 | - }); | |
| 89 | 68 | } catch (error) { |
| 90 | 69 | console.log('Error forwarding streaming response:', error); |
| 91 | 70 | if (!response.headersSent) { |
| @@ -233,7 +212,7 @@ async function sendScaleRequest(request, response) { | ||
| 233 | 212 | |
| 234 | 213 | if (!generateResponse.ok) { |
| 235 | 214 | console.log(`Scale API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); |
| 236 | 215 | return response.status(generateResponse.status500).send({ error: true }); |
| 237 | 216 | } |
| 238 | 217 | |
| 239 | 218 | const generateResponseJson = await generateResponse.json(); |
| @@ -413,6 +392,16 @@ async function sendAI21Request(request, response) { | ||
| 413 | 392 | request.socket.on('close', function () { |
| 414 | 393 | controller.abort(); |
| 415 | 394 | }); |
| 395 | + const convertedPrompt = convertAI21Messages(request.body.messages, request.body.char_name, request.body.user_name); | |
| 396 | + const body = { | |
| 397 | + messages: convertedPrompt, | |
| 398 | + model: request.body.model, | |
| 399 | + max_tokens: request.body.max_tokens, | |
| 400 | + temperature: request.body.temperature, | |
| 401 | + top_p: request.body.top_p, | |
| 402 | + stop: request.body.stop, | |
| 403 | + stream: request.body.stream, | |
| 404 | + }; | |
| 416 | 405 | const options = { |
| 417 | 406 | method: 'POST', |
| 418 | 407 | headers: { |
| @@ -420,59 +409,35 @@ async function sendAI21Request(request, response) { | ||
| 420 | 409 | 'content-type': 'application/json', |
| 421 | 410 | Authorization: `Bearer ${readSecret(request.user.directories, SECRET_KEYS.AI21)}`, |
| 422 | 411 | }, |
| 423 | 412 | body: JSON.stringify({body), |
| 424 | - numResults: 1, | |
| 425 | - maxTokens: request.body.max_tokens, | |
| 426 | - minTokens: 0, | |
| 427 | - temperature: request.body.temperature, | |
| 428 | - topP: request.body.top_p, | |
| 429 | - stopSequences: request.body.stop_tokens, | |
| 430 | - topKReturn: request.body.top_k, | |
| 431 | - frequencyPenalty: { | |
| 432 | - scale: request.body.frequency_penalty * 100, | |
| 433 | - applyToWhitespaces: false, | |
| 434 | - applyToPunctuations: false, | |
| 435 | - applyToNumbers: false, | |
| 436 | - applyToStopwords: false, | |
| 437 | - applyToEmojis: false, | |
| 438 | - }, | |
| 439 | - presencePenalty: { | |
| 440 | - scale: request.body.presence_penalty, | |
| 441 | - applyToWhitespaces: false, | |
| 442 | - applyToPunctuations: false, | |
| 443 | - applyToNumbers: false, | |
| 444 | - applyToStopwords: false, | |
| 445 | - applyToEmojis: false, | |
| 446 | - }, | |
| 447 | - countPenalty: { | |
| 448 | - scale: request.body.count_pen, | |
| 449 | - applyToWhitespaces: false, | |
| 450 | - applyToPunctuations: false, | |
| 451 | - applyToNumbers: false, | |
| 452 | - applyToStopwords: false, | |
| 453 | - applyToEmojis: false, | |
| 454 | - }, | |
| 455 | - prompt: request.body.messages, | |
| 456 | - }), | |
| 457 | 413 | signal: controller.signal, |
| 458 | 414 | }; |
| 459 | 415 | |
| 460 | - fetch(`https://api.ai21.com/studio/v1/${request.body.model}/complete`, options) | |
| 416 | + console.log('AI21 request:', body); | |
| 461 | - .then(r => r.json()) | |
| 417 | + | |
| 462 | - .then(r => { | |
| 418 | + try { | |
| 463 | - if (r.completions === undefined) { | |
| 419 | + const generateResponse = await fetch(API_AI21 + '/chat/completions', options); | |
| 464 | - console.log(r); | |
| 420 | + if (request.body.stream) { | |
| 421 | + forwardFetchResponse(generateResponse, response); | |
| 465 | 422 | } else { |
| 466 | - console.log(r.completions[0].data.text); | |
| 423 | + if (!generateResponse.ok) { | |
| 424 | + const errorText = await generateResponse.text(); | |
| 425 | + console.log(`AI21 API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); | |
| 426 | + const errorJson = tryParse(errorText) ?? { error: true }; | |
| 427 | + return response.status(500).send(errorJson); | |
| 428 | + } | |
| 429 | + const generateResponseJson = await generateResponse.json(); | |
| 430 | + console.log('AI21 response:', generateResponseJson); | |
| 431 | + return response.send(generateResponseJson); | |
| 432 | + } | |
| 433 | + } catch (error) { | |
| 434 | + console.log('Error communicating with AI21 API: ', error); | |
| 435 | + if (!response.headersSent) { | |
| 436 | + response.send({ error: true }); | |
| 437 | + } else { | |
| 438 | + response.end(); | |
| 439 | + } | |
| 467 | 440 | } |
| 468 | - const reply = { choices: [{ 'message': { 'content': r.completions?.[0]?.data?.text } }] }; | |
| 469 | - return response.send(reply); | |
| 470 | - }) | |
| 471 | - .catch(err => { | |
| 472 | - console.error(err); | |
| 473 | - return response.send({ error: true }); | |
| 474 | - }); | |
| 475 | - | |
| 476 | 441 | } |
| 477 | 442 | |
| 478 | 443 | /** |
| @@ -531,10 +496,10 @@ async function sendMistralAIRequest(request, response) { | ||
| 531 | 496 | forwardFetchResponse(generateResponse, response); |
| 532 | 497 | } else { |
| 533 | 498 | if (!generateResponse.ok) { |
| 534 | - console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); | |
| 499 | + const errorText = await generateResponse.text(); | |
| 535 | - // a 401 unauthorized response breaks the frontend auth, so return a 500 instead. prob a better way of dealing with this. | |
| 500 | + console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); | |
| 536 | - // 401s are already handled by the streaming processor and dont pop up an error toast, that should probably be fixed too. | |
| 501 | + const errorJson = tryParse(errorText) ?? { error: true }; | |
| 537 | 502 | return response.status(generateResponse.status === 401 ? 500 : generateResponse.status).send({ error: true }errorJson); |
| 538 | 503 | } |
| 539 | 504 | const generateResponseJson = await generateResponse.json(); |
| 540 | 505 | console.log('MistralAI response:', generateResponseJson); |
| @@ -607,6 +572,11 @@ async function sendCohereRequest(request, response) { | ||
| 607 | 572 | search_queries_only: false, |
| 608 | 573 | }; |
| 609 | 574 | |
| 575 | + const canDoSafetyMode = String(request.body.model).endsWith('08-2024'); | |
| 576 | + if (canDoSafetyMode) { | |
| 577 | + requestBody.safety_mode = 'NONE'; | |
| 578 | + } | |
| 579 | + | |
| 610 | 580 | console.log('Cohere request:', requestBody); |
| 611 | 581 | |
| 612 | 582 | const config = { |
| @@ -623,15 +593,15 @@ async function sendCohereRequest(request, response) { | ||
| 623 | 593 | const apiUrl = API_COHERE + '/chat'; |
| 624 | 594 | |
| 625 | 595 | if (request.body.stream) { |
| 626 | 596 | const stream = await global.fetch(apiUrl, config); |
| 627 | 597 | parseCohereStream(stream, request, response); |
| 628 | 598 | } else { |
| 629 | 599 | const generateResponse = await fetch(apiUrl, config); |
| 630 | 600 | if (!generateResponse.ok) { |
| 631 | - console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); | |
| 601 | + const errorText = await generateResponse.text(); | |
| 632 | - // a 401 unauthorized response breaks the frontend auth, so return a 500 instead. prob a better way of dealing with this. | |
| 602 | + console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); | |
| 633 | - // 401s are already handled by the streaming processor and dont pop up an error toast, that should probably be fixed too. | |
| 603 | + const errorJson = tryParse(errorText) ?? { error: true }; | |
| 634 | 604 | return response.status(generateResponse.status === 401 ? 500 : generateResponse.status).send({ error: true }errorJson); |
| 635 | 605 | } |
| 636 | 606 | const generateResponseJson = await generateResponse.json(); |
| 637 | 607 | console.log('Cohere response:', generateResponseJson); |
| @@ -6,6 +6,7 @@ const { readAllChunks, extractFileFromZipBuffer, forwardFetchResponse } = requir | ||
| 6 | 6 | const { jsonParser } = require('../express-common'); |
| 7 | 7 | |
| 8 | 8 | const API_NOVELAI = 'https://api.novelai.net'; |
| 9 | +const TEXT_NOVELAI = 'https://text.novelai.net'; | |
| 9 | 10 | const IMAGE_NOVELAI = 'https://image.novelai.net'; |
| 10 | 11 | |
| 11 | 12 | // Ban bracket generation, plus defaults |
| @@ -155,7 +156,7 @@ router.post('/generate', jsonParser, async function (req, res) { | ||
| 155 | 156 | 'repetition_penalty_slope': req.body.repetition_penalty_slope, |
| 156 | 157 | 'repetition_penalty_frequency': req.body.repetition_penalty_frequency, |
| 157 | 158 | 'repetition_penalty_presence': req.body.repetition_penalty_presence, |
| 158 | 159 | 'repetition_penalty_whitelist': isNewModel ? repPenaltyAllowList.flat() : null, |
| 159 | 160 | 'top_a': req.body.top_a, |
| 160 | 161 | 'top_p': req.body.top_p, |
| 161 | 162 | 'top_k': req.body.top_k, |
| @@ -178,9 +179,7 @@ router.post('/generate', jsonParser, async function (req, res) { | ||
| 178 | 179 | }; |
| 179 | 180 | |
| 180 | 181 | // Tells the model to stop generation at '>' |
| 181 | 182 | if ('theme_textadventure' === req.body.prefix && isNewModel) { |
| 182 | - (true === req.body.model.includes('clio') || | |
| 183 | - true === req.body.model.includes('kayra'))) { | |
| 184 | 183 | data.parameters.eos_token_id = 49405; |
| 185 | 184 | } |
| 186 | 185 | |
| @@ -193,7 +192,8 @@ router.post('/generate', jsonParser, async function (req, res) { | ||
| 193 | 192 | }; |
| 194 | 193 | |
| 195 | 194 | try { |
| 196 | 195 | const urlbaseURL = req.body.streamingmodel.includes('kayra') ? `${API_NOVELAI}/ai/generate-stream`TEXT_NOVELAI : `${API_NOVELAI}/ai/generate`; |
| 196 | + const url = req.body.streaming ? `${baseURL}/ai/generate-stream` : `${baseURL}/ai/generate`; | |
| 197 | 197 | const response = await fetch(url, { method: 'POST', timeout: 0, ...args }); |
| 198 | 198 | |
| 199 | 199 | if (req.body.streaming) { |
| @@ -144,6 +144,7 @@ const spp_nerd_v2 = new SentencePieceTokenizer('src/tokenizers/nerdstash_v2.mode | ||
| 144 | 144 | const spp_mistral = new SentencePieceTokenizer('src/tokenizers/mistral.model'); |
| 145 | 145 | const spp_yi = new SentencePieceTokenizer('src/tokenizers/yi.model'); |
| 146 | 146 | const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model'); |
| 147 | +const spp_jamba = new SentencePieceTokenizer('src/tokenizers/jamba.model'); | |
| 147 | 148 | const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json'); |
| 148 | 149 | const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json'); |
| 149 | 150 | |
| @@ -154,6 +155,7 @@ const sentencepieceTokenizers = [ | ||
| 154 | 155 | 'mistral', |
| 155 | 156 | 'yi', |
| 156 | 157 | 'gemma', |
| 158 | + 'jamba', | |
| 157 | 159 | ]; |
| 158 | 160 | |
| 159 | 161 | /** |
| @@ -186,6 +188,10 @@ function getSentencepiceTokenizer(model) { | ||
| 186 | 188 | return spp_gemma; |
| 187 | 189 | } |
| 188 | 190 | |
| 191 | + if (model.includes('jamba')) { | |
| 192 | + return spp_jamba; | |
| 193 | + } | |
| 194 | + | |
| 189 | 195 | return null; |
| 190 | 196 | } |
| 191 | 197 | |
| @@ -322,6 +328,10 @@ function getTokenizerModel(requestModel) { | ||
| 322 | 328 | return 'gemma'; |
| 323 | 329 | } |
| 324 | 330 | |
| 331 | + if (requestModel.includes('jamba')) { | |
| 332 | + return 'jamba'; | |
| 333 | + } | |
| 334 | + | |
| 325 | 335 | // default |
| 326 | 336 | return 'gpt-3.5-turbo'; |
| 327 | 337 | } |
| @@ -537,59 +547,13 @@ function createWebTokenizerDecodingHandler(tokenizer) { | ||
| 537 | 547 | |
| 538 | 548 | const router = express.Router(); |
| 539 | 549 | |
| 540 | -router.post('/ai21/count', jsonParser, async function (req, res) { | |
| 541 | - if (!req.body) return res.sendStatus(400); | |
| 542 | - const key = readSecret(req.user.directories, SECRET_KEYS.AI21); | |
| 543 | - const options = { | |
| 544 | - method: 'POST', | |
| 545 | - headers: { | |
| 546 | - accept: 'application/json', | |
| 547 | - 'content-type': 'application/json', | |
| 548 | - Authorization: `Bearer ${key}`, | |
| 549 | - }, | |
| 550 | - body: JSON.stringify({ text: req.body[0].content }), | |
| 551 | - }; | |
| 552 | - | |
| 553 | - try { | |
| 554 | - const response = await fetch('https://api.ai21.com/studio/v1/tokenize', options); | |
| 555 | - const data = await response.json(); | |
| 556 | - return res.send({ 'token_count': data?.tokens?.length || 0 }); | |
| 557 | - } catch (err) { | |
| 558 | - console.error(err); | |
| 559 | - return res.send({ 'token_count': 0 }); | |
| 560 | - } | |
| 561 | -}); | |
| 562 | - | |
| 563 | -router.post('/google/count', jsonParser, async function (req, res) { | |
| 564 | - if (!req.body) return res.sendStatus(400); | |
| 565 | - const options = { | |
| 566 | - method: 'POST', | |
| 567 | - headers: { | |
| 568 | - accept: 'application/json', | |
| 569 | - 'content-type': 'application/json', | |
| 570 | - }, | |
| 571 | - body: JSON.stringify({ contents: convertGooglePrompt(req.body, String(req.query.model)).contents }), | |
| 572 | - }; | |
| 573 | - try { | |
| 574 | - const reverseProxy = req.query.reverse_proxy?.toString() || ''; | |
| 575 | - const proxyPassword = req.query.proxy_password?.toString() || ''; | |
| 576 | - const apiKey = reverseProxy ? proxyPassword : readSecret(req.user.directories, SECRET_KEYS.MAKERSUITE); | |
| 577 | - const apiUrl = new URL(reverseProxy || API_MAKERSUITE); | |
| 578 | - const response = await fetch(`${apiUrl.origin}/v1beta/models/${req.query.model}:countTokens?key=${apiKey}`, options); | |
| 579 | - const data = await response.json(); | |
| 580 | - return res.send({ 'token_count': data?.totalTokens || 0 }); | |
| 581 | - } catch (err) { | |
| 582 | - console.error(err); | |
| 583 | - return res.send({ 'token_count': 0 }); | |
| 584 | - } | |
| 585 | -}); | |
| 586 | - | |
| 587 | 550 | router.post('/llama/encode', jsonParser, createSentencepieceEncodingHandler(spp_llama)); |
| 588 | 551 | router.post('/nerdstash/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd)); |
| 589 | 552 | router.post('/nerdstash_v2/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2)); |
| 590 | 553 | router.post('/mistral/encode', jsonParser, createSentencepieceEncodingHandler(spp_mistral)); |
| 591 | 554 | router.post('/yi/encode', jsonParser, createSentencepieceEncodingHandler(spp_yi)); |
| 592 | 555 | router.post('/gemma/encode', jsonParser, createSentencepieceEncodingHandler(spp_gemma)); |
| 556 | +router.post('/jamba/encode', jsonParser, createSentencepieceEncodingHandler(spp_jamba)); | |
| 593 | 557 | router.post('/gpt2/encode', jsonParser, createTiktokenEncodingHandler('gpt2')); |
| 594 | 558 | router.post('/claude/encode', jsonParser, createWebTokenizerEncodingHandler(claude_tokenizer)); |
| 595 | 559 | router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llama3_tokenizer)); |
| @@ -599,6 +563,7 @@ router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandl | ||
| 599 | 563 | router.post('/mistral/decode', jsonParser, createSentencepieceDecodingHandler(spp_mistral)); |
| 600 | 564 | router.post('/yi/decode', jsonParser, createSentencepieceDecodingHandler(spp_yi)); |
| 601 | 565 | router.post('/gemma/decode', jsonParser, createSentencepieceDecodingHandler(spp_gemma)); |
| 566 | +router.post('/jamba/decode', jsonParser, createSentencepieceDecodingHandler(spp_jamba)); | |
| 602 | 567 | router.post('/gpt2/decode', jsonParser, createTiktokenDecodingHandler('gpt2')); |
| 603 | 568 | router.post('/claude/decode', jsonParser, createWebTokenizerDecodingHandler(claude_tokenizer)); |
| 604 | 569 | router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llama3_tokenizer)); |
| @@ -637,6 +602,11 @@ router.post('/openai/encode', jsonParser, async function (req, res) { | ||
| 637 | 602 | return handler(req, res); |
| 638 | 603 | } |
| 639 | 604 | |
| 605 | + if (queryModel.includes('jamba')) { | |
| 606 | + const handler = createSentencepieceEncodingHandler(spp_jamba); | |
| 607 | + return handler(req, res); | |
| 608 | + } | |
| 609 | + | |
| 640 | 610 | const model = getTokenizerModel(queryModel); |
| 641 | 611 | const handler = createTiktokenEncodingHandler(model); |
| 642 | 612 | return handler(req, res); |
| @@ -680,6 +650,11 @@ router.post('/openai/decode', jsonParser, async function (req, res) { | ||
| 680 | 650 | return handler(req, res); |
| 681 | 651 | } |
| 682 | 652 | |
| 653 | + if (queryModel.includes('jamba')) { | |
| 654 | + const handler = createSentencepieceDecodingHandler(spp_jamba); | |
| 655 | + return handler(req, res); | |
| 656 | + } | |
| 657 | + | |
| 683 | 658 | const model = getTokenizerModel(queryModel); |
| 684 | 659 | const handler = createTiktokenDecodingHandler(model); |
| 685 | 660 | return handler(req, res); |
| @@ -731,6 +706,11 @@ router.post('/openai/count', jsonParser, async function (req, res) { | ||
| 731 | 706 | return res.send({ 'token_count': num_tokens }); |
| 732 | 707 | } |
| 733 | 708 | |
| 709 | + if (model === 'jamba') { | |
| 710 | + num_tokens = await countSentencepieceArrayTokens(spp_jamba, req.body); | |
| 711 | + return res.send({ 'token_count': num_tokens }); | |
| 712 | + } | |
| 713 | + | |
| 734 | 714 | const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1; |
| 735 | 715 | const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3; |
| 736 | 716 | const tokensPadding = 3; |
| @@ -110,6 +110,7 @@ router.post('/google', jsonParser, async (request, response) => { | ||
| 110 | 110 | }); |
| 111 | 111 | |
| 112 | 112 | router.post('/yandex', jsonParser, async (request, response) => { |
| 113 | + try { | |
| 113 | 114 | const chunks = request.body.chunks; |
| 114 | 115 | const lang = request.body.lang; |
| 115 | 116 | |
| @@ -130,7 +131,6 @@ router.post('/yandex', jsonParser, async (request, response) => { | ||
| 130 | 131 | |
| 131 | 132 | console.log('Input text: ' + inputText); |
| 132 | 133 | |
| 133 | - try { | |
| 134 | 134 | const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, { |
| 135 | 135 | method: 'POST', |
| 136 | 136 | body: params, |
| @@ -267,10 +267,13 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = ' | ||
| 267 | 267 | 'gemini-1.5-flash', |
| 268 | 268 | 'gemini-1.5-flash-latest', |
| 269 | 269 | 'gemini-1.5-flash-001', |
| 270 | + 'gemini-1.5-flash-exp-0827', | |
| 271 | + 'gemini-1.5-flash-8b-exp-0827', | |
| 270 | 272 | 'gemini-1.5-pro', |
| 271 | 273 | 'gemini-1.5-pro-latest', |
| 272 | 274 | 'gemini-1.5-pro-001', |
| 273 | 275 | 'gemini-1.5-pro-exp-0801', |
| 276 | + 'gemini-1.5-pro-exp-0827', | |
| 274 | 277 | 'gemini-1.0-pro-vision-latest', |
| 275 | 278 | 'gemini-pro-vision', |
| 276 | 279 | ]; |
| @@ -368,6 +371,78 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = ' | ||
| 368 | 371 | } |
| 369 | 372 | |
| 370 | 373 | /** |
| 374 | + * Convert AI21 prompt. Classic: system message squash, user/assistant message merge. | |
| 375 | + * @param {object[]} messages Array of messages | |
| 376 | + * @param {string} charName Character name | |
| 377 | + * @param {string} userName User name | |
| 378 | + */ | |
| 379 | +function convertAI21Messages(messages, charName = '', userName = '') { | |
| 380 | + if (!Array.isArray(messages)) { | |
| 381 | + return []; | |
| 382 | + } | |
| 383 | + | |
| 384 | + // Collect all the system messages up until the first instance of a non-system message, and then remove them from the messages array. | |
| 385 | + let i = 0, systemPrompt = ''; | |
| 386 | + | |
| 387 | + for (i = 0; i < messages.length; i++) { | |
| 388 | + if (messages[i].role !== 'system') { | |
| 389 | + break; | |
| 390 | + } | |
| 391 | + // Append example names if not already done by the frontend (e.g. for group chats). | |
| 392 | + if (userName && messages[i].name === 'example_user') { | |
| 393 | + if (!messages[i].content.startsWith(`${userName}: `)) { | |
| 394 | + messages[i].content = `${userName}: ${messages[i].content}`; | |
| 395 | + } | |
| 396 | + } | |
| 397 | + if (charName && messages[i].name === 'example_assistant') { | |
| 398 | + if (!messages[i].content.startsWith(`${charName}: `)) { | |
| 399 | + messages[i].content = `${charName}: ${messages[i].content}`; | |
| 400 | + } | |
| 401 | + } | |
| 402 | + systemPrompt += `${messages[i].content}\n\n`; | |
| 403 | + } | |
| 404 | + | |
| 405 | + messages.splice(0, i); | |
| 406 | + | |
| 407 | + // Prevent erroring out if the messages array is empty. | |
| 408 | + if (messages.length === 0) { | |
| 409 | + messages.unshift({ | |
| 410 | + role: 'user', | |
| 411 | + content: '[Start a new chat]', | |
| 412 | + }); | |
| 413 | + } | |
| 414 | + | |
| 415 | + if (systemPrompt) { | |
| 416 | + messages.unshift({ | |
| 417 | + role: 'system', | |
| 418 | + content: systemPrompt.trim(), | |
| 419 | + }); | |
| 420 | + } | |
| 421 | + | |
| 422 | + // Doesn't support completion names, so prepend if not already done by the frontend (e.g. for group chats). | |
| 423 | + messages.forEach(msg => { | |
| 424 | + if ('name' in msg) { | |
| 425 | + if (msg.role !== 'system' && !msg.content.startsWith(`${msg.name}: `)) { | |
| 426 | + msg.content = `${msg.name}: ${msg.content}`; | |
| 427 | + } | |
| 428 | + delete msg.name; | |
| 429 | + } | |
| 430 | + }); | |
| 431 | + | |
| 432 | + // Since the messaging endpoint only supports alternating turns, we have to merge messages with the same role if they follow each other | |
| 433 | + let mergedMessages = []; | |
| 434 | + messages.forEach((message) => { | |
| 435 | + if (mergedMessages.length > 0 && mergedMessages[mergedMessages.length - 1].role === message.role) { | |
| 436 | + mergedMessages[mergedMessages.length - 1].content += '\n\n' + message.content; | |
| 437 | + } else { | |
| 438 | + mergedMessages.push(message); | |
| 439 | + } | |
| 440 | + }); | |
| 441 | + | |
| 442 | + return mergedMessages; | |
| 443 | +} | |
| 444 | + | |
| 445 | +/** | |
| 371 | 446 | * Convert a prompt from the ChatML objects to the format used by MistralAI. |
| 372 | 447 | * @param {object[]} messages Array of messages |
| 373 | 448 | * @param {string} charName Character name |
| @@ -520,4 +595,5 @@ module.exports = { | ||
| 520 | 595 | convertCohereMessages, |
| 521 | 596 | convertMistralMessages, |
| 522 | 597 | convertCohereTools, |
| 598 | + convertAI21Messages, | |
| 523 | 599 | }; |
Binary file
| @@ -34,8 +34,9 @@ function getConfig() { | ||
| 34 | 34 | CACHED_CONFIG = config; |
| 35 | 35 | return config; |
| 36 | 36 | } catch (error) { |
| 37 | 37 | console.warnerror(color.red('FATAL: Failed to read config.yaml. Please check the file for syntax errors.')); |
| 38 | - return {}; | |
| 38 | + console.error(error.message); | |
| 39 | + process.exit(1); | |
| 39 | 40 | } |
| 40 | 41 | } |
| 41 | 42 | |
| @@ -298,8 +299,8 @@ const color = { | ||
| 298 | 299 | * @returns {string} A UUIDv4 string |
| 299 | 300 | */ |
| 300 | 301 | function uuidv4() { |
| 301 | 302 | if ('crypto' in global && 'randomUUID' in global.crypto) { |
| 302 | 303 | return global.crypto.randomUUID(); |
| 303 | 304 | } |
| 304 | 305 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { |
| 305 | 306 | const r = Math.random() * 16 | 0; |