Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| from math import isnan | |
| ROWS = [ | |
| {"Team_name":"Nguyen Quang Thao","vi-law-nli":0.5816,"vi-law-qa":0.8217,"vilaw-syllo":0.38,"Avg":0.5944333333}, | |
| {"Team_name":"NHK","vi-law-nli":0.9333,"vi-law-qa":0.8683,"vilaw-syllo":0.3275,"Avg":0.7097}, | |
| {"Team_name":"Innovation-LLM","vi-law-nli":0.9567,"vi-law-qa":0.8367,"vilaw-syllo":0.541666667,"Avg":0.7783555556}, | |
| {"Team_name":"Bosch@AI Team","vi-law-nli":0.97,"vi-law-qa":0.9267,"vilaw-syllo":0.535833333,"Avg":0.8108444444}, | |
| {"Team_name":"URAx","vi-law-nli":0.945,"vi-law-qa":0.8333,"vilaw-syllo":0.576666667,"Avg":0.7849888889}, | |
| {"Team_name":"Abe","vi-law-nli":0.82,"vi-law-qa":0.84,"vilaw-syllo":0.2875,"Avg":0.6491666667}, | |
| {"Team_name":"PSLV-Warrior","vi-law-nli":0.8517,"vi-law-qa":0.7483,"vilaw-syllo":0.525,"Avg":0.7083333333}, | |
| {"Team_name":"MinLegal","vi-law-nli":0.98,"vi-law-qa":0.8733,"vilaw-syllo":0.530833333,"Avg":0.7947111111}, | |
| {"Team_name":"NLPhi","vi-law-nli":0.6517,"vi-law-qa":0.815,"vilaw-syllo":0.479166667,"Avg":0.6486222222}, | |
| {"Team_name":"LICTU","vi-law-nli":0.8467,"vi-law-qa":0.8067,"vilaw-syllo":0.5375,"Avg":0.7303}, | |
| ] | |
| BASE_DF = pd.DataFrame(ROWS) | |
| NUM_COLS = ["vi-law-nli", "vi-law-qa", "vilaw-syllo", "Avg"] | |
| def _prep_df(df: pd.DataFrame) -> pd.DataFrame: | |
| out = df.copy() | |
| for c in NUM_COLS: | |
| out[c] = pd.to_numeric(out[c], errors="coerce").astype(float).round(6) | |
| out = out.sort_values("Avg", ascending=False, kind="mergesort").reset_index(drop=True) | |
| out.insert(0, "Rank", range(1, len(out)+1)) | |
| return out | |
| def _bar_html(v: float) -> str: | |
| if v is None or (isinstance(v, float) and isnan(v)): | |
| return "-" | |
| pct = max(0.0, min(1.0, float(v))) * 100 | |
| return f"<div class='cell'><div class='bar' style='width:{pct:.2f}%'></div><span class='val'>{v:.4f}</span></div>" | |
| def _render_table(df: pd.DataFrame) -> str: | |
| cols = ["Rank","Team_name"]+NUM_COLS | |
| header = "".join([f"<th>{c}</th>" for c in cols]) | |
| rows_html = [] | |
| for _, row in df.iterrows(): | |
| tds = [ | |
| f"<td class='rank'>{int(row['Rank'])}</td>", | |
| f"<td class='team'>{row['Team_name']}</td>", | |
| f"<td>{_bar_html(row['vi-law-nli'])}</td>", | |
| f"<td>{_bar_html(row['vi-law-qa'])}</td>", | |
| f"<td>{_bar_html(row['vilaw-syllo'])}</td>", | |
| f"<td>{_bar_html(row['Avg'])}</td>", | |
| ] | |
| rows_html.append(f"<tr>{''.join(tds)}</tr>") | |
| return f"<table class='lb-table'><thead><tr>{header}</tr></thead><tbody>{''.join(rows_html)}</tbody></table>" | |
| def _filter_and_sort(search: str, quick: str): | |
| df = BASE_DF.copy() | |
| if search: | |
| terms = [t.strip() for t in search.split(";") if t.strip()] | |
| for t in terms: | |
| df = df[df["Team_name"].str.contains(t, case=False, na=False)] | |
| if quick == "Top 3": | |
| df = df.sort_values("Avg", ascending=False).head(3) | |
| elif quick == "Top 5": | |
| df = df.sort_values("Avg", ascending=False).head(5) | |
| else: | |
| df = df.sort_values("Avg", ascending=False) | |
| return _prep_df(df) | |
| def _controller(search, quick): | |
| df = _filter_and_sort(search, quick) | |
| return _render_table(df), df | |
| CUSTOM_CSS = """ | |
| :root { | |
| --bg: #ffffff; --panel:#f8f9fa; --text:#000000; --muted:#6c757d; --bar:#28a745; --bar-bg:#e9ecef; | |
| } | |
| /* Global Gradio container styling */ | |
| .gradio-container { | |
| background: var(--bg) !important; | |
| color: var(--text) !important; | |
| } | |
| /* Main background */ | |
| .main { | |
| background: var(--bg) !important; | |
| } | |
| /* Panel backgrounds */ | |
| .panel { | |
| background: var(--panel) !important; | |
| } | |
| /* Text elements */ | |
| h1, h2, h3, h4, h5, h6, p, span, div { | |
| color: var(--text) !important; | |
| } | |
| /* Form elements */ | |
| input, textarea, select { | |
| background: #ffffff !important; | |
| color: var(--text) !important; | |
| border: 1px solid #ced4da !important; | |
| } | |
| /* Labels */ | |
| label { | |
| color: var(--text) !important; | |
| font-weight: 500 !important; | |
| } | |
| /* Radio buttons */ | |
| .radio-group { | |
| background: var(--panel) !important; | |
| } | |
| .radio-group label { | |
| color: var(--text) !important; | |
| } | |
| /* Buttons */ | |
| button { | |
| background: var(--bar) !important; | |
| color: white !important; | |
| border: none !important; | |
| } | |
| button:hover { | |
| background: #218838 !important; | |
| } | |
| /* Table styling */ | |
| .lb-table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| background: var(--bg) !important; | |
| } | |
| .lb-table thead th { | |
| background: var(--panel) !important; | |
| padding: 10px; | |
| text-align: left; | |
| color: var(--text) !important; | |
| border-bottom: 2px solid #dee2e6 !important; | |
| } | |
| .lb-table tbody td { | |
| padding: 10px; | |
| border-bottom: 1px solid #dee2e6; | |
| color: var(--text) !important; | |
| } | |
| .lb-table td.rank { | |
| width: 60px; | |
| font-weight: 700; | |
| color: var(--text) !important; | |
| } | |
| .lb-table td.team { | |
| min-width: 200px; | |
| color: var(--text) !important; | |
| } | |
| /* Progress bars */ | |
| .cell { | |
| position: relative; | |
| height: 20px; | |
| background: var(--bar-bg); | |
| border-radius: 6px; | |
| } | |
| .cell .bar { | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| bottom: 0; | |
| background: var(--bar); | |
| } | |
| .cell .val { | |
| position: absolute; | |
| right: 8px; | |
| top: 0; | |
| bottom: 0; | |
| display: flex; | |
| align-items: center; | |
| color: var(--text) !important; | |
| font-weight: 500 !important; | |
| } | |
| /* Gradio specific overrides */ | |
| .gradio-input, .gradio-output { | |
| background: var(--bg) !important; | |
| color: var(--text) !important; | |
| } | |
| .gradio-input input, .gradio-input textarea { | |
| background: #ffffff !important; | |
| color: var(--text) !important; | |
| border: 1px solid #ced4da !important; | |
| } | |
| .gradio-input label { | |
| color: var(--text) !important; | |
| } | |
| .gradio-radio { | |
| background: var(--panel) !important; | |
| } | |
| .gradio-radio label { | |
| color: var(--text) !important; | |
| } | |
| /* Search bar specific styling */ | |
| .gradio-input-container { | |
| background: var(--bg) !important; | |
| } | |
| .gradio-input-container label { | |
| color: var(--text) !important; | |
| background: var(--bg) !important; | |
| } | |
| /* Target the search input specifically */ | |
| .gradio-input input[type="text"] { | |
| background: #ffffff !important; | |
| color: var(--text) !important; | |
| border: 1px solid #ced4da !important; | |
| } | |
| /* Override any dark backgrounds on input containers */ | |
| .gradio-input > div { | |
| background: var(--bg) !important; | |
| } | |
| /* Ensure labels are black text on white background */ | |
| .gradio-input label, .gradio-input-container label { | |
| color: var(--text) !important; | |
| background: var(--bg) !important; | |
| } | |
| /* Override any panel backgrounds that might be dark */ | |
| .gradio-input .panel, .gradio-input .gradio-panel { | |
| background: var(--bg) !important; | |
| } | |
| /* Force all input-related elements to have light backgrounds */ | |
| .gradio-input, .gradio-input *, .gradio-input-container, .gradio-input-container * { | |
| background: var(--bg) !important; | |
| } | |
| /* Override any dark backgrounds on the entire row containing search and filter */ | |
| .gradio-row { | |
| background: var(--bg) !important; | |
| } | |
| .gradio-row * { | |
| background: var(--bg) !important; | |
| } | |
| /* Specific targeting for search and filter containers */ | |
| .gradio-input[data-testid="textbox"], .gradio-input[data-testid="radio"] { | |
| background: var(--bg) !important; | |
| } | |
| .gradio-input[data-testid="textbox"] label, .gradio-input[data-testid="radio"] label { | |
| color: var(--text) !important; | |
| background: var(--bg) !important; | |
| } | |
| /* Override any remaining dark backgrounds */ | |
| .gradio-input, .gradio-input-container, .gradio-input-container > div { | |
| background: var(--bg) !important; | |
| } | |
| /* Ensure the search input field itself is white */ | |
| input[type="text"], input[placeholder*="Tìm team"] { | |
| background: #ffffff !important; | |
| color: var(--text) !important; | |
| border: 1px solid #ced4da !important; | |
| } | |
| /* Aggressive override for the dark panel container */ | |
| .gradio-input, .gradio-input-container, .gradio-input-container > div, | |
| .gradio-input > div, .gradio-input > div > div { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Force all elements in the search row to have white backgrounds */ | |
| .gradio-row, .gradio-row > div, .gradio-row > div > div, | |
| .gradio-row .gradio-input, .gradio-row .gradio-input-container { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Override any remaining dark backgrounds with maximum specificity */ | |
| .gradio-input, .gradio-input *, .gradio-input-container, .gradio-input-container *, | |
| .gradio-input > div, .gradio-input > div *, .gradio-input-container > div, .gradio-input-container > div * { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Target the specific search and filter components */ | |
| .gradio-input[data-testid="textbox"], .gradio-input[data-testid="radio"], | |
| .gradio-input[data-testid="textbox"] *, .gradio-input[data-testid="radio"] * { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Override any CSS variables that might be setting dark backgrounds */ | |
| .gradio-input, .gradio-input-container { | |
| --background: var(--bg) !important; | |
| --background-color: var(--bg) !important; | |
| --panel-background: var(--bg) !important; | |
| --panel-background-color: var(--bg) !important; | |
| } | |
| /* Target the dark panel wrapper specifically */ | |
| .gradio-panel, .gradio-panel *, .gradio-container .gradio-panel, | |
| .gradio-container .gradio-panel *, .gradio-input .gradio-panel, | |
| .gradio-input .gradio-panel * { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Override any remaining dark backgrounds with !important */ | |
| .gradio-input, .gradio-input-container, .gradio-input-container > div, | |
| .gradio-input > div, .gradio-input > div > div, | |
| .gradio-input > div > div > div, .gradio-input > div > div > div > div { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Force the entire search row to be white */ | |
| .gradio-row, .gradio-row *, .gradio-row > div, .gradio-row > div *, | |
| .gradio-row > div > div, .gradio-row > div > div * { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Maximum specificity override for any dark backgrounds */ | |
| .gradio-input, .gradio-input-container, .gradio-input-container > div, | |
| .gradio-input > div, .gradio-input > div *, .gradio-input-container > div, | |
| .gradio-input-container > div *, .gradio-input > div > div, .gradio-input > div > div *, | |
| .gradio-input > div > div > div, .gradio-input > div > div > div * { | |
| background: var(--bg) !important; | |
| background-color: var(--bg) !important; | |
| } | |
| /* Download button */ | |
| .gradio-button { | |
| background: var(--bar) !important; | |
| color: white !important; | |
| border: none !important; | |
| padding: 8px 16px !important; | |
| border-radius: 6px !important; | |
| } | |
| .gradio-button:hover { | |
| background: #218838 !important; | |
| } | |
| """ | |
| with gr.Blocks(theme=gr.themes.Soft(), css=CUSTOM_CSS) as demo: | |
| gr.Markdown("# 🏆 LegalSLM Leaderboard") | |
| with gr.Row(): | |
| search = gr.Textbox(placeholder="Tìm team...", label="Search") | |
| quick = gr.Radio(choices=["All","Top 3","Top 5"], value="All", label="Quick Filter") | |
| html_table = gr.HTML(value=_render_table(_prep_df(BASE_DF))) | |
| csv_state = gr.State(_prep_df(BASE_DF)) | |
| download = gr.DownloadButton("⬇️ Tải CSV") | |
| def _download(df): | |
| path = "/tmp/leaderboard.csv" | |
| df.to_csv(path,index=False) | |
| return path | |
| download.click(_download, inputs=[csv_state], outputs=download) | |
| for comp in [search, quick]: | |
| comp.change(_controller, [search, quick], [html_table, csv_state]) | |
| if __name__ == "__main__": | |
| demo.launch() | |
| # ########################################################____V1_____############################ | |
| # # app.py | |
| # import gradio as gr | |
| # import pandas as pd | |
| # from math import isnan | |
| # ROWS = [ | |
| # {"Team_name":"Nguyen Quang Thao","vi-law-nli":0.5816,"vi-law-qa":0.8217,"vilaw-syllo":0.38,"Avg":0.5944333333}, | |
| # {"Team_name":"NHK","vi-law-nli":0.9333,"vi-law-qa":0.8683,"vilaw-syllo":0.3275,"Avg":0.7097}, | |
| # {"Team_name":"Innovation-LLM","vi-law-nli":0.9567,"vi-law-qa":0.8367,"vilaw-syllo":0.541666667,"Avg":0.7783555556}, | |
| # {"Team_name":"Bosch@AI Team","vi-law-nli":0.97,"vi-law-qa":0.9267,"vilaw-syllo":0.535833333,"Avg":0.8108444444}, | |
| # {"Team_name":"URAx","vi-law-nli":0.945,"vi-law-qa":0.8333,"vilaw-syllo":0.576666667,"Avg":0.7849888889}, | |
| # {"Team_name":"Abe","vi-law-nli":0.82,"vi-law-qa":0.84,"vilaw-syllo":0.2875,"Avg":0.6491666667}, | |
| # {"Team_name":"PSLV-Warrior","vi-law-nli":0.565,"vi-law-qa":0.0333,"vilaw-syllo":0.525,"Avg":0.3744333333}, | |
| # {"Team_name":"MinLegal","vi-law-nli":0.98,"vi-law-qa":0.8733,"vilaw-syllo":0.530833333,"Avg":0.7947111111}, | |
| # {"Team_name":"NLPhi","vi-law-nli":0.6517,"vi-law-qa":0.815,"vilaw-syllo":0.479166667,"Avg":0.6486222222}, | |
| # {"Team_name":"LICTU","vi-law-nli":0.8467,"vi-law-qa":0.8067,"vilaw-syllo":0.5375,"Avg":0.7303}, | |
| # ] | |
| # BASE_DF = pd.DataFrame(ROWS) | |
| # NUM_COLS = ["vi-law-nli", "vi-law-qa", "vilaw-syllo", "Avg"] | |
| # def _prep_df(df: pd.DataFrame) -> pd.DataFrame: | |
| # out = df.copy() | |
| # for c in NUM_COLS: | |
| # out[c] = pd.to_numeric(out[c], errors="coerce").astype(float).round(6) | |
| # out = out.sort_values("Avg", ascending=False, kind="mergesort").reset_index(drop=True) | |
| # out.insert(0, "Rank", range(1, len(out)+1)) | |
| # return out | |
| # def _bar_html(v: float) -> str: | |
| # if v is None or (isinstance(v, float) and isnan(v)): | |
| # return "-" | |
| # pct = max(0.0, min(1.0, float(v))) * 100 | |
| # return f"<div class='cell'><div class='bar' style='width:{pct:.2f}%'></div><span class='val'>{v:.4f}</span></div>" | |
| # def _render_table(df: pd.DataFrame) -> str: | |
| # cols = ["Rank","Team_name"]+NUM_COLS | |
| # header = "".join([f"<th>{c}</th>" for c in cols]) | |
| # rows_html = [] | |
| # for _, row in df.iterrows(): | |
| # tds = [ | |
| # f"<td class='rank'>{int(row['Rank'])}</td>", | |
| # f"<td class='team'>{row['Team_name']}</td>", | |
| # f"<td>{_bar_html(row['vi-law-nli'])}</td>", | |
| # f"<td>{_bar_html(row['vi-law-qa'])}</td>", | |
| # f"<td>{_bar_html(row['vilaw-syllo'])}</td>", | |
| # f"<td>{_bar_html(row['Avg'])}</td>", | |
| # ] | |
| # rows_html.append(f"<tr>{''.join(tds)}</tr>") | |
| # return f"<table class='lb-table'><thead><tr>{header}</tr></thead><tbody>{''.join(rows_html)}</tbody></table>" | |
| # def _filter_and_sort(search: str, quick: str): | |
| # df = BASE_DF.copy() | |
| # if search: | |
| # terms = [t.strip() for t in search.split(";") if t.strip()] | |
| # for t in terms: | |
| # df = df[df["Team_name"].str.contains(t, case=False, na=False)] | |
| # if quick == "Top 3": | |
| # df = df.sort_values("Avg", ascending=False).head(3) | |
| # elif quick == "Top 5": | |
| # df = df.sort_values("Avg", ascending=False).head(5) | |
| # else: | |
| # df = df.sort_values("Avg", ascending=False) | |
| # return _prep_df(df) | |
| # def _controller(search, quick): | |
| # df = _filter_and_sort(search, quick) | |
| # return _render_table(df), df | |
| # CUSTOM_CSS = """ | |
| # :root { | |
| # --bg: #0e1116; --panel:#12161f; --text:#e6e6e6; --muted:#9aa3b2; --bar:#2ea043; --bar-bg:#1f2a36; | |
| # } | |
| # .gradio-container {background: var(--bg)!important; color: var(--text);} | |
| # .lb-table { width:100%; border-collapse: collapse; } | |
| # .lb-table thead th { background: var(--panel); padding: 10px; text-align:left; } | |
| # .lb-table tbody td { padding: 10px; border-bottom: 1px solid #1d2430; } | |
| # .lb-table td.rank { width:60px; font-weight:700; } | |
| # .lb-table td.team { min-width:200px; } | |
| # .cell { position:relative; height:20px; background: var(--bar-bg); border-radius:6px; } | |
| # .cell .bar { position:absolute; left:0; top:0; bottom:0; background: var(--bar);} | |
| # .cell .val { position:absolute; right:8px; top:0; bottom:0; display:flex; align-items:center; } | |
| # """ | |
| # with gr.Blocks(css=CUSTOM_CSS) as demo: | |
| # gr.Markdown("# 🏆 LegalSLM Leaderboard") | |
| # with gr.Row(): | |
| # search = gr.Textbox(placeholder="Tìm team...", label="Search") | |
| # quick = gr.Radio(choices=["All","Top 3","Top 5"], value="All", label="Quick Filter") | |
| # html_table = gr.HTML(value=_render_table(_prep_df(BASE_DF))) | |
| # csv_state = gr.State(_prep_df(BASE_DF)) | |
| # download = gr.DownloadButton("⬇️ Tải CSV") | |
| # def _download(df): | |
| # path = "/tmp/leaderboard.csv" | |
| # df.to_csv(path,index=False) | |
| # return path | |
| # download.click(_download, inputs=[csv_state], outputs=download) | |
| # for comp in [search, quick]: | |
| # comp.change(_controller, [search, quick], [html_table, csv_state]) | |
| # if __name__ == "__main__": | |
| # demo.launch() | |