ror HF Staff commited on
Commit
18f5759
·
1 Parent(s): c03347d

Rework of model page

Browse files
Files changed (3) hide show
  1. model_page.py +48 -62
  2. styles.css +2 -1
  3. utils.py +1 -1
model_page.py CHANGED
@@ -38,60 +38,6 @@ MODEL_TITLE_Y = 1
38
  MAX_FAILURE_ITEMS = 10
39
 
40
 
41
- def _process_failure_category(failures_obj: dict, category: str, info_lines: list) -> None:
42
- """Process a single failure category (multi or single) and add to info_lines."""
43
- if category in failures_obj and failures_obj[category]:
44
- info_lines.append(generate_underlined_line(f"{category.title()} GPU failure details:"))
45
- if isinstance(failures_obj[category], list):
46
- # Handle list of failures (could be strings or dicts)
47
- for i, failure in enumerate(failures_obj[category][:MAX_FAILURE_ITEMS]):
48
- if isinstance(failure, dict):
49
- # Extract meaningful info from dict (e.g., test name, line, etc.)
50
- failure_str = failure.get('line', failure.get('test',
51
- failure.get('name', str(failure))))
52
- info_lines.append(f" {i+1}. {failure_str}")
53
- else:
54
- info_lines.append(f" {i+1}. {str(failure)}")
55
- if len(failures_obj[category]) > MAX_FAILURE_ITEMS:
56
- remaining = len(failures_obj[category]) - MAX_FAILURE_ITEMS
57
- info_lines.append(f"... and {remaining} more")
58
- else:
59
- info_lines.append(str(failures_obj[category]))
60
- info_lines.append("")
61
-
62
-
63
- def extract_failure_info(failures_obj, device: str, multi_count: int, single_count: int) -> str:
64
- """Extract failure information from failures object."""
65
- if (not failures_obj or pd.isna(failures_obj)) and multi_count == 0 and single_count == 0:
66
- return f"No failures on {device}"
67
-
68
- info_lines = []
69
-
70
- # Add counts summary
71
- if multi_count > 0 or single_count > 0:
72
- info_lines.append(generate_underlined_line(f"Failure Summary for {device}:"))
73
- if multi_count > 0:
74
- info_lines.append(f"Multi GPU failures: {multi_count}")
75
- if single_count > 0:
76
- info_lines.append(f"Single GPU failures: {single_count}")
77
- info_lines.append("")
78
-
79
- # Try to extract detailed failure information
80
- try:
81
- if isinstance(failures_obj, dict):
82
- _process_failure_category(failures_obj, 'multi', info_lines)
83
- _process_failure_category(failures_obj, 'single', info_lines)
84
-
85
- return "\n".join(info_lines) if info_lines else f"No detailed failure info for {device}"
86
-
87
- except Exception as e:
88
- if multi_count > 0 or single_count > 0:
89
- error_msg = (f"Failures detected on {device} (Multi: {multi_count}, Single: {single_count})\n"
90
- f"Details unavailable: {str(e)}")
91
- return error_msg
92
- return f"Error processing failure info for {device}: {str(e)}"
93
-
94
-
95
  def _create_pie_chart(ax: plt.Axes, device_label: str, filtered_stats: dict) -> None:
96
  """Create a pie chart for device statistics."""
97
  if not filtered_stats:
@@ -111,7 +57,7 @@ def _create_pie_chart(ax: plt.Axes, device_label: str, filtered_stats: dict) ->
111
  filtered_stats.values(),
112
  labels=[label.lower() for label in filtered_stats.keys()], # Lowercase for minimal look
113
  colors=chart_colors,
114
- autopct=lambda pct: f'{int(pct/100*sum(filtered_stats.values()))}',
115
  startangle=PIE_START_ANGLE,
116
  explode=None, # No separation
117
  shadow=False,
@@ -146,22 +92,23 @@ def plot_model_stats(df: pd.DataFrame, model_name: str) -> tuple[plt.Figure, str
146
  # Create empty stats for both devices
147
  amd_filtered = {}
148
  nvidia_filtered = {}
149
- failed_multi_amd = failed_single_amd = failed_multi_nvidia = failed_single_nvidia = 0
150
  failures_amd = failures_nvidia = {}
151
  else:
152
  row = df.loc[model_name]
153
 
154
  # Extract and process model data
155
- amd_stats, nvidia_stats, failed_multi_amd, failed_single_amd, failed_multi_nvidia, failed_single_nvidia = \
156
- extract_model_data(row)
157
 
158
  # Filter out categories with 0 values for cleaner visualization
159
  amd_filtered = {k: v for k, v in amd_stats.items() if v > 0}
160
  nvidia_filtered = {k: v for k, v in nvidia_stats.items() if v > 0}
161
 
162
  # Generate failure info directly from dataframe
163
- failures_amd = row.get('failures_amd', {})
164
- failures_nvidia = row.get('failures_nvidia', {})
 
 
 
165
 
166
  # Always create figure with two subplots side by side with padding
167
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(FIGURE_WIDTH_DUAL, FIGURE_HEIGHT_DUAL), facecolor=BLACK)
@@ -186,7 +133,46 @@ def plot_model_stats(df: pd.DataFrame, model_name: str) -> tuple[plt.Figure, str
186
  plt.tight_layout()
187
  plt.subplots_adjust(top=SUBPLOT_TOP, wspace=SUBPLOT_WSPACE)
188
 
189
- amd_failed_info = extract_failure_info(failures_amd, 'AMD', failed_multi_amd, failed_single_amd)
190
- nvidia_failed_info = extract_failure_info(failures_nvidia, 'NVIDIA', failed_multi_nvidia, failed_single_nvidia)
191
 
192
  return fig, amd_failed_info, nvidia_failed_info
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  MAX_FAILURE_ITEMS = 10
39
 
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  def _create_pie_chart(ax: plt.Axes, device_label: str, filtered_stats: dict) -> None:
42
  """Create a pie chart for device statistics."""
43
  if not filtered_stats:
 
57
  filtered_stats.values(),
58
  labels=[label.lower() for label in filtered_stats.keys()], # Lowercase for minimal look
59
  colors=chart_colors,
60
+ autopct=lambda pct: f'{int(pct * sum(filtered_stats.values()) / 100)}',
61
  startangle=PIE_START_ANGLE,
62
  explode=None, # No separation
63
  shadow=False,
 
92
  # Create empty stats for both devices
93
  amd_filtered = {}
94
  nvidia_filtered = {}
 
95
  failures_amd = failures_nvidia = {}
96
  else:
97
  row = df.loc[model_name]
98
 
99
  # Extract and process model data
100
+ amd_stats, nvidia_stats = extract_model_data(row)[:2]
 
101
 
102
  # Filter out categories with 0 values for cleaner visualization
103
  amd_filtered = {k: v for k, v in amd_stats.items() if v > 0}
104
  nvidia_filtered = {k: v for k, v in nvidia_stats.items() if v > 0}
105
 
106
  # Generate failure info directly from dataframe
107
+ failures_amd = dict(row.get('failures_amd', {}))
108
+ failures_nvidia = dict(row.get('failures_nvidia', {}))
109
+
110
+ # failure_xxx = {"single": [test, ...], "multi": [...]}
111
+ # test = {"line": test_name. "trace": error_msg}
112
 
113
  # Always create figure with two subplots side by side with padding
114
  fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(FIGURE_WIDTH_DUAL, FIGURE_HEIGHT_DUAL), facecolor=BLACK)
 
133
  plt.tight_layout()
134
  plt.subplots_adjust(top=SUBPLOT_TOP, wspace=SUBPLOT_WSPACE)
135
 
136
+ amd_failed_info = prepare_textbox_content(failures_amd, 'AMD', bool(amd_filtered))
137
+ nvidia_failed_info = prepare_textbox_content(failures_nvidia, 'NVIDIA', bool(nvidia_filtered))
138
 
139
  return fig, amd_failed_info, nvidia_failed_info
140
+
141
+
142
+ def prepare_textbox_content(failures: dict[str, list], device: str, data_available: bool) -> str:
143
+ """Extract failure information from failures object."""
144
+ # Catch the case where there is no data
145
+ if not data_available:
146
+ return generate_underlined_line(f"No data for {device}")
147
+ # Catch the case where there are no failures
148
+ if not failures:
149
+ return generate_underlined_line(f"No failures for {device}")
150
+
151
+ # Summary of failures
152
+ single_failures = failures.get("single", [])
153
+ multi_failures = failures.get("multi", [])
154
+ info_lines = [
155
+ generate_underlined_line(f"Failure summary for {device}:"),
156
+ f"Single GPU failures: {len(single_failures)}",
157
+ f"Multi GPU failures: {len(multi_failures)}",
158
+ ""
159
+ ]
160
+
161
+ # Add single-gpu failures
162
+ if single_failures:
163
+ info_lines.append(generate_underlined_line("Single GPU failures:"))
164
+ for test in single_failures:
165
+ name = test.get("line", "::*could not find name*")
166
+ name = name.split("::")[-1]
167
+ info_lines.append(name)
168
+ info_lines.append("\n")
169
+
170
+ # Add multi-gpu failures
171
+ if multi_failures:
172
+ info_lines.append(generate_underlined_line("Multi GPU failures:"))
173
+ for test in multi_failures:
174
+ name = test.get("line", "::*could not find name*")
175
+ name = name.split("::")[-1]
176
+ info_lines.append(name)
177
+
178
+ return "\n".join(info_lines)
styles.css CHANGED
@@ -539,8 +539,9 @@ h1, h2, h3, p, .markdown {
539
  resize: none !important;
540
  scrollbar-width: thin !important;
541
  scrollbar-color: #333333 #000000 !important;
542
- scroll-behavior: auto;
543
  transition: opacity 0.5s ease-in-out !important;
 
544
  }
545
 
546
  /* WebKit scrollbar styling for failed tests */
 
539
  resize: none !important;
540
  scrollbar-width: thin !important;
541
  scrollbar-color: #333333 #000000 !important;
542
+ scroll-behavior: auto !important;
543
  transition: opacity 0.5s ease-in-out !important;
544
+ scroll-padding-top: 0 !important;
545
  }
546
 
547
  /* WebKit scrollbar styling for failed tests */
utils.py CHANGED
@@ -48,4 +48,4 @@ logger = setup_logger()
48
 
49
 
50
  def generate_underlined_line(text: str) -> str:
51
- return text + "\n" + "─" * len(text) + "\n"
 
48
 
49
 
50
  def generate_underlined_line(text: str) -> str:
51
+ return text + "\n" + "─" * len(text)