RafaelJaime commited on
Commit
348aab5
verified
1 Parent(s): 7305e20

Update src/App.js

Browse files
Files changed (1) hide show
  1. src/App.js +436 -20
src/App.js CHANGED
@@ -1,25 +1,441 @@
1
- import logo from './logo.svg';
2
- import './App.css';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- function App() {
5
  return (
6
- <div className="App">
7
- <header className="App-header">
8
- <img src={logo} className="App-logo" alt="logo" />
9
- <p>
10
- Edit <code>src/App.js</code> and save to reload.
11
- </p>
12
- <a
13
- className="App-link"
14
- href="https://reactjs.org"
15
- target="_blank"
16
- rel="noopener noreferrer"
17
- >
18
- Learn React
19
- </a>
20
- </header>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  </div>
22
  );
23
- }
24
 
25
- export default App;
 
1
+ import React, { useState, useEffect, useMemo } from 'react';
2
+ import { Search, Trophy, Medal, Award, BarChart3, Filter, RefreshCw, ExternalLink, Clock, Zap, Target, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react';
3
+
4
+ const LeaderboardUrology = () => {
5
+ const [searchTerm, setSearchTerm] = useState('');
6
+ const [filterLicense, setFilterLicense] = useState('all');
7
+ const [sortBy, setSortBy] = useState('accuracy');
8
+ const [sortOrder, setSortOrder] = useState('desc');
9
+ const [data, setData] = useState([]);
10
+ const [loading, setLoading] = useState(true);
11
+ const [refreshing, setRefreshing] = useState(false);
12
+ const [lastUpdated, setLastUpdated] = useState(null);
13
+
14
+ const mockData = [
15
+ {
16
+ model: "openai/gpt-4o-mini",
17
+ baseModel: "",
18
+ accuracy: 0.18543046357615803,
19
+ totalQuestions: 151,
20
+ correctAnswers: 28,
21
+ license: "API Service",
22
+ submitType: "openrouter",
23
+ submittedTime: "2025-05-22T16:53:10Z",
24
+ params: 0,
25
+ precision: "float16",
26
+ status: "FINISHED"
27
+ },
28
+ {
29
+ model: "anthropic/claude-3-sonnet",
30
+ baseModel: "claude-3-sonnet",
31
+ accuracy: 0.32450331125827815,
32
+ totalQuestions: 151,
33
+ correctAnswers: 49,
34
+ license: "API Service",
35
+ submitType: "openrouter",
36
+ submittedTime: "2025-05-22T14:30:25Z",
37
+ params: 0,
38
+ precision: "float16",
39
+ status: "FINISHED"
40
+ },
41
+ {
42
+ model: "meta-llama/llama-3.1-70b",
43
+ baseModel: "llama-3.1-70b",
44
+ accuracy: 0.27814569536423844,
45
+ totalQuestions: 151,
46
+ correctAnswers: 42,
47
+ license: "Apache 2.0",
48
+ submitType: "huggingface",
49
+ submittedTime: "2025-05-22T12:15:30Z",
50
+ params: 70000000000,
51
+ precision: "bfloat16",
52
+ status: "FINISHED"
53
+ },
54
+ {
55
+ model: "mistralai/mixtral-8x7b",
56
+ baseModel: "mixtral-8x7b",
57
+ accuracy: 0.23841059602649006,
58
+ totalQuestions: 151,
59
+ correctAnswers: 36,
60
+ license: "Apache 2.0",
61
+ submitType: "huggingface",
62
+ submittedTime: "2025-05-22T10:45:15Z",
63
+ params: 46700000000,
64
+ precision: "bfloat16",
65
+ status: "FINISHED"
66
+ },
67
+ {
68
+ model: "google/gemini-pro",
69
+ baseModel: "gemini-pro",
70
+ accuracy: 0.29801324503311255,
71
+ totalQuestions: 151,
72
+ correctAnswers: 45,
73
+ license: "API Service",
74
+ submitType: "google",
75
+ submittedTime: "2025-05-22T08:20:40Z",
76
+ params: 0,
77
+ precision: "float16",
78
+ status: "FINISHED"
79
+ },
80
+ {
81
+ model: "cohere/command-r-plus",
82
+ baseModel: "command-r-plus",
83
+ accuracy: 0.35761589403973510,
84
+ totalQuestions: 151,
85
+ correctAnswers: 54,
86
+ license: "API Service",
87
+ submitType: "cohere",
88
+ submittedTime: "2025-05-21T18:12:30Z",
89
+ params: 0,
90
+ precision: "float16",
91
+ status: "FINISHED"
92
+ },
93
+ {
94
+ model: "openai/gpt-4-turbo",
95
+ baseModel: "gpt-4-turbo",
96
+ accuracy: 0.41721854304635763,
97
+ totalQuestions: 151,
98
+ correctAnswers: 63,
99
+ license: "API Service",
100
+ submitType: "openai",
101
+ submittedTime: "2025-05-21T16:45:10Z",
102
+ params: 0,
103
+ precision: "float16",
104
+ status: "FINISHED"
105
+ },
106
+ {
107
+ model: "microsoft/phi-3-medium",
108
+ baseModel: "phi-3-medium",
109
+ accuracy: 0.21854304635761590,
110
+ totalQuestions: 151,
111
+ correctAnswers: 33,
112
+ license: "MIT",
113
+ submitType: "azure",
114
+ submittedTime: "2025-05-21T14:22:45Z",
115
+ params: 14000000000,
116
+ precision: "float16",
117
+ status: "FINISHED"
118
+ }
119
+ ];
120
+
121
+ const loadData = async () => {
122
+ await new Promise(resolve => setTimeout(resolve, 1000));
123
+ return mockData;
124
+ };
125
+
126
+ const refreshData = async () => {
127
+ setRefreshing(true);
128
+ try {
129
+ const newData = await loadData();
130
+ const shuffledData = [...newData].sort(() => Math.random() - 0.5).slice(0, Math.floor(Math.random() * 3) + 6);
131
+ setData(shuffledData);
132
+ setLastUpdated(new Date());
133
+ } catch (error) {
134
+ console.error('Error refreshing data:', error);
135
+ } finally {
136
+ setRefreshing(false);
137
+ }
138
+ };
139
+
140
+ useEffect(() => {
141
+ const initializeData = async () => {
142
+ const initialData = await loadData();
143
+ setData(initialData);
144
+ setLastUpdated(new Date());
145
+ setLoading(false);
146
+ };
147
+ initializeData();
148
+ }, []);
149
+
150
+ const filteredAndSortedData = useMemo(() => {
151
+ let filtered = data.filter(item => {
152
+ const matchesSearch = item.model.toLowerCase().includes(searchTerm.toLowerCase()) ||
153
+ item.baseModel.toLowerCase().includes(searchTerm.toLowerCase());
154
+ const matchesFilter = filterLicense === 'all' || item.license === filterLicense;
155
+ return matchesSearch && matchesFilter;
156
+ });
157
+
158
+ return filtered.sort((a, b) => {
159
+ let aValue = a[sortBy];
160
+ let bValue = b[sortBy];
161
+
162
+ if (sortBy === 'submittedTime') {
163
+ aValue = new Date(aValue);
164
+ bValue = new Date(bValue);
165
+ }
166
+
167
+ if (sortOrder === 'desc') {
168
+ return bValue > aValue ? 1 : -1;
169
+ } else {
170
+ return aValue > bValue ? 1 : -1;
171
+ }
172
+ });
173
+ }, [data, searchTerm, filterLicense, sortBy, sortOrder]);
174
+
175
+ const getRankIcon = (index) => {
176
+ switch(index) {
177
+ case 0: return <Trophy className="w-6 h-6 text-yellow-500" />;
178
+ case 1: return <Medal className="w-6 h-6 text-gray-400" />;
179
+ case 2: return <Award className="w-6 h-6 text-amber-600" />;
180
+ default: return <span className="text-xl font-bold text-gray-500">#{index + 1}</span>;
181
+ }
182
+ };
183
+
184
+ const formatAccuracy = (accuracy) => {
185
+ return `${(accuracy * 100).toFixed(2)}%`;
186
+ };
187
+
188
+ const formatParams = (params) => {
189
+ if (params === 0) return 'API';
190
+ if (params >= 1e9) return `${(params / 1e9).toFixed(1)}B`;
191
+ if (params >= 1e6) return `${(params / 1e6).toFixed(1)}M`;
192
+ return params.toLocaleString();
193
+ };
194
+
195
+ const formatDate = (dateString) => {
196
+ return new Date(dateString).toLocaleDateString('es-ES', {
197
+ day: '2-digit',
198
+ month: '2-digit',
199
+ year: 'numeric',
200
+ hour: '2-digit',
201
+ minute: '2-digit'
202
+ });
203
+ };
204
+
205
+ const getSortIcon = (column) => {
206
+ if (sortBy !== column) return <ArrowUpDown className="w-4 h-4 text-gray-400" />;
207
+ return sortOrder === 'desc' ?
208
+ <ArrowDown className="w-4 h-4 text-blue-500" /> :
209
+ <ArrowUp className="w-4 h-4 text-blue-500" />;
210
+ };
211
+
212
+ if (loading) {
213
+ return (
214
+ <div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-900 to-indigo-900 flex items-center justify-center">
215
+ <div className="text-center">
216
+ <div className="animate-spin rounded-full h-16 w-16 border-b-2 border-white mb-4"></div>
217
+ <p className="text-white text-xl">Cargando leaderboard...</p>
218
+ </div>
219
+ </div>
220
+ );
221
+ }
222
 
 
223
  return (
224
+ <div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-900 to-indigo-900">
225
+ <div className="container mx-auto px-4 py-8">
226
+ <div className="text-center mb-8">
227
+ <h1 className="text-5xl font-bold text-white mb-4 bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">
228
+ 馃弳 Urology AI Leaderboard
229
+ </h1>
230
+ <p className="text-xl text-gray-300 mb-6">
231
+ Evaluating Natural Language Models on Urology Knowledge Assessment
232
+ </p>
233
+ <div className="flex justify-center space-x-8 text-center">
234
+ <div className="bg-white/10 backdrop-blur-sm rounded-lg p-4 border border-white/20">
235
+ <div className="text-2xl font-bold text-white">{data.length}</div>
236
+ <div className="text-sm text-gray-300">Models</div>
237
+ </div>
238
+ <div className="bg-white/10 backdrop-blur-sm rounded-lg p-4 border border-white/20">
239
+ <div className="text-2xl font-bold text-white">151</div>
240
+ <div className="text-sm text-gray-300">Questions</div>
241
+ </div>
242
+ <div className="bg-white/10 backdrop-blur-sm rounded-lg p-4 border border-white/20">
243
+ <div className="text-2xl font-bold text-white">SAS Urology</div>
244
+ <div className="text-sm text-gray-300">Specialty</div>
245
+ </div>
246
+ </div>
247
+ </div>
248
+
249
+ <div className="mb-6 flex flex-wrap gap-4 items-center justify-between">
250
+ <div className="flex flex-wrap gap-4 items-center">
251
+ <div className="relative">
252
+ <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
253
+ <input
254
+ type="text"
255
+ placeholder="Search model..."
256
+ value={searchTerm}
257
+ onChange={(e) => setSearchTerm(e.target.value)}
258
+ className="pl-10 pr-4 py-2 bg-white/10 backdrop-blur-sm border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
259
+ />
260
+ </div>
261
+
262
+ <div className="relative">
263
+ <Filter className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
264
+ <select
265
+ value={filterLicense}
266
+ onChange={(e) => setFilterLicense(e.target.value)}
267
+ className="pl-10 pr-8 py-2 bg-white/10 backdrop-blur-sm border border-white/20 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500 appearance-none"
268
+ >
269
+ <option value="all">All licenses</option>
270
+ <option value="API Service">API Service</option>
271
+ <option value="Apache 2.0">Apache 2.0</option>
272
+ <option value="MIT">MIT</option>
273
+ </select>
274
+ </div>
275
+ </div>
276
+
277
+ <button
278
+ onClick={refreshData}
279
+ disabled={refreshing}
280
+ className="flex items-center space-x-2 px-4 py-2 bg-green-600 hover:bg-green-700 disabled:bg-green-600/50 text-white rounded-lg transition-colors"
281
+ >
282
+ <RefreshCw className={`w-4 h-4 ${refreshing ? 'animate-spin' : ''}`} />
283
+ <span>{refreshing ? 'Updating...' : 'Update'}</span>
284
+ </button>
285
+ </div>
286
+
287
+ <div className="bg-white/10 backdrop-blur-sm rounded-xl border border-white/20 overflow-hidden">
288
+ <div className="overflow-x-auto">
289
+ <div className="max-h-96 overflow-y-auto">
290
+ <table className="w-full">
291
+ <thead className="sticky top-0 bg-white/10 backdrop-blur-sm">
292
+ <tr className="border-b border-white/10">
293
+ <th className="px-6 py-4 text-left text-white font-semibold">Rank</th>
294
+ <th className="px-6 py-4 text-left text-white font-semibold">Model</th>
295
+ <th
296
+ className="px-6 py-4 text-left text-white font-semibold cursor-pointer hover:bg-white/5 transition-colors"
297
+ onClick={() => {
298
+ if (sortBy === 'accuracy') {
299
+ setSortOrder(sortOrder === 'desc' ? 'asc' : 'desc');
300
+ } else {
301
+ setSortBy('accuracy');
302
+ setSortOrder('desc');
303
+ }
304
+ }}
305
+ >
306
+ <div className="flex items-center space-x-1">
307
+ <Target className="w-4 h-4" />
308
+ <span>Accuracy</span>
309
+ {getSortIcon('accuracy')}
310
+ </div>
311
+ </th>
312
+ <th className="px-6 py-4 text-left text-white font-semibold">Answers</th>
313
+ <th className="px-6 py-4 text-left text-white font-semibold">Parameters</th>
314
+ <th className="px-6 py-4 text-left text-white font-semibold">License</th>
315
+ <th
316
+ className="px-6 py-4 text-left text-white font-semibold cursor-pointer hover:bg-white/5 transition-colors"
317
+ onClick={() => {
318
+ if (sortBy === 'submittedTime') {
319
+ setSortOrder(sortOrder === 'desc' ? 'asc' : 'desc');
320
+ } else {
321
+ setSortBy('submittedTime');
322
+ setSortOrder('desc');
323
+ }
324
+ }}
325
+ >
326
+ <div className="flex items-center space-x-1">
327
+ <Clock className="w-4 h-4" />
328
+ <span>Date</span>
329
+ {getSortIcon('submittedTime')}
330
+ </div>
331
+ </th>
332
+ </tr>
333
+ </thead>
334
+ <tbody>
335
+ {filteredAndSortedData.map((item, index) => (
336
+ <tr
337
+ key={item.model}
338
+ className="border-b border-white/5 hover:bg-white/5 transition-colors group"
339
+ >
340
+ <td className="px-6 py-4">
341
+ <div className="flex items-center">
342
+ {getRankIcon(index)}
343
+ </div>
344
+ </td>
345
+ <td className="px-6 py-4">
346
+ <div className="flex flex-col">
347
+ <div className="flex items-center space-x-2">
348
+ <span className="text-white font-medium">{item.model.split('/').pop()}</span>
349
+ <ExternalLink className="w-4 h-4 text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer" />
350
+ </div>
351
+ <span className="text-sm text-gray-400">{item.model.split('/')[0]}</span>
352
+ </div>
353
+ </td>
354
+ <td className="px-6 py-4">
355
+ <div className="flex items-center space-x-3">
356
+ <div className="flex-1">
357
+ <div className="flex items-center justify-between mb-1">
358
+ <span className="text-white font-semibold">{formatAccuracy(item.accuracy)}</span>
359
+ </div>
360
+ <div className="w-full bg-gray-700 rounded-full h-2">
361
+ <div
362
+ className="bg-gradient-to-r from-blue-500 to-purple-500 h-2 rounded-full transition-all duration-500"
363
+ style={{ width: `${item.accuracy * 100}%` }}
364
+ ></div>
365
+ </div>
366
+ </div>
367
+ </div>
368
+ </td>
369
+ <td className="px-6 py-4">
370
+ <div className="text-center">
371
+ <div className="text-white font-semibold">{item.correctAnswers}/{item.totalQuestions}</div>
372
+ <div className="text-sm text-gray-400">correct</div>
373
+ </div>
374
+ </td>
375
+ <td className="px-6 py-4">
376
+ <div className="flex items-center space-x-2">
377
+ <Zap className="w-4 h-4 text-yellow-400" />
378
+ <span className="text-white">{formatParams(item.params)}</span>
379
+ </div>
380
+ </td>
381
+ <td className="px-6 py-4">
382
+ <span className={`px-2 py-1 rounded-full text-xs font-medium ${
383
+ item.license === 'API Service'
384
+ ? 'bg-blue-500/20 text-blue-300'
385
+ : item.license === 'Apache 2.0'
386
+ ? 'bg-green-500/20 text-green-300'
387
+ : 'bg-purple-500/20 text-purple-300'
388
+ }`}>
389
+ {item.license}
390
+ </span>
391
+ </td>
392
+ <td className="px-6 py-4">
393
+ <div className="text-sm text-gray-300">
394
+ {formatDate(item.submittedTime)}
395
+ </div>
396
+ </td>
397
+ </tr>
398
+ ))}
399
+ </tbody>
400
+ </table>
401
+ </div>
402
+ </div>
403
+ </div>
404
+
405
+ <div className="mt-8 space-y-6">
406
+ <div className="bg-white/10 backdrop-blur-sm rounded-lg p-6 border border-white/20">
407
+ <h3 className="text-xl font-semibold text-white mb-3">馃搳 About This Evaluation</h3>
408
+ <p className="text-gray-300 mb-3">
409
+ This leaderboard evaluates natural language models on their ability to answer urology questions.
410
+ Models must respond to multiple-choice questions about urological knowledge, demonstrating their understanding and mastery of this medical specialty.
411
+ </p>
412
+ <p className="text-gray-300 mb-4">
413
+ Questions are from the SAS (Servicio Andaluz de Salud) for the <strong>Convocatoria Concurso Oposici贸n</strong> - specialized medical examination for urology residents.
414
+ </p>
415
+ <div className="flex flex-col sm:flex-row items-center justify-center space-y-2 sm:space-y-0 sm:space-x-4 text-gray-300">
416
+ <span>Dataset: <a href="https://huggingface.co/datasets/SASLeaderboard/results" className="text-blue-400 hover:text-blue-300 transition-colors">SASLeaderboard/results</a></span>
417
+ {lastUpdated && (
418
+ <span className="text-sm">
419
+ Last updated: {lastUpdated.toLocaleString('en-US')}
420
+ </span>
421
+ )}
422
+ </div>
423
+ </div>
424
+
425
+ <div className="bg-white/10 backdrop-blur-sm rounded-lg p-4 border border-white/20">
426
+ <div className="text-center">
427
+ <h4 className="text-lg font-semibold text-white mb-2">馃帗 Academic Project</h4>
428
+ <p className="text-gray-300 text-sm">
429
+ Final project for IES Rafael Alberti<br/>
430
+ Course: Artificial Intelligence and Big Data<br/>
431
+ Subject: Artificial Intelligence Models
432
+ </p>
433
+ </div>
434
+ </div>
435
+ </div>
436
+ </div>
437
  </div>
438
  );
439
+ };
440
 
441
+ export default LeaderboardUrology;