AIEcosystem commited on
Commit
ce390aa
·
verified ·
1 Parent(s): b723fc1

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +253 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,255 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ os.environ['HF_HOME'] = '/tmp'
3
+ import time
4
  import streamlit as st
5
+ import pandas as pd
6
+ import io
7
+ import plotly.express as px
8
+ import zipfile
9
+ import hashlib
10
+ from gliner import GLiNER
11
+ from streamlit_extras.stylable_container import stylable_container
12
+ from comet_ml import Experiment
13
+
14
+ st.markdown(
15
+ """
16
+ <style>
17
+ /* Main app background and text color */
18
+ .stApp {
19
+ background-color: #F3E5F5; /* A very light purple */
20
+ color: #1A0A26; /* Dark purple for the text */
21
+ }
22
+ /* Sidebar background color */
23
+ .css-1d36184 {
24
+ background-color: #D1C4E9; /* A medium light purple */
25
+ secondary-background-color: #D1C4E9;
26
+ }
27
+ /* Expander background color and header */
28
+ .streamlit-expanderContent, .streamlit-expanderHeader {
29
+ background-color: #F3E5F5;
30
+ }
31
+ /* Text Area background and text color */
32
+ .stTextArea textarea {
33
+ background-color: #B39DDB; /* A slightly darker medium purple */
34
+ color: #1A0A26; /* Dark purple for text */
35
+ }
36
+ /* Text Input background and text color */
37
+ .stTextInput input {
38
+ background-color: #B39DDB; /* Same as the text area for consistency */
39
+ color: #1A0A26;
40
+ }
41
+ /* Button background and text color */
42
+ .stButton > button {
43
+ background-color: #B39DDB;
44
+ color: #1A0A26;
45
+ }
46
+ /* Warning box background and text color */
47
+ .stAlert.st-warning {
48
+ background-color: #9575CD; /* A medium-dark purple for the warning box */
49
+ color: #1A0A26;
50
+ }
51
+ /* Success box background and text color */
52
+ .stAlert.st-success {
53
+ background-color: #9575CD; /* A medium-dark purple for the success box */
54
+ color: #1A0A26;
55
+ }
56
+ </style>
57
+ """,
58
+ unsafe_allow_html=True
59
+ )
60
+
61
+ # --- Page Configuration and UI Elements ---
62
+ st.set_page_config(layout="wide", page_title="Named Entity Recognition App")
63
+ st.subheader("InfoFinder", divider="violet")
64
+ st.link_button("by nlpblogs", "https://nlpblogs.com", type="tertiary")
65
+
66
+ expander = st.expander("**Important notes**")
67
+ expander.write("""
68
+ **How to Use:**
69
+ 1. Type or paste your text into the text area below, then press Ctrl + Enter.
70
+ 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 or by clearing the entire list.
71
+ 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 are available for download.
72
+
73
+ **Usage Limits:** You can request results unlimited times for one (1) month.
74
+
75
+ **Supported Languages:** English
76
+
77
+ **Technical issues:** If your connection times out, please refresh the page or reopen the app's URL.
78
+
79
+ For any errors or inquiries, please contact us at info@nlpblogs.com
80
+ """)
81
+
82
+ with st.sidebar:
83
+ st.write("Use the following code to embed the InfoFinder web app on your website. Feel free to adjust the width and height values to fit your page.")
84
+ code = '''
85
+ <iframe src="https://aiecosystem-mediatagger.hf.space" frameborder="0" width="850" height="450"></iframe>
86
+ '''
87
+ st.code(code, language="html")
88
+ st.text("")
89
+ st.text("")
90
+ st.divider()
91
+ st.subheader("🚀 Ready to build your own AI Web App?", divider="violet")
92
+ st.link_button("AI Web App Builder", " https://nlpblogs.com/custom-web-app-development/", type="primary")
93
+
94
+
95
+ # --- Comet ML Setup ---
96
+ COMET_API_KEY = os.environ.get("COMET_API_KEY")
97
+ COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
98
+ COMET_PROJECT_NAME = os.environ.get("COMET_PROJECT_NAME")
99
+ comet_initialized = bool(COMET_API_KEY and COMET_WORKSPACE and COMET_PROJECT_NAME)
100
+
101
+ if not comet_initialized:
102
+ st.warning("Comet ML not initialized. Check environment variables.")
103
+
104
+ # --- Initialize session state for labels and inputs ---
105
+ if 'user_labels' not in st.session_state:
106
+ st.session_state.user_labels = []
107
+ if 'my_text_area' not in st.session_state:
108
+ st.session_state['my_text_area'] = ""
109
+ if 'question_input' not in st.session_state:
110
+ st.session_state['question_input'] = ""
111
+
112
+ # --- Model Loading and Caching ---
113
+ @st.cache_resource
114
+ def load_model():
115
+ """Initializes and caches the GLiNER model."""
116
+ try:
117
+ return GLiNER.from_pretrained("knowledgator/gliner-multitask-v1.0", device="cpu")
118
+ except Exception as e:
119
+ st.error(f"Error loading the GLiNER model: {e}")
120
+ st.stop()
121
+
122
+ model = load_gliner_model()
123
+
124
+ # --- Text Area and Clear Button ---
125
+ def clear_text_area():
126
+ """Clears the text area by resetting its value in session state."""
127
+ st.session_state['my_text_area'] = ""
128
+
129
+ user_text = st.text_area("Type or paste your text below, and then press Ctrl + Enter", height=250, key='my_text_area')
130
+ st.button("Clear text", on_click=clear_text_area)
131
+
132
+ st.subheader("Question-Answering", divider="violet")
133
+
134
+ def add_question_callback():
135
+ """Callback to add the question and clear the input."""
136
+ if st.session_state.question_input:
137
+ if st.session_state.question_input not in st.session_state.user_labels:
138
+ st.session_state.user_labels.append(st.session_state.question_input)
139
+ st.success(f"Added question: {st.session_state.question_input}")
140
+ st.session_state.question_input = ""
141
+ else:
142
+ st.warning("This question has already been added.")
143
+ else:
144
+ st.warning("Please enter a question.")
145
+
146
+ # The `st.columns` call has been removed.
147
+ question_input = st.text_input(
148
+ "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. :",
149
+ key='question_input'
150
+ )
151
+ st.button("Add Question", on_click=add_question_callback)
152
+
153
+ st.markdown("---")
154
+ st.subheader("Record of Questions", divider="violet")
155
+
156
+ if st.session_state.user_labels:
157
+ def delete_label(label_to_delete):
158
+ """Removes a label from the session state list."""
159
+ st.session_state.user_labels = [label for label in st.session_state.user_labels if label != label_to_delete]
160
+ st.rerun()
161
+
162
+ for label in st.session_state.user_labels:
163
+ col_list, col_delete = st.columns([0.9, 0.1])
164
+ with col_list:
165
+ st.write(f"- {label}")
166
+ with col_delete:
167
+ st.button("Delete", key=f"delete_{label}", on_click=delete_label, args=(label,))
168
+
169
+ st.button("Clear all questions", on_click=lambda: st.session_state.update({'user_labels': []}))
170
+ else:
171
+ st.info("No questions defined yet. Use the input above to add one.")
172
+
173
+ def get_stable_color(label):
174
+ """Generates a consistent hexadecimal color from a given string."""
175
+ hash_object = hashlib.sha1(label.encode('utf-8'))
176
+ hex_dig = hash_object.hexdigest()
177
+ return '#' + hex_dig[:6]
178
+
179
+ st.divider()
180
+
181
+ # --- Main Processing Logic ---
182
+ if st.button("Extract Answers"):
183
+ if not st.session_state.my_text_area.strip():
184
+ st.warning("Please enter some text to analyze.")
185
+ elif not st.session_state.user_labels:
186
+ st.warning("Please define at least one question.")
187
+ else:
188
+ if comet_initialized:
189
+ experiment = Experiment(
190
+ api_key=COMET_API_KEY,
191
+ workspace=COMET_WORKSPACE,
192
+ project_name=COMET_PROJECT_NAME
193
+ )
194
+ experiment.log_parameter("input_text_length", len(st.session_state.my_text_area))
195
+ experiment.log_parameter("defined_labels", st.session_state.user_labels)
196
 
197
+ start_time = time.time()
198
+ with st.spinner("Analyzing text...", show_time=True):
199
+ try:
200
+ entities = model.predict_entities(st.session_state.my_text_area, st.session_state.user_labels)
201
+ end_time = time.time()
202
+ elapsed_time = end_time - start_time
203
+ st.info(f"Processing took **{elapsed_time:.2f} seconds**.")
204
+
205
+ if entities:
206
+ df1 = pd.DataFrame(entities)
207
+ df2 = df1[['label', 'text', 'score']]
208
+ df = df2.rename(columns={'label': 'question', 'text': 'answer'})
209
+
210
+ st.subheader("Extracted Answers", divider="violet")
211
+ st.dataframe(df, use_container_width=True)
212
+
213
+ # Create Tree map
214
+ st.subheader("Tree map", divider="violet")
215
+ all_labels = df['question'].unique()
216
+ label_color_map = {label: get_stable_color(label) for label in all_labels}
217
+
218
+ fig_treemap = px.treemap(
219
+ df,
220
+ path=[px.Constant("all"), 'question', 'answer'],
221
+ values='score',
222
+ color='question',
223
+ color_discrete_map=label_color_map
224
+ )
225
+ fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F3E5F5', plot_bgcolor='#F3E5F5')
226
+ st.plotly_chart(fig_treemap)
227
+
228
+ csv_data = df.to_csv(index=False).encode('utf-8')
229
+ with stylable_container(
230
+ key="download_button",
231
+ css_styles="""button { background-color: red; border: 1px solid black; padding: 5px; color: white; }""",
232
+ ):
233
+ st.download_button(
234
+ label="Download CSV",
235
+ data=csv_data,
236
+ file_name="nlpblogs_results.csv",
237
+ mime="text/csv",
238
+ )
239
+
240
+ if comet_initialized:
241
+ experiment.log_metric("processing_time_seconds", elapsed_time)
242
+ experiment.log_table("predicted_entities", df)
243
+ experiment.log_figure(figure=fig_treemap, figure_name="entity_treemap")
244
+ # The original code references fig_pie and fig_bar, which aren't created
245
+ experiment.end()
246
+ else:
247
+ st.info("No answers were found in the text with the defined questions.")
248
+ if comet_initialized:
249
+ experiment.end()
250
+ except Exception as e:
251
+ st.error(f"An error occurred during processing: {e}")
252
+ st.write(f"Error details: {e}")
253
+ if comet_initialized:
254
+ experiment.log_text(f"Error: {e}")
255
+ experiment.end()