|
|
|
import streamlit as st |
|
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage, ToolMessage |
|
from datetime import datetime |
|
from typing import List, Optional |
|
|
|
from config.settings import settings |
|
from agent import get_agent_executor |
|
from models import ChatMessage, ChatSession, User |
|
from models.db import get_session_context |
|
from services.logger import app_logger |
|
from services.metrics import log_consultation_start |
|
|
|
|
|
|
|
|
|
|
|
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 as e: |
|
if "st.switch_page can only be called when running in MPA mode" in str(e): |
|
app_logger.warning("Consult: Running in single-page mode or st.switch_page issue. Stopping script.") |
|
st.info("Please navigate to the main login page.") |
|
else: |
|
app_logger.error(f"Consult: Error during st.switch_page: {e}") |
|
st.error("Redirection error. Please go to the login page manually.") |
|
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.") |
|
|
|
|
|
try: |
|
agent_executor = get_agent_executor() |
|
except ValueError 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() |
|
except Exception as e: |
|
st.error(f"An unexpected error occurred while initializing the AI Agent: {e}") |
|
app_logger.critical(f"Unexpected AI Agent initialization error: {e}", exc_info=True) |
|
st.stop() |
|
|
|
|
|
|
|
@st.cache_data(ttl=60) |
|
def load_chat_history_for_agent(session_id: int) -> List: |
|
"""Loads chat history from DB for the current session, formatted for LangChain agent.""" |
|
messages = [] |
|
app_logger.debug(f"Loading agent chat history for session_id: {session_id}") |
|
with get_session_context() as db: |
|
|
|
|
|
db_messages = db.query(ChatMessage).filter(ChatMessage.session_id == session_id).order_by(ChatMessage.timestamp).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)) |
|
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 |
|
|
|
def save_chat_message_to_db(session_id: int, role: str, content: str, tool_call_id: Optional[str]=None, tool_name: Optional[str]=None): |
|
"""Saves a chat message to the database.""" |
|
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() |
|
app_logger.info(f"Message saved to DB for session {session_id}. Role: {role}.") |
|
|
|
|
|
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 in session state. This might happen if you logged in before this feature was fully active. Please try logging out and logging back in.") |
|
app_logger.error(f"User {authenticated_username} (ID: {authenticated_user_id}) 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) |
|
app_logger.info(f"Initialized new consultation for session {chat_session_id} with a greeting.") |
|
|
|
|
|
|
|
|
|
with st.container(): |
|
with get_session_context() as db: |
|
|
|
|
|
ui_messages = db.query(ChatMessage).filter(ChatMessage.session_id == chat_session_id).order_by(ChatMessage.timestamp).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) |
|
|
|
|
|
if prompt := st.chat_input("Ask the AI... (e.g., 'What is hypertension?' or 'Suggest diagnostic tests for chest pain')"): |
|
|
|
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 and could not process your request. Please try again or rephrase. (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__}")) |
|
|
|
|
|
|
|
|
|
|