DeepSeek Closes #3233
| @@ -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 | Temperature | 687 | 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 Penalty | 700 | 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 Penalty | 713 | 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 P | 739 | 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"> |
| @@ -3762,6 +3780,7 @@ | |||
| 3762 | <option value="17">Mistral Nemo</option> | 3780 | <option value="17">Mistral Nemo</option> |
| 3763 | <option value="8">Yi</option> | 3781 | <option value="8">Yi</option> |
| 3764 | <option value="11">Claude 1/2</option> | 3782 | <option value="11">Claude 1/2</option> |
| 3783 | <option value="18">DeepSeek V3</option> | ||
| 3765 | <option value="6">API (WebUI / koboldcpp)</option> | 3784 | <option value="6">API (WebUI / koboldcpp)</option> |
| 3766 | </select> | 3785 | </select> |
| 3767 | </div> | 3786 | </div> |
| @@ -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'); |
| @@ -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 | }; |
| 187 | 188 | ||
| 188 | const character_names_behavior = { | 189 | const character_names_behavior = { |
| @@ -261,6 +262,7 @@ const default_settings = { | |||
| 261 | nanogpt_model: 'gpt-4o-mini', | 262 | nanogpt_model: 'gpt-4o-mini', |
| 262 | zerooneai_model: 'yi-large', | 263 | zerooneai_model: 'yi-large', |
| 263 | blockentropy_model: 'be-70b-base-llama3.1', | 264 | blockentropy_model: 'be-70b-base-llama3.1', |
| 265 | deepseek_model: 'deepseek-chat', | ||
| 264 | custom_model: '', | 266 | custom_model: '', |
| 265 | custom_url: '', | 267 | custom_url: '', |
| 266 | custom_include_body: '', | 268 | custom_include_body: '', |
| @@ -339,6 +341,7 @@ const oai_settings = { | |||
| 339 | nanogpt_model: 'gpt-4o-mini', | 341 | nanogpt_model: 'gpt-4o-mini', |
| 340 | zerooneai_model: 'yi-large', | 342 | zerooneai_model: 'yi-large', |
| 341 | blockentropy_model: 'be-70b-base-llama3.1', | 343 | blockentropy_model: 'be-70b-base-llama3.1', |
| 344 | deepseek_model: 'deepseek-chat', | ||
| 342 | custom_model: '', | 345 | custom_model: '', |
| 343 | custom_url: '', | 346 | custom_url: '', |
| 344 | custom_include_body: '', | 347 | custom_include_body: '', |
| @@ -1523,6 +1526,8 @@ function getChatCompletionModel() { | |||
| 1523 | return oai_settings.blockentropy_model; | 1526 | return oai_settings.blockentropy_model; |
| 1524 | case chat_completion_sources.NANOGPT: | 1527 | case chat_completion_sources.NANOGPT: |
| 1525 | return oai_settings.nanogpt_model; | 1528 | return oai_settings.nanogpt_model; |
| 1529 | case chat_completion_sources.DEEPSEEK: | ||
| 1530 | return oai_settings.deepseek_model; | ||
| 1526 | default: | 1531 | default: |
| 1527 | throw new Error(`Unknown chat completion source: ${oai_settings.chat_completion_source}`); | 1532 | throw new Error(`Unknown chat completion source: ${oai_settings.chat_completion_source}`); |
| 1528 | } | 1533 | } |
| @@ -1698,6 +1703,24 @@ function saveModelList(data) { | |||
| 1698 | 1703 | ||
| 1699 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model).trigger('change'); | 1704 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model).trigger('change'); |
| 1700 | } | 1705 | } |
| 1706 | |||
| 1707 | if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) { | ||
| 1708 | $('#model_deepseek_select').empty(); | ||
| 1709 | model_list.forEach((model) => { | ||
| 1710 | $('#model_deepseek_select').append( | ||
| 1711 | $('<option>', { | ||
| 1712 | value: model.id, | ||
| 1713 | text: model.id, | ||
| 1714 | })); | ||
| 1715 | }); | ||
| 1716 | |||
| 1717 | const selectedModel = model_list.find(model => model.id === oai_settings.deepseek_model); | ||
| 1718 | if (model_list.length > 0 && (!selectedModel || !oai_settings.deepseek_model)) { | ||
| 1719 | oai_settings.deepseek_model = model_list[0].id; | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | $('#model_deepseek_select').val(oai_settings.deepseek_model).trigger('change'); | ||
| 1723 | } | ||
| 1701 | } | 1724 | } |
| 1702 | 1725 | ||
| 1703 | function appendOpenRouterOptions(model_list, groupModels = false, sort = false) { | 1726 | function appendOpenRouterOptions(model_list, groupModels = false, sort = false) { |
| @@ -1838,6 +1861,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 1838 | const isGroq = oai_settings.chat_completion_source == chat_completion_sources.GROQ; | 1861 | const isGroq = oai_settings.chat_completion_source == chat_completion_sources.GROQ; |
| 1839 | const is01AI = oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI; | 1862 | const is01AI = oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI; |
| 1840 | const isNano = oai_settings.chat_completion_source == chat_completion_sources.NANOGPT; | 1863 | const isNano = oai_settings.chat_completion_source == chat_completion_sources.NANOGPT; |
| 1864 | const isDeepSeek = oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK; | ||
| 1841 | const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model); | 1865 | const isTextCompletion = isOAI && textCompletionModels.includes(oai_settings.openai_model); |
| 1842 | const isQuiet = type === 'quiet'; | 1866 | const isQuiet = type === 'quiet'; |
| 1843 | const isImpersonate = type === 'impersonate'; | 1867 | const isImpersonate = type === 'impersonate'; |
| @@ -1902,7 +1926,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 1902 | } | 1926 | } |
| 1903 | 1927 | ||
| 1904 | // Add logprobs request (currently OpenAI only, max 5 on their side) | 1928 | // Add logprobs request (currently OpenAI only, max 5 on their side) |
| 1905 | if (useLogprobs && (isOAI || isCustom)) { | 1929 | if (useLogprobs && (isOAI || isCustom || isDeepSeek)) { |
| 1906 | generate_data['logprobs'] = 5; | 1930 | generate_data['logprobs'] = 5; |
| 1907 | } | 1931 | } |
| 1908 | 1932 | ||
| @@ -2000,6 +2024,11 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2000 | delete generate_data.stop; | 2024 | delete generate_data.stop; |
| 2001 | } | 2025 | } |
| 2002 | 2026 | ||
| 2027 | // https://api-docs.deepseek.com/api/create-chat-completion | ||
| 2028 | if (isDeepSeek) { | ||
| 2029 | generate_data.top_p = generate_data.top_p || Number.EPSILON; | ||
| 2030 | } | ||
| 2031 | |||
| 2003 | if ((isOAI || isOpenRouter || isMistral || isCustom || isCohere || isNano) && oai_settings.seed >= 0) { | 2032 | if ((isOAI || isOpenRouter || isMistral || isCustom || isCohere || isNano) && oai_settings.seed >= 0) { |
| 2004 | generate_data['seed'] = oai_settings.seed; | 2033 | generate_data['seed'] = oai_settings.seed; |
| 2005 | } | 2034 | } |
| @@ -2122,6 +2151,7 @@ function parseChatCompletionLogprobs(data) { | |||
| 2122 | 2151 | ||
| 2123 | switch (oai_settings.chat_completion_source) { | 2152 | switch (oai_settings.chat_completion_source) { |
| 2124 | case chat_completion_sources.OPENAI: | 2153 | case chat_completion_sources.OPENAI: |
| 2154 | case chat_completion_sources.DEEPSEEK: | ||
| 2125 | case chat_completion_sources.CUSTOM: | 2155 | case chat_completion_sources.CUSTOM: |
| 2126 | if (!data.choices?.length) { | 2156 | if (!data.choices?.length) { |
| 2127 | return null; | 2157 | return null; |
| @@ -3041,6 +3071,7 @@ function loadOpenAISettings(data, settings) { | |||
| 3041 | oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model; | 3071 | oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model; |
| 3042 | oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model; | 3072 | oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model; |
| 3043 | oai_settings.nanogpt_model = settings.nanogpt_model ?? default_settings.nanogpt_model; | 3073 | oai_settings.nanogpt_model = settings.nanogpt_model ?? default_settings.nanogpt_model; |
| 3074 | oai_settings.deepseek_model = settings.deepseek_model ?? default_settings.deepseek_model; | ||
| 3044 | oai_settings.blockentropy_model = settings.blockentropy_model ?? default_settings.blockentropy_model; | 3075 | oai_settings.blockentropy_model = settings.blockentropy_model ?? default_settings.blockentropy_model; |
| 3045 | oai_settings.zerooneai_model = settings.zerooneai_model ?? default_settings.zerooneai_model; | 3076 | oai_settings.zerooneai_model = settings.zerooneai_model ?? default_settings.zerooneai_model; |
| 3046 | oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model; | 3077 | oai_settings.custom_model = settings.custom_model ?? default_settings.custom_model; |
| @@ -3122,6 +3153,8 @@ function loadOpenAISettings(data, settings) { | |||
| 3122 | $(`#model_groq_select option[value="${oai_settings.groq_model}"`).attr('selected', true); | 3153 | $(`#model_groq_select option[value="${oai_settings.groq_model}"`).attr('selected', true); |
| 3123 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model); | 3154 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model); |
| 3124 | $(`#model_nanogpt_select option[value="${oai_settings.nanogpt_model}"`).attr('selected', true); | 3155 | $(`#model_nanogpt_select option[value="${oai_settings.nanogpt_model}"`).attr('selected', true); |
| 3156 | $('#model_deepseek_select').val(oai_settings.deepseek_model); | ||
| 3157 | $(`#model_deepseek_select option[value="${oai_settings.deepseek_model}"`).prop('selected', true); | ||
| 3125 | $('#model_01ai_select').val(oai_settings.zerooneai_model); | 3158 | $('#model_01ai_select').val(oai_settings.zerooneai_model); |
| 3126 | $('#model_blockentropy_select').val(oai_settings.blockentropy_model); | 3159 | $('#model_blockentropy_select').val(oai_settings.blockentropy_model); |
| 3127 | $('#custom_model_id').val(oai_settings.custom_model); | 3160 | $('#custom_model_id').val(oai_settings.custom_model); |
| @@ -3861,6 +3894,7 @@ function onSettingsPresetChange() { | |||
| 3861 | perplexity_model: ['#model_perplexity_select', 'perplexity_model', false], | 3894 | perplexity_model: ['#model_perplexity_select', 'perplexity_model', false], |
| 3862 | groq_model: ['#model_groq_select', 'groq_model', false], | 3895 | groq_model: ['#model_groq_select', 'groq_model', false], |
| 3863 | nanogpt_model: ['#model_nanogpt_select', 'nanogpt_model', false], | 3896 | nanogpt_model: ['#model_nanogpt_select', 'nanogpt_model', false], |
| 3897 | deepseek_model: ['#model_deepseek_select', 'deepseek_model', false], | ||
| 3864 | zerooneai_model: ['#model_01ai_select', 'zerooneai_model', false], | 3898 | zerooneai_model: ['#model_01ai_select', 'zerooneai_model', false], |
| 3865 | blockentropy_model: ['#model_blockentropy_select', 'blockentropy_model', false], | 3899 | blockentropy_model: ['#model_blockentropy_select', 'blockentropy_model', false], |
| 3866 | custom_model: ['#custom_model_id', 'custom_model', false], | 3900 | custom_model: ['#custom_model_id', 'custom_model', false], |
| @@ -4120,6 +4154,16 @@ async function onModelChange() { | |||
| 4120 | oai_settings.nanogpt_model = value; | 4154 | oai_settings.nanogpt_model = value; |
| 4121 | } | 4155 | } |
| 4122 | 4156 | ||
| 4157 | if ($(this).is('#model_deepseek_select')) { | ||
| 4158 | if (!value) { | ||
| 4159 | console.debug('Null DeepSeek model selected. Ignoring.'); | ||
| 4160 | return; | ||
| 4161 | } | ||
| 4162 | |||
| 4163 | console.log('DeepSeek model changed to', value); | ||
| 4164 | oai_settings.deepseek_model = value; | ||
| 4165 | } | ||
| 4166 | |||
| 4123 | if (value && $(this).is('#model_01ai_select')) { | 4167 | if (value && $(this).is('#model_01ai_select')) { |
| 4124 | console.log('01.AI model changed to', value); | 4168 | console.log('01.AI model changed to', value); |
| 4125 | oai_settings.zerooneai_model = value; | 4169 | oai_settings.zerooneai_model = value; |
| @@ -4436,6 +4480,22 @@ async function onModelChange() { | |||
| 4436 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | 4480 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4437 | } | 4481 | } |
| 4438 | 4482 | ||
| 4483 | if (oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK) { | ||
| 4484 | if (oai_settings.max_context_unlocked) { | ||
| 4485 | $('#openai_max_context').attr('max', unlocked_max); | ||
| 4486 | } else if (oai_settings.deepseek_model == 'deepseek-chat') { | ||
| 4487 | $('#openai_max_context').attr('max', max_64k); | ||
| 4488 | } else if (oai_settings.deepseek_model == 'deepseek-coder') { | ||
| 4489 | $('#openai_max_context').attr('max', max_16k); | ||
| 4490 | } else { | ||
| 4491 | $('#openai_max_context').attr('max', max_64k); | ||
| 4492 | } | ||
| 4493 | |||
| 4494 | oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); | ||
| 4495 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); | ||
| 4496 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | ||
| 4497 | } | ||
| 4498 | |||
| 4439 | if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { | 4499 | 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); | 4500 | 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'); | 4501 | $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input'); |
| @@ -4653,6 +4713,19 @@ async function onConnectButtonClick(e) { | |||
| 4653 | } | 4713 | } |
| 4654 | } | 4714 | } |
| 4655 | 4715 | ||
| 4716 | if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) { | ||
| 4717 | const api_key_deepseek = String($('#api_key_deepseek').val()).trim(); | ||
| 4718 | |||
| 4719 | if (api_key_deepseek.length) { | ||
| 4720 | await writeSecret(SECRET_KEYS.DEEPSEEK, api_key_deepseek); | ||
| 4721 | } | ||
| 4722 | |||
| 4723 | if (!secret_state[SECRET_KEYS.DEEPSEEK]) { | ||
| 4724 | console.log('No secret key saved for DeepSeek'); | ||
| 4725 | return; | ||
| 4726 | } | ||
| 4727 | } | ||
| 4728 | |||
| 4656 | if (oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) { | 4729 | if (oai_settings.chat_completion_source == chat_completion_sources.ZEROONEAI) { |
| 4657 | const api_key_01ai = String($('#api_key_01ai').val()).trim(); | 4730 | const api_key_01ai = String($('#api_key_01ai').val()).trim(); |
| 4658 | 4731 | ||
| @@ -4734,6 +4807,9 @@ function toggleChatCompletionForms() { | |||
| 4734 | else if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { | 4807 | else if (oai_settings.chat_completion_source == chat_completion_sources.BLOCKENTROPY) { |
| 4735 | $('#model_blockentropy_select').trigger('change'); | 4808 | $('#model_blockentropy_select').trigger('change'); |
| 4736 | } | 4809 | } |
| 4810 | else if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) { | ||
| 4811 | $('#model_deepseek_select').trigger('change'); | ||
| 4812 | } | ||
| 4737 | $('[data-source]').each(function () { | 4813 | $('[data-source]').each(function () { |
| 4738 | const validSources = $(this).data('source').split(','); | 4814 | const validSources = $(this).data('source').split(','); |
| 4739 | $(this).toggle(validSources.includes(oai_settings.chat_completion_source)); | 4815 | $(this).toggle(validSources.includes(oai_settings.chat_completion_source)); |
| @@ -5447,6 +5523,7 @@ export function initOpenAI() { | |||
| 5447 | $('#model_perplexity_select').on('change', onModelChange); | 5523 | $('#model_perplexity_select').on('change', onModelChange); |
| 5448 | $('#model_groq_select').on('change', onModelChange); | 5524 | $('#model_groq_select').on('change', onModelChange); |
| 5449 | $('#model_nanogpt_select').on('change', onModelChange); | 5525 | $('#model_nanogpt_select').on('change', onModelChange); |
| 5526 | $('#model_deepseek_select').on('change', onModelChange); | ||
| 5450 | $('#model_01ai_select').on('change', onModelChange); | 5527 | $('#model_01ai_select').on('change', onModelChange); |
| 5451 | $('#model_blockentropy_select').on('change', onModelChange); | 5528 | $('#model_blockentropy_select').on('change', onModelChange); |
| 5452 | $('#model_custom_select').on('change', onModelChange); | 5529 | $('#model_custom_select').on('change', onModelChange); |
| @@ -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 | }; |
| 43 | 44 | ||
| 44 | const INPUT_MAP = { | 45 | const 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 | }; |
| 77 | 79 | ||
| 78 | async function clearSecret() { | 80 | async function clearSecret() { |
| @@ -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 | ]; |
| @@ -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, lol | 51 | // 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'; | ||
| 554 | 562 | ||
| 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 | } |
| 559 | 567 | ||
| 568 | if (oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) { | ||
| 569 | return deepseekTokenizer; | ||
| 570 | } | ||
| 571 | |||
| 560 | // Select correct tokenizer for WindowAI proxies | 572 | // 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 | } |
| 623 | 638 | ||
| 624 | if (oai_settings.chat_completion_source == chat_completion_sources.COHERE) { | 639 | if (oai_settings.chat_completion_source == chat_completion_sources.COHERE) { |
| @@ -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 | }; |
| 179 | 180 | ||
| 180 | /** | 181 | /** |
| @@ -51,6 +51,7 @@ const API_01AI = 'https://api.01.ai/v1'; | |||
| 51 | const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1'; | 51 | const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1'; |
| 52 | const API_AI21 = 'https://api.ai21.com/studio/v1'; | 52 | const API_AI21 = 'https://api.ai21.com/studio/v1'; |
| 53 | const API_NANOGPT = 'https://nano-gpt.com/api/v1'; | 53 | const API_NANOGPT = 'https://nano-gpt.com/api/v1'; |
| 54 | const API_DEEPSEEK = 'https://api.deepseek.com/beta'; | ||
| 54 | 55 | ||
| 55 | /** | 56 | /** |
| 56 | * Applies a post-processing step to the generated messages. | 57 | * Applies a post-processing step to the generated messages. |
| @@ -66,6 +67,8 @@ function postProcessPrompt(messages, type, names) { | |||
| 66 | return mergeMessages(messages, names, false); | 67 | return mergeMessages(messages, names, false); |
| 67 | case 'strict': | 68 | case 'strict': |
| 68 | return mergeMessages(messages, names, true); | 69 | return mergeMessages(messages, names, true); |
| 70 | case 'deepseek': | ||
| 71 | return (x => x[x.length - 1].role !== 'assistant' || (x[x.length - 1].prefix = true) ? x : x)([...mergeMessages(messages, names, true)]); | ||
| 69 | default: | 72 | default: |
| 70 | return messages; | 73 | return messages; |
| 71 | } | 74 | } |
| @@ -668,6 +671,10 @@ router.post('/status', jsonParser, async function (request, response_getstatus_o | |||
| 668 | api_url = API_NANOGPT; | 671 | api_url = API_NANOGPT; |
| 669 | api_key_openai = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); | 672 | api_key_openai = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); |
| 670 | headers = {}; | 673 | headers = {}; |
| 674 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) { | ||
| 675 | api_url = API_DEEPSEEK; | ||
| 676 | api_key_openai = readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK); | ||
| 677 | headers = {}; | ||
| 671 | } else { | 678 | } else { |
| 672 | console.log('This chat completion source is not supported yet.'); | 679 | console.log('This chat completion source is not supported yet.'); |
| 673 | return response_getstatus_openai.status(400).send({ error: true }); | 680 | return response_getstatus_openai.status(400).send({ error: true }); |
| @@ -939,6 +946,18 @@ router.post('/generate', jsonParser, function (request, response) { | |||
| 939 | apiKey = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); | 946 | apiKey = readSecret(request.user.directories, SECRET_KEYS.BLOCKENTROPY); |
| 940 | headers = {}; | 947 | headers = {}; |
| 941 | bodyParams = {}; | 948 | bodyParams = {}; |
| 949 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) { | ||
| 950 | apiUrl = API_DEEPSEEK; | ||
| 951 | apiKey = readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK); | ||
| 952 | headers = {}; | ||
| 953 | bodyParams = {}; | ||
| 954 | |||
| 955 | if (request.body.logprobs > 0) { | ||
| 956 | bodyParams['top_logprobs'] = request.body.logprobs; | ||
| 957 | bodyParams['logprobs'] = true; | ||
| 958 | } | ||
| 959 | |||
| 960 | request.body.messages = postProcessPrompt(request.body.messages, 'deepseek', getPromptNames(request)); | ||
| 942 | } else { | 961 | } else { |
| 943 | console.log('This chat completion source is not supported yet.'); | 962 | console.log('This chat completion source is not supported yet.'); |
| 944 | return response.status(400).send({ error: true }); | 963 | return response.status(400).send({ error: true }); |
| @@ -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 | }; |
| 55 | 56 | ||
| 56 | // These are the keys that are safe to expose, even if allowKeysExposure is false | 57 | // These are the keys that are safe to expose, even if allowKeysExposure is false |
| @@ -226,6 +226,7 @@ const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json'); | |||
| 226 | const commandTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/command-r.json', 'src/tokenizers/llama3.json'); | 226 | const commandTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/command-r.json', 'src/tokenizers/llama3.json'); |
| 227 | const qwen2Tokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/qwen2.json', 'src/tokenizers/llama3.json'); | 227 | const qwen2Tokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/qwen2.json', 'src/tokenizers/llama3.json'); |
| 228 | const nemoTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/nemo.json', 'src/tokenizers/llama3.json'); | 228 | const nemoTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/nemo.json', 'src/tokenizers/llama3.json'); |
| 229 | const deepseekTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/deepseek.json', 'src/tokenizers/llama3.json'); | ||
| 229 | 230 | ||
| 230 | export const sentencepieceTokenizers = [ | 231 | export const sentencepieceTokenizers = [ |
| 231 | 'llama', | 232 | 'llama', |
| @@ -407,6 +408,10 @@ export function getTokenizerModel(requestModel) { | |||
| 407 | return 'yi'; | 408 | return 'yi'; |
| 408 | } | 409 | } |
| 409 | 410 | ||
| 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 | |||
| 655 | router.post('/qwen2/encode', jsonParser, createWebTokenizerEncodingHandler(qwen2Tokenizer)); | 660 | router.post('/qwen2/encode', jsonParser, createWebTokenizerEncodingHandler(qwen2Tokenizer)); |
| 656 | router.post('/command-r/encode', jsonParser, createWebTokenizerEncodingHandler(commandTokenizer)); | 661 | router.post('/command-r/encode', jsonParser, createWebTokenizerEncodingHandler(commandTokenizer)); |
| 657 | router.post('/nemo/encode', jsonParser, createWebTokenizerEncodingHandler(nemoTokenizer)); | 662 | router.post('/nemo/encode', jsonParser, createWebTokenizerEncodingHandler(nemoTokenizer)); |
| 663 | router.post('/deepseek/encode', jsonParser, createWebTokenizerEncodingHandler(deepseekTokenizer)); | ||
| 658 | router.post('/llama/decode', jsonParser, createSentencepieceDecodingHandler(spp_llama)); | 664 | router.post('/llama/decode', jsonParser, createSentencepieceDecodingHandler(spp_llama)); |
| 659 | router.post('/nerdstash/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd)); | 665 | router.post('/nerdstash/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd)); |
| 660 | router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd_v2)); | 666 | router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandler(spp_nerd_v2)); |
| @@ -668,6 +674,7 @@ router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llam | |||
| 668 | router.post('/qwen2/decode', jsonParser, createWebTokenizerDecodingHandler(qwen2Tokenizer)); | 674 | router.post('/qwen2/decode', jsonParser, createWebTokenizerDecodingHandler(qwen2Tokenizer)); |
| 669 | router.post('/command-r/decode', jsonParser, createWebTokenizerDecodingHandler(commandTokenizer)); | 675 | router.post('/command-r/decode', jsonParser, createWebTokenizerDecodingHandler(commandTokenizer)); |
| 670 | router.post('/nemo/decode', jsonParser, createWebTokenizerDecodingHandler(nemoTokenizer)); | 676 | router.post('/nemo/decode', jsonParser, createWebTokenizerDecodingHandler(nemoTokenizer)); |
| 677 | router.post('/deepseek/decode', jsonParser, createWebTokenizerDecodingHandler(deepseekTokenizer)); | ||
| 671 | 678 | ||
| 672 | router.post('/openai/encode', jsonParser, async function (req, res) { | 679 | router.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 | } |
| 725 | 732 | ||
| 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 | } |
| 788 | 800 | ||
| 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 | } |
| 865 | 882 | ||
| 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; |