jdelavande HF Staff commited on
Commit
caa1814
·
1 Parent(s): 7857e3c

refactor + think bug corrected

Browse files
src/lib/components/chat/ChatInput.svelte CHANGED
@@ -127,9 +127,16 @@
127
  value.trim() !== ""
128
  ) {
129
  event.preventDefault();
130
- const textToSend = thinkingIsOn
131
- ? `${value.trim()} /think`
132
- : `${value.trim()} /no_think`;
 
 
 
 
 
 
 
133
  dispatch("submit", { text: textToSend });
134
  }
135
  }
@@ -160,7 +167,6 @@
160
  );
161
 
162
  let showWebSearch = $derived(!assistant);
163
- //let showWebSearch = $derived(false);
164
  let showImageGen = $derived(modelHasTools && !assistant);
165
  let showFileUpload = $derived((modelIsMultimodal || modelHasTools) && mimeTypes.length > 0);
166
  let showExtraTools = $derived(modelHasTools && !assistant);
 
127
  value.trim() !== ""
128
  ) {
129
  event.preventDefault();
130
+ let textToSend;
131
+ if (showThinking) {
132
+ if (thinkingIsOn) {
133
+ textToSend = `${value.trim()} /think`;
134
+ } else {
135
+ textToSend = `${value.trim()} /no_think`;
136
+ }
137
+ } else {
138
+ textToSend = `${value.trim()}`;
139
+ }
140
  dispatch("submit", { text: textToSend });
141
  }
142
  }
 
167
  );
168
 
169
  let showWebSearch = $derived(!assistant);
 
170
  let showImageGen = $derived(modelHasTools && !assistant);
171
  let showFileUpload = $derived((modelIsMultimodal || modelHasTools) && mimeTypes.length > 0);
172
  let showExtraTools = $derived(modelHasTools && !assistant);
src/lib/components/chat/ChatMessage.svelte CHANGED
@@ -200,10 +200,12 @@
200
  >
201
  <MarkdownRenderer content={message.content} sources={webSearchSources} />
202
  {#if message.metadata?.duration_seconds || message.metadata?.energy_wh_sim}
 
203
  <EnergyDisplay
204
- energyWh={message.metadata?.energy_wh}
205
- energyWhSim={message.metadata?.energy_wh_sim}
206
  durationSeconds={message.metadata?.duration_seconds}
 
207
  />
208
 
209
  {/if}
 
200
  >
201
  <MarkdownRenderer content={message.content} sources={webSearchSources} />
202
  {#if message.metadata?.duration_seconds || message.metadata?.energy_wh_sim}
203
+
204
  <EnergyDisplay
205
+ energyWh={message.metadata?.energy_wh || message.metadata?.energy_wh_sim}
206
+ isEstimated={message.metadata?.energy_wh === undefined}
207
  durationSeconds={message.metadata?.duration_seconds}
208
+ isTotal={false}
209
  />
210
 
211
  {/if}
src/lib/components/chat/ChatWindow.svelte CHANGED
@@ -32,7 +32,7 @@
32
  import UploadedFile from "./UploadedFile.svelte";
33
  import { useSettingsStore } from "$lib/stores/settings";
34
  import ModelSwitch from "./ModelSwitch.svelte";
35
- import EnergySummary from "./EnergySummary.svelte";
36
 
37
  import { fly } from "svelte/transition";
38
  import { cubicInOut } from "svelte/easing";
@@ -78,6 +78,24 @@
78
  );
79
  let thinkingIsOn = $state(false);
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  beforeNavigate(() => {
82
  if (page.params.id) {
83
  isSharedRecently = false;
@@ -386,11 +404,18 @@
386
  <div
387
  class="dark:via-gray-80 pointer-events-none absolute inset-x-0 bottom-0 z-0 mx-auto flex w-full max-w-3xl flex-col items-center justify-center bg-gradient-to-t from-white via-white/80 to-white/0 px-3.5 py-4 dark:border-gray-800 dark:from-gray-900 dark:to-gray-900/0 max-md:border-t max-md:bg-white max-md:dark:bg-gray-900 sm:px-5 md:py-8 xl:max-w-4xl [&>*]:pointer-events-auto"
388
  >
389
- <EnergySummary {messages} />
390
-
391
-
392
- <div class="w-full">
393
  <div class="flex w-full *:mb-3">
 
 
 
 
 
 
 
 
394
  {#if loading}
395
  <StopGeneratingBtn classNames="ml-auto" onClick={() => dispatch("stop")} />
396
  {:else if lastIsError}
 
32
  import UploadedFile from "./UploadedFile.svelte";
33
  import { useSettingsStore } from "$lib/stores/settings";
34
  import ModelSwitch from "./ModelSwitch.svelte";
35
+ import EnergyDisplay from "./EnergyDisplay.svelte";
36
 
37
  import { fly } from "svelte/transition";
38
  import { cubicInOut } from "svelte/easing";
 
78
  );
79
  let thinkingIsOn = $state(false);
80
 
81
+ // Energy display
82
+ let totalEnergyWh = $derived(
83
+ messages.reduce(
84
+ (total: number, msg: any) => total + (msg.metadata?.energy_wh || msg.metadata?.energy_wh_sim || 0),
85
+ 0
86
+ )
87
+ );
88
+ let isEstimated = $derived(
89
+ messages.some((msg: any) => msg.metadata?.energy_wh === undefined && msg.from === "assistant")
90
+ );
91
+ console.log("messages", messages);
92
+ let totalDurationSeconds = $derived(
93
+ messages.reduce(
94
+ (total: number, msg: any) => total + (msg.metadata?.duration_seconds || 0),
95
+ 0
96
+ )
97
+ );
98
+
99
  beforeNavigate(() => {
100
  if (page.params.id) {
101
  isSharedRecently = false;
 
404
  <div
405
  class="dark:via-gray-80 pointer-events-none absolute inset-x-0 bottom-0 z-0 mx-auto flex w-full max-w-3xl flex-col items-center justify-center bg-gradient-to-t from-white via-white/80 to-white/0 px-3.5 py-4 dark:border-gray-800 dark:from-gray-900 dark:to-gray-900/0 max-md:border-t max-md:bg-white max-md:dark:bg-gray-900 sm:px-5 md:py-8 xl:max-w-4xl [&>*]:pointer-events-auto"
406
  >
407
+
408
+ <div class="w-full">
409
+
 
410
  <div class="flex w-full *:mb-3">
411
+
412
+ <!-- <EnergySummary {messages} /> -->
413
+ <EnergyDisplay
414
+ energyWh={totalEnergyWh}
415
+ isEstimated={isEstimated}
416
+ durationSeconds={totalDurationSeconds}
417
+ isTotal={true}/>
418
+
419
  {#if loading}
420
  <StopGeneratingBtn classNames="ml-auto" onClick={() => dispatch("stop")} />
421
  {:else if lastIsError}
src/lib/components/chat/EnergyDisplay.svelte CHANGED
@@ -1,11 +1,9 @@
1
  <script lang="ts">
2
- let { energyWh, energyWhSim, durationSeconds } = $props();
3
 
4
  let showJoules = $state(false);
5
  let showTooltip = $state(false);
6
 
7
- const isEstimated = $derived(!(typeof energyWh === 'number' && energyWh !== 0));
8
- const energyToDisplay = $derived(isEstimated ? energyWhSim : energyWh);
9
 
10
  function convertToJoules(wh: number): number {
11
  return wh * 3600;
@@ -62,34 +60,38 @@
62
  }
63
  </style>
64
 
65
- {#if durationSeconds || energyToDisplay}
66
  <div class="mt-2 flex gap-2 items-center relative">
67
 
68
-
69
-
70
-
71
  <!-- Energy Box -->
72
- {#if energyToDisplay}
73
- <div
 
 
74
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit energy-box"
75
- on:click={() => (showJoules = !showJoules)}
76
  >
77
- Energy:
 
 
 
78
  {#if showJoules}
79
- {convertToJoules(energyToDisplay).toFixed(2)} J {isEstimated ? "(estimated)" : ""}
80
  {:else}
81
- {energyToDisplay.toFixed(4)} Wh {isEstimated ? "(estimated)" : ""}
82
  {/if}
83
- </div>
84
  {/if}
85
 
86
  <!-- Equivalent -->
87
- <div
 
 
88
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit cursor-pointer transform hover:scale-105 transition duration-150 ease-in-out"
89
- on:click={cycleEquivalent}
90
  >
91
- {equivalents[equivalentIndex](energyToDisplay)}
92
- </div>
93
 
94
 
95
  <!-- Duration -->
@@ -97,19 +99,27 @@
97
  <div
98
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit"
99
  >
100
- Duration: {durationSeconds.toFixed(3)} sec
 
 
 
 
101
  </div>
102
  {/if}
103
 
104
  <!-- Info button -->
105
- <div
 
 
 
106
  class="relative"
107
- on:mouseover={() => (showTooltip = true)}
108
- on:mouseleave={() => (showTooltip = false)}>
109
- <button
 
110
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full info-button">
111
 
112
- </button>
113
  <!-- Tooltip -->
114
  {#if showTooltip}
115
  <div class="tooltip">
@@ -120,7 +130,8 @@
120
  {/if}
121
  </div>
122
  {/if}
123
- </div>
 
124
 
125
  </div>
126
  {/if}
 
1
  <script lang="ts">
2
+ let { energyWh, isEstimated, durationSeconds, isTotal } = $props();
3
 
4
  let showJoules = $state(false);
5
  let showTooltip = $state(false);
6
 
 
 
7
 
8
  function convertToJoules(wh: number): number {
9
  return wh * 3600;
 
60
  }
61
  </style>
62
 
63
+ {#if durationSeconds || energyWh}
64
  <div class="mt-2 flex gap-2 items-center relative">
65
 
 
 
 
66
  <!-- Energy Box -->
67
+ {#if energyWh}
68
+ <button
69
+ tabindex="0"
70
+ aria-label="Energy consumption"
71
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit energy-box"
72
+ onclick={() => (showJoules = !showJoules)}
73
  >
74
+ <span class="hidden sm:inline">
75
+ {isTotal ? "Total " : ""}
76
+ Energy:
77
+ </span>
78
  {#if showJoules}
79
+ {convertToJoules(energyWh).toFixed(2)} J {isEstimated ? "(estimated)" : ""}
80
  {:else}
81
+ {energyWh.toFixed(4)} Wh {isEstimated ? "(estimated)" : ""}
82
  {/if}
83
+ </button>
84
  {/if}
85
 
86
  <!-- Equivalent -->
87
+ <button
88
+ tabindex="0"
89
+ aria-label="Energy consumption equivalent"
90
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit cursor-pointer transform hover:scale-105 transition duration-150 ease-in-out"
91
+ onclick={cycleEquivalent}
92
  >
93
+ {equivalents[equivalentIndex](energyWh)}
94
+ </button>
95
 
96
 
97
  <!-- Duration -->
 
99
  <div
100
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit"
101
  >
102
+ <span class="hidden sm:inline">
103
+ {isTotal ? "Total " : ""}
104
+ Duration:
105
+ </span>
106
+ {durationSeconds.toFixed(3)} s
107
  </div>
108
  {/if}
109
 
110
  <!-- Info button -->
111
+ <span class="hidden sm:inline">
112
+ <button
113
+ tabindex="0"
114
+ aria-label="Energy consumption info"
115
  class="relative"
116
+ onmouseover={() => (showTooltip = true)}
117
+ onmouseleave={() => (showTooltip = false)}
118
+ onfocus={() => (showTooltip = true)}>
119
+ <div
120
  class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full info-button">
121
 
122
+ </div>
123
  <!-- Tooltip -->
124
  {#if showTooltip}
125
  <div class="tooltip">
 
130
  {/if}
131
  </div>
132
  {/if}
133
+ </button>
134
+ </span>
135
 
136
  </div>
137
  {/if}
src/lib/components/chat/EnergySummary.svelte DELETED
@@ -1,105 +0,0 @@
1
- <script lang="ts">
2
- let { messages } = $props();
3
-
4
- const totalEnergy = $derived(messages.reduce(
5
- (total: number, msg: any) => total + (msg.metadata?.energy_wh || msg.metadata?.energy_wh_sim || 0),
6
- 0
7
- ));
8
-
9
- const totalDuration = $derived(messages.reduce(
10
- (total: number, msg: any) => total + (msg.metadata?.duration_seconds || 0),
11
- 0
12
- ));
13
-
14
- const isEstimated = $derived(!(
15
- typeof messages.at(-1)?.metadata?.energy_wh === 'number' &&
16
- messages.at(-1).metadata.energy_wh !== 0));
17
-
18
- let showJoules = $state(false);
19
- let equivalentIndex = $state(0);
20
- let showTooltip = $state(false);
21
-
22
- const equivalents = [
23
- (wh: number) => `≈ ${((wh / 19) * 100).toFixed(2)}% of a phone charge (19Wh)`,
24
- (wh: number) => `≈ ${(wh / 0.04).toFixed(2)} minutes of LED bulb (10W)`, // 0.04Wh/min
25
- (wh: number) => `≈ ${(wh / 1.5).toFixed(2)} seconds of microwave (1000W)`,
26
- (wh: number) => `≈ ${(wh / 0.2).toFixed(2)} pedal strokes on an e-bike (200W)`,
27
- (wh: number) => `≈ ${(wh / 12).toFixed(2)} seconds of toaster use (1kW)`
28
- ];
29
-
30
- function cycleEquivalent() {
31
- equivalentIndex = (equivalentIndex + 1) % equivalents.length;
32
- }
33
-
34
- function convertToJoules(wh: number): number {
35
- return wh * 3600;
36
- }
37
- </script>
38
-
39
- <style>
40
- .tooltip {
41
- position: absolute;
42
- bottom: 100%; /* Positionne au-dessus de l’élément parent */
43
- margin-bottom: 0.5rem; /* Équivalent de mb-2 */
44
- left: 50%;
45
- transform: translateX(-50%);
46
- background-color: #f3f4f6; /* bg-gray-200 */
47
- color: #1f2937; /* text-gray-800 */
48
- font-size: 0.75rem; /* text-xs */
49
- padding: 0.5rem 0.75rem; /* px-3 py-2 */
50
- border-radius: 0.25rem; /* rounded */
51
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
52
- 0 4px 6px -4px rgba(0, 0, 0, 0.1); /* shadow-lg */
53
- z-index: 10;
54
- width: 16rem; /* w-64 */
55
- text-align: center;
56
- }
57
-
58
- </style>
59
-
60
- {#if totalEnergy > 0}
61
- <div class="mb-4 flex flex-col sm:flex-row flex-wrap items-center justify-center gap-4 w-full">
62
- <!-- Bloc énergie totale -->
63
- <div class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded transform hover:scale-105 transition duration-150 ease-in-out cursor-pointer" on:click={() => (showJoules = !showJoules)}>
64
- Total Energy:
65
- {#if showJoules}
66
- {convertToJoules(totalEnergy).toFixed(2)} J
67
- {:else}
68
- {totalEnergy.toFixed(4)} Wh
69
- {/if}
70
- {#if isEstimated} (estimated) {/if}
71
- </div>
72
-
73
- <!-- Bloc équivalent charge téléphone -->
74
- <div class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded cursor-pointer transform hover:scale-105 transition duration-150 ease-in-out" on:click={cycleEquivalent}>
75
- {equivalents[equivalentIndex](totalEnergy)}
76
- </div>
77
-
78
- <!-- Bloc d urée -->
79
- <div class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded">
80
- Total Duration: {totalDuration.toFixed(3)} sec
81
- </div>
82
-
83
- <!-- info button -->
84
- <div
85
- class="relative"
86
- on:mouseover={() => (showTooltip = true)}
87
- on:mouseleave={() => (showTooltip = false)}>
88
- <button
89
- class="text-xs text-gray-600 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full info-button">
90
-
91
- </button>
92
-
93
- <!-- Tooltip -->
94
- {#if showTooltip}
95
- <div class="tooltip">
96
- {#if isEstimated}
97
- Estimated energy consumption based on the average GPU power and inference duration for all messages. Use Qwen/Qwen/Qwen2.5-VL-7B-Instruct model for exact results.
98
- {:else}
99
- Energy consumption measured directly on the GPU during inference for all messages.
100
- {/if}
101
- </div>
102
- {/if}
103
- </div>
104
- </div>
105
- {/if}