Spaces:
Runtime error
Runtime error
File size: 9,448 Bytes
ea671ec 95c27da ea671ec 0dcb9c1 ea671ec 0dcb9c1 ea671ec 534e7c2 98c9cb7 6c7d186 a1a8a38 faa980b 6c7d186 faa980b 6c7d186 faa980b 6c7d186 faa980b 6c7d186 faa980b 6c7d186 a1a8a38 534e7c2 ea671ec f85d964 f428771 ea671ec b65fa80 c592fd8 d744032 ea671ec aa8acbb de47955 ea671ec |
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 |
import gradio as gr
import transformers
from transformers import AutoModelForTokenClassification, AutoTokenizer
import torch
# model large
model_name = "pierreguillou/ner-bert-large-cased-pt-lenerbr"
model_large = AutoModelForTokenClassification.from_pretrained(model_name)
tokenizer_large = AutoTokenizer.from_pretrained(model_name)
# model base
model_name = "pierreguillou/ner-bert-base-cased-pt-lenerbr"
model_base = AutoModelForTokenClassification.from_pretrained(model_name)
tokenizer_base = AutoTokenizer.from_pretrained(model_name)
# css
background_colors_entity_word = {
'JURISPRUDENCIA': "#ccfbf1",
'LEGISLACAO': "#ede9fe",
'LOCAL': "#ffedd5",
'ORGANIZACAO': "#fae8ff",
'PESSOA': "#e0f2fe",
'TEMPO': "#fefde0",
}
background_colors_entity_tag = {
'JURISPRUDENCIA': "#14b8a6",
'LEGISLACAO': "#8b5cf6",
'LOCAL': "#f97316",
'ORGANIZACAO': "#d946ef",
'PESSOA': "#0ea5e9",
'TEMPO': "#e9c70e",
}
css = {
'entity_word': 'color:#000000;background: #xxxxxx; padding: 0.45em 0.6em; margin: 0 0.25em; line-height: 2.5; border-radius: 0.35em;',
'entity_tag': 'color:#fff;background: #xxxxxx; font-size: 0.8em; font-weight: bold; line-height: 2.5; border-radius: 0.35em; text-transform: uppercase; vertical-align: middle; margin-left: 0.5em;'
}
list_EN = "<span style='"
list_EN += f"{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['JURISPRUDENCIA'])};padding:0.5em;"
list_EN += "'>JURISPRUDENCIA</span>"
list_EN += "<span style='"
list_EN += f"{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['LEGISLACAO'])};padding:0.5em;"
list_EN += "'>LEGISLACAO</span>"
list_EN += "<span style='"
list_EN += f"{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['LOCAL'])};padding:0.5em;"
list_EN += "'>LOCAL</span>"
list_EN += "<span style='"
list_EN += f"{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['ORGANIZACAO'])};padding:0.5em;"
list_EN += "'>ORGANIZACAO</span>"
list_EN += "<span style='"
list_EN += f"{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['PESSOA'])};padding:0.5em;"
list_EN += "'>PESSOA</span>"
list_EN += "<span style='"
list_EN += f"{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['TEMPO'])};padding:0.5em;"
list_EN += "'>TEMPO</span>"
# list_EN += | <span style='{css['entity_tag'].replace('#xxxxxx',background_colors_entity_tag['LEGISLACAO'])}">LEGISLACAO</span>"
# infos
title = "LeNER-Br | NER App"
description = "(24/12/2021) Este aplicativo NER permite comparar 2 modelos de BERT ajustados (finetuned) na tarefa NER com o dataset jurídico LeNER-Br (NER BERT base com f1 de 0.893 e NER BERT large com f1 de 0.908). O download desses 2 modelos pode demorar alguns segundos."
article = f"<div style='text-align: center; font-size: 90%;'><p>Lista das Entidades Nomeadas (EN): {list_EN}</p><p>Links para os modelos BERT NER: <a style='color:blue;' href='https://huggingface.co/pierreguillou/ner-bert-base-cased-pt-lenerbr' target='_blank'>base</a> e <a style='color:blue;' href='https://huggingface.co/pierreguillou/ner-bert-large-cased-pt-lenerbr' target='_blank'>large</a></p><p>Blog post: <a style='color:blue;' href='https://medium.com/@pierre_guillou/nlp-modelos-e-web-app-para-reconhecimento-de-entidade-nomeada-ner-no-dom%C3%ADnio-jur%C3%ADdico-b658db55edfb' target='_blank'>NLP | Modelos e Web App para Reconhecimento de Entidade Nomeada (NER) no domínio jurídico brasileiro</a> (29/12/2021)</p><p>LeNER-Br NER App by <a style='color:blue;' href='https://www.linkedin.com/in/pierreguillou/' target='_blank'>Pierre GUILLOU</a> | <a style='color:blue;' href='https://github.com/piegu/language-models#language-models' target='_blank'>Github Repo</a></p></div>"
allow_screenshot = False
allow_flagging = False
examples = [
["Ao Instituto Médico Legal da jurisdição do acidente ou da residência cumpre fornecer, no prazo de 90 dias, laudo à vítima (art. 5, § 5, Lei n. 6.194/74 de 19 de dezembro de 1974), função técnica que pode ser suprida por prova pericial realizada por ordem do juízo da causa, ou por prova técnica realizada no âmbito administrativo que se mostre coerente com os demais elementos de prova constante dos autos."],
["Acrescento que não há de se falar em violação do artigo 114, § 3º, da Constituição Federal, posto que referido dispositivo revela-se impertinente, tratando da possibilidade de ajuizamento de dissídio coletivo pelo Ministério Público do Trabalho nos casos de greve em atividade essencial."],
["Todavia, entendo que extrair da aludida norma o sentido expresso na redação acima implica desconstruir o significado do texto constitucional, o que é absolutamente vedado ao intérprete. Nesse sentido, cito Dimitri Dimoulis: ‘(...) ao intérprete não é dado escolher significados que não estejam abarcados pela moldura da norma. Interpretar não pode significar violentar a norma.’ (Positivismo Jurídico. São Paulo: Método, 2006, p. 220).59. Dessa forma, deve-se tomar o sentido etimológico como limite da atividade interpretativa, a qual não pode superado, a ponto de destruir a própria norma a ser interpretada. Ou, como diz Konrad Hesse, ‘o texto da norma é o limite insuperável da atividade interpretativa.’ (Elementos de Direito Constitucional da República Federal da Alemanha, Porto Alegre: Sergio Antonio Fabris, 2003, p. 71)."],
]
def ner(input_text):
num = 0
for tokenizer,model in zip([tokenizer_large,tokenizer_base],[model_large,model_base]):
# tokenization
inputs = tokenizer(input_text, max_length=512, truncation=True, return_tensors="pt")
tokens = inputs.tokens()
# get predictions
outputs = model(**inputs).logits
predictions = torch.argmax(outputs, dim=2)
preds = [model_base.config.id2label[prediction] for prediction in predictions[0].numpy()]
# variables
groups_pred = dict()
group_indices = list()
group_label = ''
pred_prec = ''
group_start = ''
count = 0
# group the NEs
for i,en in enumerate(preds):
if en == 'O':
if len(group_indices) > 0:
groups_pred[count] = {'indices':group_indices,'en':group_label}
group_indices = list()
group_label = ''
count += 1
if en.startswith('B'):
if len(group_indices) > 0:
groups_pred[count] = {'indices':group_indices,'en':group_label}
group_indices = list()
group_label = ''
count += 1
group_indices.append(i)
group_label = en.replace('B-','')
pred_prec = en
elif en.startswith('I'):
if len(group_indices) > 0:
if en.replace('I-','') == group_label:
group_indices.append(i)
else:
groups_pred[count] = {'indices':group_indices,'en':group_label}
group_indices = [i]
group_label = en.replace('I-','')
count += 1
else:
group_indices = [i]
group_label = en.replace('I-','')
if i == len(preds) - 1 and len(group_indices) > 0:
groups_pred[count] = {'indices':group_indices,'en':group_label}
group_indices = list()
group_label = ''
count += 1
# there is at least one NE
len_groups_pred = len(groups_pred)
inputs = inputs['input_ids'][0].numpy()#[1:-1]
if len_groups_pred > 0:
for pred_num in range(len_groups_pred):
en = groups_pred[pred_num]['en']
indices = groups_pred[pred_num]['indices']
if pred_num == 0:
if indices[0] > 0:
output = tokenizer.decode(inputs[:indices[0]]) + f'<span style="{css["entity_word"].replace("#xxxxxx",background_colors_entity_word[en])}">' + tokenizer.decode(inputs[indices[0]:indices[-1]+1]) + f'<span style="{css["entity_tag"].replace("#xxxxxx",background_colors_entity_tag[en])}">' + en + '</span></span> '
else:
output = f'<span style="{css["entity_word"].replace("#xxxxxx",background_colors_entity_word[en])}">' + tokenizer.decode(inputs[indices[0]:indices[-1]+1]) + f'<span style="{css["entity_tag"].replace("#xxxxxx",background_colors_entity_tag[en])}">' + en + '</span></span> '
else:
output += tokenizer.decode(inputs[indices_prev[-1]+1:indices[0]]) + f'<span style="{css["entity_word"].replace("#xxxxxx",background_colors_entity_word[en])}">' + tokenizer.decode(inputs[indices[0]:indices[-1]+1]) + f'<span style="{css["entity_tag"].replace("#xxxxxx",background_colors_entity_tag[en])}">' + en + '</span></span> '
indices_prev = indices
output += tokenizer.decode(inputs[indices_prev[-1]+1:])
else:
output = input_text
# output
output = output.replace('[CLS]','').replace(' [SEP]','').replace('##','')
output = "<div style='max-width:100%; max-height:360px; overflow:auto'>" + output + "</div>"
if num == 0:
output_large = output
num += 1
else: output_base = output
return output_large, output_base
# interface gradio
iface = gr.Interface(
title=title,
description=description,
article=article,
allow_screenshot=allow_screenshot,
allow_flagging=allow_flagging,
fn=ner,
inputs=gr.inputs.Textbox(placeholder="Digite uma frase aqui ou clique em um exemplo:", lines=5),
outputs=[gr.outputs.HTML(label="NER com BERT large"),gr.outputs.HTML(label="NER com BERT base")],
examples=examples
)
iface.launch() |