code: def model_failures(self) -> List[Dict]:
      # Obtain per-model failures
      def per_model_sum(model_category_dict):
          return dicts_to_sum(model_category_dict["failed"].values())
  
      failures = {}
      non_model_failures = {
          k: per_model_sum(v)
          for k, v in self.model_results.items()
          if sum(per_model_sum(v).values())
      }
  
      for k, v in self.model_results.items():
          if k in NON_MODEL_TEST_MODULES:
              pass
  
          if sum(per_model_sum(v).values()):
              dict_failed = dict(v["failed"])
              pytorch_specific_failures = dict_failed.pop("PyTorch")
              tensorflow_specific_failures = dict_failed.pop(
                  "TensorFlow"
              )
              other_failures = dicts_to_sum(dict_failed.values())
  
              failures[k] = {
                  "PyTorch": pytorch_specific_failures,
                  "TensorFlow": tensorflow_specific_failures,
                  "other": other_failures,
              }
  
      model_reports = []
      other_module_reports = []
  
      for key, value in non_model_failures.items():
          if key in NON_MODEL_TEST_MODULES:
              device_report = self.get_device_report(value)
  
              if sum(value.values()):
                  if device_report:
                      report = f"{device_report}{key}"
                  else:
                      report = key
  
                  other_module_reports.append(report)
  
      for key, value in failures.items():
          device_report_values = [
              value["PyTorch"]["single"],
              value["PyTorch"]["multi"],
              value["TensorFlow"]["single"],
              value["TensorFlow"]["multi"],
              sum(value["other"].values()),
          ]
  
          if sum(device_report_values):
              device_report = (
                  " | ".join(
                      [str(x).rjust(9) for x in device_report_values]
                  )
                  + " | "
              )
              report = f"{device_report}{key}"
  
              model_reports.append(report)
  
      # (Possibly truncated) reports for the current workflow run - to be sent to Slack channels
      model_header = "Single PT |  Multi PT | Single TF |  Multi TF |     Other | Category\n"
      sorted_model_reports = sorted(
          model_reports, key=lambda s: s.split("| ")[-1]
      )
      model_failures_report = prepare_reports(
          title="These following model modules had failures",
          header=model_header,
          reports=sorted_model_reports,
      )
  
      module_header = "Single |  Multi | Category\n"
      sorted_module_reports = sorted(
          other_module_reports, key=lambda s: s.split("| ")[-1]
      )
      module_failures_report = prepare_reports(
          title="The following non-model modules had failures",
          header=module_header,
          reports=sorted_module_reports,
      )
  
      # To be sent to Slack channels
      model_failure_sections = [
          {
              "type": "section",
              "text": {"type": "mrkdwn", "text": model_failures_report},
          },
          {
              "type": "section",
              "text": {
                  "type": "mrkdwn",
                  "text": module_failures_report,
              },
          },
      ]
  
      # Save the complete (i.e. no truncation) failure tables (of the current workflow run)
      # (to be uploaded as artifacts)
  
      model_failures_report = prepare_reports(
          title="These following model modules had failures",
          header=model_header,
          reports=sorted_model_reports,
          to_truncate=False,
      )
      file_path = os.path.join(
          os.getcwd(), "prev_ci_results/model_failures_report.txt"
      )
      with open(file_path, "w", encoding="UTF-8") as fp:
          fp.write(model_failures_report)
  
      module_failures_report = prepare_reports(
          title="The following non-model modules had failures",
          header=module_header,
          reports=sorted_module_reports,
          to_truncate=False,
      )
      file_path = os.path.join(
          os.getcwd(), "prev_ci_results/module_failures_report.txt"
      )
      with open(file_path, "w", encoding="UTF-8") as fp:
          fp.write(module_failures_report)
  
      if self.prev_ci_artifacts is not None:
          # if the last run produces artifact named `prev_ci_results`
          if (
              "prev_ci_results" in self.prev_ci_artifacts
              and "model_failures_report.txt"
              in self.prev_ci_artifacts["prev_ci_results"]
          ):
              # Compute the difference of the previous/current (model failure) table
              prev_model_failures = self.prev_ci_artifacts[
                  "prev_ci_results"
              ]["model_failures_report.txt"]
              entries_changed = self.compute_diff_for_failure_reports(
                  model_failures_report, prev_model_failures
              )
              if len(entries_changed) > 0:
                  # Save the complete difference
                  diff_report = prepare_reports(
                      title="Changed model modules failures",
                      header=model_header,
                      reports=entries_changed,
                      to_truncate=False,
                  )
                  file_path = os.path.join(
                      os.getcwd(),
                      "prev_ci_results/changed_model_failures_report.txt",
                  )
                  with open(file_path, "w", encoding="UTF-8") as fp:
                      fp.write(diff_report)
  
                  # To be sent to Slack channels
                  diff_report = prepare_reports(
                      title="*Changed model modules failures*",
                      header=model_header,
                      reports=entries_changed,
                  )
                  model_failure_sections.append(
                      {
                          "type": "section",
                          "text": {
                              "type": "mrkdwn",
                              "text": diff_report,
                          },
                      },
                  )
  
      return model_failure_sections
  
imports: import ast
  import collections
  import functools
  import json
  import operator
  import os
  import re
  import sys
  import time
  from typing import Dict, List, Optional, Union
  import requests
  from get_ci_error_statistics import get_job_links
  from get_previous_daily_ci import get_last_daily_ci_reports
  from slack_sdk import WebClient
label_desc: Use image node_id 11 for calling the Message obj's underlying member method code with example usage: obj.model_failures() and returns: model_failure_sections, dicts_to_sum