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 | 693 | </span> |
| 694 | 694 | </div> |
| 695 | 695 | </div> |
| 696 | 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 | 697 | <div class="range-block-title" data-i18n="Temperature"> |
| 698 | 698 | Temperature |
| 699 | 699 | </div> |
| @@ -706,7 +706,7 @@ | ||
| 706 | 706 | </div> |
| 707 | 707 | </div> |
| 708 | 708 | </div> |
| 709 | 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 | 710 | <div class="range-block-title" data-i18n="Frequency Penalty"> |
| 711 | 711 | Frequency Penalty |
| 712 | 712 | </div> |
| @@ -719,7 +719,7 @@ | ||
| 719 | 719 | </div> |
| 720 | 720 | </div> |
| 721 | 721 | </div> |
| 722 | 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 | 723 | <div class="range-block-title" data-i18n="Presence Penalty"> |
| 724 | 724 | Presence Penalty |
| 725 | 725 | </div> |
| @@ -745,7 +745,7 @@ | ||
| 745 | 745 | </div> |
| 746 | 746 | </div> |
| 747 | 747 | </div> |
| 748 | 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 | 749 | <div class="range-block-title" data-i18n="Top P"> |
| 750 | 750 | Top P |
| 751 | 751 | </div> |
| @@ -1965,7 +1965,7 @@ | ||
| 1965 | 1965 | </b> |
| 1966 | 1966 | </div> |
| 1967 | 1967 | </div> |
| 1968 | 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 | 1969 | <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand"> |
| 1970 | 1970 | <input id="openai_function_calling" type="checkbox" /> |
| 1971 | 1971 | <span data-i18n="Enable function calling">Enable function calling</span> |
| @@ -1980,7 +1980,7 @@ | ||
| 1980 | 1980 | <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong> |
| 1981 | 1981 | </div> |
| 1982 | 1982 | </div> |
| 1983 | 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 | 1984 | <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand"> |
| 1985 | 1985 | <input id="openai_image_inlining" type="checkbox" /> |
| 1986 | 1986 | <span data-i18n="Send inline images">Send inline images</span> |
| @@ -1992,7 +1992,7 @@ | ||
| 1992 | 1992 | <div id="image_inlining_hint" class="flexBasis100p toggle-description justifyLeft"> |
| 1993 | 1993 | <span data-i18n="image_inlining_hint_1">Sends images in prompts if the model supports it.</span> |
| 1994 | 1994 | </div> |
| 1995 | 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 | 1996 | <div class="flex-container oneline-dropdown"> |
| 1997 | 1997 | <label for="openai_inline_image_quality" data-i18n="Inline Image Quality"> |
| 1998 | 1998 | Inline Image Quality |
| @@ -2806,6 +2806,7 @@ | ||
| 2806 | 2806 | <option value="openrouter">OpenRouter</option> |
| 2807 | 2807 | <option value="perplexity">Perplexity</option> |
| 2808 | 2808 | <option value="pollinations">Pollinations</option> |
| 2809 | + <option value="siliconflow">SiliconFlow</option> | |
| 2809 | 2810 | <option value="xai">xAI (Grok)</option> |
| 2810 | 2811 | <option value="zai">Z.AI (GLM)</option> |
| 2811 | 2812 | </optgroup> |
| @@ -3397,6 +3398,20 @@ | ||
| 3397 | 3398 | <option value="mistral-saba-24b">mistral-saba-24b</option> |
| 3398 | 3399 | </select> |
| 3399 | 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 | 3415 | <div id="electronhub_form" data-source="electronhub"> |
| 3401 | 3416 | <h4 data-i18n="Electron Hub API Key">Electron Hub API Key</h4> |
| 3402 | 3417 | <div> |
| @@ -403,6 +403,7 @@ function RA_autoconnect(PrevApi) { | ||
| 403 | 403 | || (secret_state[SECRET_KEYS.COHERE] && oai_settings.chat_completion_source == chat_completion_sources.COHERE) |
| 404 | 404 | || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY) |
| 405 | 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 | 407 | || (secret_state[SECRET_KEYS.ELECTRONHUB] && oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) |
| 407 | 408 | || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT) |
| 408 | 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 | 194 | COMETAPI: 'cometapi', |
| 195 | 195 | AZURE_OPENAI: 'azure_openai', |
| 196 | 196 | ZAI: 'zai', |
| 197 | + SILICONFLOW: 'siliconflow', | |
| 197 | 198 | }; |
| 198 | 199 | |
| 199 | 200 | const character_names_behavior = { |
| @@ -280,6 +281,7 @@ export const settingsToUpdate = { | ||
| 280 | 281 | cohere_model: ['#model_cohere_select', 'cohere_model', false, true], |
| 281 | 282 | perplexity_model: ['#model_perplexity_select', 'perplexity_model', false, true], |
| 282 | 283 | groq_model: ['#model_groq_select', 'groq_model', false, true], |
| 284 | + siliconflow_model: ['#model_siliconflow_select', 'siliconflow_model', false, true], | |
| 283 | 285 | electronhub_model: ['#model_electronhub_select', 'electronhub_model', false, true], |
| 284 | 286 | electronhub_sort_models: ['#electronhub_sort_models', 'electronhub_sort_models', false, true], |
| 285 | 287 | electronhub_group_models: ['#electronhub_group_models', 'electronhub_group_models', false, true], |
| @@ -387,6 +389,7 @@ const default_settings = { | ||
| 387 | 389 | cohere_model: 'command-r-plus', |
| 388 | 390 | perplexity_model: 'sonar-pro', |
| 389 | 391 | groq_model: 'llama-3.3-70b-versatile', |
| 392 | + siliconflow_model: 'deepseek-ai/DeepSeek-V3', | |
| 390 | 393 | electronhub_model: 'gpt-4o-mini', |
| 391 | 394 | electronhub_sort_models: 'alphabetically', |
| 392 | 395 | electronhub_group_models: false, |
| @@ -1587,6 +1590,8 @@ export function getChatCompletionModel(source = null) { | ||
| 1587 | 1590 | return oai_settings.perplexity_model; |
| 1588 | 1591 | case chat_completion_sources.GROQ: |
| 1589 | 1592 | return oai_settings.groq_model; |
| 1593 | + case chat_completion_sources.SILICONFLOW: | |
| 1594 | + return oai_settings.siliconflow_model; | |
| 1590 | 1595 | case chat_completion_sources.ELECTRONHUB: |
| 1591 | 1596 | return oai_settings.electronhub_model; |
| 1592 | 1597 | case chat_completion_sources.NANOGPT: |
| @@ -1920,6 +1925,24 @@ function saveModelList(data) { | ||
| 1920 | 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 | 1946 | if (oai_settings.chat_completion_source === chat_completion_sources.FIREWORKS) { |
| 1924 | 1947 | $('#model_fireworks_select').empty(); |
| 1925 | 1948 | model_list.forEach((model) => { |
| @@ -2654,7 +2677,7 @@ export function getStreamingReply(data, state, { chatCompletionSource = null, ov | ||
| 2654 | 2677 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || ''); |
| 2655 | 2678 | } |
| 2656 | 2679 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; |
| 2657 | 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 | 2681 | if (show_thoughts) { |
| 2659 | 2682 | state.reasoning += |
| 2660 | 2683 | data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ?? |
| @@ -3665,6 +3688,7 @@ function loadOpenAISettings(data, settings) { | ||
| 3665 | 3688 | oai_settings.cohere_model = settings.cohere_model ?? default_settings.cohere_model; |
| 3666 | 3689 | oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model; |
| 3667 | 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 | 3692 | oai_settings.electronhub_model = settings.electronhub_model ?? default_settings.electronhub_model; |
| 3669 | 3693 | oai_settings.electronhub_sort_models = settings.electronhub_sort_models ?? default_settings.electronhub_sort_models; |
| 3670 | 3694 | oai_settings.electronhub_group_models = settings.electronhub_group_models ?? default_settings.electronhub_group_models; |
| @@ -3770,6 +3794,8 @@ function loadOpenAISettings(data, settings) { | ||
| 3770 | 3794 | $(`#model_perplexity_select option[value="${oai_settings.perplexity_model}"`).prop('selected', true); |
| 3771 | 3795 | $('#model_groq_select').val(oai_settings.groq_model); |
| 3772 | 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 | 3799 | $('#model_electronhub_select').val(oai_settings.electronhub_model); |
| 3774 | 3800 | $(`#model_electronhub_select option[value="${oai_settings.electronhub_model}"`).prop('selected', true); |
| 3775 | 3801 | $('#model_nanogpt_select').val(oai_settings.nanogpt_model); |
| @@ -4077,6 +4103,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 4077 | 4103 | cohere_model: settings.cohere_model, |
| 4078 | 4104 | perplexity_model: settings.perplexity_model, |
| 4079 | 4105 | groq_model: settings.groq_model, |
| 4106 | + siliconflow_model: settings.siliconflow_model, | |
| 4080 | 4107 | xai_model: settings.xai_model, |
| 4081 | 4108 | pollinations_model: settings.pollinations_model, |
| 4082 | 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 | 4855 | * Get the maximum context size for the Moonshot model |
| 4770 | 4856 | * @param {string} model Model identifier |
| 4771 | 4857 | * @param {boolean} isUnlocked If context limits are unlocked |
| @@ -4956,6 +5042,15 @@ async function onModelChange() { | ||
| 4956 | 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 | 5054 | if ($(this).is('#model_electronhub_select')) { |
| 4960 | 5055 | if (!value) { |
| 4961 | 5056 | console.debug('Null ElectronHub model selected. Ignoring.'); |
| @@ -5356,6 +5451,15 @@ async function onModelChange() { | ||
| 5356 | 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 | 5463 | if (oai_settings.chat_completion_source == chat_completion_sources.ZAI) { |
| 5360 | 5464 | const maxContext = getZaiMaxContext(oai_settings.zai_model, oai_settings.max_context_unlocked); |
| 5361 | 5465 | $('#openai_max_context').attr('max', maxContext); |
| @@ -5411,6 +5515,7 @@ async function onConnectButtonClick(e) { | ||
| 5411 | 5515 | [chat_completion_sources.COHERE]: { key: SECRET_KEYS.COHERE, selector: '#api_key_cohere', proxy: false }, |
| 5412 | 5516 | [chat_completion_sources.PERPLEXITY]: { key: SECRET_KEYS.PERPLEXITY, selector: '#api_key_perplexity', proxy: false }, |
| 5413 | 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 | 5519 | [chat_completion_sources.ELECTRONHUB]: { key: SECRET_KEYS.ELECTRONHUB, selector: '#api_key_electronhub', proxy: false }, |
| 5415 | 5520 | [chat_completion_sources.NANOGPT]: { key: SECRET_KEYS.NANOGPT, selector: '#api_key_nanogpt', proxy: false }, |
| 5416 | 5521 | [chat_completion_sources.DEEPSEEK]: { key: SECRET_KEYS.DEEPSEEK, selector: '#api_key_deepseek', proxy: true }, |
| @@ -5493,6 +5598,9 @@ function toggleChatCompletionForms() { | ||
| 5493 | 5598 | else if (oai_settings.chat_completion_source == chat_completion_sources.GROQ) { |
| 5494 | 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 | 5604 | else if (oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) { |
| 5497 | 5605 | $('#model_electronhub_select').trigger('change'); |
| 5498 | 5606 | } |
| @@ -5647,6 +5755,12 @@ export function isImageInliningSupported() { | ||
| 5647 | 5755 | 'moonshot-v1-128k-vision-preview', |
| 5648 | 5756 | // Z.AI (GLM) |
| 5649 | 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 | 5766 | switch (oai_settings.chat_completion_source) { |
| @@ -5691,6 +5805,8 @@ export function isImageInliningSupported() { | ||
| 5691 | 5805 | return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.nanogpt_model)?.capabilities?.vision); |
| 5692 | 5806 | case chat_completion_sources.ZAI: |
| 5693 | 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 | 5810 | default: |
| 5695 | 5811 | return false; |
| 5696 | 5812 | } |
| @@ -6571,6 +6687,7 @@ export function initOpenAI() { | ||
| 6571 | 6687 | $('#model_cohere_select').on('change', onModelChange); |
| 6572 | 6688 | $('#model_perplexity_select').on('change', onModelChange); |
| 6573 | 6689 | $('#model_groq_select').on('change', onModelChange); |
| 6690 | + $('#model_siliconflow_select').on('change', onModelChange); | |
| 6574 | 6691 | $('#model_electronhub_select').on('change', onModelChange); |
| 6575 | 6692 | $('#model_nanogpt_select').on('change', onModelChange); |
| 6576 | 6693 | $('#model_deepseek_select').on('change', onModelChange); |
| @@ -127,6 +127,7 @@ export function extractReasoningFromData(data, { | ||
| 127 | 127 | case chat_completion_sources.COMETAPI: |
| 128 | 128 | case chat_completion_sources.ELECTRONHUB: |
| 129 | 129 | case chat_completion_sources.NANOGPT: |
| 130 | + case chat_completion_sources.SILICONFLOW: | |
| 130 | 131 | case chat_completion_sources.ZAI: |
| 131 | 132 | case chat_completion_sources.CUSTOM: { |
| 132 | 133 | return data?.choices?.[0]?.message?.reasoning_content |
| @@ -69,6 +69,7 @@ export const SECRET_KEYS = { | ||
| 69 | 69 | MOONSHOT: 'api_key_moonshot', |
| 70 | 70 | COMETAPI: 'api_key_cometapi', |
| 71 | 71 | ZAI: 'api_key_zai', |
| 72 | + SILICONFLOW: 'api_key_siliconflow', | |
| 72 | 73 | }; |
| 73 | 74 | |
| 74 | 75 | const FRIENDLY_NAMES = { |
| @@ -126,6 +127,7 @@ const FRIENDLY_NAMES = { | ||
| 126 | 127 | [SECRET_KEYS.COMETAPI]: 'CometAPI', |
| 127 | 128 | [SECRET_KEYS.AZURE_OPENAI]: 'Azure OpenAI', |
| 128 | 129 | [SECRET_KEYS.ZAI]: 'Z.AI', |
| 130 | + [SECRET_KEYS.SILICONFLOW]: 'SiliconFlow', | |
| 129 | 131 | }; |
| 130 | 132 | |
| 131 | 133 | const INPUT_MAP = { |
| @@ -166,6 +168,7 @@ const INPUT_MAP = { | ||
| 166 | 168 | [SECRET_KEYS.COMETAPI]: '#api_key_cometapi', |
| 167 | 169 | [SECRET_KEYS.AZURE_OPENAI]: '#api_key_azure_openai', |
| 168 | 170 | [SECRET_KEYS.ZAI]: '#api_key_zai', |
| 171 | + [SECRET_KEYS.SILICONFLOW]: '#api_key_siliconflow', | |
| 169 | 172 | }; |
| 170 | 173 | |
| 171 | 174 | const getLabel = () => moment().format('L LT'); |
| @@ -4844,6 +4844,7 @@ function getModelOptions(quiet) { | ||
| 4844 | 4844 | { id: 'model_cohere_select', api: 'openai', type: chat_completion_sources.COHERE }, |
| 4845 | 4845 | { id: 'model_perplexity_select', api: 'openai', type: chat_completion_sources.PERPLEXITY }, |
| 4846 | 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 | 4848 | { id: 'model_electronhub_select', api: 'openai', type: chat_completion_sources.ELECTRONHUB }, |
| 4848 | 4849 | { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT }, |
| 4849 | 4850 | { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK }, |
| @@ -662,6 +662,7 @@ export class ToolManager { | ||
| 662 | 662 | chat_completion_sources.ELECTRONHUB, |
| 663 | 663 | chat_completion_sources.AZURE_OPENAI, |
| 664 | 664 | chat_completion_sources.ZAI, |
| 665 | + chat_completion_sources.SILICONFLOW, | |
| 665 | 666 | ]; |
| 666 | 667 | return supportedSources.includes(oai_settings.chat_completion_source); |
| 667 | 668 | } |
| @@ -207,6 +207,7 @@ export const CHAT_COMPLETION_SOURCES = { | ||
| 207 | 207 | COMETAPI: 'cometapi', |
| 208 | 208 | AZURE_OPENAI: 'azure_openai', |
| 209 | 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 | 76 | const API_FIREWORKS = 'https://api.fireworks.ai/inference/v1'; |
| 77 | 77 | const API_COMETAPI = 'https://api.cometapi.com/v1'; |
| 78 | 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 | 82 | * Gets OpenRouter transforms based on the request. |
| @@ -1570,6 +1571,10 @@ router.post('/status', async function (request, statusResponse) { | ||
| 1570 | 1571 | console.error('Azure OpenAI status check connection error:', error); |
| 1571 | 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 | 1578 | } else { |
| 1574 | 1579 | console.warn('This chat completion source is not supported yet.'); |
| 1575 | 1580 | return statusResponse.status(400).send({ error: true }); |
| @@ -1980,6 +1985,14 @@ router.post('/generate', function (request, response) { | ||
| 1980 | 1985 | if (request.body.json_schema) { |
| 1981 | 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 | 1996 | } else { |
| 1984 | 1997 | console.warn('This chat completion source is not supported yet.'); |
| 1985 | 1998 | return response.status(400).send({ error: true }); |
| @@ -62,6 +62,7 @@ export const SECRET_KEYS = { | ||
| 62 | 62 | COMETAPI: 'api_key_cometapi', |
| 63 | 63 | AZURE_OPENAI: 'api_key_azure_openai', |
| 64 | 64 | ZAI: 'api_key_zai', |
| 65 | + SILICONFLOW: 'api_key_siliconflow', | |
| 65 | 66 | }; |
| 66 | 67 | |
| 67 | 68 | /** |