Spaces:
Runtime error
Runtime error
File size: 15,051 Bytes
9c3e084 4fe8a98 9c3e084 6eebd5b 95e0eda cc5df5a 9c3e084 4fd2001 9c3e084 eef2376 9c3e084 eef2376 9c3e084 eef2376 95e0eda eef2376 4fe8a98 eef2376 4fe8a98 9c3e084 cc5df5a 9c3e084 eef2376 9c3e084 eef2376 9c3e084 eef2376 9c3e084 cc5df5a eef2376 cc5df5a 21cd2e3 eef2376 cc5df5a eef2376 cc5df5a eef0261 21cd2e3 eef0261 cc5df5a eef0261 2284b92 eef0261 cc5df5a eef0261 4fe8a98 eef0261 cc5df5a eef0261 cb95565 eef0261 cc5df5a eef0261 9c3e084 eef2376 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
# -*- coding: utf-8 -*-
import os
import re
import numpy as np
import pandas as pd
from tqdm import tqdm
import matplotlib.pyplot as plt
import warnings
import nltk
import random, time
import datetime
# nltk.download("stopwords")
from nltk.corpus import stopwords
import torch
import torch.nn as nn
from torch.utils.data import TensorDataset, DataLoader, RandomSampler, SequentialSampler,random_split
from sklearn.metrics import classification_report
import transformers
from transformers import BartForSequenceClassification, AdamW, BartTokenizer, get_linear_schedule_with_warmup, pipeline, set_seed
from transformers import pipeline, set_seed, BartTokenizer
from datasets import load_dataset, load_metric
from dotenv import load_dotenv
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
from nltk.tokenize import sent_tokenize
from datasets import Dataset, load_metric
import datasets
import gradio as gr
import pyperclip
import openai
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
from transformers import TrainingArguments, Trainer
# from vicuna_generate import *
# from convert_article import *
# Data preprocessing
def text_preprocessing(s):
"""
- Lowercase the sentence
- Change "'t" to "not"
- Remove "@name"
- Isolate and remove punctuations except "?"
- Remove other special characters
- Remove stop words except "not" and "can"
- Remove trailing whitespace
"""
s = s.lower()
# Change 't to 'not'
s = re.sub(r"\'t", " not", s)
# Remove @name
s = re.sub(r'(@.*?)[\s]', ' ', s)
# Isolate and remove punctuations except '?'
s = re.sub(r'([\'\"\.\(\)\!\?\\\/\,])', r' \1 ', s)
s = re.sub(r'[^\w\s\?]', ' ', s)
# Remove some special characters
s = re.sub(r'([\;\:\|•«\n])', ' ', s)
# Remove stopwords except 'not' and 'can'
s = " ".join([word for word in s.split()
if word not in stopwords.words('english')
or word in ['not', 'can']])
# Remove trailing whitespace
s = re.sub(r'\s+', ' ', s).strip()
return s
def text_preprocessing(text):
"""
- Remove entity mentions (eg. '@united')
- Correct errors (eg. '&' to '&')
@param text (str): a string to be processed.
@return text (Str): the processed string.
"""
# Remove '@name'
text = re.sub(r'(@.*?)[\s]', ' ', text)
# Replace '&' with '&'
text = re.sub(r'&', '&', text)
# Remove trailing whitespace
text = re.sub(r'\s+', ' ', text).strip()
return text
# Total number of training steps is [number of batches] x [number of epochs].
# (Note that this is not the same as the number of training samples).
# Create the learning rate scheduler.
# Function to calculate the accuracy of our predictions vs labels
def flat_accuracy(preds, labels):
pred_flat = np.argmax(preds, axis=1).flatten()
labels_flat = labels.flatten()
return np.sum(pred_flat == labels_flat) / len(labels_flat)
def format_time(elapsed):
'''
Takes a time in seconds and returns a string hh:mm:ss
'''
# Round to the nearest second.
elapsed_rounded = int(round((elapsed)))
# Format as hh:mm:ss
return str(datetime.timedelta(seconds=elapsed_rounded))
def decode(paragraphs_needed):
# model_ckpt = "facebook/bart-large-cnn"
tokenizer = AutoTokenizer.from_pretrained("theQuert/NetKUp-tokenzier")
# pipe = pipeline("summarization", model="bart-decoder",tokenizer=tokenizer)
pipe = pipeline("summarization", model="hyesunyun/update-summarization-bart-large-longformer",tokenizer=tokenizer)
contexts = [str(pipe(paragraph)) for paragraph in paragraphs_needed]
return contexts
def split_article(article, trigger):
if len(article.split("\\n ")) > len(article.split("\\\\c\\\\c")):
paragraphs = article.split("\\n ")
else:
paragraphs = article.split("\\\\c\\\\c")
pars = [str(par) + " -- " + str(trigger) for par in paragraphs]
# pd.DataFrame({"paragraphs": paragraphs}).to_csv("./util/experiments/check_par.csv")
format_pars = [par for par in paragraphs]
formatted_input = "\n".join(format_pars)
return pars, formatted_input
def config():
load_dotenv()
def call_gpt(paragraph, trigger):
openai.api_key = os.environ.get("GPT-API")
tokenizer = BartTokenizer.from_pretrained("theQuert/NetKUp-tokenzier")
inputs_for_gpt = f"""
s an article writer, your task is to provide an updated paragraph in the length same as non-updated paragraph based on the given non-updated paragraph and a triggered news.Remember, the length of updated paragraph is restricted into a single paragraph.
Non-updated paragraph:
{paragraph}
Triggered News:
{trigger}
"""
completion = openai.ChatCompletion.create(
model = "gpt-3.5-turbo",
messages = [
{"role": "user", "content": inputs_for_gpt}
]
)
response = completion.choices[0].message.content
if "<"+response.split("<")[-1].strip() == "<"+paragraph.split("<")[-1].strip(): response = response
else: response = response + " <"+paragraph.split("<")[-1].strip()
return str(response)
def call_vicuna(paragraphs_tirgger):
tokenizer = BartTokenizer.from_pretrained("theQuert/NetKUp-tokenzier")
merged_with_prompts = []
for paragraph in paragraphs:
merged = f"""
As an article writer, your task is to provide an updated paragraph in the length same as non-updated paragraph based on the given non-updated paragraph and a triggered news.
Non-updated paragraph:
{paragraph}
Triggered News:
{trigger}
"""
merged_with_prompts.append(merged.strip())
pd.DataFrame({"paragraph": merged_with_prompts}).to_csv("./util/experiments/paragraphs_with_prompts.csv")
responses = vicuna_output()
return responses
def main(input_article, input_trigger):
paths = [".util/experiments/input_paragraphs.csv",
"./util/experiments/formatted_input.txt",
"./util/experiments/updated_article.txt",
"./util/experiments/paragraphs_needed.txt",
"./util/experiments/updated_paragraphs.txt",
"./util/experiments/paragraphs_with_prompts.csv",
"./util/experiments/classification.csv",
"./util/experiments/paragraphs_needed.csv",
"./util/experiments/par_with_class.csv",
]
for path in paths:
try:
if os.path.isfile(path): os.remove(path)
except: continue
modified = "TRUE"
# device = "cuda" if torch.cuda.is_available() else "cpu"
device="cpu"
# tokenizer = BartTokenizer.from_pretrained('facebook/bart-large-cnn', do_lower_case=True)
tokenizer = AutoTokenizer.from_pretrained('theQuert/NetKUp-tokenzier')
batch_size = 8
model = torch.load("./util/bart_model", map_location=torch.device("cpu"))
optimizer = AdamW(model.parameters(),
lr = 2e-5,
eps = 1e-8
)
# split the input article to paragraphs in tmp csv format
data_test, formatted_input = split_article(input_article, input_trigger)
with open("./util/experiments/formatted_input.txt", "w") as f:
f.write(formatted_input)
seed_val = 42
random.seed(seed_val)
np.random.seed(seed_val)
torch.manual_seed(seed_val)
# torch.cuda.manual_seed_all(seed_val)
input_ids = []
attention_masks = []
for sent in data_test:
encoded_dict = tokenizer.encode_plus(
text_preprocessing(sent),
add_special_tokens = True,
max_length = 600,
pad_to_max_length = True,
return_attention_mask = True,
return_tensors = 'pt',
truncation=True
)
input_ids.append(encoded_dict['input_ids'])
attention_masks.append(encoded_dict['attention_mask'])
input_ids = torch.cat(input_ids, dim=0)
attention_masks = torch.cat(attention_masks, dim=0)
test_dataset = TensorDataset(input_ids, attention_masks)
test_dataloader = DataLoader(
test_dataset,
sampler = SequentialSampler(test_dataset),
batch_size = batch_size
)
# Predictions
predictions = []
for batch in test_dataloader:
b_input_ids = batch[0].to(device)
b_input_mask = batch[1].to(device)
with torch.no_grad():
output= model(b_input_ids,
attention_mask=b_input_mask)
logits = output.logits
logits = logits.detach().cpu().numpy()
pred_flat = np.argmax(logits, axis=1).flatten()
predictions.extend(list(pred_flat))
# Write predictions for each paragraph
df_output = pd.DataFrame({"target": predictions}).to_csv('./util/experiments/classification.csv', index=False)
if len(data_test)==1: predictions[0] = 1
# extract ids for update-needed paragraphs (extract the idx with predicted target == 1)
pos_ids = [idx for idx in range(len(predictions)) if predictions[idx]==1]
neg_ids = [idx for idx in range(len(predictions)) if predictions[idx]==0]
# feed the positive paragraphs to decoder
paragraphs_needed = [data_test[idx] for idx in pos_ids]
paragraphs_needed = [par.split(" -- ")[0].replace("[ADD]", "") for par in paragraphs_needed]
pd.DataFrame({"paragraph": paragraphs_needed}).to_csv("./util/experiments/paragraphs_needed.csv", index=False)
paragraphs_needed_str = "\n\n".join(paragraphs_needed)
# paragraphs_needed_str = paragraphs_needed_str.replace("Updated Paragraph:\n", "")
with open("./util/experiments/paragraphs_needed.txt", "w") as f:
f.write(paragraphs_needed_str)
# updated_paragraphs = decode(input_paragraph, input_trigger)
# updated_paragraphs = call_vicuna(paragraphs_needed, input_trigger)
config()
updated_paragraphs = [call_gpt(paragraph, input_trigger) for paragraph in paragraphs_needed]
updated_paragraphs_str = "\n\n".join(updated_paragraphs)
updated_paragraphs_str = updated_paragraphs_str.replace("Updated Paragraph:\n", "")
with open("./util/experiments/updated_paragraphs.txt", "w") as f:
f.write(updated_paragraphs_str)
# merge updated paragraphs with non-updated paragraphs
paragraphs_merged = data_test.copy()
paragraphs_merged = [str(par).split(" -- ")[0] for par in paragraphs_merged]
for idx in range(len(pos_ids)):
paragraphs_merged[pos_ids[idx]] = updated_paragraphs[idx]
sep = "\n"
# paragarphs_merged = ["".join(par.split(" -- ")[:-1]) for par in paragraphs_merged]
updated_article = str(sep.join(paragraphs_merged))
updated_article = updated_article.replace("[{'summary_text': '", "").replace("'}]", "").strip()
class_res = pd.read_csv("./util/experiments/classification.csv")
if class_res.target.values.all() == 0: modified="False"
if len(data_test)==1:
modified="TRUE"
updated_article = call_gpt(input_article, input_trigger)
with open("./util/experiments/updated_article.txt", "w") as f:
f.write(updated_article)
# combine the predictions and paragraphs into csv format file
merged_par_pred_df = pd.DataFrame({"paragraphs": data_test, "predictions": predictions}).to_csv("./util/experiments/par_with_class.csv")
modified_in_all = str(len(paragraphs_needed)) + " / " + str(len(data_test))
return updated_article, modified_in_all
def copy_to_clipboard(t):
with open("./util/experiments/updated_article.txt", "r") as f:
t = f.read()
pyperclip.copy(t)
def compare_versions():
with open("./util/experiments/paragraphs_needed.txt", "r") as f:
old = f.read()
old = old.replace("[ADD]", "")
with open("./util/experiments/updated_paragraphs.txt", "r") as f:
new = f.read()
new = new.replace("[ADD]", "")
return old, new
with open("./examples/non_update.txt", "r") as f:
exin_1 = f.read()
with open("./examples/trigger.txt", "r") as f:
trigger_1 = f.read()
with open("./examples/non_update_2.txt", "r") as f:
exin_2 = f.read()
with open("./examples/trigger_2.txt", "r") as f:
trigger_2 = f.read()
with gr.Blocks() as demo:
gr.HTML("""<div style="text-align: center; max-width: 700px; margin: 0 auto;">
<div
style="
display: inline-flex;
align-items: center;
gap: 0.8rem;
font-size: 1.75rem;
"
>
<h1 style="font-weight: 900; margin-bottom: 7px; margin-top: 5px;">
Event Triggered Article Updating System
</h1>
</div>"""
)
with gr.Tab("Article Updating"):
input_1 = gr.Textbox(label="Non-updated Article", lines=2, placeholder="Input the contexts...")
input_2 = gr.Textbox(label="Triggered News Event", lines=1, placeholder="Input the triggered news event...")
btn = gr.Button(value="Submit")
with gr.Row():
output_1 = gr.Textbox(label="Updated Article", lines=5)
output_2 = gr.Textbox(label="#MODIFIED / #ALL")
btn.click(fn=main, inputs=[input_1, input_2], outputs=[output_1, output_2])
btn_copy = gr.Button(value="Copy Updated Article to Clipboard")
btn_copy.click(fn=copy_to_clipboard, inputs=[output_1], outputs=[])
gr.Markdown("## Input Examples")
gr.Markdown("### There are 2 examples below, click them to test inputs automatically!")
gr.Examples(
examples=[[exin_1, trigger_1], [exin_2, trigger_2]],
fn=main,
inputs=[input_1, input_2],
outputs=[output_1, output_2],
# cache_examples=True,
# run_on_click=True,
),
com_1_value, com_2_value = "Pls finish article updating, then click the button above", "Pls finish article updating, then click the button above."
with gr.Tab("Compare between versions"):
btn_com = gr.Button(value="Differences Highlighting")
with gr.Row():
com_1 = gr.Textbox(label="Non-update Article", value=com_1_value, lines=15)
com_2 = gr.Textbox(label="Updated Article", value=com_2_value, lines=15)
btn_com.click(fn=compare_versions, inputs=[], outputs=[com_1, com_2])
gr.HTML("""
<div align="center">
<p>
Demo by 🤗 <a href="https://github.com/thequert" target="_blank"><b>Yu-Ting Lee</b></a>
</p>
</div>
<div align="center">
<p>
Supported by <a href="https://www.nccu.edu.tw/"><b>National Chengchi University</a></b> & <a href="https://www.sinica.edu.tw/"><b>Academia Sinica</b></a>
</p>
</div>
"""
)
demo.launch()
|