cffl/Exploring_Intelligent_Writing_Assistance
9
1# ###########################################################################2#3# CLOUDERA APPLIED MACHINE LEARNING PROTOTYPE (AMP)4# (C) Cloudera, Inc. 20225# All rights reserved.6#7# Applicable Open Source License: Apache 2.08#9# NOTE: Cloudera open source products are modular software products10# made up of hundreds of individual components, each of which was11# individually copyrighted. Each Cloudera open source product is a12# collective work under U.S. Copyright Law. Your license to use the13# collective work is as provided in your written agreement with14# Cloudera. Used apart from the collective work, this file is15# licensed for your use pursuant to the open source license16# identified above.17#18# This code is provided to you pursuant a written agreement with19# (i) Cloudera, Inc. or (ii) a third-party authorized to distribute20# this code. If you do not have a written agreement with Cloudera nor21# with an authorized and properly licensed third party, you do not22# have any rights to access nor to use this code.23#24# Absent a written agreement with Cloudera, Inc. (“Cloudera”) to the25# contrary, A) CLOUDERA PROVIDES THIS CODE TO YOU WITHOUT WARRANTIES OF ANY26# KIND; (B) CLOUDERA DISCLAIMS ANY AND ALL EXPRESS AND IMPLIED27# WARRANTIES WITH RESPECT TO THIS CODE, INCLUDING BUT NOT LIMITED TO28# IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND29# FITNESS FOR A PARTICULAR PURPOSE; (C) CLOUDERA IS NOT LIABLE TO YOU,30# AND WILL NOT DEFEND, INDEMNIFY, NOR HOLD YOU HARMLESS FOR ANY CLAIMS31# ARISING FROM OR RELATED TO THE CODE; AND (D)WITH RESPECT TO YOUR EXERCISE32# OF ANY RIGHTS GRANTED TO YOU FOR THE CODE, CLOUDERA IS NOT LIABLE FOR ANY33# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR34# CONSEQUENTIAL DAMAGES INCLUDING, BUT NOT LIMITED TO, DAMAGES35# RELATED TO LOST REVENUE, LOST PROFITS, LOSS OF INCOME, LOSS OF36# BUSINESS ADVANTAGE OR UNAVAILABILITY, OR LOSS OR CORRUPTION OF37# DATA.38#39# ###########################################################################40 41from typing import List42 43import tokenizers44import streamlit as st45 46from src.style_transfer import StyleTransfer47from src.style_classification import StyleIntensityClassifier48from src.content_preservation import ContentPreservationScorer49from src.transformer_interpretability import InterpretTransformer50from apps.data_utils import StyleAttributeData, string_to_list_string51 52# CALLBACKS53def increment_page_progress():54 st.session_state.page_progress += 155 56 57def reset_page_progress_state():58 del st.session_state.st_result59 st.session_state.page_progress = 160 61 62# UTILITY CLASSES63class DisableableButton:64 """65 Utility class for creating "disable-able" buttons upon click.66 67 We initialize an empty container, then update that container with buttons68 upon calling `create_enabled_button` and `disable` methods where clicking69 is enabled and then disabled, respectively.70 71 """72 73 def __init__(self, button_number, button_text):74 self.button_number = button_number75 self.button_text = button_text76 77 def _init_placeholder_container(self):78 self.ph = st.empty()79 80 def create_enabled_button(self):81 self._init_placeholder_container()82 self.ph.button(83 self.button_text,84 on_click=increment_page_progress,85 key=f"ph{self.button_number}_before",86 disabled=False,87 )88 89 def disable(self):90 self.ph.button(91 self.button_text, key=f"ph{self.button_number}_after", disabled=True92 )93 94 95# CACHED FUNCTIONS96@st.cache(97 hash_funcs={tokenizers.Tokenizer: lambda _: None},98 allow_output_mutation=True,99 show_spinner=False,100)101def get_cached_style_intensity_classifier(102 style_data: StyleAttributeData,103) -> StyleIntensityClassifier:104 """105 Return a cached style classifier.106 107 This function overwrites the existing model's config values for108 `id2label` and `label2id`.109 110 Args:111 style_data (StyleAttributeData)112 113 Returns:114 StyleIntensityClassifier115 """116 sic = StyleIntensityClassifier(style_data.cls_model_path)117 118 # create or overwrite id-label lookup in model config119 sic.pipeline.model.config.__dict__["id2label"] = {120 i: a121 for i, a in enumerate(122 [123 style_data.source_attribute.capitalize(),124 style_data.target_attribute.capitalize(),125 ]126 )127 }128 sic.pipeline.model.config.__dict__["label2id"] = {129 v: k for k, v in sic.pipeline.model.config.__dict__["id2label"].items()130 }131 132 return sic133 134 135@st.cache(136 hash_funcs={tokenizers.Tokenizer: lambda _: None},137 allow_output_mutation=True,138 show_spinner=False,139)140def get_cached_word_attributions(141 text_sample: str, style_data: StyleAttributeData142) -> str:143 """144 Calculated word attributions and return HTML visual.145 146 This function overwrites the existing model's config values for147 `id2label` and `label2id`.148 149 Args:150 text_sample (str)151 style_data (StyleAttributeData)152 153 Returns:154 str155 """156 it = InterpretTransformer(cls_model_identifier=style_data.cls_model_path)157 158 # create or overwrite id-label lookup in model config159 it.explainer.id2label = {160 i: a161 for i, a in enumerate(162 [163 style_data.source_attribute.capitalize(),164 style_data.target_attribute.capitalize(),165 ]166 )167 }168 it.explainer.label2id = {v: k for k, v in it.explainer.id2label.items()}169 return it.visualize_feature_attribution_scores(text_sample).data170 171 172@st.cache(173 hash_funcs={tokenizers.Tokenizer: lambda _: None},174 allow_output_mutation=True,175 show_spinner=False,176)177def get_sti_metric(178 input_text: str, output_text: str, style_data: StyleAttributeData179) -> List[float]:180 """181 Calculate Style Transfer Intensity (STI)182 183 Args:184 input_text (str)185 output_text (str)186 style_data (StyleAttributeData)187 188 Returns:189 List[float]190 """191 sti = StyleIntensityClassifier(192 model_identifier=style_data.cls_model_path,193 )194 return sti.calculate_transfer_intensity_fraction(195 string_to_list_string(input_text), string_to_list_string(output_text)196 )197 198 199@st.cache(200 hash_funcs={tokenizers.Tokenizer: lambda _: None},201 allow_output_mutation=True,202 show_spinner=False,203)204def get_cps_metric(205 input_text: str, output_text: str, style_data: StyleAttributeData206) -> List[float]:207 """208 Calculate Content Preservation Score (CPS)209 210 Args:211 input_text (str)212 output_text (str)213 style_data (StyleAttributeData)214 215 Returns:216 List[float]217 """218 cps = ContentPreservationScorer(219 cls_model_identifier=style_data.cls_model_path,220 sbert_model_identifier=style_data.sbert_model_path,221 )222 return cps.calculate_content_preservation_score(223 string_to_list_string(input_text),224 string_to_list_string(output_text),225 mask_type="none",226 )227 228 229def generate_style_transfer(230 text_sample: str,231 style_data: StyleAttributeData,232 max_gen_length: int,233 num_beams: int,234 temperature: int,235):236 """237 Run inference on seq2seq model and persist result to238 `session_state` varaible.239 240 Args:241 text_sample (str): _description_242 style_data (StyleAttributeData): _description_243 max_gen_length (int): _description_244 num_beams (int): _description_245 temperature (int): _description_246 """247 with st.spinner("Transferring style, hang tight!"):248 249 generate_kwargs = {250 "max_gen_length": max_gen_length,251 "num_beams": num_beams,252 "temperature": temperature,253 }254 255 st_class = StyleTransfer(256 model_identifier=style_data.seq2seq_model_path,257 **generate_kwargs,258 )259 260 st_result = st_class.transfer(text_sample)261 262 st.session_state.st_result = st_result263 