Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +86 -52
src/streamlit_app.py
CHANGED
|
@@ -58,37 +58,37 @@ st.markdown(
|
|
| 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 |
-
|
| 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.
|
|
|
|
|
|
|
| 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 |
-
|
| 86 |
-
src="https://aiecosystem-question-answering.hf.space"
|
| 87 |
frameborder="0"
|
| 88 |
width="850"
|
| 89 |
height="450"
|
| 90 |
></iframe>
|
| 91 |
-
|
| 92 |
st.code(code, language="html")
|
| 93 |
st.text("")
|
| 94 |
st.text("")
|
|
@@ -96,7 +96,6 @@ with st.sidebar:
|
|
| 96 |
st.subheader("🚀 Ready to build your own AI Web App?", divider="violet")
|
| 97 |
st.link_button("AI Web App Builder", " https://nlpblogs.com/custom-web-app-development/", type="primary")
|
| 98 |
|
| 99 |
-
|
| 100 |
# --- Comet ML Setup ---
|
| 101 |
COMET_API_KEY = os.environ.get("COMET_API_KEY")
|
| 102 |
COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
|
|
@@ -106,71 +105,64 @@ comet_initialized = bool(COMET_API_KEY and COMET_WORKSPACE and COMET_PROJECT_NAM
|
|
| 106 |
if not comet_initialized:
|
| 107 |
st.warning("Comet ML not initialized. Check environment variables.")
|
| 108 |
|
| 109 |
-
# --- Initialize session state for labels
|
| 110 |
if 'user_labels' not in st.session_state:
|
| 111 |
st.session_state.user_labels = []
|
| 112 |
-
if 'my_text_area' not in st.session_state:
|
| 113 |
-
st.session_state['my_text_area'] = ""
|
| 114 |
-
if 'question_input' not in st.session_state:
|
| 115 |
-
st.session_state['question_input'] = ""
|
| 116 |
|
| 117 |
# --- Model Loading and Caching ---
|
| 118 |
@st.cache_resource
|
| 119 |
def load_gliner_model():
|
| 120 |
-
"""
|
|
|
|
|
|
|
|
|
|
| 121 |
try:
|
| 122 |
-
return GLiNER.from_pretrained("knowledgator/gliner-multitask-
|
| 123 |
except Exception as e:
|
| 124 |
st.error(f"Error loading the GLiNER model: {e}")
|
| 125 |
st.stop()
|
| 126 |
|
|
|
|
| 127 |
model = load_gliner_model()
|
| 128 |
|
| 129 |
-
|
| 130 |
-
|
|
|
|
| 131 |
"""Clears the text area by resetting its value in session state."""
|
| 132 |
st.session_state['my_text_area'] = ""
|
|
|
|
| 133 |
|
| 134 |
-
|
| 135 |
-
st.button("Clear text", on_click=clear_text_area)
|
| 136 |
|
| 137 |
-
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
st.
|
| 144 |
-
st.success(f"Added question: {st.session_state.question_input}")
|
| 145 |
-
st.session_state.question_input = ""
|
| 146 |
else:
|
| 147 |
st.warning("This question has already been added.")
|
| 148 |
else:
|
| 149 |
st.warning("Please enter a question.")
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
"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. :",
|
| 154 |
-
key='question_input'
|
| 155 |
-
)
|
| 156 |
-
st.button("Add Question", on_click=add_question_callback)
|
| 157 |
-
|
| 158 |
-
st.markdown("---")
|
| 159 |
-
st.subheader("Record of Questions", divider="violet")
|
| 160 |
|
| 161 |
if st.session_state.user_labels:
|
| 162 |
def delete_label(label_to_delete):
|
| 163 |
"""Removes a label from the session state list."""
|
| 164 |
st.session_state.user_labels = [label for label in st.session_state.user_labels if label != label_to_delete]
|
| 165 |
st.rerun()
|
| 166 |
-
|
| 167 |
for label in st.session_state.user_labels:
|
| 168 |
col_list, col_delete = st.columns([0.9, 0.1])
|
| 169 |
with col_list:
|
| 170 |
st.write(f"- {label}")
|
| 171 |
with col_delete:
|
| 172 |
st.button("Delete", key=f"delete_{label}", on_click=delete_label, args=(label,))
|
| 173 |
-
|
| 174 |
st.button("Clear all questions", on_click=lambda: st.session_state.update({'user_labels': []}))
|
| 175 |
else:
|
| 176 |
st.info("No questions defined yet. Use the input above to add one.")
|
|
@@ -185,7 +177,7 @@ st.divider()
|
|
| 185 |
|
| 186 |
# --- Main Processing Logic ---
|
| 187 |
if st.button("Extract Answers"):
|
| 188 |
-
if not
|
| 189 |
st.warning("Please enter some text to analyze.")
|
| 190 |
elif not st.session_state.user_labels:
|
| 191 |
st.warning("Please define at least one question.")
|
|
@@ -196,30 +188,29 @@ if st.button("Extract Answers"):
|
|
| 196 |
workspace=COMET_WORKSPACE,
|
| 197 |
project_name=COMET_PROJECT_NAME
|
| 198 |
)
|
| 199 |
-
experiment.log_parameter("input_text_length", len(
|
| 200 |
experiment.log_parameter("defined_labels", st.session_state.user_labels)
|
| 201 |
|
| 202 |
start_time = time.time()
|
| 203 |
with st.spinner("Analyzing text...", show_time=True):
|
| 204 |
try:
|
| 205 |
-
entities = model.predict_entities(
|
| 206 |
end_time = time.time()
|
| 207 |
elapsed_time = end_time - start_time
|
| 208 |
st.info(f"Processing took **{elapsed_time:.2f} seconds**.")
|
| 209 |
-
|
| 210 |
if entities:
|
| 211 |
df1 = pd.DataFrame(entities)
|
| 212 |
df2 = df1[['label', 'text', 'score']]
|
| 213 |
df = df2.rename(columns={'label': 'question', 'text': 'answer'})
|
| 214 |
|
| 215 |
-
st.subheader("Extracted Answers", divider="violet")
|
| 216 |
st.dataframe(df, use_container_width=True)
|
| 217 |
-
|
| 218 |
# Create Tree map
|
| 219 |
st.subheader("Tree map", divider="violet")
|
| 220 |
all_labels = df['question'].unique()
|
| 221 |
label_color_map = {label: get_stable_color(label) for label in all_labels}
|
| 222 |
-
|
| 223 |
fig_treemap = px.treemap(
|
| 224 |
df,
|
| 225 |
path=[px.Constant("all"), 'question', 'answer'],
|
|
@@ -229,6 +220,8 @@ if st.button("Extract Answers"):
|
|
| 229 |
)
|
| 230 |
fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F3E5F5', plot_bgcolor='#F3E5F5')
|
| 231 |
st.plotly_chart(fig_treemap)
|
|
|
|
|
|
|
| 232 |
|
| 233 |
csv_data = df.to_csv(index=False).encode('utf-8')
|
| 234 |
with stylable_container(
|
|
@@ -241,12 +234,13 @@ if st.button("Extract Answers"):
|
|
| 241 |
file_name="nlpblogs_results.csv",
|
| 242 |
mime="text/csv",
|
| 243 |
)
|
| 244 |
-
|
| 245 |
if comet_initialized:
|
| 246 |
experiment.log_metric("processing_time_seconds", elapsed_time)
|
| 247 |
experiment.log_table("predicted_entities", df)
|
| 248 |
experiment.log_figure(figure=fig_treemap, figure_name="entity_treemap")
|
| 249 |
-
|
|
|
|
| 250 |
experiment.end()
|
| 251 |
else:
|
| 252 |
st.info("No answers were found in the text with the defined questions.")
|
|
@@ -257,4 +251,44 @@ if st.button("Extract Answers"):
|
|
| 257 |
st.write(f"Error details: {e}")
|
| 258 |
if comet_initialized:
|
| 259 |
experiment.log_text(f"Error: {e}")
|
| 260 |
-
experiment.end()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
unsafe_allow_html=True
|
| 59 |
)
|
| 60 |
|
| 61 |
+
|
| 62 |
# --- Page Configuration and UI Elements ---
|
| 63 |
st.set_page_config(layout="wide", page_title="Named Entity Recognition App")
|
| 64 |
st.subheader("InfoFinder", divider="violet")
|
| 65 |
st.link_button("by nlpblogs", "https://nlpblogs.com", type="tertiary")
|
| 66 |
|
| 67 |
expander = st.expander("**Important notes**")
|
| 68 |
+
expander.write("""**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.
|
| 72 |
+
|
| 73 |
+
Results are presented in an easy-to-read table, visualized in an interactive tree map and are available for download.
|
| 74 |
|
| 75 |
**Usage Limits:** You can request results unlimited times for one (1) month.
|
| 76 |
|
| 77 |
+
**Supported Languages:** English
|
| 78 |
|
| 79 |
**Technical issues:** If your connection times out, please refresh the page or reopen the app's URL.
|
| 80 |
|
| 81 |
+
For any errors or inquiries, please contact us at info@nlpblogs.com""")
|
|
|
|
| 82 |
|
| 83 |
with st.sidebar:
|
| 84 |
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.")
|
| 85 |
code = '''
|
| 86 |
+
src="https://aiecosystem-question-answering.hf.space"
|
|
|
|
| 87 |
frameborder="0"
|
| 88 |
width="850"
|
| 89 |
height="450"
|
| 90 |
></iframe>
|
| 91 |
+
'''
|
| 92 |
st.code(code, language="html")
|
| 93 |
st.text("")
|
| 94 |
st.text("")
|
|
|
|
| 96 |
st.subheader("🚀 Ready to build your own AI Web App?", divider="violet")
|
| 97 |
st.link_button("AI Web App Builder", " https://nlpblogs.com/custom-web-app-development/", type="primary")
|
| 98 |
|
|
|
|
| 99 |
# --- Comet ML Setup ---
|
| 100 |
COMET_API_KEY = os.environ.get("COMET_API_KEY")
|
| 101 |
COMET_WORKSPACE = os.environ.get("COMET_WORKSPACE")
|
|
|
|
| 105 |
if not comet_initialized:
|
| 106 |
st.warning("Comet ML not initialized. Check environment variables.")
|
| 107 |
|
| 108 |
+
# --- Initialize session state for labels ---
|
| 109 |
if 'user_labels' not in st.session_state:
|
| 110 |
st.session_state.user_labels = []
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
# --- Model Loading and Caching ---
|
| 113 |
@st.cache_resource
|
| 114 |
def load_gliner_model():
|
| 115 |
+
"""
|
| 116 |
+
Initializes and caches the GLiNER model.
|
| 117 |
+
This ensures the model is only loaded once, improving performance.
|
| 118 |
+
"""
|
| 119 |
try:
|
| 120 |
+
return GLiNER.from_pretrained("knowledgator/gliner-multitask-large-v0.5", device="cpu")
|
| 121 |
except Exception as e:
|
| 122 |
st.error(f"Error loading the GLiNER model: {e}")
|
| 123 |
st.stop()
|
| 124 |
|
| 125 |
+
# Load the model
|
| 126 |
model = load_gliner_model()
|
| 127 |
|
| 128 |
+
user_text = st.text_area("Type or paste your text below, and then press Ctrl + Enter", height=250, key='my_text_area')
|
| 129 |
+
|
| 130 |
+
def clear_text():
|
| 131 |
"""Clears the text area by resetting its value in session state."""
|
| 132 |
st.session_state['my_text_area'] = ""
|
| 133 |
+
st.button("Clear text", on_click=clear_text)
|
| 134 |
|
| 135 |
+
st.subheader("Question-Answering", divider = "violet")
|
|
|
|
| 136 |
|
| 137 |
+
# Replaced two columns with a single text input
|
| 138 |
+
question_input = st.text_input("Ask wh-questions.")
|
| 139 |
+
st.write("**Wh-questions begin with what, when, where, who, whom, which, whose, why and how. We use them to ask for specific information.**")
|
| 140 |
|
| 141 |
+
if st.button("Add Question"):
|
| 142 |
+
if question_input:
|
| 143 |
+
if question_input not in st.session_state.user_labels:
|
| 144 |
+
st.session_state.user_labels.append(question_input)
|
| 145 |
+
st.success(f"Added question: {question_input}")
|
|
|
|
|
|
|
| 146 |
else:
|
| 147 |
st.warning("This question has already been added.")
|
| 148 |
else:
|
| 149 |
st.warning("Please enter a question.")
|
| 150 |
+
st.markdown("---")
|
| 151 |
+
|
| 152 |
+
st.subheader("Record of Questions", divider = "violet")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
|
| 154 |
if st.session_state.user_labels:
|
| 155 |
def delete_label(label_to_delete):
|
| 156 |
"""Removes a label from the session state list."""
|
| 157 |
st.session_state.user_labels = [label for label in st.session_state.user_labels if label != label_to_delete]
|
| 158 |
st.rerun()
|
| 159 |
+
|
| 160 |
for label in st.session_state.user_labels:
|
| 161 |
col_list, col_delete = st.columns([0.9, 0.1])
|
| 162 |
with col_list:
|
| 163 |
st.write(f"- {label}")
|
| 164 |
with col_delete:
|
| 165 |
st.button("Delete", key=f"delete_{label}", on_click=delete_label, args=(label,))
|
|
|
|
| 166 |
st.button("Clear all questions", on_click=lambda: st.session_state.update({'user_labels': []}))
|
| 167 |
else:
|
| 168 |
st.info("No questions defined yet. Use the input above to add one.")
|
|
|
|
| 177 |
|
| 178 |
# --- Main Processing Logic ---
|
| 179 |
if st.button("Extract Answers"):
|
| 180 |
+
if not user_text.strip():
|
| 181 |
st.warning("Please enter some text to analyze.")
|
| 182 |
elif not st.session_state.user_labels:
|
| 183 |
st.warning("Please define at least one question.")
|
|
|
|
| 188 |
workspace=COMET_WORKSPACE,
|
| 189 |
project_name=COMET_PROJECT_NAME
|
| 190 |
)
|
| 191 |
+
experiment.log_parameter("input_text_length", len(user_text))
|
| 192 |
experiment.log_parameter("defined_labels", st.session_state.user_labels)
|
| 193 |
|
| 194 |
start_time = time.time()
|
| 195 |
with st.spinner("Analyzing text...", show_time=True):
|
| 196 |
try:
|
| 197 |
+
entities = model.predict_entities(user_text, st.session_state.user_labels)
|
| 198 |
end_time = time.time()
|
| 199 |
elapsed_time = end_time - start_time
|
| 200 |
st.info(f"Processing took **{elapsed_time:.2f} seconds**.")
|
| 201 |
+
|
| 202 |
if entities:
|
| 203 |
df1 = pd.DataFrame(entities)
|
| 204 |
df2 = df1[['label', 'text', 'score']]
|
| 205 |
df = df2.rename(columns={'label': 'question', 'text': 'answer'})
|
| 206 |
|
| 207 |
+
st.subheader("Extracted Answers", divider = "violet")
|
| 208 |
st.dataframe(df, use_container_width=True)
|
| 209 |
+
|
| 210 |
# Create Tree map
|
| 211 |
st.subheader("Tree map", divider="violet")
|
| 212 |
all_labels = df['question'].unique()
|
| 213 |
label_color_map = {label: get_stable_color(label) for label in all_labels}
|
|
|
|
| 214 |
fig_treemap = px.treemap(
|
| 215 |
df,
|
| 216 |
path=[px.Constant("all"), 'question', 'answer'],
|
|
|
|
| 220 |
)
|
| 221 |
fig_treemap.update_layout(margin=dict(t=50, l=25, r=25, b=25), paper_bgcolor='#F3E5F5', plot_bgcolor='#F3E5F5')
|
| 222 |
st.plotly_chart(fig_treemap)
|
| 223 |
+
|
| 224 |
+
|
| 225 |
|
| 226 |
csv_data = df.to_csv(index=False).encode('utf-8')
|
| 227 |
with stylable_container(
|
|
|
|
| 234 |
file_name="nlpblogs_results.csv",
|
| 235 |
mime="text/csv",
|
| 236 |
)
|
| 237 |
+
|
| 238 |
if comet_initialized:
|
| 239 |
experiment.log_metric("processing_time_seconds", elapsed_time)
|
| 240 |
experiment.log_table("predicted_entities", df)
|
| 241 |
experiment.log_figure(figure=fig_treemap, figure_name="entity_treemap")
|
| 242 |
+
experiment.log_figure(figure=fig_pie, figure_name="entity_pie_chart")
|
| 243 |
+
experiment.log_figure(figure=fig_bar, figure_name="entity_bar_chart")
|
| 244 |
experiment.end()
|
| 245 |
else:
|
| 246 |
st.info("No answers were found in the text with the defined questions.")
|
|
|
|
| 251 |
st.write(f"Error details: {e}")
|
| 252 |
if comet_initialized:
|
| 253 |
experiment.log_text(f"Error: {e}")
|
| 254 |
+
experiment.end()
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
|