anonymous12321 commited on
Commit
54986f8
·
verified ·
1 Parent(s): 65b03c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +23 -44
app.py CHANGED
@@ -1,7 +1,8 @@
1
  """
2
- 🪶 Council Matters Classifier – PT
3
  """
4
 
 
5
  import gradio as gr
6
  import numpy as np
7
  import joblib
@@ -9,14 +10,14 @@ import re
9
  from pathlib import Path
10
  from scipy.sparse import hstack, csr_matrix
11
 
 
12
 
13
- try:
14
- import torch
15
- from transformers import AutoTokenizer, AutoModel
16
- TORCH_AVAILABLE = True
17
- except ImportError:
18
- TORCH_AVAILABLE = False
19
 
 
20
 
21
  # ---------------- Classifier ----------------
22
  class PortugueseClassifier:
@@ -30,11 +31,6 @@ class PortugueseClassifier:
30
  self.optimal_thresholds = None
31
  self.trained_base_models = None
32
 
33
- if TORCH_AVAILABLE:
34
- self.bert_tokenizer = None
35
- self.bert_model = None
36
- self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
37
-
38
  self.load_models()
39
 
40
  def load_models(self):
@@ -52,28 +48,24 @@ class PortugueseClassifier:
52
  self.optimal_thresholds = np.load(thresh_path)
53
  self.trained_base_models = joblib.load(base_path)
54
 
55
- if TORCH_AVAILABLE:
56
- self.bert_tokenizer = AutoTokenizer.from_pretrained('neuralmind/bert-base-portuguese-cased')
57
- self.bert_model = AutoModel.from_pretrained('neuralmind/bert-base-portuguese-cased')
58
- self.bert_model.eval()
59
- self.bert_model = self.bert_model.to(self.device)
60
-
61
  self.models_loaded = True
62
  except Exception as e:
63
  print(f"❌ Error loading models: {str(e)}")
64
 
 
65
  def extract_bert_features(self, text):
66
- if not TORCH_AVAILABLE or not self.bert_model:
67
- return np.zeros((1, 768))
68
  try:
69
- inputs = self.bert_tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
70
- inputs = {k: v.to(self.device) for k, v in inputs.items()}
71
- with torch.no_grad():
72
- outputs = self.bert_model(**inputs)
73
- return outputs.last_hidden_state[:, 0, :].cpu().numpy()
74
- except Exception:
 
 
75
  return np.zeros((1, 768))
76
 
 
77
  def predict(self, text):
78
  if not self.models_loaded:
79
  return [{"label": "Error", "probability": 0.0, "confidence": "low"}]
@@ -129,20 +121,10 @@ classifier = PortugueseClassifier()
129
 
130
  # ---------------- Suggestions ----------------
131
  suggestions = [
132
- "Pelo Senhor Presidente foi presente a esta reunião a informação n.º º ****** da Secção de Urbanismo e Fiscalização -- Serviço de Obras Particulares. \nPonderado e analisado o assunto o Executivo Municipal deliberou por unanimidade aprovar o projeto de arquitetura relativo ao Processo de obras n.º ***** -- EDIFIC.",
133
- "Pelo Senhor Presidente foram presentes a esta reunião os documentos relativos à assunção de compromissos plurianuais relativos à Loja do Cidadão, em Alandroal que se anexam à presente ata. \nPonderado e analisado o assunto o Executivo Municipal deliberou por maioria, com os votos a favor dos eleitos pelo PS e a abstenção da eleita pelo Nós, Cidadãos, aprovar a assunção de compromissos plurianuais. \nReferiu o Sr. Presidente que o FAM enviou então o parecer necessário para aprovação destes dois pontos e que refere que \"atendendo ao exposto propõe que a Direção Executiva do FAM emita parecer prévio positivo à proposta de modificação ao orçamento municipal de 2024 apresentado pela Câmara Municipal\". ",
134
- "-BALANCETE:\n-Operações orçamentas respeitante ao dia vinte e seis de março do corrente ano, é de um milhão oitocentos e onze mil quinhentos e quinze euros e noventa cêntimos.",
135
- "-APOIO SOLICITADO CEAN-CENTRO EDUCATIVO ALICE NABEIRO-VIAGEM DE FINALISTAS-ANO 2024:\n-Apreciação da informação (registo 5911) dos serviços financeiros, referente ao assunto em epígrafe, que a seguir se transcreve:-“ Na sequência da documentação apresentada pelo CEAN – Centro Educativo Alice Nabeiro no âmbito da realização de uma Viagem de Finalistas a Paris, e após análise dos referidos documentos da mencionada entidade e visto a atividade preponderante ser de índole educativo e social, o valor que sugiro quantifica-se em 500,00 (quinhentos euros) o qual considero razoável para o tipo de atividade referida. O valor sugerido tem cobertura orçamental através da Grande Opção do Plano, 2 232 2011/5044 – Transferências Correntes para Instituições Culturais, cuja dotação global prevista nos Documentos Previsionais para o Exercício 2023 é de 150.000,00 €. Pelo exposto e para efeitos de apreciação por parte de V. Exas., é tudo o que me cabe informar, acerca do assunto mencionado em epígrafe”.\n-A CÂMARA DELIBEROU, POR UNANIMIDADE, ATRIBUIR UM APOIO NO VALOR DE 500,00€ (QUINHENTOS EUROS) AO CEAN-CENTRO EDUCATIVO ALICE NABEIRO, TENDO EM VISTA AJUDAR A CUSTEAR A VIAGEM DE FINALISTA 2024."
136
- "-APOIO SOLICITADO PELA ASSOCIAÇÃO CULTURAL AXPRESS-ARTE - FESTIVAL INTERNACIONAL DE DANÇA:\n-Apreciação da informação (registo 5835) dos serviços financeiros, referente ao assunto em epígrafe, que a seguir se transcreve:-“ Na sequência da documentação apresentada pela Axpress-Arte – Associação Cultural para o exercício 2024, e em face da documentação apresentada pela referida instituição no âmbito da candidatura referida em epigrafe, e após análise dos referidos documentos da mencionada entidade e visto a atividade preponderante ser de índole cultural, o valor que sugiro quantifica-se em 3.000,00 (três mil euros) anuais o qual considero razoável para este tipo de atividade. O valor sugerido tem cobertura orçamental através da Grande Opção do Plano, 2 251 2011/5075 – Transferências Correntes para Instituições Culturais, cuja dotação global prevista nos Documentos Previsionais para o Exercício 2024 é de 90.000,00 €. Sendo o Histórico dos últimos anos de atribuição de apoios para a referida instituição o seguinte:\n\n————————————Quadro de Apoios 2019 – 2023————————————\nAno,Valor em Euros\n2019,0,00\n2020,0,00\n2021,0,00\n2022,3.000,00\n2023,3.000,00\n————————————————————————————————————————————————————— \n-Pelo exposto e para efeitos de apreciação por parte de V. Exas., é tudo o que me cabe informar, acerca do assunto mencionado em epígrafe”.\n-A CÂMARA DELIBEROU, POR UNANIMIDADE, ATRIBUIR UM APOIO NO VALOR DE 3.000,00€ (TRÊS MIL EUROS) À ASSOCIAÇÃO CULTURAL AXPRESS-ARTE, TENDO EM VISTA A REALIZAÇÃO DO FESTIVAL INTERNACIONAL DE DANÇA.",
137
- "Presente declaração, emitida pelo Senhor Presidente da Câmara em 07.junho.2024, para ratificação, constante da plataforma de gestão documental SigmaDoc Web/NIPG: 19890/24_Pendente: 100707.\n\nDocumentos que se dão como inteiramente reproduzidos na presente ata e ficam, para todos os efeitos legais, arquivados em pasta própria existente para o efeito.\n\nA Câmara deliberou, ao abrigo da n.º 3, do artigo 35.º do RJAL, aprovado pela Lei n.º 75/2013, de 12 de setembro, na sua redação atual, ratificar a Declaração emitida pelo Senhor Presidente da Camara em 07.junho.2024, em que o Município da Covilhã pretende ceder apoio logístico, institucional e/ou monetário para o evento \"18.ª Santa Bebiana\", atividade esta levada a cabo pela Casa do Povo do Paul, no âmbito da candidatura ao “Cultura ao Centro 2024, da CCDRC”.",
138
- "3.2. – ICOVI, Infraestruturas e Concessões da Covilhã, EM\n\nFoi presente à Câmara informação constante da plataforma de gestão documental SigmaDoc Web/NIPG: 15508/24_Pendente: 101576, relativa ao ofício da ICOVI – Infraestruturas e Concessões da Covilhã, EM, com a referência 11/23, datado de 02.abril.2024, no qual informa o Resultado Antes de Impostos de 2023 negativo no valor de - 176.266,35€ (cento e setenta e seis mil, duzentos e sessenta e seis euros e trinta e cinco cêntimos) e solicita a cobertura desse resultado.\n\nDocumento que se dá como inteiramente reproduzido na presente ata e fica, para todos os efeitos legais, arquivado em pasta própria existente para o efeito.\n\nO Senhor Vereador Ricardo Miguel Correia Leitão Ferreira da Silva criticou o facto de a empresa somente enviar à Câmara um pedido do valor sem pelo menos enviar o relatório e contas.\n\nNão participou na discussão e votação do presente assunto o Senhor Vereador José Miguel Ribeiro Oliveira, nos termos previstos no n.º 6 do artigo 55.º do Anexo I da Lei nº. 75/2013, de 12 de setembro que aprova o RJAL, conjugado com o artigo 69.º do CPA – Código do Procedimento Administrativo, aprovado pelo Decreto-lei n.º 4/2015, de 7 de janeiro, na nova redação, por exercer as funções de Presidente do Conselho da Administração.\n\nA Câmara deliberou, com o voto contra dos Senhores Vereadores Ricardo Miguel Correia Leitão Ferreira da Silva e Jorge Humberto Martins Simões, tendo em conta que a Empresa Municipal ICOVI – Infraestruturas e Concessões da Covilhã, EM, apresenta um Resultado Antes de Impostos de 2023 negativo no valor de - 176.266,35€ (cento e setenta e seis mil, duzentos e sessenta e seis euros e trinta e cinco cêntimos), nos termos da legislação aplicável, aprovar e efetuar uma transferência financeira no valor de 176.266,35€ (cento e setenta e seis mil, duzentos e sessenta e seis euros e trinta e cinco cêntimos)",
139
- "Presente à Câmara informação, constante da distribuição no sistema informático de gestão documental com a referência EDOC/2022/27808, propondo a ratificação do Aditamento ao Contrato de Comparticipação entre o Instituto da Habitação e da Reabilitação Urbana, I.P. e o Município da Covilhã, destinado à Construção de edifício multifamiliar para 12 Alojamentos de Emergência (BNAUT).\n\nDocumentos que se dão como inteiramente reproduzidos na presente ata e ficam, para todos os efeitos legais, arquivados em pasta própria existente para o efeito.\n\nA Câmara deliberou ratificar o Aditamento ao Contrato de Comparticipação entre o Instituto da Habitação e da Reabilitação Urbana, I.P. e o Município da Covilhã – BNAUT, em que as Partes acordam em proceder à alteração do n.º 1 da Cláusula Terceira, do n.º 1 da Cláusula Quarta e da alínea a) do nº 1 da Cláusula Sexta do Contrato, e que tem por objeto a concessão de um apoio financeiro não reembolsável destinado a financiar a realização do projeto designado por “Construção de edifício multifamiliar para alojamento de emergência na Rua Comendador Gomes Correia n.º 39 a 65”, enquadrado no Aviso n.º 02/CO2-i02/2021, em que a Entidade Beneficiária é a Beneficiária Final, entidade globalmente responsável pela execução do Projeto de investimento ora contratualizado.",
140
- "O Presidente da Câmara apresentou declaração de inexistência de conflitos de interesse relativamente aos procedimentos da ordem do dia da presente reunião, constantes dos pontos 1 a 7 e 9 a 18, que se dá aqui por reproduzida e fica arquivada em pasta anexa ao livro de atas.",
141
- "7. TRÂNSITO – FREGUESIA DE PRAZINS SANTO TIRSO E CORVITE – ALTERAÇÃO DE TRÂNSITO NA TRAVESSA DO CAMPO NOVO - Presente a seguinte proposta: “Por forma a incrementar as condições de segurança e acessibilidade local dos moradores, a Junta de Freguesia submeteu proposta de alteração de trânsito na Travessa do Campo Novo, Freguesia de Prazins Santo Tirso e Corvite, no tramo compreendido entre a Travessa Nova do Campo Novo e a Rua 24 de Junho, aprovada pela Assembleia de Freguesia. Considerando os constrangimentos associados ao reduzido perfil transversal da Travessa do Campo Novo, a alteração potenciará o incremento da segurança rodoviária local, bem como a mitigação da prática de estacionamento em contravenção, submete-se à apreciação Camarária conforme postura anexa.” A postura e as atas dos órgãos executivo e deliberativo da Freguesia dão-se aqui por reproduzidos e ficam arquivados em pasta anexa ao livro de atas. DELIBERADO, POR UNANIMIDADE, SUBMETER À APROVAÇÃO DA ASSEMBLEIA MUNICIPAL.",
142
- "1. Ata da reunião pública do Executivo Municipal de 11 de novembro de 2024.\nAprovada, por unanimidade, pelos presentes na reunião pública do Executivo Municipal de 11 de novembro de 2024.",
143
  ]
144
- example_idx = 0
145
 
 
146
  def next_example():
147
  global example_idx
148
  example_idx = (example_idx + 1) % len(suggestions)
@@ -169,8 +151,7 @@ def classify_display(text):
169
  chips += f"<span class='output-chip' style='border-color:{color}80;color:{color}'>{label} ({prob:.0%})</span>"
170
  return f"<div style='display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:10px'>{chips}</div>"
171
 
172
- # ---------------- CSS dfg----------------
173
-
174
  custom_css = """
175
  body { background-color: #0c0c0c; color: #f1f1f1; font-family: 'Inter', sans-serif; }
176
  .gradio-container { background-color: #0c0c0c; color: #f1f1f1; }
@@ -179,8 +160,8 @@ textarea { background-color: #181818 !important; color: #fff !important; border-
179
  button { background-color: #007aff !important; color: white !important; font-weight: 600 !important; border-radius: 8px !important; border: none !important; }
180
  button:hover { background-color: #00aaff !important; }
181
  .output-chip { background-color: #1a1a1a; padding: 5px 12px; border-radius: 8px; font-weight: 500; border: 1px solid #007aff33; }
182
- .suggestion-box { background-color: #112f50; border-radius: 10px; border: 1px solid #1f3c5a; padding: 10px; display: flex; align-items: center; justify-content: center; color: #eee; margin-top: 25px; position: relative; overflow: scroll; } .arrow-btn { width: 25px; height: 25px; font-size: 12px; padding: 0; background: none; border: none; color: #e0f0ff; cursor: pointer; font-weight: bold; }
183
-
184
  .arrow-btn:hover { color: #ffffff; transform: scale(1.3); }
185
  .use-btn { background-color:#66b3ff !important; color:#000 !important; font-weight:600 !important; border-radius:6px !important; padding:3px 8px !important; margin-left:5px;}
186
  .use-btn:hover { background-color:#99ccff !important; }
@@ -189,14 +170,12 @@ button:hover { background-color: #00aaff !important; }
189
  .suggestion-box .suggestion-text { width: 100%; text-align: center; border:none; background:none; color:#eee; font-weight:500; padding-top:8px; overflow-y: scroll;}
190
  """
191
 
192
-
193
  # ---------------- Gradio UI ----------------
194
  with gr.Blocks(css=custom_css, theme="gradio/soft") as demo:
195
  gr.Markdown("## 🏛️ **Council Matters Classifier – PT**")
196
  gr.Markdown("### Insert your text (in portuguese):")
197
 
198
  input_text = gr.Textbox(label="", placeholder="Write your text (in portuguese)...", lines=6)
199
-
200
  classify_btn = gr.Button("Classify")
201
  output = gr.HTML()
202
  classify_btn.click(fn=classify_display, inputs=input_text, outputs=output)
 
1
  """
2
+ 🪶 Council Matters Classifier – PT (HF API BERT)
3
  """
4
 
5
+ import os
6
  import gradio as gr
7
  import numpy as np
8
  import joblib
 
10
  from pathlib import Path
11
  from scipy.sparse import hstack, csr_matrix
12
 
13
+ from huggingface_hub import InferenceClient
14
 
15
+ # ---------------- HF API Client ----------------
16
+ HF_TOKEN = os.environ.get("HF_TOKEN")
17
+ if not HF_TOKEN:
18
+ raise ValueError("Set the environment variable HF_TOKEN with your Hugging Face token.")
 
 
19
 
20
+ hf_client = InferenceClient(api_key=HF_TOKEN)
21
 
22
  # ---------------- Classifier ----------------
23
  class PortugueseClassifier:
 
31
  self.optimal_thresholds = None
32
  self.trained_base_models = None
33
 
 
 
 
 
 
34
  self.load_models()
35
 
36
  def load_models(self):
 
48
  self.optimal_thresholds = np.load(thresh_path)
49
  self.trained_base_models = joblib.load(base_path)
50
 
 
 
 
 
 
 
51
  self.models_loaded = True
52
  except Exception as e:
53
  print(f"❌ Error loading models: {str(e)}")
54
 
55
+ # ---------------- HF API BERT ----------------
56
  def extract_bert_features(self, text):
 
 
57
  try:
58
+ result = hf_client.feature_extraction(
59
+ text,
60
+ model="neuralmind/bert-base-portuguese-cased"
61
+ )
62
+ embedding = np.array(result).mean(axis=1) # mean pooling over tokens
63
+ return embedding
64
+ except Exception as e:
65
+ print(f"⚠️ HF BERT extraction failed: {e}")
66
  return np.zeros((1, 768))
67
 
68
+ # ---------------- Prediction ----------------
69
  def predict(self, text):
70
  if not self.models_loaded:
71
  return [{"label": "Error", "probability": 0.0, "confidence": "low"}]
 
121
 
122
  # ---------------- Suggestions ----------------
123
  suggestions = [
124
+ # [Coloca aqui as mesmas sugestões que tinhas antes]
 
 
 
 
 
 
 
 
 
 
125
  ]
 
126
 
127
+ example_idx = 0
128
  def next_example():
129
  global example_idx
130
  example_idx = (example_idx + 1) % len(suggestions)
 
151
  chips += f"<span class='output-chip' style='border-color:{color}80;color:{color}'>{label} ({prob:.0%})</span>"
152
  return f"<div style='display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:10px'>{chips}</div>"
153
 
154
+ # ---------------- CSS ----------------
 
155
  custom_css = """
156
  body { background-color: #0c0c0c; color: #f1f1f1; font-family: 'Inter', sans-serif; }
157
  .gradio-container { background-color: #0c0c0c; color: #f1f1f1; }
 
160
  button { background-color: #007aff !important; color: white !important; font-weight: 600 !important; border-radius: 8px !important; border: none !important; }
161
  button:hover { background-color: #00aaff !important; }
162
  .output-chip { background-color: #1a1a1a; padding: 5px 12px; border-radius: 8px; font-weight: 500; border: 1px solid #007aff33; }
163
+ .suggestion-box { background-color: #112f50; border-radius: 10px; border: 1px solid #1f3c5a; padding: 10px; display: flex; align-items: center; justify-content: center; color: #eee; margin-top: 25px; position: relative; overflow: scroll; }
164
+ .arrow-btn { width: 25px; height: 25px; font-size: 12px; padding: 0; background: none; border: none; color: #e0f0ff; cursor: pointer; font-weight: bold; }
165
  .arrow-btn:hover { color: #ffffff; transform: scale(1.3); }
166
  .use-btn { background-color:#66b3ff !important; color:#000 !important; font-weight:600 !important; border-radius:6px !important; padding:3px 8px !important; margin-left:5px;}
167
  .use-btn:hover { background-color:#99ccff !important; }
 
170
  .suggestion-box .suggestion-text { width: 100%; text-align: center; border:none; background:none; color:#eee; font-weight:500; padding-top:8px; overflow-y: scroll;}
171
  """
172
 
 
173
  # ---------------- Gradio UI ----------------
174
  with gr.Blocks(css=custom_css, theme="gradio/soft") as demo:
175
  gr.Markdown("## 🏛️ **Council Matters Classifier – PT**")
176
  gr.Markdown("### Insert your text (in portuguese):")
177
 
178
  input_text = gr.Textbox(label="", placeholder="Write your text (in portuguese)...", lines=6)
 
179
  classify_btn = gr.Button("Classify")
180
  output = gr.HTML()
181
  classify_btn.click(fn=classify_display, inputs=input_text, outputs=output)