

import logging
from pathlib import Path

import numpy as np
import pytorch_lightning as pl
import torch
from pytorch_lightning.callbacks import EarlyStopping, ModelCheckpoint
from pytorch_lightning.utilities import rank_zero_only
from utils_rag import save_json





def 	__a     (      A__			:  List[str]       ):
    SCREAMING_SNAKE_CASE										=   filter(lambda A__       : p.requires_grad			,  model.parameters()       )
    SCREAMING_SNAKE_CASE										=   sum([np.prod(p.size()       ) for p in model_parameters]       )
    return params


__A			:					Optional[int]						=			logging.getLogger(__name__)





def 	__a     (      A__			:  Any			,  A__			:  str       ):
    if metric == "rouge2":
        SCREAMING_SNAKE_CASE										=   "{val_avg_rouge2:.4f}-{step_count}"
    elif metric == "bleu":
        SCREAMING_SNAKE_CASE										=   "{val_avg_bleu:.4f}-{step_count}"
    elif metric == "em":
        SCREAMING_SNAKE_CASE										=   "{val_avg_em:.4f}-{step_count}"
    else:
        raise NotImplementedError(
            F"seq2seq callbacks only support rouge2 and bleu, got {metric}, You can make your own by adding to this"
            " function."       )

    SCREAMING_SNAKE_CASE										=   ModelCheckpoint(
        dirpath=A__			,  filename=A__			,  monitor=F"val_{metric}"			,  mode="max"			,  save_top_k=3			,  every_n_epochs=1			,  )
    return checkpoint_callback





def 	__a     (      A__			:  int			,  A__			:  List[str]       ):
    return EarlyStopping(
        monitor=F"val_{metric}"			,  mode="min" if "loss" in metric else "max"			,  patience=A__			,  verbose=A__			,  )





class 			_SCREAMING_SNAKE_CASE (   pl.Callback		):







   '''simple docstring'''




   def      _snake_case		(       self					:			List[str]     , __lowerCamelCase					:			int     , __lowerCamelCase					:			Dict			):
       SCREAMING_SNAKE_CASE										=   {f"lr_group_{i}": param["lr"] for i, param in enumerate(pl_module.trainer.optimizers[0].param_groups			)}
       pl_module.logger.log_metrics(__lowerCamelCase			)





   @rank_zero_only
   def      _snake_case		(       self					:			Optional[Any]     , __lowerCamelCase					:			pl.Trainer     , __lowerCamelCase					:			pl.LightningModule     , __lowerCamelCase					:			str     , __lowerCamelCase					:			Optional[Any]=True			):
       logger.info(f"***** {type_path} results at step {trainer.global_step:05d} *****"			)
       SCREAMING_SNAKE_CASE										=   trainer.callback_metrics
       trainer.logger.log_metrics({k: v for k, v in metrics.items() if k not in ["log", "progress_bar", "preds"]}			)
       # Log results
       SCREAMING_SNAKE_CASE										=   Path(pl_module.hparams.output_dir			)
       if type_path == "test":
           SCREAMING_SNAKE_CASE										=   od / "test_results.txt"
           SCREAMING_SNAKE_CASE										=   od / "test_generations.txt"
       else:
           # this never gets hit. I prefer not to save intermediate generations, and results are in metrics.json
           # If people want this it will be easy enough to add back.
           SCREAMING_SNAKE_CASE										=   od / f"{type_path}_results/{trainer.global_step:05d}.txt"
           SCREAMING_SNAKE_CASE										=   od / f"{type_path}_generations/{trainer.global_step:05d}.txt"
           results_file.parent.mkdir(exist_ok=__lowerCamelCase			)
           generations_file.parent.mkdir(exist_ok=__lowerCamelCase			)
       with open(__lowerCamelCase     , "a+"			) as writer:
           for key in sorted(__lowerCamelCase			):
               if key in ["log", "progress_bar", "preds"]:
                   continue
               SCREAMING_SNAKE_CASE										=   metrics[key]
               if isinstance(__lowerCamelCase     , torch.Tensor			):
                   SCREAMING_SNAKE_CASE										=   val.item()
               SCREAMING_SNAKE_CASE										=   f"{key}: {val:.6f}\n"
               writer.write(__lowerCamelCase			)

       if not save_generations:
           return

       if "preds" in metrics:
           SCREAMING_SNAKE_CASE										=   "\n".join(metrics["preds"]			)
           generations_file.open("w+"			).write(__lowerCamelCase			)





   @rank_zero_only
   def      _snake_case		(       self					:			Tuple     , __lowerCamelCase					:			List[str]     , __lowerCamelCase					:			List[str]			):
       try:
           SCREAMING_SNAKE_CASE										=   pl_module.model.model.num_parameters()
       except AttributeError:
           SCREAMING_SNAKE_CASE										=   pl_module.model.num_parameters()

       SCREAMING_SNAKE_CASE										=   count_trainable_parameters(__lowerCamelCase			)
       # mp stands for million parameters
       trainer.logger.log_metrics({"n_params": npars, "mp": npars / 1e6, "grad_mp": n_trainable_pars / 1e6}			)





   @rank_zero_only
   def      _snake_case		(       self					:			Union[str, Any]     , __lowerCamelCase					:			pl.Trainer     , __lowerCamelCase					:			pl.LightningModule			):
       save_json(pl_module.metrics     , pl_module.metrics_save_path			)
       return self._write_logs(__lowerCamelCase     , __lowerCamelCase     , "test"			)





   @rank_zero_only
   def      _snake_case		(       self					:			int     , __lowerCamelCase					:			pl.Trainer     , __lowerCamelCase					:			Dict			):
       save_json(pl_module.metrics     , pl_module.metrics_save_path			)
       # Uncommenting this will save val generations
       # return self._write_logs(trainer, pl_module, "valid")


import sys

lowercase_   							=  (
    '73167176531330624919225119674426574742355349194934'
    '96983520312774506326239578318016984801869478851843'
    '85861560789112949495459501737958331952853208805511'
    '12540698747158523863050715693290963295227443043557'
    '66896648950445244523161731856403098711121722383113'
    '62229893423380308135336276614282806444486645238749'
    '30358907296290491560440772390713810515859307960866'
    '70172427121883998797908792274921901699720888093776'
    '65727333001053367881220235421809751254540594752243'
    '52584907711670556013604839586446706324415722155397'
    '53697817977846174064955149290862569321978468622482'
    '83972241375657056057490261407972968652414535100474'
    '82166370484403199890008895243450658541227588666881'
    '16427171479924442928230863465674813919123162824586'
    '17866458359124566529476545682848912883142607690042'
    '24219022671055626321111109370544217506941658960408'
    '07198403850962455444362981230987879927244284909188'
    '84580156166097919133875499200524063689912560717606'
    '05886116467109405077541002256983155200055935729725'
    '71636269561882670428252483600823257530420752963450'
)
def 	a (     A__      :  str = N	)       -> int:





      """simple docstring"""



      _lowercase      			=-sys.maxsize - 1
      for i in range(len(A__	) - 12	):
            _lowercase      			=1
            for j in range(13	):
                  product *= int(n[i + j]	)
            if product > largest_product:
                  _lowercase      			=product
      return largest_product


if __name__ == "__main__":
  print(f"{solution() = }")


