Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 170 additions & 5 deletions e2e-chatbot-app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
from collections import OrderedDict
from messages import UserMessage, AssistantResponse, render_message

# Configure Streamlit page for Gainwell branding
st.set_page_config(
page_title="Gainwell AI Assistant",
page_icon="./gainwell_logo.svg",
layout="wide",
initial_sidebar_state="collapsed"
)

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -92,9 +100,116 @@ def reduce_chat_agent_chunks(chunks):
if "history" not in st.session_state:
st.session_state.history = []

st.title("🧱 Chatbot App")
st.write(f"A basic chatbot using your own serving endpoint.")
st.write(f"Endpoint name: `{SERVING_ENDPOINT}`")
# Custom CSS for Gainwell branding
st.markdown("""
<style>
/* Main container styling */
.main > div {
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
padding: 2rem;
border-radius: 10px;
margin-bottom: 1rem;
}

/* Header styling */
.gainwell-header {
background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%);
color: white;
padding: 2rem;
border-radius: 15px;
margin-bottom: 2rem;
box-shadow: 0 10px 25px rgba(30, 64, 175, 0.2);
}

.gainwell-title {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
text-align: center;
}

.gainwell-tagline {
font-size: 1.2rem;
text-align: center;
opacity: 0.9;
margin-bottom: 1rem;
}

.gainwell-description {
font-size: 1rem;
text-align: center;
opacity: 0.8;
max-width: 600px;
margin: 0 auto;
}

/* Chat message styling */
.stChatMessage {
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 1rem;
}

/* Input styling */
.stChatInputContainer {
background: white;
border-radius: 15px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

/* Status indicator */
.status-indicator {
background: #f0f9ff;
border: 1px solid #0ea5e9;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1.5rem;
color: #0c4a6e;
}

.status-label {
font-weight: 600;
margin-bottom: 0.5rem;
}

.status-value {
font-family: 'Courier New', monospace;
background: #e0f2fe;
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-size: 0.9rem;
}
</style>
""", unsafe_allow_html=True)

# Gainwell-branded header
with open('/Users/sam.sisto/app-templates/e2e-chatbot-app/gainwell_logo.svg', 'r') as f:
logo_svg = f.read()

st.markdown(f"""
<div class="gainwell-header">
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 1rem;">
<div style="width: 60px; height: 60px; margin-right: 1rem;">
{logo_svg}
</div>
<div class="gainwell-title" style="margin-bottom: 0;">Gainwell AI Assistant</div>
</div>
<div class="gainwell-tagline">Reliability. Innovation. Delivered.</div>
<div class="gainwell-description">
Your intelligent healthcare companion powered by advanced AI technology.
Supporting Medicaid modernization and public health initiatives with data-driven insights.
</div>
</div>
""", unsafe_allow_html=True)

# Status indicator
st.markdown(f"""
<div class="status-indicator">
<div class="status-label">🔗 Connected AI Endpoint:</div>
<div class="status-value">{SERVING_ENDPOINT}</div>
</div>
""", unsafe_allow_html=True)



Expand Down Expand Up @@ -315,8 +430,40 @@ def query_responses_endpoint_and_render(input_messages):



# --- Chat input (must run BEFORE rendering messages) ---
prompt = st.chat_input("Ask a question")
# --- Healthcare-focused suggestions ---
if not st.session_state.history:
st.markdown(f"""
<div style="background: #fefce8; border: 1px solid #eab308; border-radius: 12px; padding: 1.5rem; margin-bottom: 2rem;">
<div style="display: flex; align-items: center; margin-bottom: 1rem;">
<div style="width: 30px; height: 30px; margin-right: 0.5rem;">
{logo_svg}
</div>
<h4 style="color: #a16207; margin: 0;">Healthcare Use Cases</h4>
</div>
<p style="color: #a16207; margin-bottom: 1rem;">Ask me about healthcare topics such as:</p>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem;">
<div style="background: white; padding: 1rem; border-radius: 8px;">
<strong>Medicaid & Public Health</strong><br>
<small>Program management, enrollment, compliance</small>
</div>
<div style="background: white; padding: 1rem; border-radius: 8px;">
<strong>Data Analytics</strong><br>
<small>Population health insights, cost analysis</small>
</div>
<div style="background: white; padding: 1rem; border-radius: 8px;">
<strong>System Integration</strong><br>
<small>Interoperability, workflow optimization</small>
</div>
<div style="background: white; padding: 1rem; border-radius: 8px;">
<strong>Care Management</strong><br>
<small>Quality metrics, patient outcomes</small>
</div>
</div>
</div>
""", unsafe_allow_html=True)

# --- Chat input with healthcare-focused placeholder ---
prompt = st.chat_input("Ask about healthcare data, Medicaid programs, or population health insights...")
if prompt:
# Get the task type for this endpoint
task_type = _get_endpoint_task_type(SERVING_ENDPOINT)
Expand All @@ -334,3 +481,21 @@ def query_responses_endpoint_and_render(input_messages):

# Add assistant response to history
st.session_state.history.append(assistant_response)

# --- Footer ---
st.markdown(f"""
---
<div style="text-align: center; padding: 2rem 0; color: #64748b;">
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 1rem;">
<div style="width: 30px; height: 30px; margin-right: 0.5rem;">
{logo_svg}
</div>
<strong>Gainwell Technologies</strong>
</div>
<div style="font-size: 0.9rem;">
Healthcare Innovation & Modernization<br>
Supporting Medicaid agencies, providers, and public health initiatives nationwide<br>
<a href="https://www.gainwelltechnologies.com/" target="_blank" style="color: #3b82f6; text-decoration: none;">Learn more about Gainwell Technologies</a>
</div>
</div>
""", unsafe_allow_html=True)
8 changes: 8 additions & 0 deletions e2e-chatbot-app/gainwell_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 24 additions & 5 deletions e2e-chatbot-app/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,38 @@ def render(self, idx):


def render_message(msg):
"""Render a single message."""
"""Render a single message with healthcare-focused styling."""
if msg["role"] == "assistant":
# Render content first if it exists
if msg.get("content"):
st.markdown(msg["content"])

# Then render tool calls if they exist
# Then render tool calls if they exist with healthcare-focused icons and messaging
if "tool_calls" in msg and msg["tool_calls"]:
for call in msg["tool_calls"]:
fn_name = call["function"]["name"]
args = call["function"]["arguments"]
st.markdown(f"🛠️ Calling **`{fn_name}`** with:\n```json\n{args}\n```")
st.markdown(f"""
<div style="background: #f0f9ff; border-left: 4px solid #0ea5e9; padding: 1rem; margin: 0.5rem 0; border-radius: 0 8px 8px 0;">
<strong>⚙️ Healthcare Analysis Tool: {fn_name}</strong>
<details>
<summary style="cursor: pointer; color: #0c4a6e;">View parameters</summary>
<pre style="background: #e0f2fe; padding: 0.5rem; border-radius: 4px; margin-top: 0.5rem; font-size: 0.9rem;"><code>{args}</code></pre>
</details>
</div>
""", unsafe_allow_html=True)
elif msg["role"] == "tool":
st.markdown("🧰 Tool Response:")
st.markdown("""
<div style="background: #f0fdf4; border-left: 4px solid #22c55e; padding: 1rem; margin: 0.5rem 0; border-radius: 0 8px 8px 0;">
<strong>📈 Analysis Results:</strong>
</div>
""", unsafe_allow_html=True)
st.code(msg["content"], language="json")


@st.fragment
def render_assistant_message_feedback(i, request_id):
"""Render feedback UI for assistant messages."""
"""Render healthcare-focused feedback UI for assistant messages."""
from model_serving_utils import submit_feedback
import os

Expand All @@ -92,4 +104,11 @@ def save_feedback(index):
rating=st.session_state[f"feedback_{index}"]
)

# Healthcare-focused feedback prompt
st.markdown("""
<div style="background: #f8fafc; border-radius: 8px; padding: 1rem; margin-top: 1rem;">
<small style="color: #64748b;">Was this healthcare information helpful?</small>
</div>
""", unsafe_allow_html=True)

st.feedback("thumbs", key=f"feedback_{i}", on_change=save_feedback, args=[i])