openhands openhands commited on
Commit
800e404
·
1 Parent(s): b1f3e49

Add company logos to graphs and tables, label frontier points with model names

Browse files

- Created SVG logo files for major AI companies (Anthropic, OpenAI, Google, Meta, Mistral, DeepSeek, xAI, Cohere, Alibaba, Moonshot)
- Added company logo mapping based on model name patterns
- Added Company logo column to both main leaderboard and benchmark tables
- Added company logo images on scatter plots at each data point
- Added model name labels to Pareto frontier points on graphs
- Updated column widths to accommodate new Company column

Co-authored-by: openhands <openhands@all-hands.dev>

assets/logo-alibaba.svg ADDED
assets/logo-anthropic.svg ADDED
assets/logo-cohere.svg ADDED
assets/logo-deepseek.svg ADDED
assets/logo-google.svg ADDED
assets/logo-meta.svg ADDED
assets/logo-mistral.svg ADDED
assets/logo-moonshot.svg ADDED
assets/logo-openai.svg ADDED
assets/logo-unknown.svg ADDED
assets/logo-xai.svg ADDED
leaderboard_transformer.py CHANGED
@@ -5,11 +5,61 @@ import logging
5
  from typing import Optional
6
  import base64
7
  import html
 
8
 
9
  import aliases
10
 
11
  logger = logging.getLogger(__name__)
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  INFORMAL_TO_FORMAL_NAME_MAP = {
14
  # Short Names
15
  "lit": "Literature Understanding",
@@ -423,6 +473,7 @@ def _plot_scatter_plotly(
423
  return fig
424
 
425
  # --- Section 4: Calculate and Draw Pareto Frontier ---
 
426
  if x_col_to_use and y_col_to_use:
427
  sorted_data = data_plot.sort_values(by=[x_col_to_use, y_col_to_use], ascending=[True, False])
428
  frontier_points = []
@@ -432,6 +483,7 @@ def _plot_scatter_plotly(
432
  score = row[y_col_to_use]
433
  if score >= max_score_so_far:
434
  frontier_points.append({'x': row[x_col_to_use], 'y': score})
 
435
  max_score_so_far = score
436
 
437
  if frontier_points:
@@ -496,7 +548,10 @@ def _plot_scatter_plotly(
496
  # Use consistent shape for all points (no tooling distinction)
497
  data_plot['shape_symbol'] = default_shape
498
 
499
- # --- Section 6: Plot Markers by "Openness" Category ---
 
 
 
500
  for category in category_order:
501
  group = data_plot[data_plot['Openness'] == category]
502
  if group.empty:
@@ -518,6 +573,73 @@ def _plot_scatter_plotly(
518
  line=dict(width=1, color='deeppink')
519
  )
520
  ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
 
522
  # --- Section 8: Configure Layout ---
523
  xaxis_config = dict(title=x_axis_label, rangemode="tozero")
@@ -535,10 +657,11 @@ def _plot_scatter_plotly(
535
  xaxis_config['range'] = [-0.2, (max_reported_cost + (max_reported_cost / 4))]
536
 
537
 
538
- fig.update_layout(
 
539
  template="plotly_white",
540
  title=f"OpenHands Index {name} Leaderboard",
541
- xaxis=xaxis_config, # Use the updated config
542
  yaxis=dict(title="Average (mean) score", range=[-0.2, None]),
543
  legend=dict(
544
  bgcolor='#FAF2E9',
@@ -551,6 +674,12 @@ def _plot_scatter_plotly(
551
  font_color="#d3dedc",
552
  ),
553
  )
 
 
 
 
 
 
554
 
555
  return fig
556
 
 
5
  from typing import Optional
6
  import base64
7
  import html
8
+ import os
9
 
10
  import aliases
11
 
12
  logger = logging.getLogger(__name__)
13
 
14
+ # Company logo mapping for graphs - maps model name patterns to company logo files
15
+ COMPANY_LOGO_MAP = {
16
+ "anthropic": {"path": "assets/logo-anthropic.svg", "name": "Anthropic"},
17
+ "claude": {"path": "assets/logo-anthropic.svg", "name": "Anthropic"},
18
+ "openai": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
19
+ "gpt": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
20
+ "o1": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
21
+ "o3": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
22
+ "google": {"path": "assets/logo-google.svg", "name": "Google"},
23
+ "gemini": {"path": "assets/logo-google.svg", "name": "Google"},
24
+ "gemma": {"path": "assets/logo-google.svg", "name": "Google"},
25
+ "meta": {"path": "assets/logo-meta.svg", "name": "Meta"},
26
+ "llama": {"path": "assets/logo-meta.svg", "name": "Meta"},
27
+ "mistral": {"path": "assets/logo-mistral.svg", "name": "Mistral"},
28
+ "mixtral": {"path": "assets/logo-mistral.svg", "name": "Mistral"},
29
+ "codestral": {"path": "assets/logo-mistral.svg", "name": "Mistral"},
30
+ "deepseek": {"path": "assets/logo-deepseek.svg", "name": "DeepSeek"},
31
+ "xai": {"path": "assets/logo-xai.svg", "name": "xAI"},
32
+ "grok": {"path": "assets/logo-xai.svg", "name": "xAI"},
33
+ "cohere": {"path": "assets/logo-cohere.svg", "name": "Cohere"},
34
+ "command": {"path": "assets/logo-cohere.svg", "name": "Cohere"},
35
+ "qwen": {"path": "assets/logo-alibaba.svg", "name": "Alibaba"},
36
+ "alibaba": {"path": "assets/logo-alibaba.svg", "name": "Alibaba"},
37
+ "kimi": {"path": "assets/logo-moonshot.svg", "name": "Moonshot"},
38
+ "moonshot": {"path": "assets/logo-moonshot.svg", "name": "Moonshot"},
39
+ }
40
+
41
+
42
+ def get_company_from_model_name(model_name: str) -> dict:
43
+ """
44
+ Gets the company info (logo path and name) from a model name.
45
+ Returns default unknown logo if no match found.
46
+ """
47
+ if not model_name:
48
+ return {"path": "assets/logo-unknown.svg", "name": "Unknown"}
49
+
50
+ # Handle list of models - use the first one
51
+ if isinstance(model_name, list):
52
+ model_name = model_name[0] if model_name else ""
53
+
54
+ model_lower = str(model_name).lower()
55
+
56
+ # Check each pattern
57
+ for pattern, company_info in COMPANY_LOGO_MAP.items():
58
+ if pattern in model_lower:
59
+ return company_info
60
+
61
+ return {"path": "assets/logo-unknown.svg", "name": "Unknown"}
62
+
63
  INFORMAL_TO_FORMAL_NAME_MAP = {
64
  # Short Names
65
  "lit": "Literature Understanding",
 
473
  return fig
474
 
475
  # --- Section 4: Calculate and Draw Pareto Frontier ---
476
+ frontier_rows = [] # Store entire rows for frontier points to access model names
477
  if x_col_to_use and y_col_to_use:
478
  sorted_data = data_plot.sort_values(by=[x_col_to_use, y_col_to_use], ascending=[True, False])
479
  frontier_points = []
 
483
  score = row[y_col_to_use]
484
  if score >= max_score_so_far:
485
  frontier_points.append({'x': row[x_col_to_use], 'y': score})
486
+ frontier_rows.append(row)
487
  max_score_so_far = score
488
 
489
  if frontier_points:
 
548
  # Use consistent shape for all points (no tooling distinction)
549
  data_plot['shape_symbol'] = default_shape
550
 
551
+ # --- Section 6: Plot Markers by "Openness" Category with Company Logos ---
552
+ # Collect layout images for company logos
553
+ layout_images = []
554
+
555
  for category in category_order:
556
  group = data_plot[data_plot['Openness'] == category]
557
  if group.empty:
 
573
  line=dict(width=1, color='deeppink')
574
  )
575
  ))
576
+
577
+ # Add company logo images for each point in this group
578
+ for _, row in group.iterrows():
579
+ model_name = row.get('Language Model', '')
580
+ company_info = get_company_from_model_name(model_name)
581
+ logo_path = company_info['path']
582
+
583
+ # Read the SVG file and encode as base64 data URI
584
+ if os.path.exists(logo_path):
585
+ try:
586
+ with open(logo_path, 'rb') as f:
587
+ encoded_logo = base64.b64encode(f.read()).decode('utf-8')
588
+ logo_uri = f"data:image/svg+xml;base64,{encoded_logo}"
589
+
590
+ # Add image at data point position with small offset
591
+ layout_images.append(dict(
592
+ source=logo_uri,
593
+ xref="x",
594
+ yref="y",
595
+ x=row[x_col_to_use],
596
+ y=row[y_col_to_use],
597
+ sizex=max_reported_cost * 0.06 if max_reported_cost > 0 else 0.5, # Scale relative to data
598
+ sizey=3, # Fixed y size in data units
599
+ xanchor="center",
600
+ yanchor="bottom",
601
+ layer="above"
602
+ ))
603
+ except Exception as e:
604
+ logger.warning(f"Could not load logo {logo_path}: {e}")
605
+
606
+ # --- Section 7: Add Model Name Labels to Frontier Points ---
607
+ if frontier_rows:
608
+ frontier_x = []
609
+ frontier_y = []
610
+ frontier_labels = []
611
+
612
+ for row in frontier_rows:
613
+ frontier_x.append(row[x_col_to_use])
614
+ frontier_y.append(row[y_col_to_use])
615
+
616
+ # Get the model name for the label
617
+ model_name = row.get('Language Model', '')
618
+ if isinstance(model_name, list):
619
+ model_name = model_name[0] if model_name else ''
620
+ # Clean the model name (remove path prefixes)
621
+ model_name = str(model_name).split('/')[-1]
622
+ # Truncate long names
623
+ if len(model_name) > 25:
624
+ model_name = model_name[:22] + '...'
625
+ frontier_labels.append(model_name)
626
+
627
+ # Add text labels for frontier points
628
+ fig.add_trace(go.Scatter(
629
+ x=frontier_x,
630
+ y=frontier_y,
631
+ mode='text',
632
+ name='Frontier Labels',
633
+ showlegend=False,
634
+ text=frontier_labels,
635
+ textposition='top center',
636
+ textfont=dict(
637
+ size=10,
638
+ color='#032629',
639
+ family='Manrope'
640
+ ),
641
+ hoverinfo='skip'
642
+ ))
643
 
644
  # --- Section 8: Configure Layout ---
645
  xaxis_config = dict(title=x_axis_label, rangemode="tozero")
 
657
  xaxis_config['range'] = [-0.2, (max_reported_cost + (max_reported_cost / 4))]
658
 
659
 
660
+ # Build layout configuration
661
+ layout_config = dict(
662
  template="plotly_white",
663
  title=f"OpenHands Index {name} Leaderboard",
664
+ xaxis=xaxis_config,
665
  yaxis=dict(title="Average (mean) score", range=[-0.2, None]),
666
  legend=dict(
667
  bgcolor='#FAF2E9',
 
674
  font_color="#d3dedc",
675
  ),
676
  )
677
+
678
+ # Add company logo images to the layout if any were collected
679
+ if layout_images:
680
+ layout_config['images'] = layout_images
681
+
682
+ fig.update_layout(**layout_config)
683
 
684
  return fig
685
 
ui_components.py CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
3
  import plotly.graph_objects as go
4
  import os
5
  import base64
 
6
 
7
  from huggingface_hub import HfApi
8
 
@@ -36,6 +37,68 @@ from content import (
36
 
37
  api = HfApi()
38
  os.makedirs(EXTRACTED_DATA_DIR, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  # Simplified icon map (no tooling distinction, only openness)
40
  # Not actually used since we removed icons from the table, but keeping for potential future use
41
  OPENNESS_ICON_MAP = {
@@ -384,6 +447,9 @@ def create_leaderboard_display(
384
  return f'<img src="{uri}" alt="{openness_val}" title="{openness_val}" style="width:24px; height:24px;">'
385
 
386
  df_display['Icon'] = df_display.apply(get_openness_icon_html, axis=1)
 
 
 
387
 
388
  for col in df_display.columns:
389
  if "Cost" in col:
@@ -403,6 +469,9 @@ def create_leaderboard_display(
403
  )
404
 
405
  all_cols = df_display.columns.tolist()
 
 
 
406
  all_cols.insert(0, all_cols.pop(all_cols.index('Icon')))
407
  all_cols.insert(0, all_cols.pop(all_cols.index('Pareto')))
408
  df_display = df_display[all_cols]
@@ -413,6 +482,7 @@ def create_leaderboard_display(
413
  header_rename_map = {
414
  "Pareto": "",
415
  "Icon": "",
 
416
  }
417
  df_display = df_display.rename(columns=header_rename_map)
418
 
@@ -440,12 +510,13 @@ def create_leaderboard_display(
440
  for col in df_headers:
441
  if col == "Logs" or "Cost" in col or "Score" in col:
442
  df_datatypes.append("markdown")
443
- elif col in ["SDK Version","Language Model", ""]: # "" for renamed Pareto/Icon columns
444
  df_datatypes.append("html")
445
  else:
446
  df_datatypes.append("str")
447
  # Dynamically set widths for the DataFrame columns
448
- fixed_start_widths = [40, 40, 200, 100, 200]
 
449
  num_score_cost_cols = 0
450
  remaining_headers = df_headers[len(fixed_start_widths):]
451
  for col in remaining_headers:
@@ -599,6 +670,9 @@ def create_benchmark_details_display(
599
  return f'<img src="{uri}" alt="{openness_val}" title="{openness_val}" style="width:24px; height:24px;">'
600
 
601
  benchmark_table_df['Icon'] = benchmark_table_df.apply(get_openness_icon_html, axis=1)
 
 
 
602
 
603
  #Make pretty and format the Language Model column
604
  benchmark_table_df['Language Model'] = benchmark_table_df['Language Model'].apply(clean_llm_base_list)
@@ -633,6 +707,7 @@ def create_benchmark_details_display(
633
  desired_cols_in_order = [
634
  'Pareto',
635
  'Icon',
 
636
  'Language Model',
637
  'SDK Version',
638
  'Attempted Benchmark',
@@ -650,10 +725,11 @@ def create_benchmark_details_display(
650
  benchmark_score_col: 'Score',
651
  benchmark_cost_col: 'Cost',
652
  }, inplace=True)
653
- # Remove Pareto and Icon column headers (rename to empty string)
654
  header_rename_map = {
655
  "Pareto": "",
656
  "Icon": "",
 
657
  }
658
  benchmark_table_df = benchmark_table_df.rename(columns=header_rename_map)
659
 
@@ -663,7 +739,7 @@ def create_benchmark_details_display(
663
  for col in df_headers:
664
  if "Logs" in col or "Cost" in col or "Score" in col:
665
  df_datatypes.append("markdown")
666
- elif col in ["SDK Version", "Language Model", ""]: # "" for renamed Pareto/Icon columns
667
  df_datatypes.append("html")
668
  else:
669
  df_datatypes.append("str")
@@ -689,7 +765,7 @@ def create_benchmark_details_display(
689
  datatype=df_datatypes,
690
  interactive=False,
691
  wrap=True,
692
- column_widths=[40, 40, 200, 150, 175, 85, 100, 100, 80, 40],
693
  show_search="search",
694
  elem_classes=["wrap-header-df"]
695
  )
 
3
  import plotly.graph_objects as go
4
  import os
5
  import base64
6
+ import re
7
 
8
  from huggingface_hub import HfApi
9
 
 
37
 
38
  api = HfApi()
39
  os.makedirs(EXTRACTED_DATA_DIR, exist_ok=True)
40
+
41
+ # Company logo mapping - maps model name patterns to company logo files
42
+ COMPANY_LOGO_MAP = {
43
+ "anthropic": {"path": "assets/logo-anthropic.svg", "name": "Anthropic"},
44
+ "claude": {"path": "assets/logo-anthropic.svg", "name": "Anthropic"},
45
+ "openai": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
46
+ "gpt": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
47
+ "o1": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
48
+ "o3": {"path": "assets/logo-openai.svg", "name": "OpenAI"},
49
+ "google": {"path": "assets/logo-google.svg", "name": "Google"},
50
+ "gemini": {"path": "assets/logo-google.svg", "name": "Google"},
51
+ "gemma": {"path": "assets/logo-google.svg", "name": "Google"},
52
+ "meta": {"path": "assets/logo-meta.svg", "name": "Meta"},
53
+ "llama": {"path": "assets/logo-meta.svg", "name": "Meta"},
54
+ "mistral": {"path": "assets/logo-mistral.svg", "name": "Mistral"},
55
+ "mixtral": {"path": "assets/logo-mistral.svg", "name": "Mistral"},
56
+ "codestral": {"path": "assets/logo-mistral.svg", "name": "Mistral"},
57
+ "deepseek": {"path": "assets/logo-deepseek.svg", "name": "DeepSeek"},
58
+ "xai": {"path": "assets/logo-xai.svg", "name": "xAI"},
59
+ "grok": {"path": "assets/logo-xai.svg", "name": "xAI"},
60
+ "cohere": {"path": "assets/logo-cohere.svg", "name": "Cohere"},
61
+ "command": {"path": "assets/logo-cohere.svg", "name": "Cohere"},
62
+ "qwen": {"path": "assets/logo-alibaba.svg", "name": "Alibaba"},
63
+ "alibaba": {"path": "assets/logo-alibaba.svg", "name": "Alibaba"},
64
+ "kimi": {"path": "assets/logo-moonshot.svg", "name": "Moonshot"},
65
+ "moonshot": {"path": "assets/logo-moonshot.svg", "name": "Moonshot"},
66
+ }
67
+
68
+
69
+ def get_company_from_model(model_name: str) -> dict:
70
+ """
71
+ Gets the company info (logo path and name) from a model name.
72
+ Returns default unknown logo if no match found.
73
+ """
74
+ if not model_name:
75
+ return {"path": "assets/logo-unknown.svg", "name": "Unknown"}
76
+
77
+ # Handle list of models - use the first one
78
+ if isinstance(model_name, list):
79
+ model_name = model_name[0] if model_name else ""
80
+
81
+ model_lower = str(model_name).lower()
82
+
83
+ # Check each pattern
84
+ for pattern, company_info in COMPANY_LOGO_MAP.items():
85
+ if pattern in model_lower:
86
+ return company_info
87
+
88
+ return {"path": "assets/logo-unknown.svg", "name": "Unknown"}
89
+
90
+
91
+ def get_company_logo_html(model_name: str) -> str:
92
+ """
93
+ Generates HTML for a company logo based on the model name.
94
+ """
95
+ company_info = get_company_from_model(model_name)
96
+ uri = get_svg_as_data_uri(company_info["path"])
97
+ if uri:
98
+ return f'<img src="{uri}" alt="{company_info["name"]}" title="{company_info["name"]}" style="width:20px; height:20px; vertical-align: middle;">'
99
+ return ""
100
+
101
+
102
  # Simplified icon map (no tooling distinction, only openness)
103
  # Not actually used since we removed icons from the table, but keeping for potential future use
104
  OPENNESS_ICON_MAP = {
 
447
  return f'<img src="{uri}" alt="{openness_val}" title="{openness_val}" style="width:24px; height:24px;">'
448
 
449
  df_display['Icon'] = df_display.apply(get_openness_icon_html, axis=1)
450
+
451
+ # Add company logo column based on the Language Model
452
+ df_display['Company'] = df_display['Language Model'].apply(get_company_logo_html)
453
 
454
  for col in df_display.columns:
455
  if "Cost" in col:
 
469
  )
470
 
471
  all_cols = df_display.columns.tolist()
472
+ # Move Company logo column after Icon
473
+ if 'Company' in all_cols:
474
+ all_cols.insert(0, all_cols.pop(all_cols.index('Company')))
475
  all_cols.insert(0, all_cols.pop(all_cols.index('Icon')))
476
  all_cols.insert(0, all_cols.pop(all_cols.index('Pareto')))
477
  df_display = df_display[all_cols]
 
482
  header_rename_map = {
483
  "Pareto": "",
484
  "Icon": "",
485
+ "Company": "",
486
  }
487
  df_display = df_display.rename(columns=header_rename_map)
488
 
 
510
  for col in df_headers:
511
  if col == "Logs" or "Cost" in col or "Score" in col:
512
  df_datatypes.append("markdown")
513
+ elif col in ["SDK Version","Language Model", ""]: # "" for renamed Pareto/Icon/Company columns
514
  df_datatypes.append("html")
515
  else:
516
  df_datatypes.append("str")
517
  # Dynamically set widths for the DataFrame columns
518
+ # Order: Pareto, Icon, Company, Language Model, SDK Version, ...
519
+ fixed_start_widths = [40, 40, 40, 200, 100, 200]
520
  num_score_cost_cols = 0
521
  remaining_headers = df_headers[len(fixed_start_widths):]
522
  for col in remaining_headers:
 
670
  return f'<img src="{uri}" alt="{openness_val}" title="{openness_val}" style="width:24px; height:24px;">'
671
 
672
  benchmark_table_df['Icon'] = benchmark_table_df.apply(get_openness_icon_html, axis=1)
673
+
674
+ # Add company logo column based on the Language Model
675
+ benchmark_table_df['Company'] = benchmark_table_df['Language Model'].apply(get_company_logo_html)
676
 
677
  #Make pretty and format the Language Model column
678
  benchmark_table_df['Language Model'] = benchmark_table_df['Language Model'].apply(clean_llm_base_list)
 
707
  desired_cols_in_order = [
708
  'Pareto',
709
  'Icon',
710
+ 'Company',
711
  'Language Model',
712
  'SDK Version',
713
  'Attempted Benchmark',
 
725
  benchmark_score_col: 'Score',
726
  benchmark_cost_col: 'Cost',
727
  }, inplace=True)
728
+ # Remove Pareto, Icon, and Company column headers (rename to empty string)
729
  header_rename_map = {
730
  "Pareto": "",
731
  "Icon": "",
732
+ "Company": "",
733
  }
734
  benchmark_table_df = benchmark_table_df.rename(columns=header_rename_map)
735
 
 
739
  for col in df_headers:
740
  if "Logs" in col or "Cost" in col or "Score" in col:
741
  df_datatypes.append("markdown")
742
+ elif col in ["SDK Version", "Language Model", ""]: # "" for renamed Pareto/Icon/Company columns
743
  df_datatypes.append("html")
744
  else:
745
  df_datatypes.append("str")
 
765
  datatype=df_datatypes,
766
  interactive=False,
767
  wrap=True,
768
+ column_widths=[40, 40, 40, 200, 150, 175, 85, 100, 100, 80, 40],
769
  show_search="search",
770
  elem_classes=["wrap-header-df"]
771
  )