File size: 7,674 Bytes
71a1c43 2b9aa0c 352a295 2b9aa0c 352a295 2b9aa0c 352a295 2b9aa0c 352a295 2b9aa0c 352a295 71a1c43 2b9aa0c 71a1c43 352a295 71a1c43 2b9aa0c 352a295 2b9aa0c 352a295 2b9aa0c 71a1c43 2b9aa0c 352a295 2b9aa0c 71a1c43 352a295 2b9aa0c 352a295 71a1c43 2b9aa0c 352a295 2b9aa0c 71a1c43 2b9aa0c 352a295 2b9aa0c 71a1c43 352a295 71a1c43 352a295 71a1c43 352a295 71a1c43 2b9aa0c 352a295 71a1c43 2b9aa0c 71a1c43 2b9aa0c 352a295 71a1c43 352a295 71a1c43 352a295 71a1c43 352a295 71a1c43 352a295 71a1c43 352a295 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# /home/user/app/pages/2_Consult.py
import streamlit as st
from langchain_core.messages import HumanMessage, AIMessage # SystemMessage, ToolMessage removed if not used directly
from datetime import datetime
from typing import List, Optional
from sqlmodel import select # <--- IMPORT SELECT FOR SQLMODEL QUERIES
from config.settings import settings
from agent import get_agent_executor
from models import ChatMessage, ChatSession, User # User not directly used if ID is sufficient
from models.db import get_session_context
from services.logger import app_logger
from services.metrics import log_consultation_start
# --- Auth Check (same as before) ---
if not st.session_state.get("authenticated_user_id"):
st.warning("Please log in to access the consultation page.")
try:
st.switch_page("app.py")
except st.errors.StreamlitAPIException: # Catch specific error if needed
st.info("Please navigate to the main login page.")
st.stop()
authenticated_user_id = st.session_state.get("authenticated_user_id")
authenticated_username = st.session_state.get("authenticated_username", "User")
app_logger.info(f"User {authenticated_username} (ID: {authenticated_user_id}) accessed Consult page.")
# --- Initialize Agent (same as before) ---
try:
agent_executor = get_agent_executor()
except Exception as e:
st.error(f"Could not initialize AI Agent: {e}")
app_logger.critical(f"AI Agent initialization failed: {e}", exc_info=True)
st.stop()
# --- Helper Functions ---
@st.cache_data(ttl=60)
def load_chat_history_for_agent(session_id: int) -> List:
messages = []
app_logger.debug(f"Loading agent chat history for session_id: {session_id}")
with get_session_context() as db: # db is a SQLModel Session
# --- SQLMODEL QUERY ---
statement = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp)
db_messages_results = db.exec(statement)
db_messages = db_messages_results.all()
# --------------------
for msg in db_messages:
if msg.role == "user":
messages.append(HumanMessage(content=msg.content))
elif msg.role == "assistant":
messages.append(AIMessage(content=msg.content))
# Add ToolMessage handling if you store and use them
# elif msg.role == "tool" and hasattr(msg, 'tool_call_id') and msg.tool_call_id:
# messages.append(ToolMessage(content=msg.content, tool_call_id=str(msg.tool_call_id)))
app_logger.debug(f"Loaded {len(messages)} messages for agent history for session {session_id}.")
return messages
# save_chat_message_to_db remains the same as it's performing an insert, not a query.
# --- Page Logic ---
st.title("AI Consultation Room")
st.markdown(f"Interacting as: **{authenticated_username}**")
chat_session_id = st.session_state.get("current_chat_session_id")
if not chat_session_id:
st.error("No active chat session ID found. Please try logging out and back in.")
app_logger.error(f"User {authenticated_username} on Consult page with no current_chat_session_id.")
st.stop()
agent_history_key = f"agent_chat_history_{chat_session_id}"
if agent_history_key not in st.session_state:
st.session_state[agent_history_key] = load_chat_history_for_agent(chat_session_id)
if not st.session_state[agent_history_key]:
try:
log_consultation_start(user_id=authenticated_user_id, session_id=chat_session_id)
except Exception as e:
app_logger.warning(f"Failed to log consultation start: {e}")
initial_ai_message_content = "Hello! I am your AI Health Navigator. How can I assist you today?"
st.session_state[agent_history_key].append(AIMessage(content=initial_ai_message_content))
# save_chat_message_to_db(chat_session_id, "assistant", initial_ai_message_content) # save_chat_message_to_db defined elsewhere
# Ensure save_chat_message_to_db is defined or called correctly. For this example, it's:
with get_session_context() as db:
chat_msg_obj = ChatMessage(session_id=chat_session_id, role="assistant", content=initial_ai_message_content)
db.add(chat_msg_obj) # commit handled by context manager
app_logger.info(f"Initialized new consultation for session {chat_session_id} with a greeting.")
# Display chat messages for UI
with st.container():
with get_session_context() as db: # db is a SQLModel Session
# --- SQLMODEL QUERY ---
statement = select(ChatMessage).where(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp)
ui_messages_results = db.exec(statement)
ui_messages = ui_messages_results.all()
# --------------------
for msg in ui_messages:
avatar = "π§ββοΈ" if msg.role == "assistant" else "π€"
if msg.role == "tool": avatar = "π οΈ"
with st.chat_message(msg.role, avatar=avatar):
st.markdown(msg.content)
# Chat input and AI response logic (remains largely the same as it calls agent_executor and save_chat_message_to_db)
# ... (rest of 2_Consult.py from the previous good version)
# For brevity, I'm omitting the chat input and AI response handling section as it primarily
# uses `agent_executor.invoke` and `save_chat_message_to_db`, which itself doesn't change syntax for inserts.
def save_chat_message_to_db(session_id: int, role: str, content: str, tool_call_id: Optional[str]=None, tool_name: Optional[str]=None):
app_logger.debug(f"Saving message to DB for session {session_id}: Role={role}, Content snippet='{content[:50]}...'")
with get_session_context() as db:
chat_message = ChatMessage(
session_id=session_id,
role=role,
content=content,
timestamp=datetime.utcnow(),
tool_call_id=tool_call_id,
tool_name=tool_name
)
db.add(chat_message)
# db.commit() # Handled by context manager
app_logger.info(f"Message saved to DB for session {session_id}. Role: {role}.")
if prompt := st.chat_input("Ask the AI..."):
with st.chat_message("user", avatar="π€"):
st.markdown(prompt)
save_chat_message_to_db(chat_session_id, "user", prompt)
st.session_state[agent_history_key].append(HumanMessage(content=prompt))
with st.chat_message("assistant", avatar="π§ββοΈ"):
with st.spinner("AI is thinking..."):
try:
response = agent_executor.invoke({
"input": prompt,
"chat_history": st.session_state[agent_history_key]
})
ai_response_content = response.get('output', "No output from AI.")
if not isinstance(ai_response_content, str):
ai_response_content = str(ai_response_content)
st.markdown(ai_response_content)
save_chat_message_to_db(chat_session_id, "assistant", ai_response_content)
st.session_state[agent_history_key].append(AIMessage(content=ai_response_content))
except Exception as e:
app_logger.error(f"Error during agent invocation for session {chat_session_id}: {e}", exc_info=True)
error_message_user = f"Sorry, I encountered an error: {type(e).__name__}"
st.error(error_message_user)
save_chat_message_to_db(chat_session_id, "assistant", f"Error processing request: {type(e).__name__}")
st.session_state[agent_history_key].append(AIMessage(content=f"Observed internal error: {type(e).__name__}")) |