Maria Tsilimos commited on
Commit
1189b42
·
unverified ·
1 Parent(s): 6395f59

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +210 -0
app.py ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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("4-Named Entity Recognition Web App", divider = "rainbow")
23
+ st.link_button("by nlpblogs", "https://nlpblogs.com", type = "tertiary")
24
+
25
+ expander = st.expander("**Important notes on the 4-Named Entity Recognition Web App**")
26
+ expander.write('''
27
+
28
+ **Named Entities:**
29
+ This 4-Named Entity Recognition Web App predicts four (4) labels (“person”, “location”, “organization”, “miscellaneous”). 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.
30
+
31
+ **How to Use:**
32
+ Upload your .pdf or .docx file. Then, click the 'Results' button to extract and tag entities in your text data.
33
+
34
+ **Usage Limits:**
35
+ You can request results up to 10 times.
36
+
37
+ **Customization:**
38
+ 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.
39
+
40
+ **Technical issues:**
41
+ If your connection times out, please refresh the page or reopen the app's URL.
42
+
43
+ For any errors or inquiries, please contact us at [email protected]
44
+
45
+ ''')
46
+
47
+
48
+ with st.sidebar:
49
+ container = st.container(border=True)
50
+ 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.")
51
+ st.subheader("Related NLP Web Apps", divider = "rainbow")
52
+ 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")
53
+
54
+
55
+ COMET_API_KEY = os.environ.get("COMET_API_KEY")
56
+ COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
57
+ COMET_PROJECT_NAME = os.environ.get("COMET_PROJECT_NAME")
58
+
59
+ if COMET_API_KEY and COMET_WORKSPACE and COMET_PROJECT_NAME:
60
+ comet_initialized = True
61
+ else:
62
+ comet_initialized = False
63
+ st.warning("Comet ML not initialized. Check environment variables.")
64
+
65
+
66
+
67
+ if 'file_upload_attempts' not in st.session_state:
68
+ st.session_state['file_upload_attempts'] = 0
69
+
70
+ max_attempts = 10
71
+
72
+
73
+ upload_file = st.file_uploader("Upload your file. Accepted file formats include: .pdf, .docx", type=['pdf', 'docx'])
74
+ text = None
75
+ df = None
76
+
77
+ if upload_file is not None:
78
+
79
+ file_extension = upload_file.name.split('.')[-1].lower()
80
+ if file_extension == 'pdf':
81
+ try:
82
+ pdf_reader = PdfReader(upload_file)
83
+ text = ""
84
+ for page in pdf_reader.pages:
85
+ text += page.extract_text()
86
+ st.write("Due to security protocols, the file content is hidden.")
87
+ except Exception as e:
88
+ st.error(f"An error occurred while reading PDF: {e}")
89
+ elif file_extension == 'docx':
90
+ try:
91
+ doc = docx.Document(upload_file)
92
+ text = "\n".join([para.text for para in doc.paragraphs])
93
+ st.write("Due to security protocols, the file content is hidden.")
94
+ except Exception as e:
95
+ st.error(f"An error occurred while reading docx: {e}")
96
+ else:
97
+ st.warning("Unsupported file type.")
98
+
99
+ st.stop()
100
+
101
+
102
+ st.divider()
103
+
104
+ if st.button("Results"):
105
+ if st.session_state['file_upload_attempts'] >= max_attempts:
106
+ st.error(f"You have requested results {max_attempts} times. You have reached your daily request limit.")
107
+ st.stop()
108
+ st.session_state['file_upload_attempts'] += 1
109
+
110
+
111
+ with st.spinner("Wait for it...", show_time=True):
112
+ time.sleep(5)
113
+ model = pipeline("token-classification", model="dslim/distilbert-NER", aggregation_strategy = "max")
114
+ text1 = model(text)
115
+
116
+ df1 = pd.DataFrame(text1)
117
+ pattern = r'[^\w\s]'
118
+ df1['word'] = df1['word'].replace(pattern, '', regex=True)
119
+
120
+ df2 = df1.replace('', 'Unknown')
121
+ df = df2.dropna()
122
+
123
+
124
+
125
+
126
+
127
+
128
+ if comet_initialized:
129
+ experiment = Experiment(
130
+ api_key=COMET_API_KEY,
131
+ workspace=COMET_WORKSPACE,
132
+ project_name=COMET_PROJECT_NAME,
133
+ )
134
+ experiment.log_parameter("input_text", text)
135
+ experiment.log_table("predicted_entities", df)
136
+
137
+ properties = {"border": "2px solid gray", "color": "blue", "font-size": "16px"}
138
+ df_styled = df.style.set_properties(**properties)
139
+ st.dataframe(df_styled)
140
+
141
+ with st.expander("See Glossary of tags"):
142
+ st.write('''
143
+ '**word**': ['entity extracted from your text data']
144
+
145
+ '**score**': ['accuracy score; how accurately a tag has been assigned to a given entity']
146
+
147
+ '**entity_group**': ['label (tag) assigned to a given extracted entity']
148
+
149
+ '**start**': ['index of the start of the corresponding entity']
150
+
151
+ '**end**': ['index of the end of the corresponding entity']
152
+ ''')
153
+
154
+ if df is not None:
155
+ fig = px.treemap(df, path=[px.Constant("all"), 'word', 'entity_group'],
156
+ values='score', color='entity_group')
157
+ fig.update_layout(margin = dict(t=50, l=25, r=25, b=25))
158
+ st.subheader("Tree map", divider = "rainbow")
159
+ st.plotly_chart(fig)
160
+ if comet_initialized:
161
+ experiment.log_figure(figure=fig, figure_name="entity_treemap")
162
+
163
+ if df is not None:
164
+ value_counts1 = df['entity_group'].value_counts()
165
+ df1 = pd.DataFrame(value_counts1)
166
+ final_df = df1.reset_index().rename(columns={"index": "entity_group"})
167
+ col1, col2 = st.columns(2)
168
+ with col1:
169
+ fig1 = px.pie(final_df, values='count', names='entity_group', hover_data=['count'], labels={'count': 'count'}, title='Percentage of predicted labels')
170
+ fig1.update_traces(textposition='inside', textinfo='percent+label')
171
+ st.subheader("Pie Chart", divider = "rainbow")
172
+ st.plotly_chart(fig1)
173
+ if comet_initialized:
174
+ experiment.log_figure(figure=fig1, figure_name="label_pie_chart")
175
+ with col2:
176
+ fig2 = px.bar(final_df, x="count", y="entity_group", color="entity_group", text_auto=True, title='Occurrences of predicted labels')
177
+ st.subheader("Bar Chart", divider = "rainbow")
178
+ st.plotly_chart(fig2)
179
+ if comet_initialized:
180
+ experiment.log_figure(figure=fig2, figure_name="label_bar_chart")
181
+
182
+ dfa = pd.DataFrame(
183
+ data={
184
+ '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'],
185
+ 'start': ['index of the start of the corresponding entity'],
186
+ 'end': ['index of the end of the corresponding entity'],
187
+ })
188
+ buf = io.BytesIO()
189
+ with zipfile.ZipFile(buf, "w") as myzip:
190
+ myzip.writestr("Summary of the results.csv", df.to_csv(index=False))
191
+ myzip.writestr("Glossary of tags.csv", dfa.to_csv(index=False))
192
+
193
+
194
+ with stylable_container(
195
+ key="download_button",
196
+ css_styles="""button { background-color: yellow; border: 1px solid black; padding: 5px; color: black; }""",
197
+ ):
198
+ st.download_button(
199
+ label="Download zip file",
200
+ data=buf.getvalue(),
201
+ file_name="zip file.zip",
202
+ mime="application/zip",
203
+ )
204
+ if comet_initialized:
205
+ experiment.log_asset(buf.getvalue(), file_name="downloadable_results.zip")
206
+
207
+ st.divider()
208
+ if comet_initialized:
209
+ experiment.end()
210
+ st.write(f"Number of times you requested results: {st.session_state['file_upload_attempts']}/{max_attempts}")