Files changed (2) hide show
  1. README.md +2 -2
  2. index.html +28 -170
README.md CHANGED
@@ -1,11 +1,11 @@
1
  ---
2
- title: Course_Demo
3
  emoji: 👁
4
  colorFrom: purple
5
  colorTo: purple
6
  sdk: static
7
  pinned: false
8
- short_description: Course Demo
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Demo
3
  emoji: 👁
4
  colorFrom: purple
5
  colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ short_description: demo
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,71 +1,19 @@
1
  <!DOCTYPE html>
2
  <html lang="zh-Hant">
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Gemma 多模態影像分析助手</title>
7
- <script>
8
- (function () {
9
- var theme;
10
- try {
11
- theme = localStorage.getItem('theme');
12
- } catch (e) {}
13
- if (!theme) {
14
- theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
15
- }
16
- document.documentElement.dataset.theme = theme;
17
- })();
18
- </script>
19
  <style>
20
- :root,
21
- :root[data-theme="light"] {
22
- --bg-color: #ffffff;
23
- --bg-glow-1: rgba(124, 58, 237, 0.07);
24
- --bg-glow-2: rgba(8, 145, 178, 0.07);
25
- --card-bg: rgba(255, 255, 255, 0.9);
26
- --card-border: rgba(15, 23, 42, 0.08);
27
- --border-glow: rgba(8, 145, 178, 0.35);
28
- --neon-cyan: #0891b2;
29
- --neon-purple: #7c3aed;
30
- --text-main: #0f172a;
31
- --text-muted: #64748b;
32
- --input-bg: #f8fafc;
33
- --input-border: rgba(15, 23, 42, 0.12);
34
- --result-bg: #f8fafc;
35
- --result-text: #1e293b;
36
- --result-shadow: inset 0 1px 3px rgba(15, 23, 42, 0.06);
37
- --card-shadow: 0 10px 30px rgba(15, 23, 42, 0.08), inset 0 0 15px rgba(124, 58, 237, 0.03);
38
- --preview-shadow: 0 4px 12px rgba(15, 23, 42, 0.15);
39
- --focus-shadow: rgba(8, 145, 178, 0.25);
40
- --btn-text: #ffffff;
41
- --btn-disabled-bg: #e2e8f0;
42
- --btn-disabled-text: #94a3b8;
43
- --scanline-opacity: 0.6;
44
- }
45
-
46
- :root[data-theme="dark"] {
47
  --bg-color: #0b0f19;
48
- --bg-glow-1: rgba(176, 38, 255, 0.1);
49
- --bg-glow-2: rgba(0, 240, 255, 0.1);
50
- --card-bg: rgba(17, 24, 39, 0.75);
51
- --card-border: rgba(0, 240, 255, 0.3);
52
  --border-glow: rgba(0, 240, 255, 0.3);
53
  --neon-cyan: #00f0ff;
54
  --neon-purple: #b026ff;
55
  --text-main: #f3f4f6;
56
  --text-muted: #9ca3af;
57
- --input-bg: rgba(3, 7, 18, 0.6);
58
- --input-border: rgba(255, 255, 255, 0.1);
59
- --result-bg: rgba(3, 7, 18, 0.8);
60
- --result-text: #e5e7eb;
61
- --result-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.4);
62
- --card-shadow: 0 0 30px rgba(0, 240, 255, 0.1), inset 0 0 15px rgba(176, 38, 255, 0.05);
63
- --preview-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
64
- --focus-shadow: rgba(0, 240, 255, 0.3);
65
- --btn-text: #000000;
66
- --btn-disabled-bg: #374151;
67
- --btn-disabled-text: #9ca3af;
68
- --scanline-opacity: 1;
69
  }
70
 
71
  body {
@@ -74,12 +22,11 @@
74
  margin: 40px auto;
75
  padding: 20px;
76
  background-color: var(--bg-color);
77
- background-image:
78
- radial-gradient(circle at 10% 20%, var(--bg-glow-1) 0%, transparent 40%),
79
- radial-gradient(circle at 90% 80%, var(--bg-glow-2) 0%, transparent 40%);
80
  color: var(--text-main);
81
  min-height: 100vh;
82
- transition: background-color 0.35s ease, color 0.35s ease;
83
  }
84
 
85
  .card {
@@ -88,11 +35,10 @@
88
  -webkit-backdrop-filter: blur(16px);
89
  padding: 30px;
90
  border-radius: 16px;
91
- border: 1px solid var(--card-border);
92
- box-shadow: var(--card-shadow);
93
  position: relative;
94
  overflow: hidden;
95
- transition: background-color 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
96
  }
97
 
98
  .card::before {
@@ -103,7 +49,6 @@
103
  width: 100%;
104
  height: 2px;
105
  background: linear-gradient(90deg, transparent, var(--neon-cyan), transparent);
106
- opacity: var(--scanline-opacity);
107
  animation: scanline 4s linear infinite;
108
  }
109
 
@@ -117,7 +62,6 @@
117
  font-size: 1.8rem;
118
  background: linear-gradient(135deg, var(--neon-cyan), var(--neon-purple));
119
  -webkit-background-clip: text;
120
- background-clip: text;
121
  -webkit-text-fill-color: transparent;
122
  letter-spacing: 0.5px;
123
  }
@@ -147,23 +91,23 @@
147
  textarea {
148
  width: 100%;
149
  padding: 12px 14px;
150
- background: var(--input-bg);
151
- border: 1px solid var(--input-border);
152
  border-radius: 8px;
153
  box-sizing: border-box;
154
  color: var(--text-main);
155
  font-size: 0.95rem;
156
- transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
157
  }
158
 
159
  input:focus {
160
  outline: none;
161
  border-color: var(--neon-cyan);
162
- box-shadow: 0 0 10px var(--focus-shadow);
163
  }
164
 
165
  input[type="file"]::file-selector-button {
166
- background: color-mix(in srgb, var(--neon-cyan) 12%, transparent);
167
  color: var(--neon-cyan);
168
  border: 1px solid var(--neon-cyan);
169
  padding: 6px 12px;
@@ -174,12 +118,12 @@
174
 
175
  input[type="file"]::file-selector-button:hover {
176
  background: var(--neon-cyan);
177
- color: var(--btn-text);
178
  }
179
 
180
  button {
181
  background: linear-gradient(135deg, var(--neon-cyan), var(--neon-purple));
182
- color: var(--btn-text);
183
  border: none;
184
  padding: 12px 20px;
185
  font-weight: 700;
@@ -199,53 +143,13 @@
199
  }
200
 
201
  button:disabled {
202
- background: var(--btn-disabled-bg);
203
- color: var(--btn-disabled-text);
204
  cursor: not-allowed;
205
  box-shadow: none;
206
  transform: none;
207
  }
208
 
209
- .theme-toggle {
210
- position: fixed;
211
- top: 20px;
212
- right: 20px;
213
- z-index: 10;
214
- width: auto;
215
- display: inline-flex;
216
- align-items: center;
217
- gap: 6px;
218
- padding: 8px 14px;
219
- border-radius: 999px;
220
- border: 1px solid var(--input-border);
221
- background: var(--card-bg);
222
- color: var(--text-muted);
223
- font-size: 0.8rem;
224
- font-weight: 600;
225
- letter-spacing: 0;
226
- box-shadow: 0 4px 14px rgba(15, 23, 42, 0.12);
227
- backdrop-filter: blur(8px);
228
- -webkit-backdrop-filter: blur(8px);
229
- }
230
-
231
- .theme-toggle:hover {
232
- opacity: 1;
233
- transform: none;
234
- color: var(--text-main);
235
- box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
236
- }
237
-
238
- .theme-toggle svg {
239
- width: 16px;
240
- height: 16px;
241
- flex-shrink: 0;
242
- }
243
-
244
- :root[data-theme="light"] .icon-sun,
245
- :root[data-theme="dark"] .icon-moon {
246
- display: none;
247
- }
248
-
249
  #preview-container {
250
  margin-top: 12px;
251
  text-align: center;
@@ -257,61 +161,33 @@
257
  border-radius: 8px;
258
  display: none;
259
  border: 1px solid var(--border-glow);
260
- box-shadow: var(--preview-shadow);
261
  }
262
 
263
  #result {
264
  margin-top: 12px;
265
  padding: 16px;
266
- background: var(--result-bg);
267
- border: 1px solid var(--input-border);
268
  border-radius: 8px;
269
  white-space: pre-wrap;
270
  min-height: 60px;
271
  font-size: 0.95rem;
272
- color: var(--result-text);
273
- box-shadow: var(--result-shadow);
274
- transition: background-color 0.35s ease, color 0.35s ease, border-color 0.35s ease;
275
- }
276
-
277
- @media (max-width: 520px) {
278
- body {
279
- margin: 20px auto;
280
- padding: 16px;
281
- }
282
-
283
- .theme-toggle {
284
- top: 12px;
285
- right: 12px;
286
- }
287
-
288
- .card {
289
- padding: 22px;
290
- }
291
  }
292
  </style>
293
  </head>
294
  <body>
295
- <button class="theme-toggle" id="themeToggle" type="button" aria-label="切換背景樣式" onclick="toggleTheme()">
296
- <svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true">
297
- <circle cx="12" cy="12" r="4"></circle>
298
- <path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"></path>
299
- </svg>
300
- <svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
301
- <path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"></path>
302
- </svg>
303
- <span id="themeLabel">深色</span>
304
- </button>
305
-
306
  <div class="card">
307
  <h2>Gemma 多模態影像分析助手</h2>
308
  <p>透過 Hugging Face Router 呼叫 gemma-4-31B-it 模��進行高精度影像辨識與分析。</p>
309
-
310
  <div class="form-group">
311
  <label for="apiKey">Hugging Face Token (HF_TOKEN)</label>
312
  <input type="password" id="apiKey" placeholder="請輸入您的 HF_TOKEN">
313
  </div>
314
-
315
  <div class="form-group">
316
  <label for="imageInput">上傳圖片</label>
317
  <input type="file" id="imageInput" accept="image/*" onchange="previewSelectedImage(event)">
@@ -319,14 +195,14 @@
319
  <img id="imagePreview" alt="圖片預覽">
320
  </div>
321
  </div>
322
-
323
  <div class="form-group">
324
  <label for="promptInput">輸入提示詞 (Prompt)</label>
325
  <input type="text" id="promptInput" value="Describe this image in one sentence in chinese">
326
  </div>
327
-
328
  <button id="submitBtn" onclick="analyzeImage()">啟動分析</button>
329
-
330
  <div class="form-group" style="margin-top: 24px;">
331
  <label>模型回應</label>
332
  <div id="result">系統待命,尚未開始分析...</div>
@@ -334,24 +210,6 @@
334
  </div>
335
 
336
  <script>
337
- function toggleTheme() {
338
- const root = document.documentElement;
339
- const next = root.dataset.theme === 'dark' ? 'light' : 'dark';
340
- root.dataset.theme = next;
341
- try {
342
- localStorage.setItem('theme', next);
343
- } catch (e) {}
344
- updateThemeLabel();
345
- }
346
-
347
- function updateThemeLabel() {
348
- const isDark = document.documentElement.dataset.theme === 'dark';
349
- document.getElementById('themeLabel').textContent = isDark ? '淺色' : '深色';
350
- document.getElementById('themeToggle').setAttribute('aria-label', isDark ? '切換為淺色背景' : '切換為深色背景');
351
- }
352
-
353
- updateThemeLabel();
354
-
355
  // 選擇圖片時即時顯示預覽
356
  function previewSelectedImage(event) {
357
  const file = event.target.files[0];
@@ -461,4 +319,4 @@
461
  }
462
  </script>
463
  </body>
464
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="zh-Hant">
3
+ //
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>Gemma 多模態影像分析助手</title>
 
 
 
 
 
 
 
 
 
 
 
 
8
  <style>
9
+ :root {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  --bg-color: #0b0f19;
11
+ --card-bg: rgba(17, 24, 39, 0.75);
 
 
 
12
  --border-glow: rgba(0, 240, 255, 0.3);
13
  --neon-cyan: #00f0ff;
14
  --neon-purple: #b026ff;
15
  --text-main: #f3f4f6;
16
  --text-muted: #9ca3af;
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
  body {
 
22
  margin: 40px auto;
23
  padding: 20px;
24
  background-color: var(--bg-color);
25
+ background-image:
26
+ radial-gradient(circle at 10% 20%, rgba(176, 38, 255, 0.1) 0%, transparent 40%),
27
+ radial-gradient(circle at 90% 80%, rgba(0, 240, 255, 0.1) 0%, transparent 40%);
28
  color: var(--text-main);
29
  min-height: 100vh;
 
30
  }
31
 
32
  .card {
 
35
  -webkit-backdrop-filter: blur(16px);
36
  padding: 30px;
37
  border-radius: 16px;
38
+ border: 1px solid var(--border-glow);
39
+ box-shadow: 0 0 30px rgba(0, 240, 255, 0.1), inset 0 0 15px rgba(176, 38, 255, 0.05);
40
  position: relative;
41
  overflow: hidden;
 
42
  }
43
 
44
  .card::before {
 
49
  width: 100%;
50
  height: 2px;
51
  background: linear-gradient(90deg, transparent, var(--neon-cyan), transparent);
 
52
  animation: scanline 4s linear infinite;
53
  }
54
 
 
62
  font-size: 1.8rem;
63
  background: linear-gradient(135deg, var(--neon-cyan), var(--neon-purple));
64
  -webkit-background-clip: text;
 
65
  -webkit-text-fill-color: transparent;
66
  letter-spacing: 0.5px;
67
  }
 
91
  textarea {
92
  width: 100%;
93
  padding: 12px 14px;
94
+ background: rgba(3, 7, 18, 0.6);
95
+ border: 1px solid rgba(255, 255, 255, 0.1);
96
  border-radius: 8px;
97
  box-sizing: border-box;
98
  color: var(--text-main);
99
  font-size: 0.95rem;
100
+ transition: all 0.3s ease;
101
  }
102
 
103
  input:focus {
104
  outline: none;
105
  border-color: var(--neon-cyan);
106
+ box-shadow: 0 0 10px rgba(0, 240, 255, 0.3);
107
  }
108
 
109
  input[type="file"]::file-selector-button {
110
+ background: rgba(0, 240, 255, 0.1);
111
  color: var(--neon-cyan);
112
  border: 1px solid var(--neon-cyan);
113
  padding: 6px 12px;
 
118
 
119
  input[type="file"]::file-selector-button:hover {
120
  background: var(--neon-cyan);
121
+ color: #000;
122
  }
123
 
124
  button {
125
  background: linear-gradient(135deg, var(--neon-cyan), var(--neon-purple));
126
+ color: #000;
127
  border: none;
128
  padding: 12px 20px;
129
  font-weight: 700;
 
143
  }
144
 
145
  button:disabled {
146
+ background: #374151;
147
+ color: #9ca3af;
148
  cursor: not-allowed;
149
  box-shadow: none;
150
  transform: none;
151
  }
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  #preview-container {
154
  margin-top: 12px;
155
  text-align: center;
 
161
  border-radius: 8px;
162
  display: none;
163
  border: 1px solid var(--border-glow);
164
+ box-shadow: 0 4px 12px rgba(0,0,0,0.5);
165
  }
166
 
167
  #result {
168
  margin-top: 12px;
169
  padding: 16px;
170
+ background: rgba(3, 7, 18, 0.8);
171
+ border: 1px solid rgba(255, 255, 255, 0.08);
172
  border-radius: 8px;
173
  white-space: pre-wrap;
174
  min-height: 60px;
175
  font-size: 0.95rem;
176
+ color: #e5e7eb;
177
+ box-shadow: inset 0 2px 4px rgba(0,0,0,0.4);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  }
179
  </style>
180
  </head>
181
  <body>
 
 
 
 
 
 
 
 
 
 
 
182
  <div class="card">
183
  <h2>Gemma 多模態影像分析助手</h2>
184
  <p>透過 Hugging Face Router 呼叫 gemma-4-31B-it 模��進行高精度影像辨識與分析。</p>
185
+
186
  <div class="form-group">
187
  <label for="apiKey">Hugging Face Token (HF_TOKEN)</label>
188
  <input type="password" id="apiKey" placeholder="請輸入您的 HF_TOKEN">
189
  </div>
190
+
191
  <div class="form-group">
192
  <label for="imageInput">上傳圖片</label>
193
  <input type="file" id="imageInput" accept="image/*" onchange="previewSelectedImage(event)">
 
195
  <img id="imagePreview" alt="圖片預覽">
196
  </div>
197
  </div>
198
+
199
  <div class="form-group">
200
  <label for="promptInput">輸入提示詞 (Prompt)</label>
201
  <input type="text" id="promptInput" value="Describe this image in one sentence in chinese">
202
  </div>
203
+
204
  <button id="submitBtn" onclick="analyzeImage()">啟動分析</button>
205
+
206
  <div class="form-group" style="margin-top: 24px;">
207
  <label>模型回應</label>
208
  <div id="result">系統待命,尚未開始分析...</div>
 
210
  </div>
211
 
212
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  // 選擇圖片時即時顯示預覽
214
  function previewSelectedImage(event) {
215
  const file = event.target.files[0];
 
319
  }
320
  </script>
321
  </body>
322
+ </html>