feat: add siliconflow chat provider (#4764) * feat: add siliconflow chat provider * fix: remove siliconflow seed handling * fix: enable SiliconFlow image inlining from shared vision list * fix: handle SiliconFlow model context limits and sizing * fix: drop SiliconFlow reasoning effort handling since controls are hidden * fix: parse SiliconFlow reasoning in streaming and non-streaming * fix: add missing comma in supported models list * Remove seed from HTML template * Combine streamed reasoning parsing blocks * Update logo image * Unhide image inlining controls --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -0,0 +1,4 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | <svg width="142.22" height="68.010002" viewBox="0 0 142.22 68.010002" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> | ||
| 3 | <path d="M 136.05,0 H 74.21 c -3.42,0 -6.18,2.77 -6.18,6.18 v 18.55 c 0,3.42 -2.77,6.18 -6.18,6.18 H 6.18 C 2.76,30.91 0,33.68 0,37.09 v 24.74 c 0,3.42 2.77,6.18 6.18,6.18 h 61.84 c 3.42,0 6.18,-2.77 6.18,-6.18 V 43.28 c 0,-3.42 2.77,-6.18 6.18,-6.18 h 55.66 c 3.42,0 6.18,-2.77 6.18,-6.18 V 6.18 C 142.22,2.76 139.45,0 136.04,0 Z" /> | ||
| 4 | </svg> | ||
| @@ -693,7 +693,7 @@ | |||
| 693 | </span> | 693 | </span> |
| 694 | </div> | 694 | </div> |
| 695 | </div> | 695 | </div> |
| 696 | <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai,zai"> | 696 | <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,siliconflow,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai,zai"> |
| 697 | <div class="range-block-title" data-i18n="Temperature"> | 697 | <div class="range-block-title" data-i18n="Temperature"> |
| 698 | Temperature | 698 | Temperature |
| 699 | </div> | 699 | </div> |
| @@ -706,7 +706,7 @@ | |||
| 706 | </div> | 706 | </div> |
| 707 | </div> | 707 | </div> |
| 708 | </div> | 708 | </div> |
| 709 | <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,mistralai,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai"> | 709 | <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,siliconflow,mistralai,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai"> |
| 710 | <div class="range-block-title" data-i18n="Frequency Penalty"> | 710 | <div class="range-block-title" data-i18n="Frequency Penalty"> |
| 711 | Frequency Penalty | 711 | Frequency Penalty |
| 712 | </div> | 712 | </div> |
| @@ -719,7 +719,7 @@ | |||
| 719 | </div> | 719 | </div> |
| 720 | </div> | 720 | </div> |
| 721 | </div> | 721 | </div> |
| 722 | <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,mistralai,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai"> | 722 | <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,siliconflow,mistralai,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai"> |
| 723 | <div class="range-block-title" data-i18n="Presence Penalty"> | 723 | <div class="range-block-title" data-i18n="Presence Penalty"> |
| 724 | Presence Penalty | 724 | Presence Penalty |
| 725 | </div> | 725 | </div> |
| @@ -745,7 +745,7 @@ | |||
| 745 | </div> | 745 | </div> |
| 746 | </div> | 746 | </div> |
| 747 | </div> | 747 | </div> |
| 748 | <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai,zai"> | 748 | <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,siliconflow,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai,zai"> |
| 749 | <div class="range-block-title" data-i18n="Top P"> | 749 | <div class="range-block-title" data-i18n="Top P"> |
| 750 | Top P | 750 | Top P |
| 751 | </div> | 751 | </div> |
| @@ -1965,7 +1965,7 @@ | |||
| 1965 | </b> | 1965 | </b> |
| 1966 | </div> | 1966 | </div> |
| 1967 | </div> | 1967 | </div> |
| 1968 | <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,aimlapi,openrouter,groq,deepseek,makersuite,vertexai,ai21,xai,pollinations,moonshot,fireworks,cometapi,electronhub,azure_openai,zai"> | 1968 | <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,aimlapi,openrouter,groq,siliconflow,deepseek,makersuite,vertexai,ai21,xai,pollinations,moonshot,fireworks,cometapi,electronhub,azure_openai,zai"> |
| 1969 | <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand"> | 1969 | <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand"> |
| 1970 | <input id="openai_function_calling" type="checkbox" /> | 1970 | <input id="openai_function_calling" type="checkbox" /> |
| 1971 | <span data-i18n="Enable function calling">Enable function calling</span> | 1971 | <span data-i18n="Enable function calling">Enable function calling</span> |
| @@ -1980,7 +1980,7 @@ | |||
| 1980 | <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong> | 1980 | <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong> |
| 1981 | </div> | 1981 | </div> |
| 1982 | </div> | 1982 | </div> |
| 1983 | <div class="range-block" data-source="openai,aimlapi,openrouter,mistralai,makersuite,vertexai,claude,custom,xai,pollinations,moonshot,cohere,cometapi,nanogpt,electronhub,azure_openai,zai"> | 1983 | <div class="range-block" data-source="openai,aimlapi,openrouter,mistralai,makersuite,vertexai,claude,custom,xai,pollinations,moonshot,cohere,cometapi,nanogpt,electronhub,azure_openai,zai,siliconflow"> |
| 1984 | <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand"> | 1984 | <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand"> |
| 1985 | <input id="openai_image_inlining" type="checkbox" /> | 1985 | <input id="openai_image_inlining" type="checkbox" /> |
| 1986 | <span data-i18n="Send inline images">Send inline images</span> | 1986 | <span data-i18n="Send inline images">Send inline images</span> |
| @@ -1992,7 +1992,7 @@ | |||
| 1992 | <div id="image_inlining_hint" class="flexBasis100p toggle-description justifyLeft"> | 1992 | <div id="image_inlining_hint" class="flexBasis100p toggle-description justifyLeft"> |
| 1993 | <span data-i18n="image_inlining_hint_1">Sends images in prompts if the model supports it.</span> | 1993 | <span data-i18n="image_inlining_hint_1">Sends images in prompts if the model supports it.</span> |
| 1994 | </div> | 1994 | </div> |
| 1995 | <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,xai,pollinations,cohere,cometapi,nanogpt,moonshot,aimlapi,openrouter,mistralai,electronhub,azure_openai,zai"> | 1995 | <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,xai,pollinations,cohere,cometapi,nanogpt,moonshot,aimlapi,openrouter,mistralai,electronhub,azure_openai,zai,siliconflow"> |
| 1996 | <div class="flex-container oneline-dropdown"> | 1996 | <div class="flex-container oneline-dropdown"> |
| 1997 | <label for="openai_inline_image_quality" data-i18n="Inline Image Quality"> | 1997 | <label for="openai_inline_image_quality" data-i18n="Inline Image Quality"> |
| 1998 | Inline Image Quality | 1998 | Inline Image Quality |
| @@ -2806,6 +2806,7 @@ | |||
| 2806 | <option value="openrouter">OpenRouter</option> | 2806 | <option value="openrouter">OpenRouter</option> |
| 2807 | <option value="perplexity">Perplexity</option> | 2807 | <option value="perplexity">Perplexity</option> |
| 2808 | <option value="pollinations">Pollinations</option> | 2808 | <option value="pollinations">Pollinations</option> |
| 2809 | <option value="siliconflow">SiliconFlow</option> | ||
| 2809 | <option value="xai">xAI (Grok)</option> | 2810 | <option value="xai">xAI (Grok)</option> |
| 2810 | <option value="zai">Z.AI (GLM)</option> | 2811 | <option value="zai">Z.AI (GLM)</option> |
| 2811 | </optgroup> | 2812 | </optgroup> |
| @@ -3397,6 +3398,20 @@ | |||
| 3397 | <option value="mistral-saba-24b">mistral-saba-24b</option> | 3398 | <option value="mistral-saba-24b">mistral-saba-24b</option> |
| 3398 | </select> | 3399 | </select> |
| 3399 | </div> | 3400 | </div> |
| 3401 | <div id="siliconflow_form" data-source="siliconflow"> | ||
| 3402 | <h4>SiliconFlow API Key</h4> | ||
| 3403 | <div class="flex-container"> | ||
| 3404 | <input id="api_key_siliconflow" name="api_key_siliconflow" class="text_pole flex1" value="" type="text" autocomplete="off"> | ||
| 3405 | <div title="Manage API keys" data-i18n="[title]Manage API keys" class="menu_button fa-solid fa-key fa-fw manage-api-keys" data-key="api_key_siliconflow"></div> | ||
| 3406 | </div> | ||
| 3407 | <div data-for="api_key_siliconflow" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you click 'Connect'."> | ||
| 3408 | For privacy reasons, your API key will be hidden after you click 'Connect'. | ||
| 3409 | </div> | ||
| 3410 | <h4>SiliconFlow Model</h4> | ||
| 3411 | <select id="model_siliconflow_select"> | ||
| 3412 | <option value="" data-i18n="-- Connect to the API --">-- Connect to the API --</option> | ||
| 3413 | </select> | ||
| 3414 | </div> | ||
| 3400 | <div id="electronhub_form" data-source="electronhub"> | 3415 | <div id="electronhub_form" data-source="electronhub"> |
| 3401 | <h4 data-i18n="Electron Hub API Key">Electron Hub API Key</h4> | 3416 | <h4 data-i18n="Electron Hub API Key">Electron Hub API Key</h4> |
| 3402 | <div> | 3417 | <div> |
| @@ -403,6 +403,7 @@ function RA_autoconnect(PrevApi) { | |||
| 403 | || (secret_state[SECRET_KEYS.COHERE] && oai_settings.chat_completion_source == chat_completion_sources.COHERE) | 403 | || (secret_state[SECRET_KEYS.COHERE] && oai_settings.chat_completion_source == chat_completion_sources.COHERE) |
| 404 | || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) | 404 | || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) |
| 405 | || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ) | 405 | || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ) |
| 406 | || (secret_state[SECRET_KEYS.SILICONFLOW] && oai_settings.chat_completion_source == chat_completion_sources.SILICONFLOW) | ||
| 406 | || (secret_state[SECRET_KEYS.ELECTRONHUB] && oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) | 407 | || (secret_state[SECRET_KEYS.ELECTRONHUB] && oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) |
| 407 | || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT) | 408 | || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT) |
| 408 | || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) | 409 | || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK) |
| @@ -194,6 +194,7 @@ export const chat_completion_sources = { | |||
| 194 | COMETAPI: 'cometapi', | 194 | COMETAPI: 'cometapi', |
| 195 | AZURE_OPENAI: 'azure_openai', | 195 | AZURE_OPENAI: 'azure_openai', |
| 196 | ZAI: 'zai', | 196 | ZAI: 'zai', |
| 197 | SILICONFLOW: 'siliconflow', | ||
| 197 | }; | 198 | }; |
| 198 | 199 | ||
| 199 | const character_names_behavior = { | 200 | const character_names_behavior = { |
| @@ -280,6 +281,7 @@ export const settingsToUpdate = { | |||
| 280 | cohere_model: ['#model_cohere_select', 'cohere_model', false, true], | 281 | cohere_model: ['#model_cohere_select', 'cohere_model', false, true], |
| 281 | perplexity_model: ['#model_perplexity_select', 'perplexity_model', false, true], | 282 | perplexity_model: ['#model_perplexity_select', 'perplexity_model', false, true], |
| 282 | groq_model: ['#model_groq_select', 'groq_model', false, true], | 283 | groq_model: ['#model_groq_select', 'groq_model', false, true], |
| 284 | siliconflow_model: ['#model_siliconflow_select', 'siliconflow_model', false, true], | ||
| 283 | electronhub_model: ['#model_electronhub_select', 'electronhub_model', false, true], | 285 | electronhub_model: ['#model_electronhub_select', 'electronhub_model', false, true], |
| 284 | electronhub_sort_models: ['#electronhub_sort_models', 'electronhub_sort_models', false, true], | 286 | electronhub_sort_models: ['#electronhub_sort_models', 'electronhub_sort_models', false, true], |
| 285 | electronhub_group_models: ['#electronhub_group_models', 'electronhub_group_models', false, true], | 287 | electronhub_group_models: ['#electronhub_group_models', 'electronhub_group_models', false, true], |
| @@ -387,6 +389,7 @@ const default_settings = { | |||
| 387 | cohere_model: 'command-r-plus', | 389 | cohere_model: 'command-r-plus', |
| 388 | perplexity_model: 'sonar-pro', | 390 | perplexity_model: 'sonar-pro', |
| 389 | groq_model: 'llama-3.3-70b-versatile', | 391 | groq_model: 'llama-3.3-70b-versatile', |
| 392 | siliconflow_model: 'deepseek-ai/DeepSeek-V3', | ||
| 390 | electronhub_model: 'gpt-4o-mini', | 393 | electronhub_model: 'gpt-4o-mini', |
| 391 | electronhub_sort_models: 'alphabetically', | 394 | electronhub_sort_models: 'alphabetically', |
| 392 | electronhub_group_models: false, | 395 | electronhub_group_models: false, |
| @@ -1587,6 +1590,8 @@ export function getChatCompletionModel(source = null) { | |||
| 1587 | return oai_settings.perplexity_model; | 1590 | return oai_settings.perplexity_model; |
| 1588 | case chat_completion_sources.GROQ: | 1591 | case chat_completion_sources.GROQ: |
| 1589 | return oai_settings.groq_model; | 1592 | return oai_settings.groq_model; |
| 1593 | case chat_completion_sources.SILICONFLOW: | ||
| 1594 | return oai_settings.siliconflow_model; | ||
| 1590 | case chat_completion_sources.ELECTRONHUB: | 1595 | case chat_completion_sources.ELECTRONHUB: |
| 1591 | return oai_settings.electronhub_model; | 1596 | return oai_settings.electronhub_model; |
| 1592 | case chat_completion_sources.NANOGPT: | 1597 | case chat_completion_sources.NANOGPT: |
| @@ -1920,6 +1925,24 @@ function saveModelList(data) { | |||
| 1920 | $('#model_groq_select').val(oai_settings.groq_model).trigger('change'); | 1925 | $('#model_groq_select').val(oai_settings.groq_model).trigger('change'); |
| 1921 | } | 1926 | } |
| 1922 | 1927 | ||
| 1928 | if (oai_settings.chat_completion_source === chat_completion_sources.SILICONFLOW) { | ||
| 1929 | $('#model_siliconflow_select').empty(); | ||
| 1930 | model_list.forEach((model) => { | ||
| 1931 | $('#model_siliconflow_select').append( | ||
| 1932 | $('<option>', { | ||
| 1933 | value: model.id, | ||
| 1934 | text: model.id, | ||
| 1935 | })); | ||
| 1936 | }); | ||
| 1937 | |||
| 1938 | const selectedModel = model_list.find(model => model.id === oai_settings.siliconflow_model); | ||
| 1939 | if (model_list.length > 0 && (!selectedModel || !oai_settings.siliconflow_model)) { | ||
| 1940 | oai_settings.siliconflow_model = model_list[0].id; | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | $('#model_siliconflow_select').val(oai_settings.siliconflow_model).trigger('change'); | ||
| 1944 | } | ||
| 1945 | |||
| 1923 | if (oai_settings.chat_completion_source === chat_completion_sources.FIREWORKS) { | 1946 | if (oai_settings.chat_completion_source === chat_completion_sources.FIREWORKS) { |
| 1924 | $('#model_fireworks_select').empty(); | 1947 | $('#model_fireworks_select').empty(); |
| 1925 | model_list.forEach((model) => { | 1948 | model_list.forEach((model) => { |
| @@ -2654,7 +2677,7 @@ export function getStreamingReply(data, state, { chatCompletionSource = null, ov | |||
| 2654 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || ''); | 2677 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || ''); |
| 2655 | } | 2678 | } |
| 2656 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; | 2679 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; |
| 2657 | } else if ([chat_completion_sources.CUSTOM, chat_completion_sources.POLLINATIONS, chat_completion_sources.AIMLAPI, chat_completion_sources.MOONSHOT, chat_completion_sources.COMETAPI, chat_completion_sources.ELECTRONHUB, chat_completion_sources.NANOGPT, chat_completion_sources.ZAI].includes(chat_completion_source)) { | 2680 | } else if ([chat_completion_sources.CUSTOM, chat_completion_sources.POLLINATIONS, chat_completion_sources.AIMLAPI, chat_completion_sources.MOONSHOT, chat_completion_sources.COMETAPI, chat_completion_sources.ELECTRONHUB, chat_completion_sources.NANOGPT, chat_completion_sources.ZAI, chat_completion_sources.SILICONFLOW].includes(chat_completion_source)) { |
| 2658 | if (show_thoughts) { | 2681 | if (show_thoughts) { |
| 2659 | state.reasoning += | 2682 | state.reasoning += |
| 2660 | data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ?? | 2683 | data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ?? |
| @@ -3665,6 +3688,7 @@ function loadOpenAISettings(data, settings) { | |||
| 3665 | oai_settings.cohere_model = settings.cohere_model ?? default_settings.cohere_model; | 3688 | oai_settings.cohere_model = settings.cohere_model ?? default_settings.cohere_model; |
| 3666 | oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model; | 3689 | oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model; |
| 3667 | oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model; | 3690 | oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model; |
| 3691 | oai_settings.siliconflow_model = settings.siliconflow_model ?? default_settings.siliconflow_model; | ||
| 3668 | oai_settings.electronhub_model = settings.electronhub_model ?? default_settings.electronhub_model; | 3692 | oai_settings.electronhub_model = settings.electronhub_model ?? default_settings.electronhub_model; |
| 3669 | oai_settings.electronhub_sort_models = settings.electronhub_sort_models ?? default_settings.electronhub_sort_models; | 3693 | oai_settings.electronhub_sort_models = settings.electronhub_sort_models ?? default_settings.electronhub_sort_models; |
| 3670 | oai_settings.electronhub_group_models = settings.electronhub_group_models ?? default_settings.electronhub_group_models; | 3694 | oai_settings.electronhub_group_models = settings.electronhub_group_models ?? default_settings.electronhub_group_models; |
| @@ -3770,6 +3794,8 @@ function loadOpenAISettings(data, settings) { | |||
| 3770 | $(`#model_perplexity_select option[value="${oai_settings.perplexity_model}"`).prop('selected', true); | 3794 | $(`#model_perplexity_select option[value="${oai_settings.perplexity_model}"`).prop('selected', true); |
| 3771 | $('#model_groq_select').val(oai_settings.groq_model); | 3795 | $('#model_groq_select').val(oai_settings.groq_model); |
| 3772 | $(`#model_groq_select option[value="${oai_settings.groq_model}"`).prop('selected', true); | 3796 | $(`#model_groq_select option[value="${oai_settings.groq_model}"`).prop('selected', true); |
| 3797 | $('#model_siliconflow_select').val(oai_settings.siliconflow_model); | ||
| 3798 | $(`#model_siliconflow_select option[value="${oai_settings.siliconflow_model}"`).prop('selected', true); | ||
| 3773 | $('#model_electronhub_select').val(oai_settings.electronhub_model); | 3799 | $('#model_electronhub_select').val(oai_settings.electronhub_model); |
| 3774 | $(`#model_electronhub_select option[value="${oai_settings.electronhub_model}"`).prop('selected', true); | 3800 | $(`#model_electronhub_select option[value="${oai_settings.electronhub_model}"`).prop('selected', true); |
| 3775 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model); | 3801 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model); |
| @@ -4077,6 +4103,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | |||
| 4077 | cohere_model: settings.cohere_model, | 4103 | cohere_model: settings.cohere_model, |
| 4078 | perplexity_model: settings.perplexity_model, | 4104 | perplexity_model: settings.perplexity_model, |
| 4079 | groq_model: settings.groq_model, | 4105 | groq_model: settings.groq_model, |
| 4106 | siliconflow_model: settings.siliconflow_model, | ||
| 4080 | xai_model: settings.xai_model, | 4107 | xai_model: settings.xai_model, |
| 4081 | pollinations_model: settings.pollinations_model, | 4108 | pollinations_model: settings.pollinations_model, |
| 4082 | aimlapi_model: settings.aimlapi_model, | 4109 | aimlapi_model: settings.aimlapi_model, |
| @@ -4766,6 +4793,65 @@ function getZaiMaxContext(model, isUnlocked) { | |||
| 4766 | } | 4793 | } |
| 4767 | 4794 | ||
| 4768 | /** | 4795 | /** |
| 4796 | * Get the maximum context size for the SiliconFlow model | ||
| 4797 | * @param {string} model Model identifier | ||
| 4798 | * @param {boolean} isUnlocked Whether context limits are unlocked | ||
| 4799 | * @returns {number} Maximum context size in tokens | ||
| 4800 | */ | ||
| 4801 | function getSiliconflowMaxContext(model, isUnlocked) { | ||
| 4802 | if (isUnlocked) { | ||
| 4803 | return unlocked_max; | ||
| 4804 | } | ||
| 4805 | |||
| 4806 | const contextMap = { | ||
| 4807 | 'baidu/ERNIE-4.5-300B-A47B': max_128k, | ||
| 4808 | 'ByteDance-Seed/Seed-OSS-36B-Instruct': max_256k, | ||
| 4809 | 'deepseek-ai/DeepSeek-R1': max_128k, | ||
| 4810 | 'deepseek-ai/DeepSeek-V3': max_128k, | ||
| 4811 | 'deepseek-ai/DeepSeek-V3.1': max_128k, | ||
| 4812 | 'deepseek-ai/DeepSeek-V3.1-Terminus': max_128k, | ||
| 4813 | 'deepseek-ai/DeepSeek-V3.2-Exp': max_128k, | ||
| 4814 | 'deepseek-ai/deepseek-vl2': max_4k, | ||
| 4815 | 'inclusionAI/Ling-1T': max_128k, | ||
| 4816 | 'inclusionAI/Ling-flash-2.0': max_128k, | ||
| 4817 | 'inclusionAI/Ling-mini-2.0': max_128k, | ||
| 4818 | 'inclusionAI/Ring-1T': max_128k, | ||
| 4819 | 'inclusionAI/Ring-flash-2.0': max_128k, | ||
| 4820 | 'meta-llama/Llama-3.3-70B-Instruct': max_32k, | ||
| 4821 | 'meta-llama/Meta-Llama-3.1-8B-Instruct': max_32k, | ||
| 4822 | 'MiniMaxAI/MiniMax-M1-80k': max_128k, | ||
| 4823 | 'MiniMaxAI/MiniMax-M2': max_128k, | ||
| 4824 | 'moonshotai/Kimi-K2-Instruct': max_128k, | ||
| 4825 | 'moonshotai/Kimi-K2-Instruct-0905': max_256k, | ||
| 4826 | 'moonshotai/Kimi-K2-Thinking': max_256k, | ||
| 4827 | 'openai/gpt-oss-120b': max_128k, | ||
| 4828 | 'openai/gpt-oss-20b': max_128k, | ||
| 4829 | 'Qwen/Qwen3-235B-A22B-Instruct-2507': max_256k, | ||
| 4830 | 'Qwen/Qwen3-235B-A22B-Thinking-2507': max_256k, | ||
| 4831 | 'Qwen/Qwen3-30B-A3B-Instruct-2507': max_256k, | ||
| 4832 | 'Qwen/Qwen3-30B-A3B-Thinking-2507': max_256k, | ||
| 4833 | 'Qwen/Qwen3-VL-235B-A22B-Instruct': max_256k, | ||
| 4834 | 'Qwen/Qwen3-VL-235B-A22B-Thinking': max_256k, | ||
| 4835 | 'Qwen/Qwen3-VL-30B-A3B-Instruct': max_256k, | ||
| 4836 | 'Qwen/Qwen3-VL-30B-A3B-Thinking': max_256k, | ||
| 4837 | 'Qwen/Qwen3-VL-32B-Instruct': max_256k, | ||
| 4838 | 'Qwen/Qwen3-VL-32B-Thinking': max_256k, | ||
| 4839 | 'Qwen/Qwen3-VL-8B-Instruct': max_256k, | ||
| 4840 | 'Qwen/Qwen3-VL-8B-Thinking': max_256k, | ||
| 4841 | 'stepfun-ai/step3': max_64k, | ||
| 4842 | 'tencent/Hunyuan-A13B-Instruct': max_128k, | ||
| 4843 | 'zai-org/GLM-4.5': max_128k, | ||
| 4844 | 'zai-org/GLM-4.5-Air': max_128k, | ||
| 4845 | 'zai-org/GLM-4.5V': max_64k, | ||
| 4846 | 'zai-org/GLM-4.6': max_200k, | ||
| 4847 | }; | ||
| 4848 | |||
| 4849 | // Return context size if model found, otherwise default to 32k | ||
| 4850 | return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_32k; | ||
| 4851 | |||
| 4852 | } | ||
| 4853 | |||
| 4854 | /** | ||
| 4769 | * Get the maximum context size for the Moonshot model | 4855 | * Get the maximum context size for the Moonshot model |
| 4770 | * @param {string} model Model identifier | 4856 | * @param {string} model Model identifier |
| 4771 | * @param {boolean} isUnlocked If context limits are unlocked | 4857 | * @param {boolean} isUnlocked If context limits are unlocked |
| @@ -4956,6 +5042,15 @@ async function onModelChange() { | |||
| 4956 | oai_settings.groq_model = value; | 5042 | oai_settings.groq_model = value; |
| 4957 | } | 5043 | } |
| 4958 | 5044 | ||
| 5045 | if ($(this).is('#model_siliconflow_select')) { | ||
| 5046 | if (!value) { | ||
| 5047 | console.debug('Null SiliconFlow model selected. Ignoring.'); | ||
| 5048 | return; | ||
| 5049 | } | ||
| 5050 | console.log('SiliconFlow model changed to', value); | ||
| 5051 | oai_settings.siliconflow_model = value; | ||
| 5052 | } | ||
| 5053 | |||
| 4959 | if ($(this).is('#model_electronhub_select')) { | 5054 | if ($(this).is('#model_electronhub_select')) { |
| 4960 | if (!value) { | 5055 | if (!value) { |
| 4961 | console.debug('Null ElectronHub model selected. Ignoring.'); | 5056 | console.debug('Null ElectronHub model selected. Ignoring.'); |
| @@ -5356,6 +5451,15 @@ async function onModelChange() { | |||
| 5356 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | 5451 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 5357 | } | 5452 | } |
| 5358 | 5453 | ||
| 5454 | if (oai_settings.chat_completion_source === chat_completion_sources.SILICONFLOW) { | ||
| 5455 | const maxContext = getSiliconflowMaxContext(oai_settings.siliconflow_model, oai_settings.max_context_unlocked); | ||
| 5456 | $('#openai_max_context').attr('max', maxContext); | ||
| 5457 | oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); | ||
| 5458 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); | ||
| 5459 | oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); | ||
| 5460 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | ||
| 5461 | } | ||
| 5462 | |||
| 5359 | if (oai_settings.chat_completion_source == chat_completion_sources.ZAI) { | 5463 | if (oai_settings.chat_completion_source == chat_completion_sources.ZAI) { |
| 5360 | const maxContext = getZaiMaxContext(oai_settings.zai_model, oai_settings.max_context_unlocked); | 5464 | const maxContext = getZaiMaxContext(oai_settings.zai_model, oai_settings.max_context_unlocked); |
| 5361 | $('#openai_max_context').attr('max', maxContext); | 5465 | $('#openai_max_context').attr('max', maxContext); |
| @@ -5411,6 +5515,7 @@ async function onConnectButtonClick(e) { | |||
| 5411 | [chat_completion_sources.COHERE]: { key: SECRET_KEYS.COHERE, selector: '#api_key_cohere', proxy: false }, | 5515 | [chat_completion_sources.COHERE]: { key: SECRET_KEYS.COHERE, selector: '#api_key_cohere', proxy: false }, |
| 5412 | [chat_completion_sources.PERPLEXITY]: { key: SECRET_KEYS.PERPLEXITY, selector: '#api_key_perplexity', proxy: false }, | 5516 | [chat_completion_sources.PERPLEXITY]: { key: SECRET_KEYS.PERPLEXITY, selector: '#api_key_perplexity', proxy: false }, |
| 5413 | [chat_completion_sources.GROQ]: { key: SECRET_KEYS.GROQ, selector: '#api_key_groq', proxy: false }, | 5517 | [chat_completion_sources.GROQ]: { key: SECRET_KEYS.GROQ, selector: '#api_key_groq', proxy: false }, |
| 5518 | [chat_completion_sources.SILICONFLOW]: { key: SECRET_KEYS.SILICONFLOW, selector: '#api_key_siliconflow', proxy: false }, | ||
| 5414 | [chat_completion_sources.ELECTRONHUB]: { key: SECRET_KEYS.ELECTRONHUB, selector: '#api_key_electronhub', proxy: false }, | 5519 | [chat_completion_sources.ELECTRONHUB]: { key: SECRET_KEYS.ELECTRONHUB, selector: '#api_key_electronhub', proxy: false }, |
| 5415 | [chat_completion_sources.NANOGPT]: { key: SECRET_KEYS.NANOGPT, selector: '#api_key_nanogpt', proxy: false }, | 5520 | [chat_completion_sources.NANOGPT]: { key: SECRET_KEYS.NANOGPT, selector: '#api_key_nanogpt', proxy: false }, |
| 5416 | [chat_completion_sources.DEEPSEEK]: { key: SECRET_KEYS.DEEPSEEK, selector: '#api_key_deepseek', proxy: true }, | 5521 | [chat_completion_sources.DEEPSEEK]: { key: SECRET_KEYS.DEEPSEEK, selector: '#api_key_deepseek', proxy: true }, |
| @@ -5493,6 +5598,9 @@ function toggleChatCompletionForms() { | |||
| 5493 | else if (oai_settings.chat_completion_source == chat_completion_sources.GROQ) { | 5598 | else if (oai_settings.chat_completion_source == chat_completion_sources.GROQ) { |
| 5494 | $('#model_groq_select').trigger('change'); | 5599 | $('#model_groq_select').trigger('change'); |
| 5495 | } | 5600 | } |
| 5601 | else if (oai_settings.chat_completion_source == chat_completion_sources.SILICONFLOW) { | ||
| 5602 | $('#model_siliconflow_select').trigger('change'); | ||
| 5603 | } | ||
| 5496 | else if (oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) { | 5604 | else if (oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) { |
| 5497 | $('#model_electronhub_select').trigger('change'); | 5605 | $('#model_electronhub_select').trigger('change'); |
| 5498 | } | 5606 | } |
| @@ -5647,6 +5755,12 @@ export function isImageInliningSupported() { | |||
| 5647 | 'moonshot-v1-128k-vision-preview', | 5755 | 'moonshot-v1-128k-vision-preview', |
| 5648 | // Z.AI (GLM) | 5756 | // Z.AI (GLM) |
| 5649 | 'glm-4.5v', | 5757 | 'glm-4.5v', |
| 5758 | // SiliconFlow | ||
| 5759 | 'Qwen/Qwen3-VL-32B-Instruct', | ||
| 5760 | 'Qwen/Qwen3-VL-8B-Instruct', | ||
| 5761 | 'Qwen/Qwen3-VL-235B-A22B-Instruct', | ||
| 5762 | 'Qwen/Qwen3-VL-30B-A3B-Instruct', | ||
| 5763 | 'zai-org/GLM-4.5V', | ||
| 5650 | ]; | 5764 | ]; |
| 5651 | 5765 | ||
| 5652 | switch (oai_settings.chat_completion_source) { | 5766 | switch (oai_settings.chat_completion_source) { |
| @@ -5691,6 +5805,8 @@ export function isImageInliningSupported() { | |||
| 5691 | return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.nanogpt_model)?.capabilities?.vision); | 5805 | return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.nanogpt_model)?.capabilities?.vision); |
| 5692 | case chat_completion_sources.ZAI: | 5806 | case chat_completion_sources.ZAI: |
| 5693 | return visionSupportedModels.some(model => oai_settings.zai_model.includes(model)); | 5807 | return visionSupportedModels.some(model => oai_settings.zai_model.includes(model)); |
| 5808 | case chat_completion_sources.SILICONFLOW: | ||
| 5809 | return visionSupportedModels.some(model => oai_settings.siliconflow_model.includes(model)); | ||
| 5694 | default: | 5810 | default: |
| 5695 | return false; | 5811 | return false; |
| 5696 | } | 5812 | } |
| @@ -6571,6 +6687,7 @@ export function initOpenAI() { | |||
| 6571 | $('#model_cohere_select').on('change', onModelChange); | 6687 | $('#model_cohere_select').on('change', onModelChange); |
| 6572 | $('#model_perplexity_select').on('change', onModelChange); | 6688 | $('#model_perplexity_select').on('change', onModelChange); |
| 6573 | $('#model_groq_select').on('change', onModelChange); | 6689 | $('#model_groq_select').on('change', onModelChange); |
| 6690 | $('#model_siliconflow_select').on('change', onModelChange); | ||
| 6574 | $('#model_electronhub_select').on('change', onModelChange); | 6691 | $('#model_electronhub_select').on('change', onModelChange); |
| 6575 | $('#model_nanogpt_select').on('change', onModelChange); | 6692 | $('#model_nanogpt_select').on('change', onModelChange); |
| 6576 | $('#model_deepseek_select').on('change', onModelChange); | 6693 | $('#model_deepseek_select').on('change', onModelChange); |
| @@ -127,6 +127,7 @@ export function extractReasoningFromData(data, { | |||
| 127 | case chat_completion_sources.COMETAPI: | 127 | case chat_completion_sources.COMETAPI: |
| 128 | case chat_completion_sources.ELECTRONHUB: | 128 | case chat_completion_sources.ELECTRONHUB: |
| 129 | case chat_completion_sources.NANOGPT: | 129 | case chat_completion_sources.NANOGPT: |
| 130 | case chat_completion_sources.SILICONFLOW: | ||
| 130 | case chat_completion_sources.ZAI: | 131 | case chat_completion_sources.ZAI: |
| 131 | case chat_completion_sources.CUSTOM: { | 132 | case chat_completion_sources.CUSTOM: { |
| 132 | return data?.choices?.[0]?.message?.reasoning_content | 133 | return data?.choices?.[0]?.message?.reasoning_content |
| @@ -69,6 +69,7 @@ export const SECRET_KEYS = { | |||
| 69 | MOONSHOT: 'api_key_moonshot', | 69 | MOONSHOT: 'api_key_moonshot', |
| 70 | COMETAPI: 'api_key_cometapi', | 70 | COMETAPI: 'api_key_cometapi', |
| 71 | ZAI: 'api_key_zai', | 71 | ZAI: 'api_key_zai', |
| 72 | SILICONFLOW: 'api_key_siliconflow', | ||
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | const FRIENDLY_NAMES = { | 75 | const FRIENDLY_NAMES = { |
| @@ -126,6 +127,7 @@ const FRIENDLY_NAMES = { | |||
| 126 | [SECRET_KEYS.COMETAPI]: 'CometAPI', | 127 | [SECRET_KEYS.COMETAPI]: 'CometAPI', |
| 127 | [SECRET_KEYS.AZURE_OPENAI]: 'Azure OpenAI', | 128 | [SECRET_KEYS.AZURE_OPENAI]: 'Azure OpenAI', |
| 128 | [SECRET_KEYS.ZAI]: 'Z.AI', | 129 | [SECRET_KEYS.ZAI]: 'Z.AI', |
| 130 | [SECRET_KEYS.SILICONFLOW]: 'SiliconFlow', | ||
| 129 | }; | 131 | }; |
| 130 | 132 | ||
| 131 | const INPUT_MAP = { | 133 | const INPUT_MAP = { |
| @@ -166,6 +168,7 @@ const INPUT_MAP = { | |||
| 166 | [SECRET_KEYS.COMETAPI]: '#api_key_cometapi', | 168 | [SECRET_KEYS.COMETAPI]: '#api_key_cometapi', |
| 167 | [SECRET_KEYS.AZURE_OPENAI]: '#api_key_azure_openai', | 169 | [SECRET_KEYS.AZURE_OPENAI]: '#api_key_azure_openai', |
| 168 | [SECRET_KEYS.ZAI]: '#api_key_zai', | 170 | [SECRET_KEYS.ZAI]: '#api_key_zai', |
| 171 | [SECRET_KEYS.SILICONFLOW]: '#api_key_siliconflow', | ||
| 169 | }; | 172 | }; |
| 170 | 173 | ||
| 171 | const getLabel = () => moment().format('L LT'); | 174 | const getLabel = () => moment().format('L LT'); |
| @@ -4844,6 +4844,7 @@ function getModelOptions(quiet) { | |||
| 4844 | { id: 'model_cohere_select', api: 'openai', type: chat_completion_sources.COHERE }, | 4844 | { id: 'model_cohere_select', api: 'openai', type: chat_completion_sources.COHERE }, |
| 4845 | { id: 'model_perplexity_select', api: 'openai', type: chat_completion_sources.PERPLEXITY }, | 4845 | { id: 'model_perplexity_select', api: 'openai', type: chat_completion_sources.PERPLEXITY }, |
| 4846 | { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ }, | 4846 | { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ }, |
| 4847 | { id: 'model_siliconflow_select', api: 'openai', type: chat_completion_sources.SILICONFLOW }, | ||
| 4847 | { id: 'model_electronhub_select', api: 'openai', type: chat_completion_sources.ELECTRONHUB }, | 4848 | { id: 'model_electronhub_select', api: 'openai', type: chat_completion_sources.ELECTRONHUB }, |
| 4848 | { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT }, | 4849 | { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT }, |
| 4849 | { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK }, | 4850 | { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK }, |
| @@ -662,6 +662,7 @@ export class ToolManager { | |||
| 662 | chat_completion_sources.ELECTRONHUB, | 662 | chat_completion_sources.ELECTRONHUB, |
| 663 | chat_completion_sources.AZURE_OPENAI, | 663 | chat_completion_sources.AZURE_OPENAI, |
| 664 | chat_completion_sources.ZAI, | 664 | chat_completion_sources.ZAI, |
| 665 | chat_completion_sources.SILICONFLOW, | ||
| 665 | ]; | 666 | ]; |
| 666 | return supportedSources.includes(oai_settings.chat_completion_source); | 667 | return supportedSources.includes(oai_settings.chat_completion_source); |
| 667 | } | 668 | } |
| @@ -207,6 +207,7 @@ export const CHAT_COMPLETION_SOURCES = { | |||
| 207 | COMETAPI: 'cometapi', | 207 | COMETAPI: 'cometapi', |
| 208 | AZURE_OPENAI: 'azure_openai', | 208 | AZURE_OPENAI: 'azure_openai', |
| 209 | ZAI: 'zai', | 209 | ZAI: 'zai', |
| 210 | SILICONFLOW: 'siliconflow', | ||
| 210 | }; | 211 | }; |
| 211 | 212 | ||
| 212 | /** | 213 | /** |
| @@ -76,6 +76,7 @@ const API_MOONSHOT = 'https://api.moonshot.ai/v1'; | |||
| 76 | const API_FIREWORKS = 'https://api.fireworks.ai/inference/v1'; | 76 | const API_FIREWORKS = 'https://api.fireworks.ai/inference/v1'; |
| 77 | const API_COMETAPI = 'https://api.cometapi.com/v1'; | 77 | const API_COMETAPI = 'https://api.cometapi.com/v1'; |
| 78 | const API_ZAI = 'https://api.z.ai/api/paas/v4'; | 78 | const API_ZAI = 'https://api.z.ai/api/paas/v4'; |
| 79 | const API_SILICONFLOW = 'https://api.siliconflow.com/v1'; | ||
| 79 | 80 | ||
| 80 | /** | 81 | /** |
| 81 | * Gets OpenRouter transforms based on the request. | 82 | * Gets OpenRouter transforms based on the request. |
| @@ -1570,6 +1571,10 @@ router.post('/status', async function (request, statusResponse) { | |||
| 1570 | console.error('Azure OpenAI status check connection error:', error); | 1571 | console.error('Azure OpenAI status check connection error:', error); |
| 1571 | return statusResponse.status(500).send({ error: true, message: 'Failed to connect to the Azure endpoint.' }); | 1572 | return statusResponse.status(500).send({ error: true, message: 'Failed to connect to the Azure endpoint.' }); |
| 1572 | } | 1573 | } |
| 1574 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.SILICONFLOW) { | ||
| 1575 | apiUrl = API_SILICONFLOW; | ||
| 1576 | apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW); | ||
| 1577 | headers = {}; | ||
| 1573 | } else { | 1578 | } else { |
| 1574 | console.warn('This chat completion source is not supported yet.'); | 1579 | console.warn('This chat completion source is not supported yet.'); |
| 1575 | return statusResponse.status(400).send({ error: true }); | 1580 | return statusResponse.status(400).send({ error: true }); |
| @@ -1980,6 +1985,14 @@ router.post('/generate', function (request, response) { | |||
| 1980 | if (request.body.json_schema) { | 1985 | if (request.body.json_schema) { |
| 1981 | setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema); | 1986 | setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema); |
| 1982 | } | 1987 | } |
| 1988 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.SILICONFLOW) { | ||
| 1989 | apiUrl = API_SILICONFLOW; | ||
| 1990 | apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW); | ||
| 1991 | headers = {}; | ||
| 1992 | bodyParams = {}; | ||
| 1993 | if (request.body.json_schema) { | ||
| 1994 | setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema); | ||
| 1995 | } | ||
| 1983 | } else { | 1996 | } else { |
| 1984 | console.warn('This chat completion source is not supported yet.'); | 1997 | console.warn('This chat completion source is not supported yet.'); |
| 1985 | return response.status(400).send({ error: true }); | 1998 | return response.status(400).send({ error: true }); |
| @@ -62,6 +62,7 @@ export const SECRET_KEYS = { | |||
| 62 | COMETAPI: 'api_key_cometapi', | 62 | COMETAPI: 'api_key_cometapi', |
| 63 | AZURE_OPENAI: 'api_key_azure_openai', | 63 | AZURE_OPENAI: 'api_key_azure_openai', |
| 64 | ZAI: 'api_key_zai', | 64 | ZAI: 'api_key_zai', |
| 65 | SILICONFLOW: 'api_key_siliconflow', | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | /** | 68 | /** |