mgbam commited on
Commit
45ea80d
Β·
verified Β·
1 Parent(s): 21067cf

Update pages/2_Consult.py

Browse files
Files changed (1) hide show
  1. pages/2_Consult.py +216 -155
pages/2_Consult.py CHANGED
@@ -1,193 +1,254 @@
 
1
  import streamlit as st
2
- from langchain.schema import HumanMessage, AIMessage, SystemMessage
3
  from datetime import datetime
4
- from typing import List, Union, Optional
5
  from sqlmodel import select
6
 
7
  from config.settings import settings
8
- from agent import get_agent_executor # Returns the configured Gemini-based agent executor
9
  from models import ChatMessage, ChatSession
10
  from models.db import get_session_context
11
  from services.logger import app_logger
12
- from services.metrics import log_consultation_start
13
 
14
  # --- Authentication Check ---
15
  if not st.session_state.get("authenticated_user_id"):
16
  st.warning("Please log in to access the consultation page.")
17
  try:
18
- st.switch_page("app.py")
19
  except st.errors.StreamlitAPIException:
 
20
  st.info("Please navigate to the main login page.")
21
- st.stop()
22
 
23
- # Retrieve authenticated user info
24
- authenticated_user_id = st.session_state["authenticated_user_id"]
25
- authenticated_username = st.session_state.get("authenticated_username", "User")
26
  app_logger.info(f"User '{authenticated_username}' (ID: {authenticated_user_id}) accessed Consult page.")
27
 
28
- # --- Initialize AI Agent ---
 
29
  try:
30
  agent_executor = get_agent_executor()
31
- app_logger.info("Gemini-based agent executor initialized for Consult page.")
32
- except ValueError as e:
33
  st.error(f"AI Agent Initialization Error: {e}")
34
- app_logger.critical(f"Fatal: AI Agent init failed: {e}", exc_info=True)
35
- st.info("Ensure API keys (e.g., Gemini) are configured in settings or environment.")
36
  st.stop()
37
- except Exception as e:
38
- st.error(f"Unexpected error initializing AI Agent: {e}")
39
- app_logger.critical(f"Fatal: Unexpected AI Agent init error: {e}", exc_info=True)
40
  st.stop()
41
 
42
- # --- Session State Setup ---
43
- st.session_state.setdefault('current_consult_patient_context', {})
44
- st.session_state.setdefault('consult_context_submitted', False)
45
 
46
- @st.cache_data(ttl=30, show_spinner=False)
47
- def load_chat_history(session_id: int) -> List[Union[HumanMessage, AIMessage, SystemMessage]]:
48
- """
49
- Load chat history from the database and convert to LangChain messages.
50
- """
51
- history: List[Union[HumanMessage, AIMessage, SystemMessage]] = []
52
- with get_session_context() as db:
53
- stmt = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)
54
- for msg in db.exec(stmt).all():
55
- if msg.role == "user":
56
- history.append(HumanMessage(content=msg.content))
57
- elif msg.role == "assistant":
58
- history.append(AIMessage(content=msg.content))
59
- elif msg.role == "system":
60
- history.append(SystemMessage(content=msg.content))
61
- return history
62
-
63
-
64
- def save_message(session_id: int, role: str, content: str, tool_call_id: Optional[str] = None, tool_name: Optional[str] = None):
65
- """
66
- Persist a chat message to the database.
67
- """
68
- with get_session_context() as db:
69
- obj = ChatMessage(
70
- session_id=session_id,
71
- role=role,
72
- content=content,
73
- timestamp=datetime.utcnow(),
74
- tool_call_id=tool_call_id,
75
- tool_name=tool_name,
76
- )
77
- db.add(obj)
78
- app_logger.info(f"Saved {role} message to DB for session {session_id}.")
79
-
80
-
81
- def update_session_context(session_id: int, summary: str):
82
- """
83
- Update the ChatSession record with a summary of patient context.
84
- """
85
- with get_session_context() as db:
86
- session = db.get(ChatSession, session_id)
87
- if session:
88
- session.patient_context_summary = summary
89
- db.add(session)
90
- app_logger.info(f"Updated session {session_id} with context summary.")
91
- else:
92
- app_logger.error(f"ChatSession {session_id} not found.")
93
-
94
- # --- Page Header ---
 
 
 
 
 
 
 
 
 
 
 
 
95
  st.title("AI Consultation Room")
96
- st.markdown(f"**User:** {authenticated_username}")
97
- st.info(f"{settings.MAIN_DISCLAIMER_SHORT} Use only anonymized, simulated data.")
 
 
98
 
99
- # --- Ensure Chat Session Exists ---
100
  chat_session_id = st.session_state.get("current_chat_session_id")
101
  if not chat_session_id:
102
- st.error("No active chat session. Please log out and log back in.")
103
- app_logger.error("Missing current_chat_session_id in session_state.")
104
  st.stop()
105
 
106
- # --- Step 1: Patient Context Input ---
107
  if not st.session_state.consult_context_submitted:
108
- st.subheader("Step 1: Provide Patient Context (Optional)")
109
- with st.form("context_form"):
110
- age = st.number_input("Patient Age (Sim)", min_value=0, max_value=120, step=1)
111
- gender = st.selectbox("Patient Gender (Sim)", ["Not Specified", "Male", "Female", "Other"], index=0)
112
- complaint = st.text_area("Chief Complaint (Sim)", height=80)
113
- history = st.text_area("Key Medical History (Sim)", height=80)
114
- meds = st.text_area("Current Medications (Sim)", height=80)
115
- submit = st.form_submit_button("Start Consult")
116
-
117
- if submit:
118
- raw = {"Age": age, "Gender": gender, "Complaint": complaint.strip(), "History": history.strip(), "Meds": meds.strip()}
119
- filtered = {k: v for k, v in raw.items() if v and not (isinstance(v, str) and v == "Not Specified")}
120
- st.session_state.current_consult_patient_context = filtered
121
-
122
- summary = "; ".join(f"{k}: {v}" for k, v in filtered.items()) if filtered else "No patient context provided."
123
- update_session_context(chat_session_id, summary)
124
- save_message(chat_session_id, "system", f"Context: {summary}")
125
- st.session_state.consult_context_submitted = True
126
- app_logger.info(f"Context for session {chat_session_id}: {summary}")
127
- st.experimental_rerun()
128
- st.stop()
129
-
130
- # --- Step 2: Chat Interface ---
131
- st.subheader("Step 2: Interact with the AI")
132
- history_key = f"history_{chat_session_id}"
133
- if history_key not in st.session_state:
134
- st.session_state[history_key] = load_chat_history(chat_session_id)
135
- if not st.session_state[history_key]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  try:
137
- log_consultation_start(authenticated_user_id, chat_session_id)
138
- except:
139
- pass
140
- greeting = "Hello! I'm your AI Health Navigator. How can I assist today?"
141
- if st.session_state.current_consult_patient_context:
142
- greeting += " (Patient context noted.)"
143
- st.session_state[history_key].append(AIMessage(content=greeting))
144
- save_message(chat_session_id, "assistant", greeting)
145
-
146
- # Display chat messages
147
- with st.container(height=400):
 
 
 
 
 
 
 
148
  with get_session_context() as db:
149
  stmt = select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)
150
- for msg in db.exec(stmt):
151
- if msg.role == "system":
152
- continue
153
- avatar = "πŸ§‘β€βš•οΈ" if msg.role == "assistant" else "πŸ‘€"
154
- if msg.role == "tool":
155
- avatar = "πŸ› οΈ"
156
- with st.chat_message(msg.role, avatar=avatar):
157
- st.markdown(msg.content)
158
-
159
- # Capture user input
160
- if user_input := st.chat_input("Ask the AI..."):
161
- with st.chat_message("user", avatar="πŸ‘€"):
162
- st.markdown(user_input)
163
- save_message(chat_session_id, "user", user_input)
164
- st.session_state[history_key].append(HumanMessage(content=user_input))
165
-
166
- with st.chat_message("assistant", avatar="πŸ§‘β€βš•οΈ"):
167
- with st.spinner("AI is thinking..."):
 
 
 
 
 
 
168
  try:
169
- # Prepare invocation payload
170
- context_str = "; ".join(f"{k}: {v}" for k, v in st.session_state.current_consult_patient_context.items())
171
- if not context_str:
172
- context_str = "No patient context provided."
173
-
174
- payload = {
175
- "input": user_input,
176
- "chat_history": st.session_state[history_key],
177
- "patient_context": context_str,
 
 
 
 
178
  }
179
- app_logger.debug(f"Invoking agent: {payload}")
180
- result = agent_executor.invoke(payload)
181
- output = str(result.get("output", "No response generated."))
182
-
183
- app_logger.info(f"Agent output: {output[:100]}")
184
- st.markdown(output)
185
- save_message(chat_session_id, "assistant", output)
186
- st.session_state[history_key].append(AIMessage(content=output))
 
 
 
 
 
 
 
 
187
  except Exception as e:
188
- app_logger.error(f"Error during agent invocation: {e}", exc_info=True)
189
- error_msg = f"Sorry, an error occurred ({type(e).__name__})."
190
- st.error(error_msg)
191
- save_message(chat_session_id, "assistant", error_msg)
192
- st.session_state[history_key].append(AIMessage(content=error_msg))
193
- st.experimental_rerun()
 
 
 
 
 
 
1
+ # /home/user/app/pages/2_Consult.py
2
  import streamlit as st
3
+ from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
4
  from datetime import datetime
5
+ from typing import List, Optional, Dict, Any
6
  from sqlmodel import select
7
 
8
  from config.settings import settings
9
+ from agent import get_agent_executor # This now returns the OpenAI-based agent executor
10
  from models import ChatMessage, ChatSession
11
  from models.db import get_session_context
12
  from services.logger import app_logger
13
+ from services.metrics import log_consultation_start # Assuming this function exists
14
 
15
  # --- Authentication Check ---
16
  if not st.session_state.get("authenticated_user_id"):
17
  st.warning("Please log in to access the consultation page.")
18
  try:
19
+ st.switch_page("app.py") # Redirect to the main login page (app.py)
20
  except st.errors.StreamlitAPIException:
21
+ # This can happen if st.switch_page is called when not in a multipage app context (e.g. dev)
22
  st.info("Please navigate to the main login page.")
23
+ st.stop() # Halt script execution
24
 
25
+ authenticated_user_id = st.session_state.get("authenticated_user_id")
26
+ authenticated_username = st.session_state.get("authenticated_username", "User") # Default to "User"
 
27
  app_logger.info(f"User '{authenticated_username}' (ID: {authenticated_user_id}) accessed Consult page.")
28
 
29
+ # --- Initialize Agent ---
30
+ # This will now initialize the OpenAI agent via get_agent_executor() from agent.py
31
  try:
32
  agent_executor = get_agent_executor()
33
+ app_logger.info("OpenAI-based agent executor initialized successfully for Consult page.")
34
+ except ValueError as e: # Catch specific error from get_agent_executor if API key is missing
35
  st.error(f"AI Agent Initialization Error: {e}")
36
+ app_logger.critical(f"Fatal: AI Agent could not be initialized in Consult page: {e}", exc_info=True)
37
+ st.info("Please ensure the OPENAI_API_KEY is correctly configured in the application settings (Hugging Face Secrets).")
38
  st.stop()
39
+ except Exception as e: # Catch any other unexpected error during agent init
40
+ st.error(f"An unexpected error occurred while initializing the AI Agent: {e}")
41
+ app_logger.critical(f"Fatal: Unexpected AI Agent initialization error: {e}", exc_info=True)
42
  st.stop()
43
 
 
 
 
44
 
45
+ # --- Session State for Consult Page ---
46
+ # Using more descriptive key for the patient context dictionary
47
+ if 'current_consult_patient_context_dict' not in st.session_state:
48
+ st.session_state.current_consult_patient_context_dict = {}
49
+ if 'consult_context_submitted' not in st.session_state:
50
+ st.session_state.consult_context_submitted = False
51
+
52
+ # --- Helper Functions ---
53
+ @st.cache_data(ttl=30, show_spinner=False, max_entries=10) # Cache agent history for current session
54
+ def load_chat_history_for_agent(session_id: int) -> List[Any]: # List of LangChain BaseMessage
55
+ """Loads chat history from DB, formatted for LangChain agent (HumanMessage, AIMessage, SystemMessage)."""
56
+ messages = []
57
+ app_logger.debug(f"Loading agent chat history from DB for session_id: {session_id}")
58
+ try:
59
+ with get_session_context() as db:
60
+ statement = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)
61
+ db_messages = db.exec(statement).all()
62
+ for msg in db_messages:
63
+ if msg.role == "user": messages.append(HumanMessage(content=msg.content))
64
+ elif msg.role == "assistant": messages.append(AIMessage(content=msg.content))
65
+ elif msg.role == "system": messages.append(SystemMessage(content=msg.content))
66
+ # ToolMessages are usually part of agent_scratchpad, not general chat_history for invoke
67
+ app_logger.debug(f"Loaded {len(messages)} LangChain messages for agent history (session {session_id}).")
68
+ except Exception as e:
69
+ app_logger.error(f"Error loading chat history for session {session_id}: {e}", exc_info=True)
70
+ st.toast(f"Error loading chat history: {e}", icon="⚠️") # Non-blocking error
71
+ return messages
72
+
73
+ def save_chat_message_to_db(session_id: int, role: str, content: str, tool_call_id: Optional[str]=None, tool_name: Optional[str]=None):
74
+ """Saves a chat message to the database."""
75
+ app_logger.debug(f"Saving message to DB for session {session_id}: Role='{role}', Content snippet='{content[:50]}...'")
76
+ try:
77
+ with get_session_context() as db:
78
+ chat_message_obj = ChatMessage(
79
+ session_id=session_id, role=role, content=content, timestamp=datetime.utcnow(),
80
+ tool_call_id=tool_call_id, tool_name=tool_name
81
+ )
82
+ db.add(chat_message_obj) # Commit will be handled by the context manager
83
+ app_logger.info(f"Message (Role: {role}) saved to DB for session {session_id}.")
84
+ except Exception as e:
85
+ app_logger.error(f"Error saving chat message to DB for session {session_id}: {e}", exc_info=True)
86
+ st.toast(f"Error saving message: {e}", icon="⚠️")
87
+
88
+
89
+ def update_chat_session_with_context_summary_in_db(session_id: int, context_summary: str):
90
+ """Updates the ChatSession record with the patient context summary."""
91
+ try:
92
+ with get_session_context() as db:
93
+ session_to_update = db.get(ChatSession, session_id) # Fetch by primary key
94
+ if session_to_update:
95
+ session_to_update.patient_context_summary = context_summary
96
+ db.add(session_to_update) # SQLModel handles add for updates if PK is present
97
+ app_logger.info(f"Updated ChatSession {session_id} with patient context summary in DB.")
98
+ else:
99
+ app_logger.error(f"Could not find ChatSession {session_id} in DB to update context summary.")
100
+ except Exception as e:
101
+ app_logger.error(f"Error updating chat session {session_id} context summary: {e}", exc_info=True)
102
+ st.toast(f"Error saving context summary: {e}", icon="⚠️")
103
+
104
+
105
+ # --- Page Logic ---
106
  st.title("AI Consultation Room")
107
+ st.markdown(f"Interacting as: **{authenticated_username}**")
108
+ # Prominent disclaimer on the consult page itself
109
+ st.warning(f"**Reminder & Disclaimer:** {settings.MAIN_DISCLAIMER_LONG} {settings.SIMULATION_DISCLAIMER}")
110
+
111
 
 
112
  chat_session_id = st.session_state.get("current_chat_session_id")
113
  if not chat_session_id:
114
+ st.error("Error: No active chat session ID found. This is unexpected after login. Please try logging out and logging back in. If the problem persists, please contact support.")
115
+ app_logger.critical(f"User '{authenticated_username}' (ID: {authenticated_user_id}) on Consult page encountered MISSING current_chat_session_id.")
116
  st.stop()
117
 
118
+ # --- Patient Context Input Form ---
119
  if not st.session_state.consult_context_submitted:
120
+ st.subheader("Step 1: Provide Patient Context (Optional, Use Simulated Data Only)")
121
+ with st.form(key="patient_context_form_consult_page_openai"): # Unique key
122
+ st.markdown("**Crucial Reminder: Use only anonymized, simulated data for this demonstration. Do NOT enter real PHI.**")
123
+ age_in = st.number_input("Patient Age (Simulated)", min_value=0, max_value=120, step=1, value=None, help="Leave blank if not applicable.")
124
+ gender_options = ["Not Specified", "Male", "Female", "Other"]
125
+ gender_in = st.selectbox("Patient Gender (Simulated)", gender_options, index=0)
126
+ cc_in = st.text_area("Chief Complaint / Reason for Consult (Simulated)", height=100, placeholder="e.g., Persistent cough for 2 weeks, fatigue")
127
+ hist_in = st.text_area("Key Medical History (Simulated)", height=100, placeholder="e.g., Type 2 Diabetes (controlled), Hypertension (on medication), Asthma (mild intermittent)")
128
+ meds_in = st.text_area("Current Medications (Simulated)", height=100, placeholder="e.g., Metformin 500mg BID, Lisinopril 10mg OD, Salbutamol inhaler PRN")
129
+ submit_context_btn = st.form_submit_button("Start Consult with this Context")
130
+
131
+ if submit_context_btn:
132
+ raw_context = {
133
+ "Age": age_in, "Gender": gender_in, "Chief Complaint": cc_in,
134
+ "Key Medical History": hist_in, "Current Medications": meds_in,
135
+ }
136
+ # Filter out None/empty/"Not Specified" values for a cleaner context dictionary
137
+ filtered_context_dict = {
138
+ k: v for k, v in raw_context.items()
139
+ if v is not None and str(v).strip() and \
140
+ (isinstance(v, str) and v.lower() != "not specified") and \
141
+ (isinstance(v, int) and v > 0 or not isinstance(v, int)) # ensure age > 0 if int
142
+ }
143
+ st.session_state.current_consult_patient_context_dict = filtered_context_dict
144
+
145
+ if filtered_context_dict:
146
+ context_summary_str = "; ".join([f"{k}: {v}" for k, v in filtered_context_dict.items()])
147
+ else:
148
+ context_summary_str = "No specific patient context was provided for this session."
149
+
150
+ update_chat_session_with_context_summary_in_db(chat_session_id, context_summary_str)
151
+ # Save a system message to DB indicating context was set for this session
152
+ save_chat_message_to_db(chat_session_id, "system", f"Initial Patient Context Set: {context_summary_str}")
153
+
154
+ st.session_state.consult_context_submitted = True
155
+ app_logger.info(f"Patient context submitted for session {chat_session_id}: {context_summary_str}")
156
+ st.rerun() # Rerun to hide form and proceed to chat interface
157
+ st.stop() # Don't proceed to chat interface until context form is handled
158
+
159
+ # --- Chat Interface (Shown after context is submitted) ---
160
+ st.subheader("Step 2: Interact with AI Health Navigator")
161
+ agent_history_key = f"agent_chat_history_{chat_session_id}" # Session-specific key for agent's message history
162
+
163
+ # Initialize or load agent's chat history (list of LangChain messages)
164
+ if agent_history_key not in st.session_state:
165
+ st.session_state[agent_history_key] = load_chat_history_for_agent(chat_session_id)
166
+ if not st.session_state[agent_history_key]: # If history is empty after loading from DB
167
  try:
168
+ log_consultation_start(user_id=authenticated_user_id, session_id=chat_session_id)
169
+ except Exception as e_metric:
170
+ app_logger.warning(f"Failed to log consultation start metric: {e_metric}")
171
+
172
+ initial_ai_message_content = "Hello! I am your AI Health Navigator. How can I assist you today?"
173
+ patient_context_for_greeting = st.session_state.get('current_consult_patient_context_dict', {})
174
+ if patient_context_for_greeting: # Check if the dict itself is non-empty
175
+ initial_ai_message_content += " I have noted the patient context you provided."
176
+
177
+ # Add initial AI message to agent's history and save to DB
178
+ st.session_state[agent_history_key].append(AIMessage(content=initial_ai_message_content))
179
+ save_chat_message_to_db(chat_session_id, "assistant", initial_ai_message_content)
180
+ app_logger.info(f"Initialized new consultation (session {chat_session_id}) with a greeting.")
181
+
182
+ # Display chat messages for UI (fetch fresh from DB for UI consistency)
183
+ # This uses a scrollable container.
184
+ chat_display_container = st.container(height=450)
185
+ with chat_display_container:
186
  with get_session_context() as db:
187
  stmt = select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)
188
+ ui_messages_from_db = db.exec(stmt).all()
189
+ for msg in ui_messages_from_db:
190
+ if msg.role == "system": continue # Don't display raw system messages in chat UI
191
+ avatar_icon = "πŸ§‘β€βš•οΈ" if msg.role == "assistant" else "πŸ‘€"
192
+ if msg.role == "tool": avatar_icon = "πŸ› οΈ" # Example if you log tool messages for UI
193
+ with st.chat_message(msg.role, avatar=avatar_icon):
194
+ st.markdown(msg.content) # Add source/confidence here if msg object from DB supports it
195
+
196
+ # Chat input from user
197
+ if user_prompt := st.chat_input("Ask the AI... (e.g., 'What is hypertension?')"):
198
+ # Display user message in UI immediately
199
+ with chat_display_container: # Also add to the container
200
+ with st.chat_message("user", avatar="πŸ‘€"):
201
+ st.markdown(user_prompt)
202
+
203
+ save_chat_message_to_db(chat_session_id, "user", user_prompt)
204
+ st.session_state[agent_history_key].append(HumanMessage(content=user_prompt))
205
+
206
+ # Get AI response
207
+ with chat_display_container: # Add AI response to the container
208
+ with st.chat_message("assistant", avatar="πŸ§‘β€βš•οΈ"):
209
+ thinking_message = st.empty() # Placeholder for "AI is thinking..."
210
+ thinking_message.markdown("β–Œ") # Simple animated cursor
211
+
212
  try:
213
+ # Prepare patient context string for the agent
214
+ patient_context_dict = st.session_state.get('current_consult_patient_context_dict', {})
215
+ if patient_context_dict: # If there's any context
216
+ context_parts_for_invoke = [f"{k}: {v}" for k, v in patient_context_dict.items()]
217
+ patient_context_str_for_invoke = "; ".join(context_parts_for_invoke)
218
+ else: # If no context was provided or all fields were empty/default
219
+ patient_context_str_for_invoke = "No specific patient context was provided by the user for this interaction."
220
+
221
+ # These are the keys expected by the OpenAI Functions Agent prompt
222
+ invoke_payload = {
223
+ "input": user_prompt,
224
+ "chat_history": st.session_state[agent_history_key], # List of BaseMessage
225
+ "patient_context": patient_context_str_for_invoke
226
  }
227
+ app_logger.debug(f"Invoking OpenAI agent with payload: {invoke_payload}")
228
+
229
+ thinking_message.markdown("AI is thinking...") # Update spinner text
230
+
231
+ response = agent_executor.invoke(invoke_payload)
232
+
233
+ ai_response_content = response.get('output', "I could not generate a valid response at this time.")
234
+ if not isinstance(ai_response_content, str): ai_response_content = str(ai_response_content)
235
+
236
+ app_logger.info(f"OpenAI Agent response for session {chat_session_id}: '{ai_response_content[:100]}...'")
237
+ thinking_message.empty() # Clear "thinking..." message
238
+ st.markdown(ai_response_content) # Display AI response
239
+
240
+ save_chat_message_to_db(chat_session_id, "assistant", ai_response_content)
241
+ st.session_state[agent_history_key].append(AIMessage(content=ai_response_content))
242
+
243
  except Exception as e:
244
+ app_logger.error(f"Error during OpenAI agent invocation for session {chat_session_id}: {e}", exc_info=True)
245
+ error_type_name = type(e).__name__
246
+ user_friendly_error = f"Sorry, an error occurred ({error_type_name}). Please try rephrasing your query or contact support if the issue persists."
247
+ thinking_message.empty() # Clear "thinking..." message
248
+ st.error(user_friendly_error) # Display error in the AI's bubble
249
+
250
+ db_error_msg = f"System encountered an error: {error_type_name}. Details logged."
251
+ save_chat_message_to_db(chat_session_id, "assistant", db_error_msg)
252
+ st.session_state[agent_history_key].append(AIMessage(content=f"Note to self: Encountered error ({error_type_name})."))
253
+
254
+ st.rerun() # Rerun to ensure the new messages are at the bottom of the scrollable container