mgbam commited on
Commit
861d237
Β·
verified Β·
1 Parent(s): 6720639

Update pages/2_Consult.py

Browse files
Files changed (1) hide show
  1. pages/2_Consult.py +120 -82
pages/2_Consult.py CHANGED
@@ -1,147 +1,185 @@
1
  # /home/user/app/pages/2_Consult.py
2
  import streamlit as st
3
- from langchain_core.messages import HumanMessage, AIMessage # SystemMessage, ToolMessage removed if not used directly
4
  from datetime import datetime
5
- from typing import List, Optional
6
- from sqlmodel import select # <--- IMPORT SELECT FOR SQLMODEL QUERIES
7
 
8
  from config.settings import settings
9
- from agent import get_agent_executor
10
- from models import ChatMessage, ChatSession, User # User not directly used if ID is sufficient
11
  from models.db import get_session_context
12
  from services.logger import app_logger
13
  from services.metrics import log_consultation_start
14
 
15
- # --- Auth Check (same as before) ---
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")
20
- except st.errors.StreamlitAPIException: # Catch specific error if needed
21
- st.info("Please navigate to the main login page.")
22
  st.stop()
23
 
24
  authenticated_user_id = st.session_state.get("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 Agent (same as before) ---
29
  try:
30
  agent_executor = get_agent_executor()
31
  except Exception as e:
32
- st.error(f"Could not initialize AI Agent: {e}")
33
  app_logger.critical(f"AI Agent initialization failed: {e}", exc_info=True)
34
  st.stop()
35
 
 
 
 
 
 
 
36
  # --- Helper Functions ---
37
- @st.cache_data(ttl=60)
38
  def load_chat_history_for_agent(session_id: int) -> List:
39
  messages = []
 
 
40
  app_logger.debug(f"Loading agent chat history for session_id: {session_id}")
41
- with get_session_context() as db: # db is a SQLModel Session
42
- # --- SQLMODEL QUERY ---
43
  statement = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)
44
- db_messages_results = db.exec(statement)
45
- db_messages = db_messages_results.all()
46
- # --------------------
47
  for msg in db_messages:
48
- if msg.role == "user":
49
- messages.append(HumanMessage(content=msg.content))
50
- elif msg.role == "assistant":
51
- messages.append(AIMessage(content=msg.content))
52
- # Add ToolMessage handling if you store and use them
53
- # elif msg.role == "tool" and hasattr(msg, 'tool_call_id') and msg.tool_call_id:
54
- # messages.append(ToolMessage(content=msg.content, tool_call_id=str(msg.tool_call_id)))
55
- app_logger.debug(f"Loaded {len(messages)} messages for agent history for session {session_id}.")
56
  return messages
57
 
58
- # save_chat_message_to_db remains the same as it's performing an insert, not a query.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  # --- Page Logic ---
61
  st.title("AI Consultation Room")
62
  st.markdown(f"Interacting as: **{authenticated_username}**")
 
63
 
64
  chat_session_id = st.session_state.get("current_chat_session_id")
65
-
66
  if not chat_session_id:
67
- st.error("No active chat session ID found. Please try logging out and back in.")
68
- app_logger.error(f"User {authenticated_username} on Consult page with no current_chat_session_id.")
 
 
69
  st.stop()
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  agent_history_key = f"agent_chat_history_{chat_session_id}"
72
  if agent_history_key not in st.session_state:
73
  st.session_state[agent_history_key] = load_chat_history_for_agent(chat_session_id)
74
- if not st.session_state[agent_history_key]:
75
- try:
76
- log_consultation_start(user_id=authenticated_user_id, session_id=chat_session_id)
77
- except Exception as e:
78
- app_logger.warning(f"Failed to log consultation start: {e}")
79
  initial_ai_message_content = "Hello! I am your AI Health Navigator. How can I assist you today?"
80
  st.session_state[agent_history_key].append(AIMessage(content=initial_ai_message_content))
81
- # save_chat_message_to_db(chat_session_id, "assistant", initial_ai_message_content) # save_chat_message_to_db defined elsewhere
82
- # Ensure save_chat_message_to_db is defined or called correctly. For this example, it's:
83
- with get_session_context() as db:
84
- chat_msg_obj = ChatMessage(session_id=chat_session_id, role="assistant", content=initial_ai_message_content)
85
- db.add(chat_msg_obj) # commit handled by context manager
86
- app_logger.info(f"Initialized new consultation for session {chat_session_id} with a greeting.")
87
-
88
 
89
- # Display chat messages for UI
90
  with st.container():
91
- with get_session_context() as db: # db is a SQLModel Session
92
- # --- SQLMODEL QUERY ---
93
- statement = select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)
94
- ui_messages_results = db.exec(statement)
95
- ui_messages = ui_messages_results.all()
96
- # --------------------
97
  for msg in ui_messages:
 
 
98
  avatar = "πŸ§‘β€βš•οΈ" if msg.role == "assistant" else "πŸ‘€"
99
  if msg.role == "tool": avatar = "πŸ› οΈ"
100
  with st.chat_message(msg.role, avatar=avatar):
101
- st.markdown(msg.content)
102
-
103
- # Chat input and AI response logic (remains largely the same as it calls agent_executor and save_chat_message_to_db)
104
- # ... (rest of 2_Consult.py from the previous good version)
105
- # For brevity, I'm omitting the chat input and AI response handling section as it primarily
106
- # uses `agent_executor.invoke` and `save_chat_message_to_db`, which itself doesn't change syntax for inserts.
107
-
108
- def save_chat_message_to_db(session_id: int, role: str, content: str, tool_call_id: Optional[str]=None, tool_name: Optional[str]=None):
109
- app_logger.debug(f"Saving message to DB for session {session_id}: Role={role}, Content snippet='{content[:50]}...'")
110
- with get_session_context() as db:
111
- chat_message = ChatMessage(
112
- session_id=session_id,
113
- role=role,
114
- content=content,
115
- timestamp=datetime.utcnow(),
116
- tool_call_id=tool_call_id,
117
- tool_name=tool_name
118
- )
119
- db.add(chat_message)
120
- # db.commit() # Handled by context manager
121
- app_logger.info(f"Message saved to DB for session {session_id}. Role: {role}.")
122
 
123
  if prompt := st.chat_input("Ask the AI..."):
124
- with st.chat_message("user", avatar="πŸ‘€"):
125
- st.markdown(prompt)
126
  save_chat_message_to_db(chat_session_id, "user", prompt)
127
  st.session_state[agent_history_key].append(HumanMessage(content=prompt))
128
 
129
  with st.chat_message("assistant", avatar="πŸ§‘β€βš•οΈ"):
130
  with st.spinner("AI is thinking..."):
131
  try:
 
 
 
 
132
  response = agent_executor.invoke({
133
  "input": prompt,
134
- "chat_history": st.session_state[agent_history_key]
 
135
  })
136
- ai_response_content = response.get('output', "No output from AI.")
137
- if not isinstance(ai_response_content, str):
138
- ai_response_content = str(ai_response_content)
139
- st.markdown(ai_response_content)
140
  save_chat_message_to_db(chat_session_id, "assistant", ai_response_content)
141
  st.session_state[agent_history_key].append(AIMessage(content=ai_response_content))
142
  except Exception as e:
143
  app_logger.error(f"Error during agent invocation for session {chat_session_id}: {e}", exc_info=True)
144
- error_message_user = f"Sorry, I encountered an error: {type(e).__name__}"
145
- st.error(error_message_user)
146
- save_chat_message_to_db(chat_session_id, "assistant", f"Error processing request: {type(e).__name__}")
147
- st.session_state[agent_history_key].append(AIMessage(content=f"Observed internal error: {type(e).__name__}"))
 
1
  # /home/user/app/pages/2_Consult.py
2
  import streamlit as st
3
+ from langchain_core.messages import HumanMessage, AIMessage
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 # Assumes this is your LangChain agent
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
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: st.switch_page("app.py")
19
+ except st.errors.StreamlitAPIException: st.info("Please navigate to the main login page.")
 
 
20
  st.stop()
21
 
22
  authenticated_user_id = st.session_state.get("authenticated_user_id")
23
  authenticated_username = st.session_state.get("authenticated_username", "User")
24
+ app_logger.info(f"User '{authenticated_username}' (ID: {authenticated_user_id}) accessed Consult page.")
25
 
26
+ # --- Initialize Agent ---
27
  try:
28
  agent_executor = get_agent_executor()
29
  except Exception as e:
30
+ st.error(f"Fatal Error: Could not initialize AI Agent: {e}. Please check API keys and configurations.")
31
  app_logger.critical(f"AI Agent initialization failed: {e}", exc_info=True)
32
  st.stop()
33
 
34
+ # --- Session State for Consult Page ---
35
+ if 'current_consult_patient_context' not in st.session_state:
36
+ st.session_state.current_consult_patient_context = {} # Stores structured context for current consult
37
+ if 'consult_context_submitted' not in st.session_state:
38
+ st.session_state.consult_context_submitted = False
39
+
40
  # --- Helper Functions ---
41
+ @st.cache_data(ttl=30, show_spinner=False) # Short cache for agent history
42
  def load_chat_history_for_agent(session_id: int) -> List:
43
  messages = []
44
+ # ... (load_chat_history_for_agent from previous full rewrite of 2_Consult.py, using SQLModel select) ...
45
+ # This function should convert DB ChatMessages to LangChain HumanMessage/AIMessage
46
  app_logger.debug(f"Loading agent chat history for session_id: {session_id}")
47
+ with get_session_context() as db:
 
48
  statement = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)
49
+ db_messages = db.exec(statement).all()
 
 
50
  for msg in db_messages:
51
+ if msg.role == "user": messages.append(HumanMessage(content=msg.content))
52
+ elif msg.role == "assistant": messages.append(AIMessage(content=msg.content))
 
 
 
 
 
 
53
  return messages
54
 
55
+
56
+ def save_chat_message_to_db(session_id: int, role: str, content: str, tool_call_id: Optional[str]=None, tool_name: Optional[str]=None):
57
+ # ... (save_chat_message_to_db from previous full rewrite of 2_Consult.py) ...
58
+ app_logger.debug(f"Saving message to DB for session {session_id}: Role={role}")
59
+ with get_session_context() as db:
60
+ chat_message = ChatMessage(
61
+ session_id=session_id, role=role, content=content, timestamp=datetime.utcnow(),
62
+ tool_call_id=tool_call_id, tool_name=tool_name
63
+ )
64
+ db.add(chat_message) # Commit handled by context manager
65
+ app_logger.info(f"Message saved to DB for session {session_id}. Role: {role}.")
66
+
67
+
68
+ def update_chat_session_with_context(session_id: int, context_summary: str):
69
+ with get_session_context() as db:
70
+ session_to_update = db.get(ChatSession, session_id)
71
+ if session_to_update:
72
+ session_to_update.patient_context_summary = context_summary
73
+ db.add(session_to_update) # Stage for commit
74
+ app_logger.info(f"Updated ChatSession {session_id} with patient context summary.")
75
+ else:
76
+ app_logger.error(f"Could not find ChatSession {session_id} to update with context.")
77
 
78
  # --- Page Logic ---
79
  st.title("AI Consultation Room")
80
  st.markdown(f"Interacting as: **{authenticated_username}**")
81
+ st.info(settings.MAIN_DISCLAIMER_SHORT + " Do not enter real PHI.")
82
 
83
  chat_session_id = st.session_state.get("current_chat_session_id")
 
84
  if not chat_session_id:
85
+ st.error("No active chat session. This may occur if you logged out and back in. A new session was created. If issues persist, please re-login fully or contact support.")
86
+ app_logger.error(f"User '{authenticated_username}' on Consult page with no current_chat_session_id.")
87
+ # Attempt to create a new one if truly missing, or guide to re-login
88
+ # For now, stopping is safer if app.py is supposed to always create one.
89
  st.stop()
90
 
91
+ # --- Patient Context Input Form ---
92
+ if not st.session_state.consult_context_submitted:
93
+ st.subheader("Optional: Provide Patient Context (Simulated Data Only)")
94
+ with st.form(key="patient_context_form"):
95
+ st.markdown("**Reminder: Use only anonymized, simulated data for this demonstration.**")
96
+ age = st.number_input("Patient Age (Simulated)", min_value=0, max_value=120, step=1)
97
+ gender = st.selectbox("Patient Gender (Simulated)", ["Not Specified", "Male", "Female", "Other"])
98
+ chief_complaint = st.text_area("Chief Complaint / Reason for Consult (Simulated)", height=100)
99
+ key_history = st.text_area("Key Medical History (Simulated - e.g., diabetes, hypertension)", height=100)
100
+ current_meds = st.text_area("Current Medications (Simulated - e.g., metformin, lisinopril)", height=100)
101
+ submit_context_button = st.form_submit_button("Start Consult with this Context")
102
+
103
+ if submit_context_button:
104
+ context = {
105
+ "age": age if age > 0 else "Not Specified",
106
+ "gender": gender,
107
+ "chief_complaint": chief_complaint.strip() if chief_complaint.strip() else "Not Specified",
108
+ "key_medical_history": key_history.strip() if key_history.strip() else "Not Specified",
109
+ "current_medications": current_meds.strip() if current_meds.strip() else "Not Specified",
110
+ }
111
+ st.session_state.current_consult_patient_context = context
112
+ st.session_state.consult_context_submitted = True
113
+
114
+ # Create a summary for the agent and DB
115
+ context_summary_parts = [f"{k.replace('_', ' ').title()}: {v}" for k, v in context.items() if v != "Not Specified" and v != ""]
116
+ context_summary_for_agent = "Patient Context: " + "; ".join(context_summary_parts) if context_summary_parts else "No specific patient context provided."
117
+
118
+ # Save context summary to ChatSession model
119
+ update_chat_session_with_context(chat_session_id, context_summary_for_agent)
120
+
121
+ # Prepend context to agent's chat history as a system message or initial user message
122
+ # For this example, let's add it as a system message to guide the AI
123
+ agent_history_key = f"agent_chat_history_{chat_session_id}"
124
+ if agent_history_key not in st.session_state: st.session_state[agent_history_key] = []
125
+ st.session_state[agent_history_key].insert(0, SystemMessage(content=context_summary_for_agent))
126
+ # Also save this "system" context message to DB for record keeping if desired
127
+ save_chat_message_to_db(chat_session_id, "system", context_summary_for_agent)
128
+
129
+ app_logger.info(f"Patient context submitted for session {chat_session_id}: {context_summary_for_agent}")
130
+ st.rerun() # Rerun to hide form and show chat
131
+ st.stop() # Don't proceed to chat until context is submitted or skipped
132
+
133
+ # --- Chat Interface (Shown after context is submitted/skipped) ---
134
  agent_history_key = f"agent_chat_history_{chat_session_id}"
135
  if agent_history_key not in st.session_state:
136
  st.session_state[agent_history_key] = load_chat_history_for_agent(chat_session_id)
137
+ if not st.session_state[agent_history_key]: # If history is empty (even after context attempt)
138
+ try: log_consultation_start(user_id=authenticated_user_id, session_id=chat_session_id)
139
+ except Exception as e: app_logger.warning(f"Failed to log consultation start: {e}")
 
 
140
  initial_ai_message_content = "Hello! I am your AI Health Navigator. How can I assist you today?"
141
  st.session_state[agent_history_key].append(AIMessage(content=initial_ai_message_content))
142
+ save_chat_message_to_db(chat_session_id, "assistant", initial_ai_message_content)
 
 
 
 
 
 
143
 
144
+ # Display chat messages from DB for UI
145
  with st.container():
146
+ with get_session_context() as db:
147
+ stmt = select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)
148
+ ui_messages = db.exec(stmt).all()
 
 
 
149
  for msg in ui_messages:
150
+ if msg.role == "system": # Don't show system context messages directly in chat UI
151
+ continue
152
  avatar = "πŸ§‘β€βš•οΈ" if msg.role == "assistant" else "πŸ‘€"
153
  if msg.role == "tool": avatar = "πŸ› οΈ"
154
  with st.chat_message(msg.role, avatar=avatar):
155
+ st.markdown(msg.content) # Add source/confidence here if msg object supports it
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
  if prompt := st.chat_input("Ask the AI..."):
158
+ with st.chat_message("user", avatar="πŸ‘€"): st.markdown(prompt)
 
159
  save_chat_message_to_db(chat_session_id, "user", prompt)
160
  st.session_state[agent_history_key].append(HumanMessage(content=prompt))
161
 
162
  with st.chat_message("assistant", avatar="πŸ§‘β€βš•οΈ"):
163
  with st.spinner("AI is thinking..."):
164
  try:
165
+ # Pass patient context if your agent is designed to use it explicitly
166
+ # current_context = st.session_state.get('current_consult_patient_context', {})
167
+ # context_str_for_invoke = "; ".join([f"{k}: {v}" for k,v in current_context.items() if v and v!="Not Specified"])
168
+
169
  response = agent_executor.invoke({
170
  "input": prompt,
171
+ "chat_history": st.session_state[agent_history_key],
172
+ # "patient_context": context_str_for_invoke # If agent expects this
173
  })
174
+ ai_response_content = response.get('output', "I could not generate a response.")
175
+ if not isinstance(ai_response_content, str): ai_response_content = str(ai_response_content)
176
+
177
+ st.markdown(ai_response_content) # Display sources/confidence here if available in ai_response_content
178
  save_chat_message_to_db(chat_session_id, "assistant", ai_response_content)
179
  st.session_state[agent_history_key].append(AIMessage(content=ai_response_content))
180
  except Exception as e:
181
  app_logger.error(f"Error during agent invocation for session {chat_session_id}: {e}", exc_info=True)
182
+ error_msg_user = f"Sorry, an error occurred: {type(e).__name__}. Please try again."
183
+ st.error(error_msg_user)
184
+ save_chat_message_to_db(chat_session_id, "assistant", f"Internal error: {type(e).__name__}")
185
+ st.session_state[agent_history_key].append(AIMessage(content=f"Internal error: {type(e).__name__}"))