update submission
Browse files- app.py +204 -47
- content.py +5 -4
- data/model.jsonl +36 -8
- submission.py +426 -252
app.py
CHANGED
|
@@ -536,6 +536,144 @@ def create_capability_subplots(data_dict, title="Capability Performance", top_n=
|
|
| 536 |
return fig
|
| 537 |
|
| 538 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 539 |
def create_summary_table(capability_dict, domain_dict, verified_dict, type_name="Agent"):
|
| 540 |
"""
|
| 541 |
Create summary table showing rank, average accuracy and F1 scores.
|
|
@@ -675,19 +813,38 @@ def build_app():
|
|
| 675 |
if not any(len(category_data) > 0 for category_data in model_domain_filtered.values()):
|
| 676 |
model_domain_filtered = {}
|
| 677 |
|
| 678 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 679 |
|
| 680 |
# Header
|
| 681 |
-
gr.HTML(
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
|
| 685 |
-
|
| 686 |
-
|
| 687 |
-
|
| 688 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 689 |
</div>
|
| 690 |
-
"""
|
|
|
|
| 691 |
|
| 692 |
# Welcome Banner
|
| 693 |
gr.HTML("""
|
|
@@ -749,13 +906,11 @@ def build_app():
|
|
| 749 |
|
| 750 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 751 |
gr.Markdown("""
|
| 752 |
-
**Verification Status:**
|
| 753 |
-
• **✓** = Officially verified by LLM-as-Judge
|
| 754 |
-
• **○** = User-submitted, pending official verification
|
| 755 |
""")
|
| 756 |
agent_domain_table = gr.Dataframe(
|
| 757 |
-
value=
|
| 758 |
-
label="
|
| 759 |
)
|
| 760 |
|
| 761 |
# Update chart when slider changes
|
|
@@ -796,13 +951,11 @@ def build_app():
|
|
| 796 |
|
| 797 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 798 |
gr.Markdown("""
|
| 799 |
-
**Verification Status:**
|
| 800 |
-
• **✓** = Officially verified by LLM-as-Judge
|
| 801 |
-
• **○** = User-submitted, pending official verification
|
| 802 |
""")
|
| 803 |
agent_capability_table = gr.Dataframe(
|
| 804 |
-
value=
|
| 805 |
-
label="
|
| 806 |
)
|
| 807 |
|
| 808 |
# Update chart when slider changes
|
|
@@ -853,13 +1006,11 @@ def build_app():
|
|
| 853 |
|
| 854 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 855 |
gr.Markdown("""
|
| 856 |
-
**Verification Status:**
|
| 857 |
-
• **✓** = Officially verified by LLM-as-Judge
|
| 858 |
-
• **○** = User-submitted, pending official verification
|
| 859 |
""")
|
| 860 |
model_domain_table = gr.Dataframe(
|
| 861 |
-
value=
|
| 862 |
-
label="
|
| 863 |
)
|
| 864 |
|
| 865 |
# Update chart when slider changes
|
|
@@ -900,13 +1051,11 @@ def build_app():
|
|
| 900 |
|
| 901 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 902 |
gr.Markdown("""
|
| 903 |
-
**Verification Status:**
|
| 904 |
-
• **✓** = Officially verified by LLM-as-Judge
|
| 905 |
-
• **○** = User-submitted, pending official verification
|
| 906 |
""")
|
| 907 |
model_capability_table = gr.Dataframe(
|
| 908 |
-
value=
|
| 909 |
-
label="
|
| 910 |
)
|
| 911 |
|
| 912 |
# Update chart when slider changes
|
|
@@ -971,48 +1120,56 @@ def build_app():
|
|
| 971 |
)
|
| 972 |
|
| 973 |
gr.Markdown("""
|
| 974 |
-
**📋
|
| 975 |
|
| 976 |
-
Your JSONL file should contain one
|
| 977 |
|
| 978 |
```json
|
| 979 |
{
|
| 980 |
"episode_id": "trajectory_id",
|
| 981 |
-
"
|
|
|
|
| 982 |
"llm_as_judge_score_list": [true, false, true]
|
| 983 |
}
|
| 984 |
```
|
| 985 |
|
| 986 |
**Field Descriptions:**
|
| 987 |
-
- `episode_id` (required): The episode identifier
|
| 988 |
-
- `
|
| 989 |
-
- `
|
| 990 |
-
|
| 991 |
-
- If not provided, scoring will be done during weekly official evaluation
|
| 992 |
-
- Official scores (`verified=true`) are computed by our LLM-as-Judge system
|
| 993 |
|
| 994 |
**Important Notes:**
|
| 995 |
-
- `answer_list` and `llm_as_judge_score_list` must
|
| 996 |
-
-
|
|
|
|
| 997 |
""")
|
| 998 |
|
| 999 |
with gr.Row():
|
| 1000 |
submit_button = gr.Button("Submit", variant="primary", size="lg")
|
| 1001 |
|
| 1002 |
-
submission_result = gr.
|
| 1003 |
|
| 1004 |
submit_button.click(
|
| 1005 |
-
|
| 1006 |
-
[
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1007 |
model_name_textbox,
|
| 1008 |
submission_type,
|
| 1009 |
url_textbox,
|
| 1010 |
file_upload,
|
| 1011 |
organisation,
|
| 1012 |
mail,
|
| 1013 |
-
model_family_textbox
|
| 1014 |
],
|
| 1015 |
-
submission_result,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1016 |
)
|
| 1017 |
|
| 1018 |
# ============================================================
|
|
@@ -1078,4 +1235,4 @@ Results are reported as **Accuracy** and **F1 Score**:
|
|
| 1078 |
|
| 1079 |
if __name__ == "__main__":
|
| 1080 |
demo_app = build_app()
|
| 1081 |
-
demo_app.launch(debug=True, show_error=True)
|
|
|
|
| 536 |
return fig
|
| 537 |
|
| 538 |
|
| 539 |
+
def _rank_prefix(i):
|
| 540 |
+
medals = ["🥇", "🥈", "🥉"]
|
| 541 |
+
return f"{medals[i]} {i+1}" if i < 3 else str(i + 1)
|
| 542 |
+
|
| 543 |
+
|
| 544 |
+
def _fmt(v):
|
| 545 |
+
return f"{v * 100:.2f}%"
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
def _build_rows_sorted(items, verified_dict, score_fn, type_name):
|
| 549 |
+
"""
|
| 550 |
+
Build rows for verified entries only (verified=True).
|
| 551 |
+
Unverified submissions are excluded from the leaderboard display.
|
| 552 |
+
"""
|
| 553 |
+
rows = []
|
| 554 |
+
for item in sorted(items):
|
| 555 |
+
if not verified_dict.get(item, False):
|
| 556 |
+
continue
|
| 557 |
+
row = score_fn(item, True, type_name)
|
| 558 |
+
rows.append(row)
|
| 559 |
+
|
| 560 |
+
rows.sort(key=lambda r: r["_sort"], reverse=True)
|
| 561 |
+
for i, r in enumerate(rows):
|
| 562 |
+
r["Rank"] = _rank_prefix(i)
|
| 563 |
+
|
| 564 |
+
return rows
|
| 565 |
+
|
| 566 |
+
|
| 567 |
+
def create_capability_table(capability_dict, domain_dict, verified_dict, type_name="Agent"):
|
| 568 |
+
"""
|
| 569 |
+
Summary table grouped by capability (A/B/C/D).
|
| 570 |
+
verified=True → ranked by official score
|
| 571 |
+
verified=False → appended unranked, scores marked with * (self-reported)
|
| 572 |
+
"""
|
| 573 |
+
items = set()
|
| 574 |
+
for d in domain_dict.values():
|
| 575 |
+
items.update(d.keys())
|
| 576 |
+
if not items:
|
| 577 |
+
return pd.DataFrame()
|
| 578 |
+
|
| 579 |
+
cap_cols = {
|
| 580 |
+
"Recall": "Recall (A)",
|
| 581 |
+
"Causal Inference": "Causal Inf. (B)",
|
| 582 |
+
"State Updating": "State Upd. (C)",
|
| 583 |
+
"State Abstraction": "State Abs. (D)",
|
| 584 |
+
}
|
| 585 |
+
cap_weights = {}
|
| 586 |
+
if QA_DISTRIBUTION:
|
| 587 |
+
pt = QA_DISTRIBUTION.get("overall_distribution", {}).get("problem_types", {})
|
| 588 |
+
letter_to_cap = {"A": "Recall", "B": "Causal Inference",
|
| 589 |
+
"C": "State Updating", "D": "State Abstraction"}
|
| 590 |
+
for letter, info in pt.items():
|
| 591 |
+
cap_weights[letter_to_cap.get(letter, "")] = info.get("ratio", 0.0)
|
| 592 |
+
|
| 593 |
+
def score_fn(item, is_verified, type_name):
|
| 594 |
+
model_family = ""
|
| 595 |
+
for cd in capability_dict.values():
|
| 596 |
+
if item in cd and isinstance(cd[item], dict):
|
| 597 |
+
model_family = cd[item].get("model_family", "")
|
| 598 |
+
if model_family:
|
| 599 |
+
break
|
| 600 |
+
|
| 601 |
+
cap_scores = {}
|
| 602 |
+
for cap_name in cap_cols:
|
| 603 |
+
d = capability_dict.get(cap_name, {}).get(item, {})
|
| 604 |
+
cap_scores[cap_name] = d.get("accuracy", 0.0) if isinstance(d, dict) else 0.0
|
| 605 |
+
|
| 606 |
+
w_sum = sum(cap_scores[c] * cap_weights.get(c, 0.0) for c in cap_cols)
|
| 607 |
+
w_tot = sum(cap_weights.get(c, 0.0) for c in cap_cols)
|
| 608 |
+
avg = w_sum / w_tot if w_tot > 0 else sum(cap_scores.values()) / len(cap_scores)
|
| 609 |
+
|
| 610 |
+
row = {
|
| 611 |
+
type_name: f"{item} {'✓' if is_verified else '○'}",
|
| 612 |
+
"Model Family": model_family,
|
| 613 |
+
"Avg Score": _fmt(avg),
|
| 614 |
+
"_sort": avg,
|
| 615 |
+
}
|
| 616 |
+
for cap_name, col_label in cap_cols.items():
|
| 617 |
+
row[col_label] = _fmt(cap_scores[cap_name])
|
| 618 |
+
return row
|
| 619 |
+
|
| 620 |
+
rows = _build_rows_sorted(items, verified_dict, score_fn, type_name)
|
| 621 |
+
return pd.DataFrame([
|
| 622 |
+
{"Rank": r["Rank"], **{k: v for k, v in r.items() if k not in ("Rank", "_sort")}}
|
| 623 |
+
for r in rows
|
| 624 |
+
])
|
| 625 |
+
|
| 626 |
+
|
| 627 |
+
def create_domain_table(capability_dict, domain_dict, verified_dict, type_name="Agent"):
|
| 628 |
+
"""
|
| 629 |
+
Summary table grouped by domain.
|
| 630 |
+
verified=True → ranked by official score
|
| 631 |
+
verified=False → appended unranked, scores marked with * (self-reported)
|
| 632 |
+
"""
|
| 633 |
+
items = set()
|
| 634 |
+
for d in domain_dict.values():
|
| 635 |
+
items.update(d.keys())
|
| 636 |
+
if not items:
|
| 637 |
+
return pd.DataFrame()
|
| 638 |
+
|
| 639 |
+
domain_order = ["TEXT2SQL", "SOFTWARE", "WEB", "GAME", "EMBODIED_AI", "OPENWORLD_QA"]
|
| 640 |
+
domain_weights = {}
|
| 641 |
+
if QA_DISTRIBUTION:
|
| 642 |
+
for dom, info in QA_DISTRIBUTION.get("domain_distribution", {}).items():
|
| 643 |
+
domain_weights[dom] = info.get("qa_ratio", 0.0)
|
| 644 |
+
|
| 645 |
+
def score_fn(item, is_verified, type_name):
|
| 646 |
+
model_family = ""
|
| 647 |
+
for cd in capability_dict.values():
|
| 648 |
+
if item in cd and isinstance(cd[item], dict):
|
| 649 |
+
model_family = cd[item].get("model_family", "")
|
| 650 |
+
if model_family:
|
| 651 |
+
break
|
| 652 |
+
|
| 653 |
+
dom_scores = {}
|
| 654 |
+
for dom in domain_order:
|
| 655 |
+
d = domain_dict.get(dom, {}).get(item, {})
|
| 656 |
+
dom_scores[dom] = d.get("accuracy", 0.0) if isinstance(d, dict) else 0.0
|
| 657 |
+
|
| 658 |
+
w_sum = sum(dom_scores[d] * domain_weights.get(d, 0.0) for d in domain_order)
|
| 659 |
+
w_tot = sum(domain_weights.get(d, 0.0) for d in domain_order)
|
| 660 |
+
avg = w_sum / w_tot if w_tot > 0 else sum(dom_scores.values()) / len(dom_scores)
|
| 661 |
+
|
| 662 |
+
row = {
|
| 663 |
+
type_name: f"{item} {'✓' if is_verified else '○'}",
|
| 664 |
+
"Model Family": model_family,
|
| 665 |
+
"Avg Score": _fmt(avg),
|
| 666 |
+
"_sort": avg,
|
| 667 |
+
}
|
| 668 |
+
for dom in domain_order:
|
| 669 |
+
row[dom] = _fmt(dom_scores[dom])
|
| 670 |
+
return row
|
| 671 |
+
|
| 672 |
+
rows = _build_rows_sorted(items, verified_dict, score_fn, type_name)
|
| 673 |
+
return pd.DataFrame([{"Rank": r["Rank"], **{k: v for k, v in r.items() if k != "Rank" and k != "_sort"}}
|
| 674 |
+
for r in rows])
|
| 675 |
+
|
| 676 |
+
|
| 677 |
def create_summary_table(capability_dict, domain_dict, verified_dict, type_name="Agent"):
|
| 678 |
"""
|
| 679 |
Create summary table showing rank, average accuracy and F1 scores.
|
|
|
|
| 813 |
if not any(len(category_data) > 0 for category_data in model_domain_filtered.values()):
|
| 814 |
model_domain_filtered = {}
|
| 815 |
|
| 816 |
+
import base64, pathlib
|
| 817 |
+
_logo_path = pathlib.Path("assets/ama_logo.jpg")
|
| 818 |
+
if _logo_path.exists():
|
| 819 |
+
_logo_b64 = base64.b64encode(_logo_path.read_bytes()).decode()
|
| 820 |
+
_logo_tag = (
|
| 821 |
+
'<img src="data:image/jpeg;base64,' + _logo_b64 + '"'
|
| 822 |
+
' alt="AMA-Bench" style="height:80px;object-fit:contain;flex-shrink:0;">'
|
| 823 |
+
)
|
| 824 |
+
else:
|
| 825 |
+
_logo_tag = "🤖 "
|
| 826 |
+
|
| 827 |
+
with gr.Blocks(title="AMA-Bench Leaderboard") as demo:
|
| 828 |
|
| 829 |
# Header
|
| 830 |
+
gr.HTML(
|
| 831 |
+
"""
|
| 832 |
+
<div style="display:flex; align-items:center; justify-content:center;
|
| 833 |
+
gap:24px; padding:20px 20px 10px; margin-bottom:20px;">
|
| 834 |
+
"""
|
| 835 |
+
+ _logo_tag
|
| 836 |
+
+ """
|
| 837 |
+
<div style="text-align:left;">
|
| 838 |
+
<h1 style="margin:0; font-size:48px; font-weight:700; color:#1a1a2e; line-height:1.1;">
|
| 839 |
+
AMA-Bench: Leaderboard
|
| 840 |
+
</h1>
|
| 841 |
+
<p style="font-size:18px; color:#666; margin:8px 0 0;">
|
| 842 |
+
Agent Memory Assessment Benchmark - Performance Visualization
|
| 843 |
+
</p>
|
| 844 |
+
</div>
|
| 845 |
</div>
|
| 846 |
+
"""
|
| 847 |
+
)
|
| 848 |
|
| 849 |
# Welcome Banner
|
| 850 |
gr.HTML("""
|
|
|
|
| 906 |
|
| 907 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 908 |
gr.Markdown("""
|
| 909 |
+
**Verification Status:** Only officially verified entries (✓) are shown. User-submitted results (○) will appear after weekly LLM-as-Judge evaluation.
|
|
|
|
|
|
|
| 910 |
""")
|
| 911 |
agent_domain_table = gr.Dataframe(
|
| 912 |
+
value=create_domain_table(AGENT_CAPABILITY, AGENT_DOMAIN, AGENT_VERIFIED, "Agent"),
|
| 913 |
+
label="Scores by Domain"
|
| 914 |
)
|
| 915 |
|
| 916 |
# Update chart when slider changes
|
|
|
|
| 951 |
|
| 952 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 953 |
gr.Markdown("""
|
| 954 |
+
**Verification Status:** Only officially verified entries (✓) are shown. User-submitted results (○) will appear after weekly LLM-as-Judge evaluation.
|
|
|
|
|
|
|
| 955 |
""")
|
| 956 |
agent_capability_table = gr.Dataframe(
|
| 957 |
+
value=create_capability_table(AGENT_CAPABILITY, AGENT_DOMAIN, AGENT_VERIFIED, "Agent"),
|
| 958 |
+
label="Scores by Capability"
|
| 959 |
)
|
| 960 |
|
| 961 |
# Update chart when slider changes
|
|
|
|
| 1006 |
|
| 1007 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 1008 |
gr.Markdown("""
|
| 1009 |
+
**Verification Status:** Only officially verified entries (✓) are shown. User-submitted results (○) will appear after weekly LLM-as-Judge evaluation.
|
|
|
|
|
|
|
| 1010 |
""")
|
| 1011 |
model_domain_table = gr.Dataframe(
|
| 1012 |
+
value=create_domain_table(MODEL_CAPABILITY, model_domain_filtered, MODEL_VERIFIED, "Model"),
|
| 1013 |
+
label="Scores by Domain"
|
| 1014 |
)
|
| 1015 |
|
| 1016 |
# Update chart when slider changes
|
|
|
|
| 1051 |
|
| 1052 |
with gr.Accordion("📊 Summary Statistics", open=True):
|
| 1053 |
gr.Markdown("""
|
| 1054 |
+
**Verification Status:** Only officially verified entries (✓) are shown. User-submitted results (○) will appear after weekly LLM-as-Judge evaluation.
|
|
|
|
|
|
|
| 1055 |
""")
|
| 1056 |
model_capability_table = gr.Dataframe(
|
| 1057 |
+
value=create_capability_table(MODEL_CAPABILITY, MODEL_DOMAIN, MODEL_VERIFIED, "Model"),
|
| 1058 |
+
label="Scores by Capability"
|
| 1059 |
)
|
| 1060 |
|
| 1061 |
# Update chart when slider changes
|
|
|
|
| 1120 |
)
|
| 1121 |
|
| 1122 |
gr.Markdown("""
|
| 1123 |
+
**📋 Submission Format:**
|
| 1124 |
|
| 1125 |
+
Your JSONL file should contain one line per episode:
|
| 1126 |
|
| 1127 |
```json
|
| 1128 |
{
|
| 1129 |
"episode_id": "trajectory_id",
|
| 1130 |
+
"question_uuid_list": ["uuid-1", "uuid-2", "uuid-3"],
|
| 1131 |
+
"answer_list": ["The agent moved right.", "..."],
|
| 1132 |
"llm_as_judge_score_list": [true, false, true]
|
| 1133 |
}
|
| 1134 |
```
|
| 1135 |
|
| 1136 |
**Field Descriptions:**
|
| 1137 |
+
- `episode_id` *(required)*: The episode identifier — used to automatically look up the domain
|
| 1138 |
+
- `question_uuid_list` *(required)*: UUIDs of the benchmark questions in the same order as `answer_list` — used to look up each question's capability (A/B/C/D).
|
| 1139 |
+
- `answer_list` *(required)*: Your model/agent's answers, one per question
|
| 1140 |
+
- `llm_as_judge_score_list` *(required)*: `true`/`false` per answer — your self-evaluated correctness scores used for leaderboard ranking.
|
|
|
|
|
|
|
| 1141 |
|
| 1142 |
**Important Notes:**
|
| 1143 |
+
- `question_uuid_list`, `answer_list`, and `llm_as_judge_score_list` must all be the same length
|
| 1144 |
+
- Domain is resolved automatically from `episode_id`; capability (A/B/C/D) is resolved from `question_uuid_list` — no need to supply them manually
|
| 1145 |
+
- All submissions start as `verified=false` and become `verified=true` after official LLM-as-Judge evaluation
|
| 1146 |
""")
|
| 1147 |
|
| 1148 |
with gr.Row():
|
| 1149 |
submit_button = gr.Button("Submit", variant="primary", size="lg")
|
| 1150 |
|
| 1151 |
+
submission_result = gr.HTML()
|
| 1152 |
|
| 1153 |
submit_button.click(
|
| 1154 |
+
fn=lambda: gr.update(interactive=False, value="⏳ Submitting..."),
|
| 1155 |
+
inputs=[],
|
| 1156 |
+
outputs=[submit_button],
|
| 1157 |
+
).then(
|
| 1158 |
+
fn=add_new_submission,
|
| 1159 |
+
inputs=[
|
| 1160 |
model_name_textbox,
|
| 1161 |
submission_type,
|
| 1162 |
url_textbox,
|
| 1163 |
file_upload,
|
| 1164 |
organisation,
|
| 1165 |
mail,
|
| 1166 |
+
model_family_textbox,
|
| 1167 |
],
|
| 1168 |
+
outputs=[submission_result],
|
| 1169 |
+
).then(
|
| 1170 |
+
fn=lambda: gr.update(interactive=True, value="Submit"),
|
| 1171 |
+
inputs=[],
|
| 1172 |
+
outputs=[submit_button],
|
| 1173 |
)
|
| 1174 |
|
| 1175 |
# ============================================================
|
|
|
|
| 1235 |
|
| 1236 |
if __name__ == "__main__":
|
| 1237 |
demo_app = build_app()
|
| 1238 |
+
demo_app.launch(debug=True, show_error=True, theme=gr.themes.Soft())
|
content.py
CHANGED
|
@@ -16,12 +16,14 @@ Results can be submitted for evaluation. Each submission should contain answers
|
|
| 16 |
|
| 17 |
We expect submissions to be JSON Lines files with the following format:
|
| 18 |
```
|
| 19 |
-
{"episode_id": "
|
| 20 |
```
|
| 21 |
|
| 22 |
**Required fields:**
|
| 23 |
- `episode_id`: The episode identifier
|
| 24 |
-
- `
|
|
|
|
|
|
|
| 25 |
- `reasoning_trace`: (Optional) The reasoning process or explanation for the answers
|
| 26 |
"""
|
| 27 |
|
|
@@ -52,5 +54,4 @@ def model_hyperlink(link, model_name):
|
|
| 52 |
"""Create a hyperlink to the model information."""
|
| 53 |
if not link or link.strip() == "":
|
| 54 |
return model_name
|
| 55 |
-
return f'<a target="_blank" href="{link}" style="color: var(--link-text-color); text-decoration: underline;text-decoration-style: dotted;">{model_name}</a>'
|
| 56 |
-
|
|
|
|
| 16 |
|
| 17 |
We expect submissions to be JSON Lines files with the following format:
|
| 18 |
```
|
| 19 |
+
{"episode_id": "trajectory_id", "question_uuid_list": ["uuid-1", "uuid-2", "uuid-3"], "answer_list": ["The agent moved right.", "..."], "llm_as_judge_score_list": [true, false, true]}
|
| 20 |
```
|
| 21 |
|
| 22 |
**Required fields:**
|
| 23 |
- `episode_id`: The episode identifier
|
| 24 |
+
- `question_uuid_list`: List of question UUIDs corresponding to each answer (e.g., `["uuid-1", "uuid-2"]`)
|
| 25 |
+
- `answer_list`: Your model's answers, in the same order as `question_uuid_list`
|
| 26 |
+
- `llm_as_judge_score_list`: Boolean scores for each answer (e.g., `[true, false, true]`)
|
| 27 |
- `reasoning_trace`: (Optional) The reasoning process or explanation for the answers
|
| 28 |
"""
|
| 29 |
|
|
|
|
| 54 |
"""Create a hyperlink to the model information."""
|
| 55 |
if not link or link.strip() == "":
|
| 56 |
return model_name
|
| 57 |
+
return f'<a target="_blank" href="{link}" style="color: var(--link-text-color); text-decoration: underline;text-decoration-style: dotted;">{model_name}</a>'
|
|
|
data/model.jsonl
CHANGED
|
@@ -1,8 +1,36 @@
|
|
| 1 |
-
{"model": "Claude Haiku 3.5", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 2 |
-
{"model": "GPT-5 mini", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 3 |
-
{"model": "gpt 5.2", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 4 |
-
{"model": "Gemini 2.5 flash", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 5 |
-
{"model": "Qwen2.5-14B-Instruct-1M", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 6 |
-
{"model": "Qwen3-32B", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 7 |
-
{"model": "Qwen3-14B", "Date": "2026-03-03", "verified": true, "Score": {"
|
| 8 |
-
{"model": "Qwen3-8B", "Date": "2026-03-03", "verified": true, "Score": {"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{"model": "Claude Haiku 3.5", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5}, {"B": 0.458}, {"C": 0.564}, {"D": 0.583}], "EMBODIED_AI": [{"A": 0.3934}, {"B": 0.4667}, {"C": 0.34}, {"D": 0.0}], "WEB": [{"A": 0.4711}, {"B": 0.5889}, {"C": 0.5222}, {"D": 0.5932}], "TEXT2SQL": [{"A": 0.6233}, {"B": 0.1961}, {"C": 0.4328}, {"D": 0.1569}], "OPENWORLD_QA": [{"A": 0.6596}, {"B": 0.7333}, {"C": 0.5625}, {"D": 0.5}], "SOFTWARE": [{"A": 0.26}, {"B": 0.4366}, {"C": 0.1739}, {"D": 0.1324}]}}
|
| 2 |
+
{"model": "OpenAI GPT-5.1 mini", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5}, {"B": 0.514}, {"C": 0.4872}, {"D": 0.5}], "EMBODIED_AI": [{"A": 0.6557}, {"B": 0.5667}, {"C": 0.4133}, {"D": 0.0169}], "WEB": [{"A": 0.8}, {"B": 0.8925}, {"C": 0.8387}, {"D": 0.7869}], "TEXT2SQL": [{"A": 0.8924}, {"B": 0.7778}, {"C": 0.8731}, {"D": 0.7941}], "OPENWORLD_QA": [{"A": 0.7347}, {"B": 0.8105}, {"C": 0.757}, {"D": 0.85}], "SOFTWARE": [{"A": 0.4811}, {"B": 0.6933}, {"C": 0.4521}, {"D": 0.6667}]}}
|
| 3 |
+
{"model": "gpt 5.2", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.8362}, {"B": 0.8194}, {"C": 0.7564}, {"D": 0.8333}], "EMBODIED_AI": [{"A": 0.9508}, {"B": 0.8}, {"C": 0.5067}, {"D": 0.0}], "WEB": [{"A": 0.744}, {"B": 0.8925}, {"C": 0.7204}, {"D": 0.7705}], "TEXT2SQL": [{"A": 0.9058}, {"B": 0.8627}, {"C": 0.8806}, {"D": 0.6765}], "OPENWORLD_QA": [{"A": 0.6939}, {"B": 0.7158}, {"C": 0.5794}, {"D": 0.65}], "SOFTWARE": [{"A": 0.4623}, {"B": 0.7067}, {"C": 0.3699}, {"D": 0.625}]}}
|
| 4 |
+
{"model": "Gemini 2.5 flash", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4224}, {"B": 0.1667}, {"C": 0.1795}, {"D": 0.1333}], "EMBODIED_AI": [{"A": 0.541}, {"B": 0.6333}, {"C": 0.4}, {"D": 0.0169}], "WEB": [{"A": 0.664}, {"B": 0.6237}, {"C": 0.6344}, {"D": 0.4918}], "TEXT2SQL": [{"A": 0.688}, {"B": 0.6344}, {"C": 0.6559}, {"D": 0.5246}], "OPENWORLD_QA": [{"A": 0.77}, {"B": 0.619}, {"C": 0.721}, {"D": 0.758}], "SOFTWARE": [{"A": 0.3726}, {"B": 0.32}, {"C": 0.3288}, {"D": 0.5139}]}}
|
| 5 |
+
{"model": "Qwen2.5-14B-Instruct-1M", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4957}, {"B": 0.4444}, {"C": 0.5769}, {"D": 0.4833}], "EMBODIED_AI": [{"A": 0.6842}, {"B": 0.4211}, {"C": 0.2211}, {"D": 0.0}], "WEB": [{"A": 0.488}, {"B": 0.6882}, {"C": 0.5376}, {"D": 0.4918}], "TEXT2SQL": [{"A": 0.6319}, {"B": 0.2339}, {"C": 0.5526}, {"D": 0.119}], "OPENWORLD_QA": [{"A": 0.48}, {"B": 0.4091}, {"C": 0.6087}, {"D": 0.5}], "SOFTWARE": [{"A": 0.5189}, {"B": 0.3867}, {"C": 0.3014}, {"D": 0.5417}]}}
|
| 6 |
+
{"model": "Qwen3-32B", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5431}, {"B": 0.4861}, {"C": 0.5128}, {"D": 0.6}], "EMBODIED_AI": [{"A": 0.7966}, {"B": 0.6437}, {"C": 0.4345}, {"D": 0.0526}], "WEB": [{"A": 0.504}, {"B": 0.6667}, {"C": 0.5054}, {"D": 0.541}], "TEXT2SQL": [{"A": 0.7309}, {"B": 0.3203}, {"C": 0.5672}, {"D": 0.2059}], "OPENWORLD_QA": [{"A": 0.4894}, {"B": 0.5978}, {"C": 0.4904}, {"D": 0.4138}], "SOFTWARE": [{"A": 0.5581}, {"B": 0.5254}, {"C": 0.3898}, {"D": 0.4655}]}}
|
| 7 |
+
{"model": "Qwen3-14B", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5162}, {"B": 0.5}, {"C": 0.5556}, {"D": 0.6}], "EMBODIED_AI": [{"A": 0.6557}, {"B": 0.5}, {"C": 0.3133}, {"D": 0.0508}], "WEB": [{"A": 0.512}, {"B": 0.5591}, {"C": 0.5484}, {"D": 0.5246}], "TEXT2SQL": [{"A": 0.6502}, {"B": 0.2288}, {"C": 0.4851}, {"D": 0.1471}], "OPENWORLD_QA": [{"A": 0.5306}, {"B": 0.5895}, {"C": 0.4393}, {"D": 0.3667}], "SOFTWARE": [{"A": 0.4953}, {"B": 0.4267}, {"C": 0.3425}, {"D": 0.3194}]}}
|
| 8 |
+
{"model": "Qwen3-8B", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5294}, {"B": 0.4111}, {"C": 0.4333}, {"D": 0.5}], "EMBODIED_AI": [{"A": 0.541}, {"B": 0.3333}, {"C": 0.2867}, {"D": 0.0169}], "WEB": [{"A": 0.424}, {"B": 0.4839}, {"C": 0.4409}, {"D": 0.3934}], "TEXT2SQL": [{"A": 0.5605}, {"B": 0.1895}, {"C": 0.4478}, {"D": 0.1471}], "OPENWORLD_QA": [{"A": 0.4796}, {"B": 0.5263}, {"C": 0.4579}, {"D": 0.4333}], "SOFTWARE": [{"A": 0.4481}, {"B": 0.44}, {"C": 0.3014}, {"D": 0.3472}]}}
|
| 9 |
+
{"model": "BM25 (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.3365}, {"B": 0.3333}, {"C": 0.4638}, {"D": 0.2963}], "EMBODIED_AI": [{"A": 0.2295}, {"B": 0.3111}, {"C": 0.0933}, {"D": 0.0008}], "WEB": [{"A": 0.272}, {"B": 0.3548}, {"C": 0.2366}, {"D": 0.1311}], "TEXT2SQL": [{"A": 0.3857}, {"B": 0.4183}, {"C": 0.3582}, {"D": 0.1078}], "OPENWORLD_QA": [{"A": 0.2347}, {"B": 0.3474}, {"C": 0.3178}, {"D": 0.2167}], "SOFTWARE": [{"A": 0.467}, {"B": 0.76}, {"C": 0.5616}, {"D": 0.7778}]}}
|
| 10 |
+
{"model": "Qwen3-Embedding-4B (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4914}, {"B": 0.5278}, {"C": 0.5769}, {"D": 0.4667}], "EMBODIED_AI": [{"A": 0.4262}, {"B": 0.2444}, {"C": 0.1467}, {"D": 0.0}], "WEB": [{"A": 0.312}, {"B": 0.4194}, {"C": 0.2043}, {"D": 0.2131}], "TEXT2SQL": [{"A": 0.5785}, {"B": 0.5556}, {"C": 0.306}, {"D": 0.2255}], "OPENWORLD_QA": [{"A": 0.4388}, {"B": 0.4632}, {"C": 0.4112}, {"D": 0.2833}], "SOFTWARE": [{"A": 0.5849}, {"B": 0.7067}, {"C": 0.4795}, {"D": 0.625}]}}
|
| 11 |
+
{"model": "GRAPHRAG (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5347}, {"B": 0.5484}, {"C": 0.5588}, {"D": 0.5962}], "EMBODIED_AI": [{"A": 0.0426}, {"B": 0.3913}, {"C": 0.1565}, {"D": 0.0}], "WEB": [{"A": 0.314}, {"B": 0.4778}, {"C": 0.4333}, {"D": 0.4576}], "TEXT2SQL": [{"A": 0.2646}, {"B": 0.2353}, {"C": 0.2687}, {"D": 0.098}], "OPENWORLD_QA": [{"A": 0.3474}, {"B": 0.4348}, {"C": 0.233}, {"D": 0.2586}], "SOFTWARE": [{"A": 0.3585}, {"B": 0.36}, {"C": 0.2603}, {"D": 0.4167}]}}
|
| 12 |
+
{"model": "Hipporag2 (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5137}, {"B": 0.6029}, {"C": 0.6806}, {"D": 0.625}], "EMBODIED_AI": [{"A": 0.3607}, {"B": 0.2111}, {"C": 0.1333}, {"D": 0.0}], "WEB": [{"A": 0.344}, {"B": 0.4731}, {"C": 0.4086}, {"D": 0.2787}], "TEXT2SQL": [{"A": 0.6233}, {"B": 0.5882}, {"C": 0.4627}, {"D": 0.1765}], "OPENWORLD_QA": [{"A": 0.4595}, {"B": 0.5135}, {"C": 0.5122}, {"D": 0.3478}], "SOFTWARE": [{"A": 0.3471}, {"B": 0.5902}, {"C": 0.4237}, {"D": 0.7586}]}}
|
| 13 |
+
{"model": "Memagent (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.3103}, {"B": 0.3056}, {"C": 0.3718}, {"D": 0.2833}], "EMBODIED_AI": [{"A": 0.0656}, {"B": 0.2889}, {"C": 0.0533}, {"D": 0.0169}], "WEB": [{"A": 0.256}, {"B": 0.3118}, {"C": 0.2258}, {"D": 0.2623}], "TEXT2SQL": [{"A": 0.2518}, {"B": 0.2975}, {"C": 0.272}, {"D": 0.1602}], "OPENWORLD_QA": [{"A": 0.1939}, {"B": 0.1895}, {"C": 0.1495}, {"D": 0.1}], "SOFTWARE": [{"A": 0.4292}, {"B": 0.6267}, {"C": 0.6027}, {"D": 0.5}]}}
|
| 14 |
+
{"model": "Mem1 (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.2217}, {"B": 0.24}, {"C": 0.1918}, {"D": 0.25}], "EMBODIED_AI": [{"A": 0.0164}, {"B": 0.1111}, {"C": 0.0067}, {"D": 0.0}], "WEB": [{"A": 0.12}, {"B": 0.1075}, {"C": 0.1828}, {"D": 0.1148}], "TEXT2SQL": [{"A": 0.0762}, {"B": 0.0784}, {"C": 0.0746}, {"D": 0.0294}], "OPENWORLD_QA": [{"A": 0.1224}, {"B": 0.2}, {"C": 0.0935}, {"D": 0.0667}], "SOFTWARE": [{"A": 0.1698}, {"B": 0.16}, {"C": 0.1918}, {"D": 0.2222}]}}
|
| 15 |
+
{"model": "Amem (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.3793}, {"B": 0.4028}, {"C": 0.5}, {"D": 0.4167}], "EMBODIED_AI": [{"A": 0.082}, {"B": 0.4}, {"C": 0.22}, {"D": 0.0339}], "WEB": [{"A": 0.36}, {"B": 0.4624}, {"C": 0.3011}, {"D": 0.4426}], "TEXT2SQL": [{"A": 0.4036}, {"B": 0.3333}, {"C": 0.3134}, {"D": 0.2059}], "OPENWORLD_QA": [{"A": 0.2755}, {"B": 0.3579}, {"C": 0.2243}, {"D": 0.3167}], "SOFTWARE": [{"A": 0.283}, {"B": 0.2667}, {"C": 0.2877}, {"D": 0.3472}]}}
|
| 16 |
+
{"model": "Mem0 (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4259}, {"B": 0.3788}, {"C": 0.473}, {"D": 0.2857}], "EMBODIED_AI": [{"A": 0.0164}, {"B": 0.3444}, {"C": 0.0667}, {"D": 0.0169}], "WEB": [{"A": 0.256}, {"B": 0.3656}, {"C": 0.2473}, {"D": 0.2131}], "TEXT2SQL": [{"A": 0.16}, {"B": 0.1512}, {"C": 0.1139}, {"D": 0.0517}], "OPENWORLD_QA": [{"A": 0.1735}, {"B": 0.1895}, {"C": 0.1682}, {"D": 0.1167}], "SOFTWARE": [{"A": 0.1953}, {"B": 0.234}, {"C": 0.2444}, {"D": 0.2727}]}}
|
| 17 |
+
{"model": "Memorag (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5405}, {"B": 0.6}, {"C": 0.64}, {"D": 0.45}], "EMBODIED_AI": [{"A": 0.1639}, {"B": 0.1111}, {"C": 0.0667}, {"D": 0.0}], "WEB": [{"A": 0.368}, {"B": 0.4839}, {"C": 0.2473}, {"D": 0.3607}], "TEXT2SQL": [{"A": 0.7273}, {"B": 0.7333}, {"C": 0.6154}, {"D": 0.4}], "OPENWORLD_QA": [{"A": 0.4}, {"B": 0.5789}, {"C": 0.3333}, {"D": 0.3333}], "SOFTWARE": [{"A": 0.4495}, {"B": 0.6494}, {"C": 0.5067}, {"D": 0.5946}]}}
|
| 18 |
+
{"model": "Memgpt (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.3534}, {"B": 0.3472}, {"C": 0.4744}, {"D": 0.5667}], "EMBODIED_AI": [{"A": 0.1475}, {"B": 0.2444}, {"C": 0.04}, {"D": 0.0169}], "WEB": [{"A": 0.384}, {"B": 0.4624}, {"C": 0.2688}, {"D": 0.1967}], "TEXT2SQL": [{"A": 0.287}, {"B": 0.3595}, {"C": 0.1418}, {"D": 0.0392}], "OPENWORLD_QA": [{"A": 0.2615}, {"B": 0.5156}, {"C": 0.3099}, {"D": 0.175}], "SOFTWARE": [{"A": 0.5385}, {"B": 0.7333}, {"C": 0.5111}, {"D": 0.6136}]}}
|
| 19 |
+
{"model": "Mem-alpha (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4286}, {"B": 0.4783}, {"C": 0.4868}, {"D": 0.3621}], "EMBODIED_AI": [{"A": 0.0984}, {"B": 0.4222}, {"C": 0.1}, {"D": 0.0}], "WEB": [{"A": 0.3077}, {"B": 0.5172}, {"C": 0.2759}, {"D": 0.3509}], "TEXT2SQL": [{"A": 0.3318}, {"B": 0.3922}, {"C": 0.3806}, {"D": 0.098}], "OPENWORLD_QA": [{"A": 0.2674}, {"B": 0.2927}, {"C": 0.2065}, {"D": 0.1538}], "SOFTWARE": [{"A": 0.2594}, {"B": 0.4133}, {"C": 0.3288}, {"D": 0.3889}]}}
|
| 20 |
+
{"model": "Memorybank (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4359}, {"B": 0.4028}, {"C": 0.5}, {"D": 0.4167}], "EMBODIED_AI": [{"A": 0.1017}, {"B": 0.3908}, {"C": 0.131}, {"D": 0.0175}], "WEB": [{"A": 0.3393}, {"B": 0.5357}, {"C": 0.3571}, {"D": 0.375}], "TEXT2SQL": [{"A": 0.3139}, {"B": 0.3007}, {"C": 0.2612}, {"D": 0.0784}], "OPENWORLD_QA": [{"A": 0.2959}, {"B": 0.4421}, {"C": 0.2897}, {"D": 0.3667}], "SOFTWARE": [{"A": 0.4386}, {"B": 0.4545}, {"C": 0.2857}, {"D": 0.85}]}}
|
| 21 |
+
{"model": "Simple mem (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.2083}, {"B": 0.2353}, {"C": 0.4615}, {"D": 0.25}], "EMBODIED_AI": [{"A": 0.0}, {"B": 0.1149}, {"C": 0.069}, {"D": 0.0}], "WEB": [{"A": 0.156}, {"B": 0.2099}, {"C": 0.0988}, {"D": 0.0943}], "TEXT2SQL": [{"A": 0.354}, {"B": 0.1644}, {"C": 0.1802}, {"D": 0.0717}], "OPENWORLD_QA": [{"A": 0.1224}, {"B": 0.1684}, {"C": 0.1121}, {"D": 0.0833}], "SOFTWARE": [{"A": 0.2538}, {"B": 0.2444}, {"C": 0.1333}, {"D": 0.3409}]}}
|
| 22 |
+
{"model": "AMA-agent (Ours) (32B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.6471}, {"B": 0.7}, {"C": 0.6}, {"D": 0.6167}], "EMBODIED_AI": [{"A": 0.8033}, {"B": 0.5778}, {"C": 0.44}, {"D": 0.2169}], "WEB": [{"A": 0.53}, {"B": 0.68}, {"C": 0.4133}, {"D": 0.4}], "TEXT2SQL": [{"A": 0.7584}, {"B": 0.4615}, {"C": 0.6782}, {"D": 0.4118}], "OPENWORLD_QA": [{"A": 0.4482}, {"B": 0.5558}, {"C": 0.4612}, {"D": 0.39}], "SOFTWARE": [{"A": 0.6049}, {"B": 0.7268}, {"C": 0.4905}, {"D": 0.7778}]}}
|
| 23 |
+
{"model": "BM25 (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.3966}, {"B": 0.4583}, {"C": 0.4615}, {"D": 0.3333}], "EMBODIED_AI": [{"A": 0.3443}, {"B": 0.3222}, {"C": 0.0733}, {"D": 0.0169}], "WEB": [{"A": 0.224}, {"B": 0.4409}, {"C": 0.2688}, {"D": 0.1803}], "TEXT2SQL": [{"A": 0.3498}, {"B": 0.451}, {"C": 0.3731}, {"D": 0.1765}], "OPENWORLD_QA": [{"A": 0.2347}, {"B": 0.2842}, {"C": 0.3364}, {"D": 0.2167}], "SOFTWARE": [{"A": 0.4292}, {"B": 0.6667}, {"C": 0.4247}, {"D": 0.75}]}}
|
| 24 |
+
{"model": "Qwen3-Embedding-4B (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4397}, {"B": 0.3056}, {"C": 0.6026}, {"D": 0.35}], "EMBODIED_AI": [{"A": 0.4262}, {"B": 0.3111}, {"C": 0.1133}, {"D": 0.0}], "WEB": [{"A": 0.392}, {"B": 0.4301}, {"C": 0.2258}, {"D": 0.2459}], "TEXT2SQL": [{"A": 0.5291}, {"B": 0.451}, {"C": 0.3582}, {"D": 0.2059}], "OPENWORLD_QA": [{"A": 0.4184}, {"B": 0.3895}, {"C": 0.3925}, {"D": 0.25}], "SOFTWARE": [{"A": 0.5283}, {"B": 0.68}, {"C": 0.3699}, {"D": 0.5972}]}}
|
| 25 |
+
{"model": "GRAPHRAG (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4818}, {"B": 0.3182}, {"C": 0.4324}, {"D": 0.4464}], "EMBODIED_AI": [{"A": 0.0196}, {"B": 0.28}, {"C": 0.088}, {"D": 0.0}], "WEB": [{"A": 0.304}, {"B": 0.3656}, {"C": 0.3441}, {"D": 0.2787}], "TEXT2SQL": [{"A": 0.1502}, {"B": 0.1156}, {"C": 0.1769}, {"D": 0.0408}], "OPENWORLD_QA": [{"A": 0.2}, {"B": 0.2283}, {"C": 0.1748}, {"D": 0.2241}], "SOFTWARE": [{"A": 0.2784}, {"B": 0.2754}, {"C": 0.209}, {"D": 0.3333}]}}
|
| 26 |
+
{"model": "Hipporag2 (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4528}, {"B": 0.4343}, {"C": 0.4946}, {"D": 0.4429}], "EMBODIED_AI": [{"A": 0.1026}, {"B": 0.2807}, {"C": 0.1053}, {"D": 0.0}], "WEB": [{"A": 0.3191}, {"B": 0.3525}, {"C": 0.3908}, {"D": 0.2573}], "TEXT2SQL": [{"A": 0.4316}, {"B": 0.5217}, {"C": 0.534}, {"D": 0.2759}], "OPENWORLD_QA": [{"A": 0.4316}, {"B": 0.5217}, {"C": 0.534}, {"D": 0.2759}], "SOFTWARE": [{"A": 0.3497}, {"B": 0.5538}, {"C": 0.3871}, {"D": 0.5}]}}
|
| 27 |
+
{"model": "Memagent (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.1638}, {"B": 0.2917}, {"C": 0.3077}, {"D": 0.25}], "EMBODIED_AI": [{"A": 0.0164}, {"B": 0.1889}, {"C": 0.04}, {"D": 0.0169}], "WEB": [{"A": 0.2}, {"B": 0.2903}, {"C": 0.1828}, {"D": 0.1475}], "TEXT2SQL": [{"A": 0.2018}, {"B": 0.2484}, {"C": 0.1343}, {"D": 0.1078}], "OPENWORLD_QA": [{"A": 0.1735}, {"B": 0.1895}, {"C": 0.0935}, {"D": 0.0167}], "SOFTWARE": [{"A": 0.3396}, {"B": 0.5333}, {"C": 0.4795}, {"D": 0.3194}]}}
|
| 28 |
+
{"model": "Mem1 (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.1624}, {"B": 0.2222}, {"C": 0.2692}, {"D": 0.15}], "EMBODIED_AI": [{"A": 0.0328}, {"B": 0.2444}, {"C": 0.0}, {"D": 0.0169}], "WEB": [{"A": 0.24}, {"B": 0.2151}, {"C": 0.1828}, {"D": 0.0656}], "TEXT2SQL": [{"A": 0.1076}, {"B": 0.1242}, {"C": 0.1045}, {"D": 0.0392}], "OPENWORLD_QA": [{"A": 0.1224}, {"B": 0.1895}, {"C": 0.0841}, {"D": 0.15}], "SOFTWARE": [{"A": 0.1934}, {"B": 0.16}, {"C": 0.1233}, {"D": 0.2917}]}}
|
| 29 |
+
{"model": "Amem (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.431}, {"B": 0.5278}, {"C": 0.5641}, {"D": 0.4333}], "EMBODIED_AI": [{"A": 0.082}, {"B": 0.3667}, {"C": 0.1667}, {"D": 0.0847}], "WEB": [{"A": 0.336}, {"B": 0.4946}, {"C": 0.3333}, {"D": 0.3115}], "TEXT2SQL": [{"A": 0.3991}, {"B": 0.4575}, {"C": 0.3134}, {"D": 0.1667}], "OPENWORLD_QA": [{"A": 0.1327}, {"B": 0.3158}, {"C": 0.2056}, {"D": 0.2833}], "SOFTWARE": [{"A": 0.4198}, {"B": 0.5333}, {"C": 0.3973}, {"D": 0.5833}]}}
|
| 30 |
+
{"model": "Mem0 (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5741}, {"B": 0.5152}, {"C": 0.5946}, {"D": 0.5}], "EMBODIED_AI": [{"A": 0.0164}, {"B": 0.3889}, {"C": 0.02}, {"D": 0.0169}], "WEB": [{"A": 0.32}, {"B": 0.4086}, {"C": 0.2688}, {"D": 0.2623}], "TEXT2SQL": [{"A": 0.1928}, {"B": 0.2418}, {"C": 0.1493}, {"D": 0.1765}], "OPENWORLD_QA": [{"A": 0.1837}, {"B": 0.1895}, {"C": 0.1589}, {"D": 0.2167}], "SOFTWARE": [{"A": 0.3984}, {"B": 0.3191}, {"C": 0.2667}, {"D": 0.3864}]}}
|
| 31 |
+
{"model": "Memgpt (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.4538}, {"B": 0.4889}, {"C": 0.5444}, {"D": 0.4833}], "EMBODIED_AI": [{"A": 0.1803}, {"B": 0.1778}, {"C": 0.0333}, {"D": 0.0}], "WEB": [{"A": 0.36}, {"B": 0.4516}, {"C": 0.2903}, {"D": 0.2459}], "TEXT2SQL": [{"A": 0.2063}, {"B": 0.3007}, {"C": 0.1866}, {"D": 0.0196}], "OPENWORLD_QA": [{"A": 0.0918}, {"B": 0.1158}, {"C": 0.0841}, {"D": 0.1}], "SOFTWARE": [{"A": 0.4151}, {"B": 0.5333}, {"C": 0.3562}, {"D": 0.625}]}}
|
| 32 |
+
{"model": "Mem-alpha (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.292}, {"B": 0.3768}, {"C": 0.4211}, {"D": 0.2759}], "EMBODIED_AI": [{"A": 0.0984}, {"B": 0.2}, {"C": 0.0333}, {"D": 0.0}], "WEB": [{"A": 0.1736}, {"B": 0.2889}, {"C": 0.2}, {"D": 0.2881}], "TEXT2SQL": [{"A": 0.2242}, {"B": 0.3922}, {"C": 0.2537}, {"D": 0.0294}], "OPENWORLD_QA": [{"A": 0.2093}, {"B": 0.2439}, {"C": 0.2174}, {"D": 0.1346}], "SOFTWARE": [{"A": 0.217}, {"B": 0.32}, {"C": 0.1781}, {"D": 0.5139}]}}
|
| 33 |
+
{"model": "Memorag (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5}, {"B": 0.5278}, {"C": 0.641}, {"D": 0.55}], "EMBODIED_AI": [{"A": 0.1639}, {"B": 0.1333}, {"C": 0.02}, {"D": 0.0169}], "WEB": [{"A": 0.232}, {"B": 0.3763}, {"C": 0.1935}, {"D": 0.2295}], "TEXT2SQL": [{"A": 0.6637}, {"B": 0.6928}, {"C": 0.5896}, {"D": 0.3039}], "OPENWORLD_QA": [{"A": 0.2449}, {"B": 0.3789}, {"C": 0.3271}, {"D": 0.2333}], "SOFTWARE": [{"A": 0.4481}, {"B": 0.68}, {"C": 0.4384}, {"D": 0.6111}]}}
|
| 34 |
+
{"model": "Memorybank (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.2821}, {"B": 0.3056}, {"C": 0.3974}, {"D": 0.3167}], "EMBODIED_AI": [{"A": 0.0656}, {"B": 0.2889}, {"C": 0.06}, {"D": 0.0169}], "WEB": [{"A": 0.28}, {"B": 0.3871}, {"C": 0.2473}, {"D": 0.4426}], "TEXT2SQL": [{"A": 0.2735}, {"B": 0.2157}, {"C": 0.209}, {"D": 0.1078}], "OPENWORLD_QA": [{"A": 0.2857}, {"B": 0.3895}, {"C": 0.243}, {"D": 0.4167}], "SOFTWARE": [{"A": 0.25}, {"B": 0.3467}, {"C": 0.2192}, {"D": 0.625}]}}
|
| 35 |
+
{"model": "Simple mem (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.3613}, {"B": 0.1556}, {"C": 0.3556}, {"D": 0.3333}], "EMBODIED_AI": [{"A": 0.0328}, {"B": 0.2778}, {"C": 0.08}, {"D": 0.0}], "WEB": [{"A": 0.1538}, {"B": 0.3333}, {"C": 0.1379}, {"D": 0.193}], "TEXT2SQL": [{"A": 0.1302}, {"B": 0.069}, {"C": 0.0846}, {"D": 0.0102}], "OPENWORLD_QA": [{"A": 0.1939}, {"B": 0.3053}, {"C": 0.215}, {"D": 0.3}], "SOFTWARE": [{"A": 0.2028}, {"B": 0.2133}, {"C": 0.1507}, {"D": 0.2361}]}}
|
| 36 |
+
{"model": "AMA-agent (Ours) (8B)", "Date": "2026-03-03", "verified": true, "Score": {"Game": [{"A": 0.5798}, {"B": 0.5}, {"C": 0.4556}, {"D": 0.6167}], "EMBODIED_AI": [{"A": 0.7705}, {"B": 0.4}, {"C": 0.1667}, {"D": 0.0}], "WEB": [{"A": 0.52}, {"B": 0.5269}, {"C": 0.4086}, {"D": 0.3934}], "TEXT2SQL": [{"A": 0.713}, {"B": 0.3529}, {"C": 0.597}, {"D": 0.3137}], "OPENWORLD_QA": [{"A": 0.475}, {"B": 0.4875}, {"C": 0.4556}, {"D": 0.32}], "SOFTWARE": [{"A": 0.5534}, {"B": 0.6164}, {"C": 0.5352}, {"D": 0.6286}]}}
|
submission.py
CHANGED
|
@@ -1,14 +1,28 @@
|
|
| 1 |
"""
|
| 2 |
Submission handling module for AMA-Bench Leaderboard
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
"""
|
| 5 |
|
| 6 |
import json
|
| 7 |
import os
|
| 8 |
import datetime
|
| 9 |
from email.utils import parseaddr
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
# Optional imports with fallbacks
|
| 12 |
try:
|
| 13 |
from content import format_error, format_warning, format_log
|
| 14 |
except ImportError:
|
|
@@ -17,85 +31,80 @@ except ImportError:
|
|
| 17 |
def format_log(msg): return f"✅ {msg}"
|
| 18 |
|
| 19 |
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
Expected format:
|
| 25 |
-
{
|
| 26 |
-
"episode_id": str,
|
| 27 |
-
"answer_list": list,
|
| 28 |
-
"llm_as_judge_score_list": list # Optional, list of true/false
|
| 29 |
-
}
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
|
|
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
| 36 |
"""
|
| 37 |
if not isinstance(data, dict):
|
| 38 |
return False, "Submission must be a JSON object"
|
| 39 |
|
| 40 |
-
#
|
| 41 |
if "episode_id" not in data:
|
| 42 |
return False, "Missing required field: episode_id"
|
| 43 |
-
|
| 44 |
-
if "answer_list" not in data:
|
| 45 |
-
return False, "Missing required field: answer_list"
|
| 46 |
-
|
| 47 |
-
# Validate episode_id
|
| 48 |
if not isinstance(data["episode_id"], str) or not data["episode_id"].strip():
|
| 49 |
return False, "episode_id must be a non-empty string"
|
| 50 |
|
| 51 |
-
#
|
| 52 |
-
if
|
| 53 |
-
return False, "
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
return True, ""
|
| 73 |
|
| 74 |
|
| 75 |
-
def validate_submission_file(file_path):
|
| 76 |
-
"""
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
|
| 82 |
-
Returns:
|
| 83 |
-
(is_valid, error_msg, submissions): Tuple of validation result and submissions
|
| 84 |
-
"""
|
| 85 |
try:
|
| 86 |
-
|
| 87 |
-
return False, "File not found", []
|
| 88 |
-
|
| 89 |
-
if not file_path.endswith('.jsonl'):
|
| 90 |
-
return False, "File must be in JSONL format (.jsonl)", []
|
| 91 |
-
|
| 92 |
-
submissions = []
|
| 93 |
-
with open(file_path, 'r', encoding='utf-8') as f:
|
| 94 |
for line_num, line in enumerate(f, 1):
|
| 95 |
line = line.strip()
|
| 96 |
if not line:
|
| 97 |
continue
|
| 98 |
-
|
| 99 |
try:
|
| 100 |
data = json.loads(line)
|
| 101 |
except json.JSONDecodeError as e:
|
|
@@ -105,244 +114,409 @@ def validate_submission_file(file_path):
|
|
| 105 |
if not is_valid:
|
| 106 |
return False, f"Validation error on line {line_num}: {error_msg}", []
|
| 107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
submissions.append(data)
|
| 109 |
|
| 110 |
if not submissions:
|
| 111 |
return False, "File is empty or contains no valid submissions", []
|
| 112 |
-
|
| 113 |
return True, "", submissions
|
| 114 |
|
| 115 |
except Exception as e:
|
| 116 |
return False, f"Error reading file: {e}", []
|
| 117 |
|
| 118 |
|
| 119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
"""
|
| 121 |
-
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
|
| 127 |
-
|
| 128 |
-
|
| 129 |
"""
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
if len(answer_list) != len(gt_answers):
|
| 140 |
-
return None
|
| 141 |
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
capabilities = groundtruth.get("capabilities", []) # List of A/B/C/D for each question
|
| 149 |
|
| 150 |
-
# Calculate per-capability accuracy
|
| 151 |
-
capability_scores = {"A": [], "B": [], "C": [], "D": []}
|
| 152 |
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
"
|
| 161 |
-
|
| 162 |
-
"accuracy": correct_count / total_count if total_count > 0 else 0,
|
| 163 |
-
"capability_scores": {}
|
| 164 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
}
|
| 174 |
-
|
| 175 |
-
return result
|
| 176 |
-
|
| 177 |
|
| 178 |
-
def process_submission(file_path, model_name, submission_type, organisation, verified=False):
|
| 179 |
-
"""
|
| 180 |
-
Process a submission file and save results.
|
| 181 |
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
submission_type: "model" or "agent"
|
| 186 |
-
organisation: Organisation name
|
| 187 |
-
verified: Whether this is an official verified submission
|
| 188 |
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
# Save submission file
|
| 204 |
-
saved_file = f"{submission_dir}/submission_{timestamp}.jsonl"
|
| 205 |
-
with open(saved_file, 'w', encoding='utf-8') as f:
|
| 206 |
-
for sub in submissions:
|
| 207 |
-
f.write(json.dumps(sub, ensure_ascii=False) + "\n")
|
| 208 |
-
|
| 209 |
-
# Create metadata
|
| 210 |
-
metadata = {
|
| 211 |
-
"model": model_name if submission_type == "model" else None,
|
| 212 |
-
"agent_name": model_name if submission_type == "agent" else None,
|
| 213 |
-
"model_family": "",
|
| 214 |
-
"submission_type": submission_type,
|
| 215 |
-
"organisation": organisation,
|
| 216 |
-
"Date": datetime.datetime.today().strftime('%Y-%m-%d'),
|
| 217 |
-
"timestamp": timestamp,
|
| 218 |
-
"verified": verified,
|
| 219 |
-
"submission_count": len(submissions),
|
| 220 |
-
"file_path": saved_file
|
| 221 |
-
}
|
| 222 |
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
"
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
"metadata": metadata
|
| 234 |
-
}
|
| 235 |
|
| 236 |
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
String with formatted result message
|
| 252 |
-
"""
|
| 253 |
try:
|
| 254 |
-
# Validate inputs
|
| 255 |
if file is None:
|
| 256 |
return format_warning("Please attach a submission file.")
|
| 257 |
-
|
| 258 |
_, parsed_mail = parseaddr(mail)
|
| 259 |
if "@" not in parsed_mail:
|
| 260 |
return format_warning("Please provide a valid email address.")
|
| 261 |
-
|
| 262 |
if not model or not submission_type or not organisation:
|
| 263 |
return format_warning("Please fill in all required fields.")
|
| 264 |
|
| 265 |
-
print(f"
|
| 266 |
|
| 267 |
-
# Validate file format
|
| 268 |
is_valid, error_msg, submissions = validate_submission_file(file.name)
|
| 269 |
if not is_valid:
|
| 270 |
return format_error(error_msg)
|
| 271 |
|
| 272 |
-
print(f"
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
)
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
import traceback
|
| 304 |
-
traceback.print_exc()
|
| 305 |
-
return format_error(f"An error occurred during submission: {str(e)}")
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
def update_leaderboard_data(submission_metadata, scores):
|
| 309 |
-
"""
|
| 310 |
-
Update leaderboard JSONL files with new submission results.
|
| 311 |
-
|
| 312 |
-
Args:
|
| 313 |
-
submission_metadata: Metadata from processed submission
|
| 314 |
-
scores: Computed scores by domain and capability
|
| 315 |
-
|
| 316 |
-
Returns:
|
| 317 |
-
Boolean indicating success
|
| 318 |
-
"""
|
| 319 |
-
try:
|
| 320 |
-
submission_type = submission_metadata["submission_type"]
|
| 321 |
-
|
| 322 |
-
# Determine which file to update
|
| 323 |
-
if submission_type == "agent":
|
| 324 |
-
data_file = "data/agent.jsonl"
|
| 325 |
-
else:
|
| 326 |
-
data_file = "data/model.jsonl"
|
| 327 |
-
|
| 328 |
-
# Create new entry
|
| 329 |
-
entry = {
|
| 330 |
-
"model" if submission_type == "model" else "agent_name": submission_metadata.get("model") or submission_metadata.get("agent_name"),
|
| 331 |
-
"model_family": submission_metadata.get("model_family", ""),
|
| 332 |
-
"Date": submission_metadata["Date"],
|
| 333 |
-
"verified": submission_metadata["verified"],
|
| 334 |
-
"Score": scores
|
| 335 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 343 |
|
| 344 |
except Exception as e:
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
traceback.print_exc()
|
| 348 |
-
return False
|
|
|
|
| 1 |
"""
|
| 2 |
Submission handling module for AMA-Bench Leaderboard
|
| 3 |
+
|
| 4 |
+
Submission format:
|
| 5 |
+
{
|
| 6 |
+
"episode_id": str,
|
| 7 |
+
"question_uuid_list": list[str], # required - UUIDs that map answers to groundtruth
|
| 8 |
+
"answer_list": list[str], # required - same length as question_uuid_list
|
| 9 |
+
"llm_as_judge_score_list": list[bool] # optional - same length as answer_list
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
Scoring logic:
|
| 13 |
+
- Uses llm_as_judge_score_list (true/false) from the submission
|
| 14 |
+
- Maps each question to its domain and capability (A/B/C/D) via groundtruth metadata
|
| 15 |
+
- Computes per-domain, per-capability accuracy
|
| 16 |
+
- Writes entry to data/agent.jsonl or data/model.jsonl (verified=False by default)
|
| 17 |
"""
|
| 18 |
|
| 19 |
import json
|
| 20 |
import os
|
| 21 |
import datetime
|
| 22 |
from email.utils import parseaddr
|
| 23 |
+
from collections import defaultdict
|
| 24 |
+
from typing import Dict, List, Tuple, Optional
|
| 25 |
|
|
|
|
| 26 |
try:
|
| 27 |
from content import format_error, format_warning, format_log
|
| 28 |
except ImportError:
|
|
|
|
| 31 |
def format_log(msg): return f"✅ {msg}"
|
| 32 |
|
| 33 |
|
| 34 |
+
# ---------------------------------------------------------------------------
|
| 35 |
+
# Validation
|
| 36 |
+
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
+
def validate_submission_format(data: dict) -> Tuple[bool, str]:
|
| 39 |
+
"""
|
| 40 |
+
Validate a single submission record.
|
| 41 |
|
| 42 |
+
Required fields: episode_id, question_uuid_list, answer_list
|
| 43 |
+
Optional fields: llm_as_judge_score_list, reasoning_trace
|
| 44 |
"""
|
| 45 |
if not isinstance(data, dict):
|
| 46 |
return False, "Submission must be a JSON object"
|
| 47 |
|
| 48 |
+
# episode_id
|
| 49 |
if "episode_id" not in data:
|
| 50 |
return False, "Missing required field: episode_id"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
if not isinstance(data["episode_id"], str) or not data["episode_id"].strip():
|
| 52 |
return False, "episode_id must be a non-empty string"
|
| 53 |
|
| 54 |
+
# answer_list
|
| 55 |
+
if "answer_list" not in data:
|
| 56 |
+
return False, "Missing required field: answer_list"
|
| 57 |
+
if not isinstance(data["answer_list"], list) or not data["answer_list"]:
|
| 58 |
+
return False, "answer_list must be a non-empty list"
|
| 59 |
+
|
| 60 |
+
# question_uuid_list
|
| 61 |
+
if "question_uuid_list" not in data:
|
| 62 |
+
return False, "Missing required field: question_uuid_list"
|
| 63 |
+
if not isinstance(data["question_uuid_list"], list):
|
| 64 |
+
return False, "question_uuid_list must be a list"
|
| 65 |
+
if len(data["question_uuid_list"]) != len(data["answer_list"]):
|
| 66 |
+
return False, (
|
| 67 |
+
f"question_uuid_list length ({len(data['question_uuid_list'])}) must match "
|
| 68 |
+
f"answer_list length ({len(data['answer_list'])})"
|
| 69 |
+
)
|
| 70 |
+
for i, q in enumerate(data["question_uuid_list"]):
|
| 71 |
+
if not isinstance(q, str) or not q.strip():
|
| 72 |
+
return False, f"question_uuid_list[{i}] must be a non-empty string"
|
| 73 |
+
|
| 74 |
+
# llm_as_judge_score_list (required)
|
| 75 |
+
if "llm_as_judge_score_list" not in data:
|
| 76 |
+
return False, "Missing required field: llm_as_judge_score_list"
|
| 77 |
+
score_list = data["llm_as_judge_score_list"]
|
| 78 |
+
if not isinstance(score_list, list):
|
| 79 |
+
return False, "llm_as_judge_score_list must be a list"
|
| 80 |
+
if len(score_list) != len(data["answer_list"]):
|
| 81 |
+
return False, (
|
| 82 |
+
f"llm_as_judge_score_list length ({len(score_list)}) must match "
|
| 83 |
+
f"answer_list length ({len(data['answer_list'])})"
|
| 84 |
+
)
|
| 85 |
+
for i, score in enumerate(score_list):
|
| 86 |
+
if not isinstance(score, bool):
|
| 87 |
+
return False, f"llm_as_judge_score_list[{i}] must be true or false (boolean)"
|
| 88 |
|
| 89 |
return True, ""
|
| 90 |
|
| 91 |
|
| 92 |
+
def validate_submission_file(file_path: str) -> Tuple[bool, str, List[dict]]:
|
| 93 |
+
"""Validate and load a JSONL submission file."""
|
| 94 |
+
if not os.path.exists(file_path):
|
| 95 |
+
return False, "File not found", []
|
| 96 |
+
if not file_path.endswith(".jsonl"):
|
| 97 |
+
return False, "File must be in JSONL format (.jsonl)", []
|
| 98 |
|
| 99 |
+
submissions = []
|
| 100 |
+
seen_ids = set()
|
| 101 |
|
|
|
|
|
|
|
|
|
|
| 102 |
try:
|
| 103 |
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
for line_num, line in enumerate(f, 1):
|
| 105 |
line = line.strip()
|
| 106 |
if not line:
|
| 107 |
continue
|
|
|
|
| 108 |
try:
|
| 109 |
data = json.loads(line)
|
| 110 |
except json.JSONDecodeError as e:
|
|
|
|
| 114 |
if not is_valid:
|
| 115 |
return False, f"Validation error on line {line_num}: {error_msg}", []
|
| 116 |
|
| 117 |
+
episode_id = data["episode_id"]
|
| 118 |
+
if episode_id in seen_ids:
|
| 119 |
+
return False, f"Duplicate episode_id '{episode_id}' on line {line_num}", []
|
| 120 |
+
seen_ids.add(episode_id)
|
| 121 |
submissions.append(data)
|
| 122 |
|
| 123 |
if not submissions:
|
| 124 |
return False, "File is empty or contains no valid submissions", []
|
|
|
|
| 125 |
return True, "", submissions
|
| 126 |
|
| 127 |
except Exception as e:
|
| 128 |
return False, f"Error reading file: {e}", []
|
| 129 |
|
| 130 |
|
| 131 |
+
# ---------------------------------------------------------------------------
|
| 132 |
+
# Groundtruth loading
|
| 133 |
+
# ---------------------------------------------------------------------------
|
| 134 |
+
|
| 135 |
+
def load_groundtruth_metadata(dataset_name: str = "Pettingllms/AMA-bench",
|
| 136 |
+
token: str = None) -> Dict[str, dict]:
|
| 137 |
"""
|
| 138 |
+
Load groundtruth metadata. Returns a dict with two sub-dicts:
|
| 139 |
|
| 140 |
+
{
|
| 141 |
+
"episode_domain": {
|
| 142 |
+
"episode_id": "GAME" | "TEXT2SQL" | ...
|
| 143 |
+
},
|
| 144 |
+
"question_cap": {
|
| 145 |
+
"question_uuid": "A" | "B" | "C" | "D"
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
|
| 149 |
+
- episode_domain: episode_id -> domain (used even when question uuid doesn't match)
|
| 150 |
+
- question_cap: question_uuid -> capability letter
|
| 151 |
"""
|
| 152 |
+
episode_domain: Dict[str, str] = {}
|
| 153 |
+
question_cap: Dict[str, str] = {}
|
| 154 |
+
|
| 155 |
+
def _index_rows(rows):
|
| 156 |
+
for row in rows:
|
| 157 |
+
episode_id = str(row.get("episode_id", ""))
|
| 158 |
+
domain = row.get("domain", "UNKNOWN").upper()
|
| 159 |
+
episode_domain[episode_id] = domain
|
| 160 |
+
for qa in row.get("qa_pairs", []):
|
| 161 |
+
question_uuid = qa.get("question_uuid", "").strip()
|
| 162 |
+
if not question_uuid:
|
| 163 |
+
continue
|
| 164 |
+
cap_letter = _normalize_cap(qa.get("type", "A"))
|
| 165 |
+
question_cap[question_uuid] = cap_letter
|
| 166 |
|
| 167 |
+
# --- Try HuggingFace ---
|
| 168 |
+
try:
|
| 169 |
+
from datasets import load_dataset, VerificationMode
|
| 170 |
+
dataset = load_dataset(
|
| 171 |
+
dataset_name, split="test", token=token,
|
| 172 |
+
verification_mode=VerificationMode.NO_CHECKS,
|
| 173 |
+
)
|
| 174 |
+
_index_rows(dataset)
|
| 175 |
+
print(f"[groundtruth] Loaded {len(episode_domain)} episodes, "
|
| 176 |
+
f"{len(question_cap)} Q&A entries from HuggingFace (indexed by question_uuid).")
|
| 177 |
+
return {"episode_domain": episode_domain, "question_cap": question_cap}
|
| 178 |
+
except Exception as hf_err:
|
| 179 |
+
print(f"[groundtruth] HuggingFace failed ({hf_err}), trying local fallback…")
|
| 180 |
+
|
| 181 |
+
# --- Local fallback ---
|
| 182 |
+
for local_path in ["test/open_end_qa_set.jsonl", "data/open_end_qa_set.jsonl"]:
|
| 183 |
+
if not os.path.exists(local_path):
|
| 184 |
+
continue
|
| 185 |
+
try:
|
| 186 |
+
rows = []
|
| 187 |
+
with open(local_path, "r", encoding="utf-8") as f:
|
| 188 |
+
for line in f:
|
| 189 |
+
line = line.strip()
|
| 190 |
+
if line:
|
| 191 |
+
rows.append(json.loads(line))
|
| 192 |
+
_index_rows(rows)
|
| 193 |
+
print(f"[groundtruth] Loaded {len(episode_domain)} episodes, "
|
| 194 |
+
f"{len(question_cap)} Q&A entries from {local_path} (indexed by question_uuid).")
|
| 195 |
+
return {"episode_domain": episode_domain, "question_cap": question_cap}
|
| 196 |
+
except Exception as e:
|
| 197 |
+
print(f"[groundtruth] Error reading {local_path}: {e}")
|
| 198 |
+
|
| 199 |
+
print("[groundtruth] WARNING: No groundtruth metadata available.")
|
| 200 |
+
return {"episode_domain": {}, "question_cap": {}}
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
def _normalize_cap(cap: str) -> str:
|
| 204 |
+
"""Normalize capability label to single letter A/B/C/D."""
|
| 205 |
+
mapping = {
|
| 206 |
+
"A": "A", "Recall": "A",
|
| 207 |
+
"B": "B", "Causal Inference": "B", "Causal": "B",
|
| 208 |
+
"C": "C", "State Updating": "C", "State": "C",
|
| 209 |
+
"D": "D", "State Abstraction": "D", "Abstraction": "D",
|
| 210 |
+
}
|
| 211 |
+
return mapping.get(cap.strip(), "A")
|
| 212 |
|
|
|
|
|
|
|
| 213 |
|
| 214 |
+
# ---------------------------------------------------------------------------
|
| 215 |
+
# Scoring
|
| 216 |
+
# ---------------------------------------------------------------------------
|
| 217 |
|
| 218 |
+
VALID_DOMAINS = {"TEXT2SQL", "SOFTWARE", "WEB", "GAME", "EMBODIED_AI", "OPENWORLD_QA"}
|
| 219 |
+
VALID_CAPS = ["A", "B", "C", "D"]
|
|
|
|
| 220 |
|
|
|
|
|
|
|
| 221 |
|
| 222 |
+
def compute_scores_from_submissions(
|
| 223 |
+
submissions: List[dict],
|
| 224 |
+
groundtruth_meta: Dict[str, dict],
|
| 225 |
+
) -> Dict:
|
| 226 |
+
"""
|
| 227 |
+
Compute per-domain, per-capability accuracy using llm_as_judge_score_list.
|
| 228 |
|
| 229 |
+
Each question is matched to groundtruth via question_uuid.
|
| 230 |
+
Score structure matches agent.jsonl / model.jsonl:
|
| 231 |
+
{
|
| 232 |
+
"TEXT2SQL": [{"A": 0.xx}, {"B": 0.xx}, {"C": 0.xx}, {"D": 0.xx}],
|
| 233 |
+
...
|
|
|
|
|
|
|
| 234 |
}
|
| 235 |
+
"""
|
| 236 |
+
# domain -> capability -> [scores]
|
| 237 |
+
domain_cap_scores: Dict[str, Dict[str, List[float]]] = defaultdict(
|
| 238 |
+
lambda: defaultdict(list)
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
scored_questions = 0
|
| 242 |
+
skipped_episodes = 0 # no judge scores
|
| 243 |
+
unmatched_questions = 0 # question cap not found (domain still resolved via episode)
|
| 244 |
+
|
| 245 |
+
# Unpack the two indexes from groundtruth metadata
|
| 246 |
+
episode_domain: Dict[str, str] = groundtruth_meta.get("episode_domain", {})
|
| 247 |
+
question_cap: Dict[str, str] = groundtruth_meta.get("question_cap", {})
|
| 248 |
+
|
| 249 |
+
for sub in submissions:
|
| 250 |
+
episode_id = str(sub["episode_id"])
|
| 251 |
+
question_uuid_list = sub["question_uuid_list"]
|
| 252 |
+
judge_scores = sub.get("llm_as_judge_score_list")
|
| 253 |
+
|
| 254 |
+
# Resolve domain via episode_id
|
| 255 |
+
domain = episode_domain.get(episode_id, "UNKNOWN").upper()
|
| 256 |
+
|
| 257 |
+
for i, question_uuid in enumerate(question_uuid_list):
|
| 258 |
+
if i >= len(judge_scores):
|
| 259 |
+
break
|
| 260 |
+
|
| 261 |
+
# Resolve capability via question_uuid
|
| 262 |
+
cap = question_cap.get(question_uuid.strip())
|
| 263 |
+
if cap is None:
|
| 264 |
+
unmatched_questions += 1
|
| 265 |
+
continue
|
| 266 |
+
|
| 267 |
+
score = 1.0 if judge_scores[i] is True else 0.0
|
| 268 |
+
domain_cap_scores[domain][cap].append(score)
|
| 269 |
+
scored_questions += 1
|
| 270 |
+
|
| 271 |
+
# Build Score dict — always include all 6 known domains
|
| 272 |
+
score_dict: Dict[str, List[dict]] = {}
|
| 273 |
+
for domain in sorted(VALID_DOMAINS | set(domain_cap_scores.keys())):
|
| 274 |
+
cap_data = domain_cap_scores.get(domain, {})
|
| 275 |
+
score_dict[domain] = [
|
| 276 |
+
{cap: round(sum(cap_data[cap]) / len(cap_data[cap]), 4)
|
| 277 |
+
if cap_data.get(cap) else 0.0}
|
| 278 |
+
for cap in VALID_CAPS
|
| 279 |
+
]
|
| 280 |
+
|
| 281 |
+
# Coverage warning
|
| 282 |
+
coverage_warning = None
|
| 283 |
+
parts = []
|
| 284 |
+
if skipped_episodes:
|
| 285 |
+
parts.append(f"{skipped_episodes} episode(s) had no llm_as_judge_score_list")
|
| 286 |
+
if unmatched_questions:
|
| 287 |
+
parts.append(f"{unmatched_questions} question(s) not matched in groundtruth")
|
| 288 |
+
if parts:
|
| 289 |
+
coverage_warning = "; ".join(parts)
|
| 290 |
|
| 291 |
+
return {
|
| 292 |
+
"Score": score_dict,
|
| 293 |
+
"scored_questions": scored_questions,
|
| 294 |
+
"skipped_episodes": skipped_episodes,
|
| 295 |
+
"unmatched_questions": unmatched_questions,
|
| 296 |
+
"coverage_warning": coverage_warning,
|
| 297 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
|
|
|
|
|
|
|
|
|
|
| 299 |
|
| 300 |
+
# ---------------------------------------------------------------------------
|
| 301 |
+
# Leaderboard update
|
| 302 |
+
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
| 303 |
|
| 304 |
+
def update_leaderboard_data(
|
| 305 |
+
model_or_agent_name: str,
|
| 306 |
+
model_family: str,
|
| 307 |
+
submission_type: str,
|
| 308 |
+
organisation: str,
|
| 309 |
+
score_dict: Dict,
|
| 310 |
+
verified: bool = False,
|
| 311 |
+
) -> bool:
|
| 312 |
+
"""Append a scored entry to data/agent.jsonl or data/model.jsonl."""
|
| 313 |
+
try:
|
| 314 |
+
os.makedirs("data", exist_ok=True)
|
| 315 |
+
data_file = "data/agent.jsonl" if submission_type == "agent" else "data/model.jsonl"
|
| 316 |
+
name_key = "agent_name" if submission_type == "agent" else "model"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
|
| 318 |
+
entry = {
|
| 319 |
+
name_key: model_or_agent_name,
|
| 320 |
+
"model_family": model_family,
|
| 321 |
+
"Date": datetime.datetime.today().strftime("%Y-%m-%d"),
|
| 322 |
+
"verified": verified,
|
| 323 |
+
"Score": score_dict,
|
| 324 |
+
}
|
| 325 |
+
with open(data_file, "a", encoding="utf-8") as f:
|
| 326 |
+
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
| 327 |
|
| 328 |
+
print(f"[leaderboard] Appended to {data_file}: {model_or_agent_name}")
|
| 329 |
+
return True
|
| 330 |
+
except Exception as e:
|
| 331 |
+
print(f"[leaderboard] Error: {e}")
|
| 332 |
+
import traceback; traceback.print_exc()
|
| 333 |
+
return False
|
|
|
|
|
|
|
| 334 |
|
| 335 |
|
| 336 |
+
# ---------------------------------------------------------------------------
|
| 337 |
+
# Main entry point
|
| 338 |
+
# ---------------------------------------------------------------------------
|
| 339 |
+
|
| 340 |
+
def add_new_submission(
|
| 341 |
+
model: str,
|
| 342 |
+
submission_type: str,
|
| 343 |
+
url: str,
|
| 344 |
+
file,
|
| 345 |
+
organisation: str,
|
| 346 |
+
mail: str,
|
| 347 |
+
model_family: str = "",
|
| 348 |
+
) -> str:
|
| 349 |
+
"""Validate, score, and record a new submission."""
|
|
|
|
|
|
|
| 350 |
try:
|
|
|
|
| 351 |
if file is None:
|
| 352 |
return format_warning("Please attach a submission file.")
|
|
|
|
| 353 |
_, parsed_mail = parseaddr(mail)
|
| 354 |
if "@" not in parsed_mail:
|
| 355 |
return format_warning("Please provide a valid email address.")
|
|
|
|
| 356 |
if not model or not submission_type or not organisation:
|
| 357 |
return format_warning("Please fill in all required fields.")
|
| 358 |
|
| 359 |
+
print(f"[submission] Processing {organisation}/{model} ({submission_type})")
|
| 360 |
|
|
|
|
| 361 |
is_valid, error_msg, submissions = validate_submission_file(file.name)
|
| 362 |
if not is_valid:
|
| 363 |
return format_error(error_msg)
|
| 364 |
|
| 365 |
+
print(f"[submission] Validated {len(submissions)} episode submissions")
|
| 366 |
+
|
| 367 |
+
groundtruth_meta = load_groundtruth_metadata()
|
| 368 |
+
score_result = compute_scores_from_submissions(submissions, groundtruth_meta)
|
| 369 |
+
score_dict = score_result["Score"]
|
| 370 |
+
|
| 371 |
+
# Save raw submission
|
| 372 |
+
submission_dir = f"submissions/{organisation}_{model}"
|
| 373 |
+
os.makedirs(submission_dir, exist_ok=True)
|
| 374 |
+
timestamp = datetime.datetime.today().strftime("%Y%m%d_%H%M%S")
|
| 375 |
+
saved_file = f"{submission_dir}/submission_{timestamp}.jsonl"
|
| 376 |
+
with open(saved_file, "w", encoding="utf-8") as f_out:
|
| 377 |
+
for sub in submissions:
|
| 378 |
+
f_out.write(json.dumps(sub, ensure_ascii=False) + "\n")
|
| 379 |
+
|
| 380 |
+
# Save metadata
|
| 381 |
+
metadata = {
|
| 382 |
+
"model" if submission_type.lower() == "model" else "agent_name": model,
|
| 383 |
+
"model_family": model_family,
|
| 384 |
+
"submission_type": submission_type.lower(),
|
| 385 |
+
"organisation": organisation,
|
| 386 |
+
"url": url,
|
| 387 |
+
"mail": parsed_mail,
|
| 388 |
+
"Date": datetime.datetime.today().strftime("%Y-%m-%d"),
|
| 389 |
+
"timestamp": timestamp,
|
| 390 |
+
"verified": False,
|
| 391 |
+
"submission_count": len(submissions),
|
| 392 |
+
"scored_questions": score_result["scored_questions"],
|
| 393 |
+
"skipped_episodes": score_result["skipped_episodes"],
|
| 394 |
+
"unmatched_questions": score_result["unmatched_questions"],
|
| 395 |
+
"file_path": saved_file,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
}
|
| 397 |
+
with open(f"{submission_dir}/metadata_{timestamp}.json", "w", encoding="utf-8") as f_meta:
|
| 398 |
+
json.dump(metadata, f_meta, indent=2, ensure_ascii=False)
|
| 399 |
+
|
| 400 |
+
# Update leaderboard
|
| 401 |
+
updated = update_leaderboard_data(
|
| 402 |
+
model_or_agent_name=model,
|
| 403 |
+
model_family=model_family,
|
| 404 |
+
submission_type=submission_type.lower(),
|
| 405 |
+
organisation=organisation,
|
| 406 |
+
score_dict=score_dict,
|
| 407 |
+
verified=False,
|
| 408 |
+
)
|
| 409 |
+
if not updated:
|
| 410 |
+
return format_error("Submission validated but failed to update leaderboard data.")
|
| 411 |
+
|
| 412 |
+
type_label = "Agent" if submission_type.lower() == "agent" else "Model"
|
| 413 |
+
|
| 414 |
+
# Compute per-domain averages and overall avg
|
| 415 |
+
domain_order = ["TEXT2SQL", "SOFTWARE", "WEB", "GAME", "EMBODIED_AI", "OPENWORLD_QA"]
|
| 416 |
+
domain_avgs = {}
|
| 417 |
+
for dom in domain_order:
|
| 418 |
+
caps = score_dict.get(dom, [])
|
| 419 |
+
vals = [list(c.values())[0] for c in caps if c]
|
| 420 |
+
domain_avgs[dom] = sum(vals) / len(vals) if vals else 0.0
|
| 421 |
+
overall_avg = sum(domain_avgs.values()) / len(domain_avgs) if domain_avgs else 0.0
|
| 422 |
+
|
| 423 |
+
# Build domain rows — all colors explicit to override Gradio dark theme
|
| 424 |
+
TD = 'style="padding:8px 12px;text-align:center;color:#2c3e50;background:#ffffff;"'
|
| 425 |
+
TD_NAME = 'style="padding:8px 12px;font-weight:600;color:#1a1a2e;background:#ffffff;"'
|
| 426 |
+
TD_AVG = 'style="padding:8px 12px;text-align:center;font-weight:700;color:#0e9e7a;background:#ffffff;"'
|
| 427 |
+
|
| 428 |
+
dom_rows_html = ""
|
| 429 |
+
for i, dom in enumerate(domain_order):
|
| 430 |
+
caps = score_dict.get(dom, [])
|
| 431 |
+
cap_cells = "".join(
|
| 432 |
+
f'<td {TD}>{list(c.values())[0]*100:.1f}%</td>'
|
| 433 |
+
for c in caps
|
| 434 |
+
)
|
| 435 |
+
avg = domain_avgs.get(dom, 0.0)
|
| 436 |
+
row_bg = "#f9fbff" if i % 2 == 0 else "#ffffff"
|
| 437 |
+
dom_rows_html += (
|
| 438 |
+
f'<tr style="border-bottom:1px solid #e8eef3;">'
|
| 439 |
+
f'<td style="padding:8px 12px;font-weight:600;color:#1a1a2e;background:{row_bg};">{dom}</td>'
|
| 440 |
+
f'<td style="padding:8px 12px;text-align:center;font-weight:700;color:#0e9e7a;background:{row_bg};">{avg*100:.2f}%</td>'
|
| 441 |
+
+ "".join(
|
| 442 |
+
f'<td style="padding:8px 12px;text-align:center;color:#2c3e50;background:{row_bg};">{list(c.values())[0]*100:.1f}%</td>'
|
| 443 |
+
for c in caps
|
| 444 |
+
)
|
| 445 |
+
+ '</tr>'
|
| 446 |
+
)
|
| 447 |
+
|
| 448 |
+
warning_html = (
|
| 449 |
+
'<div style="margin-top:12px;padding:10px 14px;background:#fff8e1;'
|
| 450 |
+
'border-left:4px solid #f0ad4e;border-radius:6px;font-size:13px;color:#7d5a00;">'
|
| 451 |
+
f'⚠️ {score_result["coverage_warning"]}</div>'
|
| 452 |
+
if score_result["coverage_warning"] else ""
|
| 453 |
+
)
|
| 454 |
|
| 455 |
+
result_html = (
|
| 456 |
+
'<div style="border:1px solid #c8e6c9;border-radius:12px;overflow:hidden;'
|
| 457 |
+
'margin-top:16px;font-family:-apple-system,BlinkMacSystemFont,sans-serif;'
|
| 458 |
+
'background:#ffffff;color:#1a1a2e;">'
|
| 459 |
+
|
| 460 |
+
# Header
|
| 461 |
+
'<div style="background:linear-gradient(135deg,#1abc9c,#16a085);padding:16px 22px;'
|
| 462 |
+
'display:flex;align-items:center;gap:12px;">'
|
| 463 |
+
'<span style="font-size:24px;">✅</span>'
|
| 464 |
+
'<span style="color:#ffffff;font-size:18px;font-weight:700;letter-spacing:0.3px;">'
|
| 465 |
+
'Submission Received Successfully</span>'
|
| 466 |
+
'</div>'
|
| 467 |
+
|
| 468 |
+
# Meta row
|
| 469 |
+
'<div style="padding:18px 22px;background:#f0faf7;display:flex;flex-wrap:wrap;'
|
| 470 |
+
'gap:28px;border-bottom:1px solid #d5eee8;">'
|
| 471 |
+
+ "".join(
|
| 472 |
+
f'<div><div style="color:#6b8f85;font-size:11px;font-weight:600;'
|
| 473 |
+
f'letter-spacing:0.8px;text-transform:uppercase;">{label}</div>'
|
| 474 |
+
f'<div style="font-weight:700;font-size:15px;color:{color};margin-top:3px;">{value}</div></div>'
|
| 475 |
+
for label, value, color in [
|
| 476 |
+
(type_label, model, "#1a1a2e"),
|
| 477 |
+
("Organisation", organisation, "#1a1a2e"),
|
| 478 |
+
("Episodes", str(len(submissions)), "#1a1a2e"),
|
| 479 |
+
("Questions Scored", str(score_result["scored_questions"]), "#1a1a2e"),
|
| 480 |
+
("Overall Avg", f"{overall_avg*100:.2f}%", "#0e9e7a"),
|
| 481 |
+
("Submission ID", timestamp, "#666"),
|
| 482 |
+
]
|
| 483 |
+
)
|
| 484 |
+
+ '</div>'
|
| 485 |
+
|
| 486 |
+
# Score table
|
| 487 |
+
'<div style="padding:18px 22px;background:#ffffff;">'
|
| 488 |
+
'<div style="font-size:13px;font-weight:600;color:#444;margin-bottom:12px;">'
|
| 489 |
+
'📊 Score Preview '
|
| 490 |
+
'<span style="font-weight:400;color:#888;">(self-reported · pending official verification)</span>'
|
| 491 |
+
'</div>'
|
| 492 |
+
'<div style="border-radius:8px;overflow:hidden;border:1px solid #e0eaf0;">'
|
| 493 |
+
'<table style="width:100%;border-collapse:collapse;font-size:13px;">'
|
| 494 |
+
'<thead>'
|
| 495 |
+
'<tr style="background:#e8f4f0;">'
|
| 496 |
+
'<th style="padding:9px 12px;text-align:left;color:#1a1a2e;font-weight:600;">Domain</th>'
|
| 497 |
+
'<th style="padding:9px 12px;text-align:center;color:#1a1a2e;font-weight:600;">Avg</th>'
|
| 498 |
+
'<th style="padding:9px 12px;text-align:center;color:#1a1a2e;font-weight:600;">Recall (A)</th>'
|
| 499 |
+
'<th style="padding:9px 12px;text-align:center;color:#1a1a2e;font-weight:600;">Causal Inf. (B)</th>'
|
| 500 |
+
'<th style="padding:9px 12px;text-align:center;color:#1a1a2e;font-weight:600;">State Upd. (C)</th>'
|
| 501 |
+
'<th style="padding:9px 12px;text-align:center;color:#1a1a2e;font-weight:600;">State Abs. (D)</th>'
|
| 502 |
+
'</tr>'
|
| 503 |
+
'</thead>'
|
| 504 |
+
f'<tbody>{dom_rows_html}</tbody>'
|
| 505 |
+
'</table>'
|
| 506 |
+
'</div>'
|
| 507 |
+
+ warning_html +
|
| 508 |
+
'<div style="margin-top:14px;padding:10px 14px;background:#fffbea;border-radius:6px;'
|
| 509 |
+
'font-size:12px;color:#7d5a00;line-height:1.7;border-left:3px solid #f5c518;">'
|
| 510 |
+
'ℹ️ This is a <strong style="color:#5a3e00;">self-reported preview</strong> based on your '
|
| 511 |
+
'<code style="background:#f5e9b8;color:#5a3e00;padding:1px 4px;border-radius:3px;">llm_as_judge_score_list</code>. '
|
| 512 |
+
'Official scores will be recomputed by LLM-as-Judge — your entry will appear on the leaderboard after weekly verification.'
|
| 513 |
+
'</div>'
|
| 514 |
+
'</div>'
|
| 515 |
+
'</div>'
|
| 516 |
+
'</div>'
|
| 517 |
+
)
|
| 518 |
+
return result_html
|
| 519 |
|
| 520 |
except Exception as e:
|
| 521 |
+
import traceback; traceback.print_exc()
|
| 522 |
+
return format_error(f"An error occurred: {str(e)}")
|
|
|
|
|
|