CoolFace
Apppublic

geraskalnas/document-summarization

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
1likes
summarize.py173 linesDownload Raw Back to root
1"""2summarize - a module for summarizing text using a model from the Hugging Face model hub3"""4import logging5import pprint as pp6 7logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(message)s")8 9import torch10from tqdm.auto import tqdm11from transformers import AutoModelForSeq2SeqLM, AutoTokenizer12 13from utils import validate_pytorch214 15 16def load_model_and_tokenizer(model_name: str) -> tuple:17    """18    load_model_and_tokenizer - load a model and tokenizer from a model name/ID on the hub19 20    :param str model_name: the model name/ID on the hub21    :return tuple: a tuple containing the model and tokenizer22    """23    device = "cuda" if torch.cuda.is_available() else "cpu"24    model = AutoModelForSeq2SeqLM.from_pretrained(25        model_name,26    ).to(device)27    model = model.eval()28 29    tokenizer = AutoTokenizer.from_pretrained(model_name)30 31    logging.info(f"Loaded model {model_name} to {device}")32 33    if validate_pytorch2():34        try:35            logging.info("Compiling model with Torch 2.0")36            model = torch.compile(model)37        except Exception as e:38            logging.warning(f"Could not compile model with Torch 2.0: {e}")39    else:40        logging.info("Torch 2.0 not detected, skipping compilation")41 42    return model, tokenizer43 44 45def summarize_and_score(46    ids, mask, model, tokenizer, is_general_attention_model=True, **kwargs47) -> tuple:48    """49    summarize_and_score - given a batch of ids and a mask, return a summary and a score for the summary50 51    Args:52        ids (): the batch of ids53        mask (): the attention mask for the batch54        model   (): the model to use for summarization55        tokenizer (): the tokenizer to use for summarization56        is_general_attention_model (bool, optional): whether the model is a general attention model. Defaults to True.57        **kwargs: any additional arguments to pass to the model58    Returns:59        tuple (str, float): the summary,  the score for the summary60    """61 62    ids = ids[None, :]63    mask = mask[None, :]64 65    input_ids = ids.to("cuda") if torch.cuda.is_available() else ids66    attention_mask = mask.to("cuda") if torch.cuda.is_available() else mask67 68    global_attention_mask = torch.zeros_like(attention_mask)69    # put global attention on <s> token70    global_attention_mask[:, 0] = 171 72    if is_general_attention_model:73        summary_pred_ids = model.generate(74            input_ids,75            attention_mask=attention_mask,76            output_scores=True,77            return_dict_in_generate=True,78            **kwargs,79        )80    else:81        summary_pred_ids = model.generate(82            input_ids,83            attention_mask=attention_mask,84            global_attention_mask=global_attention_mask,85            output_scores=True,86            return_dict_in_generate=True,87            **kwargs,88        )89    summary = tokenizer.batch_decode(90        summary_pred_ids.sequences,91        skip_special_tokens=True,92        remove_invalid_values=True,93    )94    score = round(summary_pred_ids.sequences_scores.cpu().numpy()[0], 4)95 96    return summary, score97 98 99def summarize_via_tokenbatches(100    input_text: str,101    model,102    tokenizer,103    batch_length=2048,104    batch_stride=16,105    min_batch_length=512,106    **kwargs,107) -> list:108    """109    summarize_via_tokenbatches - summarize a long string via batches of tokens110 111    Args:112        input_text (str): the text to summarize113        model (): the model to use for summarization114        tokenizer (): the tokenizer to use for summarization115        batch_length (int, optional): the length of each batch. Defaults to 2048.116        batch_stride (int, optional): the stride of each batch. Defaults to 16. The stride is the number of tokens that overlap between batches.117        min_batch_length (int, optional): the minimum length of each batch. Defaults to 512.118 119        **kwargs: any additional arguments to pass to the model for inference120    Returns:121        list: a list of dictionaries containing the input tokens, the summary, and the summary score122    """123 124    logger = logging.getLogger(__name__)125    # log all input parameters126    if batch_length < min_batch_length:127        logger.warning(128            f"batch_length must be at least {min_batch_length}. Setting batch_length to {min_batch_length}"129        )130        batch_length = min_batch_length131 132    logger.info(f"input parameters:\n{pp.pformat(kwargs)}")133    logger.info(f"batch_length: {batch_length}, batch_stride: {batch_stride}")134 135    encoded_input = tokenizer(136        input_text,137        padding="max_length",138        truncation=True,139        max_length=batch_length,140        stride=batch_stride,141        return_overflowing_tokens=True,142        add_special_tokens=False,143        return_tensors="pt",144    )145 146    in_id_arr, att_arr = encoded_input.input_ids, encoded_input.attention_mask147    gen_summaries = []148 149    pbar = tqdm(total=len(in_id_arr))150 151    for _id, _mask in zip(in_id_arr, att_arr):152        result, score = summarize_and_score(153            ids=_id,154            mask=_mask,155            model=model,156            tokenizer=tokenizer,157            **kwargs,158        )159        score = round(float(score), 4)160        _sum = {161            "input_tokens": _id,162            "summary": result,163            "summary_score": score,164        }165        gen_summaries.append(_sum)166        logger.debug(f"Score for batch: {score}. num chars: {len(repr(result))}")167        logger.debug(f"Summary:\n\t{result}")168        pbar.update()169 170    pbar.close()171 172    return gen_summaries173