nlpblogs commited on
Commit
bcd98d4
·
verified ·
1 Parent(s): d5add9d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -35
app.py CHANGED
@@ -1,13 +1,11 @@
1
  import streamlit as st
2
- import time # Still imported, but time.sleep(5) will be removed from the main logic
3
  import pandas as pd
4
  import io
5
- from streamlit_extras.stylable_container import stylable_container
6
  import plotly.express as px
7
  import zipfile
8
- from gliner import GLiNER # Import GLiNER
9
  import os
10
- from comet_ml import Experiment
11
 
12
  st.set_page_config(layout="wide", page_title="Named Entity Recognition App")
13
 
@@ -17,17 +15,26 @@ st.link_button("DEMO APP by nlpblogs", "https://nlpblogs.com", type="tertiary")
17
 
18
  expander = st.expander("**Important notes on the Free NER Web App**")
19
  expander.write('''
20
- **Named Entities:** This Free NER Web App predicts eight (8) labels (“person”, “country”, “city”, “organization”, “date”, “money”, “percent value”, “position”). 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.
21
-
22
- **How to Use:** Type or paste your text and press Ctrl + Enter. Then, click the 'Results' button to extract and tag entities in your text data.
23
-
24
- **Usage Limits:** Unlimited number of Result requests.
25
-
26
- **Customization:** 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.
27
-
28
- **Technical issues:** If your connection times out, please refresh the page or reopen the app's URL.
29
-
30
- For any errors or inquiries, please contact us at info@nlpblogs.com
 
 
 
 
 
 
 
 
 
31
  ''')
32
 
33
  # --- Sidebar ---
@@ -51,7 +58,7 @@ else:
51
  # --- Cache the GLiNER model ---
52
  @st.cache_resource
53
  def load_gliner_model():
54
-
55
  return GLiNER.from_pretrained("xomad/gliner-model-merge-large-v1.0")
56
 
57
  # Load the model using the cached function
@@ -63,6 +70,7 @@ text = st.text_area("Type or paste your text below, and then press Ctrl + Enter"
63
  st.write("**Input text**: ", text)
64
 
65
  def clear_text():
 
66
  st.session_state['my_text_area'] = ""
67
 
68
  st.button("Clear text", on_click=clear_text)
@@ -70,18 +78,35 @@ st.divider()
70
 
71
  # --- Results Section ---
72
  if st.button("Results"):
 
73
  if not text.strip(): # Check if the input text is empty
74
  st.warning("Please enter some text to extract entities.")
75
  else:
76
  with st.spinner("Extracting entities..."): # Spinner while processing
77
- # No need for time.sleep(5) here, as the model is already loaded
78
- labels = ["person", "country", "city", "organization", "date", "money", "percent value", "position"]
 
79
  entities = model.predict_entities(text, labels)
80
 
81
- # Ensure entities is a list of dictionaries for DataFrame creation
82
- # If no entities are found, 'entities' might be an empty list, which is fine for pd.DataFrame
83
  df = pd.DataFrame(entities)
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  if comet_initialized:
86
  experiment = Experiment(
87
  api_key=COMET_API_KEY,
@@ -90,7 +115,8 @@ if st.button("Results"):
90
  )
91
  experiment.log_parameter("input_text", text)
92
  experiment.log_table("predicted_entities", df)
93
-
 
94
  properties = {"border": "2px solid gray", "color": "blue", "font-size": "16px"}
95
  df_styled = df.style.set_properties(**properties)
96
  st.dataframe(df_styled)
@@ -103,6 +129,8 @@ if st.button("Results"):
103
 
104
  '**label**': ['label (tag) assigned to a given extracted entity']
105
 
 
 
106
  '**start**': ['index of the start of the corresponding entity']
107
 
108
  '**end**': ['index of the end of the corresponding entity']
@@ -111,31 +139,33 @@ if st.button("Results"):
111
  # --- Visualizations ---
112
  if not df.empty: # Only plot if DataFrame is not empty
113
  st.subheader("Tree map", divider="red")
114
- fig = px.treemap(df, path=[px.Constant("all"), 'text', 'label'],
115
- values='score', color='label')
116
  fig.update_layout(margin=dict(t=50, l=25, r=25, b=25))
117
  st.plotly_chart(fig)
118
  if comet_initialized:
119
- experiment.log_figure(figure=fig, figure_name="entity_treemap")
120
 
121
  col1, col2 = st.columns(2)
122
  with col1:
123
  st.subheader("Pie Chart", divider="red")
124
- value_counts1 = df['label'].value_counts()
 
125
  df1 = pd.DataFrame(value_counts1)
126
- final_df = df1.reset_index().rename(columns={"index": "label"})
127
- fig1 = px.pie(final_df, values='count', names='label', hover_data=['count'], labels={'count': 'count'}, title='Percentage of predicted labels')
128
  fig1.update_traces(textposition='inside', textinfo='percent+label')
129
  st.plotly_chart(fig1)
130
  if comet_initialized:
131
- experiment.log_figure(figure=fig1, figure_name="label_pie_chart")
132
 
133
  with col2:
134
  st.subheader("Bar Chart", divider="red")
135
- fig2 = px.bar(final_df, x="count", y="label", color="label", text_auto=True, title='Occurrences of predicted labels')
 
136
  st.plotly_chart(fig2)
137
  if comet_initialized:
138
- experiment.log_figure(figure=fig2, figure_name="label_bar_chart")
139
  else:
140
  st.info("No entities found in the provided text.")
141
 
@@ -143,6 +173,7 @@ if st.button("Results"):
143
  dfa = pd.DataFrame(
144
  data={
145
  'text': ['entity extracted from your text data'], 'score': ['accuracy score; how accurately a tag has been assigned to a given entity'], 'label': ['label (tag) assigned to a given extracted entity'],
 
146
  'start': ['index of the start of the corresponding entity'],
147
  'end': ['index of the end of the corresponding entity'],
148
  })
@@ -161,9 +192,11 @@ if st.button("Results"):
161
  file_name="zip file.zip",
162
  mime="application/zip",
163
  )
164
- if comet_initialized:
165
- experiment.log_asset(buf.getvalue(), file_name="downloadable_results.zip")
166
-
167
  st.divider()
168
- if comet_initialized:
169
- experiment.end()
 
 
 
 
 
 
1
  import streamlit as st
 
2
  import pandas as pd
3
  import io
 
4
  import plotly.express as px
5
  import zipfile
6
+ from gliner import GLiNER
7
  import os
8
+ from streamlit_extras.stylable_container import stylable_container
9
 
10
  st.set_page_config(layout="wide", page_title="Named Entity Recognition App")
11
 
 
15
 
16
  expander = st.expander("**Important notes on the Free NER Web App**")
17
  expander.write('''
18
+ **Named Entities:** This Free NER Web App predicts nine (9) labels
19
+ grouped into three categories: **People** (person, organization, position),
20
+ **Locations** (country, city), and **Numbers** (date, seconds, money, percent value).
21
+ Results are presented in an easy-to-read table, visualized in an
22
+ interactive treemap, pie chart, and bar chart, and are available for download
23
+ along with a Glossary of tags.
24
+
25
+ **How to Use:** Type or paste your text and press Ctrl + Enter. Then,
26
+ click the 'Results' button to extract and tag entities in your text data.
27
+
28
+ **Usage Limits:** Unlimited number of Result requests.
29
+
30
+ **Customization:** To change the app's background color to white or
31
+ black, click the three-dot menu on the right-hand side of your app, go to
32
+ Settings and then Choose app theme, colors and fonts.
33
+
34
+ **Technical issues:** If your connection times out, please refresh the
35
+ page or reopen the app's URL.
36
+
37
+ For any errors or inquiries, please contact us at [email protected]
38
  ''')
39
 
40
  # --- Sidebar ---
 
58
  # --- Cache the GLiNER model ---
59
  @st.cache_resource
60
  def load_gliner_model():
61
+ """Caches the GLiNER model to prevent re-loading on every app rerun."""
62
  return GLiNER.from_pretrained("xomad/gliner-model-merge-large-v1.0")
63
 
64
  # Load the model using the cached function
 
70
  st.write("**Input text**: ", text)
71
 
72
  def clear_text():
73
+ """Clears the text area."""
74
  st.session_state['my_text_area'] = ""
75
 
76
  st.button("Clear text", on_click=clear_text)
 
78
 
79
  # --- Results Section ---
80
  if st.button("Results"):
81
+ start_time = time.time()
82
  if not text.strip(): # Check if the input text is empty
83
  st.warning("Please enter some text to extract entities.")
84
  else:
85
  with st.spinner("Extracting entities..."): # Spinner while processing
86
+
87
+ # --- MODIFICATION: ADDED "seconds" to labels ---
88
+ labels = ["person", "country", "city", "organization", "date", "seconds", "money", "percent value", "position"]
89
  entities = model.predict_entities(text, labels)
90
 
 
 
91
  df = pd.DataFrame(entities)
92
 
93
+ # --- MODIFICATION: ADDED "seconds" to category mapping ---
94
+ if not df.empty:
95
+ # Create a mapping dictionary for labels to categories
96
+ category_mapping = {
97
+ "person": "People",
98
+ "organization": "People",
99
+ "position": "People",
100
+ "country": "Locations",
101
+ "city": "Locations",
102
+ "date": "Time",
103
+ "seconds": "Time",
104
+ "money": "Numbers",
105
+ "percent value": "Numbers"
106
+ }
107
+ # Add a new 'category' column to the DataFrame
108
+ df['category'] = df['label'].map(category_mapping)
109
+
110
  if comet_initialized:
111
  experiment = Experiment(
112
  api_key=COMET_API_KEY,
 
115
  )
116
  experiment.log_parameter("input_text", text)
117
  experiment.log_table("predicted_entities", df)
118
+ experiment.end()
119
+
120
  properties = {"border": "2px solid gray", "color": "blue", "font-size": "16px"}
121
  df_styled = df.style.set_properties(**properties)
122
  st.dataframe(df_styled)
 
129
 
130
  '**label**': ['label (tag) assigned to a given extracted entity']
131
 
132
+ '**category**': ['the high-level category for the label']
133
+
134
  '**start**': ['index of the start of the corresponding entity']
135
 
136
  '**end**': ['index of the end of the corresponding entity']
 
139
  # --- Visualizations ---
140
  if not df.empty: # Only plot if DataFrame is not empty
141
  st.subheader("Tree map", divider="red")
142
+ # Modified treemap path to show category as the first level
143
+ fig = px.treemap(df, path=[px.Constant("all"), 'category', 'label', 'text'], values='score', color='category')
144
  fig.update_layout(margin=dict(t=50, l=25, r=25, b=25))
145
  st.plotly_chart(fig)
146
  if comet_initialized:
147
+ experiment.log_figure(figure=fig, figure_name="entity_treemap_categories")
148
 
149
  col1, col2 = st.columns(2)
150
  with col1:
151
  st.subheader("Pie Chart", divider="red")
152
+ # Pie chart now visualizes the distribution of categories
153
+ value_counts1 = df['category'].value_counts()
154
  df1 = pd.DataFrame(value_counts1)
155
+ final_df = df1.reset_index().rename(columns={"index": "category"})
156
+ fig1 = px.pie(final_df, values='count', names='category', hover_data=['count'], labels={'count': 'count'}, title='Percentage of predicted categories')
157
  fig1.update_traces(textposition='inside', textinfo='percent+label')
158
  st.plotly_chart(fig1)
159
  if comet_initialized:
160
+ experiment.log_figure(figure=fig1, figure_name="category_pie_chart")
161
 
162
  with col2:
163
  st.subheader("Bar Chart", divider="red")
164
+ # Bar chart now visualizes the distribution of categories
165
+ fig2 = px.bar(final_df, x="count", y="category", color="category", text_auto=True, title='Occurrences of predicted categories')
166
  st.plotly_chart(fig2)
167
  if comet_initialized:
168
+ experiment.log_figure(figure=fig2, figure_name="category_bar_chart")
169
  else:
170
  st.info("No entities found in the provided text.")
171
 
 
173
  dfa = pd.DataFrame(
174
  data={
175
  'text': ['entity extracted from your text data'], 'score': ['accuracy score; how accurately a tag has been assigned to a given entity'], 'label': ['label (tag) assigned to a given extracted entity'],
176
+ 'category': ['the high-level category for the label'],
177
  'start': ['index of the start of the corresponding entity'],
178
  'end': ['index of the end of the corresponding entity'],
179
  })
 
192
  file_name="zip file.zip",
193
  mime="application/zip",
194
  )
 
 
 
195
  st.divider()
196
+
197
+ end_time = time.time()
198
+ elapsed_time = end_time - start_time
199
+ st.info(f"Results processed in **{elapsed_time:.2f} seconds**.")
200
+
201
+
202
+