Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -29,7 +29,6 @@ try:
|
|
| 29 |
except:
|
| 30 |
nlp = spacy.blank("grc")
|
| 31 |
|
| 32 |
-
# Mapeamento de Classes Gramaticais
|
| 33 |
TAG_MAP = {
|
| 34 |
'NOUN': 'Substantivo', 'VERB': 'Verbo', 'ADJ': 'Adjetivo',
|
| 35 |
'DET': 'Artigo/Det.', 'PRON': 'Pronome', 'ADV': 'Advérbio',
|
|
@@ -50,9 +49,11 @@ FORMA_TO_LEMA = load_json('ddgp_forma_to_lema.json')
|
|
| 50 |
ENTRIES = load_json('ddgp3x_entry.json')
|
| 51 |
ABREV = load_json('abrev.json')
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
| 56 |
|
| 57 |
# --- 2. FUNÇÕES DE APOIO ---
|
| 58 |
|
|
@@ -63,21 +64,14 @@ def normalizar_grego(texto):
|
|
| 63 |
return unicodedata.normalize('NFC', texto).strip()
|
| 64 |
|
| 65 |
def aplicar_abreviaturas_seguro(texto):
|
| 66 |
-
"""Substitui abreviaturas apenas como palavras inteiras para evitar confusão."""
|
| 67 |
if not texto: return ""
|
| 68 |
-
|
| 69 |
-
# Ordenamos as abreviaturas das maiores para as menores
|
| 70 |
sorted_abrevs = sorted(ABREV.keys(), key=len, reverse=True)
|
| 71 |
-
|
| 72 |
for ab in sorted_abrevs:
|
| 73 |
-
# Escapa caracteres especiais (como ponto) para o Regex
|
| 74 |
pattern = r'\b' + re.escape(ab) + r'(?=\s|[.,;:]|$)'
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
classe_css = "autor-sc" if categoria == 'autor' else "abrev"
|
| 79 |
-
|
| 80 |
-
# Substituição com Tooltip
|
| 81 |
subst = f'<span class="{classe_css}" title="{desc}">{ab}</span>'
|
| 82 |
texto = re.sub(pattern, subst, texto)
|
| 83 |
return texto
|
|
@@ -87,7 +81,6 @@ def format_entry_html(entry_id):
|
|
| 87 |
if not entry: return None
|
| 88 |
gword = entry.get('gword', '')
|
| 89 |
pdesc = entry.get('pdesc', '')
|
| 90 |
-
|
| 91 |
pdesc = aplicar_abreviaturas_seguro(pdesc)
|
| 92 |
pdesc = re.sub(r'〈(.*?)〉', r'<span class="etimo">〈\1〉</span>', pdesc)
|
| 93 |
|
|
@@ -128,43 +121,41 @@ def consultar_ddgp(termo):
|
|
| 128 |
if res: html += res
|
| 129 |
return html
|
| 130 |
|
| 131 |
-
# Adicione esta variável global no topo do arquivo (abaixo dos imports)
|
| 132 |
-
CONSULTAS_CONTADOR = 0
|
| 133 |
-
|
| 134 |
def analisar_texto(texto):
|
| 135 |
-
global CONSULTAS_CONTADOR
|
| 136 |
if not texto: return None, None, "0", "0", "0", "0", "0", ""
|
| 137 |
-
|
| 138 |
-
CONSULTAS_CONTADOR += 1 # Incrementa o contador da sessão
|
| 139 |
doc = nlp(texto)
|
| 140 |
dados = []
|
| 141 |
-
|
| 142 |
-
|
|
|
|
| 143 |
|
| 144 |
for token in doc:
|
| 145 |
l_orig = token.lemma_
|
| 146 |
l_norm = normalizar_grego(l_orig)
|
| 147 |
pos_pt = TAG_MAP.get(token.pos_, token.pos_)
|
| 148 |
|
| 149 |
-
#
|
| 150 |
-
|
|
|
|
| 151 |
|
| 152 |
-
if token.pos_ not in ['PUNCT', 'SYM', 'SPACE'] and l_norm not in
|
| 153 |
-
|
| 154 |
-
if "não localizado" not in
|
| 155 |
-
|
| 156 |
-
|
| 157 |
|
| 158 |
dados.append({
|
| 159 |
'Palavra': token.text,
|
| 160 |
'Lema': l_orig,
|
| 161 |
'Classe': pos_pt,
|
| 162 |
-
'
|
| 163 |
})
|
| 164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
df = pd.DataFrame(dados)
|
| 166 |
-
|
| 167 |
-
# Cálculos Estatísticos
|
| 168 |
tokens_df = df[~df['Classe'].isin(['Pontuação', 'PUNCT', 'SYM', 'SPACE'])]
|
| 169 |
n_tokens = len(tokens_df)
|
| 170 |
n_types = tokens_df['Palavra'].str.lower().nunique()
|
|
@@ -184,9 +175,8 @@ def analisar_texto(texto):
|
|
| 184 |
with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
|
| 185 |
with gr.Row():
|
| 186 |
with gr.Column(scale=1, min_width=100):
|
| 187 |
-
# Inserção do logo via URL do GitHub (80px de altura)
|
| 188 |
gr.HTML("""
|
| 189 |
-
<div style="display: flex; align-items: center; justify-content:
|
| 190 |
<img src="https://raw.githubusercontent.com/aniseferreira/DDGP_Plus/main/ddgp/logo.png" style="height: 80px;">
|
| 191 |
</div>
|
| 192 |
""")
|
|
@@ -194,7 +184,7 @@ with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
|
|
| 194 |
gr.Markdown("# Estação Filológica DDGP & OdyCy")
|
| 195 |
gr.Markdown("Análise lexical e consulta ao Dicionário de Dificuldades do Grego Prático.")
|
| 196 |
|
| 197 |
-
with gr.Tab("📝 Análise lexical"):
|
| 198 |
txt = gr.Textbox(label="Texto em Grego Antigo", lines=6, placeholder="Insira o texto aqui...")
|
| 199 |
btn = gr.Button("🚀 Executar Análise", variant="primary")
|
| 200 |
|
|
@@ -207,22 +197,29 @@ with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
|
|
| 207 |
|
| 208 |
with gr.Row():
|
| 209 |
with gr.Column(scale=2):
|
| 210 |
-
out_t = gr.Dataframe(label="Formas")
|
| 211 |
out_f = gr.File(label="Exportar CSV")
|
| 212 |
with gr.Column(scale=1):
|
| 213 |
gr.Markdown("### 📖 Léxico Contextual")
|
| 214 |
out_l = gr.HTML()
|
| 215 |
|
| 216 |
-
with gr.Tab("🔍 Busca direta no DDGP"):
|
| 217 |
-
in_b = gr.Textbox(label="Busca direta no DDGP", placeholder="(ex. λόγος, logos)")
|
| 218 |
btn_b = gr.Button("Consultar Base")
|
| 219 |
out_b = gr.HTML()
|
| 220 |
|
| 221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
btn.click(analisar_texto, inputs=txt,
|
| 223 |
-
outputs=[out_t, out_f, t1, t2, t3, t4, t5, out_l]
|
|
|
|
| 224 |
|
| 225 |
-
btn_b.click(consultar_ddgp, inputs=in_b, outputs=out_b
|
| 226 |
-
|
| 227 |
|
| 228 |
demo.launch()
|
|
|
|
| 29 |
except:
|
| 30 |
nlp = spacy.blank("grc")
|
| 31 |
|
|
|
|
| 32 |
TAG_MAP = {
|
| 33 |
'NOUN': 'Substantivo', 'VERB': 'Verbo', 'ADJ': 'Adjetivo',
|
| 34 |
'DET': 'Artigo/Det.', 'PRON': 'Pronome', 'ADV': 'Advérbio',
|
|
|
|
| 49 |
ENTRIES = load_json('ddgp3x_entry.json')
|
| 50 |
ABREV = load_json('abrev.json')
|
| 51 |
|
| 52 |
+
css_content = ""
|
| 53 |
+
for f_css in ['style.css', 'style_map.css']:
|
| 54 |
+
if os.path.exists(f_css):
|
| 55 |
+
with open(f_css, 'r', encoding='utf-8') as f:
|
| 56 |
+
css_content += f.read() + "\n"
|
| 57 |
|
| 58 |
# --- 2. FUNÇÕES DE APOIO ---
|
| 59 |
|
|
|
|
| 64 |
return unicodedata.normalize('NFC', texto).strip()
|
| 65 |
|
| 66 |
def aplicar_abreviaturas_seguro(texto):
|
|
|
|
| 67 |
if not texto: return ""
|
|
|
|
|
|
|
| 68 |
sorted_abrevs = sorted(ABREV.keys(), key=len, reverse=True)
|
|
|
|
| 69 |
for ab in sorted_abrevs:
|
|
|
|
| 70 |
pattern = r'\b' + re.escape(ab) + r'(?=\s|[.,;:]|$)'
|
| 71 |
+
info = ABREV[ab]
|
| 72 |
+
desc = info.get('descricao', '')
|
| 73 |
+
categoria = info.get('categoria', '')
|
| 74 |
classe_css = "autor-sc" if categoria == 'autor' else "abrev"
|
|
|
|
|
|
|
| 75 |
subst = f'<span class="{classe_css}" title="{desc}">{ab}</span>'
|
| 76 |
texto = re.sub(pattern, subst, texto)
|
| 77 |
return texto
|
|
|
|
| 81 |
if not entry: return None
|
| 82 |
gword = entry.get('gword', '')
|
| 83 |
pdesc = entry.get('pdesc', '')
|
|
|
|
| 84 |
pdesc = aplicar_abreviaturas_seguro(pdesc)
|
| 85 |
pdesc = re.sub(r'〈(.*?)〉', r'<span class="etimo">〈\1〉</span>', pdesc)
|
| 86 |
|
|
|
|
| 121 |
if res: html += res
|
| 122 |
return html
|
| 123 |
|
|
|
|
|
|
|
|
|
|
| 124 |
def analisar_texto(texto):
|
|
|
|
| 125 |
if not texto: return None, None, "0", "0", "0", "0", "0", ""
|
|
|
|
|
|
|
| 126 |
doc = nlp(texto)
|
| 127 |
dados = []
|
| 128 |
+
|
| 129 |
+
lemas_unicos_encontrados = set()
|
| 130 |
+
verbetes_dict = {}
|
| 131 |
|
| 132 |
for token in doc:
|
| 133 |
l_orig = token.lemma_
|
| 134 |
l_norm = normalizar_grego(l_orig)
|
| 135 |
pos_pt = TAG_MAP.get(token.pos_, token.pos_)
|
| 136 |
|
| 137 |
+
# Simplifica a morfologia removendo prefixos das tags para poupar espaço
|
| 138 |
+
morph_info = str(token.morph).replace("Case=", "").replace("Gender=", "").replace("Number=", "").replace("VerbForm=", "").replace("Person=", "").replace("Tense=", "").replace("Mood=", "").replace("Voice=", "")
|
| 139 |
+
if not morph_info: morph_info = "-"
|
| 140 |
|
| 141 |
+
if token.pos_ not in ['PUNCT', 'SYM', 'SPACE'] and l_norm not in lemas_unicos_encontrados:
|
| 142 |
+
res_html = consultar_ddgp(l_norm)
|
| 143 |
+
if "não localizado" not in res_html:
|
| 144 |
+
verbetes_dict[l_orig] = res_html
|
| 145 |
+
lemas_unicos_encontrados.add(l_norm)
|
| 146 |
|
| 147 |
dados.append({
|
| 148 |
'Palavra': token.text,
|
| 149 |
'Lema': l_orig,
|
| 150 |
'Classe': pos_pt,
|
| 151 |
+
'Morfologia': morph_info
|
| 152 |
})
|
| 153 |
|
| 154 |
+
lexico_html = ""
|
| 155 |
+
for lema_ord in sorted(verbetes_dict.keys()):
|
| 156 |
+
lexico_html += verbetes_dict[lema_ord]
|
| 157 |
+
|
| 158 |
df = pd.DataFrame(dados)
|
|
|
|
|
|
|
| 159 |
tokens_df = df[~df['Classe'].isin(['Pontuação', 'PUNCT', 'SYM', 'SPACE'])]
|
| 160 |
n_tokens = len(tokens_df)
|
| 161 |
n_types = tokens_df['Palavra'].str.lower().nunique()
|
|
|
|
| 175 |
with gr.Blocks(css=css_content, title="DDGP + OdyCy") as demo:
|
| 176 |
with gr.Row():
|
| 177 |
with gr.Column(scale=1, min_width=100):
|
|
|
|
| 178 |
gr.HTML("""
|
| 179 |
+
<div style="display: flex; align-items: center; justify-content: flex-start; height: 80px;">
|
| 180 |
<img src="https://raw.githubusercontent.com/aniseferreira/DDGP_Plus/main/ddgp/logo.png" style="height: 80px;">
|
| 181 |
</div>
|
| 182 |
""")
|
|
|
|
| 184 |
gr.Markdown("# Estação Filológica DDGP & OdyCy")
|
| 185 |
gr.Markdown("Análise lexical e consulta ao Dicionário de Dificuldades do Grego Prático.")
|
| 186 |
|
| 187 |
+
with gr.Tab("📝 Análise lexical"):
|
| 188 |
txt = gr.Textbox(label="Texto em Grego Antigo", lines=6, placeholder="Insira o texto aqui...")
|
| 189 |
btn = gr.Button("🚀 Executar Análise", variant="primary")
|
| 190 |
|
|
|
|
| 197 |
|
| 198 |
with gr.Row():
|
| 199 |
with gr.Column(scale=2):
|
| 200 |
+
out_t = gr.Dataframe(label="Formas")
|
| 201 |
out_f = gr.File(label="Exportar CSV")
|
| 202 |
with gr.Column(scale=1):
|
| 203 |
gr.Markdown("### 📖 Léxico Contextual")
|
| 204 |
out_l = gr.HTML()
|
| 205 |
|
| 206 |
+
with gr.Tab("🔍 Busca direta no DDGP"):
|
| 207 |
+
in_b = gr.Textbox(label="Busca direta no DDGP", placeholder="(ex. λόγος, logos)")
|
| 208 |
btn_b = gr.Button("Consultar Base")
|
| 209 |
out_b = gr.HTML()
|
| 210 |
|
| 211 |
+
gr.Markdown(f"""
|
| 212 |
+
---
|
| 213 |
+
**DDGP Plus** — Analisador Morfológico e Dicionário Digital de Grego–Português 2026 v.1
|
| 214 |
+
Baseado no Dicionário Digital de Grego–Português (DDGP e DGP - ver [hipatia.fclar.unesp.br](http://hipatia.fclar.unesp.br))
|
| 215 |
+
Projetos Abertos em Letras Clássicas Digitais. Responsável: **Anise D'Orange Ferreira**.
|
| 216 |
+
""")
|
| 217 |
+
|
| 218 |
btn.click(analisar_texto, inputs=txt,
|
| 219 |
+
outputs=[out_t, out_f, t1, t2, t3, t4, t5, out_l],
|
| 220 |
+
api_name="analisar")
|
| 221 |
|
| 222 |
+
btn_b.click(consultar_ddgp, inputs=in_b, outputs=out_b,
|
| 223 |
+
api_name="consultar")
|
| 224 |
|
| 225 |
demo.launch()
|