jdelavande HF Staff commited on
Commit
e122263
·
1 Parent(s): 0921221

improved design and preprompts

Browse files
PREPROMPT.md ADDED
@@ -0,0 +1 @@
 
 
1
+ You are a helpful assistant based on Qwen/Qwen2.5-72B-Instruct; your primary role is to assist users like a normal chatbot—answering questions, helping with tasks, and holding conversations; in addition, if the user asks about the energy indicators displayed below messages (e.g., “Energy”, “≈ phone charge”, “Duration”), you can explain what they mean and how they are calculated; you do not have access to the actual values, but you can clarify that some values are measured using NVIDIA's NVML API on supported GPUs like the T4 (recorded in millijoules, converted to Wh), while others are estimated from inference time using estimated_energy = average_power × inference_time with average_power ≈ 70W; 1 Wh = 3600 J; real-world equivalents help users understand energy use (e.g., phone charge ≈ 19 Wh); users can click on energy values to toggle Wh/J, and on equivalents to cycle through different comparisons; adapt explanations based on user expertise—keep it simple for general audiences and precise for technical questions.
src/lib/components/chat/EnergyDisplay.svelte CHANGED
@@ -10,6 +10,20 @@
10
  function convertToJoules(wh: number): number {
11
  return wh * 3600;
12
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  </script>
14
 
15
  <style>
@@ -22,20 +36,22 @@
22
  transform: scale(1.05);
23
  }
24
  .tooltip {
25
- position: absolute;
26
- top: 100%;
27
- left: 0;
28
- z-index: 10;
29
- margin-top: 0.25rem;
30
- padding: 0.5rem;
31
- background-color: #f3f4f6;
32
- color: #1f2937;
33
- font-size: 0.75rem;
34
- border-radius: 0.25rem;
35
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
36
- width: max-content;
37
- max-width: 400px;
38
- }
 
 
39
  .info-button {
40
  transition: transform 0.2s ease;
41
  cursor: pointer;
@@ -49,24 +65,16 @@
49
  {#if durationSeconds || energyToDisplay}
50
  <div class="mt-2 flex gap-2 items-center relative">
51
 
52
- <!-- Info button -->
53
- <div
54
- class="relative"
55
- on:mouseover={() => (showTooltip = true)}
56
- on:mouseleave={() => (showTooltip = false)}>
57
- <button
58
- class="text-xs text-gray-500 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded-full info-button">
59
-
60
- </button>
61
- </div>
62
 
63
 
64
  <!-- Energy Box -->
65
  {#if energyToDisplay}
66
  <div
67
- class="text-xs text-gray-500 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit energy-box"
68
  on:click={() => (showJoules = !showJoules)}
69
  >
 
70
  {#if showJoules}
71
  {convertToJoules(energyToDisplay).toFixed(2)} J {isEstimated ? "(estimated)" : ""}
72
  {:else}
@@ -75,26 +83,44 @@
75
  </div>
76
  {/if}
77
 
 
 
 
 
 
 
 
 
78
 
79
  <!-- Duration -->
80
  {#if durationSeconds}
81
  <div
82
- class="text-xs text-gray-500 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded w-fit"
83
- >
84
- {durationSeconds} sec
85
  </div>
86
  {/if}
87
 
88
-
 
 
 
 
 
 
 
 
89
  <!-- Tooltip -->
90
  {#if showTooltip}
91
  <div class="tooltip">
92
  {#if isEstimated}
93
- Estimated energy consumption based on the average GPU power and inference duration. Use Qwen/Qwen/Qwen2.5-VL-7B-Instruct model for exact results.
94
  {:else}
95
- Energy consumption measured directly on the GPU during inference.
96
  {/if}
97
  </div>
98
  {/if}
 
 
99
  </div>
100
  {/if}
 
10
  function convertToJoules(wh: number): number {
11
  return wh * 3600;
12
  }
13
+
14
+ let equivalentIndex = $state(0);
15
+
16
+ const equivalents = [
17
+ (wh: number) => `≈ ${((wh / 19) * 100).toFixed(2)}% of a phone charge (19Wh)`,
18
+ (wh: number) => `≈ ${(wh / 0.04).toFixed(2)} minutes of LED bulb (10W)`, // 0.04Wh/min
19
+ (wh: number) => `≈ ${(wh / 1.5).toFixed(2)} seconds of microwave (1000W)`,
20
+ (wh: number) => `≈ ${(wh / 0.2).toFixed(2)} pedal strokes on an e-bike (200W)`,
21
+ (wh: number) => `≈ ${(wh / 12).toFixed(2)} seconds of toaster use (1kW)`
22
+ ];
23
+
24
+ function cycleEquivalent() {
25
+ equivalentIndex = (equivalentIndex + 1) % equivalents.length;
26
+ }
27
  </script>
28
 
29
  <style>
 
36
  transform: scale(1.05);
37
  }
38
  .tooltip {
39
+ position: absolute;
40
+ top: 100%; /* Positionne au-dessus de l’élément parent */
41
+ margin-bottom: 0.5rem; /* Équivalent de mb-2 */
42
+ left: 50%;
43
+ transform: translateX(-50%);
44
+ background-color: #f3f4f6; /* bg-gray-200 */
45
+ color: #1f2937; /* text-gray-800 */
46
+ font-size: 0.75rem; /* text-xs */
47
+ padding: 0.5rem 0.75rem; /* px-3 py-2 */
48
+ border-radius: 0.25rem; /* rounded */
49
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
50
+ 0 4px 6px -4px rgba(0, 0, 0, 0.1); /* shadow-lg */
51
+ z-index: 10;
52
+ width: 16rem; /* w-64 */
53
+ text-align: center;
54
+ }
55
  .info-button {
56
  transition: transform 0.2s ease;
57
  cursor: pointer;
 
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}
 
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 -->
96
  {#if durationSeconds}
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">
116
  {#if isEstimated}
117
+ Estimated energy consumption based on the average GPU power and inference duration for this message. Use Qwen/Qwen/Qwen2.5-VL-7B-Instruct model for exact results.
118
  {:else}
119
+ Energy consumption measured directly on the GPU during inference for this message.
120
  {/if}
121
  </div>
122
  {/if}
123
+ </div>
124
+
125
  </div>
126
  {/if}
src/lib/components/chat/EnergySummary.svelte CHANGED
@@ -6,14 +6,18 @@
6
  0
7
  ));
8
 
9
- const isNotEstimated = $derived(
10
- typeof messages.at(-1)?.metadata?.energy_wh === 'number' &&
11
- messages.at(-1).metadata.energy_wh !== 0);
 
12
 
13
- const phoneChargePercent = $derived(((totalEnergy / 19) * 100).toFixed(2));
 
 
14
 
15
  let showJoules = $state(false);
16
  let equivalentIndex = $state(0);
 
17
 
18
  const equivalents = [
19
  (wh: number) => `≈ ${((wh / 19) * 100).toFixed(2)}% of a phone charge (19Wh)`,
@@ -32,22 +36,70 @@
32
  }
33
  </script>
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  {#if totalEnergy > 0}
36
  <div class="mb-4 flex flex-col sm:flex-row flex-wrap items-center justify-center gap-4 w-full">
37
  <!-- Bloc énergie totale -->
38
- <div class="text-xs text-gray-500 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)}>
39
  Total Energy:
40
  {#if showJoules}
41
  {convertToJoules(totalEnergy).toFixed(2)} J
42
  {:else}
43
  {totalEnergy.toFixed(4)} Wh
44
  {/if}
45
- {#if !isNotEstimated} (estimated) {/if}
46
  </div>
47
 
48
  <!-- Bloc équivalent charge téléphone -->
49
- <div class="text-xs text-gray-500 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}>
50
  {equivalents[equivalentIndex](totalEnergy)}
51
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  </div>
53
  {/if}
 
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)`,
 
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}