diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 442dfba76..58a5cdeae 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -785,6 +785,11 @@ async def process_chat_payload(request, form_data, user, metadata, model): ), form_data["messages"], ) + if "thinking" in features: + form_data["enable_thinking"] = features["thinking"] + form_data["chat_template_kwargs"] = { + "enable_thinking": features["thinking"] + } tool_ids = form_data.pop("tool_ids", None) files = form_data.pop("files", None) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 34abc20e8..776555227 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -121,8 +121,8 @@ let selectedToolIds = []; let imageGenerationEnabled = false; let webSearchEnabled = false; - let thinkingEnabled = false; let codeInterpreterEnabled = false; + let thinkingEnabled = false; let chat = null; let tags = []; @@ -148,6 +148,7 @@ files = []; selectedToolIds = []; webSearchEnabled = false; + webSearchEnabled = false; imageGenerationEnabled = false; if (localStorage.getItem(`chat-input${chatIdProp ? `-${chatIdProp}` : ''}`)) { @@ -161,6 +162,7 @@ files = input.files; selectedToolIds = input.selectedToolIds; webSearchEnabled = input.webSearchEnabled; + thinkingEnabled = input.thinkingEnabled; imageGenerationEnabled = input.imageGenerationEnabled; codeInterpreterEnabled = input.codeInterpreterEnabled; } @@ -426,6 +428,7 @@ files = []; selectedToolIds = []; webSearchEnabled = false; + thinkingEnabled = false; imageGenerationEnabled = false; codeInterpreterEnabled = false; @@ -441,6 +444,7 @@ webSearchEnabled = input.webSearchEnabled; imageGenerationEnabled = input.imageGenerationEnabled; codeInterpreterEnabled = input.codeInterpreterEnabled; + thinkingEnabled = input.thinkingEnabled; } } catch (e) {} } @@ -749,6 +753,10 @@ webSearchEnabled = true; } + if ($page.url.searchParams.get('thinking') === 'true') { + thinkingEnabled = true; + } + if ($page.url.searchParams.get('image-generation') === 'true') { imageGenerationEnabled = true; } @@ -1636,7 +1644,8 @@ $config?.features?.enable_web_search && ($user?.role === 'admin' || $user?.permissions?.features?.web_search) ? webSearchEnabled || ($settings?.webSearch ?? false) === 'always' - : false + : false, + thinking: thinkingEnabled }, variables: { ...getPromptVariables( @@ -2062,6 +2071,7 @@ bind:imageGenerationEnabled bind:codeInterpreterEnabled bind:webSearchEnabled + bind:thinkingEnabled bind:atSelectedModel toolServers={$toolServers} transparentBackground={$settings?.backgroundImageUrl ?? false} @@ -2118,6 +2128,7 @@ bind:imageGenerationEnabled bind:codeInterpreterEnabled bind:webSearchEnabled + bind:thinkingEnabled bind:atSelectedModel transparentBackground={$settings?.backgroundImageUrl ?? false} toolServers={$toolServers} diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 9e5593ea9..2b1fcd9b7 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -47,6 +47,7 @@ import XMark from '../icons/XMark.svelte'; import Headphone from '../icons/Headphone.svelte'; import GlobeAlt from '../icons/GlobeAlt.svelte'; + import Thinking from "../icons/Thinking.svelte"; import PhotoSolid from '../icons/PhotoSolid.svelte'; import Photo from '../icons/Photo.svelte'; import CommandLine from '../icons/CommandLine.svelte'; @@ -83,6 +84,7 @@ export let imageGenerationEnabled = false; export let webSearchEnabled = false; export let codeInterpreterEnabled = false; + export let thinkingEnabled = false; $: onChange({ prompt, @@ -90,7 +92,8 @@ selectedToolIds, imageGenerationEnabled, webSearchEnabled, - codeInterpreterEnabled + codeInterpreterEnabled, + thinkingEnabled }); let showTools = false; @@ -117,6 +120,10 @@ (model) => $models.find((m) => m.id === model)?.info?.meta?.capabilities?.vision ?? true ); + let switchThinkingCapableModels = []; + $: switchThinkingCapableModels = $models.filter((model) => model.info?.meta?.capabilities?.switch_thinking ?? false) + .map((model) => model.id) + const scrollToBottom = () => { const element = document.getElementById('messages-container'); element.scrollTo({ @@ -773,6 +780,7 @@ selectedToolIds = []; webSearchEnabled = false; imageGenerationEnabled = false; + thinkingEnabled = false; } }} on:paste={async (e) => { @@ -980,6 +988,7 @@ selectedToolIds = []; webSearchEnabled = false; imageGenerationEnabled = false; + thinkingEnabled = false; } }} rows="1" @@ -1127,6 +1136,24 @@ {/if} {#if $_user} + {#if selectedModels.length > 0 && selectedModels.some((model) => switchThinkingCapableModels.includes(model))} + + + + {/if} + {#if $config?.features?.enable_web_search && ($_user.role === 'admin' || $_user?.permissions?.features?.web_search)}