import os import gradio as gr import wget from ftlangdetect import detect from cleantext import clean from keybert import KeyBERT from keyphrase_vectorizers import KeyphraseCountVectorizer from functools import partial # models sentence-bert multilingual # fonte SBERT: https://www.sbert.net/docs/pretrained_models.html#multi-lingual-models # models na Hugging Face model hub (https://huggingface.co/sentence-transformers/...) model_id = ["paraphrase-multilingual-MiniLM-L12-v2", "sentence-transformers/LaBSE", "distiluse-base-multilingual-cased-v1"] model_name = ["SBERT multilingual", "LaBSE", "DistilBERT mltilingual (v1)"] kw_model_0 = KeyBERT(model=model_id[0]) kw_model_1 = KeyBERT(model=model_id[1]) kw_model_2 = KeyBERT(model=model_id[2]) kw_model = { 0: kw_model_0, 1: kw_model_1, 2: kw_model_2 } ## KeyphraseVectorizers # source: https://github.com/TimSchopf/KeyphraseVectorizers#keyphrasevectorizers download spacy pipeline (https://spacy.io/models/pt) source: https://melaniewalsh.github.io/Intro-Cultural-Analytics/05-Text-Analysis/Multilingual/Portuguese/03-POS-Keywords-Portuguese.html os.system("python -m spacy download pt_core_news_lg") # Part-of-Speech Tagging for Portuguese (https://melaniewalsh.github.io/Intro-Cultural-Analytics/05-Text-Analysis/Multilingual/Portuguese/03-POS-Keywords-Portuguese.html) pos_pattern='*****+' # download stop words in Portuguese #import nltk #nltk.download('stopwords') #from nltk.corpus import stopwords #stop_words = set(stopwords.words('portuguese')) # define o vectorizer vectorizer = KeyphraseCountVectorizer(spacy_pipeline='pt_core_news_lg', pos_pattern=pos_pattern, stop_words=None, lowercase=False) # function principal (keywords) def get_kw_html(model_id, doc, top_n, diversity): # detect lang res = detect(text=doc, low_memory=False) lang = res["lang"] score = res["score"] if len(doc) == 0: # get keywords and highlighted text keywords, keywords_json = [("",0.)], {"":0.} html_doc = '

' label = "O texto do documento não pode estar vazio. Recomece, por favor." elif lang!="pt" or score<0.9: # get keywords and highlighted text keywords, keywords_json = [("",0.)], {"":0.} html_doc = '

' label = "O APP não tem certeza de que o texto do documento está em português. Recomece com um texto em português, por favor." else: # keywords def get_kw(kw_model=kw_model[model_id], doc=doc, top_n=top_n, diversity=diversity): keywords = kw_model.extract_keywords(doc, vectorizer=vectorizer, use_mmr=True, diversity=diversity, top_n=top_n, ) keywords_json = {item[0]:item[1] for item in keywords} return keywords, keywords_json # highlight def get_html(keywords, doc=doc): # ordering of lists (from longest keywords to shortest ones) list3 = [keyword[0] for keyword in keywords] list2 = [len(item.split()) for item in list3] list1 = list(range(len(list2))) list2, list1 = (list(t) for t in zip(*sorted(zip(list2, list1)))) list1 = list1[::-1] keywords_list = [list3[idx] for idx in list1] # converting doc to html format html_doc = doc for idx,keyword in enumerate(keywords_list): if sum([True if keyword in item else False for item in keywords_list[:idx]]) == 0: if keyword not in '' and keyword not in '': html_doc = html_doc.replace(keyword, '' + keyword + '') html_doc = '

' + html_doc + '

' return html_doc # function to clean text of document doc = clean(doc, fix_unicode=True, # fix various unicode errors to_ascii=False, # transliterate to closest ASCII representation lower=False, # lowercase text no_line_breaks=True, # fully strip line breaks as opposed to only normalizing them no_urls=False, # replace all URLs with a special token no_emails=False, # replace all email addresses with a special token no_phone_numbers=False, # replace all phone numbers with a special token no_numbers=False, # replace all numbers with a special token no_digits=False, # replace all digits with a special token no_currency_symbols=False, # replace all currency symbols with a special token no_punct=False, # remove punctuations replace_with_punct="", # instead of removing punctuations you may replace them replace_with_url="", replace_with_email="", replace_with_phone_number="", replace_with_number="", replace_with_digit="0", replace_with_currency_symbol="", lang="pt" # set to 'de' for German special handling ) # get keywords and highlighted text keywords, keywords_json = get_kw() html_doc = get_html(keywords) label = f"A palavra/frase chave com a maior probabilidade é: {keywords[0]}" return label, keywords_json, html_doc title = "Extração das key palavras/frases em português" description = '

(17/12/2022) Forneça seu próprio documento em português e o APP vai fazer a extração das palavras/frases chave com as maiores probabilidades de similardide ao texto.\
Segundo você, qual é o melhor modelo?

\

Este aplicativo usa os modelos seguintes:\
- SBERT multilingual,\
- sentence-transformers/LaBSE,\
- KeyphraseVectorizers para definir o vetorizador que extrai palavras/frases chave com padrões de parte do texto de um documento.\
- KeyBERT para calcular as similaridades entre as palavras/frases chave e o texto do documento.

' doc_original = """ As contas de pelo menos seis jornalistas norte-americanos que cobrem tecnologia foram suspensas pelo Twitter na noite desta quinta-feira (15). Os profissionais escrevem sobre o tema para diversos veículos de comunicação dos Estados Unidos, como os jornais 'The New York Times' e 'Washington Post'. A rede social afirmou apenas que suspende contas que violam as regras, mas não deu mais detalhes sobre os bloqueios. Assim que comprou o Twitter, Elon Musk disse defender a liberdade de expressão, e reativou, inclusive, a conta do ex-presidente Donald Trump, suspensa desde o ataque ao Capitólio, em 2021. Os jornalistas que tiveram as contas bloqueadas questionaram o compromisso de Musk com a liberdade de expressão. Eles encararam o bloqueio como uma retaliação de Musk às críticas que o bilionário vem recebendo pela forma como está conduzindo a rede social: com demissões em massa e o desmonte de áreas, como o conselho de confiança e segurança da empresa. Metade dos funcionários do Twitter foram demitidos desde que ele assumiu o comando da empresa e outros mil pediram demissão. """ examples = [ [doc_original.strip()], ] interface_0 = gr.Interface( fn=partial(get_kw_html, 0), inputs=[ gr.Textbox(lines=15, label="Texto do documento"), gr.Slider(1, 20, value=5, label="Número das palavras/frases chave a procurar (padrão: 5)"), gr.Slider(0, 1, value=0.2, label="Diversidade entre as palavras/frases chave encontrados (0: mínimo - 1: máximo - padrão: 0,2)") ], outputs=[ gr.Textbox(label=f"{model_name[0]}"), gr.Label(show_label=False), gr.HTML(), ] ) interface_1 = gr.Interface( fn=partial(get_kw_html, 1), inputs=[ gr.Textbox(lines=15, label="Texto do documento"), gr.Slider(1, 20, value=5, label="Número das palavras/frases chave a procurar (padrão: 5)"), gr.Slider(0, 1, value=0.2, label="Diversidade entre as palavras/frases chave encontrados (0: mínimo - 1: máximo - padrão: 0,2)") ], outputs=[ gr.Textbox(label=f"{model_name[1]}"), gr.Label(show_label=False), gr.HTML(), ] ) interface_2 = gr.Interface( fn=partial(get_kw_html, 2), inputs=[ gr.Textbox(lines=15, label="Texto do documento"), gr.Slider(1, 20, value=5, label="Número das palavras/frases chave a procurar (padrão: 5)"), gr.Slider(0, 1, value=0.2, label="Diversidade entre as palavras/frases chave encontrados (0: mínimo - 1: máximo - padrão: 0,2)") ], outputs=[ gr.Textbox(label=f"{model_name[2]}"), gr.Label(show_label=False), gr.HTML(), ] ) demo = gr.Parallel(interface_0, interface_1, interface_2, title=title, description=description, examples=examples, allow_flagging="never") if __name__ == "__main__": demo.launch()