]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
070fd3ac66746590b90b2aa9b08b8f109f4f492e
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 import { Lightbulb, LightbulbOff, Check, Info } from '@lucide/svelte';
3 import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
4 import * as Tooltip from '$lib/components/ui/tooltip';
5 import { ReasoningEffort } from '$lib/enums';
6 import { REASONING_EFFORT_TOKENS } from '$lib/constants/reasoning-effort-tokens';
7 import { REASONING_EFFORT_LEVELS } from '$lib/constants/reasoning-effort';
8 import type { ReasoningEffortLevel } from '$lib/types';
9 import {
10 modelsStore,
11 checkModelSupportsThinking,
12 supportsThinking,
13 propsCacheVersion,
14 loadedModelIds
15 } from '$lib/stores/models.svelte';
16 import { chatStore } from '$lib/stores/chat.svelte';
17 import { conversationsStore, activeMessages } from '$lib/stores/conversations.svelte';
18 import { isRouterMode } from '$lib/stores/server.svelte';
19 import type { DatabaseMessage } from '$lib/types/database';
20
21 let subOpen = $state(false);
22
23 let conversationModel = $derived(
24 chatStore.getConversationModel(activeMessages() as DatabaseMessage[])
25 );
26
27 let modelSupportsThinkingFromMessages = $derived.by(() => {
28 const modelId = isRouterMode() ? modelsStore.selectedModelName || conversationModel : null;
29 if (!modelId) return false;
30
31 const messages = conversationsStore.activeMessages;
32
33 return messages.some(
34 (m) => m.role === 'assistant' && m.model === modelId && !!m.reasoningContent
35 );
36 });
37
38 let modelSupportsThinking = $derived.by(() => {
39 loadedModelIds();
40 propsCacheVersion();
41
42 if (isRouterMode()) {
43 const modelId = modelsStore.selectedModelName || conversationModel;
44 return checkModelSupportsThinking(modelId ?? '') || modelSupportsThinkingFromMessages;
45 }
46
47 return supportsThinking() || modelSupportsThinkingFromMessages;
48 });
49
50 let thinkingEnabled = $derived(conversationsStore.getThinkingEnabled());
51 let currentEffort = $derived(conversationsStore.getReasoningEffort());
52 let isOff = $derived(!thinkingEnabled);
53
54 function isSelected(item: ReasoningEffortLevel): boolean {
55 if (item.isOff) return isOff;
56 return thinkingEnabled && currentEffort === item.value;
57 }
58
59 function handleSelection(item: ReasoningEffortLevel) {
60 if (item.isOff) {
61 conversationsStore.setThinkingEnabled(false);
62 } else {
63 conversationsStore.setThinkingEnabled(true);
64 conversationsStore.setReasoningEffort(item.value as ReasoningEffort);
65 }
66 subOpen = false;
67 }
68 </script>
69
70 {#if modelSupportsThinking}
71 <DropdownMenu.Sub bind:open={subOpen}>
72 <DropdownMenu.SubTrigger class="flex cursor-pointer items-center gap-2">
73 {#if thinkingEnabled}
74 <Lightbulb class="h-4 w-4 shrink-0 text-amber-400" />
75 {:else}
76 <LightbulbOff class="h-4 w-4 shrink-0 text-muted-foreground" />
77 {/if}
78
79 <span class="text-sm inline-flex gap-2 {!thinkingEnabled ? 'text-muted-foreground' : ''}">
80 Reasoning
81
82 <span class="capitalize text-muted-foreground">
83 {thinkingEnabled ? currentEffort : 'off'}
84 </span>
85 </span>
86 </DropdownMenu.SubTrigger>
87
88 <DropdownMenu.SubContent
89 class="w-60 bg-popover p-1.5 text-popover-foreground shadow-md outline-none"
90 >
91 {#each REASONING_EFFORT_LEVELS as level (level.value)}
92 <button
93 type="button"
94 class="flex w-full cursor-pointer items-center gap-3 rounded-md px-2 py-1.75 text-left text-sm transition-colors hover:bg-accent"
95 class:bg-accent={isSelected(level)}
96 onclick={() => handleSelection(level)}
97 >
98 {#if isSelected(level)}
99 <Check class="h-4 w-4 shrink-0 text-foreground" />
100 {:else}
101 <div class="h-4 w-4 shrink-0"></div>
102 {/if}
103
104 <span class="flex-1">{level.label}</span>
105
106 {#if !level.isOff}
107 <span class="text-[11px] text-muted-foreground opacity-60">
108 {REASONING_EFFORT_TOKENS[level.value] === -1
109 ? 'Unlimited'
110 : `Max ${REASONING_EFFORT_TOKENS[level.value].toLocaleString()} tokens`}
111 </span>
112 {/if}
113
114 {#if level.hasInfo}
115 <Tooltip.Root>
116 <Tooltip.Trigger>
117 <Info class="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
118 </Tooltip.Trigger>
119 <Tooltip.Content side="left">
120 <p>Maximum reasoning effort with extended context usage</p>
121 </Tooltip.Content>
122 </Tooltip.Root>
123 {/if}
124 </button>
125 {/each}
126 </DropdownMenu.SubContent>
127 </DropdownMenu.Sub>
128 {/if}