{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!rm -rf ./deps\n!cp -r /kaggle/input/csefest2022dlsprintdeps ./deps\n!cp -r /kaggle/input/ekush-lib ./deps","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:17:28.282658Z","iopub.execute_input":"2023-10-15T23:17:28.283037Z","iopub.status.idle":"2023-10-15T23:17:36.616063Z","shell.execute_reply.started":"2023-10-15T23:17:28.283008Z","shell.execute_reply":"2023-10-15T23:17:36.614727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install ./deps/pygtrie-2.5.0/pygtrie-2.5.0\n!pip install ./deps/exceptiongroup-1.0.0rc8-py3-none-any.whl\n!pip install ./deps/hypothesis-6.54.4-py3-none-any.whl\n!pip install ./deps/pyctcdecode-0.5.0-py2.py3-none-any.whl\n!pip install ./deps/pypi-kenlm-0.1.20220713/pypi-kenlm-0.1.20220713\n!pip install ./deps/bnunicodenormalizer-0.0.23/bnunicodenormalizer-0.0.23\n!pip install ./deps/python-Levenshtein-0.12.2/python-Levenshtein-0.12.2\n!pip install ./deps/jiwer-2.3.0-py3-none-any.whl\n!pip install --no-index --find-link ./deps ./deps/deepfilternet-0.5.6-py3-none-any.whl\n!pip install --no-deps --no-index --find-link ./deps ./deps/ekush-lib/ekush\n\n!chmod +x ./deps/kenlm/kenlm/bin/lmplz","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:17:36.618792Z","iopub.execute_input":"2023-10-15T23:17:36.619579Z","iopub.status.idle":"2023-10-15T23:23:15.142148Z","shell.execute_reply.started":"2023-10-15T23:17:36.619542Z","shell.execute_reply":"2023-10-15T23:23:15.140839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from typing import Optional, Any, Union, Dict, List, Tuple\n\nimport os\n\nimport re\nimport json\nimport glob\nimport joblib\nfrom tqdm.notebook import tqdm\n\nimport numpy as np\nimport pandas as pd\n\nimport torch\nimport torchaudio\nimport torchaudio.functional as F\nimport torchaudio.transforms as T\nfrom torch.utils.data import Dataset, DataLoader, IterableDataset\n\nfrom transformers import (\n    AutomaticSpeechRecognitionPipeline,\n    Wav2Vec2ForCTC,\n    Wav2Vec2CTCTokenizer,\n    Wav2Vec2FeatureExtractor,\n    Wav2Vec2Processor,\n)\n\nfrom transformers.pipelines.pt_utils import KeyDataset\n\nimport df\n\nfrom bnunicodenormalizer import Normalizer \nfrom datasets import load_metric\n\nimport ekush\n\nbnorm = Normalizer()\nwer = load_metric(\"../input/csefest2022dlsprintdeps/metrics/metrics/wer.py\")\ncer = load_metric(\"../input/csefest2022dlsprintdeps/metrics/metrics/cer.py\")\n\ntorchaudio.set_audio_backend(\"soundfile\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-10-15T23:23:15.143932Z","iopub.execute_input":"2023-10-15T23:23:15.145280Z","iopub.status.idle":"2023-10-15T23:23:30.316344Z","shell.execute_reply.started":"2023-10-15T23:23:15.145208Z","shell.execute_reply":"2023-10-15T23:23:30.315325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Config","metadata":{}},{"cell_type":"code","source":"base_model_path = '/kaggle/input/wav2vec2-mix-363'\nckpt_path = base_model_path\n\nvocab_path = os.path.join(base_model_path, \"vocab.json\")\nsym2id, id2sym = ekush.asr.decoder.load_output_symbols(vocab_path)\nsilence_tokens = { v: None for k, v in sym2id.items() if k.lower() in [\"\", \"<pad>\", \"<sil>\", \"</s>\"] }\n\nlm_cfg = [\n    ekush.asr.decoder.LMConfig(\n        lm_path = \"/kaggle/input/ekush-language-models/arpa/bn.5gram.bin\",\n        unigrams_path = \"/kaggle/input/ekush-language-models/arpa/unigrams.txt\",\n        alpha = 0.40,\n        beta = 2.00,\n        unk_log_prob_offset = -10.0,\n        eos_token = \"</s>\",\n        score_boundary = True,\n        weight = 1.0,\n    ),\n]\n\ndenoiser_model_path = None\n# denoiser_model_path = \"/kaggle/input/speech-denoising-models/DeepFilterNet3\"\n\nendpointer_cfg = ekush.asr.decoder.EndpointerConfig(\n    rules = [\n        ekush.asr.decoder.EndpointerRule(\n            min_silence_log_prob=-0.5, min_utt_length_frames=50,\n            min_trailing_silence_frames=25, must_contain_non_silence=True,\n        ),\n        ekush.asr.decoder.EndpointerRule(\n            min_silence_log_prob=-1, min_utt_length_frames=50,\n            min_trailing_silence_frames=50, must_contain_non_silence=True\n        ),\n        ekush.asr.decoder.EndpointerRule(\n            min_silence_log_prob=-1, min_utt_length_frames=500,\n            min_trailing_silence_frames=25, must_contain_non_silence=True\n        ),\n        ekush.asr.decoder.EndpointerRule(\n            min_silence_log_prob=-3, min_utt_length_frames=1500,\n            min_trailing_silence_frames=10, must_contain_non_silence=False\n        ),\n    ]\n)\n\ndecoder_cfg = ekush.asr.decoder.DecoderConfig(\n    output_symbols = id2sym,\n    silence_tokens = silence_tokens,\n    ms_per_frame = 20,\n    n_best = 5,\n    beam_width = 300,\n    beam_prune_log_prob = -10,\n    beam_min_avg_log_prob = -20.0,\n    token_min_log_prob = -7.0,\n    endpointer = endpointer_cfg,\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:23:30.318923Z","iopub.execute_input":"2023-10-15T23:23:30.319670Z","iopub.status.idle":"2023-10-15T23:23:30.336817Z","shell.execute_reply.started":"2023-10-15T23:23:30.319636Z","shell.execute_reply":"2023-10-15T23:23:30.335815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Loading models","metadata":{}},{"cell_type":"code","source":"# Acooustic model.\nam_tokenizer = Wav2Vec2CTCTokenizer.from_pretrained(base_model_path)\n\nam_feature_extractor = Wav2Vec2FeatureExtractor(\n    feature_size=1,\n    sampling_rate=16000,\n    padding_value=0.0,\n    padding_side=\"right\",\n    do_normalize=False,  # Audio is pre-normalized before chunking\n    return_attention_mask=True,\n    processor_class=\"Wav2Vec2Processor\"\n)\n\nam = Wav2Vec2ForCTC.from_pretrained(base_model_path)\nif torch.cuda.is_available():\n    am.cuda()\nam.eval()","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:23:30.338035Z","iopub.execute_input":"2023-10-15T23:23:30.339293Z","iopub.status.idle":"2023-10-15T23:23:49.236123Z","shell.execute_reply.started":"2023-10-15T23:23:30.339238Z","shell.execute_reply":"2023-10-15T23:23:49.235152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Language model.\nlm = ekush.asr.decoder.load_language_models(lm_cfg)","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:23:49.237846Z","iopub.execute_input":"2023-10-15T23:23:49.238573Z","iopub.status.idle":"2023-10-15T23:25:34.781332Z","shell.execute_reply.started":"2023-10-15T23:23:49.238537Z","shell.execute_reply":"2023-10-15T23:25:34.780250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Speech denoising model.\ndenoiser = None\ndf_state = None\nif denoiser_model_path is not None:\n    denoiser, df_state, _ = df.init_df(model_base_dir=denoiser_model_path, log_file=None)","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:34.782901Z","iopub.execute_input":"2023-10-15T23:25:34.783990Z","iopub.status.idle":"2023-10-15T23:25:34.790111Z","shell.execute_reply.started":"2023-10-15T23:25:34.783950Z","shell.execute_reply":"2023-10-15T23:25:34.788987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Beam Search Decoder.\ndecoder = ekush.asr.lib.decoder.BeamSearchDecoder(decoder_cfg, lm)","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:34.791529Z","iopub.execute_input":"2023-10-15T23:25:34.792682Z","iopub.status.idle":"2023-10-15T23:25:34.802966Z","shell.execute_reply.started":"2023-10-15T23:25:34.792648Z","shell.execute_reply":"2023-10-15T23:25:34.801795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Utility Classes and Functions","metadata":{}},{"cell_type":"code","source":"def normalize_text(text: str) -> str:\n    _words = [ bnorm(word)['normalized']  for word in text.split() ]\n    text = \" \".join([word for word in _words if word is not None]) \n    text = text.replace(\"\\u2047\", \"-\")\n    return text\n\nclass AudioDataset(Dataset):\n        \n    def __init__(\n        self,\n        audio_dir: str,\n        sample_rate: float = 16000,\n        apply_mean_std_norm: bool = False,\n        denoiser: Optional[torch.nn.Module] = None,\n        df_state: Optional[object] = None,\n        speed_factor: float = 1.0,\n    ):\n        self.audio_dir = audio_dir\n        self.audio_files = sorted(glob.glob(os.path.join(self.audio_dir, \"*\")))\n        self.output_sample_rate = sample_rate\n        self.apply_mean_std_norm = apply_mean_std_norm\n\n        self.denoiser = denoiser\n        self.df_state = df_state\n        self.denoiser_sample_rate = df_state.sr() if df_state is not None else None\n        \n        self.speed_factor = speed_factor if 0 < speed_factor <= 1.0  else 1.0\n        \n        sample_rate = self.denoiser_sample_rate if self.denoiser_sample_rate is not None else self.output_sample_rate\n        self.audio_processor = ekush.asr.lib.audio.AudioProcessor(sample_rate)\n\n    def __len__(self):\n        return len(self.audio_files)\n\n    def __getitem__(self, idx): \n        audio_path = self.audio_files[idx]\n        name, _ = os.path.splitext(os.path.basename(audio_path))\n        \n        # Load audio as downmixed mono waveform.\n        wav = self.audio_processor.load_audio(audio_path, downmix_to_mono=True)\n        \n        # Denoise if denoising model provided.\n        if self.denoiser is not None:\n            wav = df.enhance(self.denoiser, self.df_state, wav)\n            if self.denoiser_sample_rate != self.output_sample_rate:\n                wav = self.audio_processor.resample(wav, self.denoiser_sample_rate, self.output_sample_rate)\n        \n        # Adding speed perturbation.\n        if self.speed_factor != 1:\n            wav, _ = torchaudio.functional.speed(wav, orig_freq=self.output_sample_rate, factor=self.speed_factor)\n        \n        if self.apply_mean_std_norm:\n            std, mean = torch.std_mean(wav, dim=-1, keepdim=True)\n            wav = torch.divide(wav - mean, std + 1e-7)\n        \n        return   {'name': name, 'raw': wav.numpy()[0], 'sampling_rate': self.output_sample_rate}\n\n\nclass Speech2LogitsPipeline(AutomaticSpeechRecognitionPipeline):\n\n    def __init__(\n        self,\n        model,\n        feature_extractor: Union[\"SequenceFeatureExtractor\", str] = None,\n        tokenizer = None,\n        decoder: Optional[Union[\"BeamSearchDecoderCTC\", str]] = None,\n        chunk_length_s: float = 15,\n        stride_length_s: float = 5,\n        framework: Optional[str] = None,\n        task: str = \"\",\n        args_parser = None,\n        device: Union[int, \"torch.device\"] = None,\n        torch_dtype: Optional[Union[str, \"torch.dtype\"]] = None,\n        binary_output: bool = False,\n        **kwargs,\n    ):\n        super().__init__(\n            model=model,\n            feature_extractor=feature_extractor,\n            tokenizer=tokenizer,\n            decoder=decoder,\n            chunk_length_s=chunk_length_s,\n            stride_length_s=stride_length_s,\n            framework=framework,\n            task=task,\n            args_parser=args_parser,\n            device=device,\n            torch_dtype=torch_dtype,\n            binary_output=binary_output,\n        )\n\n    def rescale_stride(self, stride, ratio):\n        \"\"\"\n        Rescales the stride values from audio space to tokens/logits space.\n\n        (160_000, 16_000, 16_000) -> (2000, 200, 200) for instance.\n        \"\"\"\n        # Shape is [B, SEQ] for tokens\n        # [B, SEQ, V] for logits\n\n        new_strides = []\n        for input_n, left, right in stride:\n            token_n = int(round(input_n * ratio))\n            left = int(round(left / input_n * token_n))\n            right = int(round(right / input_n * token_n))\n            new_stride = (token_n, left, right)\n            new_strides.append(new_stride)\n\n        return new_strides\n\n    def chunk_iter(self, inputs, feature_extractor, chunk_len, stride_left, stride_right, rescale=True, dtype=None):\n        inputs_len = inputs.shape[0]\n        step = chunk_len - stride_left - stride_right\n\n        for chunk_start_idx in range(0, inputs_len, step):\n            chunk_end_idx = chunk_start_idx + chunk_len\n            chunk = inputs[chunk_start_idx:chunk_end_idx]\n            processed = feature_extractor(chunk, sampling_rate=feature_extractor.sampling_rate, return_tensors=\"pt\")\n            if dtype is not None:\n                processed = processed.to(dtype=dtype)\n            _stride_left = 0 if chunk_start_idx == 0 else stride_left\n\n            # all right strides must be full, otherwise it is the last item\n            is_last = chunk_end_idx > inputs_len if stride_right > 0 else chunk_end_idx >= inputs_len\n            _stride_right = 0 if is_last else stride_right\n\n            chunk_len = chunk.shape[0]\n            stride = (chunk_len, _stride_left, _stride_right)\n            if \"input_features\" in processed:\n                processed_len = processed[\"input_features\"].shape[-1]\n            elif \"input_values\" in processed:\n                processed_len = processed[\"input_values\"].shape[-1]\n\n            if processed_len != chunk.shape[-1] and rescale:\n                ratio = processed_len / chunk_len\n                stride = rescale_stride([stride], ratio)[0]\n            \n            if chunk.shape[0] > _stride_left:\n                yield {\"is_last\": is_last, \"stride\": stride, **processed}\n            \n            if is_last:\n                break\n\n    def preprocess(self, inputs, chunk_length_s=0, stride_length_s=None):\n\n        if not isinstance(inputs, dict):\n            raise ValueError(\"inputs provided must be a dictionary\")\n\n            \n        # Accepting `\"array\"` which is the key defined in `datasets` for\n        # better integration\n        if not (\"sampling_rate\" in inputs and (\"raw\" in inputs or \"array\" in inputs)):\n            raise ValueError(\n                \"When passing a dictionary to Speech2LogitsPipeline, the dict needs to contain a \"\n                '\"raw\" key containing the numpy array representing the audio and a \"sampling_rate\" key, '\n                \"containing the sampling_rate associated with that array\"\n            )\n\n        stride = inputs.pop(\"stride\", None)\n        inputs = inputs.pop(\"raw\")\n        extra = inputs\n\n        ratio = 1\n        if stride is not None:\n            if stride[0] + stride[1] > inputs.shape[0]:\n                raise ValueError(\"Stride is too large for input\")\n\n            # Stride needs to get the chunk length here, it's going to get\n            # swallowed by the `feature_extractor` later, and then batching\n            # can add extra data in the inputs, so we need to keep track\n            # of the original length in the stride so we can cut properly.\n            stride = (inputs.shape[0], int(round(stride[0] * ratio)), int(round(stride[1] * ratio)))\n\n        if not isinstance(inputs, np.ndarray):\n            raise ValueError(f\"We expect a numpy ndarray as input, got `{type(inputs)}`\")\n\n        if len(inputs.shape) != 1:\n            raise ValueError(\"We expect a single channel audio input for Speech2LogitsPipeline\")\n\n        if chunk_length_s:\n            if stride_length_s is None:\n                stride_length_s = chunk_length_s / 6\n\n            if isinstance(stride_length_s, (int, float)):\n                stride_length_s = [stride_length_s, stride_length_s]\n\n            # XXX: Carefuly, this variable will not exist in `seq2seq` setting.\n            # Currently chunking is not possible at this level for `seq2seq` so\n            # it's ok.\n            align_to = getattr(self.model.config, \"inputs_to_logits_ratio\", 1)\n            chunk_len = int(round(chunk_length_s * self.feature_extractor.sampling_rate / align_to) * align_to)\n            stride_left = int(round(stride_length_s[0] * self.feature_extractor.sampling_rate / align_to) * align_to)\n            stride_right = int(round(stride_length_s[1] * self.feature_extractor.sampling_rate / align_to) * align_to)\n\n            if chunk_len < stride_left + stride_right:\n                raise ValueError(\"Chunk length must be superior to stride length\")\n\n            rescale = self.type != \"seq2seq_whisper\"\n            # make sure that\n            for item in self.chunk_iter(\n                inputs, self.feature_extractor, chunk_len, stride_left, stride_right, rescale, self.torch_dtype\n            ):\n                yield item\n        else:\n            processed = self.feature_extractor(\n                inputs, sampling_rate=self.feature_extractor.sampling_rate, return_tensors=\"pt\"\n            )\n\n            if self.torch_dtype is not None:\n                processed = processed.to(dtype=self.torch_dtype)\n\n            if stride is not None:\n                if self.type == \"seq2seq\":\n                    raise ValueError(\"Stride is only usable with CTC models, try removing it !\")\n\n                processed[\"stride\"] = stride\n\n            yield {\"is_last\": True, **processed, **extra}\n\n    def _forward(self, model_inputs):\n        attention_mask = model_inputs.pop(\"attention_mask\", None)\n        stride = model_inputs.pop(\"stride\", None)\n        is_last = model_inputs.pop(\"is_last\")\n        input_values = model_inputs.pop(\"input_values\")\n        outputs = self.model(input_values=input_values, attention_mask=attention_mask)\n\n        out = {\"logits\": outputs.logits}\n\n        if stride is not None:\n            # Send stride to `postprocess`.\n            # it needs to be handled there where\n            # the pieces are to be concatenated.\n            ratio = 1 / self.model.config.inputs_to_logits_ratio\n            if isinstance(stride, tuple):\n                out[\"stride\"] = self.rescale_stride([stride], ratio)[0]\n            else:\n                out[\"stride\"] = self.rescale_stride(stride, ratio)\n\n        # Leftover\n        extra = model_inputs\n\n        return {\"is_last\": is_last, **out, **extra}\n\n    def postprocess(\n        self,\n        model_outputs,\n        decoder_kwargs: Optional[Dict] = None,\n        return_timestamps=None,\n        return_language=None,\n    ):\n        all_logits = []\n        all_names = []\n\n        for outputs in model_outputs:\n            logits = outputs[\"logits\"]\n            stride = outputs.get(\"stride\", None)\n\n            if stride is not None:\n                total_n, left, right = stride\n                # Total_n might be < logits.shape[1]\n                # because of padding, that's why\n                # we need to reconstruct this information\n                # This won't work with left padding (which doesn't exist right now)\n                right_n = total_n - right\n                logits = logits[:, left:right_n]\n\n            all_logits.append(logits)\n#             all_names.append(name)\n        \n        logits = torch.concat(all_logits, dim=1).squeeze(0)\n        # name = torch.concat(all_names, dim=0)\n\n        return {\"logits\": logits}","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:34.804944Z","iopub.execute_input":"2023-10-15T23:25:34.805694Z","iopub.status.idle":"2023-10-15T23:25:34.840131Z","shell.execute_reply.started":"2023-10-15T23:25:34.805654Z","shell.execute_reply":"2023-10-15T23:25:34.838947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Decoding Audio","metadata":{}},{"cell_type":"code","source":"# Creating dataset.\ntest_dataset = AudioDataset(\n    audio_dir='/kaggle/input/bengaliai-speech/test_mp3s',\n    sample_rate=16000,\n    apply_mean_std_norm=True,\n    denoiser=denoiser,\n    df_state=df_state,\n    speed_factor=1.0,\n)\n\n# Creating pipeline.\npipeline = Speech2LogitsPipeline(\n    model=am,\n    feature_extractor=am_feature_extractor,\n    tokenizer=None,\n    chunk_length_s=15,\n    stride_length_s=5,\n    device=0,\n)\n\n# Getting logits.\noutputs = pipeline(test_dataset, batch_size=16)\n\nall_logits = []\nfor y in tqdm(outputs):\n    all_logits.append(y[\"logits\"].detach())","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:34.844107Z","iopub.execute_input":"2023-10-15T23:25:34.845085Z","iopub.status.idle":"2023-10-15T23:25:39.995580Z","shell.execute_reply.started":"2023-10-15T23:25:34.845048Z","shell.execute_reply":"2023-10-15T23:25:39.994589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Decoding logits.\nresults = decoder.decode_batch(all_logits, is_prob_frames=False, num_jobs=os.cpu_count())\n\n# Gathering text.\nall_text = []\n\nfor result in results:\n    text = []\n\n    for nbest_list in result:\n        if len(nbest_list) == 0:\n            continue\n        \n        all_emtpy = True\n        for utt in nbest_list:\n            t = utt.text.strip()\n            if t == \"\":\n                continue\n                \n            all_empty = False\n            break\n\n        if all_empty:\n            continue\n        \n        # Normalizing unicode.\n        t = normalize_text(t)\n        if not t.endswith(\"।\"):\n            t += \"।\"\n        \n        text.append(t)\n    \n    # Combining utterances. Setting \"।\" if empty string to get around error.\n    text = \" \".join(text)\n    text = text.strip()\n    if len(text) == 0:\n        text = \"।\"\n    \n    all_text.append(text)","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:39.997099Z","iopub.execute_input":"2023-10-15T23:25:39.997684Z","iopub.status.idle":"2023-10-15T23:25:56.956300Z","shell.execute_reply.started":"2023-10-15T23:25:39.997651Z","shell.execute_reply":"2023-10-15T23:25:56.955004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_paths = [ os.path.splitext(os.path.basename(p))[0] for p in test_dataset.audio_files ]\n\nsubmission_df = pd.DataFrame({'id': base_paths ,'sentence': all_text})\nsubmission_df.to_csv('submission.csv',index=None)","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:56.958279Z","iopub.execute_input":"2023-10-15T23:25:56.958629Z","iopub.status.idle":"2023-10-15T23:25:56.978355Z","shell.execute_reply.started":"2023-10-15T23:25:56.958603Z","shell.execute_reply":"2023-10-15T23:25:56.977152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -r /kaggle/working/deps","metadata":{"execution":{"iopub.status.busy":"2023-10-15T23:25:56.980098Z","iopub.execute_input":"2023-10-15T23:25:56.980823Z","iopub.status.idle":"2023-10-15T23:25:58.157608Z","shell.execute_reply.started":"2023-10-15T23:25:56.980789Z","shell.execute_reply":"2023-10-15T23:25:58.156300Z"},"trusted":true},"execution_count":null,"outputs":[]}]}