




import json
import os
import shutil
import tempfile
import unittest
from multiprocessing import get_context
from pathlib import Path

import datasets
import numpy as np
from datasets import load_dataset
from parameterized import parameterized

from transformers import AutoProcessor
from transformers.models.wavaveca import WavaVecaCTCTokenizer, WavaVecaFeatureExtractor
from transformers.models.wavaveca.tokenization_wavaveca import VOCAB_FILES_NAMES
from transformers.testing_utils import require_pyctcdecode, require_torch, require_torchaudio, slow
from transformers.utils import FEATURE_EXTRACTOR_NAME, is_pyctcdecode_available, is_torch_available

from ..wavaveca.test_feature_extraction_wavaveca import floats_list


if is_pyctcdecode_available():
   from huggingface_hub import snapshot_download
   from pyctcdecode import BeamSearchDecoderCTC

   from transformers.models.wavaveca_with_lm import WavaVecaProcessorWithLM
   from transformers.models.wavaveca_with_lm.processing_wavaveca_with_lm import WavaVecaDecoderWithLMOutput

if is_torch_available():
   from transformers import WavaVecaForCTC




@require_pyctcdecode
class       a__	( unittest.TestCase				):







     def       lowerCAmelCase_    (     self			)  ->   Tuple:



          '''simple docstring'''



          a     =				"| <pad> <unk> <s> </s> a b c d e f g h i j k".split()
          a     =				dict(zip(A  ,		range(len(A			)			)			)			)

          a     =				{
              "unk_token": "<unk>",
              "bos_token": "<s>",
              "eos_token": "</s>",
          }
          a     =				{
              "feature_size": 1,
              "padding_value": 0.0,
              "sampling_rate": 16000,
              "return_attention_mask": False,
              "do_normalize": True,
          }

          a     =				tempfile.mkdtemp()
          a     =				os.path.join(self.tmpdirname  ,		VOCAB_FILES_NAMES["vocab_file"]			)
          a     =				os.path.join(self.tmpdirname  ,		A			)
          with open(self.vocab_file  ,		"w"  ,		encoding="utf-8"			) as fp:
               fp.write(json.dumps(A			) + "\n"			)

          with open(self.feature_extraction_file  ,		"w"  ,		encoding="utf-8"			) as fp:
               fp.write(json.dumps(A			) + "\n"			)

          # load decoder from hub
          a     =				"hf-internal-testing/ngram-beam-search-decoder"







     def       lowerCAmelCase_    (     self  ,		**A			)  ->   str:



          '''simple docstring'''



          a     =				self.add_kwargs_tokens_map.copy()
          kwargs.update(A			)
          return WavaVecaCTCTokenizer.from_pretrained(self.tmpdirname  ,		**A			)







     def       lowerCAmelCase_    (     self  ,		**A			)  ->   Optional[int]:



          '''simple docstring'''



          return WavaVecaFeatureExtractor.from_pretrained(self.tmpdirname  ,		**A			)







     def       lowerCAmelCase_    (     self  ,		**A			)  ->   Dict:



          '''simple docstring'''



          return BeamSearchDecoderCTC.load_from_hf_hub(self.decoder_name  ,		**A			)







     def       lowerCAmelCase_    (     self			)  ->   int:



          '''simple docstring'''



          shutil.rmtree(self.tmpdirname			)







     def       lowerCAmelCase_    (     self			)  ->   Any:



          '''simple docstring'''



          a     =				self.get_tokenizer()
          a     =				self.get_feature_extractor()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          processor.save_pretrained(self.tmpdirname			)
          a     =				WavaVecaProcessorWithLM.from_pretrained(self.tmpdirname			)

          # tokenizer
          self.assertEqual(processor.tokenizer.get_vocab()  ,		tokenizer.get_vocab()			)
          self.assertIsInstance(processor.tokenizer  ,		A			)

          # feature extractor
          self.assertEqual(processor.feature_extractor.to_json_string()  ,		feature_extractor.to_json_string()			)
          self.assertIsInstance(processor.feature_extractor  ,		A			)

          # decoder
          self.assertEqual(processor.decoder._alphabet.labels  ,		decoder._alphabet.labels			)
          self.assertEqual(
              processor.decoder.model_container[decoder._model_key]._unigram_set  ,		decoder.model_container[decoder._model_key]._unigram_set  ,		)
          self.assertIsInstance(processor.decoder  ,		A			)







     def       lowerCAmelCase_    (     self			)  ->   Optional[int]:



          '''simple docstring'''



          a     =				WavaVecaProcessorWithLM(
              tokenizer=self.get_tokenizer()  ,		feature_extractor=self.get_feature_extractor()  ,		decoder=self.get_decoder()			)
          processor.save_pretrained(self.tmpdirname			)

          # make sure that error is thrown when decoder alphabet doesn't match
          a     =				WavaVecaProcessorWithLM.from_pretrained(
              self.tmpdirname  ,		alpha=5.0  ,		beta=3.0  ,		score_boundary=-7.0  ,		unk_score_offset=3			)

          # decoder
          self.assertEqual(processor.language_model.alpha  ,		5.0			)
          self.assertEqual(processor.language_model.beta  ,		3.0			)
          self.assertEqual(processor.language_model.score_boundary  ,		-7.0			)
          self.assertEqual(processor.language_model.unk_score_offset  ,		3			)







     def       lowerCAmelCase_    (     self			)  ->   Optional[Any]:



          '''simple docstring'''



          a     =				self.get_tokenizer()
          # add token to trigger raise
          tokenizer.add_tokens(["xx"]			)
          with self.assertRaisesRegex(A  ,		"include"			):
               WavaVecaProcessorWithLM(
                   tokenizer=A  ,		feature_extractor=self.get_feature_extractor()  ,		decoder=self.get_decoder()			)







     def       lowerCAmelCase_    (     self			)  ->   Optional[Any]:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          a     =				floats_list((3, 1000)			)

          a     =				feature_extractor(A  ,		return_tensors="np"			)
          a     =				processor(A  ,		return_tensors="np"			)

          for key in input_feat_extract.keys():
               self.assertAlmostEqual(input_feat_extract[key].sum()  ,		input_processor[key].sum()  ,		delta=1e-2			)







     def       lowerCAmelCase_    (     self			)  ->   Dict:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          a     =				"This is a test string"

          a     =				processor(text=A			)

          a     =				tokenizer(A			)

          for key in encoded_tok.keys():
               self.assertListEqual(encoded_tok[key]  ,		encoded_processor[key]			)







     def       lowerCAmelCase_    (     self  ,		A=(2, 10, 16)  ,		A=77			)  ->   str:



          '''simple docstring'''



          np.random.seed(A			)
          return np.random.rand(*A			)







     def       lowerCAmelCase_    (     self			)  ->   Any:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          a     =				self._get_dummy_logits(shape=(10, 16)  ,		seed=13			)

          a     =				processor.decode(A			)

          a     =				decoder.decode_beams(A			)[0]

          self.assertEqual(decoded_decoder[0]  ,		decoded_processor.text			)
          self.assertEqual("</s> <s> </s>"  ,		decoded_processor.text			)
          self.assertEqual(decoded_decoder[-2]  ,		decoded_processor.logit_score			)
          self.assertEqual(decoded_decoder[-1]  ,		decoded_processor.lm_score			)







     @parameterized.expand([[None], ["fork"], ["spawn"]]			)
     def       lowerCAmelCase_    (     self  ,		A			)  ->   Dict:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          a     =				self._get_dummy_logits()

          # note: pool should be instantiated *after* Wav2Vec2ProcessorWithLM.
          #       otherwise, the LM won't be available to the pool's sub-processes.
          # manual logic used to allow parameterized test for both pool=None and pool=Pool(...)
          if pool_context is None:
               a     =				processor.batch_decode(A			)
          else:
               with get_context(A			).Pool() as pool:
                    a     =				processor.batch_decode(A  ,		A			)

          a     =				list(A			)

          with get_context("fork"			).Pool() as p:
               a     =				decoder.decode_beams_batch(A  ,		A			)

          a  ,				a  ,				a     =				[], [], []
          for beams in decoded_beams:
               texts_decoder.append(beams[0][0]			)
               logit_scores_decoder.append(beams[0][-2]			)
               lm_scores_decoder.append(beams[0][-1]			)

          self.assertListEqual(A  ,		decoded_processor.text			)
          self.assertListEqual(["<s> <s> </s>", "<s> <s> <s>"]  ,		decoded_processor.text			)
          self.assertListEqual(A  ,		decoded_processor.logit_score			)
          self.assertListEqual(A  ,		decoded_processor.lm_score			)







     def       lowerCAmelCase_    (     self			)  ->   int:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          a     =				self._get_dummy_logits()

          a     =				15
          a     =				-2_0.0
          a     =				-4.0

          a     =				processor.batch_decode(
              A  ,		beam_width=A  ,		beam_prune_logp=A  ,		token_min_logp=A  ,		)
          a     =				decoded_processor_out.text

          a     =				list(A			)

          with get_context("fork"			).Pool() as pool:
               a     =				decoder.decode_beams_batch(
                   A  ,		A  ,		beam_width=A  ,		beam_prune_logp=A  ,		token_min_logp=A  ,		)

          a     =				[d[0][0] for d in decoded_decoder_out]
          a     =				[d[0][2] for d in decoded_decoder_out]
          a     =				[d[0][3] for d in decoded_decoder_out]

          self.assertListEqual(A  ,		A			)
          self.assertListEqual(["</s> <s> <s>", "<s> <s> <s>"]  ,		A			)

          self.assertTrue(np.array_equal(A  ,		decoded_processor_out.logit_score			)			)
          self.assertTrue(np.allclose([-2_0.0_5_4, -1_8.4_4_7]  ,		A  ,		atol=1e-3			)			)

          self.assertTrue(np.array_equal(A  ,		decoded_processor_out.lm_score			)			)
          self.assertTrue(np.allclose([-1_5.5_5_4, -1_3.9_4_7_4]  ,		A  ,		atol=1e-3			)			)







     def       lowerCAmelCase_    (     self			)  ->   List[str]:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          a     =				self._get_dummy_logits()

          a     =				2.0
          a     =				5.0
          a     =				-2_0.0
          a     =				True

          a     =				processor.batch_decode(
              A  ,		alpha=A  ,		beta=A  ,		unk_score_offset=A  ,		lm_score_boundary=A  ,		)
          a     =				decoded_processor_out.text

          a     =				list(A			)
          decoder.reset_params(
              alpha=A  ,		beta=A  ,		unk_score_offset=A  ,		lm_score_boundary=A  ,		)

          with get_context("fork"			).Pool() as pool:
               a     =				decoder.decode_beams_batch(
                   A  ,		A  ,		)

          a     =				[d[0][0] for d in decoded_decoder_out]

          self.assertListEqual(A  ,		A			)
          self.assertListEqual(["<s> </s> <s> </s> </s>", "</s> </s> <s> </s> </s>"]  ,		A			)
          a     =				processor.decoder.model_container[processor.decoder._model_key]
          self.assertEqual(lm_model.alpha  ,		2.0			)
          self.assertEqual(lm_model.beta  ,		5.0			)
          self.assertEqual(lm_model.unk_score_offset  ,		-2_0.0			)
          self.assertEqual(lm_model.score_boundary  ,		A			)







     def       lowerCAmelCase_    (     self			)  ->   Tuple:



          '''simple docstring'''



          a     =				WavaVecaProcessorWithLM.from_pretrained("hf-internal-testing/processor_with_lm"			)

          a     =				processor.decoder.model_container[processor.decoder._model_key]
          a     =				Path(language_model._kenlm_model.path.decode("utf-8"			)			).parent.parent.absolute()

          a     =				os.listdir(A			)
          a     =				["alphabet.json", "language_model"]

          downloaded_decoder_files.sort()
          expected_decoder_files.sort()

          # test that only decoder relevant files from
          # https://huggingface.co/hf-internal-testing/processor_with_lm/tree/main
          # are downloaded and none of the rest (e.g. README.md, ...)
          self.assertListEqual(A  ,		A			)







     def       lowerCAmelCase_    (     self			)  ->   Dict:



          '''simple docstring'''



          a     =				snapshot_download("hf-internal-testing/processor_with_lm"			)

          a     =				WavaVecaProcessorWithLM.from_pretrained(A			)

          a     =				processor.decoder.model_container[processor.decoder._model_key]
          a     =				Path(language_model._kenlm_model.path.decode("utf-8"			)			).parent.parent.absolute()

          a     =				os.listdir(A			)
          a     =				os.listdir(A			)

          local_decoder_files.sort()
          expected_decoder_files.sort()

          # test that both decoder form hub and local files in cache are the same
          self.assertListEqual(A  ,		A			)







     def       lowerCAmelCase_    (     self			)  ->   Dict:



          '''simple docstring'''



          a     =				WavaVecaProcessorWithLM.from_pretrained("hf-internal-testing/processor_with_lm"			)
          a     =				AutoProcessor.from_pretrained("hf-internal-testing/processor_with_lm"			)

          a     =				floats_list((3, 1000)			)

          a     =				processor_wavaveca(A  ,		return_tensors="np"			)
          a     =				processor_auto(A  ,		return_tensors="np"			)

          for key in input_wavaveca.keys():
               self.assertAlmostEqual(input_wavaveca[key].sum()  ,		input_auto[key].sum()  ,		delta=1e-2			)

          a     =				self._get_dummy_logits()

          a     =				processor_wavaveca.batch_decode(A			)
          a     =				processor_auto.batch_decode(A			)

          self.assertListEqual(decoded_wavaveca.text  ,		decoded_auto.text			)







     def       lowerCAmelCase_    (     self			)  ->   int:



          '''simple docstring'''



          a     =				self.get_feature_extractor()
          a     =				self.get_tokenizer()
          a     =				self.get_decoder()

          a     =				WavaVecaProcessorWithLM(tokenizer=A  ,		feature_extractor=A  ,		decoder=A			)

          self.assertListEqual(
              processor.model_input_names  ,		feature_extractor.model_input_names  ,		msg="`processor` and `feature_extractor` model input names do not match"  ,		)







     @staticmethod
     def       lowerCAmelCase_    (     A  ,		A			)  ->   List[Any]:



          '''simple docstring'''



          a     =				[d[key] for d in offsets]
          return retrieved_list







     def       lowerCAmelCase_    (     self			)  ->   int:



          '''simple docstring'''



          a     =				WavaVecaProcessorWithLM.from_pretrained("hf-internal-testing/processor_with_lm"			)
          a     =				self._get_dummy_logits()[0]

          a     =				processor.decode(A  ,		output_word_offsets=A			)
          # check Wav2Vec2CTCTokenizerOutput keys for word
          self.assertEqual(len(outputs.keys()			)  ,		4			)
          self.assertTrue("text" in outputs			)
          self.assertTrue("word_offsets" in outputs			)
          self.assertTrue(isinstance(A  ,		A			)			)

          self.assertEqual(" ".join(self.get_from_offsets(outputs["word_offsets"]  ,		"word"			)			)  ,		outputs.text			)
          self.assertListEqual(self.get_from_offsets(outputs["word_offsets"]  ,		"word"			)  ,		["<s>", "<s>", "</s>"]			)
          self.assertListEqual(self.get_from_offsets(outputs["word_offsets"]  ,		"start_offset"			)  ,		[0, 2, 4]			)
          self.assertListEqual(self.get_from_offsets(outputs["word_offsets"]  ,		"end_offset"			)  ,		[1, 3, 5]			)







     def       lowerCAmelCase_    (     self			)  ->   List[str]:



          '''simple docstring'''



          a     =				WavaVecaProcessorWithLM.from_pretrained("hf-internal-testing/processor_with_lm"			)
          a     =				self._get_dummy_logits()

          a     =				processor.batch_decode(A  ,		output_word_offsets=A			)

          # check Wav2Vec2CTCTokenizerOutput keys for word
          self.assertEqual(len(outputs.keys()			)  ,		4			)
          self.assertTrue("text" in outputs			)
          self.assertTrue("word_offsets" in outputs			)
          self.assertTrue(isinstance(A  ,		A			)			)

          self.assertListEqual(
              [" ".join(self.get_from_offsets(A  ,		"word"			)			) for o in outputs["word_offsets"]]  ,		outputs.text			)
          self.assertListEqual(self.get_from_offsets(outputs["word_offsets"][0]  ,		"word"			)  ,		["<s>", "<s>", "</s>"]			)
          self.assertListEqual(self.get_from_offsets(outputs["word_offsets"][0]  ,		"start_offset"			)  ,		[0, 2, 4]			)
          self.assertListEqual(self.get_from_offsets(outputs["word_offsets"][0]  ,		"end_offset"			)  ,		[1, 3, 5]			)







     @slow
     @require_torch
     @require_torchaudio
     def       lowerCAmelCase_    (     self			)  ->   Dict:



          '''simple docstring'''



          import torch

          a     =				load_dataset("common_voice"  ,		"en"  ,		split="train"  ,		streaming=A			)
          a     =				ds.cast_column("audio"  ,		datasets.Audio(sampling_rate=16000			)			)
          a     =				iter(A			)
          a     =				next(A			)

          a     =				AutoProcessor.from_pretrained("patrickvonplaten/wav2vec2-base-100h-with-lm"			)
          a     =				WavaVecaForCTC.from_pretrained("patrickvonplaten/wav2vec2-base-100h-with-lm"			)

          # compare to filename `common_voice_en_100038.mp3` of dataset viewer on https://huggingface.co/datasets/common_voice/viewer/en/train
          a     =				processor(sample["audio"]["array"]  ,		return_tensors="pt"			).input_values

          with torch.no_grad():
               a     =				model(A			).logits.cpu().numpy()

          a     =				processor.decode(logits[0]  ,		output_word_offsets=A			)

          a     =				model.config.inputs_to_logits_ratio / processor.feature_extractor.sampling_rate
          a     =				[
              {
                  "start_time": d["start_offset"] * time_offset,
                  "end_time": d["end_offset"] * time_offset,
                  "word": d["word"],
              }
              for d in output["word_offsets"]
          ]

          a     =				"WHY DOES MILISANDRA LOOK LIKE SHE WANTS TO CONSUME JOHN SNOW ON THE RIVER AT THE WALL"

          # output words
          self.assertEqual(" ".join(self.get_from_offsets(A  ,		"word"			)			)  ,		A			)
          self.assertEqual(" ".join(self.get_from_offsets(A  ,		"word"			)			)  ,		output.text			)

          # output times
          a     =				torch.tensor(self.get_from_offsets(A  ,		"start_time"			)			)
          a     =				torch.tensor(self.get_from_offsets(A  ,		"end_time"			)			)

          # fmt: off
          a     =				torch.tensor([1.4_1_9_9, 1.6_5_9_9, 2.2_5_9_9, 3.0, 3.2_4, 3.5_9_9_9, 3.7_9_9_9, 4.0_9_9_9, 4.2_6, 4.9_4, 5.2_8, 5.6_5_9_9, 5.7_8, 5.9_4, 6.3_2, 6.5_3_9_9, 6.6_5_9_9]			)
          a     =				torch.tensor([1.5_3_9_9, 1.8_9_9_9, 2.9, 3.1_6, 3.5_3_9_9, 3.7_2, 4.0_1_9_9, 4.1_7_9_9, 4.7_6, 5.1_5_9_9, 5.5_5_9_9, 5.6_9_9_9, 5.8_6, 6.1_9_9_9, 6.3_8, 6.6_1_9_9, 6.9_4]			)
          # fmt: on

          self.assertTrue(torch.allclose(A  ,		A  ,		atol=0.0_1			)			)
          self.assertTrue(torch.allclose(A  ,		A  ,		atol=0.0_1			)			)







from manim import *




class       a__	( UpperCamelCase__				):







     def       lowerCAmelCase_    (     self			)  ->   List[Any]:



          '''simple docstring'''



          a     =				Rectangle(height=0.5  ,		width=0.5			)
          a     =				Rectangle(height=0.4_6  ,		width=0.4_6			).set_stroke(width=0			)

          a     =				Rectangle(height=0.2_5  ,		width=0.2_5			)

          a     =				[mem.copy() for i in range(6			)]
          a     =				[mem.copy() for i in range(6			)]
          a     =				VGroup(*A			).arrange(A  ,		buff=0			)
          a     =				VGroup(*A			).arrange(A  ,		buff=0			)
          a     =				VGroup(A  ,		A			).arrange(A  ,		buff=0			)
          a     =				Text("CPU"  ,		font_size=24			)
          a     =				Group(A  ,		A			).arrange(A  ,		buff=0.5  ,		aligned_edge=A			)
          cpu.move_to([-2.5, -0.5, 0]			)
          self.add(A			)

          a     =				[mem.copy() for i in range(4			)]
          a     =				VGroup(*A			).arrange(A  ,		buff=0			)
          a     =				Text("GPU"  ,		font_size=24			)
          a     =				Group(A  ,		A			).arrange(A  ,		buff=0.5  ,		aligned_edge=A			)
          gpu.move_to([-1, -1, 0]			)
          self.add(A			)

          a     =				[mem.copy() for i in range(6			)]
          a     =				VGroup(*A			).arrange(A  ,		buff=0			)

          a     =				Text("Model"  ,		font_size=24			)
          a     =				Group(A  ,		A			).arrange(A  ,		buff=0.5  ,		aligned_edge=A			)
          model.move_to([3, -1.0, 0]			)
          self.add(A			)

          a     =				[]
          a     =				[]

          for i, rect in enumerate(A			):
               a     =				fill.copy().set_fill(A  ,		opacity=0.8			)
               target.move_to(A			)
               model_arr.append(A			)

               a     =				Rectangle(height=0.4_6  ,		width=0.4_6			).set_stroke(width=0.0			).set_fill(A  ,		opacity=0.8			)
               cpu_target.move_to(cpu_left_col_base[i]			)
               model_cpu_arr.append(A			)

          self.add(*A  ,		*A			)

          a     =				[meta_mem.copy() for i in range(6			)]
          a     =				[meta_mem.copy() for i in range(6			)]
          a     =				VGroup(*A			).arrange(A  ,		buff=0			)
          a     =				VGroup(*A			).arrange(A  ,		buff=0			)
          a     =				VGroup(A  ,		A			).arrange(A  ,		buff=0			)
          a     =				Text("Disk"  ,		font_size=24			)
          a     =				Group(A  ,		A			).arrange(A  ,		buff=0.5  ,		aligned_edge=A			)
          disk.move_to([-4, -1.2_5, 0]			)
          self.add(A  ,		A			)

          a     =				Square(side_length=2.2			)
          key.move_to([-5, 2, 0]			)

          a     =				MarkupText(
              F'''<b>Key:</b>\n\n<span fgcolor=\'{YELLOW}\'>●</span> Empty Model'''  ,		font_size=18  ,		)

          key_text.move_to([-5, 2.4, 0]			)

          self.add(A  ,		A			)

          a     =				MarkupText(
              F'''<span fgcolor=\'{BLUE}\'>●</span> Checkpoint'''  ,		font_size=18  ,		)

          blue_text.next_to(A  ,		DOWN * 2.4  ,		aligned_edge=key_text.get_left()			)
          self.add(A			)

          a     =				MarkupText(
              F'''Now watch as an input is passed through the model\nand how the memory is utilized and handled.'''  ,		font_size=24  ,		)
          step_a.move_to([2, 2, 0]			)

          self.play(Write(A			)			)

          a     =				Square(0.3			)
          input.set_fill(A  ,		opacity=1.0			)
          input.set_stroke(width=0.0			)
          input.next_to(model_base[0]  ,		A  ,		buff=0.5			)

          self.play(Write(A			)			)

          input.generate_target()
          input.target.next_to(model_arr[0]  ,		direction=A  ,		buff=0.0_2			)
          self.play(MoveToTarget(A			)			)

          self.play(FadeOut(A			)			)

          a     =				Arrow(start=A  ,		end=A  ,		color=A  ,		buff=0.5			)
          a.next_to(model_arr[0].get_left()  ,		A  ,		buff=0.2			)

          model_cpu_arr[0].generate_target()
          model_cpu_arr[0].target.move_to(gpu_rect[0]			)

          a     =				MarkupText(
              F'''As the input reaches a layer, the hook triggers\nand weights are moved from the CPU\nto the GPU and back.'''  ,		font_size=24  ,		)
          step_a.move_to([2, 2, 0]			)

          self.play(Write(A  ,		run_time=3			)			)

          a     =				{"run_time": 1, "fade_in": True, "fade_out": True, "buff": 0.0_2}

          self.play(
              Write(A			)  ,		Circumscribe(model_arr[0]  ,		color=A  ,		**A			)  ,		Circumscribe(model_cpu_arr[0]  ,		color=A  ,		**A			)  ,		Circumscribe(gpu_rect[0]  ,		color=A  ,		**A			)  ,		)
          self.play(MoveToTarget(model_cpu_arr[0]			)			)

          a     =				a.copy()
          for i in range(6			):
               a_c.next_to(model_arr[i].get_right() + 0.0_2  ,		A  ,		buff=0.2			)

               input.generate_target()
               input.target.move_to(model_arr[i].get_right() + 0.0_2			)

               a     =				AnimationGroup(
                   FadeOut(A  ,		run_time=0.5			)  ,		MoveToTarget(A  ,		run_time=0.5			)  ,		FadeIn(A  ,		run_time=0.5			)  ,		lag_ratio=0.2			)

               self.play(A			)

               model_cpu_arr[i].generate_target()
               model_cpu_arr[i].target.move_to(cpu_left_col_base[i]			)

               if i < 5:
                    model_cpu_arr[i + 1].generate_target()
                    model_cpu_arr[i + 1].target.move_to(gpu_rect[0]			)
                    if i >= 1:
                         a     =				0.7

                    self.play(
                        Circumscribe(model_arr[i]  ,		**A			)  ,		Circumscribe(cpu_left_col_base[i]  ,		**A			)  ,		Circumscribe(cpu_left_col_base[i + 1]  ,		color=A  ,		**A			)  ,		Circumscribe(gpu_rect[0]  ,		color=A  ,		**A			)  ,		Circumscribe(model_arr[i + 1]  ,		color=A  ,		**A			)  ,		)
                    if i < 1:
                         self.play(
                             MoveToTarget(model_cpu_arr[i]			)  ,		MoveToTarget(model_cpu_arr[i + 1]			)  ,		)
                    else:
                         self.play(
                             MoveToTarget(model_cpu_arr[i]  ,		run_time=0.7			)  ,		MoveToTarget(model_cpu_arr[i + 1]  ,		run_time=0.7			)  ,		)
               else:
                    model_cpu_arr[i].generate_target()
                    model_cpu_arr[i].target.move_to(cpu_left_col_base[-1]			)
                    input.generate_target()
                    input.target.next_to(model_arr[-1].get_right()  ,		RIGHT + 0.0_2  ,		buff=0.2			)

                    self.play(
                        Circumscribe(model_arr[-1]  ,		color=A  ,		**A			)  ,		Circumscribe(cpu_left_col_base[-1]  ,		color=A  ,		**A			)  ,		Circumscribe(gpu_rect[0]  ,		color=A  ,		**A			)  ,		)

                    self.play(MoveToTarget(model_cpu_arr[i]			)			)

               a     =				a_c
               a     =				a_c.copy()

          input.generate_target()
          input.target.next_to(model_base[-1]  ,		RIGHT + 0.0_2  ,		buff=0.5			)
          self.play(
              FadeOut(A			)  ,		FadeOut(A  ,		run_time=0.5			)  ,		)

          a     =				MarkupText(F'''Inference on a model too large for GPU memory\nis successfully completed.'''  ,		font_size=24			)
          step_a.move_to([2, 2, 0]			)

          self.play(Write(A  ,		run_time=3			)  ,		MoveToTarget(A			)			)

          self.wait()

