





'''simple docstring'''


import argparse
import json
from pathlib import Path

import torch
import torchaudio
from datasets import load_dataset
from huggingface_hub import hf_hub_download

from transformers import ASTConfig, ASTFeatureExtractor, ASTForAudioClassification
from transformers.utils import logging


logging.set_verbosity_info()
_SCREAMING_SNAKE_CASE									=				logging.get_logger(__name__)


def 						__a(SCREAMING_SNAKE_CASE_	:       Dict     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   ASTConfig()

    if "10-10" in model_name:
        pass
    elif "speech-commands" in model_name:
        _lowerCAmelCase						      =   128
    elif "12-12" in model_name:
        _lowerCAmelCase						      =   12
        _lowerCAmelCase						      =   12
    elif "14-14" in model_name:
        _lowerCAmelCase						      =   14
        _lowerCAmelCase						      =   14
    elif "16-16" in model_name:
        _lowerCAmelCase						      =   16
        _lowerCAmelCase						      =   16
    else:
        raise ValueError("Model not supported"     )

    _lowerCAmelCase						      =   "huggingface/label-files"
    if "speech-commands" in model_name:
        _lowerCAmelCase						      =   35
        _lowerCAmelCase						      =   "speech-commands-v2-id2label.json"
    else:
        _lowerCAmelCase						      =   527
        _lowerCAmelCase						      =   "audioset-id2label.json"

    _lowerCAmelCase						      =   json.load(open(hf_hub_download(SCREAMING_SNAKE_CASE_		,							SCREAMING_SNAKE_CASE_		,							repo_type="dataset"     )		,							"r"     )     )
    _lowerCAmelCase						      =   {int(SCREAMING_SNAKE_CASE_     ): v for k, v in idalabel.items()}
    _lowerCAmelCase						      =   idalabel
    _lowerCAmelCase						      =   {v: k for k, v in idalabel.items()}

    return config


def 						__a(SCREAMING_SNAKE_CASE_	:       str     ):



    '''simple docstring'''





    if "module.v" in name:
        _lowerCAmelCase						      =   name.replace("module.v"		,							"audio_spectrogram_transformer"     )
    if "cls_token" in name:
        _lowerCAmelCase						      =   name.replace("cls_token"		,							"embeddings.cls_token"     )
    if "dist_token" in name:
        _lowerCAmelCase						      =   name.replace("dist_token"		,							"embeddings.distillation_token"     )
    if "pos_embed" in name:
        _lowerCAmelCase						      =   name.replace("pos_embed"		,							"embeddings.position_embeddings"     )
    if "patch_embed.proj" in name:
        _lowerCAmelCase						      =   name.replace("patch_embed.proj"		,							"embeddings.patch_embeddings.projection"     )
    # transformer blocks
    if "blocks" in name:
        _lowerCAmelCase						      =   name.replace("blocks"		,							"encoder.layer"     )
    if "attn.proj" in name:
        _lowerCAmelCase						      =   name.replace("attn.proj"		,							"attention.output.dense"     )
    if "attn" in name:
        _lowerCAmelCase						      =   name.replace("attn"		,							"attention.self"     )
    if "norm1" in name:
        _lowerCAmelCase						      =   name.replace("norm1"		,							"layernorm_before"     )
    if "norm2" in name:
        _lowerCAmelCase						      =   name.replace("norm2"		,							"layernorm_after"     )
    if "mlp.fc1" in name:
        _lowerCAmelCase						      =   name.replace("mlp.fc1"		,							"intermediate.dense"     )
    if "mlp.fc2" in name:
        _lowerCAmelCase						      =   name.replace("mlp.fc2"		,							"output.dense"     )
    # final layernorm
    if "audio_spectrogram_transformer.norm" in name:
        _lowerCAmelCase						      =   name.replace("audio_spectrogram_transformer.norm"		,							"audio_spectrogram_transformer.layernorm"     )
    # classifier head
    if "module.mlp_head.0" in name:
        _lowerCAmelCase						      =   name.replace("module.mlp_head.0"		,							"classifier.layernorm"     )
    if "module.mlp_head.1" in name:
        _lowerCAmelCase						      =   name.replace("module.mlp_head.1"		,							"classifier.dense"     )

    return name


def 						__a(SCREAMING_SNAKE_CASE_	:       int		,							SCREAMING_SNAKE_CASE_	:       Any     ):



    '''simple docstring'''





    for key in orig_state_dict.copy().keys():
        _lowerCAmelCase						      =   orig_state_dict.pop(SCREAMING_SNAKE_CASE_     )

        if "qkv" in key:
            _lowerCAmelCase						      =   key.split("."     )
            _lowerCAmelCase						      =   int(key_split[3]     )
            _lowerCAmelCase						      =   config.hidden_size
            if "weight" in key:
                _lowerCAmelCase						      =   val[:dim, :]
                _lowerCAmelCase						      =   val[dim : dim * 2, :]
                _lowerCAmelCase						      =   val[-dim:, :]
            else:
                _lowerCAmelCase						      =   val[:dim]
                _lowerCAmelCase						      =   val[dim : dim * 2]
                _lowerCAmelCase						      =   val[-dim:]
        else:
            _lowerCAmelCase						      =   val

    return orig_state_dict


def 						__a(SCREAMING_SNAKE_CASE_	:       Any     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   [
        "module.v.head.weight",
        "module.v.head.bias",
        "module.v.head_dist.weight",
        "module.v.head_dist.bias",
    ]
    for k in ignore_keys:
        state_dict.pop(SCREAMING_SNAKE_CASE_		,							SCREAMING_SNAKE_CASE_     )


@torch.no_grad()
def 						__a(SCREAMING_SNAKE_CASE_	:       Any		,							SCREAMING_SNAKE_CASE_	:       List[Any]		,							SCREAMING_SNAKE_CASE_	:       Optional[int]=False     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   get_audio_spectrogram_transformer_config(SCREAMING_SNAKE_CASE_     )

    _lowerCAmelCase						      =   {
        "ast-finetuned-audioset-10-10-0.4593": (
            "https://www.dropbox.com/s/ca0b1v2nlxzyeb4/audioset_10_10_0.4593.pth?dl=1"
        ),
        "ast-finetuned-audioset-10-10-0.450": (
            "https://www.dropbox.com/s/1tv0hovue1bxupk/audioset_10_10_0.4495.pth?dl=1"
        ),
        "ast-finetuned-audioset-10-10-0.448": (
            "https://www.dropbox.com/s/6u5sikl4b9wo4u5/audioset_10_10_0.4483.pth?dl=1"
        ),
        "ast-finetuned-audioset-10-10-0.448-v2": (
            "https://www.dropbox.com/s/kt6i0v9fvfm1mbq/audioset_10_10_0.4475.pth?dl=1"
        ),
        "ast-finetuned-audioset-12-12-0.447": (
            "https://www.dropbox.com/s/snfhx3tizr4nuc8/audioset_12_12_0.4467.pth?dl=1"
        ),
        "ast-finetuned-audioset-14-14-0.443": (
            "https://www.dropbox.com/s/z18s6pemtnxm4k7/audioset_14_14_0.4431.pth?dl=1"
        ),
        "ast-finetuned-audioset-16-16-0.442": (
            "https://www.dropbox.com/s/mdsa4t1xmcimia6/audioset_16_16_0.4422.pth?dl=1"
        ),
        "ast-finetuned-speech-commands-v2": (
            "https://www.dropbox.com/s/q0tbqpwv44pquwy/speechcommands_10_10_0.9812.pth?dl=1"
        ),
    }

    # load original state_dict
    _lowerCAmelCase						      =   model_name_to_url[model_name]
    _lowerCAmelCase						      =   torch.hub.load_state_dict_from_url(SCREAMING_SNAKE_CASE_		,							map_location="cpu"     )
    # remove some keys
    remove_keys(SCREAMING_SNAKE_CASE_     )
    # rename some keys
    _lowerCAmelCase						      =   convert_state_dict(SCREAMING_SNAKE_CASE_		,							SCREAMING_SNAKE_CASE_     )

    # load 🤗 model
    _lowerCAmelCase						      =   ASTForAudioClassification(SCREAMING_SNAKE_CASE_     )
    model.eval()

    model.load_state_dict(SCREAMING_SNAKE_CASE_     )

    # verify outputs on dummy input
    # source: https://github.com/YuanGongND/ast/blob/79e873b8a54d0a3b330dd522584ff2b9926cd581/src/run.py#L62
    _lowerCAmelCase						      =   -4.267_7393 if "speech-commands" not in model_name else -6.84_5978
    _lowerCAmelCase						      =   4.568_9974 if "speech-commands" not in model_name else 5.565_4526
    _lowerCAmelCase						      =   1024 if "speech-commands" not in model_name else 128
    _lowerCAmelCase						      =   ASTFeatureExtractor(mean=SCREAMING_SNAKE_CASE_		,							std=SCREAMING_SNAKE_CASE_		,							max_length=SCREAMING_SNAKE_CASE_     )

    if "speech-commands" in model_name:
        _lowerCAmelCase						      =   load_dataset("speech_commands"		,							"v0.02"		,							split="validation"     )
        _lowerCAmelCase						      =   dataset[0]["audio"]["array"]
    else:
        _lowerCAmelCase						      =   hf_hub_download(
            repo_id="nielsr/audio-spectogram-transformer-checkpoint"		,							filename="sample_audio.flac"		,							repo_type="dataset"		,							)

        _lowerCAmelCase      ,      _lowerCAmelCase						      =   torchaudio.load(SCREAMING_SNAKE_CASE_     )
        _lowerCAmelCase						      =   waveform.squeeze().numpy()

    _lowerCAmelCase						      =   feature_extractor(SCREAMING_SNAKE_CASE_		,							sampling_rate=16000		,							return_tensors="pt"     )

    # forward pass
    _lowerCAmelCase						      =   model(**SCREAMING_SNAKE_CASE_     )
    _lowerCAmelCase						      =   outputs.logits

    if model_name == "ast-finetuned-audioset-10-10-0.4593":
        _lowerCAmelCase						      =   torch.tensor([-0.8760, -7.0042, -8.6602]     )
    elif model_name == "ast-finetuned-audioset-10-10-0.450":
        _lowerCAmelCase						      =   torch.tensor([-1.1986, -7.0903, -8.2718]     )
    elif model_name == "ast-finetuned-audioset-10-10-0.448":
        _lowerCAmelCase						      =   torch.tensor([-2.6128, -8.0080, -9.4344]     )
    elif model_name == "ast-finetuned-audioset-10-10-0.448-v2":
        _lowerCAmelCase						      =   torch.tensor([-1.5080, -7.4534, -8.8917]     )
    elif model_name == "ast-finetuned-audioset-12-12-0.447":
        _lowerCAmelCase						      =   torch.tensor([-0.5050, -6.5833, -8.0843]     )
    elif model_name == "ast-finetuned-audioset-14-14-0.443":
        _lowerCAmelCase						      =   torch.tensor([-0.3826, -7.0336, -8.2413]     )
    elif model_name == "ast-finetuned-audioset-16-16-0.442":
        _lowerCAmelCase						      =   torch.tensor([-1.2113, -6.9101, -8.3470]     )
    elif model_name == "ast-finetuned-speech-commands-v2":
        _lowerCAmelCase						      =   torch.tensor([6.1589, -8.0566, -8.7984]     )
    else:
        raise ValueError("Unknown model name"     )
    if not torch.allclose(logits[0, :3]		,							SCREAMING_SNAKE_CASE_		,							atol=1e-4     ):
        raise ValueError("Logits don't match"     )
    print("Looks ok!"     )

    if pytorch_dump_folder_path is not None:
        Path(SCREAMING_SNAKE_CASE_     ).mkdir(exist_ok=SCREAMING_SNAKE_CASE_     )
        print(F'''Saving model {model_name} to {pytorch_dump_folder_path}'''     )
        model.save_pretrained(SCREAMING_SNAKE_CASE_     )
        print(F'''Saving feature extractor to {pytorch_dump_folder_path}'''     )
        feature_extractor.save_pretrained(SCREAMING_SNAKE_CASE_     )

    if push_to_hub:
        print("Pushing model and feature extractor to the hub..."     )
        model.push_to_hub(F'''MIT/{model_name}'''     )
        feature_extractor.push_to_hub(F'''MIT/{model_name}'''     )


if __name__ == "__main__":
       _SCREAMING_SNAKE_CASE									=				argparse.ArgumentParser()
       # Required parameters
       parser.add_argument(
           "--model_name",
           default="ast-finetuned-audioset-10-10-0.4593",
           type=str,
           help="Name of the Audio Spectrogram Transformer model you'd like to convert.",
       )
       parser.add_argument(
           "--pytorch_dump_folder_path", default=None, type=str, help="Path to the output PyTorch model directory."
       )
       parser.add_argument(
           "--push_to_hub", action="store_true", help="Whether or not to push the converted model to the 🤗 hub."
       )

       _SCREAMING_SNAKE_CASE									=				parser.parse_args()
       convert_audio_spectrogram_transformer_checkpoint(args.model_name, args.pytorch_dump_folder_path, args.push_to_hub)









'''simple docstring'''


import argparse
import json
import math
import os
import time
import traceback
import zipfile
from collections import Counter

import requests


def 						__a(SCREAMING_SNAKE_CASE_	:       Any		,							SCREAMING_SNAKE_CASE_	:       Tuple=None     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   None
    if token is not None:
        _lowerCAmelCase						      =   {"Accept": "application/vnd.github+json", "Authorization": F'''Bearer {token}'''}

    _lowerCAmelCase						      =   F'''https://api.github.com/repos/huggingface/transformers/actions/runs/{workflow_run_id}/jobs?per_page=100'''
    _lowerCAmelCase						      =   requests.get(SCREAMING_SNAKE_CASE_		,							headers=SCREAMING_SNAKE_CASE_     ).json()
    _lowerCAmelCase						      =   {}

    try:
        job_links.update({job["name"]: job["html_url"] for job in result["jobs"]}     )
        _lowerCAmelCase						      =   math.ceil((result["total_count"] - 100) / 100     )

        for i in range(SCREAMING_SNAKE_CASE_     ):
            _lowerCAmelCase						      =   requests.get(url + F'''&page={i + 2}'''		,							headers=SCREAMING_SNAKE_CASE_     ).json()
            job_links.update({job["name"]: job["html_url"] for job in result["jobs"]}     )

        return job_links
    except Exception:
        print(F'''Unknown error, could not fetch links:\n{traceback.format_exc()}'''     )

    return {}


def 						__a(SCREAMING_SNAKE_CASE_	:       Optional[Any]		,							SCREAMING_SNAKE_CASE_	:       Dict=None     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   None
    if token is not None:
        _lowerCAmelCase						      =   {"Accept": "application/vnd.github+json", "Authorization": F'''Bearer {token}'''}

    _lowerCAmelCase						      =   F'''https://api.github.com/repos/huggingface/transformers/actions/runs/{worflow_run_id}/artifacts?per_page=100'''
    _lowerCAmelCase						      =   requests.get(SCREAMING_SNAKE_CASE_		,							headers=SCREAMING_SNAKE_CASE_     ).json()
    _lowerCAmelCase						      =   {}

    try:
        artifacts.update({artifact["name"]: artifact["archive_download_url"] for artifact in result["artifacts"]}     )
        _lowerCAmelCase						      =   math.ceil((result["total_count"] - 100) / 100     )

        for i in range(SCREAMING_SNAKE_CASE_     ):
            _lowerCAmelCase						      =   requests.get(url + F'''&page={i + 2}'''		,							headers=SCREAMING_SNAKE_CASE_     ).json()
            artifacts.update({artifact["name"]: artifact["archive_download_url"] for artifact in result["artifacts"]}     )

        return artifacts
    except Exception:
        print(F'''Unknown error, could not fetch links:\n{traceback.format_exc()}'''     )

    return {}


def 						__a(SCREAMING_SNAKE_CASE_	:       Any		,							SCREAMING_SNAKE_CASE_	:       List[str]		,							SCREAMING_SNAKE_CASE_	:       Any		,							SCREAMING_SNAKE_CASE_	:       Dict     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   None
    if token is not None:
        _lowerCAmelCase						      =   {"Accept": "application/vnd.github+json", "Authorization": F'''Bearer {token}'''}

    _lowerCAmelCase						      =   requests.get(SCREAMING_SNAKE_CASE_		,							headers=SCREAMING_SNAKE_CASE_		,							allow_redirects=SCREAMING_SNAKE_CASE_     )
    _lowerCAmelCase						      =   result.headers["Location"]
    _lowerCAmelCase						      =   requests.get(SCREAMING_SNAKE_CASE_		,							allow_redirects=SCREAMING_SNAKE_CASE_     )
    _lowerCAmelCase						      =   os.path.join(SCREAMING_SNAKE_CASE_		,							F'''{artifact_name}.zip'''     )
    with open(SCREAMING_SNAKE_CASE_		,							"wb"     ) as fp:
        fp.write(response.content     )


def 						__a(SCREAMING_SNAKE_CASE_	:       Optional[Any]		,							SCREAMING_SNAKE_CASE_	:       Optional[Any]=None     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   []
    _lowerCAmelCase						      =   []
    _lowerCAmelCase						      =   None

    with zipfile.ZipFile(SCREAMING_SNAKE_CASE_     ) as z:
        for filename in z.namelist():
            if not os.path.isdir(SCREAMING_SNAKE_CASE_     ):
                # read the file
                if filename in ["failures_line.txt", "summary_short.txt", "job_name.txt"]:
                    with z.open(SCREAMING_SNAKE_CASE_     ) as f:
                        for line in f:
                            _lowerCAmelCase						      =   line.decode("UTF-8"     ).strip()
                            if filename == "failures_line.txt":
                                try:
                                    # `error_line` is the place where `error` occurs
                                    _lowerCAmelCase						      =   line[: line.index(": "     )]
                                    _lowerCAmelCase						      =   line[line.index(": "     ) + len(": "     ) :]
                                    errors.append([error_line, error]     )
                                except Exception:
                                    # skip un-related lines
                                    pass
                            elif filename == "summary_short.txt" and line.startswith("FAILED "     ):
                                # `test` is the test method that failed
                                _lowerCAmelCase						      =   line[len("FAILED "     ) :]
                                failed_tests.append(SCREAMING_SNAKE_CASE_     )
                            elif filename == "job_name.txt":
                                _lowerCAmelCase						      =   line

    if len(SCREAMING_SNAKE_CASE_     ) != len(SCREAMING_SNAKE_CASE_     ):
        raise ValueError(
            F'''`errors` and `failed_tests` should have the same number of elements. Got {len(SCREAMING_SNAKE_CASE_     )} for `errors` '''
            F'''and {len(SCREAMING_SNAKE_CASE_     )} for `failed_tests` instead. The test reports in {artifact_zip_path} have some'''
            " problem."     )

    _lowerCAmelCase						      =   None
    if job_name and job_links:
        _lowerCAmelCase						      =   job_links.get(SCREAMING_SNAKE_CASE_		,							SCREAMING_SNAKE_CASE_     )

    # A list with elements of the form (line of error, error, failed test)
    _lowerCAmelCase						      =   [x + [y] + [job_link] for x, y in zip(SCREAMING_SNAKE_CASE_		,							SCREAMING_SNAKE_CASE_     )]

    return result


def 						__a(SCREAMING_SNAKE_CASE_	:       List[str]		,							SCREAMING_SNAKE_CASE_	:       Tuple=None     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   []

    _lowerCAmelCase						      =   [os.path.join(SCREAMING_SNAKE_CASE_		,							SCREAMING_SNAKE_CASE_     ) for p in os.listdir(SCREAMING_SNAKE_CASE_     ) if p.endswith(".zip"     )]
    for p in paths:
        errors.extend(get_errors_from_single_artifact(SCREAMING_SNAKE_CASE_		,							job_links=SCREAMING_SNAKE_CASE_     )     )

    return errors


def 						__a(SCREAMING_SNAKE_CASE_	:       List[str]		,							SCREAMING_SNAKE_CASE_	:       str=None     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   Counter()
    counter.update([x[1] for x in logs]     )
    _lowerCAmelCase						      =   counter.most_common()
    _lowerCAmelCase						      =   {}
    for error, count in counts:
        if error_filter is None or error not in error_filter:
            _lowerCAmelCase						      =   {"count": count, "failed_tests": [(x[2], x[0]) for x in logs if x[1] == error]}

    _lowerCAmelCase						      =   dict(sorted(r.items()		,							key=lambda SCREAMING_SNAKE_CASE_     : item[1]["count"]		,							reverse=SCREAMING_SNAKE_CASE_     )     )
    return r


def 						__a(SCREAMING_SNAKE_CASE_	:       List[str]     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   test.split("::"     )[0]
    if test.startswith("tests/models/"     ):
        _lowerCAmelCase						      =   test.split("/"     )[2]
    else:
        _lowerCAmelCase						      =   None

    return test


def 						__a(SCREAMING_SNAKE_CASE_	:       Optional[Any]		,							SCREAMING_SNAKE_CASE_	:       Tuple=None     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   [(x[0], x[1], get_model(x[2]     )) for x in logs]
    _lowerCAmelCase						      =   [x for x in logs if x[2] is not None]
    _lowerCAmelCase						      =   {x[2] for x in logs}

    _lowerCAmelCase						      =   {}
    for test in tests:
        _lowerCAmelCase						      =   Counter()
        # count by errors in `test`
        counter.update([x[1] for x in logs if x[2] == test]     )
        _lowerCAmelCase						      =   counter.most_common()
        _lowerCAmelCase						      =   {error: count for error, count in counts if (error_filter is None or error not in error_filter)}
        _lowerCAmelCase						      =   sum(error_counts.values()     )
        if n_errors > 0:
            _lowerCAmelCase						      =   {"count": n_errors, "errors": error_counts}

    _lowerCAmelCase						      =   dict(sorted(r.items()		,							key=lambda SCREAMING_SNAKE_CASE_     : item[1]["count"]		,							reverse=SCREAMING_SNAKE_CASE_     )     )
    return r


def 						__a(SCREAMING_SNAKE_CASE_	:       Optional[int]     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   "| no. | error | status |"
    _lowerCAmelCase						      =   "|-:|:-|:-|"
    _lowerCAmelCase						      =   [header, sep]
    for error in reduced_by_error:
        _lowerCAmelCase						      =   reduced_by_error[error]["count"]
        _lowerCAmelCase						      =   F'''| {count} | {error[:100]} |  |'''
        lines.append(SCREAMING_SNAKE_CASE_     )

    return "\n".join(SCREAMING_SNAKE_CASE_     )


def 						__a(SCREAMING_SNAKE_CASE_	:       Optional[int]     ):



    '''simple docstring'''





    _lowerCAmelCase						      =   "| model | no. of errors | major error | count |"
    _lowerCAmelCase						      =   "|-:|-:|-:|-:|"
    _lowerCAmelCase						      =   [header, sep]
    for model in reduced_by_model:
        _lowerCAmelCase						      =   reduced_by_model[model]["count"]
        _lowerCAmelCase      ,      _lowerCAmelCase						      =   list(reduced_by_model[model]["errors"].items()     )[0]
        _lowerCAmelCase						      =   F'''| {model} | {count} | {error[:60]} | {_count} |'''
        lines.append(SCREAMING_SNAKE_CASE_     )

    return "\n".join(SCREAMING_SNAKE_CASE_     )


if __name__ == "__main__":
       _SCREAMING_SNAKE_CASE									=				argparse.ArgumentParser()
       # Required parameters
       parser.add_argument("--workflow_run_id", type=str, required=True, help="A GitHub Actions workflow run id.")
       parser.add_argument(
           "--output_dir",
           type=str,
           required=True,
           help="Where to store the downloaded artifacts and other result files.",
       )
       parser.add_argument("--token", default=None, type=str, help="A token that has actions:read permission.")
       _SCREAMING_SNAKE_CASE									=				parser.parse_args()

       os.makedirs(args.output_dir, exist_ok=True)

       _SCREAMING_SNAKE_CASE									=				get_job_links(args.workflow_run_id, token=args.token)
       _SCREAMING_SNAKE_CASE									=				{}
       # To deal with `workflow_call` event, where a job name is the combination of the job names in the caller and callee.
       # For example, `PyTorch 1.11 / Model tests (models/albert, single-gpu)`.
       if _job_links:
              for k, v in _job_links.items():
                     # This is how GitHub actions combine job names.
                     if " / " in k:
                            _SCREAMING_SNAKE_CASE									=				k.find(" / ")
                            _SCREAMING_SNAKE_CASE									=				k[index + len(" / ") :]
                     _SCREAMING_SNAKE_CASE									=				v
       with open(os.path.join(args.output_dir, "job_links.json"), "w", encoding="UTF-8") as fp:
              json.dump(job_links, fp, ensure_ascii=False, indent=4)

       _SCREAMING_SNAKE_CASE									=				get_artifacts_links(args.workflow_run_id, token=args.token)
       with open(os.path.join(args.output_dir, "artifacts.json"), "w", encoding="UTF-8") as fp:
              json.dump(artifacts, fp, ensure_ascii=False, indent=4)

       for idx, (name, url) in enumerate(artifacts.items()):
              download_artifact(name, url, args.output_dir, args.token)
              # Be gentle to GitHub
              time.sleep(1)

       _SCREAMING_SNAKE_CASE									=				get_all_errors(args.output_dir, job_links=job_links)

       # `e[1]` is the error
       _SCREAMING_SNAKE_CASE									=				Counter()
       counter.update([e[1] for e in errors])

       # print the top 30 most common test errors
       _SCREAMING_SNAKE_CASE									=				counter.most_common(30)
       for item in most_common:
              print(item)

       with open(os.path.join(args.output_dir, "errors.json"), "w", encoding="UTF-8") as fp:
              json.dump(errors, fp, ensure_ascii=False, indent=4)

       _SCREAMING_SNAKE_CASE									=				reduce_by_error(errors)
       _SCREAMING_SNAKE_CASE									=				reduce_by_model(errors)

       _SCREAMING_SNAKE_CASE									=				make_github_table(reduced_by_error)
       _SCREAMING_SNAKE_CASE									=				make_github_table_per_model(reduced_by_model)

       with open(os.path.join(args.output_dir, "reduced_by_error.txt"), "w", encoding="UTF-8") as fp:
              fp.write(sa)
       with open(os.path.join(args.output_dir, "reduced_by_model.txt"), "w", encoding="UTF-8") as fp:
              fp.write(sa)


