mgbam commited on
Commit
1aff0c6
Β·
verified Β·
1 Parent(s): 743ac85

Update pages/2_Consult.py

Browse files
Files changed (1) hide show
  1. pages/2_Consult.py +92 -100
pages/2_Consult.py CHANGED
@@ -1,7 +1,7 @@
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, Dict, Any
5
  from sqlmodel import select
6
 
7
  from config.settings import settings
@@ -20,56 +20,51 @@ if not st.session_state.get("authenticated_user_id"):
20
  st.info("Please navigate to the main login page.")
21
  st.stop()
22
 
 
23
  authenticated_user_id = st.session_state["authenticated_user_id"]
24
  authenticated_username = st.session_state.get("authenticated_username", "User")
25
  app_logger.info(f"User '{authenticated_username}' (ID: {authenticated_user_id}) accessed Consult page.")
26
 
27
- # --- Initialize Agent ---
28
  try:
29
  agent_executor = get_agent_executor()
30
  app_logger.info("Gemini-based agent executor initialized for Consult page.")
31
  except ValueError as e:
32
  st.error(f"AI Agent Initialization Error: {e}")
33
- app_logger.critical(f"Fatal: AI Agent could not be initialized: {e}", exc_info=True)
34
- st.info("Please ensure API keys (e.g., Google API Key for Gemini) are configured.")
35
  st.stop()
36
  except Exception as e:
37
  st.error(f"Unexpected error initializing AI Agent: {e}")
38
- app_logger.critical(f"Fatal: Unexpected AI Agent initialization error: {e}", exc_info=True)
39
  st.stop()
40
 
41
  # --- Session State Setup ---
42
- if 'current_consult_patient_context_dict' not in st.session_state:
43
- st.session_state.current_consult_patient_context_dict = {}
44
- if 'consult_context_submitted' not in st.session_state:
45
- st.session_state.consult_context_submitted = False
46
 
47
- # --- Caching helper to load history ---
48
  @st.cache_data(ttl=30, show_spinner=False)
49
- def load_chat_history_for_agent(session_id: int) -> List[Union[HumanMessage, AIMessage, SystemMessage]]:
50
- messages: List[Union[HumanMessage, AIMessage, SystemMessage]] = []
51
- app_logger.debug(f"Loading agent chat history for session {session_id}")
 
 
52
  with get_session_context() as db:
53
- statement = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)
54
- for msg in db.exec(statement).all():
55
  if msg.role == "user":
56
- messages.append(HumanMessage(content=msg.content))
57
  elif msg.role == "assistant":
58
- messages.append(AIMessage(content=msg.content))
59
  elif msg.role == "system":
60
- messages.append(SystemMessage(content=msg.content))
61
- app_logger.debug(f"Loaded {len(messages)} messages for session {session_id}")
62
- return messages
63
-
64
- # --- Database write helpers ---
65
- def save_chat_message_to_db(
66
- session_id: int,
67
- role: str,
68
- content: str,
69
- tool_call_id: Optional[str] = None,
70
- tool_name: Optional[str] = None,
71
- ):
72
- app_logger.debug(f"Saving message to DB for session {session_id}: Role={role}")
73
  with get_session_context() as db:
74
  obj = ChatMessage(
75
  session_id=session_id,
@@ -80,80 +75,79 @@ def save_chat_message_to_db(
80
  tool_name=tool_name,
81
  )
82
  db.add(obj)
83
- app_logger.info(f"Message saved to DB for session {session_id}. Role: {role}.")
84
 
85
 
86
- def update_chat_session_with_context_summary_in_db(session_id: int, summary: str):
 
 
 
87
  with get_session_context() as db:
88
  session = db.get(ChatSession, session_id)
89
  if session:
90
  session.patient_context_summary = summary
91
  db.add(session)
92
- app_logger.info(f"Updated ChatSession {session_id} with context summary.")
93
  else:
94
- app_logger.error(f"ChatSession {session_id} not found for updating context.")
95
 
96
- # --- Page Title & Disclaimer ---
97
  st.title("AI Consultation Room")
98
- st.markdown(f"Interacting as: **{authenticated_username}**")
99
- st.info(f"{settings.MAIN_DISCLAIMER_SHORT} Remember to use only anonymized, simulated data.")
100
 
101
- # --- Retrieve or Create Chat Session ---
102
  chat_session_id = st.session_state.get("current_chat_session_id")
103
  if not chat_session_id:
104
- st.error("No active chat session found. Please logout and login again.")
105
- app_logger.error("No current_chat_session_id in session_state.")
106
  st.stop()
107
 
108
- # --- Patient Context Form ---
109
  if not st.session_state.consult_context_submitted:
110
  st.subheader("Step 1: Provide Patient Context (Optional)")
111
- with st.form("patient_context_form"):
112
- age = st.number_input("Patient Age (Simulated)", min_value=0, max_value=120, step=1)
113
- gender = st.selectbox("Patient Gender (Simulated)", ["Not Specified", "Male", "Female", "Other"], index=0)
114
- complaint = st.text_area("Chief Complaint", height=80, placeholder="e.g., Persistent cough")
115
- history = st.text_area("Key Medical History", height=80, placeholder="e.g., Type 2 Diabetes")
116
- meds = st.text_area("Current Medications", height=80, placeholder="e.g., Metformin")
117
  submit = st.form_submit_button("Start Consult")
118
 
119
  if submit:
120
- raw = {"age": age, "gender": gender, "complaint": complaint, "history": history, "meds": meds}
121
- filtered = {k.title(): v for k, v in raw.items() if v and not (isinstance(v, str) and v == "Not Specified")}
122
- st.session_state.current_consult_patient_context_dict = filtered
123
-
124
- summary = (
125
- "; ".join(f"{k}: {v}" for k, v in filtered.items())
126
- if filtered else
127
- "No specific patient context provided."
128
- )
129
- update_chat_session_with_context_summary_in_db(chat_session_id, summary)
130
- save_chat_message_to_db(chat_session_id, "system", f"Context: {summary}")
131
  st.session_state.consult_context_submitted = True
132
- app_logger.info(f"Patient context for session {chat_session_id}: {summary}")
133
- st.rerun()
134
  st.stop()
135
 
136
- # --- Chat Interaction ---
137
- st.subheader("Step 2: Interact with AI Health Navigator")
138
- history_key = f"agent_history_{chat_session_id}"
139
  if history_key not in st.session_state:
140
- st.session_state[history_key] = load_chat_history_for_agent(chat_session_id)
141
  if not st.session_state[history_key]:
142
  try:
143
  log_consultation_start(authenticated_user_id, chat_session_id)
144
- except Exception as e:
145
- app_logger.warning(f"Metrics log failed: {e}")
146
- greeting = "Hello! I am your AI Health Navigator. How can I help today?"
147
- if st.session_state.current_consult_patient_context_dict:
148
- greeting += " I have noted the patient context provided."
149
  st.session_state[history_key].append(AIMessage(content=greeting))
150
- save_chat_message_to_db(chat_session_id, "assistant", greeting)
151
 
152
- # Display past messages
153
  with st.container(height=400):
154
  with get_session_context() as db:
155
  stmt = select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)
156
- for msg in db.exec(stmt).all():
157
  if msg.role == "system":
158
  continue
159
  avatar = "πŸ§‘β€βš•οΈ" if msg.role == "assistant" else "πŸ‘€"
@@ -162,40 +156,38 @@ with st.container(height=400):
162
  with st.chat_message(msg.role, avatar=avatar):
163
  st.markdown(msg.content)
164
 
165
- # Capture user input and invoke agent
166
- if prompt := st.chat_input("Ask the AI... (e.g., 'What is hypertension?')"):
167
  with st.chat_message("user", avatar="πŸ‘€"):
168
- st.markdown(prompt)
169
- save_chat_message_to_db(chat_session_id, "user", prompt)
170
- st.session_state[history_key].append(HumanMessage(content=prompt))
171
 
172
  with st.chat_message("assistant", avatar="πŸ§‘β€βš•οΈ"):
173
  with st.spinner("AI is thinking..."):
174
  try:
175
- pctxt = st.session_state.current_consult_patient_context_dict
176
- if pctxt:
177
- pc_str = "; ".join(f"{k}: {v}" for k, v in pctxt.items())
178
- else:
179
- pc_str = "No specific patient context provided."
180
 
181
  payload = {
182
- "input": prompt,
183
  "chat_history": st.session_state[history_key],
184
- "patient_context": pc_str,
185
  }
186
- app_logger.debug(f"Invoking agent with payload: {payload}")
187
- resp = agent_executor.invoke(payload)
188
- content = resp.get("output", "I could not generate a response.")
189
- content = str(content)
190
-
191
- app_logger.info(f"Agent response session {chat_session_id}: {content[:100]}")
192
- st.markdown(content)
193
- save_chat_message_to_db(chat_session_id, "assistant", content)
194
- st.session_state[history_key].append(AIMessage(content=content))
195
- except Exception as err:
196
- app_logger.error(f"Error during agent invocation for session {chat_session_id}: {err}", exc_info=True)
197
- st.error(f"Sorry, an error occurred: {type(err).__name__}. Please try again.")
198
- err_msg = f"System encountered an error: {type(err).__name__}."
199
- save_chat_message_to_db(chat_session_id, "assistant", err_msg)
200
- st.session_state[history_key].append(AIMessage(content=err_msg))
201
- st.rerun()
 
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
 
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,
 
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 "πŸ‘€"
 
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()