mgbam commited on
Commit
f6673c4
·
verified ·
1 Parent(s): b8aec8c

Update pages/3_Reports.py

Browse files
Files changed (1) hide show
  1. pages/3_Reports.py +81 -44
pages/3_Reports.py CHANGED
@@ -1,17 +1,17 @@
1
  # /home/user/app/pages/3_Reports.py
2
  import streamlit as st
3
  from datetime import datetime
4
- from typing import List, Dict, Any # For type hinting the dictionary
5
  from sqlmodel import select
6
 
7
  from config.settings import settings
8
- from models import ChatMessage, ChatSession # ChatSession model still needed for query
9
  from models.db import get_session_context
10
  from services.pdf_report import generate_pdf_report
11
  from services.logger import app_logger
12
  from services.metrics import log_report_generated
13
 
14
- # --- Authentication Check ---
15
  if not st.session_state.get("authenticated_user_id"):
16
  st.warning("Please log in to access reports.")
17
  try:
@@ -28,46 +28,36 @@ st.title("Consultation Reports")
28
  st.markdown("View and download your past consultation sessions.")
29
 
30
  # --- Helper Function to Load User's Chat Session Data (Primitives) ---
31
- # @st.cache_data(ttl=300) # If caching, ensure it works well with this primitive data structure
32
  def get_user_chat_session_display_data(user_id: int) -> List[Dict[str, Any]]:
33
- """
34
- Fetches essential data for chat sessions for display, not full ORM objects.
35
- Returns a list of dictionaries.
36
- """
37
  app_logger.debug(f"Fetching chat session display data for user_id: {user_id}")
38
  session_data_list: List[Dict[str, Any]] = []
39
  try:
40
  with get_session_context() as db_session:
41
- # Select specific columns needed for display
42
  statement = select(ChatSession.id, ChatSession.title, ChatSession.start_time)\
43
  .where(ChatSession.user_id == user_id)\
44
  .order_by(ChatSession.start_time.desc())
45
- results = db_session.exec(statement).all() # results will be list of Rows/Tuples
46
-
47
  for row in results:
48
  session_data_list.append({
49
  "id": row.id,
50
  "title": row.title,
51
- "start_time": row.start_time # Store the datetime object, format it later
52
  })
53
  app_logger.debug(f"Found {len(session_data_list)} session display entries for user_id: {user_id}")
54
  except Exception as e:
55
  app_logger.error(f"Error fetching chat session display data for user_id {user_id}: {e}", exc_info=True)
56
- st.error("Could not load your chat sessions. Please try again later.")
57
  return session_data_list
58
 
59
- # Fetch session display data for the current authenticated user
60
  chat_session_display_items = get_user_chat_session_display_data(authenticated_user_id)
61
 
62
  if not chat_session_display_items:
63
  st.info("You have no past consultation sessions recorded.")
64
  st.stop()
65
 
66
- # --- Display Sessions and Download Option ---
67
- # Prepare options for the selectbox: (Display String, Session ID)
68
  session_options = []
69
  for s_data in chat_session_display_items:
70
- # Access data from the dictionary
71
  start_time_obj = s_data["start_time"]
72
  start_time_display = start_time_obj.strftime('%Y-%m-%d %H:%M') if start_time_obj else "Date N/A"
73
  title_display = s_data["title"] if s_data["title"] else f"Consultation on {start_time_display}"
@@ -81,50 +71,97 @@ selected_option_tuple = st.selectbox(
81
  index=0
82
  )
83
 
 
 
84
  if selected_option_tuple:
85
  selected_session_id = selected_option_tuple[1]
86
- app_logger.info(f"User '{authenticated_username}' selected session ID: {selected_session_id} for report viewing.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
- # Find the selected session's data from the list of dictionaries
89
  selected_session_data = next((s_data for s_data in chat_session_display_items if s_data['id'] == selected_session_id), None)
90
 
91
  if selected_session_data:
92
  st.markdown("---")
93
  st.subheader(f"Details for Session ID: {selected_session_data['id']}")
94
-
95
  start_time_obj_detail = selected_session_data["start_time"]
96
  start_time_detail_display = start_time_obj_detail.strftime('%Y-%m-%d %H:%M:%S UTC') if start_time_obj_detail else "Not recorded"
97
  st.write(f"**Started:** {start_time_detail_display}")
98
  st.write(f"**Title:** {selected_session_data['title'] or 'Untitled Session'}")
99
 
100
- # Fetch messages ONLY for the selected session when needed
101
- messages_for_report: List[ChatMessage] = []
102
- try:
103
- with get_session_context() as db_session:
104
- statement = select(ChatMessage).where(ChatMessage.session_id == selected_session_id).order_by(ChatMessage.timestamp)
105
- results = db_session.exec(statement)
106
- messages_for_report = results.all()
107
- except Exception as e:
108
- app_logger.error(f"Error fetching messages for session {selected_session_id}: {e}", exc_info=True)
109
- st.error("Could not load messages for this session.")
110
-
111
- if messages_for_report:
112
  with st.expander("View Chat Transcript", expanded=False):
113
- for msg_idx, msg in enumerate(messages_for_report):
114
- # Accessing msg.role, msg.timestamp, msg.content should be fine here
115
- # as `messages_for_report` are newly fetched ORM objects within an active (though soon to close) session.
116
- # The key is that their attributes are accessed while their session is implicitly active or just before it closes.
117
- icon = "🧑‍⚕️" if msg.role == "assistant" else "👤"
118
- if msg.role == "tool": icon = "🛠️"
119
- timestamp_display = msg.timestamp.strftime('%Y-%m-%d %H:%M:%S') if msg.timestamp else "Time N/A"
120
- st.markdown(f"**{icon} {msg.role.capitalize()}** ({timestamp_display})")
121
- st.markdown(f"> ```\n{msg.content}\n```")
122
- if msg_idx < len(messages_for_report) - 1:
 
 
 
123
  st.markdown("---")
124
-
125
  st.markdown("---")
126
  try:
127
- pdf_bytes = generate_pdf_report(messages_for_report, patient_name=authenticated_username)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  current_time_str = datetime.now().strftime('%Y%m%d_%H%M%S')
129
  pdf_file_name = f"Consultation_Report_Session{selected_session_id}_{current_time_str}.pdf"
130
  st.download_button(
 
1
  # /home/user/app/pages/3_Reports.py
2
  import streamlit as st
3
  from datetime import datetime
4
+ from typing import List, Dict, Any
5
  from sqlmodel import select
6
 
7
  from config.settings import settings
8
+ from models import ChatMessage, ChatSession # ChatMessage model for query
9
  from models.db import get_session_context
10
  from services.pdf_report import generate_pdf_report
11
  from services.logger import app_logger
12
  from services.metrics import log_report_generated
13
 
14
+ # --- Authentication Check (same as before) ---
15
  if not st.session_state.get("authenticated_user_id"):
16
  st.warning("Please log in to access reports.")
17
  try:
 
28
  st.markdown("View and download your past consultation sessions.")
29
 
30
  # --- Helper Function to Load User's Chat Session Data (Primitives) ---
31
+ # @st.cache_data(ttl=300)
32
  def get_user_chat_session_display_data(user_id: int) -> List[Dict[str, Any]]:
 
 
 
 
33
  app_logger.debug(f"Fetching chat session display data for user_id: {user_id}")
34
  session_data_list: List[Dict[str, Any]] = []
35
  try:
36
  with get_session_context() as db_session:
 
37
  statement = select(ChatSession.id, ChatSession.title, ChatSession.start_time)\
38
  .where(ChatSession.user_id == user_id)\
39
  .order_by(ChatSession.start_time.desc())
40
+ results = db_session.exec(statement).all()
 
41
  for row in results:
42
  session_data_list.append({
43
  "id": row.id,
44
  "title": row.title,
45
+ "start_time": row.start_time
46
  })
47
  app_logger.debug(f"Found {len(session_data_list)} session display entries for user_id: {user_id}")
48
  except Exception as e:
49
  app_logger.error(f"Error fetching chat session display data for user_id {user_id}: {e}", exc_info=True)
50
+ st.error("Could not load your chat sessions.")
51
  return session_data_list
52
 
 
53
  chat_session_display_items = get_user_chat_session_display_data(authenticated_user_id)
54
 
55
  if not chat_session_display_items:
56
  st.info("You have no past consultation sessions recorded.")
57
  st.stop()
58
 
 
 
59
  session_options = []
60
  for s_data in chat_session_display_items:
 
61
  start_time_obj = s_data["start_time"]
62
  start_time_display = start_time_obj.strftime('%Y-%m-%d %H:%M') if start_time_obj else "Date N/A"
63
  title_display = s_data["title"] if s_data["title"] else f"Consultation on {start_time_display}"
 
71
  index=0
72
  )
73
 
74
+ # --- Store Fetched Message Data in Session State to Persist Across Reruns ---
75
+ # This key will be specific to the selected session to avoid conflicts if the user selects another session.
76
  if selected_option_tuple:
77
  selected_session_id = selected_option_tuple[1]
78
+ MESSAGES_FOR_SESSION_KEY = f"messages_for_session_{selected_session_id}"
79
+
80
+ # Fetch messages only if not already in session state for this selected session, or if forced refresh
81
+ if MESSAGES_FOR_SESSION_KEY not in st.session_state:
82
+ app_logger.info(f"Fetching messages for session ID: {selected_session_id} as not in session_state.")
83
+ messages_data_for_display: List[Dict[str, Any]] = []
84
+ try:
85
+ with get_session_context() as db_session:
86
+ # Select specific columns needed
87
+ statement = select(
88
+ ChatMessage.role,
89
+ ChatMessage.content,
90
+ ChatMessage.timestamp,
91
+ ChatMessage.tool_name # If you use it
92
+ ).where(ChatMessage.session_id == selected_session_id).order_by(ChatMessage.timestamp)
93
+
94
+ results = db_session.exec(statement).all() # List of Row objects
95
+
96
+ for msg_row in results:
97
+ messages_data_for_display.append({
98
+ "role": msg_row.role,
99
+ "content": msg_row.content,
100
+ "timestamp": msg_row.timestamp, # Keep as datetime for formatting
101
+ "tool_name": msg_row.tool_name if hasattr(msg_row, 'tool_name') else None
102
+ })
103
+ st.session_state[MESSAGES_FOR_SESSION_KEY] = messages_data_for_display
104
+ app_logger.info(f"Fetched and stored {len(messages_data_for_display)} messages for session {selected_session_id} in session_state.")
105
+ except Exception as e:
106
+ app_logger.error(f"Error fetching messages for session {selected_session_id}: {e}", exc_info=True)
107
+ st.error("Could not load messages for this session.")
108
+ st.session_state[MESSAGES_FOR_SESSION_KEY] = [] # Store empty list on error
109
+ else:
110
+ app_logger.debug(f"Using cached messages from session_state for session ID: {selected_session_id}")
111
+ messages_data_for_display = st.session_state[MESSAGES_FOR_SESSION_KEY]
112
+
113
 
114
+ # --- Display selected session details and messages ---
115
  selected_session_data = next((s_data for s_data in chat_session_display_items if s_data['id'] == selected_session_id), None)
116
 
117
  if selected_session_data:
118
  st.markdown("---")
119
  st.subheader(f"Details for Session ID: {selected_session_data['id']}")
 
120
  start_time_obj_detail = selected_session_data["start_time"]
121
  start_time_detail_display = start_time_obj_detail.strftime('%Y-%m-%d %H:%M:%S UTC') if start_time_obj_detail else "Not recorded"
122
  st.write(f"**Started:** {start_time_detail_display}")
123
  st.write(f"**Title:** {selected_session_data['title'] or 'Untitled Session'}")
124
 
125
+ if messages_data_for_display: # Use the data from session_state
 
 
 
 
 
 
 
 
 
 
 
126
  with st.expander("View Chat Transcript", expanded=False):
127
+ for msg_idx, msg_data in enumerate(messages_data_for_display): # Iterate over list of dicts
128
+ # Access data from the dictionary
129
+ role = msg_data["role"]
130
+ content = msg_data["content"]
131
+ timestamp_obj = msg_data["timestamp"]
132
+
133
+ icon = "🧑‍⚕️" if role == "assistant" else "👤"
134
+ if role == "tool": icon = "🛠️"
135
+ timestamp_display = timestamp_obj.strftime('%Y-%m-%d %H:%M:%S') if timestamp_obj else "Time N/A"
136
+
137
+ st.markdown(f"**{icon} {role.capitalize()}** ({timestamp_display})")
138
+ st.markdown(f"> ```\n{content}\n```")
139
+ if msg_idx < len(messages_data_for_display) - 1:
140
  st.markdown("---")
141
+
142
  st.markdown("---")
143
  try:
144
+ # For PDF generation, we might need to reconstruct ChatMessage-like objects
145
+ # if generate_pdf_report strictly expects List[ChatMessage].
146
+ # Or, modify generate_pdf_report to accept List[Dict].
147
+ # For now, assuming generate_pdf_report can handle List[Dict] or we adapt.
148
+
149
+ # If generate_pdf_report strictly needs ChatMessage instances:
150
+ pdf_report_messages = []
151
+ for msg_d in messages_data_for_display:
152
+ # This is a mock ChatMessage, not an ORM instance.
153
+ # Ensure your generate_pdf_report can handle this structure.
154
+ pdf_report_messages.append(
155
+ ChatMessage( # Re-create a temporary (non-ORM) ChatMessage-like object
156
+ role=msg_d["role"],
157
+ content=msg_d["content"],
158
+ timestamp=msg_d["timestamp"], # datetime object
159
+ tool_name=msg_d.get("tool_name") # Get tool_name if exists
160
+ # session_id and id are not strictly needed if generate_pdf_report doesn't use them.
161
+ )
162
+ )
163
+
164
+ pdf_bytes = generate_pdf_report(pdf_report_messages, patient_name=authenticated_username)
165
  current_time_str = datetime.now().strftime('%Y%m%d_%H%M%S')
166
  pdf_file_name = f"Consultation_Report_Session{selected_session_id}_{current_time_str}.pdf"
167
  st.download_button(