mgbam commited on
Commit
352a295
Β·
verified Β·
1 Parent(s): 310dade

Update pages/2_Consult.py

Browse files
Files changed (1) hide show
  1. pages/2_Consult.py +69 -87
pages/2_Consult.py CHANGED
@@ -1,87 +1,61 @@
1
  # /home/user/app/pages/2_Consult.py
2
  import streamlit as st
3
- from langchain_core.messages import HumanMessage, AIMessage, SystemMessage, ToolMessage
4
  from datetime import datetime
5
- from typing import List, Optional # Corrected import for List and Optional
 
6
 
7
  from config.settings import settings
8
  from agent import get_agent_executor
9
- from models import ChatMessage, ChatSession, User # User might not be needed directly if ID is used
10
- from models.db import get_session_context # Or from models import get_session_context
11
  from services.logger import app_logger
12
- from services.metrics import log_consultation_start # Assuming this function exists
13
 
14
- # Page config typically in app.py
15
- # st.set_page_config(page_title=f"Consult - {settings.APP_TITLE}", layout="wide")
16
-
17
- # --- Authentication Check ---
18
  if not st.session_state.get("authenticated_user_id"):
19
  st.warning("Please log in to access the consultation page.")
20
  try:
21
  st.switch_page("app.py")
22
- except st.errors.StreamlitAPIException as e:
23
- if "st.switch_page can only be called when running in MPA mode" in str(e):
24
- app_logger.warning("Consult: Running in single-page mode or st.switch_page issue. Stopping script.")
25
- st.info("Please navigate to the main login page.")
26
- else:
27
- app_logger.error(f"Consult: Error during st.switch_page: {e}")
28
- st.error("Redirection error. Please go to the login page manually.")
29
  st.stop()
30
 
31
- # Get authenticated user's ID and username
32
  authenticated_user_id = st.session_state.get("authenticated_user_id")
33
  authenticated_username = st.session_state.get("authenticated_username", "User")
34
  app_logger.info(f"User {authenticated_username} (ID: {authenticated_user_id}) accessed Consult page.")
35
 
36
- # --- Initialize Agent ---
37
  try:
38
  agent_executor = get_agent_executor()
39
- except ValueError as e: # Handles missing API key or other init issues
40
  st.error(f"Could not initialize AI Agent: {e}")
41
  app_logger.critical(f"AI Agent initialization failed: {e}", exc_info=True)
42
  st.stop()
43
- except Exception as e:
44
- st.error(f"An unexpected error occurred while initializing the AI Agent: {e}")
45
- app_logger.critical(f"Unexpected AI Agent initialization error: {e}", exc_info=True)
46
- st.stop()
47
-
48
 
49
  # --- Helper Functions ---
50
- @st.cache_data(ttl=60) # Short cache for chat history to avoid constant DB hits on reruns
51
- def load_chat_history_for_agent(session_id: int) -> List: # Type hint for return
52
- """Loads chat history from DB for the current session, formatted for LangChain agent."""
53
  messages = []
54
  app_logger.debug(f"Loading agent chat history for session_id: {session_id}")
55
- with get_session_context() as db:
56
- # If using SQLModel: from sqlmodel import select
57
- # db_messages = db.exec(select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)).all()
58
- db_messages = db.query(ChatMessage).filter(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp).all()
 
 
59
  for msg in db_messages:
60
  if msg.role == "user":
61
  messages.append(HumanMessage(content=msg.content))
62
  elif msg.role == "assistant":
63
  messages.append(AIMessage(content=msg.content))
64
- elif msg.role == "tool" and hasattr(msg, 'tool_call_id') and msg.tool_call_id: # Ensure tool_call_id exists
65
- messages.append(ToolMessage(content=msg.content, tool_call_id=str(msg.tool_call_id))) # Cast to str just in case
66
- # Add other roles if necessary
67
  app_logger.debug(f"Loaded {len(messages)} messages for agent history for session {session_id}.")
68
  return messages
69
 
70
- def save_chat_message_to_db(session_id: int, role: str, content: str, tool_call_id: Optional[str]=None, tool_name: Optional[str]=None):
71
- """Saves a chat message to the database."""
72
- app_logger.debug(f"Saving message to DB for session {session_id}: Role={role}, Content snippet='{content[:50]}...'")
73
- with get_session_context() as db:
74
- chat_message = ChatMessage(
75
- session_id=session_id,
76
- role=role,
77
- content=content,
78
- timestamp=datetime.utcnow(),
79
- tool_call_id=tool_call_id,
80
- tool_name=tool_name
81
- )
82
- db.add(chat_message)
83
- db.commit()
84
- app_logger.info(f"Message saved to DB for session {session_id}. Role: {role}.")
85
 
86
  # --- Page Logic ---
87
  st.title("AI Consultation Room")
@@ -90,76 +64,84 @@ st.markdown(f"Interacting as: **{authenticated_username}**")
90
  chat_session_id = st.session_state.get("current_chat_session_id")
91
 
92
  if not chat_session_id:
93
- st.error("No active chat session ID found in session state. This might happen if you logged in before this feature was fully active. Please try logging out and logging back in.")
94
- app_logger.error(f"User {authenticated_username} (ID: {authenticated_user_id}) on Consult page with no current_chat_session_id.")
95
  st.stop()
96
 
97
- # Initialize agent's chat history if not already present for this session_id
98
- # We use a more specific key for agent_chat_history to handle session changes
99
  agent_history_key = f"agent_chat_history_{chat_session_id}"
100
  if agent_history_key not in st.session_state:
101
  st.session_state[agent_history_key] = load_chat_history_for_agent(chat_session_id)
102
- if not st.session_state[agent_history_key]: # If no history, maybe add a system greeting
103
  try:
104
  log_consultation_start(user_id=authenticated_user_id, session_id=chat_session_id)
105
  except Exception as e:
106
  app_logger.warning(f"Failed to log consultation start: {e}")
107
  initial_ai_message_content = "Hello! I am your AI Health Navigator. How can I assist you today?"
108
  st.session_state[agent_history_key].append(AIMessage(content=initial_ai_message_content))
109
- save_chat_message_to_db(chat_session_id, "assistant", initial_ai_message_content)
 
 
 
 
110
  app_logger.info(f"Initialized new consultation for session {chat_session_id} with a greeting.")
111
 
112
 
113
- # Display chat messages for UI (always fetch fresh from DB for UI consistency)
114
- # This ensures UI reflects what's actually in the DB.
115
- with st.container(): # Use a container for the chat display area
116
- with get_session_context() as db:
117
- # If using SQLModel: from sqlmodel import select
118
- # ui_messages = db.exec(select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)).all()
119
- ui_messages = db.query(ChatMessage).filter(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp).all()
 
120
  for msg in ui_messages:
121
  avatar = "πŸ§‘β€βš•οΈ" if msg.role == "assistant" else "πŸ‘€"
122
  if msg.role == "tool": avatar = "πŸ› οΈ"
123
-
124
  with st.chat_message(msg.role, avatar=avatar):
125
  st.markdown(msg.content)
126
 
127
- # Chat input
128
- if prompt := st.chat_input("Ask the AI... (e.g., 'What is hypertension?' or 'Suggest diagnostic tests for chest pain')"):
129
- # Add user message to UI immediately (optimistic update)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  with st.chat_message("user", avatar="πŸ‘€"):
131
  st.markdown(prompt)
132
- # Save user message to DB
133
  save_chat_message_to_db(chat_session_id, "user", prompt)
134
- # Add to agent's history (LangChain format)
135
  st.session_state[agent_history_key].append(HumanMessage(content=prompt))
136
 
137
- # Get AI response
138
- with st.chat_message("assistant", avatar="πŸ§‘β€βš•οΈ"): # Prepare AI's chat message bubble
139
  with st.spinner("AI is thinking..."):
140
  try:
141
  response = agent_executor.invoke({
142
  "input": prompt,
143
- "chat_history": st.session_state[agent_history_key] # Pass the current agent history
144
  })
145
  ai_response_content = response.get('output', "No output from AI.")
146
- if not isinstance(ai_response_content, str): # Ensure it's a string
147
  ai_response_content = str(ai_response_content)
148
-
149
- st.markdown(ai_response_content) # Display AI response in UI
150
- save_chat_message_to_db(chat_session_id, "assistant", ai_response_content) # Save to DB
151
- st.session_state[agent_history_key].append(AIMessage(content=ai_response_content)) # Add to agent's history
152
-
153
  except Exception as e:
154
  app_logger.error(f"Error during agent invocation for session {chat_session_id}: {e}", exc_info=True)
155
- error_message_user = f"Sorry, I encountered an error and could not process your request. Please try again or rephrase. (Error: {type(e).__name__})"
156
- st.error(error_message_user) # Display error in the AI's bubble
157
- # Save a generic error message to DB for the assistant's turn
158
  save_chat_message_to_db(chat_session_id, "assistant", f"Error processing request: {type(e).__name__}")
159
- # Add error representation to agent history so it's aware
160
- st.session_state[agent_history_key].append(AIMessage(content=f"Observed internal error: {type(e).__name__}"))
161
-
162
- # A full st.rerun() can be a bit disruptive if not needed.
163
- # Streamlit's chat_input and context managers usually handle updates well.
164
- # If messages aren't appearing correctly, a targeted rerun might be useful.
165
- # st.rerun()
 
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")
 
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__}"))