AIEcosystem commited on
Commit
b8cd831
·
verified ·
1 Parent(s): ff2083e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +22 -88
src/streamlit_app.py CHANGED
@@ -8,8 +8,6 @@ import plotly.express as px
8
  import zipfile
9
  import json
10
  import hashlib
11
-
12
-
13
  from typing import Optional
14
  from gliner import GLiNER
15
  from comet_ml import Experiment
@@ -18,8 +16,6 @@ from comet_ml import Experiment
18
  st.set_page_config(layout="wide", page_title="NER")
19
  st.subheader("HR.ai", divider="green")
20
  st.link_button("by nlpblogs", "https://nlpblogs.com", type="tertiary")
21
-
22
-
23
  st.markdown(
24
  """
25
  <style>
@@ -67,40 +63,11 @@ st.markdown(
67
  background-color: #D4F4D4;
68
  color: #000000;
69
  }
70
-
71
  </style>
72
  """,
73
- unsafe_allow_html=True
74
- )
75
-
76
  expander = st.expander("**Important notes**")
77
- expander.write("""
78
- **How to Use the HR.ai web app:**
79
-
80
- 1. Type or paste your text into the text area, then press Ctrl + Enter.
81
- 2. Click the 'Results' button to extract and tag entities in your text data.
82
-
83
- Results are presented in easy-to-read tables, visualized in an interactive tree map, pie chart and bar chart, and are available for download along with a Glossary of tags.
84
-
85
- **How to Use the Question-Answering feature:**
86
-
87
- 1. Type or paste your text into the text area, then press Ctrl + Enter.
88
- 2. Click the 'Add Question' button to add your question to the Record of Questions. You can manage your questions by deleting them one by one.
89
- 3. Click the 'Extract Answers' button to extract the answer to your question.
90
-
91
- Results are presented in an easy-to-read table, visualized in an interactive tree map, and is available for download.
92
-
93
- **Entities:** "Email", "Phone_number", "Street_address", "City", "Country", "Date_of_birth", "Marital_status", "Person", "Full_time", "Part_time", "Contract", "Terminated", "Retired", "Job_title", "Date", "Organization", "Role", "Performance_score", "Leave_of_absence", "Retirement_plan", "Bonus", "Stock_options", "Health_insurance", "Pay_rate", "Annual_salary", "Tax", "Deductions", "Interview_type", "Applicant", "Referral", "Job_board", "Recruiter", "Offer_letter", "Agreement", "Certification", "Skill"
94
-
95
- **Usage Limits:** You can request results unlimited times for one (1) month.
96
-
97
- **Supported Languages:** English
98
-
99
- **Technical issues:** If your connection times out, please refresh the page or reopen the app's URL.
100
-
101
- For any errors or inquiries, please contact us at info@nlpblogs.com""")
102
-
103
-
104
  with st.sidebar:
105
  st.write("Use the following code to embed the web app on your website. Feel free to adjust the width and height values to fit your page.")
106
  code = '''
@@ -117,16 +84,13 @@ with st.sidebar:
117
  st.divider()
118
  st.subheader("🚀 Ready to build your own AI Web App?", divider="green")
119
  st.link_button("AI Web App Builder", "https://nlpblogs.com/build-your-named-entity-recognition-app/", type="primary")
120
-
121
  # --- Comet ML Setup ---
122
  COMET_API_KEY = os.environ.get("COMET_API_KEY")
123
  COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
124
  COMET_PROJECT_NAME = os.environ.get("COMET_PROJECT_NAME")
125
  comet_initialized = bool(COMET_API_KEY and COMET_WORKSPACE and COMET_PROJECT_NAME)
126
-
127
  if not comet_initialized:
128
  st.warning("Comet ML not initialized. Check environment variables.")
129
-
130
  # --- Model Loading and Caching ---
131
  @st.cache_resource
132
  def load_gliner_model(model_name):
@@ -139,10 +103,8 @@ def load_gliner_model(model_name):
139
  except Exception as e:
140
  st.error(f"Error loading the GLiNER model: {e}")
141
  st.stop()
142
-
143
  # --- HR_AI Model Labels and Mappings ---
144
  labels = ["Email", "Phone_number", "Street_address", "City", "Country", "Date_of_birth", "Marital_status", "Person", "Full_time", "Part_time", "Contract", "Terminated", "Retired", "Job_title", "Date", "Organization", "Role", "Performance_score", "Leave_of_absence", "Retirement_plan", "Bonus", "Stock_options", "Health_insurance", "Pay_rate", "Annual_salary", "Tax", "Deductions", "Interview_type", "Applicant", "Referral", "Job_board", "Recruiter", "Offer_letter", "Agreement", "Certification", "Skill"]
145
-
146
  category_mapping = {
147
  "Contact Information": ["Email", "Phone_number", "Street_address", "City", "Country"],
148
  "Personal Details": ["Date_of_birth", "Marital_status", "Person"],
@@ -155,51 +117,53 @@ category_mapping = {
155
  "Deductions": ["Tax", "Deductions"],
156
  "Recruitment & Sourcing": ["Interview_type", "Applicant", "Referral", "Job_board", "Recruiter"],
157
  "Legal & Compliance": ["Offer_letter", "Agreement"],
158
- "Professional_Development": ["Certification", "Skill"]
159
- }
160
  reverse_category_mapping = {label: category for category, label_list in category_mapping.items() for label in label_list}
161
-
162
  # --- InfoFinder Helpers ---
163
  if 'user_labels' not in st.session_state:
164
  st.session_state.user_labels = []
165
-
166
  def get_stable_color(label):
167
  hash_object = hashlib.sha1(label.encode('utf-8'))
168
  hex_dig = hash_object.hexdigest()
169
  return '#' + hex_dig[:6]
170
-
171
  # --- Main App with Tabs ---
172
  tab1, tab2 = st.tabs(["HR.ai", "Question-Answering"])
173
-
174
  with tab1:
175
-
176
-
177
  # Load model for this tab
178
  model_hr = load_gliner_model("HR_AI")
179
-
180
- text = st.text_area("Type or paste your text below, and then press Ctrl + Enter", height=250, key='my_text_area_hr')
181
-
 
 
 
 
 
 
 
182
  def clear_text_hr():
183
  st.session_state['my_text_area_hr'] = ""
184
-
185
  st.button("Clear text", on_click=clear_text_hr, key="clear_hr")
186
-
187
  if st.button("Results"):
188
  start_time = time.time()
 
 
189
  if not text.strip():
190
  st.warning("Please enter some text to extract entities.")
 
 
191
  else:
192
  with st.spinner("Extracting entities...", show_time=True):
193
  entities = model_hr.predict_entities(text, labels)
194
  df = pd.DataFrame(entities)
195
-
196
  if not df.empty:
197
  df['category'] = df['label'].map(reverse_category_mapping)
198
  if comet_initialized:
199
  experiment = Experiment(api_key=COMET_API_KEY, workspace=COMET_WORKSPACE, project_name=COMET_PROJECT_NAME)
200
  experiment.log_parameter("input_text", text)
201
  experiment.log_table("predicted_entities", df)
202
-
203
  st.subheader("Grouped Entities by Category", divider="green")
204
  category_names = sorted(list(category_mapping.keys()))
205
  category_tabs_hr = st.tabs(category_names)
@@ -210,7 +174,6 @@ with tab1:
210
  st.dataframe(df_category_filtered.drop(columns=['category']), use_container_width=True)
211
  else:
212
  st.info(f"No entities found for the '{category_name}' category.")
213
-
214
  with st.expander("See Glossary of tags"):
215
  st.write('''
216
  - **text**: ['entity extracted from your text data']
@@ -220,12 +183,10 @@ with tab1:
220
  - **end**: ['index of the end of the corresponding entity']
221
  ''')
222
  st.divider()
223
-
224
  st.subheader("Candidate Card", divider="green")
225
  fig_treemap = px.treemap(df, path=[px.Constant("all"), 'category', 'label', 'text'], values='score', color='category')
226
  fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F5FFFA', plot_bgcolor='#F5FFFA')
227
  st.plotly_chart(fig_treemap)
228
-
229
  col1, col2 = st.columns(2)
230
  with col1:
231
  st.subheader("Pie chart", divider="green")
@@ -235,13 +196,11 @@ with tab1:
235
  fig_pie.update_traces(textposition='inside', textinfo='percent+label')
236
  fig_pie.update_layout(paper_bgcolor='#F5FFFA', plot_bgcolor='#F5FFFA')
237
  st.plotly_chart(fig_pie)
238
-
239
  with col2:
240
  st.subheader("Bar chart", divider="green")
241
  fig_bar = px.bar(grouped_counts, x="count", y="category", color="category", text_auto=True, title='Occurrences of predicted categories')
242
  fig_bar.update_layout(paper_bgcolor='#F5FFFA', plot_bgcolor='#F5FFFA')
243
  st.plotly_chart(fig_bar)
244
-
245
  st.subheader("Most Frequent Entities", divider="green")
246
  word_counts = df['text'].value_counts().reset_index()
247
  word_counts.columns = ['Entity', 'Count']
@@ -253,50 +212,37 @@ with tab1:
253
  st.plotly_chart(fig_repeating_bar)
254
  else:
255
  st.warning("No entities were found that occur more than once.")
256
-
257
  st.divider()
258
-
259
  dfa = pd.DataFrame(data={'Column Name': ['text', 'label', 'score', 'start', 'end'], 'Description': ['entity extracted from your text data', 'label (tag) assigned to a given extracted entity', 'accuracy score; how accurately a tag has been assigned to a given entity', 'index of the start of the corresponding entity', 'index of the end of the corresponding entity']})
260
  buf = io.BytesIO()
261
  with zipfile.ZipFile(buf, "w") as myzip:
262
  myzip.writestr("Summary of the results.csv", df.to_csv(index=False))
263
  myzip.writestr("Glossary of tags.csv", dfa.to_csv(index=False))
264
-
265
  st.download_button(
266
  label="Download results and glossary (zip)",
267
  data=buf.getvalue(),
268
  file_name="nlpblogs_results.zip",
269
  mime="application/zip",
270
  )
271
-
272
  if comet_initialized:
273
  experiment.log_figure(figure=fig_treemap, figure_name="entity_treemap_categories")
274
  experiment.end()
275
  else:
276
  st.warning("No entities were found in the provided text.")
277
-
278
  end_time = time.time()
279
  elapsed_time = end_time - start_time
280
  st.text("")
281
  st.text("")
282
  st.info(f"Results processed in **{elapsed_time:.2f} seconds**.")
283
-
284
  with tab2:
285
-
286
-
287
  # Load model for this tab
288
  model_qa = load_gliner_model("InfoFinder")
289
-
290
  user_text = st.text_area("Type or paste your text below, and then press Ctrl + Enter", height=250, key='my_text_area_infofinder')
291
-
292
  def clear_text_qa():
293
  st.session_state['my_text_area_infofinder'] = ""
294
-
295
  st.button("Clear text", on_click=clear_text_qa, key="clear_qa")
296
-
297
  st.subheader("Question-Answering", divider="green")
298
  question_input = st.text_input("Ask wh-questions. **Wh-questions begin with what, when, where, who, whom, which, whose, why and how. We use them to ask for specific information.**")
299
-
300
  if st.button("Add Question"):
301
  if question_input:
302
  if question_input not in st.session_state.user_labels:
@@ -306,10 +252,8 @@ with tab2:
306
  st.warning("This question has already been added.")
307
  else:
308
  st.warning("Please enter a question.")
309
-
310
  st.markdown("---")
311
  st.subheader("Record of Questions", divider="green")
312
-
313
  if st.session_state.user_labels:
314
  for i, label in enumerate(st.session_state.user_labels):
315
  col_list, col_delete = st.columns([0.9, 0.1])
@@ -321,9 +265,7 @@ with tab2:
321
  st.rerun()
322
  else:
323
  st.info("No questions defined yet. Use the input above to add one.")
324
-
325
  st.divider()
326
-
327
  if st.button("Extract Answers"):
328
  if not user_text.strip():
329
  st.warning("Please enter some text to analyze.")
@@ -334,7 +276,6 @@ with tab2:
334
  experiment = Experiment(api_key=COMET_API_KEY, workspace=COMET_WORKSPACE, project_name=COMET_PROJECT_NAME)
335
  experiment.log_parameter("input_text_length", len(user_text))
336
  experiment.log_parameter("defined_labels", st.session_state.user_labels)
337
-
338
  start_time = time.time()
339
  with st.spinner("Analyzing text...", show_time=True):
340
  try:
@@ -342,27 +283,22 @@ with tab2:
342
  end_time = time.time()
343
  elapsed_time = end_time - start_time
344
  st.info(f"Processing took **{elapsed_time:.2f} seconds**.")
345
-
346
  if entities:
347
  df1 = pd.DataFrame(entities)
348
  df2 = df1[['label', 'text', 'score']]
349
  df = df2.rename(columns={'label': 'question', 'text': 'answer'})
350
-
351
  st.subheader("Extracted Answers", divider="green")
352
  expander = st.expander("**Download**")
353
- expander.write("""
354
- To download the data, simply hover your cursor over the table. A download icon will appear on the right side.
355
  """)
356
  st.dataframe(df, use_container_width=True)
357
-
358
  st.subheader("Tree map", divider="green")
359
  all_labels = df['question'].unique()
360
  label_color_map = {label: get_stable_color(label) for label in all_labels}
361
  fig_treemap = px.treemap(df, path=[px.Constant("all"), 'question', 'answer'], values='score', color='question', color_discrete_map=label_color_map)
362
  fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F3E5F5', plot_bgcolor='#F3E5F5')
363
  st.plotly_chart(fig_treemap)
364
-
365
-
366
  if comet_initialized:
367
  experiment.log_metric("processing_time_seconds", elapsed_time)
368
  experiment.log_table("predicted_entities", df)
@@ -377,6 +313,4 @@ with tab2:
377
  st.write(f"Error details: {e}")
378
  if comet_initialized:
379
  experiment.log_text(f"Error: {e}")
380
- experiment.end()
381
-
382
-
 
8
  import zipfile
9
  import json
10
  import hashlib
 
 
11
  from typing import Optional
12
  from gliner import GLiNER
13
  from comet_ml import Experiment
 
16
  st.set_page_config(layout="wide", page_title="NER")
17
  st.subheader("HR.ai", divider="green")
18
  st.link_button("by nlpblogs", "https://nlpblogs.com", type="tertiary")
 
 
19
  st.markdown(
20
  """
21
  <style>
 
63
  background-color: #D4F4D4;
64
  color: #000000;
65
  }
 
66
  </style>
67
  """,
68
+ unsafe_allow_html=True)
 
 
69
  expander = st.expander("**Important notes**")
70
+ expander.write(""" **How to Use the HR.ai web app:** 1. Type or paste your text into the text area, then press Ctrl + Enter.2. Click the 'Results' button to extract and tag entities in your text data. Results are presented in easy-to-read tables, visualized in an interactive tree map, pie chart and bar chart, and are available for download along with a Glossary of tags. **How to Use the Question-Answering feature:**1. Type or paste your text into the text area, then press Ctrl + Enter. 2. Click the 'Add Question' button to add your question to the Record of Questions. You can manage your questions by deleting them one by one.3. Click the 'Extract Answers' button to extract the answer to your question.Results are presented in an easy-to-read table, visualized in an interactive tree map, and is available for download. **Entities:** "Email", "Phone_number", "Street_address", "City", "Country", "Date_of_birth", "Marital_status", "Person", "Full_time", "Part_time", "Contract", "Terminated", "Retired", "Job_title", "Date", "Organization", "Role", "Performance_score", "Leave_of_absence", "Retirement_plan", "Bonus", "Stock_options", "Health_insurance", "Pay_rate", "Annual_salary", "Tax", "Deductions", "Interview_type", "Applicant", "Referral", "Job_board", "Recruiter", "Offer_letter", "Agreement", "Certification", "Skill"**Usage Limits:** You can request results unlimited times for one (1) month. **Supported Languages:** English **Technical issues:** If your connection times out, please refresh the page or reopen the app's URL. For any errors or inquiries, please contact us at info@nlpblogs.com""")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  with st.sidebar:
72
  st.write("Use the following code to embed the web app on your website. Feel free to adjust the width and height values to fit your page.")
73
  code = '''
 
84
  st.divider()
85
  st.subheader("🚀 Ready to build your own AI Web App?", divider="green")
86
  st.link_button("AI Web App Builder", "https://nlpblogs.com/build-your-named-entity-recognition-app/", type="primary")
 
87
  # --- Comet ML Setup ---
88
  COMET_API_KEY = os.environ.get("COMET_API_KEY")
89
  COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
90
  COMET_PROJECT_NAME = os.environ.get("COMET_PROJECT_NAME")
91
  comet_initialized = bool(COMET_API_KEY and COMET_WORKSPACE and COMET_PROJECT_NAME)
 
92
  if not comet_initialized:
93
  st.warning("Comet ML not initialized. Check environment variables.")
 
94
  # --- Model Loading and Caching ---
95
  @st.cache_resource
96
  def load_gliner_model(model_name):
 
103
  except Exception as e:
104
  st.error(f"Error loading the GLiNER model: {e}")
105
  st.stop()
 
106
  # --- HR_AI Model Labels and Mappings ---
107
  labels = ["Email", "Phone_number", "Street_address", "City", "Country", "Date_of_birth", "Marital_status", "Person", "Full_time", "Part_time", "Contract", "Terminated", "Retired", "Job_title", "Date", "Organization", "Role", "Performance_score", "Leave_of_absence", "Retirement_plan", "Bonus", "Stock_options", "Health_insurance", "Pay_rate", "Annual_salary", "Tax", "Deductions", "Interview_type", "Applicant", "Referral", "Job_board", "Recruiter", "Offer_letter", "Agreement", "Certification", "Skill"]
 
108
  category_mapping = {
109
  "Contact Information": ["Email", "Phone_number", "Street_address", "City", "Country"],
110
  "Personal Details": ["Date_of_birth", "Marital_status", "Person"],
 
117
  "Deductions": ["Tax", "Deductions"],
118
  "Recruitment & Sourcing": ["Interview_type", "Applicant", "Referral", "Job_board", "Recruiter"],
119
  "Legal & Compliance": ["Offer_letter", "Agreement"],
120
+ "Professional_Development": ["Certification", "Skill"]}
 
121
  reverse_category_mapping = {label: category for category, label_list in category_mapping.items() for label in label_list}
 
122
  # --- InfoFinder Helpers ---
123
  if 'user_labels' not in st.session_state:
124
  st.session_state.user_labels = []
 
125
  def get_stable_color(label):
126
  hash_object = hashlib.sha1(label.encode('utf-8'))
127
  hex_dig = hash_object.hexdigest()
128
  return '#' + hex_dig[:6]
 
129
  # --- Main App with Tabs ---
130
  tab1, tab2 = st.tabs(["HR.ai", "Question-Answering"])
 
131
  with tab1:
 
 
132
  # Load model for this tab
133
  model_hr = load_gliner_model("HR_AI")
134
+
135
+ # Define the word limit
136
+ word_limit = 200
137
+
138
+ text = st.text_area("Type or paste your text below (max 200 words), and then press Ctrl + Enter", height=250, key='my_text_area_hr')
139
+
140
+ # Calculate and display the word count
141
+ word_count = len(text.split())
142
+ st.markdown(f"**Word count:** {word_count}/{word_limit}")
143
+
144
  def clear_text_hr():
145
  st.session_state['my_text_area_hr'] = ""
146
+
147
  st.button("Clear text", on_click=clear_text_hr, key="clear_hr")
148
+
149
  if st.button("Results"):
150
  start_time = time.time()
151
+
152
+ # Check for word limit and empty text
153
  if not text.strip():
154
  st.warning("Please enter some text to extract entities.")
155
+ elif word_count > word_limit:
156
+ st.warning(f"Your text exceeds the {word_limit} word limit. Please shorten it to continue.")
157
  else:
158
  with st.spinner("Extracting entities...", show_time=True):
159
  entities = model_hr.predict_entities(text, labels)
160
  df = pd.DataFrame(entities)
 
161
  if not df.empty:
162
  df['category'] = df['label'].map(reverse_category_mapping)
163
  if comet_initialized:
164
  experiment = Experiment(api_key=COMET_API_KEY, workspace=COMET_WORKSPACE, project_name=COMET_PROJECT_NAME)
165
  experiment.log_parameter("input_text", text)
166
  experiment.log_table("predicted_entities", df)
 
167
  st.subheader("Grouped Entities by Category", divider="green")
168
  category_names = sorted(list(category_mapping.keys()))
169
  category_tabs_hr = st.tabs(category_names)
 
174
  st.dataframe(df_category_filtered.drop(columns=['category']), use_container_width=True)
175
  else:
176
  st.info(f"No entities found for the '{category_name}' category.")
 
177
  with st.expander("See Glossary of tags"):
178
  st.write('''
179
  - **text**: ['entity extracted from your text data']
 
183
  - **end**: ['index of the end of the corresponding entity']
184
  ''')
185
  st.divider()
 
186
  st.subheader("Candidate Card", divider="green")
187
  fig_treemap = px.treemap(df, path=[px.Constant("all"), 'category', 'label', 'text'], values='score', color='category')
188
  fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F5FFFA', plot_bgcolor='#F5FFFA')
189
  st.plotly_chart(fig_treemap)
 
190
  col1, col2 = st.columns(2)
191
  with col1:
192
  st.subheader("Pie chart", divider="green")
 
196
  fig_pie.update_traces(textposition='inside', textinfo='percent+label')
197
  fig_pie.update_layout(paper_bgcolor='#F5FFFA', plot_bgcolor='#F5FFFA')
198
  st.plotly_chart(fig_pie)
 
199
  with col2:
200
  st.subheader("Bar chart", divider="green")
201
  fig_bar = px.bar(grouped_counts, x="count", y="category", color="category", text_auto=True, title='Occurrences of predicted categories')
202
  fig_bar.update_layout(paper_bgcolor='#F5FFFA', plot_bgcolor='#F5FFFA')
203
  st.plotly_chart(fig_bar)
 
204
  st.subheader("Most Frequent Entities", divider="green")
205
  word_counts = df['text'].value_counts().reset_index()
206
  word_counts.columns = ['Entity', 'Count']
 
212
  st.plotly_chart(fig_repeating_bar)
213
  else:
214
  st.warning("No entities were found that occur more than once.")
 
215
  st.divider()
 
216
  dfa = pd.DataFrame(data={'Column Name': ['text', 'label', 'score', 'start', 'end'], 'Description': ['entity extracted from your text data', 'label (tag) assigned to a given extracted entity', 'accuracy score; how accurately a tag has been assigned to a given entity', 'index of the start of the corresponding entity', 'index of the end of the corresponding entity']})
217
  buf = io.BytesIO()
218
  with zipfile.ZipFile(buf, "w") as myzip:
219
  myzip.writestr("Summary of the results.csv", df.to_csv(index=False))
220
  myzip.writestr("Glossary of tags.csv", dfa.to_csv(index=False))
 
221
  st.download_button(
222
  label="Download results and glossary (zip)",
223
  data=buf.getvalue(),
224
  file_name="nlpblogs_results.zip",
225
  mime="application/zip",
226
  )
 
227
  if comet_initialized:
228
  experiment.log_figure(figure=fig_treemap, figure_name="entity_treemap_categories")
229
  experiment.end()
230
  else:
231
  st.warning("No entities were found in the provided text.")
 
232
  end_time = time.time()
233
  elapsed_time = end_time - start_time
234
  st.text("")
235
  st.text("")
236
  st.info(f"Results processed in **{elapsed_time:.2f} seconds**.")
 
237
  with tab2:
 
 
238
  # Load model for this tab
239
  model_qa = load_gliner_model("InfoFinder")
 
240
  user_text = st.text_area("Type or paste your text below, and then press Ctrl + Enter", height=250, key='my_text_area_infofinder')
 
241
  def clear_text_qa():
242
  st.session_state['my_text_area_infofinder'] = ""
 
243
  st.button("Clear text", on_click=clear_text_qa, key="clear_qa")
 
244
  st.subheader("Question-Answering", divider="green")
245
  question_input = st.text_input("Ask wh-questions. **Wh-questions begin with what, when, where, who, whom, which, whose, why and how. We use them to ask for specific information.**")
 
246
  if st.button("Add Question"):
247
  if question_input:
248
  if question_input not in st.session_state.user_labels:
 
252
  st.warning("This question has already been added.")
253
  else:
254
  st.warning("Please enter a question.")
 
255
  st.markdown("---")
256
  st.subheader("Record of Questions", divider="green")
 
257
  if st.session_state.user_labels:
258
  for i, label in enumerate(st.session_state.user_labels):
259
  col_list, col_delete = st.columns([0.9, 0.1])
 
265
  st.rerun()
266
  else:
267
  st.info("No questions defined yet. Use the input above to add one.")
 
268
  st.divider()
 
269
  if st.button("Extract Answers"):
270
  if not user_text.strip():
271
  st.warning("Please enter some text to analyze.")
 
276
  experiment = Experiment(api_key=COMET_API_KEY, workspace=COMET_WORKSPACE, project_name=COMET_PROJECT_NAME)
277
  experiment.log_parameter("input_text_length", len(user_text))
278
  experiment.log_parameter("defined_labels", st.session_state.user_labels)
 
279
  start_time = time.time()
280
  with st.spinner("Analyzing text...", show_time=True):
281
  try:
 
283
  end_time = time.time()
284
  elapsed_time = end_time - start_time
285
  st.info(f"Processing took **{elapsed_time:.2f} seconds**.")
 
286
  if entities:
287
  df1 = pd.DataFrame(entities)
288
  df2 = df1[['label', 'text', 'score']]
289
  df = df2.rename(columns={'label': 'question', 'text': 'answer'})
 
290
  st.subheader("Extracted Answers", divider="green")
291
  expander = st.expander("**Download**")
292
+ expander.write("""
293
+ To download the data, simply hover your cursor over the table. A download icon will appear on the right side.
294
  """)
295
  st.dataframe(df, use_container_width=True)
 
296
  st.subheader("Tree map", divider="green")
297
  all_labels = df['question'].unique()
298
  label_color_map = {label: get_stable_color(label) for label in all_labels}
299
  fig_treemap = px.treemap(df, path=[px.Constant("all"), 'question', 'answer'], values='score', color='question', color_discrete_map=label_color_map)
300
  fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F3E5F5', plot_bgcolor='#F3E5F5')
301
  st.plotly_chart(fig_treemap)
 
 
302
  if comet_initialized:
303
  experiment.log_metric("processing_time_seconds", elapsed_time)
304
  experiment.log_table("predicted_entities", df)
 
313
  st.write(f"Error details: {e}")
314
  if comet_initialized:
315
  experiment.log_text(f"Error: {e}")
316
+ experiment.end()