import streamlit as st import tempfile from pathlib import Path import base64 import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), "./src")) from verificaUD import verificaUD print("Verifica-UD running") translations = { '🇧🇷': { 'title': 'Verifica-UD', 'subtitle': 'Um verificador de textos de Português Brasileiro anotados segundo as diretrizes das Universal Dependencies', 'input_label': 'Escolha um arquivo .conllu de até 200MB para iniciar a verificação', 'buscando': 'Buscando', 'intro': 'O Verifica-UD faz uma verificação estrutural, léxica e sintática da anotação de textos do Português brasileiro, seguindo o modelo das Universal Dependencies. O Verifica-UD foi desenvolvido dentro do projeto POeTiSA.', 'to_cite': 'Clique aqui para citar o Verifica-UD', 'not_conllu': 'Este arquivo não está no formato correto.', 'no_file': '... à espera de um arquivo .conllu', 'file_uploaded': 'Arquivo recebido corretamente', 'download': 'Baixe o relatório completo.', 'file_name': 'Nome do arquivo', 'sentences': 'Número total de sentenças', 'err': 'erros', 'wrn': 'avisos', 'errFound': 'Erros encontrados', 'wrnFound': 'Avisos emitidos sobre possíveis erros', 'structural': 'estrutural(is)', 'lexical': 'lexical(is)', 'sintatical': 'sintático(s)', 'sentencesOk': 'Número de sentenças sem erros', 'sentencesClean': 'Número de sentenças sem erros ou avisos', 'struct_err': 'Erros estruturais', 'struct_wrn': 'Avisos estruturais', 'tagger_err': 'Erros léxicais', 'tagger_wrn': 'Avisos lexicais', 'parser_err': 'Erros sintáticos', 'parser_wrn': 'Avisos sintáticos', 'options': 'Escolha o tipo de verificação', 'struct': 'Apenas verificação estrutural', 'tagger': 'Verificação estrutural e lexical', 'parser': 'Verificação estrutural, lexical e sintática', 'result': 'Sumário de resultados', 'list_er_wr': 'Mensagens de erros e avisos em ordem de ID da sentença no arquivo', 'congrats': 'Nenhum erro ou aviso encontrado!', 'dev': 'Desenvolvido por' }, '🇺🇸': { 'title': 'Verifica-UD', 'subtitle': 'A verifier for Universal Dependencies annotation in Brazilian Portuguese', 'input_label': 'Entre um arquivo .conllu para verificar:', 'buscando': 'Buscando', 'intro': 'Verifica-UD faz uma verificação estrutural, léxica e morfosintática para anotação de textos em Português brasileiro, seguindo o modelo internacional do Universal Dependencies. Verifica-UD faz parte do projeto POeTiSA.', 'to_cite': 'Para citar o Verifica-UD', 'not_conllu': 'Este arquivo não está no formato correto.', 'no_file': 'Entre o nome de um arquivo .conllu', 'file_uploaded': 'File uploaded successfully', 'download': 'Baixe o relatório completo.', 'file_name': 'Nome do arquivo', 'sentences': 'Número total de sentenças', 'err': 'erros', 'wrn': 'avisos', 'errFound': 'Erros encontrados:', 'wrnFound': 'Avisos emitidos sobre possíveis erros:', 'structural': 'estruturais', 'lexical': 'lexicais', 'sintatical': 'sintáticos/morfosintáticos', 'sentencesOk': 'Número de sentenças sem erros', 'sentencesClean': 'Número de sentenças sem erros ou avisos', 'struct_err': 'Erros estruturais', 'struct_wrn': 'Avisos estruturais', 'tagger_err': 'Erros léxicais', 'tagger_wrn': 'Avisos lexicais', 'parser_err': 'Erros sintáticos', 'parser_wrn': 'Avisos sintáticos', 'options': 'Escolha o tipo de verificação', 'struct': 'Apenas verificação estrutural', 'tagger': 'Verificação estrutural e lexical', 'parser': 'Verificação estrutural, lexical e sintática', 'result': 'Sumário de resultados', 'list_er_wr': 'Erros e avisos encontrados', 'congrats': 'Nenhum erro ou aviso encontrado!', 'dev': 'Developed by' }, '🇫🇷': { 'title': 'Verifica-UD', 'subtitle': 'Um verificador de arquivos .conllu para textos anotados em Português Brasileiro', 'input_label': 'Entre um arquivo .conllu para verificar:', 'buscando': 'Buscando', 'intro': 'Verifica-UD faz uma verificação estrutural, léxica e morfosintática para anotação de textos em Português brasileiro, seguindo o modelo internacional do Universal Dependencies. Verifica-UD faz parte do projeto POeTiSA.', 'to_cite': 'Para citar o Verifica-UD', 'not_conllu': 'Este arquivo não está no formato correto.', 'no_file': 'Entre o nome de um arquivo .conllu', 'file_uploaded': 'Arquivo recebido corretamente', 'download': 'Baixe o relatório completo.', 'file_name': 'Nome do arquivo', 'sentences': 'Número total de sentenças', 'err': 'erros', 'wrn': 'avisos', 'errFound': 'Erros encontrados:', 'wrnFound': 'Avisos emitidos sobre possíveis erros:', 'structural': 'estruturais', 'lexical': 'lexicais', 'sintatical': 'sintáticos/morfosintáticos', 'sentencesOk': 'Número de sentenças sem erros', 'sentencesClean': 'Número de sentenças sem erros ou avisos', 'struct_err': 'Erros estruturais', 'struct_wrn': 'Avisos estruturais', 'tagger_err': 'Erros léxicais', 'tagger_wrn': 'Avisos lexicais', 'parser_err': 'Erros sintáticos', 'parser_wrn': 'Avisos sintáticos', 'options': 'Escolha o tipo de verificação', 'struct': 'Só verificação estrutural', 'tagger': 'Verificação estrutural e lexical', 'parser': 'Verificação estrutural, lexical e sintática', 'result': 'Sumário de resultados', 'list_er_wr': 'Erros e avisos encontrados', 'congrats': 'Nenhum erro ou aviso encontrado!', 'dev': 'Développé par' }, '🇮🇹': { 'title': 'Verifica-UD', 'subtitle': 'Um verificador de arquivos .conllu para textos anotados em Português Brasileiro', 'input_label': 'Entre um arquivo .conllu para verificar:', 'buscando': 'Buscando', 'intro': 'Verifica-UD faz uma verificação estrutural, léxica e morfosintática para anotação de textos em Português brasileiro, seguindo o modelo internacional do Universal Dependencies. Verifica-UD faz parte do projeto POeTiSA.', 'to_cite': 'Para citar o Verifica-UD', 'not_conllu': 'Este arquivo não está no formato correto.', 'no_file': 'Entre o nome de um arquivo .conllu', 'file_uploaded': 'Arquivo recebido corretamente', 'download': 'Baixe o relatório completo.', 'file_name': 'Nome do arquivo', 'sentences': 'Número total de sentenças', 'err': 'erros', 'wrn': 'avisos', 'errFound': 'Erros encontrados:', 'wrnFound': 'Avisos emitidos sobre possíveis erros:', 'structural': 'estruturais', 'lexical': 'lexicais', 'sintatical': 'sintáticos/morfosintáticos', 'sentencesOk': 'Número de sentenças sem erros', 'sentencesClean': 'Número de sentenças sem erros ou avisos', 'struct_err': 'Erros estruturais', 'struct_wrn': 'Avisos estruturais', 'tagger_err': 'Erros lexicais', 'tagger_wrn': 'Avisos lexicais', 'parser_err': 'Erros sintáticos', 'parser_wrn': 'Avisos sintáticos', 'options': 'Escolha o tipo de verificação', 'struct': 'Apenas verificação estrutural', 'tagger': 'Verificação estrutural e lexical', 'parser': 'Verificação estrutural, lexical e sintática', 'result': 'Sumário de resultados', 'list_er_wr': 'Erros e avisos encontrados', 'congrats': 'Nenhum erro ou aviso encontrado!', 'dev': 'Sviluppato da' }, '🇪🇸': { 'title': 'Verifica-UD', 'subtitle': 'Um verificador de arquivos .conllu para textos anotados em Português Brasileiro', 'input_label': 'Entre um arquivo .conllu para verificar:', 'buscando': 'Buscando', 'intro': 'Verifica-UD faz uma verificação estrutural, léxica e morfosintática para anotação de textos em Português brasileiro, seguindo o modelo internacional do Universal Dependencies. Verifica-UD faz parte do projeto POeTiSA.', 'to_cite': 'Para citar o Verifica-UD', 'not_conllu': 'Este arquivo não está no formato correto.', 'no_file': 'Entre o nome de um arquivo .conllu', 'file_uploaded': 'Arquivo recebido corretamente', 'download': 'Baixe o relatório completo.', 'file_name': 'Nome do arquivo', 'sentences': 'Número total de sentenças', 'err': 'erros', 'wrn': 'avisos', 'errFound': 'Erros encontrados:', 'wrnFound': 'Avisos emitidos sobre possíveis erros:', 'structural': 'estruturais', 'lexical': 'lexicais', 'sintatical': 'sintáticos/morfosintáticos', 'sentencesOk': 'Número de sentenças sem erros', 'sentencesClean': 'Número de sentenças sem erros ou avisos', 'struct_err': 'Erros estruturais', 'struct_wrn': 'Avisos estruturais', 'tagger_err': 'Erros léxicais', 'tagger_wrn': 'Avisos lexicais', 'parser_err': 'Erros sintáticos', 'parser_wrn': 'Avisos sintáticos', 'options': 'Escolha o tipo de verificação', 'struct': 'Apenas verificação estrutural', 'tagger': 'Verificação estrutural e lexical', 'parser': 'Verificação estrutural, lexical e sintática', 'result': 'Sumário de resultados', 'list_er_wr': 'Erros e avisos encontrados', 'congrats': 'Nenhum erro ou aviso encontrado!', 'dev': 'Desarrollado por' } } def img_to_bytes(img_path): img_bytes = Path(img_path).read_bytes() encoded = base64.b64encode(img_bytes).decode() return encoded def img_to_html(img_path, img_style='max-width: 100%;'): img_html = f"" return img_html st.markdown(""" """, unsafe_allow_html=True) st.set_page_config( page_title="Verifica-UD", layout="centered", initial_sidebar_state="collapsed" ) # language sidebar lang_options = { "🇧🇷 Português": "🇧🇷", "🇺🇸 English": "🇺🇸", "🇫🇷 Français": "🇫🇷", "🇮🇹 Italiano": "🇮🇹", "🇪🇸 Español": "🇪🇸" } selected = st.sidebar.radio("🌐 Interface", list(lang_options.keys())) t = translations[lang_options[selected]] # choices sidebar verif_options = { t['parser']: "p", t['tagger']: "t", t['struct']: "s" } v_selected = st.sidebar.radio(t['options'], list(verif_options.keys())) t_struct, t_tagger, t_parser = True, True, True if (v_selected == 's'): t_struct, t_tagger, t_parser = True, False, False elif (v_selected == 't'): t_struct, t_tagger, t_parser = True, True, False elif (v_selected == 'p'): t_struct, t_tagger, t_parser = True, True, True # Streamlit app title st.markdown(f"

{t['title']}

", unsafe_allow_html=True) #st.title(t["title"]) st.markdown("
"+t["subtitle"]+"

", unsafe_allow_html=True) # introduction #st.write(t["intro"]+"

", unsafe_allow_html=True) logo_html = img_to_html("./img/verificaUD.png", img_style="width:120px; margin-right:20px; margin-top:-10px;") intro_combined = f"""
{logo_html}
{t['intro']}

""" st.markdown(intro_combined, unsafe_allow_html=True) # --- File Upload --- uploaded_file = st.file_uploader(t['input_label'], type=None) # --- Run Button --- if uploaded_file: st.success("✅ "+t['file_uploaded']) # Save to a temporary file with tempfile.NamedTemporaryFile(delete=False) as tmp_file: tmp_file.write(uploaded_file.read()) tmp_path = tmp_file.name rep_path = tmp_file.name+".rep.txt" # --- Call Verifica-UD Function --- def process_file(file_path, rep_path, t_struct, t_tagger, t_parser): if (t_parser): mode = "p" elif (t_tagger): mode = "t" elif (t_struct): mode = "s" else: mode = "p" verificaUD(file_path, rep_path, mode) with open(rep_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() lines = content.split("\n") conlluName = lines[0][9:] bits = lines[2].split() sentNumber = bits[1] toknNumber = bits[3][:-1] bits = lines[3].split() sentNoErro = bits[3] bits = lines[4].split() sentNoErWr = bits[5] bits = lines[5].split() struct_err = bits[2] struct_wrn = bits[5] bits = lines[6].split() tagger_err = bits[2] tagger_wrn = bits[5] bits = lines[7].split() parser_err = bits[2] parser_wrn = bits[5] result = { "conlluName": conlluName, "sentNumber": sentNumber, "toknNumber": toknNumber, "sentNoErro": sentNoErro, "sentNoErWr": sentNoErWr, "struct_err": struct_err, "struct_wrn": struct_wrn, "tagger_err": tagger_err, "tagger_wrn": tagger_wrn, "parser_err": parser_err, "parser_wrn": parser_wrn, "list_er_wr": "\n".join(map(str, lines[10:])), "toggles": [t_struct, t_tagger, t_parser] } return result, content.replace(file_path, uploaded_file.name) output, content = process_file(tmp_path, rep_path, t_struct, t_tagger, t_parser) # --- Display Output --- st.subheader(t['result']) total_err = int(output['struct_err'])+int(output['tagger_err'])+int(output['parser_err']) total_wrn = int(output['struct_wrn'])+int(output['tagger_wrn'])+int(output['parser_wrn']) st.write(f"{t['sentences']}: {output['sentNumber']} ({output['toknNumber']} tokens)") st.write(f"{t['errFound']}: ({output['struct_err']} {t['structural']}, {output['tagger_err']} {t['lexical']}, {output['parser_err']} {t['sintatical']})") st.write(f"{t['wrnFound']}: ({output['struct_wrn']} {t['structural']}, {output['tagger_wrn']} {t['lexical']}, {output['parser_wrn']} {t['sintatical']})") # Build the table rows dynamically rows = [] if t_struct: rows.extend([ f"{t['struct_err']}{output['struct_err']} tokens{t['struct_wrn']}{output['struct_wrn']} tokens"]) if t_tagger: rows.extend([ f"{t['tagger_err']}{output['tagger_err']} tokens{t['tagger_wrn']}{output['tagger_wrn']} tokens"]) if t_parser: rows.extend([ f"{t['parser_err']}{output['parser_err']} tokens{t['parser_wrn']}{output['parser_wrn']} tokens"]) # Combine rows into a full table table_html = f""" {''.join(rows)}
{output["sentNoErro"]} ({t["sentencesOk"]}){output["sentNoErWr"]} ({t["sentencesClean"]})
""" # Display the table st.markdown(table_html, unsafe_allow_html=True) if (total_err+total_wrn > 0): # --- Display errors and warnings text area --- st.write(t['list_er_wr']) #rawText = st.text_area(t['list_er_wr']+f'({total_err} {t["err"]} - {total_wrn} {t["wrn"]}):\n', output["list_er_wr"], height=300) colors = ["#16793C", "#14874E", "#1A49B7", "#504AA4"] lines = output["list_er_wr"].strip().split("\n") html_lines = [] for line in lines: fields = line.split("\t") styled_fields = [] styled_fields.append(f'{fields[0]}') styled_fields.append(f'{fields[1]}') position = fields[2].index(":") code_msg = [fields[2][:position], fields[2][position+1:]] #code_msg = fields[2].split(": ") styled_fields.append(f'{code_msg[0]}:') styled_fields.append(f'{code_msg[1]}
') html_lines.append(" ".join(styled_fields)) # Combine into scrollable box styled_html = f"""
{''.join(html_lines)}
""" st.markdown(styled_html, unsafe_allow_html=True) # --- Download Option --- #st.download_button(label=t['download'], # data=content, # file_name=uploaded_file.name.replace(".conllu",".rep.txt"), # mime="text/plain") with st.container(): st.markdown('
', unsafe_allow_html=True) st.download_button( label="📥 "+t['download'], data=content, file_name=uploaded_file.name.replace(".conllu",".rep.txt"), mime="text/plain", key="download_report") st.markdown('
', unsafe_allow_html=True) else: st.write(f"{t['congrats']}") # Clean up temp file os.remove(tmp_path) else: st.info(t['no_file']) # To cite expander st.write("
", unsafe_allow_html=True) with st.expander(t["to_cite"], expanded=False): st.markdown( """ LOPES, L.; DURAN, M. S.; PARDO, T. A. S. Verifica UD - A verifier for Universal Dependencies annotation in Portuguese. In: Proc. of the UDFest-BR 2023, 2023. DOI: https://doi.org/10.5753/stil.2023.25485
Links: URL - DOI
BibTeX:
""", unsafe_allow_html=True) st.code(""" @inproceedings{Lopes2023VerificaUD, author = 'LOPES, L. and DURAN, M. S. and PARDO, T. A. S.', title = 'Verifica UD - A verifier for Universal Dependencies annotation in Portuguese', booktitle = 'Proc. of the UDFest-BR 2023', series = 'UDFest-BR', year = 2023, pages = '1-8', url = 'https://sol.sbc.org.br/index.php/stil/article/view/25485', }""") st.write("
", unsafe_allow_html=True) # Footer / Footnote with st.container(): logorow1 = st.columns([3,4,1,4,1,4,3]) with logorow1[1]: st.markdown(""+img_to_html('./img/icmc.png')+"",unsafe_allow_html=True) with logorow1[3]: st.markdown(""+img_to_html('./img/c4ia.png')+"",unsafe_allow_html=True) with logorow1[5]: st.markdown(""+img_to_html('./img/nilc-removebg.png','max-width:80%')+"",unsafe_allow_html=True) logorow2 = st.columns([1,4,1,4,1,5,1,4,1]) with logorow2[1]: st.markdown(""+img_to_html('./img/inova_nobackground.png')+"",unsafe_allow_html=True) with logorow2[3]: st.markdown("" + img_to_html('./img/softex_nobackground.png') + "",unsafe_allow_html=True) with logorow2[5]: st.markdown("" + img_to_html('./img/mcti_nobackground.png') + "",unsafe_allow_html=True) with logorow2[7]: st.markdown(""+img_to_html('./img/motorola_nobackground.png', 'max-width:70%; object-position: center bottom')+"",unsafe_allow_html=True) creditrow = st.columns([3,18,3]) with creditrow[1]: st.markdown('

'+t["dev"]+' Lucelene Lopes\ \ \
open source License: MIT

',unsafe_allow_html=True)