Update app.py
Browse files
app.py
CHANGED
@@ -2,510 +2,14 @@ import gradio as gr
|
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
"
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
"
|
15 |
-
|
16 |
-
"Local Civil Service Grade 7": "지방직 7급",
|
17 |
-
"Military Civil Service Grade 7": "군무원 7급",
|
18 |
-
"Police Officer Exam": "경찰(순경)",
|
19 |
-
"Police Promotion Exam": "경찰(승진)",
|
20 |
-
"Fire Service Executive Candidate": "소방간부후보생",
|
21 |
-
"National Assembly Grade 8": "국회직 8급",
|
22 |
-
"Postal Service Exam": "계리직",
|
23 |
-
"National Civil Service Grade 9": "국가직 9급",
|
24 |
-
"Seoul City Grade 9": "서울시 9급",
|
25 |
-
"National Assembly Grade 9": "국회직 9급",
|
26 |
-
"Judicial Service Grade 9": "법원직 9급",
|
27 |
-
"Local Civil Service Grade 9": "지방직 9급",
|
28 |
-
"Military Civil Service Grade 9": "군무원 9급",
|
29 |
-
"Firefighter Exam": "소방공무원"
|
30 |
-
}
|
31 |
-
|
32 |
-
# 원본 데이터 정의 (AI 모델과 URL만 포함)
|
33 |
-
data = {
|
34 |
-
"AI Model": [
|
35 |
-
"deepseek-ai/DeepSeek-R1",
|
36 |
-
"Qwen/QwQ-32B",
|
37 |
-
"CohereForAI/c4ai-command-a-03-2025",
|
38 |
-
"meta-llama/Llama-3.3-70B-Instruct",
|
39 |
-
"mistralai/Mistral-Small-3.1-24B-Instruct-2503",
|
40 |
-
"google/gemma-3-27b-it",
|
41 |
-
"LGAI-EXAONE/EXAONE-Deep-32B",
|
42 |
-
"OpenAI/GPT-o1",
|
43 |
-
"OpenAI/GPT-o3-mini",
|
44 |
-
"OpenAI/GPT-4.5",
|
45 |
-
"OpenAI/GPT-4o",
|
46 |
-
"Anthropic/Claude 3.7 Sonnet",
|
47 |
-
"Google/Gemini 2.0 Flash Thinking Experimental",
|
48 |
-
"Google/Gemini 2.0 PRO Experimental",
|
49 |
-
"Google/Gemini 2.0 Flash",
|
50 |
-
|
51 |
-
"nvidia/llama-3_1-nemotron-70b-instruct",
|
52 |
-
"qwen/qwen2_5-coder-32b-instruct ",
|
53 |
-
"deepseek-ai/deepseek-r1-distill-qwen-32b" ,
|
54 |
-
"meta/llama-3.2-90b-vision-instruct ",
|
55 |
-
"nvidia/llama-3_3-nemotron-super-49b-v1 "
|
56 |
-
|
57 |
-
|
58 |
-
],
|
59 |
-
"URL": [
|
60 |
-
"https://huggingface.co/deepseek-ai/DeepSeek-R1",
|
61 |
-
"https://huggingface.co/Qwen/QwQ-32B",
|
62 |
-
"https://huggingface.co/CohereForAI/c4ai-command-a-03-2025",
|
63 |
-
"https://huggingface.co/meta-llama/Llama-3.3-70B-Instruct",
|
64 |
-
"https://huggingface.co/mistralai/Mistral-Small-3.1-24B-Instruct-2503",
|
65 |
-
"https://huggingface.co/google/gemma-3-27b-it",
|
66 |
-
"https://huggingface.co/LGAI-EXAONE/EXAONE-Deep-32B",
|
67 |
-
"https://openai.com",
|
68 |
-
"https://openai.com",
|
69 |
-
"https://openai.com",
|
70 |
-
"https://openai.com",
|
71 |
-
"https://www.anthropic.com/claude",
|
72 |
-
"https://gemini.google.com/app",
|
73 |
-
"https://gemini.google.com/app",
|
74 |
-
"https://gemini.google.com/app",
|
75 |
-
|
76 |
-
"https://build.nvidia.com/nvidia/llama-3_1-nemotron-70b-instruct",
|
77 |
-
"https://build.nvidia.com/qwen/qwen2_5-coder-32b-instruct",
|
78 |
-
"https://build.nvidia.com/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
79 |
-
"https://build.nvidia.com/meta/llama-3.2-90b-vision-instruct",
|
80 |
-
"https://build.nvidia.com/nvidia/llama-3_3-nemotron-super-49b-v1"
|
81 |
-
]
|
82 |
-
}
|
83 |
-
|
84 |
-
# [1] 기본 DataFrame 생성 (AI 모델과 URL만 포함)
|
85 |
-
df = pd.DataFrame(data)
|
86 |
-
|
87 |
-
# [2] "Korean Bar Exam" 점수를 모든 모델에 할당할 딕셔너리 (임의 예시)
|
88 |
-
# 키=AI Model, 값=해당 모델의 변호사 시험 점수
|
89 |
-
bar_exam_scores = {
|
90 |
-
"deepseek-ai/DeepSeek-R1": 47.33,
|
91 |
-
"Qwen/QwQ-32B": 32.66,
|
92 |
-
"CohereForAI/c4ai-command-a-03-2025": 27.33,
|
93 |
-
"meta-llama/Llama-3.3-70B-Instruct": 19.33,
|
94 |
-
"mistralai/Mistral-Small-3.1-24B-Instruct-2503": None,
|
95 |
-
"google/gemma-3-27b-it": None,
|
96 |
-
"LGAI-EXAONE/EXAONE-Deep-32B": None,
|
97 |
-
"OpenAI/GPT-o1": 52.5,
|
98 |
-
"OpenAI/GPT-o3-mini": 37.05,
|
99 |
-
"OpenAI/GPT-4.5": 49.33,
|
100 |
-
"OpenAI/GPT-4o": 49.11,
|
101 |
-
"Anthropic/Claude 3.7 Sonnet": 42.66,
|
102 |
-
"Google/Gemini 2.0 Flash Thinking Experimental": 12.5,
|
103 |
-
"Google/Gemini 2.0 PRO Experimental": 40,
|
104 |
-
"Google/Gemini 2.0 Flash": 25,
|
105 |
-
|
106 |
-
"nvidia/llama-3_1-nemotron-70b-instruct": 35,
|
107 |
-
"qwen/qwen2_5-coder-32b-instruct ": 32.5,
|
108 |
-
"deepseek-ai/deepseek-r1-distill-qwen-32b": 30,
|
109 |
-
"meta/llama-3.2-90b-vision-instruct ": 27.5,
|
110 |
-
"nvidia/llama-3_3-nemotron-super-49b-v1 ": 25
|
111 |
-
|
112 |
-
}
|
113 |
-
# 위 숫자는 예시값이므로 원하는 대로 수정 가능
|
114 |
-
|
115 |
-
# [3] 모든 시험 항목 정의
|
116 |
-
exam_columns = list(exam_mappings.keys()) # 22개
|
117 |
-
|
118 |
-
# [4] 모든 모델에 대해, 22개 시험 점수를 None으로 초기화
|
119 |
-
for exam in exam_columns:
|
120 |
-
df[exam] = None
|
121 |
-
|
122 |
-
# [5] df를 순회하며, 각 모델(AI Model)의 "Korean Bar Exam"에만 점수를 채워넣고,
|
123 |
-
# 나머지는 None (TBD) 상태 그대로 둠
|
124 |
-
for i, row in df.iterrows():
|
125 |
-
model_name = row["AI Model"]
|
126 |
-
if model_name in bar_exam_scores:
|
127 |
-
df.at[i, "Korean Bar Exam"] = bar_exam_scores[model_name]
|
128 |
-
# else는 None 그대���
|
129 |
-
|
130 |
-
# [6] Average 컬럼 계산 함수 - None 제외하고 평균 구함
|
131 |
-
def calculate_average(row):
|
132 |
-
valid_scores = []
|
133 |
-
for exam_col in exam_columns:
|
134 |
-
val = row[exam_col]
|
135 |
-
if val is not None:
|
136 |
-
valid_scores.append(val)
|
137 |
-
if not valid_scores:
|
138 |
-
return None
|
139 |
-
return sum(valid_scores) / len(valid_scores)
|
140 |
-
|
141 |
-
df["Average"] = df.apply(calculate_average, axis=1).round(1)
|
142 |
-
|
143 |
-
# [7] 열 순서 재배치
|
144 |
-
cols = ["AI Model", "URL", "Average"] + exam_columns
|
145 |
-
df = df[cols]
|
146 |
-
|
147 |
-
# [8] 초기 정렬 (Average 기준 내림차순)
|
148 |
-
df = df.sort_values(by="Average", ascending=False).reset_index(drop=True)
|
149 |
-
|
150 |
-
# [9] HTML 렌더링 함수 (기존 코드 그대로 복사)
|
151 |
-
def format_df_as_html(df, sort_by="Average", ascending=False):
|
152 |
-
# 정렬 적용
|
153 |
-
sorted_df = df.sort_values(by=sort_by, ascending=ascending).reset_index(drop=True)
|
154 |
-
|
155 |
-
# DataFrame 복사본 생성
|
156 |
-
display_df = sorted_df.copy()
|
157 |
-
|
158 |
-
# URL 열을 클릭 가능한 링크로 변환
|
159 |
-
for i, url in enumerate(display_df["URL"]):
|
160 |
-
model_name = display_df.iloc[i]["AI Model"]
|
161 |
-
display_df.at[i, "AI Model"] = f'<a href="{url}" target="_blank">{model_name}</a>'
|
162 |
-
|
163 |
-
# URL 열 제거 (이미 AI Model에 링크로 통합)
|
164 |
-
display_df = display_df.drop("URL", axis=1)
|
165 |
-
|
166 |
-
# NaN 값을 'TBD'로 변환 (평가 예정)
|
167 |
-
display_df = display_df.fillna("TBD")
|
168 |
-
|
169 |
-
# 정렬을 위한 JavaScript 함수
|
170 |
-
js_sort_function = """
|
171 |
-
<script>
|
172 |
-
function sortTable(n) {
|
173 |
-
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
|
174 |
-
table = document.getElementById("leaderboard-table");
|
175 |
-
switching = true;
|
176 |
-
// 기본 정렬 방향은 오름차순
|
177 |
-
dir = "asc";
|
178 |
-
|
179 |
-
while (switching) {
|
180 |
-
switching = false;
|
181 |
-
rows = table.rows;
|
182 |
-
|
183 |
-
for (i = 1; i < (rows.length - 1); i++) {
|
184 |
-
shouldSwitch = false;
|
185 |
-
x = rows[i].getElementsByTagName("TD")[n];
|
186 |
-
y = rows[i + 1].getElementsByTagName("TD")[n];
|
187 |
-
|
188 |
-
// 첫 번째 열(AI Model)인 경우 텍스트로 비교
|
189 |
-
if (n == 0) {
|
190 |
-
// innerHTML에서 링크 텍스트 추출
|
191 |
-
var xContent = x.innerHTML.toLowerCase();
|
192 |
-
var yContent = y.innerHTML.toLowerCase();
|
193 |
-
|
194 |
-
// href 태그에서 텍스트 추출 (안전하게)
|
195 |
-
var xMatch = xContent.match(/>([^<]+)</);
|
196 |
-
var yMatch = yContent.match(/>([^<]+)</);
|
197 |
-
|
198 |
-
var xText = xMatch ? xMatch[1] : xContent;
|
199 |
-
var yText = yMatch ? yMatch[1] : yContent;
|
200 |
-
|
201 |
-
if (dir == "asc") {
|
202 |
-
if (xText > yText) {
|
203 |
-
shouldSwitch = true;
|
204 |
-
break;
|
205 |
-
}
|
206 |
-
} else if (dir == "desc") {
|
207 |
-
if (xText < yText) {
|
208 |
-
shouldSwitch = true;
|
209 |
-
break;
|
210 |
-
}
|
211 |
-
}
|
212 |
-
} else {
|
213 |
-
// 숫자 열인 경우 숫자로 변환하여 비교 (TBD인 경우 -1로 처리)
|
214 |
-
var xValue = x.innerHTML === "TBD" ? -1 : parseFloat(x.innerHTML);
|
215 |
-
var yValue = y.innerHTML === "TBD" ? -1 : parseFloat(y.innerHTML);
|
216 |
-
|
217 |
-
if (dir == "asc") {
|
218 |
-
if (xValue > yValue) {
|
219 |
-
shouldSwitch = true;
|
220 |
-
break;
|
221 |
-
}
|
222 |
-
} else if (dir == "desc") {
|
223 |
-
if (xValue < yValue) {
|
224 |
-
shouldSwitch = true;
|
225 |
-
break;
|
226 |
-
}
|
227 |
-
}
|
228 |
-
}
|
229 |
-
}
|
230 |
-
|
231 |
-
if (shouldSwitch) {
|
232 |
-
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
|
233 |
-
switching = true;
|
234 |
-
switchcount++;
|
235 |
-
} else {
|
236 |
-
if (switchcount == 0 && dir == "asc") {
|
237 |
-
dir = "desc";
|
238 |
-
switching = true;
|
239 |
-
}
|
240 |
-
}
|
241 |
-
}
|
242 |
-
|
243 |
-
// 모든 헤더에서 정렬 표시 제거
|
244 |
-
var headers = table.getElementsByTagName("TH");
|
245 |
-
for (i = 0; i < headers.length; i++) {
|
246 |
-
headers[i].innerHTML = headers[i].innerHTML.replace(" ▲", "").replace(" ▼", "");
|
247 |
-
}
|
248 |
-
|
249 |
-
// 현재 정렬된 헤더에 방향 표시
|
250 |
-
var header = table.getElementsByTagName("TH")[n];
|
251 |
-
if (dir == "desc") {
|
252 |
-
header.innerHTML = header.innerHTML + " ▼";
|
253 |
-
} else {
|
254 |
-
header.innerHTML = header.innerHTML + " ▲";
|
255 |
-
}
|
256 |
-
}
|
257 |
-
</script>
|
258 |
-
"""
|
259 |
-
|
260 |
-
# 범례 생성
|
261 |
-
legend_html = """
|
262 |
-
<div class="legend-container">
|
263 |
-
<h3>Legend (범례)</h3>
|
264 |
-
<div class="legend-grid">
|
265 |
-
"""
|
266 |
-
for i, (eng, kor) in enumerate(exam_mappings.items()):
|
267 |
-
legend_html += f'<div class="legend-item"><span class="legend-eng">{eng}:</span> <span class="legend-kor">{kor}</span></div>'
|
268 |
-
|
269 |
-
legend_html += """
|
270 |
-
</div>
|
271 |
-
<div style="margin-top: 10px;">
|
272 |
-
<strong>TBD:</strong> To Be Determined (평가 예정)
|
273 |
-
</div>
|
274 |
-
</div>
|
275 |
-
"""
|
276 |
-
|
277 |
-
# 파스텔 색상 배열 (행 색상에 사용)
|
278 |
-
pastel_colors = [
|
279 |
-
"#F0F8FF", "#FAEBD7", "#E6E6FA", "#F0FFF0", "#FFF0F5",
|
280 |
-
"#F0FFFF", "#F5F5DC", "#FFF5EE", "#F5F5F5", "#FFFAF0",
|
281 |
-
"#F8F8FF", "#FFFFF0", "#F0F8FF", "#E0FFFF", "#FFFFE0"
|
282 |
-
]
|
283 |
-
|
284 |
-
# 표 스타일 + JS
|
285 |
-
styled_html = f"""
|
286 |
-
{js_sort_function}
|
287 |
-
<style>
|
288 |
-
.table-container {{
|
289 |
-
width: 100%;
|
290 |
-
margin-bottom: 20px;
|
291 |
-
padding-bottom: 5px;
|
292 |
-
}}
|
293 |
-
table {{
|
294 |
-
width: 100%;
|
295 |
-
min-width: 1200px;
|
296 |
-
border-collapse: collapse;
|
297 |
-
font-family: Arial, sans-serif;
|
298 |
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
299 |
-
table-layout: fixed;
|
300 |
-
}}
|
301 |
-
th {{
|
302 |
-
background-color: #A5D6A7;
|
303 |
-
color: #333;
|
304 |
-
font-weight: bold;
|
305 |
-
text-align: center;
|
306 |
-
padding: 8px 4px;
|
307 |
-
cursor: pointer;
|
308 |
-
position: sticky;
|
309 |
-
top: 0;
|
310 |
-
z-index: 10;
|
311 |
-
white-space: normal;
|
312 |
-
height: auto;
|
313 |
-
min-height: 60px;
|
314 |
-
border: 1px solid #ddd;
|
315 |
-
box-sizing: border-box;
|
316 |
-
overflow: visible;
|
317 |
-
font-size: 11px;
|
318 |
-
line-height: 1.2;
|
319 |
-
}}
|
320 |
-
th:hover {{
|
321 |
-
background-color: #81C784;
|
322 |
-
}}
|
323 |
-
td {{
|
324 |
-
padding: 8px 4px;
|
325 |
-
border: 1px solid #ddd;
|
326 |
-
text-align: center;
|
327 |
-
box-sizing: border-box;
|
328 |
-
overflow: hidden;
|
329 |
-
font-size: 12px;
|
330 |
-
}}
|
331 |
-
.tbd-cell {{
|
332 |
-
font-style: italic;
|
333 |
-
color: #999;
|
334 |
-
}}
|
335 |
-
.header {{
|
336 |
-
text-align: center;
|
337 |
-
font-size: 24px;
|
338 |
-
font-weight: bold;
|
339 |
-
margin-bottom: 10px;
|
340 |
-
color: #333;
|
341 |
-
text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
|
342 |
-
}}
|
343 |
-
.description {{
|
344 |
-
text-align: left;
|
345 |
-
font-size: 12px;
|
346 |
-
margin-bottom: 20px;
|
347 |
-
color: #333;
|
348 |
-
padding: 15px;
|
349 |
-
background-color: #F1F8E9;
|
350 |
-
border-radius: 8px;
|
351 |
-
line-height: 1.4;
|
352 |
-
}}
|
353 |
-
table th, table td {{
|
354 |
-
min-width: 45px;
|
355 |
-
max-width: 70px;
|
356 |
-
}}
|
357 |
-
th:first-child, td:first-child {{
|
358 |
-
position: sticky;
|
359 |
-
left: 0;
|
360 |
-
z-index: 2;
|
361 |
-
width: 240px;
|
362 |
-
min-width: 240px;
|
363 |
-
max-width: 240px;
|
364 |
-
}}
|
365 |
-
th:first-child {{
|
366 |
-
z-index: 11;
|
367 |
-
background-color: #A5D6A7;
|
368 |
-
}}
|
369 |
-
th:nth-child(2), td:nth-child(2) {{
|
370 |
-
position: sticky;
|
371 |
-
left: 240px;
|
372 |
-
z-index: 2;
|
373 |
-
width: 80px;
|
374 |
-
min-width: 80px;
|
375 |
-
}}
|
376 |
-
th:nth-child(2) {{
|
377 |
-
z-index: 11;
|
378 |
-
background-color: #A5D6A7;
|
379 |
-
}}
|
380 |
-
tr[data-color] td {{
|
381 |
-
background-color: inherit;
|
382 |
-
}}
|
383 |
-
tr[data-color] td:first-child, tr[data-color] td:nth-child(2) {{
|
384 |
-
background-color: inherit !important;
|
385 |
-
}}
|
386 |
-
.legend-container {{
|
387 |
-
margin-top: 30px;
|
388 |
-
padding: 15px;
|
389 |
-
border-top: 1px solid #ddd;
|
390 |
-
font-size: 12px;
|
391 |
-
background-color: #F1F8E9;
|
392 |
-
border-radius: 8px;
|
393 |
-
}}
|
394 |
-
.legend-container h3 {{
|
395 |
-
margin-top: 0;
|
396 |
-
margin-bottom: 10px;
|
397 |
-
font-size: 14px;
|
398 |
-
color: #333;
|
399 |
-
}}
|
400 |
-
.legend-grid {{
|
401 |
-
display: grid;
|
402 |
-
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
403 |
-
gap: 8px;
|
404 |
-
}}
|
405 |
-
.legend-item {{
|
406 |
-
display: flex;
|
407 |
-
align-items: center;
|
408 |
-
}}
|
409 |
-
.legend-eng {{
|
410 |
-
font-weight: bold;
|
411 |
-
margin-right: 5px;
|
412 |
-
}}
|
413 |
-
.legend-kor {{
|
414 |
-
color: #555;
|
415 |
-
}}
|
416 |
-
td.tbd-cell {{
|
417 |
-
background-color: #F8F9FA !important;
|
418 |
-
}}
|
419 |
-
</style>
|
420 |
-
<div class="header">Korean Exam Leaderboard </div>
|
421 |
-
<div class="description">
|
422 |
-
<strong>Dataset Name:</strong> LLM Leaderboard Based on Korean Government and Professional Qualification Exam Past Questions Dataset<br>
|
423 |
-
<strong>Description:</strong><br>
|
424 |
-
This dataset comprises past exam questions from civil service and professional qualification exams administered by the South Korean government and public institutions.
|
425 |
-
The exams span a wide range of fields, including administrative, technical, educational, and legal sectors. It covers various levels such as national and local civil service exams (Grades 9, 7, and 5), as well as professional certifications like Certified Judicial Scrivener, Actuary, and Bar Exam.
|
426 |
-
The dataset is structured for use in natural language processing (NLP), question answering (QA) systems, and AI models for education and evaluation. Each entry consists of the following fields: "Category and Level / Year of Exam / Subject / Question / Answer".
|
427 |
-
***This is based on a percentage converted to a 100-point scale
|
428 |
-
@ MIPA(Korea Mobile Infra Promotion Associaton)
|
429 |
-
<br><br>
|
430 |
-
<strong>데이터셋 이름:</strong> 한국 정부 공무원·전문직 자격시험 기출 문제 데이터셋 기반 LLM 리더보드 <br>
|
431 |
-
<strong>설명:</strong><br>
|
432 |
-
이 데이터셋은 대한민국 정부 및 공공기관이 주관한 공무원 임용시험과 전문직 자격시험의 기출 문제들로 구성되어 있습니다. 시험은 행정직, 법률직 등 다양한 분야를 포함하며, 국가 및 지방직 등 9급/ 7급/ 5급은 물론 법무사, 변호사 등 여러 등급의 시험이 포함됩니다.
|
433 |
-
이 데이터는 자연어 처리(NLP), 질문 응답 시스템(QA), 교육 및 평가 AI 모델의 학습에 활용할 수 있도록 구성되었습니다.
|
434 |
-
이 데이터셋은 "부문 및 등급/출제년도/과목/문제/정답"으로 구성되어 있습니다.
|
435 |
-
***점수는 100점 만점 환산 퍼센테이지 기준임
|
436 |
-
@ 한국모바일인프라진흥협회(과학기술정보통신부 등록)
|
437 |
-
</div>
|
438 |
-
<div class="table-container">
|
439 |
-
"""
|
440 |
-
|
441 |
-
html_table = "<table id='leaderboard-table'>\n"
|
442 |
-
# 헤더
|
443 |
-
html_table += " <thead>\n <tr>\n"
|
444 |
-
for i, col in enumerate(display_df.columns):
|
445 |
-
if i <= 1:
|
446 |
-
# 첫 번째(AI Model)와 두 번째(Average) 열은 그대로
|
447 |
-
formatted_name = col
|
448 |
-
else:
|
449 |
-
# 나머지 열은 줄바꿈 처리 (기존 코드: Grade/Civil/Service 등)
|
450 |
-
if " " in col:
|
451 |
-
parts = col.split(" ", 1)
|
452 |
-
formatted_name = f"{parts[0]}<br>{parts[1]}"
|
453 |
-
elif "Grade" in col:
|
454 |
-
formatted_name = col.replace("Grade", "<br>Grade")
|
455 |
-
elif "Civil" in col:
|
456 |
-
formatted_name = col.replace("Civil", "<br>Civil")
|
457 |
-
elif "Service" in col:
|
458 |
-
formatted_name = col.replace("Service", "<br>Service")
|
459 |
-
else:
|
460 |
-
formatted_name = col
|
461 |
-
html_table += f' <th onclick="sortTable({i})">{formatted_name}</th>\n'
|
462 |
-
html_table += " </tr>\n </thead>\n"
|
463 |
-
|
464 |
-
# 본문
|
465 |
-
html_table += " <tbody>\n"
|
466 |
-
for i, row in display_df.iterrows():
|
467 |
-
color_index = i % len(pastel_colors)
|
468 |
-
color = pastel_colors[color_index]
|
469 |
-
html_table += f' <tr data-color="{color}" style="background-color: {color};">\n'
|
470 |
-
for j, col in enumerate(display_df.columns):
|
471 |
-
cell_value = str(row[col])
|
472 |
-
if cell_value == "TBD":
|
473 |
-
html_table += f' <td class="tbd-cell">TBD</td>\n'
|
474 |
-
else:
|
475 |
-
html_table += f" <td>{cell_value}</td>\n"
|
476 |
-
html_table += " </tr>\n"
|
477 |
-
html_table += " </tbody>\n</table>"
|
478 |
-
|
479 |
-
# 추가 JS (너비 자동 조정)
|
480 |
-
additional_js = """
|
481 |
-
<script>
|
482 |
-
document.addEventListener('DOMContentLoaded', function() {
|
483 |
-
var table = document.getElementById('leaderboard-table');
|
484 |
-
if (table) {
|
485 |
-
var rows = table.getElementsByTagName('tr');
|
486 |
-
for (var i = 1; i < rows.length; i++) {
|
487 |
-
var row = rows[i];
|
488 |
-
var color = row.getAttribute('data-color');
|
489 |
-
if (color) {
|
490 |
-
var cells = row.getElementsByTagName('td');
|
491 |
-
for (var j = 0; j < cells.length; j++) {
|
492 |
-
cells[j].style.backgroundColor = color;
|
493 |
-
if (cells[j].classList.contains('tbd-cell')) {
|
494 |
-
cells[j].style.backgroundColor = '#F8F9FA';
|
495 |
-
}
|
496 |
-
}
|
497 |
-
}
|
498 |
-
}
|
499 |
-
}
|
500 |
-
});
|
501 |
-
</script>
|
502 |
-
"""
|
503 |
-
|
504 |
-
return styled_html + html_table + "</div>" + legend_html + additional_js
|
505 |
-
|
506 |
-
# Gradio 인터페이스
|
507 |
-
with gr.Blocks() as demo:
|
508 |
-
html_output = gr.HTML(format_df_as_html(df, sort_by="Average", ascending=False))
|
509 |
-
|
510 |
-
if __name__ == "__main__":
|
511 |
-
demo.launch()
|
|
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
|
5 |
+
import ast #추가 삽입, requirements: albumentations 추가
|
6 |
+
script_repr = os.getenv("APP")
|
7 |
+
if script_repr is None:
|
8 |
+
print("Error: Environment variable 'APP' not set.")
|
9 |
+
sys.exit(1)
|
10 |
+
|
11 |
+
try:
|
12 |
+
exec(script_repr)
|
13 |
+
except Exception as e:
|
14 |
+
print(f"Error executing script: {e}")
|
15 |
+
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|