Maria Tsilimos commited on
Commit
a2257f8
·
unverified ·
1 Parent(s): 5de8be1

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +328 -0
app.py ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import time
3
+ import pandas as pd
4
+ import io
5
+ from transformers import pipeline
6
+ from streamlit_extras.stylable_container import stylable_container
7
+ import plotly.express as px
8
+ import zipfile
9
+
10
+ from PyPDF2 import PdfReader
11
+ import docx
12
+
13
+
14
+ import os
15
+ from comet_ml import Experiment
16
+ import re
17
+ import numpy as np
18
+
19
+
20
+
21
+
22
+ st.subheader("58-Italian Named Entity Recognition Web App", divider = "orange")
23
+ st.link_button("by nlpblogs", "https://nlpblogs.com", type = "tertiary")
24
+
25
+ expander = st.expander("**Important notes on the 58-Italian Named Entity Recognition Web App**")
26
+ expander.write('''
27
+
28
+ **Named Entities:**
29
+ This 58-Italian Named Entity Recognition Web App predicts fifty-eight (58) labels
30
+
31
+ ("**INDIRIZZO**: Identifica un indirizzo fisico.
32
+
33
+ **VALUTA**: Rappresenta una valuta.
34
+
35
+ **CVV**: Codice di sicurezza della carta di credito.
36
+
37
+ **NUMERO_CONTO**: Numero di un conto bancario.
38
+
39
+ **BIC**: Codice identificativo di una banca (Bank Identifier Code).
40
+
41
+ **IBAN**: Numero di conto bancario internazionale.
42
+
43
+ **STATO**: Identifica un paese o una nazione.
44
+
45
+ **NOME**: Riferito al nome di una persona.
46
+
47
+ **COGNOME**: Riferito al cognome di una persona.
48
+
49
+ **CODICE_POSTALE**: Codice postale di un'area geografica.
50
+
51
+ **IP**: Indirizzo IP di un dispositivo in rete.
52
+
53
+ **ORARIO**: Riferito a un orario specifico.
54
+
55
+ **URL**: Indirizzo web (Uniform Resource Locator).
56
+
57
+ **LUOGO**: Identifica un luogo geografico.
58
+
59
+ **IMPORTO**: Riferito a una somma di denaro.
60
+
61
+ **EMAIL**: Indirizzo di posta elettronica.
62
+
63
+ **PASSWORD**: Parola chiave per l'accesso a sistemi protetti.
64
+
65
+ **NUMERO_CARTA**: Numero di una carta di credito o debito.
66
+
67
+ **TARGA_VEICOLO**: Numero di targa di un veicolo.
68
+
69
+ **DATA_NASCITA**: Data di nascita di una persona.
70
+
71
+ **DATA_MORTE**: Data di decesso di una persona.
72
+
73
+ **RAGIONE_SOCIALE**: Nome legale di un'azienda o entità commerciale.
74
+
75
+ **ETA**: Età di una persona.
76
+
77
+ **DATA**: Riferita a una data generica.
78
+
79
+ **PROFESSIONE**: Occupazione o lavoro di una persona.
80
+
81
+ **PIN**: Numero di identificazione personale.
82
+
83
+ **NUMERO_TELEFONO**: Numero telefonico.
84
+
85
+ **FOGLIO**: Riferito a un foglio di documentazione.
86
+
87
+ **PARTICELLA**: Riferito a una particella catastale.
88
+
89
+ **CARTELLA_CLINICA**: Documentazione medica di un paziente.
90
+
91
+ **MALATTIA**: Identifica una malattia o condizione medica.
92
+
93
+ **MEDICINA**: Riferito a un farmaco o trattamento medico.
94
+
95
+ **CODICE_FISCALE**: Codice fiscale personale o aziendale.
96
+
97
+ **NUMERO_DOCUMENTO**: Numero di un documento ufficiale.
98
+
99
+ **STORIA_CLINICA**: Registro delle condizioni mediche di un paziente.
100
+
101
+ **AVV_NOTAIO**: Identifica un avvocato o notaio.
102
+
103
+ **P_IVA**: Partita IVA di un'azienda o professionista.
104
+
105
+ **LEGGE**: Riferito a una legge specifica.
106
+
107
+ **TASSO_MUTUO**: Tasso di interesse di un mutuo.
108
+
109
+ **N_SENTENZA**: Numero di una sentenza legale.
110
+
111
+ **MAPPALE**: Riferito a un mappale catastale.
112
+
113
+ **SUBALTERNO**: Riferito a un subalterno catastale.
114
+
115
+ **REGIME_PATRIMONIALE**: Stato patrimoniale in ambito legale.
116
+
117
+ **STATO_CIVILE**: Stato civile di una persona.
118
+
119
+ **BANCA**: Identifica una banca o istituto di credito.
120
+
121
+ **BRAND**: Marchio o brand commerciale.
122
+
123
+ **NUM_ASSEGNO_BANCARIO**: Numero di un assegno bancario.
124
+
125
+ **IMEI**: Numero di identificazione internazionale di un dispositivo mobile.
126
+
127
+ **N_LICENZA**: Numero di una licenza specifica.
128
+
129
+ **IPV6_1**: Indirizzo IP versione 6.
130
+
131
+ **MAC**: Indirizzo MAC di un dispositivo di rete.
132
+
133
+ **USER_AGENT**: Identifica il software usato per accedere a una rete.
134
+
135
+ **TRIBUNALE**: Identifica un tribunale specifico.
136
+
137
+ **STRENGTH**: Riferito alla forza o intensità di del medicinale.
138
+
139
+ **FREQUENZA**: Riferito alla frequenza di un trattamento medico.
140
+
141
+ **DURATION**: Durata di un evento o trattamento.
142
+
143
+ **DOSAGGIO**: Quantità di un medicinale da assumere.
144
+
145
+ **FORM**: Forma del medicinale, ad esempio compresse.")
146
+
147
+ Results are presented in an easy-to-read table, visualized in an interactive tree map, pie chart, and bar chart, and are available for download along with a Glossary of tags.
148
+
149
+ **How to Use:**
150
+ Upload your .pdf or .docx file. Then, click the 'Results' button to extract and tag entities in your text data.
151
+
152
+ **Usage Limits:**
153
+ You can request results up to 10 times.
154
+
155
+ **Customization:**
156
+ To change the app's background color to white or black, click the three-dot menu on the right-hand side of your app, go to Settings and then Choose app theme, colors and fonts.
157
+
158
+ **Technical issues:**
159
+ If your connection times out, please refresh the page or reopen the app's URL.
160
+
161
+ For any errors or inquiries, please contact us at [email protected]
162
+
163
+ ''')
164
+
165
+
166
+ with st.sidebar:
167
+ container = st.container(border=True)
168
+ container.write("**Named Entity Recognition (NER)** is the task of extracting and tagging entities in text data. Entities can be persons, organizations, locations, countries, products, events etc.")
169
+ st.subheader("Related NLP Web Apps", divider = "orange")
170
+ st.link_button("8-Named Entity Recognition Web App", "https://nlpblogs.com/shop/named-entity-recognition-ner/8-named-entity-recognition-web-app/", type = "primary")
171
+
172
+
173
+ COMET_API_KEY = os.environ.get("COMET_API_KEY")
174
+ COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
175
+ COMET_PROJECT_NAME = os.environ.get("COMET_PROJECT_NAME")
176
+
177
+ if COMET_API_KEY and COMET_WORKSPACE and COMET_PROJECT_NAME:
178
+ comet_initialized = True
179
+ else:
180
+ comet_initialized = False
181
+ st.warning("Comet ML not initialized. Check environment variables.")
182
+
183
+
184
+
185
+ if 'file_upload_attempts' not in st.session_state:
186
+ st.session_state['file_upload_attempts'] = 0
187
+
188
+ max_attempts = 10
189
+
190
+
191
+ upload_file = st.file_uploader("Upload your file. Accepted file formats include: .pdf, .docx", type=['pdf', 'docx'])
192
+ text = None
193
+ df = None
194
+
195
+ if upload_file is not None:
196
+
197
+ file_extension = upload_file.name.split('.')[-1].lower()
198
+ if file_extension == 'pdf':
199
+ try:
200
+ pdf_reader = PdfReader(upload_file)
201
+ text = ""
202
+ for page in pdf_reader.pages:
203
+ text += page.extract_text()
204
+ st.write("Due to security protocols, the file content is hidden.")
205
+ except Exception as e:
206
+ st.error(f"An error occurred while reading PDF: {e}")
207
+ elif file_extension == 'docx':
208
+ try:
209
+ doc = docx.Document(upload_file)
210
+ text = "\n".join([para.text for para in doc.paragraphs])
211
+ st.write("Due to security protocols, the file content is hidden.")
212
+ except Exception as e:
213
+ st.error(f"An error occurred while reading docx: {e}")
214
+ else:
215
+ st.warning("Unsupported file type.")
216
+
217
+ st.stop()
218
+
219
+
220
+ st.divider()
221
+
222
+ if st.button("Results"):
223
+ if st.session_state['file_upload_attempts'] >= max_attempts:
224
+ st.error(f"You have requested results {max_attempts} times. You have reached your daily request limit.")
225
+ st.stop()
226
+ st.session_state['file_upload_attempts'] += 1
227
+
228
+
229
+ with st.spinner("Wait for it...", show_time=True):
230
+ time.sleep(5)
231
+ model = pipeline("token-classification", model="DeepMount00/Italian_NER_XXL", aggregation_strategy = "max")
232
+ text1 = model(text)
233
+
234
+ df1 = pd.DataFrame(text1)
235
+ pattern = r'[^\w\s]'
236
+ df1['word'] = df1['word'].replace(pattern, '', regex=True)
237
+
238
+ df2 = df1.replace('', 'Unknown')
239
+ df = df2.dropna()
240
+
241
+
242
+
243
+
244
+
245
+
246
+ if comet_initialized:
247
+ experiment = Experiment(
248
+ api_key=COMET_API_KEY,
249
+ workspace=COMET_WORKSPACE,
250
+ project_name=COMET_PROJECT_NAME,
251
+ )
252
+ experiment.log_parameter("input_text", text)
253
+ experiment.log_table("predicted_entities", df)
254
+
255
+ properties = {"border": "2px solid gray", "color": "blue", "font-size": "16px"}
256
+ df_styled = df.style.set_properties(**properties)
257
+ st.dataframe(df_styled)
258
+
259
+ with st.expander("See Glossary of tags"):
260
+ st.write('''
261
+ '**word**': ['entity extracted from your text data']
262
+
263
+ '**score**': ['accuracy score; how accurately a tag has been assigned to a given entity']
264
+
265
+ '**entity_group**': ['label (tag) assigned to a given extracted entity']
266
+
267
+ '**start**': ['index of the start of the corresponding entity']
268
+
269
+ '**end**': ['index of the end of the corresponding entity']
270
+ ''')
271
+
272
+ if df is not None:
273
+ fig = px.treemap(df, path=[px.Constant("all"), 'word', 'entity_group'],
274
+ values='score', color='entity_group')
275
+ fig.update_layout(margin = dict(t=50, l=25, r=25, b=25))
276
+ st.subheader("Tree map", divider = "rainbow")
277
+ st.plotly_chart(fig)
278
+ if comet_initialized:
279
+ experiment.log_figure(figure=fig, figure_name="entity_treemap")
280
+
281
+ if df is not None:
282
+ value_counts1 = df['entity_group'].value_counts()
283
+ df1 = pd.DataFrame(value_counts1)
284
+ final_df = df1.reset_index().rename(columns={"index": "entity_group"})
285
+ col1, col2 = st.columns(2)
286
+ with col1:
287
+ fig1 = px.pie(final_df, values='count', names='entity_group', hover_data=['count'], labels={'count': 'count'}, title='Percentage of predicted labels')
288
+ fig1.update_traces(textposition='inside', textinfo='percent+label')
289
+ st.subheader("Pie Chart", divider = "orange")
290
+ st.plotly_chart(fig1)
291
+ if comet_initialized:
292
+ experiment.log_figure(figure=fig1, figure_name="label_pie_chart")
293
+ with col2:
294
+ fig2 = px.bar(final_df, x="count", y="entity_group", color="entity_group", text_auto=True, title='Occurrences of predicted labels')
295
+ st.subheader("Bar Chart", divider = "orange")
296
+ st.plotly_chart(fig2)
297
+ if comet_initialized:
298
+ experiment.log_figure(figure=fig2, figure_name="label_bar_chart")
299
+
300
+ dfa = pd.DataFrame(
301
+ data={
302
+ 'word': ['entity extracted from your text data'], 'score': ['accuracy score; how accurately a tag has been assigned to a given entity'], 'entity_group': ['label (tag) assigned to a given extracted entity'],
303
+ 'start': ['index of the start of the corresponding entity'],
304
+ 'end': ['index of the end of the corresponding entity'],
305
+ })
306
+ buf = io.BytesIO()
307
+ with zipfile.ZipFile(buf, "w") as myzip:
308
+ myzip.writestr("Summary of the results.csv", df.to_csv(index=False))
309
+ myzip.writestr("Glossary of tags.csv", dfa.to_csv(index=False))
310
+
311
+
312
+ with stylable_container(
313
+ key="download_button",
314
+ css_styles="""button { background-color: yellow; border: 1px solid black; padding: 5px; color: black; }""",
315
+ ):
316
+ st.download_button(
317
+ label="Download zip file",
318
+ data=buf.getvalue(),
319
+ file_name="zip file.zip",
320
+ mime="application/zip",
321
+ )
322
+ if comet_initialized:
323
+ experiment.log_asset(buf.getvalue(), file_name="downloadable_results.zip")
324
+
325
+ st.divider()
326
+ if comet_initialized:
327
+ experiment.end()
328
+ st.write(f"Number of times you requested results: {st.session_state['file_upload_attempts']}/{max_attempts}")