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__}"))