Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
mmeb v3 update
#147
by MINGYISU - opened
- app.py +104 -53
- datasets.py +21 -1
- overview.png +2 -2
- report_score_v3.py +250 -0
- scores/LCO-Embedding-Omni-7B.json +0 -0
- scores/e5-omni-3B.json +0 -0
- scores/e5-omni-7B.json +0 -0
- scores/omni-embed-nemotron-3b.json +0 -0
- utils.py +61 -50
- utils_v2.py → utils_v3.py +53 -10
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
from utils import *
|
| 2 |
-
import
|
| 3 |
import gradio as gr
|
| 4 |
|
| 5 |
global data_component
|
|
@@ -13,25 +13,38 @@ def update_table(query, min_size, max_size, selected_tasks=None):
|
|
| 13 |
return filtered_df
|
| 14 |
|
| 15 |
def update_table_v2(query, min_size, max_size):
|
| 16 |
-
df =
|
| 17 |
-
filtered_df =
|
| 18 |
return filtered_df
|
| 19 |
|
| 20 |
with gr.Blocks() as block:
|
| 21 |
gr.Markdown(LEADERBOARD_INTRODUCTION)
|
| 22 |
-
|
|
|
|
| 23 |
with gr.Tabs(elem_classes="tab-buttons") as tabs:
|
| 24 |
# Table 1, the main leaderboard of overall scores
|
| 25 |
-
with gr.TabItem("📊 MMEB (
|
| 26 |
with gr.Row():
|
| 27 |
with gr.Accordion("Citation", open=False):
|
| 28 |
citation_button2 = gr.Textbox(
|
| 29 |
-
value=
|
| 30 |
-
label=
|
| 31 |
elem_id="citation-button",
|
| 32 |
lines=10,
|
| 33 |
)
|
| 34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
with gr.Row():
|
| 37 |
search_bar2 = gr.Textbox(
|
|
@@ -42,7 +55,7 @@ with gr.Blocks() as block:
|
|
| 42 |
|
| 43 |
df = get_df()
|
| 44 |
df['Date'] = 'unknown'
|
| 45 |
-
df2 =
|
| 46 |
min_size2, max_size2 = get_size_range(df2)
|
| 47 |
|
| 48 |
with gr.Row():
|
|
@@ -60,12 +73,12 @@ with gr.Blocks() as block:
|
|
| 60 |
step=0.1,
|
| 61 |
label="Maximum number of parameters (B)",
|
| 62 |
)
|
| 63 |
-
df2_all = df2[
|
| 64 |
data_component2 = gr.components.Dataframe(
|
| 65 |
value=df2_all,
|
| 66 |
-
headers=
|
| 67 |
type="pandas",
|
| 68 |
-
datatype=
|
| 69 |
interactive=False,
|
| 70 |
visible=True,
|
| 71 |
max_height=2400,
|
|
@@ -74,9 +87,9 @@ with gr.Blocks() as block:
|
|
| 74 |
refresh_button2 = gr.Button("Refresh")
|
| 75 |
|
| 76 |
# save a summary of rankings
|
| 77 |
-
|
| 78 |
-
download_overall_but = gr.DownloadButton("Download MMEB Ranking (CSV)", value=
|
| 79 |
-
download_overall_but_json = gr.DownloadButton("Download MMEB Ranking (JSON)", value=
|
| 80 |
|
| 81 |
def update_with_tasks_v2(*args):
|
| 82 |
return update_table_v2(*args)
|
|
@@ -96,84 +109,122 @@ with gr.Blocks() as block:
|
|
| 96 |
inputs=[search_bar2, min_size_slider2, max_size_slider2],
|
| 97 |
outputs=data_component2
|
| 98 |
)
|
| 99 |
-
refresh_button2.click(fn=
|
| 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
def get_special_processed_df2():
|
| 103 |
"""Temporary special processing to merge v1 scores with v2 image scores.
|
| 104 |
Will be removed later after v2 is fully adopted."""
|
| 105 |
-
df2_i = df2[
|
| 106 |
df1 = df.rename(columns={'V1-Overall': 'Image-Overall'})
|
| 107 |
-
df1 = df1[
|
| 108 |
combined_df = pd.concat([df1, df2_i], ignore_index=True)
|
| 109 |
-
for task in
|
| 110 |
combined_df[task] = combined_df[task].apply(lambda score: '-' if pd.isna(score) else score)
|
| 111 |
-
combined_df =
|
| 112 |
-
return combined_df[
|
|
|
|
| 113 |
|
| 114 |
-
# table
|
| 115 |
-
with gr.TabItem("🖼️ Image
|
| 116 |
-
gr.Markdown(
|
| 117 |
df2_i = get_special_processed_df2()
|
| 118 |
data_component3 = gr.components.Dataframe(
|
| 119 |
value=df2_i,
|
| 120 |
-
headers=
|
| 121 |
type="pandas",
|
| 122 |
-
datatype=
|
| 123 |
interactive=False,
|
| 124 |
visible=True,
|
| 125 |
max_height=2400,
|
| 126 |
)
|
| 127 |
-
|
| 128 |
-
download_i_but = gr.DownloadButton("Download Image Ranking (CSV)", value=
|
| 129 |
-
download_i_but_json = gr.DownloadButton("Download Image Ranking (JSON)", value=
|
| 130 |
-
|
| 131 |
-
# table
|
| 132 |
-
with gr.TabItem("💽 Video", elem_id="tab-video", id=
|
| 133 |
-
gr.Markdown(
|
| 134 |
-
df2_v =
|
| 135 |
data_component4 = gr.components.Dataframe(
|
| 136 |
value=df2_v,
|
| 137 |
-
headers=
|
| 138 |
type="pandas",
|
| 139 |
-
datatype=
|
| 140 |
interactive=False,
|
| 141 |
visible=True,
|
| 142 |
max_height=2400,
|
| 143 |
)
|
| 144 |
-
|
| 145 |
-
download_v_but = gr.DownloadButton("Download Video Ranking (CSV)", value=
|
| 146 |
-
download_v_but_json = gr.DownloadButton("Download Video Ranking (JSON)", value=
|
| 147 |
-
|
| 148 |
-
# table
|
| 149 |
-
with gr.TabItem("
|
| 150 |
-
gr.Markdown(
|
| 151 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
old_df_vd = pd.read_json('archive/cached_vd_scores_before_fix.jsonl', orient='records', lines=True)
|
| 153 |
df2_d = df2_d.merge(old_df_vd, on='Models', how='left')
|
| 154 |
df2_d = df2_d.fillna(0)
|
| 155 |
-
temp_header =
|
| 156 |
df2_d = df2_d[temp_header]
|
| 157 |
data_component5 = gr.components.Dataframe(
|
| 158 |
value=df2_d,
|
| 159 |
headers=temp_header,
|
| 160 |
type="pandas",
|
| 161 |
-
datatype=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
interactive=False,
|
| 163 |
visible=True,
|
| 164 |
max_height=2400,
|
| 165 |
)
|
| 166 |
-
v2.save_ranking_summary(df2_d, 'visdoc_ranking')
|
| 167 |
-
download_vd_but = gr.DownloadButton("Download Visual Document Ranking (CSV)", value=v2.download_ranking(df2_d, 'visdoc_ranking'))
|
| 168 |
-
download_vd_but_json = gr.DownloadButton("Download Visual Document Ranking (JSON)", value=v2.download_ranking(df2_d, 'visdoc_ranking', format='json'))
|
| 169 |
|
| 170 |
-
# table
|
| 171 |
-
with gr.TabItem("
|
| 172 |
gr.Image("overview.png", width=900, label="Dataset Overview")
|
| 173 |
gr.Markdown(LEADERBOARD_INFO, elem_classes="markdown-text")
|
| 174 |
|
| 175 |
-
# table
|
| 176 |
-
with gr.TabItem("🚀 Submit here! ", elem_id="tab-submit", id=
|
| 177 |
with gr.Row():
|
| 178 |
gr.Markdown(SUBMIT_INTRODUCTION, elem_classes="markdown-text")
|
| 179 |
|
|
|
|
| 1 |
from utils import *
|
| 2 |
+
import utils_v3 as v3
|
| 3 |
import gradio as gr
|
| 4 |
|
| 5 |
global data_component
|
|
|
|
| 13 |
return filtered_df
|
| 14 |
|
| 15 |
def update_table_v2(query, min_size, max_size):
|
| 16 |
+
df = v3.get_df()
|
| 17 |
+
filtered_df = v3.search_and_filter_models(df, query, min_size, max_size)
|
| 18 |
return filtered_df
|
| 19 |
|
| 20 |
with gr.Blocks() as block:
|
| 21 |
gr.Markdown(LEADERBOARD_INTRODUCTION)
|
| 22 |
+
with gr.Accordion("🔥 What's NEW:"):
|
| 23 |
+
gr.Markdown(ANNOUNCEMENT)
|
| 24 |
with gr.Tabs(elem_classes="tab-buttons") as tabs:
|
| 25 |
# Table 1, the main leaderboard of overall scores
|
| 26 |
+
with gr.TabItem("📊 MMEB (V3)", elem_id="tab-overall", id=1):
|
| 27 |
with gr.Row():
|
| 28 |
with gr.Accordion("Citation", open=False):
|
| 29 |
citation_button2 = gr.Textbox(
|
| 30 |
+
value=v3.CITATION_BUTTON_TEXT_V3,
|
| 31 |
+
label="Copy the following snippet to cite MMEB-V3",
|
| 32 |
elem_id="citation-button",
|
| 33 |
lines=10,
|
| 34 |
)
|
| 35 |
+
gr.Textbox(
|
| 36 |
+
value=v3.CITATION_BUTTON_TEXT_V2,
|
| 37 |
+
label="Copy the following snippet to cite VLM2Vec/MMEB-V2",
|
| 38 |
+
elem_id="citation-button",
|
| 39 |
+
lines=10,
|
| 40 |
+
)
|
| 41 |
+
gr.Textbox(
|
| 42 |
+
value=CITATION_BUTTON_TEXT,
|
| 43 |
+
label="Copy the following snippet to cite VLM2Vec/MMEB-V1",
|
| 44 |
+
elem_id="citation-button",
|
| 45 |
+
lines=10,
|
| 46 |
+
)
|
| 47 |
+
gr.Markdown(v3.TABLE_INTRODUCTION)
|
| 48 |
|
| 49 |
with gr.Row():
|
| 50 |
search_bar2 = gr.Textbox(
|
|
|
|
| 55 |
|
| 56 |
df = get_df()
|
| 57 |
df['Date'] = 'unknown'
|
| 58 |
+
df2 = v3.get_df('Overall-V2')
|
| 59 |
min_size2, max_size2 = get_size_range(df2)
|
| 60 |
|
| 61 |
with gr.Row():
|
|
|
|
| 73 |
step=0.1,
|
| 74 |
label="Maximum number of parameters (B)",
|
| 75 |
)
|
| 76 |
+
df2_all = df2[v3.COLUMN_NAMES]
|
| 77 |
data_component2 = gr.components.Dataframe(
|
| 78 |
value=df2_all,
|
| 79 |
+
headers=v3.COLUMN_NAMES,
|
| 80 |
type="pandas",
|
| 81 |
+
datatype=v3.DATA_TITLE_TYPE,
|
| 82 |
interactive=False,
|
| 83 |
visible=True,
|
| 84 |
max_height=2400,
|
|
|
|
| 87 |
refresh_button2 = gr.Button("Refresh")
|
| 88 |
|
| 89 |
# save a summary of rankings
|
| 90 |
+
v3.save_ranking_summary(df2_all, 'mmeb_ranking')
|
| 91 |
+
download_overall_but = gr.DownloadButton("Download MMEB Ranking (CSV)", value=v3.download_ranking(df2_all, 'mmeb_ranking'))
|
| 92 |
+
download_overall_but_json = gr.DownloadButton("Download MMEB Ranking (JSON)", value=v3.download_ranking(df2_all, 'mmeb_ranking', format='json'))
|
| 93 |
|
| 94 |
def update_with_tasks_v2(*args):
|
| 95 |
return update_table_v2(*args)
|
|
|
|
| 109 |
inputs=[search_bar2, min_size_slider2, max_size_slider2],
|
| 110 |
outputs=data_component2
|
| 111 |
)
|
| 112 |
+
refresh_button2.click(fn=v3.refresh_data, outputs=data_component2)
|
| 113 |
|
| 114 |
+
# table 2, text scores
|
| 115 |
+
with gr.TabItem("📝 Text [NEW]", elem_id="tab-text", id=2):
|
| 116 |
+
data_component_t = gr.components.Dataframe(
|
| 117 |
+
value=v3.rank_models(df2[v3.COLUMN_NAMES_T], 'Text-Overall'),
|
| 118 |
+
headers=v3.COLUMN_NAMES_T,
|
| 119 |
+
type="pandas",
|
| 120 |
+
datatype=v3.DATA_TITLE_TYPE_T,
|
| 121 |
+
interactive=False,
|
| 122 |
+
visible=True,
|
| 123 |
+
max_height=2400,
|
| 124 |
+
)
|
| 125 |
|
| 126 |
def get_special_processed_df2():
|
| 127 |
"""Temporary special processing to merge v1 scores with v2 image scores.
|
| 128 |
Will be removed later after v2 is fully adopted."""
|
| 129 |
+
df2_i = df2[v3.COLUMN_NAMES_I]
|
| 130 |
df1 = df.rename(columns={'V1-Overall': 'Image-Overall'})
|
| 131 |
+
df1 = df1[v3.BASE_COLS + v3.SUB_TASKS_I + ['Image-Overall']]
|
| 132 |
combined_df = pd.concat([df1, df2_i], ignore_index=True)
|
| 133 |
+
for task in v3.TASKS_I:
|
| 134 |
combined_df[task] = combined_df[task].apply(lambda score: '-' if pd.isna(score) else score)
|
| 135 |
+
combined_df = v3.rank_models(combined_df, 'Image-Overall')
|
| 136 |
+
return combined_df[v3.COLUMN_NAMES_I]
|
| 137 |
+
|
| 138 |
|
| 139 |
+
# table 3, image scores only
|
| 140 |
+
with gr.TabItem("🖼️ Image", elem_id="tab-image", id=3):
|
| 141 |
+
gr.Markdown(v3.TABLE_INTRODUCTION_I)
|
| 142 |
df2_i = get_special_processed_df2()
|
| 143 |
data_component3 = gr.components.Dataframe(
|
| 144 |
value=df2_i,
|
| 145 |
+
headers=v3.COLUMN_NAMES_I,
|
| 146 |
type="pandas",
|
| 147 |
+
datatype=v3.DATA_TITLE_TYPE_I,
|
| 148 |
interactive=False,
|
| 149 |
visible=True,
|
| 150 |
max_height=2400,
|
| 151 |
)
|
| 152 |
+
v3.save_ranking_summary(df2_i, 'image_ranking')
|
| 153 |
+
download_i_but = gr.DownloadButton("Download Image Ranking (CSV)", value=v3.download_ranking(df2_i, 'image_ranking'))
|
| 154 |
+
download_i_but_json = gr.DownloadButton("Download Image Ranking (JSON)", value=v3.download_ranking(df2_i, 'image_ranking', format='json'))
|
| 155 |
+
|
| 156 |
+
# table 4, video scores only
|
| 157 |
+
with gr.TabItem("💽 Video", elem_id="tab-video", id=4):
|
| 158 |
+
gr.Markdown(v3.TABLE_INTRODUCTION_V)
|
| 159 |
+
df2_v = v3.rank_models(df2[v3.COLUMN_NAMES_V], 'Video-Overall')
|
| 160 |
data_component4 = gr.components.Dataframe(
|
| 161 |
value=df2_v,
|
| 162 |
+
headers=v3.COLUMN_NAMES_V,
|
| 163 |
type="pandas",
|
| 164 |
+
datatype=v3.DATA_TITLE_TYPE_V,
|
| 165 |
interactive=False,
|
| 166 |
visible=True,
|
| 167 |
max_height=2400,
|
| 168 |
)
|
| 169 |
+
v3.save_ranking_summary(df2_v, 'video_ranking')
|
| 170 |
+
download_v_but = gr.DownloadButton("Download Video Ranking (CSV)", value=v3.download_ranking(df2_v, 'video_ranking'))
|
| 171 |
+
download_v_but_json = gr.DownloadButton("Download Video Ranking (JSON)", value=v3.download_ranking(df2_v, 'video_ranking', format='json'))
|
| 172 |
+
|
| 173 |
+
# table 5, audio scores
|
| 174 |
+
with gr.TabItem("🎵 Audio [NEW]", elem_id="tab-audio", id=5):
|
| 175 |
+
gr.Markdown(v3.TABLE_INTRODUCTION_A)
|
| 176 |
+
data_component_a = gr.components.Dataframe(
|
| 177 |
+
value=v3.rank_models(df2[v3.COLUMN_NAMES_A], 'Audio-Overall'),
|
| 178 |
+
headers=v3.COLUMN_NAMES_A,
|
| 179 |
+
type="pandas",
|
| 180 |
+
datatype=v3.DATA_TITLE_TYPE_A,
|
| 181 |
+
interactive=False,
|
| 182 |
+
visible=True,
|
| 183 |
+
max_height=2400,
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
# table 6, visual document scores only
|
| 187 |
+
with gr.TabItem("📑 Visual Doc", elem_id="tab-visdoc", id=6):
|
| 188 |
+
gr.Markdown(v3.TABLE_INTRODUCTION_D)
|
| 189 |
+
df2_d = v3.rank_models(df2[v3.COLUMN_NAMES_D], 'Visdoc-Overall')
|
| 190 |
old_df_vd = pd.read_json('archive/cached_vd_scores_before_fix.jsonl', orient='records', lines=True)
|
| 191 |
df2_d = df2_d.merge(old_df_vd, on='Models', how='left')
|
| 192 |
df2_d = df2_d.fillna(0)
|
| 193 |
+
temp_header = v3.COLUMN_NAMES_D[:5] + ['Visdoc-Overall-before-fix', 'VisDoc-OOD-before-fix'] + v3.COLUMN_NAMES_D[5:] + [ 'ViDoSeek-page-before-fix', 'MMLongBench-page-before-fix']
|
| 194 |
df2_d = df2_d[temp_header]
|
| 195 |
data_component5 = gr.components.Dataframe(
|
| 196 |
value=df2_d,
|
| 197 |
headers=temp_header,
|
| 198 |
type="pandas",
|
| 199 |
+
datatype=v3.DATA_TITLE_TYPE_D+['number']*4,
|
| 200 |
+
interactive=False,
|
| 201 |
+
visible=True,
|
| 202 |
+
max_height=2400,
|
| 203 |
+
)
|
| 204 |
+
v3.save_ranking_summary(df2_d, 'visdoc_ranking')
|
| 205 |
+
download_vd_but = gr.DownloadButton("Download Visual Document Ranking (CSV)", value=v3.download_ranking(df2_d, 'visdoc_ranking'))
|
| 206 |
+
download_vd_but_json = gr.DownloadButton("Download Visual Document Ranking (JSON)", value=v3.download_ranking(df2_d, 'visdoc_ranking', format='json'))
|
| 207 |
+
|
| 208 |
+
# table 7, agent scores
|
| 209 |
+
with gr.TabItem("🤖 Agents [NEW]", elem_id="tab-agents", id=7):
|
| 210 |
+
gr.Markdown(v3.TABLE_INTRODUCTION_AG)
|
| 211 |
+
data_component_ag = gr.components.Dataframe(
|
| 212 |
+
value=v3.rank_models(df2[v3.COLUMN_NAMES_AG], 'Agent-Overall'),
|
| 213 |
+
headers=v3.COLUMN_NAMES_AG,
|
| 214 |
+
type="pandas",
|
| 215 |
+
datatype=v3.DATA_TITLE_TYPE_AG,
|
| 216 |
interactive=False,
|
| 217 |
visible=True,
|
| 218 |
max_height=2400,
|
| 219 |
)
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
+
# table 8
|
| 222 |
+
with gr.TabItem("📰 About", elem_id="tab-about", id=8):
|
| 223 |
gr.Image("overview.png", width=900, label="Dataset Overview")
|
| 224 |
gr.Markdown(LEADERBOARD_INFO, elem_classes="markdown-text")
|
| 225 |
|
| 226 |
+
# table 9
|
| 227 |
+
with gr.TabItem("🚀 Submit here! ", elem_id="tab-submit", id=9):
|
| 228 |
with gr.Row():
|
| 229 |
gr.Markdown(SUBMIT_INTRODUCTION, elem_classes="markdown-text")
|
| 230 |
|
datasets.py
CHANGED
|
@@ -8,6 +8,15 @@ def sum_lol(lol):
|
|
| 8 |
SCORE_BASE_DIR = "scores"
|
| 9 |
META_DATA = ["model_name", "model_size", "url", "report_generated_date"]
|
| 10 |
DATASETS = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
"image": {
|
| 12 |
"I-CLS": ['VOC2007', 'N24News', 'SUN397', 'ObjectNet', 'Country211', 'Place365', 'ImageNet-1K', 'HatefulMemes', 'ImageNet-A', 'ImageNet-R'],
|
| 13 |
"I-QA": ['OK-VQA', 'A-OKVQA', 'DocVQA', 'InfographicsVQA', 'ChartQA', 'Visual7W', 'ScienceQA', 'GQA', 'TextVQA', 'VizWiz'],
|
|
@@ -25,7 +34,18 @@ DATASETS = {
|
|
| 25 |
"V-QA": ['Video-MME', 'MVBench', 'NExTQA', 'EgoSchema', 'ActivityNetQA'],
|
| 26 |
"V-RET": ['MSR-VTT', 'MSVD', 'DiDeMo', 'VATEX', 'YouCook2'],
|
| 27 |
"V-MRET": ['QVHighlight', 'Charades-STA', 'MomentSeeker']
|
| 28 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
}
|
| 30 |
ALL_DATASETS_SPLITS = {k: sum_lol(list(v.values())) for k, v in DATASETS.items()}
|
| 31 |
ALL_DATASETS = sum_lol(list(ALL_DATASETS_SPLITS.values()))
|
|
|
|
| 8 |
SCORE_BASE_DIR = "scores"
|
| 9 |
META_DATA = ["model_name", "model_size", "url", "report_generated_date"]
|
| 10 |
DATASETS = {
|
| 11 |
+
"text": {
|
| 12 |
+
"FollowIR": ['core17-instructions', 'news21-instructions', 'robust04-instructions'],
|
| 13 |
+
"R2MED": ['Bioinformatics', 'Biology', 'IIYi-Clinical', 'MedQA-Diag', 'MedXpertQA-Exam', 'Medical-Sciences', 'PMC-Clinical', 'PMC-Treatment'],
|
| 14 |
+
"InfoSearch": ['Audience-v1', 'Clarity-v1', 'Format-v1', 'Language-v1', 'Length-v1', 'Source-v1'],
|
| 15 |
+
"BRIGHT": ['aops', 'biology', 'earth_science', 'economics', 'leetcode', 'pony', 'psychology', 'robotics', 'stackoverflow', 'sustainable_living', 'theoremqa_questions', 'theoremqa_theorems'],
|
| 16 |
+
"LongEmbed": ['2wikimqa', 'narrativeqa', 'needle', 'passkey', 'qmsum', 'summ_screen_fd'],
|
| 17 |
+
"MultiConIR": ['Books', 'Legal Document', 'Medical Case', 'Movies', 'People'],
|
| 18 |
+
"NanoBEIR": ['NanoArguAna', 'NanoClimateFEVER', 'NanoDBPedia', 'NanoFEVER', 'NanoFiQA2018', 'NanoHotpotQA', 'NanoMSMARCO', 'NanoNFCorpus', 'NanoNQ', 'NanoQuoraRetrieval', 'NanoSCIDOCS', 'NanoSciFact', 'NanoTouche2020']
|
| 19 |
+
},
|
| 20 |
"image": {
|
| 21 |
"I-CLS": ['VOC2007', 'N24News', 'SUN397', 'ObjectNet', 'Country211', 'Place365', 'ImageNet-1K', 'HatefulMemes', 'ImageNet-A', 'ImageNet-R'],
|
| 22 |
"I-QA": ['OK-VQA', 'A-OKVQA', 'DocVQA', 'InfographicsVQA', 'ChartQA', 'Visual7W', 'ScienceQA', 'GQA', 'TextVQA', 'VizWiz'],
|
|
|
|
| 34 |
"V-QA": ['Video-MME', 'MVBench', 'NExTQA', 'EgoSchema', 'ActivityNetQA'],
|
| 35 |
"V-RET": ['MSR-VTT', 'MSVD', 'DiDeMo', 'VATEX', 'YouCook2'],
|
| 36 |
"V-MRET": ['QVHighlight', 'Charades-STA', 'MomentSeeker']
|
| 37 |
+
},
|
| 38 |
+
"audio": {
|
| 39 |
+
"A-CLS": ["SpeechCommands", "UrbanSound8K", "ESC-50", "NSynth", "CREMA-D"],
|
| 40 |
+
"A-RET": ['Clotho', 'SoundDescs', 'TUTSound', 'TUTSound(hard)', 'AVE', 'SpeechCOCO']
|
| 41 |
+
},
|
| 42 |
+
"agent": {
|
| 43 |
+
"Tool": ['apibank', 'apigen', 'mnms', 'reversechain', 'rotbench', 't-eval-dialog', 't-eval-step', 'taskbench-daily', 'toolace', 'toolbench', 'toolemu', 'tooleyes', 'toollens', 'ultratool', 'autotools-food', 'autotools-music', 'autotools-weather', 'restgpt-spotify', 'restgpt-tmdb',
|
| 44 |
+
'craft-math-algebra', 'craft-tabmwp', 'craft-vqa', 'gorilla-huggingface', 'gorilla-pytorch', 'gorilla-tensor', 'toolink',
|
| 45 |
+
'appbench', 'gpt4tools', 'gta', 'taskbench-huggingface', 'taskbench-multimedia', 'metatool', 'tool-be-honest', 'toolalpaca', 'toolbench-sam'],
|
| 46 |
+
"GUI": ['GAE-GUIAct_q2t', 'GAE-GUIAct_q2s', 'GAE-GUIAct_s2s', 'GAE-GUIAct_t2s', 'GAE-Mind2Web_q2t', 'GAE-Mind2Web_q2s', 'GAE-Mind2Web_s2s', 'GAE-Mind2Web_t2s'],
|
| 47 |
+
"Memory": ["REALTALK", "KnowMeBench", "PeerQA", "DeepPlanning"]
|
| 48 |
+
}
|
| 49 |
}
|
| 50 |
ALL_DATASETS_SPLITS = {k: sum_lol(list(v.values())) for k, v in DATASETS.items()}
|
| 51 |
ALL_DATASETS = sum_lol(list(ALL_DATASETS_SPLITS.values()))
|
overview.png
CHANGED
|
Git LFS Details
|
|
Git LFS Details
|
report_score_v3.py
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
report_score_v3.py: The official script to generate the final scores report (in JSON) for MMEB-V3 leaderboard submission.
|
| 3 |
+
You should only modify the Configuration section below to add your model's metadata. No other changes are needed.
|
| 4 |
+
An example configuration is provided for your reference.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
import json
|
| 9 |
+
from datetime import datetime
|
| 10 |
+
|
| 11 |
+
# ==============================================================================
|
| 12 |
+
# Configuration
|
| 13 |
+
# ==============================================================================
|
| 14 |
+
|
| 15 |
+
# ==> Unified list of experiments to process.
|
| 16 |
+
# Fill in the metadata for each experiment. `None` will become `null` in the JSON.
|
| 17 |
+
|
| 18 |
+
EXAMPLES = [
|
| 19 |
+
{
|
| 20 |
+
"path": "vlm2vec_exps/VLM2Vec-Qwen2VL-V2.0-2B/",
|
| 21 |
+
"metadata": {
|
| 22 |
+
"model_name": "VLM2Vec-Qwen2VL-V2.0-2B",
|
| 23 |
+
"model_size": "2", # in B, digits only here. 2 for 2B, 0.4 for 400M, etc.
|
| 24 |
+
"embedding_dimension": None, # Please fill in
|
| 25 |
+
"max_length_tokens": None, # Please fill in
|
| 26 |
+
"model_release_date": "2025-04-01", # Please adjust this date
|
| 27 |
+
"score_source": "", # e.g., "Self-Reported" or "TIGER-Lab"
|
| 28 |
+
"url": "" # e.g., Paper, GitHub, or Hugging Face link
|
| 29 |
+
}
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"path": "vlm2vec_exps/VLM2Vec-Qwen2VL-V2.1-2B/",
|
| 33 |
+
"metadata": {
|
| 34 |
+
"model_name": "VLM2Vec-Qwen2VL-V2.1-2B",
|
| 35 |
+
"model_size": "2", # in B, digits only here. 2 for 2B, 0.4 for 400M, etc.
|
| 36 |
+
"embedding_dimension": None, # Please fill in
|
| 37 |
+
"max_length_tokens": None, # Please fill in
|
| 38 |
+
"model_release_date": "2025-05-15", # Please adjust this date
|
| 39 |
+
"score_source": "", # e.g., "Self-Reported" or "TIGER-Lab"
|
| 40 |
+
"url": "" # e.g., Paper, GitHub, or Hugging Face link
|
| 41 |
+
}
|
| 42 |
+
},
|
| 43 |
+
]
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
# ==============================================================================
|
| 47 |
+
# TODO: Your models' metadata goes here. Please fill in the required fields.
|
| 48 |
+
# ==============================================================================
|
| 49 |
+
|
| 50 |
+
EXPERIMENTS = [
|
| 51 |
+
{
|
| 52 |
+
"path": ...,
|
| 53 |
+
"metadata": {
|
| 54 |
+
"model_name": ..., # * Mandatory Field
|
| 55 |
+
"model_backbone": ...,
|
| 56 |
+
"model_size": ...,
|
| 57 |
+
"embedding_dimension": ...,
|
| 58 |
+
"max_length_tokens": ...,
|
| 59 |
+
"model_release_date": ...,
|
| 60 |
+
"data_source": "Self-Reported",
|
| 61 |
+
"url": ...,
|
| 62 |
+
"contact": ...,
|
| 63 |
+
}
|
| 64 |
+
},
|
| 65 |
+
...
|
| 66 |
+
]
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
# ==============================================================================
|
| 70 |
+
# Main Processing Logic (No changes needed below this line)
|
| 71 |
+
# ==============================================================================
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# Define the datasets grouped by modality
|
| 75 |
+
modality2dataset = {
|
| 76 |
+
"audio": [
|
| 77 |
+
'SpeechCommand', 'UrbanSound8k', 'ESC-50', 'NSynth', 'CREMA-D', 'Clotho', 'SoundDescs', 'TUTSound', 'TUTSound(hard)', 'AVE', 'SpeechCOCO'
|
| 78 |
+
],
|
| 79 |
+
"image": [
|
| 80 |
+
"ImageNet-1K", "N24News", "HatefulMemes", "VOC2007", "SUN397", "Place365", "ImageNet-A", "ImageNet-R", "ObjectNet", "Country211",
|
| 81 |
+
"OK-VQA", "A-OKVQA", "DocVQA", "InfographicsVQA", "ChartQA", "Visual7W", "ScienceQA", "VizWiz", "GQA", "TextVQA",
|
| 82 |
+
"VisDial", "CIRR", "VisualNews_t2i", "VisualNews_i2t", "MSCOCO_t2i", "MSCOCO_i2t", "NIGHTS", "WebQA", "FashionIQ", "Wiki-SS-NQ", "OVEN", "EDIS",
|
| 83 |
+
"MSCOCO", "RefCOCO", "RefCOCO-Matching", "Visual7W-Pointing"
|
| 84 |
+
],
|
| 85 |
+
"video": [
|
| 86 |
+
"K700", "SmthSmthV2", "HMDB51", "UCF101", "Breakfast",
|
| 87 |
+
"MVBench", "Video-MME", "NExTQA", "EgoSchema", "ActivityNetQA",
|
| 88 |
+
"DiDeMo", "MSR-VTT", "MSVD", "VATEX", "YouCook2",
|
| 89 |
+
"QVHighlight", "Charades-STA", "MomentSeeker",
|
| 90 |
+
],
|
| 91 |
+
"visdoc": [
|
| 92 |
+
"ViDoRe_arxivqa", "ViDoRe_docvqa", "ViDoRe_infovqa", "ViDoRe_tabfquad", "ViDoRe_tatdqa", "ViDoRe_shiftproject",
|
| 93 |
+
"ViDoRe_syntheticDocQA_artificial_intelligence", "ViDoRe_syntheticDocQA_energy", "ViDoRe_syntheticDocQA_government_reports", "ViDoRe_syntheticDocQA_healthcare_industry",
|
| 94 |
+
"ViDoRe_esg_reports_human_labeled_v2", "ViDoRe_biomedical_lectures_v2_multilingual", "ViDoRe_economics_reports_v2_multilingual", "ViDoRe_esg_reports_v2_multilingual",
|
| 95 |
+
"VisRAG_ArxivQA", "VisRAG_ChartQA", "VisRAG_MP-DocVQA", "VisRAG_SlideVQA", "VisRAG_InfoVQA", "VisRAG_PlotQA",
|
| 96 |
+
"ViDoSeek-page", "ViDoSeek-doc", "MMLongBench-page", "MMLongBench-doc"
|
| 97 |
+
],
|
| 98 |
+
"text": [
|
| 99 |
+
'core17-instructions', 'news21-instructions', 'robust04-instructions', 'Bioinformatics', 'Biology', 'IIYi-Clinical', 'MedQA-Diag', 'MedXpertQA-Exam', 'Medical-Sciences', 'PMC-Clinical', 'PMC-Treatment', 'Audience-v1', 'Clarity-v1', 'Format-v1', 'Language-v1', 'Length-v1', 'Source-v1', 'aops', 'biology', 'earth_science', 'economics', 'leetcode', 'pony', 'psychology', 'robotics', 'stackoverflow', 'sustainable_living', 'theoremqa_questions', 'theoremqa_theorems', '2wikimqa', 'narrativeqa', 'needle', 'passkey', 'qmsum', 'summ_screen_fd', 'Books', 'Legal Document', 'Medical Case', 'Movies', 'People', 'NanoArguAna', 'NanoClimateFEVER', 'NanoDBPedia', 'NanoFEVER', 'NanoFiQA2018', 'NanoHotpotQA', 'NanoMSMARCO', 'NanoNFCorpus', 'NanoNQ', 'NanoQuoraRetrieval', 'NanoSCIDOCS', 'NanoSciFact', 'NanoTouche2020'
|
| 100 |
+
],
|
| 101 |
+
"tool": [
|
| 102 |
+
'apibank', 'apigen', 'mnms', 'reversechain', 'rotbench', 't-eval-dialog', 't-eval-step', 'taskbench-daily', 'toolace', 'toolbench', 'toolemu', 'tooleyes', 'toollens', 'ultratool', 'autotools-food', 'autotools-music', 'autotools-weather', 'restgpt-spotify', 'restgpt-tmdb', 'craft-math-algebra', 'craft-tabmwp', 'craft-vqa', 'gorilla-huggingface', 'gorilla-pytorch', 'gorilla-tensor', 'toolink', 'appbench', 'gpt4tools', 'gta', 'taskbench-huggingface', 'taskbench-multimedia', 'metatool', 'tool-be-honest', 'toolalpaca', 'toolbench-sam'
|
| 103 |
+
],
|
| 104 |
+
"gui": [
|
| 105 |
+
'GAE-GUIAct_q2t', 'GAE-GUIAct_q2s', 'GAE-GUIAct_s2s', 'GAE-GUIAct_t2s', 'GAE-Mind2Web_q2t', 'GAE-Mind2Web_q2s', 'GAE-Mind2Web_s2s', 'GAE-Mind2Web_t2s'
|
| 106 |
+
],
|
| 107 |
+
"memory": [
|
| 108 |
+
'REALTALK', 'KnowMeBench', 'PeerQA', 'DeepPlanning'
|
| 109 |
+
]
|
| 110 |
+
}
|
| 111 |
+
modality2metric = {
|
| 112 |
+
"image": "hit@1",
|
| 113 |
+
"video": "hit@1",
|
| 114 |
+
"visdoc": "ndcg_linear@5",
|
| 115 |
+
"audio": "hit@1",
|
| 116 |
+
"text": "hit@1",
|
| 117 |
+
"tool": "hit@1",
|
| 118 |
+
"gui": "hit@1",
|
| 119 |
+
"memory": "hit@1"
|
| 120 |
+
}
|
| 121 |
+
modalities = ["image", "video", "visdoc", "audio", "text", "tool", "gui", "memory"] # Process in this order
|
| 122 |
+
|
| 123 |
+
for experiment in EXPERIMENTS:
|
| 124 |
+
base_path = experiment['path']
|
| 125 |
+
experiment_metadata = experiment['metadata']
|
| 126 |
+
experiment_name_for_log = os.path.basename(base_path.strip('/'))
|
| 127 |
+
|
| 128 |
+
current_experiment_scores = {}
|
| 129 |
+
|
| 130 |
+
print(f"\nProcessing experiment: {experiment_name_for_log}")
|
| 131 |
+
print(f"Path: {base_path}")
|
| 132 |
+
|
| 133 |
+
for modality in modalities:
|
| 134 |
+
current_experiment_scores[modality] = {}
|
| 135 |
+
modality_specific_result_dir = os.path.join(base_path, modality)
|
| 136 |
+
|
| 137 |
+
for dataset_name in modality2dataset.get(modality, []):
|
| 138 |
+
current_experiment_scores[modality][dataset_name] = "FILE_N/A" # Initialize
|
| 139 |
+
|
| 140 |
+
if not os.path.isdir(modality_specific_result_dir):
|
| 141 |
+
print(f" Directory not found: {modality_specific_result_dir}")
|
| 142 |
+
for dataset_name in modality2dataset.get(modality, []):
|
| 143 |
+
current_experiment_scores[modality][dataset_name] = "DIR_N/A"
|
| 144 |
+
continue
|
| 145 |
+
|
| 146 |
+
for filename in os.listdir(modality_specific_result_dir):
|
| 147 |
+
if filename.endswith("_score.json"):
|
| 148 |
+
score_file_path = os.path.join(modality_specific_result_dir, filename)
|
| 149 |
+
dataset_name_from_file = None
|
| 150 |
+
for known_dataset in modality2dataset.get(modality, []):
|
| 151 |
+
if filename == f"{known_dataset}_score.json":
|
| 152 |
+
dataset_name_from_file = known_dataset
|
| 153 |
+
break
|
| 154 |
+
|
| 155 |
+
if dataset_name_from_file:
|
| 156 |
+
try:
|
| 157 |
+
with open(score_file_path, "r") as f:
|
| 158 |
+
score_data = json.load(f)
|
| 159 |
+
current_experiment_scores[modality][dataset_name_from_file] = score_data
|
| 160 |
+
except json.JSONDecodeError:
|
| 161 |
+
print(f" Error decoding JSON from {score_file_path}")
|
| 162 |
+
current_experiment_scores[modality][dataset_name_from_file] = "JSON_ERROR"
|
| 163 |
+
except Exception as e:
|
| 164 |
+
print(f" Error reading file {score_file_path}: {e}")
|
| 165 |
+
current_experiment_scores[modality][dataset_name_from_file] = "READ_ERROR"
|
| 166 |
+
|
| 167 |
+
# --- Construct and Save the Final JSON Report ---
|
| 168 |
+
final_metadata = experiment_metadata.copy()
|
| 169 |
+
final_metadata['report_generated_date'] = datetime.now().isoformat()
|
| 170 |
+
# --- Special handling ---
|
| 171 |
+
# Special handling for VisDoc datasets with "-fixed" suffix
|
| 172 |
+
current_experiment_scores['visdoc'] = {(f'{k}-fixed' if k in ['MMLongBench-page', 'ViDoSeek-page'] else k): v
|
| 173 |
+
for k, v in current_experiment_scores['visdoc'].items()} # temp fix
|
| 174 |
+
# merge "tool", "gui", and "memory" into "agent"
|
| 175 |
+
# current_experiment_scores['agent'] = current_experiment_scores.pop('tool', {}) | current_experiment_scores.pop('gui', {}) | current_experiment_scores.pop('memory', {})
|
| 176 |
+
# -------------------------
|
| 177 |
+
|
| 178 |
+
final_output = {
|
| 179 |
+
"metadata": final_metadata,
|
| 180 |
+
"metrics": current_experiment_scores
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
output_json_path = os.path.join(base_path, f"{final_metadata['model_name']}.json")
|
| 184 |
+
try:
|
| 185 |
+
with open(output_json_path, "w") as f:
|
| 186 |
+
json.dump(final_output, f, indent=4)
|
| 187 |
+
print(f" Report for '{experiment_name_for_log}' saved to: {output_json_path}")
|
| 188 |
+
except Exception as e:
|
| 189 |
+
print(f" Error saving JSON report for '{experiment_name_for_log}' to {output_json_path}: {e}")
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
# --- Print detailed main scores per dataset for easy copy to spreadsheet ---
|
| 193 |
+
print(f"\n --- Detailed Main Scores for Spreadsheet (Experiment: {experiment_name_for_log}) ---")
|
| 194 |
+
for modality in modalities:
|
| 195 |
+
main_metric_key = modality2metric[modality]
|
| 196 |
+
for dataset_name in modality2dataset.get(modality, []):
|
| 197 |
+
score_to_print_val = "NOT_FOUND_IN_RESULTS"
|
| 198 |
+
modality_data = current_experiment_scores.get(modality, {})
|
| 199 |
+
score_info = modality_data.get(dataset_name)
|
| 200 |
+
|
| 201 |
+
if isinstance(score_info, dict):
|
| 202 |
+
metric_value = score_info.get(main_metric_key)
|
| 203 |
+
if isinstance(metric_value, (int, float)):
|
| 204 |
+
score_to_print_val = f"{metric_value:.4f}"
|
| 205 |
+
else:
|
| 206 |
+
score_to_print_val = f"METRIC_KEY_MISSING ({main_metric_key})"
|
| 207 |
+
elif isinstance(score_info, str):
|
| 208 |
+
score_to_print_val = score_info
|
| 209 |
+
|
| 210 |
+
print(f"{dataset_name}\t{score_to_print_val}")
|
| 211 |
+
print("")
|
| 212 |
+
|
| 213 |
+
# --- Print average scores and missing datasets per modality ---
|
| 214 |
+
print(f"\n --- Summary for Experiment: {experiment_name_for_log} ---")
|
| 215 |
+
for modality in modalities:
|
| 216 |
+
if modality not in current_experiment_scores:
|
| 217 |
+
print(f" Modality '{modality.upper()}' not processed.")
|
| 218 |
+
continue
|
| 219 |
+
main_metric_key = modality2metric[modality]
|
| 220 |
+
modality_data = current_experiment_scores[modality]
|
| 221 |
+
collected_metric_values = []
|
| 222 |
+
datasets_missing_score_file = []
|
| 223 |
+
datasets_file_found_metric_missing = []
|
| 224 |
+
|
| 225 |
+
for dataset_name in modality2dataset.get(modality, []):
|
| 226 |
+
score_info = modality_data.get(dataset_name)
|
| 227 |
+
if isinstance(score_info, dict):
|
| 228 |
+
metric_value = score_info.get(main_metric_key)
|
| 229 |
+
if isinstance(metric_value, (int, float)):
|
| 230 |
+
collected_metric_values.append(metric_value)
|
| 231 |
+
else:
|
| 232 |
+
datasets_file_found_metric_missing.append(f"{dataset_name} (metric '{main_metric_key}' missing/invalid)")
|
| 233 |
+
else:
|
| 234 |
+
datasets_missing_score_file.append(f"{dataset_name} (status: {score_info if score_info else 'Not Processed'})")
|
| 235 |
+
|
| 236 |
+
if collected_metric_values:
|
| 237 |
+
average_score = sum(collected_metric_values) / len(collected_metric_values)
|
| 238 |
+
print(f" Average of {modality.upper()}\t- {main_metric_key}:\t{average_score:.4f} (from {len(collected_metric_values)} datasets)")
|
| 239 |
+
else:
|
| 240 |
+
print(f" Average of {modality.upper()}\t- {main_metric_key}:\tN/A (no valid scores found)")
|
| 241 |
+
|
| 242 |
+
if datasets_missing_score_file:
|
| 243 |
+
print(f" Datasets with missing/errored score files:")
|
| 244 |
+
for ds_status in datasets_missing_score_file: print(f" - {ds_status}")
|
| 245 |
+
if datasets_file_found_metric_missing:
|
| 246 |
+
print(f" Score files found but main metric ('{main_metric_key}') missing/invalid:")
|
| 247 |
+
for ds_status in datasets_file_found_metric_missing: print(f" - {ds_status}")
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
print("\nProcessing complete.")
|
scores/LCO-Embedding-Omni-7B.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scores/e5-omni-3B.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scores/e5-omni-7B.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scores/omni-embed-nemotron-3b.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
utils.py
CHANGED
|
@@ -18,43 +18,51 @@ LEADERBOARD_INTRODUCTION = """
|
|
| 18 |
# 📊 **MMEB LEADERBOARD (VLM2Vec)**
|
| 19 |
|
| 20 |
## Introduction
|
| 21 |
-
We introduce
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
-
|
| 46 |
<ul>
|
| 47 |
-
<li>[2026-
|
| 48 |
-
<li>[
|
| 49 |
-
<li>[
|
| 50 |
-
</
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
| [**📖MMEB-V2/VLM2Vec-V2 Paper**](https://arxiv.org/abs/2507.04590)
|
| 54 |
-
| [**📖MMEB-V1/VLM2Vec-V1 Paper**](https://arxiv.org/abs/2410.05160)
|
| 55 |
-
| [**🤗Hugging Face**](https://huggingface.co/datasets/TIGER-Lab/MMEB-V2)
|
| 56 |
-
| [**Discord**](https://discord.gg/njyKubdtry) |
|
| 57 |
-
"""
|
| 58 |
|
| 59 |
LEADERBOARD_INFO = f"""
|
| 60 |
## Dataset Overview
|
|
@@ -73,27 +81,32 @@ CITATION_BUTTON_TEXT = r"""@article{jiang2024vlm2vec,
|
|
| 73 |
}"""
|
| 74 |
|
| 75 |
SUBMIT_INTRODUCTION = """# Submit on MMEB Leaderboard Introduction \n
|
| 76 |
-
##
|
| 77 |
1. **Step 1️⃣:** Please refer to the [**GitHub page**](https://github.com/TIGER-AI-Lab/VLM2Vec) for detailed instructions about evaluating your model. \n
|
| 78 |
-
2. **Step 2️⃣:** After running the evaluation pipelines, please use the
|
| 79 |
-
-
|
| 80 |
-
- Note the "model size" field is digits-only and is
|
| 81 |
- If possible, please also add a contact method in case we want to reach you in the future
|
| 82 |
3. **Step 3️⃣:** Finally, create a pull request and upload the generated JSON file to the ***scores*** folder.
|
| 83 |
-
-
|
| 84 |
- Go to the [scores folder](https://huggingface.co/spaces/TIGER-Lab/MMEB-Leaderboard/upload/main/scores)
|
| 85 |
- Select "Upload file" and upload your JSON files.
|
| 86 |
-
-
|
| 87 |
-
- We will then review
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
```json
|
| 90 |
{
|
| 91 |
"metadata": {
|
| 92 |
"model_name": "<Model Name>",
|
| 93 |
"url": "<Model URL>" or null,
|
| 94 |
"model_size": <Model Size> or null,
|
| 95 |
-
"
|
| 96 |
-
"contact": xxx@gmail.com
|
| 97 |
... ...
|
| 98 |
},
|
| 99 |
"metrics": {
|
|
@@ -116,11 +129,9 @@ SUBMIT_INTRODUCTION = """# Submit on MMEB Leaderboard Introduction \n
|
|
| 116 |
}
|
| 117 |
```
|
| 118 |
## ⚠️ Special Instructions for submitting to MMEB Image (Previously MMEB-V1) Leaderboard
|
| 119 |
-
We understand that some researchers want to exclusively submit to the Image leaderboard, but unfortunately our current leaderboard
|
| 120 |
-
To do so,
|
| 121 |
-
The leaderboard will automatically assign a 0 to the missing datasets.
|
| 122 |
-
We might be able to hide your model from the other leaderboards in the next leaderboard updates, but for now your model will be shown on all leaderboards and might have a lower rank. \n
|
| 123 |
-
We highly recommend joining our [discord server](https://discord.gg/njyKubdtry), which provides a convenient way to stay informed with latest updates, or share any feedback you have for improving the leaderboard experience. We appreciate your contributions to the MMEB community!
|
| 124 |
"""
|
| 125 |
|
| 126 |
def create_hyperlinked_names(df):
|
|
|
|
| 18 |
# 📊 **MMEB LEADERBOARD (VLM2Vec)**
|
| 19 |
|
| 20 |
## Introduction
|
| 21 |
+
We introduce **Massive Multimodal Embedding Benchmark (MMEB)**, a novel comprehensive benchmark for evaluating omni-modality embedding models across text, image, video, audio, visual document, and agent-centric retrieval scenarios.
|
| 22 |
+
|
| 23 |
+
**MMEB-V1** includes 36 datasets spanning four image-text meta-task categories: classification, visual question answering, retrieval, visual grounding.
|
| 24 |
+
|
| 25 |
+
**MMEB-V2** expands the evaluation scope to include five new tasks:
|
| 26 |
+
- four video-based tasks: Video Retrieval, Moment Retrieval, Video Classification, and Video Question Answering
|
| 27 |
+
- one task focused on visual documents: Visual Document Retrieval.
|
| 28 |
+
|
| 29 |
+
**MMEB-V3** further extends to a fuller modality setting by adding three major new evaluation categories:
|
| 30 |
+
- Audio Tasks: audio classification, cross-modal audio retrieval, and audio temporal grounding.
|
| 31 |
+
- Text Retrieval: instruction-following retrieval, reasoning retrieval, long-context retrieval, multi-condition retrieval, and general text retrieval.
|
| 32 |
+
- Agent Tasks: tool retrieval, GUI control, and agent memory retrieval.
|
| 33 |
+
|
| 34 |
+
<div style="display:inline-flex; flex-wrap:wrap; gap:6px; align-items:center; margin:8px 0;">
|
| 35 |
+
<a target="_blank" href="https://tiger-ai-lab.github.io/VLM2Vec/">
|
| 36 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-🌐%20Website-red?style=flat"></a>
|
| 37 |
+
<a target="_blank" href="https://github.com/TIGER-AI-Lab/VLM2Vec">
|
| 38 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-MMEB--V3%20Code-green?style=flat&logo=github"></a>
|
| 39 |
+
<a target="_blank" href="https://huggingface.co/datasets/VLM2Vec/MMEB-V3">
|
| 40 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-🤗%20Dataset(MMEB--V3)-red?style=flat"></a>
|
| 41 |
+
<a target="_blank" href="https://arxiv.org/abs/2604.23321">
|
| 42 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-V3 Paper-black?style=flat&logo=arxiv"></a>
|
| 43 |
+
<a target="_blank" href="https://arxiv.org/abs/2507.04590">
|
| 44 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-V2 Paper-black?style=flat&logo=arxiv"></a>
|
| 45 |
+
<a target="_blank" href="https://arxiv.org/abs/2410.05160">
|
| 46 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-V1 Paper-black?style=flat&logo=arxiv"></a>
|
| 47 |
+
<a target="_blank" href="https://huggingface.co/datasets/TIGER-Lab/MMEB-V2">
|
| 48 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-🤗%20Dataset(V2)-red?style=flat"></a>
|
| 49 |
+
<a target="_blank" href="https://huggingface.co/datasets/TIGER-Lab/MMEB-eval">
|
| 50 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-🤗%20Dataset(V1)-red?style=flat"></a>
|
| 51 |
+
<a target="_blank" href="https://huggingface.co/VLM2Vec">
|
| 52 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-🤗%20Models-red?style=flat"></a>
|
| 53 |
+
<a target="_blank" href="https://huggingface.co/spaces/TIGER-Lab/MMEB-Leaderboard">
|
| 54 |
+
<img style="height:17pt" src="https://img.shields.io/badge/-🤗%20Leaderboard-red?style=flat"></a>
|
| 55 |
+
</div>
|
| 56 |
+
"""
|
| 57 |
|
| 58 |
+
ANNOUNCEMENT = """
|
| 59 |
<ul>
|
| 60 |
+
<li>[2026-07] MMEB-V3 Leaderboard is now live!</li>
|
| 61 |
+
<li>[2026-07] MMEB-V3 is accepted to COLM 2026!</li>
|
| 62 |
+
<li>[2026-04] MMEB-V3 released!</li>
|
| 63 |
+
<li>[2026-01] VLM2Vec/MMEB-V2 is accepted to TMLR 2026!</li>
|
| 64 |
+
<li>[2025-06] VLM2Vec/MMEB-V2 released!</li>
|
| 65 |
+
</ul>"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
LEADERBOARD_INFO = f"""
|
| 68 |
## Dataset Overview
|
|
|
|
| 81 |
}"""
|
| 82 |
|
| 83 |
SUBMIT_INTRODUCTION = """# Submit on MMEB Leaderboard Introduction \n
|
| 84 |
+
## Please follow the guidelines in order to submit successfully. \n
|
| 85 |
1. **Step 1️⃣:** Please refer to the [**GitHub page**](https://github.com/TIGER-AI-Lab/VLM2Vec) for detailed instructions about evaluating your model. \n
|
| 86 |
+
2. **Step 2️⃣:** After running the evaluation pipelines, please use the provided script **(e.g., [report_score_v2.py](https://github.com/TIGER-AI-Lab/VLM2Vec/blob/main/experiments/report_score_v2.py))** to generate the final score sheet. (Use [report_score_v3.py](https://github.com/TIGER-AI-Lab/VLM2Vec/blob/main/experiments/report_score_v3.py) for v3 submission).
|
| 87 |
+
- Adjust your model's configurations in the script before running it
|
| 88 |
+
- Note the "model size" field is digits-only and is in Billions (B), so please convert it if yours is in different units/formats (e.x., "8" for 8 billion, "0.5" for 500 million).
|
| 89 |
- If possible, please also add a contact method in case we want to reach you in the future
|
| 90 |
3. **Step 3️⃣:** Finally, create a pull request and upload the generated JSON file to the ***scores*** folder.
|
| 91 |
+
- If directly using web UI:
|
| 92 |
- Go to the [scores folder](https://huggingface.co/spaces/TIGER-Lab/MMEB-Leaderboard/upload/main/scores)
|
| 93 |
- Select "Upload file" and upload your JSON files.
|
| 94 |
+
- If by git command line: refer to the [PR documentation](https://huggingface.co/docs/hub/repositories-pull-requests-discussions#pull-requests-advanced-usage).
|
| 95 |
+
- Submit the PR and leave any comments if any. We will then review and update the leaderboard accordingly.\n
|
| 96 |
+
- To delete or modify your submission, submit a new PR with the updated file.\n\n
|
| 97 |
+
|
| 98 |
+
## 🐞 Bug reporting and feedback
|
| 99 |
+
If you encounter any issues or have improvement feedback regarding the leaderboard, please report them in Discussion.\n
|
| 100 |
+
If you cannot reach us via above methods, email us at **m7su@uwaterloo.ca**.
|
| 101 |
+
|
| 102 |
+
## Appendix 1: Example: valid score sheet format ⬇️: \n
|
| 103 |
```json
|
| 104 |
{
|
| 105 |
"metadata": {
|
| 106 |
"model_name": "<Model Name>",
|
| 107 |
"url": "<Model URL>" or null,
|
| 108 |
"model_size": <Model Size> or null,
|
| 109 |
+
"contact": xxx@xxxxx.com
|
|
|
|
| 110 |
... ...
|
| 111 |
},
|
| 112 |
"metrics": {
|
|
|
|
| 129 |
}
|
| 130 |
```
|
| 131 |
## ⚠️ Special Instructions for submitting to MMEB Image (Previously MMEB-V1) Leaderboard
|
| 132 |
+
We understand that some researchers want to exclusively submit to the Image leaderboard, but unfortunately our current leaderboard cannot exclude your model from other modalities' leaderboards.
|
| 133 |
+
To do so, run the 36 image datasets only and simply ignore other datasets.
|
| 134 |
+
The leaderboard will automatically assign a 0 to the missing datasets and your model will be shown on all leaderboards, and might have a lower rank. \n
|
|
|
|
|
|
|
| 135 |
"""
|
| 136 |
|
| 137 |
def create_hyperlinked_names(df):
|
utils_v2.py → utils_v3.py
RENAMED
|
@@ -6,11 +6,18 @@ from utils import create_hyperlinked_names, process_model_size
|
|
| 6 |
from datasets import *
|
| 7 |
|
| 8 |
BASE_COLS = ['Rank', 'Models', 'Model Size(B)', 'Date']
|
| 9 |
-
BASE_DATA_TITLE_TYPE = ['
|
| 10 |
|
| 11 |
-
|
|
|
|
| 12 |
DATA_TITLE_TYPE = BASE_DATA_TITLE_TYPE + \
|
| 13 |
-
['number'] *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
SUB_TASKS_I = ["I-CLS", "I-QA", "I-RET", "I-VG"]
|
| 16 |
TASKS_I = ['Image-Overall'] + SUB_TASKS_I + ALL_DATASETS_SPLITS['image']
|
|
@@ -24,14 +31,26 @@ COLUMN_NAMES_V = BASE_COLS + TASKS_V
|
|
| 24 |
DATA_TITLE_TYPE_V = BASE_DATA_TITLE_TYPE + \
|
| 25 |
['number'] * len(TASKS_V)
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
SUB_TASKS_D = ['ViDoRe-V1', 'ViDoRe-V2', 'VisRAG', 'VisDoc-OOD']
|
| 28 |
TASKS_D = ['Visdoc-Overall'] + SUB_TASKS_D + ALL_DATASETS_SPLITS['visdoc']
|
| 29 |
COLUMN_NAMES_D = BASE_COLS + TASKS_D
|
| 30 |
DATA_TITLE_TYPE_D = BASE_DATA_TITLE_TYPE + \
|
| 31 |
['number'] * len(TASKS_D)
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
TABLE_INTRODUCTION = """**MMEB**: Massive MultiModal Embedding Benchmark \n
|
| 34 |
-
Models are ranked based on **Overall**"""
|
| 35 |
TABLE_INTRODUCTION_I = """**I-CLS**: Image Classification, **I-QA**: (Image) Visual Question Answering, **I-RET**: Image Retrieval, **I-VG**: (Image) Visual Grounding \n
|
| 36 |
Models are ranked based on **Image-Overall**\n
|
| 37 |
**Models from the old V1 leaderboard are missing detailed scores of each dataset.
|
|
@@ -39,15 +58,19 @@ TABLE_INTRODUCTION_I = """**I-CLS**: Image Classification, **I-QA**: (Image) Vis
|
|
| 39 |
and provide us the scores sheet with the new format, so that we can make them consistent with the other models' formats.**"""
|
| 40 |
TABLE_INTRODUCTION_V = """**V-CLS**: Video Classification, **V-QA**: (Video) Visual Question Answering, **V-RET**: Video Retrieval, **V-MRET**: Video Moment Retrieval \n
|
| 41 |
Models are ranked based on **Video-Overall**"""
|
|
|
|
|
|
|
| 42 |
TABLE_INTRODUCTION_D = """⚠️ Please re-evaluate your models if you see a 0 on ViDoSeek-page-fixed or MMLongBench-page-fixed datasets. \n
|
| 43 |
**VisDoc**: Visual Document Understanding \n
|
| 44 |
Models are ranked based on **Visdoc-Overall**"""
|
|
|
|
|
|
|
| 45 |
|
| 46 |
LEADERBOARD_INFO = """
|
| 47 |
## Dataset Summary
|
| 48 |
"""
|
| 49 |
|
| 50 |
-
|
| 51 |
title={VLM2Vec-V2: Advancing Multimodal Embedding for Videos, Images, and Visual Documents},
|
| 52 |
author={Rui Meng and Ziyan Jiang and Ye Liu and Mingyi Su and Xinyi Yang and Yuepeng Fu and Can Qin and Zeyuan Chen and Ran Xu and Caiming Xiong and Yingbo Zhou and Wenhu Chen and Semih Yavuz},
|
| 53 |
year={2025},
|
|
@@ -56,6 +79,15 @@ CITATION_BUTTON_TEXT = r"""@misc{meng2025vlm2vecv2advancingmultimodalembedding,
|
|
| 56 |
primaryClass={cs.CV},
|
| 57 |
url={https://arxiv.org/abs/2507.04590},
|
| 58 |
}"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
def load_single_json(file_path):
|
| 61 |
with open(file_path, 'r') as file:
|
|
@@ -71,8 +103,12 @@ def load_data(base_dir=SCORE_BASE_DIR):
|
|
| 71 |
all_data.append(data)
|
| 72 |
return all_data
|
| 73 |
|
| 74 |
-
def load_scores(raw_scores=
|
| 75 |
"""This function loads the raw scores from the user provided scores summary and flattens them into a single dictionary."""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
all_scores = {}
|
| 77 |
for modality, datasets_list in DATASETS.items(): # Ex.: ('image', {'I-CLS': [...], 'I-QA': [...]})
|
| 78 |
for sub_task, datasets in datasets_list.items(): # Ex.: ('I-CLS', ['VOC2007', 'N24News', ...])
|
|
@@ -100,6 +136,8 @@ def calculate_score(raw_scores=None):
|
|
| 100 |
|
| 101 |
# Calculate overall score for all datasets
|
| 102 |
avg_scores['Overall'] = get_avg(sum(all_scores.values()), len(ALL_DATASETS))
|
|
|
|
|
|
|
| 103 |
|
| 104 |
# Calculate scores for each modality
|
| 105 |
for modality in MODALITIES:
|
|
@@ -134,17 +172,22 @@ def generate_model_row(data):
|
|
| 134 |
def print_time(time: str|None):
|
| 135 |
try:
|
| 136 |
dt = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S.%f")
|
| 137 |
-
return dt.strftime("%
|
| 138 |
except (ValueError, TypeError):
|
| 139 |
return 'unknown'
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
def rank_models(df, column='Overall', rank_name='Rank'):
|
| 142 |
"""Ranks the models based on the specific score."""
|
| 143 |
df = df.sort_values(by=column, ascending=False).reset_index(drop=True)
|
| 144 |
-
df[rank_name] =
|
| 145 |
return df
|
| 146 |
|
| 147 |
-
def get_df():
|
| 148 |
"""Generates a DataFrame from the loaded data."""
|
| 149 |
all_data = load_data()
|
| 150 |
rows = [generate_model_row(data) for data in all_data]
|
|
@@ -152,7 +195,7 @@ def get_df():
|
|
| 152 |
df['Model Size(B)'] = df['Model Size(B)'].apply(process_model_size)
|
| 153 |
df['Date'] = df['Date'].apply(print_time)
|
| 154 |
df = create_hyperlinked_names(df)
|
| 155 |
-
df = rank_models(df, column=
|
| 156 |
return df
|
| 157 |
|
| 158 |
def refresh_data():
|
|
|
|
| 6 |
from datasets import *
|
| 7 |
|
| 8 |
BASE_COLS = ['Rank', 'Models', 'Model Size(B)', 'Date']
|
| 9 |
+
BASE_DATA_TITLE_TYPE = ['str', 'markdown', 'str', 'str']
|
| 10 |
|
| 11 |
+
OVERALL_COLS = ["Overall", "Overall-V2", "Text-Overall", 'Image-Overall', 'Video-Overall', 'Audio-Overall', 'Visdoc-Overall', "Agent-Overall"]
|
| 12 |
+
COLUMN_NAMES = BASE_COLS + OVERALL_COLS
|
| 13 |
DATA_TITLE_TYPE = BASE_DATA_TITLE_TYPE + \
|
| 14 |
+
['number'] * len(OVERALL_COLS)
|
| 15 |
+
|
| 16 |
+
SUB_TASKS_T = ["FollowIR", "R2MED", "InfoSearch", "BRIGHT", "LongEmbed", "MultiConIR", "NanoBEIR"]
|
| 17 |
+
TASKS_T = ['Text-Overall'] + SUB_TASKS_T + ALL_DATASETS_SPLITS['text']
|
| 18 |
+
COLUMN_NAMES_T = BASE_COLS + TASKS_T
|
| 19 |
+
DATA_TITLE_TYPE_T = BASE_DATA_TITLE_TYPE + \
|
| 20 |
+
['number'] * len(TASKS_T)
|
| 21 |
|
| 22 |
SUB_TASKS_I = ["I-CLS", "I-QA", "I-RET", "I-VG"]
|
| 23 |
TASKS_I = ['Image-Overall'] + SUB_TASKS_I + ALL_DATASETS_SPLITS['image']
|
|
|
|
| 31 |
DATA_TITLE_TYPE_V = BASE_DATA_TITLE_TYPE + \
|
| 32 |
['number'] * len(TASKS_V)
|
| 33 |
|
| 34 |
+
SUB_TASKS_A = ["A-CLS", "A-RET"]
|
| 35 |
+
TASKS_A = ['Audio-Overall'] + SUB_TASKS_A + ALL_DATASETS_SPLITS['audio']
|
| 36 |
+
COLUMN_NAMES_A = BASE_COLS + TASKS_A
|
| 37 |
+
DATA_TITLE_TYPE_A = BASE_DATA_TITLE_TYPE + \
|
| 38 |
+
['number'] * len(TASKS_A)
|
| 39 |
+
|
| 40 |
SUB_TASKS_D = ['ViDoRe-V1', 'ViDoRe-V2', 'VisRAG', 'VisDoc-OOD']
|
| 41 |
TASKS_D = ['Visdoc-Overall'] + SUB_TASKS_D + ALL_DATASETS_SPLITS['visdoc']
|
| 42 |
COLUMN_NAMES_D = BASE_COLS + TASKS_D
|
| 43 |
DATA_TITLE_TYPE_D = BASE_DATA_TITLE_TYPE + \
|
| 44 |
['number'] * len(TASKS_D)
|
| 45 |
|
| 46 |
+
SUB_TASKS_AG = ['Tool', 'GUI', 'Memory']
|
| 47 |
+
TASKS_AG = ['Agent-Overall'] + SUB_TASKS_AG + ALL_DATASETS_SPLITS['agent']
|
| 48 |
+
COLUMN_NAMES_AG = BASE_COLS + TASKS_AG
|
| 49 |
+
DATA_TITLE_TYPE_AG = BASE_DATA_TITLE_TYPE + \
|
| 50 |
+
['number'] * len(TASKS_AG)
|
| 51 |
+
|
| 52 |
TABLE_INTRODUCTION = """**MMEB**: Massive MultiModal Embedding Benchmark \n
|
| 53 |
+
Models are ranked based on **Overall-V2**."""
|
| 54 |
TABLE_INTRODUCTION_I = """**I-CLS**: Image Classification, **I-QA**: (Image) Visual Question Answering, **I-RET**: Image Retrieval, **I-VG**: (Image) Visual Grounding \n
|
| 55 |
Models are ranked based on **Image-Overall**\n
|
| 56 |
**Models from the old V1 leaderboard are missing detailed scores of each dataset.
|
|
|
|
| 58 |
and provide us the scores sheet with the new format, so that we can make them consistent with the other models' formats.**"""
|
| 59 |
TABLE_INTRODUCTION_V = """**V-CLS**: Video Classification, **V-QA**: (Video) Visual Question Answering, **V-RET**: Video Retrieval, **V-MRET**: Video Moment Retrieval \n
|
| 60 |
Models are ranked based on **Video-Overall**"""
|
| 61 |
+
TABLE_INTRODUCTION_A = """**A-CLS**: Audio Classification, **A-RET**: Audio Retrieval \n
|
| 62 |
+
Models are ranked based on **Audio-Overall**"""
|
| 63 |
TABLE_INTRODUCTION_D = """⚠️ Please re-evaluate your models if you see a 0 on ViDoSeek-page-fixed or MMLongBench-page-fixed datasets. \n
|
| 64 |
**VisDoc**: Visual Document Understanding \n
|
| 65 |
Models are ranked based on **Visdoc-Overall**"""
|
| 66 |
+
TABLE_INTRODUCTION_AG = """**Tool**: Tool Retrieval, **GUI**: GUI Control, **Memory**: Agent Memory Retrieval \n
|
| 67 |
+
Models are ranked based on **Agent-Overall**"""
|
| 68 |
|
| 69 |
LEADERBOARD_INFO = """
|
| 70 |
## Dataset Summary
|
| 71 |
"""
|
| 72 |
|
| 73 |
+
CITATION_BUTTON_TEXT_V2 = r"""@misc{meng2025vlm2vecv2advancingmultimodalembedding,
|
| 74 |
title={VLM2Vec-V2: Advancing Multimodal Embedding for Videos, Images, and Visual Documents},
|
| 75 |
author={Rui Meng and Ziyan Jiang and Ye Liu and Mingyi Su and Xinyi Yang and Yuepeng Fu and Can Qin and Zeyuan Chen and Ran Xu and Caiming Xiong and Yingbo Zhou and Wenhu Chen and Semih Yavuz},
|
| 76 |
year={2025},
|
|
|
|
| 79 |
primaryClass={cs.CV},
|
| 80 |
url={https://arxiv.org/abs/2507.04590},
|
| 81 |
}"""
|
| 82 |
+
CITATION_BUTTON_TEXT_V3 = r"""@misc{huang2026mmebv3measuringperformancegaps,
|
| 83 |
+
title={MMEB-V3: Measuring the Performance Gaps of Omni-Modality Embedding Models},
|
| 84 |
+
author={Haohang Huang and Xuan Lu and Mingyi Su and Xuan Zhang and Ziyan Jiang and Ping Nie and Kai Zou and Tomas Pfister and Wenhu Chen and Wei Zhang and Xiaoyu Shen and Rui Meng},
|
| 85 |
+
year={2026},
|
| 86 |
+
eprint={2604.23321},
|
| 87 |
+
archivePrefix={arXiv},
|
| 88 |
+
primaryClass={cs.IR},
|
| 89 |
+
url={https://arxiv.org/abs/2604.23321},
|
| 90 |
+
}"""
|
| 91 |
|
| 92 |
def load_single_json(file_path):
|
| 93 |
with open(file_path, 'r') as file:
|
|
|
|
| 103 |
all_data.append(data)
|
| 104 |
return all_data
|
| 105 |
|
| 106 |
+
def load_scores(raw_scores={}):
|
| 107 |
"""This function loads the raw scores from the user provided scores summary and flattens them into a single dictionary."""
|
| 108 |
+
# temp fix, will figure out later ===========
|
| 109 |
+
if any(_ in raw_scores for _ in ['tool', 'gui', 'memory']):
|
| 110 |
+
raw_scores['agent'] = raw_scores.pop('tool', {}) | raw_scores.pop('gui', {}) | raw_scores.pop('memory', {})
|
| 111 |
+
# ===========================================
|
| 112 |
all_scores = {}
|
| 113 |
for modality, datasets_list in DATASETS.items(): # Ex.: ('image', {'I-CLS': [...], 'I-QA': [...]})
|
| 114 |
for sub_task, datasets in datasets_list.items(): # Ex.: ('I-CLS', ['VOC2007', 'N24News', ...])
|
|
|
|
| 136 |
|
| 137 |
# Calculate overall score for all datasets
|
| 138 |
avg_scores['Overall'] = get_avg(sum(all_scores.values()), len(ALL_DATASETS))
|
| 139 |
+
v2_scores = {k:v for k,v in all_scores.items() if k in ALL_DATASETS_SPLITS['image'] or k in ALL_DATASETS_SPLITS['video'] or k in ALL_DATASETS_SPLITS['visdoc']}
|
| 140 |
+
avg_scores['Overall-V2'] = get_avg(sum(v2_scores.values()), len(v2_scores))
|
| 141 |
|
| 142 |
# Calculate scores for each modality
|
| 143 |
for modality in MODALITIES:
|
|
|
|
| 172 |
def print_time(time: str|None):
|
| 173 |
try:
|
| 174 |
dt = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S.%f")
|
| 175 |
+
return dt.strftime("%y-%m-%d")
|
| 176 |
except (ValueError, TypeError):
|
| 177 |
return 'unknown'
|
| 178 |
|
| 179 |
+
medal_map = {
|
| 180 |
+
"1": "🏆",
|
| 181 |
+
"2": "🥈",
|
| 182 |
+
"3": "🥉"
|
| 183 |
+
}
|
| 184 |
def rank_models(df, column='Overall', rank_name='Rank'):
|
| 185 |
"""Ranks the models based on the specific score."""
|
| 186 |
df = df.sort_values(by=column, ascending=False).reset_index(drop=True)
|
| 187 |
+
df[rank_name] = df[column].rank(method='min', ascending=False).astype(int).astype(str).map(lambda x: medal_map.get(x, x))
|
| 188 |
return df
|
| 189 |
|
| 190 |
+
def get_df(rank_column='Overall'):
|
| 191 |
"""Generates a DataFrame from the loaded data."""
|
| 192 |
all_data = load_data()
|
| 193 |
rows = [generate_model_row(data) for data in all_data]
|
|
|
|
| 195 |
df['Model Size(B)'] = df['Model Size(B)'].apply(process_model_size)
|
| 196 |
df['Date'] = df['Date'].apply(print_time)
|
| 197 |
df = create_hyperlinked_names(df)
|
| 198 |
+
df = rank_models(df, column=rank_column)
|
| 199 |
return df
|
| 200 |
|
| 201 |
def refresh_data():
|