|
|
|
import streamlit as st |
|
from langchain_core.messages import HumanMessage, AIMessage |
|
from datetime import datetime |
|
from typing import List, Optional |
|
from sqlmodel import select |
|
|
|
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: |
|
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.") |
|
|
|
|
|
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() |
|
|
|
|
|
@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: |
|
|
|
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)) |
|
|
|
|
|
|
|
app_logger.debug(f"Loaded {len(messages)} messages for agent history for session {session_id}.") |
|
return messages |
|
|
|
|
|
|
|
|
|
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)) |
|
|
|
|
|
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) |
|
app_logger.info(f"Initialized new consultation for session {chat_session_id} with a greeting.") |
|
|
|
|
|
|
|
with st.container(): |
|
with get_session_context() as db: |
|
|
|
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) |
|
|
|
|
|
|
|
|
|
|
|
|
|
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) |
|
|
|
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__}")) |