Merge pull request #3237 from SillyTavern/deepseek Deepseek

44833b665e8be687a8773ae51ad169e153af7fff

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

Signed
12 files changed, +186 -15Ignore whitespace
public/img/deepseek.svg+6 -0
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
3<g id="surface1">
4<path d="M 126.65625 23.902344 C 125.300781 23.242188 124.714844 24.507812 123.925781 25.152344 C 123.652344 25.359375 123.425781 25.632812 123.195312 25.878906 C 121.210938 27.996094 118.894531 29.382812 115.871094 29.214844 C 111.449219 28.96875 107.675781 30.355469 104.335938 33.738281 C 103.625 29.566406 101.269531 27.082031 97.683594 25.484375 C 95.808594 24.652344 93.910156 23.824219 92.59375 22.015625 C 91.675781 20.730469 91.425781 19.296875 90.964844 17.886719 C 90.671875 17.035156 90.378906 16.164062 89.402344 16.019531 C 88.335938 15.855469 87.921875 16.746094 87.503906 17.492188 C 85.835938 20.542969 85.1875 23.902344 85.253906 27.308594 C 85.398438 34.964844 88.628906 41.066406 95.054688 45.402344 C 95.785156 45.898438 95.972656 46.398438 95.742188 47.125 C 95.308594 48.617188 94.785156 50.070312 94.324219 51.566406 C 94.03125 52.523438 93.59375 52.726562 92.570312 52.316406 C 89.109375 50.828125 85.96875 48.691406 83.3125 46.019531 C 78.742188 41.605469 74.613281 36.730469 69.460938 32.910156 C 68.269531 32.03125 67.042969 31.191406 65.785156 30.398438 C 60.535156 25.296875 66.480469 21.105469 67.855469 20.609375 C 69.296875 20.085938 68.351562 18.304688 63.703125 18.324219 C 59.050781 18.347656 54.792969 19.898438 49.371094 21.972656 C 48.566406 22.28125 47.734375 22.527344 46.890625 22.703125 C 41.820312 21.75 36.636719 21.566406 31.515625 22.160156 C 21.460938 23.28125 13.433594 28.039062 7.53125 36.148438 C 0.4375 45.898438 -1.230469 56.980469 0.8125 68.535156 C 2.960938 80.714844 9.179688 90.800781 18.730469 98.683594 C 28.640625 106.859375 40.046875 110.863281 53.066406 110.097656 C 60.96875 109.644531 69.777344 108.582031 79.703125 100.175781 C 82.207031 101.425781 84.832031 101.921875 89.195312 102.292969 C 92.554688 102.609375 95.785156 102.132812 98.289062 101.609375 C 102.207031 100.777344 101.9375 97.148438 100.523438 96.484375 C 89.03125 91.128906 91.550781 93.3125 89.253906 91.546875 C 95.097656 84.632812 103.898438 77.457031 107.34375 54.199219 C 107.609375 52.347656 107.382812 51.183594 107.34375 49.691406 C 107.324219 48.785156 107.53125 48.425781 108.570312 48.324219 C 111.457031 48.027344 114.253906 47.164062 116.8125 45.792969 C 124.257812 41.722656 127.265625 35.046875 127.972656 27.035156 C 128.078125 25.808594 127.953125 24.542969 126.65625 23.898438 Z M 61.765625 96 C 50.625 87.242188 45.222656 84.355469 42.992188 84.480469 C 40.902344 84.609375 41.28125 86.992188 41.738281 88.550781 C 42.21875 90.085938 42.84375 91.140625 43.71875 92.492188 C 44.324219 93.382812 44.742188 94.710938 43.113281 95.707031 C 39.523438 97.925781 33.289062 94.960938 32.996094 94.816406 C 25.738281 90.539062 19.664062 84.894531 15.390625 77.179688 C 11.265625 69.75 8.863281 61.78125 8.46875 53.273438 C 8.363281 51.214844 8.964844 50.492188 11.011719 50.117188 C 13.703125 49.601562 16.457031 49.53125 19.167969 49.910156 C 30.539062 51.574219 40.214844 56.65625 48.332031 64.703125 C 52.960938 69.289062 56.464844 74.769531 60.074219 80.121094 C 63.914062 85.808594 68.042969 91.226562 73.300781 95.664062 C 75.15625 97.222656 76.632812 98.40625 78.054688 99.273438 C 73.777344 99.753906 66.640625 99.863281 61.765625 96 Z M 67.097656 61.652344 C 67.097656 61.117188 67.359375 60.609375 67.800781 60.304688 C 68.246094 60 68.808594 59.929688 69.3125 60.121094 C 70.378906 62.097656 70.207031 62.515625 69.894531 62.824219 C 69.585938 63.132812 69.164062 63.300781 68.726562 63.296875 C 68.292969 63.296875 67.875 63.125 67.570312 62.816406 C 67.265625 62.507812 67.097656 62.085938 67.105469 61.652344 Z M 83.683594 70.164062 C 82.617188 70.597656 81.558594 70.96875 80.539062 71.019531 C 79.007812 71.070312 77.503906 70.59375 76.28125 69.664062 C 74.820312 68.4375 73.777344 67.753906 73.339844 65.621094 C 73.1875 64.578125 73.214844 63.519531 73.425781 62.484375 C 73.796875 60.742188 73.382812 59.621094 72.148438 58.609375 C 71.152344 57.777344 69.878906 57.546875 68.480469 57.546875 C 68 57.519531 67.535156 57.375 67.125 57.128906 C 66.539062 56.84375 66.058594 56.117188 66.515625 55.222656 C 66.667969 54.933594 67.371094 54.230469 67.542969 54.101562 C 69.441406 53.023438 71.632812 53.375 73.652344 54.1875 C 75.53125 54.953125 76.949219 56.363281 78.992188 58.355469 C 81.078125 60.761719 81.457031 61.429688 82.644531 63.230469 C 83.585938 64.644531 84.4375 66.097656 85.019531 67.753906 C 85.375 68.792969 84.917969 69.644531 83.683594 70.164062 Z M 83.683594 70.164062 "/>
5</g>
6</svg>
public/index.html+26 -6
@@ -682,7 +682,7 @@
682 </span>682 </span>
683 </div>683 </div>
684 </div>684 </div>
685 <div class="range-block" data-source="openai,claude,windowai,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt">685 <div class="range-block" data-source="openai,claude,windowai,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt,deepseek">
686 <div class="range-block-title" data-i18n="Temperature">686 <div class="range-block-title" data-i18n="Temperature">
687 Temperature687 Temperature
688 </div>688 </div>
@@ -695,7 +695,7 @@
695 </div>695 </div>
696 </div>696 </div>
697 </div>697 </div>
698 <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt">698 <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek">
699 <div class="range-block-title" data-i18n="Frequency Penalty">699 <div class="range-block-title" data-i18n="Frequency Penalty">
700 Frequency Penalty700 Frequency Penalty
701 </div>701 </div>
@@ -708,7 +708,7 @@
708 </div>708 </div>
709 </div>709 </div>
710 </div>710 </div>
711 <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt">711 <div class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq,mistralai,nanogpt,deepseek">
712 <div class="range-block-title" data-i18n="Presence Penalty">712 <div class="range-block-title" data-i18n="Presence Penalty">
713 Presence Penalty713 Presence Penalty
714 </div>714 </div>
@@ -734,7 +734,7 @@
734 </div>734 </div>
735 </div>735 </div>
736 </div>736 </div>
737 <div class="range-block" data-source="openai,claude,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt">737 <div class="range-block" data-source="openai,claude,openrouter,ai21,scale,makersuite,mistralai,custom,cohere,perplexity,groq,01ai,nanogpt,deepseek">
738 <div class="range-block-title" data-i18n="Top P">738 <div class="range-block-title" data-i18n="Top P">
739 Top P739 Top P
740 </div>740 </div>
@@ -2679,6 +2679,7 @@
2679 <option value="blockentropy">Block Entropy</option>2679 <option value="blockentropy">Block Entropy</option>
2680 <option value="claude">Claude</option>2680 <option value="claude">Claude</option>
2681 <option value="cohere">Cohere</option>2681 <option value="cohere">Cohere</option>
2682 <option value="deepseek">DeepSeek</option>
2682 <option value="groq">Groq</option>2683 <option value="groq">Groq</option>
2683 <option value="makersuite">Google AI Studio</option>2684 <option value="makersuite">Google AI Studio</option>
2684 <option value="mistralai">MistralAI</option>2685 <option value="mistralai">MistralAI</option>
@@ -3192,6 +3193,23 @@
3192 </select>3193 </select>
3193 </div>3194 </div>
3194 </div>3195 </div>
3196 <div id="deepseek_form" data-source="deepseek">
3197 <h4 data-i18n="DeepSeek API Key">DeepSeek API Key</h4>
3198 <div class="flex-container">
3199 <input id="api_key_deepseek" name="api_key_deepseek" class="text_pole flex1" value="" type="text" autocomplete="off">
3200 <div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_nanogpt"></div>
3201 </div>
3202 <div data-for="api_key_deepseek" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page.">
3203 For privacy reasons, your API key will be hidden after you reload the page.
3204 </div>
3205 <div>
3206 <h4 data-i18n="DeepSeek Model">DeepSeek Model</h4>
3207 <select id="model_deepseek_select">
3208 <option value="deepseek-chat">deepseek-chat</option>
3209 <option value="deepseek-coder">deepseek-coder</option>
3210 </select>
3211 </div>
3212 </div>
3195 <div id="perplexity_form" data-source="perplexity">3213 <div id="perplexity_form" data-source="perplexity">
3196 <h4 data-i18n="Perplexity API Key">Perplexity API Key</h4>3214 <h4 data-i18n="Perplexity API Key">Perplexity API Key</h4>
3197 <div class="flex-container">3215 <div class="flex-container">
@@ -3311,8 +3329,9 @@
3311 <h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4>3329 <h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4>
3312 <select id="custom_prompt_post_processing" class="text_pole" title="Applies additional processing to the prompt before sending it to the API." data-i18n="[title]Applies additional processing to the prompt before sending it to the API.">3330 <select id="custom_prompt_post_processing" class="text_pole" title="Applies additional processing to the prompt before sending it to the API." data-i18n="[title]Applies additional processing to the prompt before sending it to the API.">
3313 <option data-i18n="prompt_post_processing_none" value="">None</option>3331 <option data-i18n="prompt_post_processing_none" value="">None</option>
3314 <option value="merge">Merge consecutive roles</option>3332 <option data-i18n="prompt_post_processing_merge" value="merge">Merge consecutive roles</option>
3315 <option value="strict">Strict (user first, alternating roles)</option>3333 <option data-i18n="prompt_post_processing_semi" value="semi">Semi-strict (alternating roles)</option>
3334 <option data-i18n="prompt_post_processing_strict" value="strict">Strict (user first, alternating roles)</option>
3316 </select>3335 </select>
3317 </form>3336 </form>
3318 <div id="01ai_form" data-source="01ai">3337 <div id="01ai_form" data-source="01ai">
@@ -3762,6 +3781,7 @@
3762 <option value="17">Mistral Nemo</option>3781 <option value="17">Mistral Nemo</option>
3763 <option value="8">Yi</option>3782 <option value="8">Yi</option>
3764 <option value="11">Claude 1/2</option>3783 <option value="11">Claude 1/2</option>
3784 <option value="18">DeepSeek V3</option>
3765 <option value="6">API (WebUI / koboldcpp)</option>3785 <option value="6">API (WebUI / koboldcpp)</option>
3766 </select>3786 </select>
3767 </div>3787 </div>
public/scripts/RossAscends-mods.js+1 -0
@@ -390,6 +390,7 @@ function RA_autoconnect(PrevApi) {
390 || (secret_state[SECRET_KEYS.ZEROONEAI] && oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI)390 || (secret_state[SECRET_KEYS.ZEROONEAI] && oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI)
391 || (secret_state[SECRET_KEYS.BLOCKENTROPY] && oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY)391 || (secret_state[SECRET_KEYS.BLOCKENTROPY] && oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY)
392 || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT)392 || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT)
393 || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK)
393 || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM)394 || (isValidUrl(oai_settings.custom_url) && oai_settings.chat_completion_source == chat_completion_sources.CUSTOM)
394 ) {395 ) {
395 $('#api_button_openai').trigger('click');396 $('#api_button_openai').trigger('click');
public/scripts/openai.js+79 -1
@@ -183,6 +183,7 @@ export const chat_completion_sources = {
183 ZEROONEAI: '01ai',183 ZEROONEAI: '01ai',
184 BLOCKENTROPY: 'blockentropy',184 BLOCKENTROPY: 'blockentropy',
185 NANOGPT: 'nanogpt',185 NANOGPT: 'nanogpt',
186 DEEPSEEK: 'deepseek',
186};187};
187188
188const character_names_behavior = {189const character_names_behavior = {
@@ -204,6 +205,7 @@ const custom_prompt_post_processing_types = {
204 /** @deprecated Use MERGE instead. */205 /** @deprecated Use MERGE instead. */
205 CLAUDE: 'claude',206 CLAUDE: 'claude',
206 MERGE: 'merge',207 MERGE: 'merge',
208 SEMI: 'semi',
207 STRICT: 'strict',209 STRICT: 'strict',
208};210};
209211
@@ -261,6 +263,7 @@ const default_settings = {
261 nanogpt_model: 'gpt-4o-mini',263 nanogpt_model: 'gpt-4o-mini',
262 zerooneai_model: 'yi-large',264 zerooneai_model: 'yi-large',
263 blockentropy_model: 'be-70b-base-llama3.1',265 blockentropy_model: 'be-70b-base-llama3.1',
266 deepseek_model: 'deepseek-chat',
264 custom_model: '',267 custom_model: '',
265 custom_url: '',268 custom_url: '',
266 custom_include_body: '',269 custom_include_body: '',
@@ -339,6 +342,7 @@ const oai_settings = {
339 nanogpt_model: 'gpt-4o-mini',342 nanogpt_model: 'gpt-4o-mini',
340 zerooneai_model: 'yi-large',343 zerooneai_model: 'yi-large',
341 blockentropy_model: 'be-70b-base-llama3.1',344 blockentropy_model: 'be-70b-base-llama3.1',
345 deepseek_model: 'deepseek-chat',
342 custom_model: '',346 custom_model: '',
343 custom_url: '',347 custom_url: '',
344 custom_include_body: '',348 custom_include_body: '',
@@ -1523,6 +1527,8 @@ function getChatCompletionModel() {
1523 return oai_settings.blockentropy_model;1527 return oai_settings.blockentropy_model;
1524 case chat_completion_sources.NANOGPT:1528 case chat_completion_sources.NANOGPT:
1525 return oai_settings.nanogpt_model;1529 return oai_settings.nanogpt_model;
1530 case chat_completion_sources.DEEPSEEK:
1531 return oai_settings.deepseek_model;
1526 default:1532 default:
1527 throw new Error(`Unknown chat completion source: ${oai_settings.chat_completion_source}`);1533 throw new Error(`Unknown chat completion source: ${oai_settings.chat_completion_source}`);
1528 }1534 }
@@ -1698,6 +1704,24 @@ function saveModelList(data) {
16981704
1699 $('#model_nanogpt_select').val(oai_settings.nanogpt_model).trigger('change');1705 $('#model_nanogpt_select').val(oai_settings.nanogpt_model).trigger('change');
1700 }1706 }
1707
1708 if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) {
1709 $('#model_deepseek_select').empty();
1710 model_list.forEach((model) => {
1711 $('#model_deepseek_select').append(
1712 $('<option>', {
1713 value: model.id,
1714 text: model.id,
1715 }));
1716 });
1717
1718 const selectedModel = model_list.find(model => model.id === oai_settings.deepseek_model);
1719 if (model_list.length > 0 && (!selectedModel || !oai_settings.deepseek_model)) {
1720 oai_settings.deepseek_model = model_list[0].id;
1721 }
1722
1723 $('#model_deepseek_select').val(oai_settings.deepseek_model).trigger('change');
1724 }
1701}1725}
17021726
1703function appendOpenRouterOptions(model_list, groupModels = false, sort = false) {1727function appendOpenRouterOptions(model_list, groupModels = false, sort = false) {
@@ -1838,6 +1862,7 @@ async function sendOpenAIRequest(type, messages, signal) {
1838 const isGroq = oai_settings.chat_completion_source == chat_completion_sources.GROQ;1862 const isGroq = oai_settings.chat_completion_source == chat_completion_sources.GROQ;
1839 const is01AI = oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI;1863 const is01AI = oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI;
1840 const isNano = oai_settings.chat_completion_source == chat_completion_sources.NANOGPT;1864 const isNano = oai_settings.chat_completion_source == chat_completion_sources.NANOGPT;
1865 const isDeepSeek = oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK;
1841 const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model);1866 const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model);
1842 const isQuiet = type === 'quiet';1867 const isQuiet = type === 'quiet';
1843 const isImpersonate = type === 'impersonate';1868 const isImpersonate = type === 'impersonate';
@@ -1902,7 +1927,7 @@ async function sendOpenAIRequest(type, messages, signal) {
1902 }1927 }
19031928
1904 // Add logprobs request (currently OpenAI only, max 5 on their side)1929 // Add logprobs request (currently OpenAI only, max 5 on their side)
1905 if (useLogprobs && (isOAI || isCustom)) {1930 if (useLogprobs && (isOAI || isCustom || isDeepSeek)) {
1906 generate_data['logprobs'] = 5;1931 generate_data['logprobs'] = 5;
1907 }1932 }
19081933
@@ -2000,6 +2025,11 @@ async function sendOpenAIRequest(type, messages, signal) {
2000 delete generate_data.stop;2025 delete generate_data.stop;
2001 }2026 }
20022027
2028 // https://api-docs.deepseek.com/api/create-chat-completion
2029 if (isDeepSeek) {
2030 generate_data.top_p = generate_data.top_p || Number.EPSILON;
2031 }
2032
2003 if ((isOAI || isOpenRouter || isMistral || isCustom || isCohere || isNano) && oai_settings.seed >= 0) {2033 if ((isOAI || isOpenRouter || isMistral || isCustom || isCohere || isNano) && oai_settings.seed >= 0) {
2004 generate_data['seed'] = oai_settings.seed;2034 generate_data['seed'] = oai_settings.seed;
2005 }2035 }
@@ -2122,6 +2152,7 @@ function parseChatCompletionLogprobs(data) {
21222152
2123 switch (oai_settings.chat_completion_source) {2153 switch (oai_settings.chat_completion_source) {
2124 case chat_completion_sources.OPENAI:2154 case chat_completion_sources.OPENAI:
2155 case chat_completion_sources.DEEPSEEK:
2125 case chat_completion_sources.CUSTOM:2156 case chat_completion_sources.CUSTOM:
2126 if (!data.choices?.length) {2157 if (!data.choices?.length) {
2127 return null;2158 return null;
@@ -3041,6 +3072,7 @@ function loadOpenAISettings(data, settings) {
3041 oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model;3072 oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model;
3042 oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model;3073 oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model;
3043 oai_settings.nanogpt_model = settings.nanogpt_model ?? default_settings.nanogpt_model;3074 oai_settings.nanogpt_model = settings.nanogpt_model ?? default_settings.nanogpt_model;
3075 oai_settings.deepseek_model = settings.deepseek_model ?? default_settings.deepseek_model;
3044 oai_settings.blockentropy_model = settings.blockentropy_model ?? default_settings.blockentropy_model;3076 oai_settings.blockentropy_model = settings.blockentropy_model ?? default_settings.blockentropy_model;
3045 oai_settings.zerooneai_model = settings.zerooneai_model ?? default_settings.zerooneai_model;3077 oai_settings.zerooneai_model = settings.zerooneai_model ?? default_settings.zerooneai_model;
3046 oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model;3078 oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model;
@@ -3122,6 +3154,8 @@ function loadOpenAISettings(data, settings) {
3122 $(`#model_groq_select option[value="${oai_settings.groq_model}"`).attr('selected', true);3154 $(`#model_groq_select option[value="${oai_settings.groq_model}"`).attr('selected', true);
3123 $('#model_nanogpt_select').val(oai_settings.nanogpt_model);3155 $('#model_nanogpt_select').val(oai_settings.nanogpt_model);
3124 $(`#model_nanogpt_select option[value="${oai_settings.nanogpt_model}"`).attr('selected', true);3156 $(`#model_nanogpt_select option[value="${oai_settings.nanogpt_model}"`).attr('selected', true);
3157 $('#model_deepseek_select').val(oai_settings.deepseek_model);
3158 $(`#model_deepseek_select option[value="${oai_settings.deepseek_model}"`).prop('selected', true);
3125 $('#model_01ai_select').val(oai_settings.zerooneai_model);3159 $('#model_01ai_select').val(oai_settings.zerooneai_model);
3126 $('#model_blockentropy_select').val(oai_settings.blockentropy_model);3160 $('#model_blockentropy_select').val(oai_settings.blockentropy_model);
3127 $('#custom_model_id').val(oai_settings.custom_model);3161 $('#custom_model_id').val(oai_settings.custom_model);
@@ -3861,6 +3895,7 @@ function onSettingsPresetChange() {
3861 perplexity_model: ['#model_perplexity_select', 'perplexity_model', false],3895 perplexity_model: ['#model_perplexity_select', 'perplexity_model', false],
3862 groq_model: ['#model_groq_select', 'groq_model', false],3896 groq_model: ['#model_groq_select', 'groq_model', false],
3863 nanogpt_model: ['#model_nanogpt_select', 'nanogpt_model', false],3897 nanogpt_model: ['#model_nanogpt_select', 'nanogpt_model', false],
3898 deepseek_model: ['#model_deepseek_select', 'deepseek_model', false],
3864 zerooneai_model: ['#model_01ai_select', 'zerooneai_model', false],3899 zerooneai_model: ['#model_01ai_select', 'zerooneai_model', false],
3865 blockentropy_model: ['#model_blockentropy_select', 'blockentropy_model', false],3900 blockentropy_model: ['#model_blockentropy_select', 'blockentropy_model', false],
3866 custom_model: ['#custom_model_id', 'custom_model', false],3901 custom_model: ['#custom_model_id', 'custom_model', false],
@@ -4120,6 +4155,16 @@ async function onModelChange() {
4120 oai_settings.nanogpt_model = value;4155 oai_settings.nanogpt_model = value;
4121 }4156 }
41224157
4158 if ($(this).is('#model_deepseek_select')) {
4159 if (!value) {
4160 console.debug('Null DeepSeek model selected. Ignoring.');
4161 return;
4162 }
4163
4164 console.log('DeepSeek model changed to', value);
4165 oai_settings.deepseek_model = value;
4166 }
4167
4123 if (value && $(this).is('#model_01ai_select')) {4168 if (value && $(this).is('#model_01ai_select')) {
4124 console.log('01.AI model changed to', value);4169 console.log('01.AI model changed to', value);
4125 oai_settings.zerooneai_model = value;4170 oai_settings.zerooneai_model = value;
@@ -4436,6 +4481,22 @@ async function onModelChange() {
4436 $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');4481 $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
4437 }4482 }
44384483
4484 if (oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK) {
4485 if (oai_settings.max_context_unlocked) {
4486 $('#openai_max_context').attr('max', unlocked_max);
4487 } else if (oai_settings.deepseek_model == 'deepseek-chat') {
4488 $('#openai_max_context').attr('max', max_64k);
4489 } else if (oai_settings.deepseek_model == 'deepseek-coder') {
4490 $('#openai_max_context').attr('max', max_16k);
4491 } else {
4492 $('#openai_max_context').attr('max', max_64k);
4493 }
4494
4495 oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
4496 $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
4497 $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
4498 }
4499
4439 if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) {4500 if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) {
4440 oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1);4501 oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1);
4441 $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input');4502 $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input');
@@ -4653,6 +4714,19 @@ async function onConnectButtonClick(e) {
4653 }4714 }
4654 }4715 }
46554716
4717 if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) {
4718 const api_key_deepseek = String($('#api_key_deepseek').val()).trim();
4719
4720 if (api_key_deepseek.length) {
4721 await writeSecret(SECRET_KEYS.DEEPSEEK, api_key_deepseek);
4722 }
4723
4724 if (!secret_state[SECRET_KEYS.DEEPSEEK]) {
4725 console.log('No secret key saved for DeepSeek');
4726 return;
4727 }
4728 }
4729
4656 if (oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) {4730 if (oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) {
4657 const api_key_01ai = String($('#api_key_01ai').val()).trim();4731 const api_key_01ai = String($('#api_key_01ai').val()).trim();
46584732
@@ -4734,6 +4808,9 @@ function toggleChatCompletionForms() {
4734 else if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) {4808 else if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) {
4735 $('#model_blockentropy_select').trigger('change');4809 $('#model_blockentropy_select').trigger('change');
4736 }4810 }
4811 else if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) {
4812 $('#model_deepseek_select').trigger('change');
4813 }
4737 $('[data-source]').each(function () {4814 $('[data-source]').each(function () {
4738 const validSources = $(this).data('source').split(',');4815 const validSources = $(this).data('source').split(',');
4739 $(this).toggle(validSources.includes(oai_settings.chat_completion_source));4816 $(this).toggle(validSources.includes(oai_settings.chat_completion_source));
@@ -5447,6 +5524,7 @@ export function initOpenAI() {
5447 $('#model_perplexity_select').on('change', onModelChange);5524 $('#model_perplexity_select').on('change', onModelChange);
5448 $('#model_groq_select').on('change', onModelChange);5525 $('#model_groq_select').on('change', onModelChange);
5449 $('#model_nanogpt_select').on('change', onModelChange);5526 $('#model_nanogpt_select').on('change', onModelChange);
5527 $('#model_deepseek_select').on('change', onModelChange);
5450 $('#model_01ai_select').on('change', onModelChange);5528 $('#model_01ai_select').on('change', onModelChange);
5451 $('#model_blockentropy_select').on('change', onModelChange);5529 $('#model_blockentropy_select').on('change', onModelChange);
5452 $('#model_custom_select').on('change', onModelChange);5530 $('#model_custom_select').on('change', onModelChange);
public/scripts/secrets.js+2 -0
@@ -39,6 +39,7 @@ export const SECRET_KEYS = {
39 TAVILY: 'api_key_tavily',39 TAVILY: 'api_key_tavily',
40 BFL: 'api_key_bfl',40 BFL: 'api_key_bfl',
41 GENERIC: 'api_key_generic',41 GENERIC: 'api_key_generic',
42 DEEPSEEK: 'api_key_deepseek',
42};43};
4344
44const INPUT_MAP = {45const INPUT_MAP = {
@@ -73,6 +74,7 @@ const INPUT_MAP = {
73 [SECRET_KEYS.BLOCKENTROPY]: '#api_key_blockentropy',74 [SECRET_KEYS.BLOCKENTROPY]: '#api_key_blockentropy',
74 [SECRET_KEYS.NANOGPT]: '#api_key_nanogpt',75 [SECRET_KEYS.NANOGPT]: '#api_key_nanogpt',
75 [SECRET_KEYS.GENERIC]: '#api_key_generic',76 [SECRET_KEYS.GENERIC]: '#api_key_generic',
77 [SECRET_KEYS.DEEPSEEK]: '#api_key_deepseek',
76};78};
7779
78async function clearSecret() {80async function clearSecret() {
public/scripts/slash-commands.js+1 -0
@@ -3815,6 +3815,7 @@ function getModelOptions(quiet) {
3815 { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT },3815 { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT },
3816 { id: 'model_01ai_select', api: 'openai', type: chat_completion_sources.ZEROONEAI },3816 { id: 'model_01ai_select', api: 'openai', type: chat_completion_sources.ZEROONEAI },
3817 { id: 'model_blockentropy_select', api: 'openai', type: chat_completion_sources.BLOCKENTROPY },3817 { id: 'model_blockentropy_select', api: 'openai', type: chat_completion_sources.BLOCKENTROPY },
3818 { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK },
3818 { id: 'model_novel_select', api: 'novel', type: null },3819 { id: 'model_novel_select', api: 'novel', type: null },
3819 { id: 'horde_model', api: 'koboldhorde', type: null },3820 { id: 'horde_model', api: 'koboldhorde', type: null },
3820 ];3821 ];
public/scripts/tokenizers.js+15 -0
@@ -31,6 +31,7 @@ export const tokenizers = {
31 QWEN2: 15,31 QWEN2: 15,
32 COMMAND_R: 16,32 COMMAND_R: 16,
33 NEMO: 17,33 NEMO: 17,
34 DEEPSEEK: 18,
34 BEST_MATCH: 99,35 BEST_MATCH: 99,
35 MANUAL_SELECTION: 411,36 MANUAL_SELECTION: 411,
36};37};
@@ -46,6 +47,7 @@ export const ENCODE_TOKENIZERS = [
46 tokenizers.QWEN2,47 tokenizers.QWEN2,
47 tokenizers.COMMAND_R,48 tokenizers.COMMAND_R,
48 tokenizers.NEMO,49 tokenizers.NEMO,
50 tokenizers.DEEPSEEK,
49 // uncomment when NovelAI releases Kayra and Clio weights, lol51 // uncomment when NovelAI releases Kayra and Clio weights, lol
50 //tokenizers.NERD,52 //tokenizers.NERD,
51 //tokenizers.NERD2,53 //tokenizers.NERD2,
@@ -133,6 +135,11 @@ const TOKENIZER_URLS = {
133 decode: '/api/tokenizers/nemo/decode',135 decode: '/api/tokenizers/nemo/decode',
134 count: '/api/tokenizers/nemo/encode',136 count: '/api/tokenizers/nemo/encode',
135 },137 },
138 [tokenizers.DEEPSEEK]: {
139 encode: '/api/tokenizers/deepseek/encode',
140 decode: '/api/tokenizers/deepseek/decode',
141 count: '/api/tokenizers/deepseek/encode',
142 },
136 [tokenizers.API_TEXTGENERATIONWEBUI]: {143 [tokenizers.API_TEXTGENERATIONWEBUI]: {
137 encode: '/api/tokenizers/remote/textgenerationwebui/encode',144 encode: '/api/tokenizers/remote/textgenerationwebui/encode',
138 count: '/api/tokenizers/remote/textgenerationwebui/encode',145 count: '/api/tokenizers/remote/textgenerationwebui/encode',
@@ -551,12 +558,17 @@ export function getTokenizerModel() {
551 const qwen2Tokenizer = 'qwen2';558 const qwen2Tokenizer = 'qwen2';
552 const commandRTokenizer = 'command-r';559 const commandRTokenizer = 'command-r';
553 const nemoTokenizer = 'nemo';560 const nemoTokenizer = 'nemo';
561 const deepseekTokenizer = 'deepseek';
554562
555 // Assuming no one would use it for different models.. right?563 // Assuming no one would use it for different models.. right?
556 if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) {564 if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) {
557 return gpt4Tokenizer;565 return gpt4Tokenizer;
558 }566 }
559567
568 if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) {
569 return deepseekTokenizer;
570 }
571
560 // Select correct tokenizer for WindowAI proxies572 // Select correct tokenizer for WindowAI proxies
561 if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI && oai_settings.windowai_model) {573 if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI && oai_settings.windowai_model) {
562 if (oai_settings.windowai_model.includes('gpt-4')) {574 if (oai_settings.windowai_model.includes('gpt-4')) {
@@ -619,6 +631,9 @@ export function getTokenizerModel() {
619 else if (oai_settings.openrouter_model.includes('jamba')) {631 else if (oai_settings.openrouter_model.includes('jamba')) {
620 return jambaTokenizer;632 return jambaTokenizer;
621 }633 }
634 else if (oai_settings.openrouter_model.includes('deepseek')) {
635 return deepseekTokenizer;
636 }
622 }637 }
623638
624 if (oai_settings.chat_completion_source == chat_completion_sources.COHERE) {639 if (oai_settings.chat_completion_source == chat_completion_sources.COHERE) {
src/constants.js+1 -0
@@ -175,6 +175,7 @@ export const CHAT_COMPLETION_SOURCES = {
175 ZEROONEAI: '01ai',175 ZEROONEAI: '01ai',
176 BLOCKENTROPY: 'blockentropy',176 BLOCKENTROPY: 'blockentropy',
177 NANOGPT: 'nanogpt',177 NANOGPT: 'nanogpt',
178 DEEPSEEK: 'deepseek',
178};179};
179180
180/**181/**
src/endpoints/backends/chat-completions.js+23 -2
@@ -51,6 +51,7 @@ const API_01AI = 'https://api.01.ai/v1';
51const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1';51const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1';
52const API_AI21 = 'https://api.ai21.com/studio/v1';52const API_AI21 = 'https://api.ai21.com/studio/v1';
53const API_NANOGPT = 'https://nano-gpt.com/api/v1';53const API_NANOGPT = 'https://nano-gpt.com/api/v1';
54const API_DEEPSEEK = 'https://api.deepseek.com/beta';
5455
55/**56/**
56 * Applies a post-processing step to the generated messages.57 * Applies a post-processing step to the generated messages.
@@ -63,9 +64,13 @@ function postProcessPrompt(messages, type, names) {
63 switch (type) {64 switch (type) {
64 case 'merge':65 case 'merge':
65 case 'claude':66 case 'claude':
66 return mergeMessages(messages, names, false);67 return mergeMessages(messages, names, false, false);
68 case 'semi':
69 return mergeMessages(messages, names, true, false);
67 case 'strict':70 case 'strict':
68 return mergeMessages(messages, names, true);71 return mergeMessages(messages, names, true, true);
72 case 'deepseek':
73 return (x => x.length && (x[x.length - 1].role !== 'assistant' || (x[x.length - 1].prefix = true)) ? x : x)(mergeMessages(messages, names, true, false));
69 default:74 default:
70 return messages;75 return messages;
71 }76 }
@@ -668,6 +673,10 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o
668 api_url = API_NANOGPT;673 api_url = API_NANOGPT;
669 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);674 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.NANOGPT);
670 headers = {};675 headers = {};
676 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {
677 api_url = API_DEEPSEEK.replace('/beta', '');
678 api_key_openai = readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);
679 headers = {};
671 } else {680 } else {
672 console.log('This chat completion source is not supported yet.');681 console.log('This chat completion source is not supported yet.');
673 return response_getstatus_openai.status(400).send({ error: true });682 return response_getstatus_openai.status(400).send({ error: true });
@@ -939,6 +948,18 @@ router.post('/generate', jsonParser, function (request, response) {
939 apiKey = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY);948 apiKey = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY);
940 headers = {};949 headers = {};
941 bodyParams = {};950 bodyParams = {};
951 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) {
952 apiUrl = API_DEEPSEEK;
953 apiKey = readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK);
954 headers = {};
955 bodyParams = {};
956
957 if (request.body.logprobs > 0) {
958 bodyParams['top_logprobs'] = request.body.logprobs;
959 bodyParams['logprobs'] = true;
960 }
961
962 request.body.messages = postProcessPrompt(request.body.messages, 'deepseek', getPromptNames(request));
942 } else {963 } else {
943 console.log('This chat completion source is not supported yet.');964 console.log('This chat completion source is not supported yet.');
944 return response.status(400).send({ error: true });965 return response.status(400).send({ error: true });
src/endpoints/secrets.js+1 -0
@@ -51,6 +51,7 @@ export const SECRET_KEYS = {
51 NANOGPT: 'api_key_nanogpt',51 NANOGPT: 'api_key_nanogpt',
52 BFL: 'api_key_bfl',52 BFL: 'api_key_bfl',
53 GENERIC: 'api_key_generic',53 GENERIC: 'api_key_generic',
54 DEEPSEEK: 'api_key_deepseek',
54};55};
5556
56// These are the keys that are safe to expose, even if allowKeysExposure is false57// These are the keys that are safe to expose, even if allowKeysExposure is false
src/endpoints/tokenizers.js+24 -0
@@ -226,6 +226,7 @@ const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json');
226const commandTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/command-r.json', 'src/tokenizers/llama3.json');226const commandTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/command-r.json', 'src/tokenizers/llama3.json');
227const qwen2Tokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/qwen2.json', 'src/tokenizers/llama3.json');227const qwen2Tokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/qwen2.json', 'src/tokenizers/llama3.json');
228const nemoTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/nemo.json', 'src/tokenizers/llama3.json');228const nemoTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/nemo.json', 'src/tokenizers/llama3.json');
229const deepseekTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/deepseek.json', 'src/tokenizers/llama3.json');
229230
230export const sentencepieceTokenizers = [231export const sentencepieceTokenizers = [
231 'llama',232 'llama',
@@ -407,6 +408,10 @@ export function getTokenizerModel(requestModel) {
407 return 'yi';408 return 'yi';
408 }409 }
409410
411 if (requestModel.includes('deepseek')) {
412 return 'deepseek';
413 }
414
410 if (requestModel.includes('gemma') || requestModel.includes('gemini')) {415 if (requestModel.includes('gemma') || requestModel.includes('gemini')) {
411 return 'gemma';416 return 'gemma';
412 }417 }
@@ -655,6 +660,7 @@ router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llam
655router.post('/qwen2/encode', jsonParser, createWebTokenizerEncodingHandler(qwen2Tokenizer));660router.post('/qwen2/encode', jsonParser, createWebTokenizerEncodingHandler(qwen2Tokenizer));
656router.post('/command-r/encode', jsonParser, createWebTokenizerEncodingHandler(commandTokenizer));661router.post('/command-r/encode', jsonParser, createWebTokenizerEncodingHandler(commandTokenizer));
657router.post('/nemo/encode', jsonParser, createWebTokenizerEncodingHandler(nemoTokenizer));662router.post('/nemo/encode', jsonParser, createWebTokenizerEncodingHandler(nemoTokenizer));
663router.post('/deepseek/encode', jsonParser, createWebTokenizerEncodingHandler(deepseekTokenizer));
658router.post('/llama/decode', jsonParser, createSentencepieceDecodingHandler(spp_llama));664router.post('/llama/decode', jsonParser, createSentencepieceDecodingHandler(spp_llama));
659router.post('/nerdstash/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd));665router.post('/nerdstash/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd));
660router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd_v2));666router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd_v2));
@@ -668,6 +674,7 @@ router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llam
668router.post('/qwen2/decode', jsonParser, createWebTokenizerDecodingHandler(qwen2Tokenizer));674router.post('/qwen2/decode', jsonParser, createWebTokenizerDecodingHandler(qwen2Tokenizer));
669router.post('/command-r/decode', jsonParser, createWebTokenizerDecodingHandler(commandTokenizer));675router.post('/command-r/decode', jsonParser, createWebTokenizerDecodingHandler(commandTokenizer));
670router.post('/nemo/decode', jsonParser, createWebTokenizerDecodingHandler(nemoTokenizer));676router.post('/nemo/decode', jsonParser, createWebTokenizerDecodingHandler(nemoTokenizer));
677router.post('/deepseek/decode', jsonParser, createWebTokenizerDecodingHandler(deepseekTokenizer));
671678
672router.post('/openai/encode', jsonParser, async function (req, res) {679router.post('/openai/encode', jsonParser, async function (req, res) {
673 try {680 try {
@@ -723,6 +730,11 @@ router.post('/openai/encode', jsonParser, async function (req, res) {
723 return handler(req, res);730 return handler(req, res);
724 }731 }
725732
733 if (queryModel.includes('deepseek')) {
734 const handler = createWebTokenizerEncodingHandler(deepseekTokenizer);
735 return handler(req, res);
736 }
737
726 const model = getTokenizerModel(queryModel);738 const model = getTokenizerModel(queryModel);
727 const handler = createTiktokenEncodingHandler(model);739 const handler = createTiktokenEncodingHandler(model);
728 return handler(req, res);740 return handler(req, res);
@@ -786,6 +798,11 @@ router.post('/openai/decode', jsonParser, async function (req, res) {
786 return handler(req, res);798 return handler(req, res);
787 }799 }
788800
801 if (queryModel.includes('deepseek')) {
802 const handler = createWebTokenizerDecodingHandler(deepseekTokenizer);
803 return handler(req, res);
804 }
805
789 const model = getTokenizerModel(queryModel);806 const model = getTokenizerModel(queryModel);
790 const handler = createTiktokenDecodingHandler(model);807 const handler = createTiktokenDecodingHandler(model);
791 return handler(req, res);808 return handler(req, res);
@@ -863,6 +880,13 @@ router.post('/openai/count', jsonParser, async function (req, res) {
863 return res.send({ 'token_count': num_tokens });880 return res.send({ 'token_count': num_tokens });
864 }881 }
865882
883 if (model === 'deepseek') {
884 const instance = await deepseekTokenizer.get();
885 if (!instance) throw new Error('Failed to load the DeepSeek tokenizer');
886 num_tokens = countWebTokenizerTokens(instance, req.body);
887 return res.send({ 'token_count': num_tokens });
888 }
889
866 const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;890 const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;
867 const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3;891 const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3;
868 const tokensPadding = 3;892 const tokensPadding = 3;
src/prompt-converters.js+7 -6
@@ -639,9 +639,10 @@ export function convertMistralMessages(messages, names) {
639 * @param {any[]} messages Messages to merge639 * @param {any[]} messages Messages to merge
640 * @param {PromptNames} names Prompt names640 * @param {PromptNames} names Prompt names
641 * @param {boolean} strict Enable strict mode: only allow one system message at the start, force user first message641 * @param {boolean} strict Enable strict mode: only allow one system message at the start, force user first message
642 * @param {boolean} placeholders Add user placeholders to the messages in strict mode
642 * @returns {any[]} Merged messages643 * @returns {any[]} Merged messages
643 */644 */
644export function mergeMessages(messages, names, strict) {645export function mergeMessages(messages, names, strict, placeholders) {
645 let mergedMessages = [];646 let mergedMessages = [];
646647
647 /** @type {Map<string,object>} */648 /** @type {Map<string,object>} */
@@ -700,9 +701,9 @@ export function mergeMessages(messages, names, strict) {
700 }701 }
701 });702 });
702703
703 // Prevent erroring out if the messages array is empty.704 // Prevent erroring out if the mergedMessages array is empty.
704 if (messages.length === 0) {705 if (mergedMessages.length === 0) {
705 messages.unshift({706 mergedMessages.unshift({
706 role: 'user',707 role: 'user',
707 content: PROMPT_PLACEHOLDER,708 content: PROMPT_PLACEHOLDER,
708 });709 });
@@ -741,7 +742,7 @@ export function mergeMessages(messages, names, strict) {
741 mergedMessages[i].role = 'user';742 mergedMessages[i].role = 'user';
742 }743 }
743 }744 }
744 if (mergedMessages.length) {745 if (mergedMessages.length && placeholders) {
745 if (mergedMessages[0].role === 'system' && (mergedMessages.length === 1 || mergedMessages[1].role !== 'user')) {746 if (mergedMessages[0].role === 'system' && (mergedMessages.length === 1 || mergedMessages[1].role !== 'user')) {
746 mergedMessages.splice(1, 0, { role: 'user', content: PROMPT_PLACEHOLDER });747 mergedMessages.splice(1, 0, { role: 'user', content: PROMPT_PLACEHOLDER });
747 }748 }
@@ -749,7 +750,7 @@ export function mergeMessages(messages, names, strict) {
749 mergedMessages.unshift({ role: 'user', content: PROMPT_PLACEHOLDER });750 mergedMessages.unshift({ role: 'user', content: PROMPT_PLACEHOLDER });
750 }751 }
751 }752 }
752 return mergeMessages(mergedMessages, names, false);753 return mergeMessages(mergedMessages, names, false, placeholders);
753 }754 }
754755
755 return mergedMessages;756 return mergedMessages;