File size: 5,323 Bytes
2def93d
4060393
 
c645389
1c2dc95
4ef479c
4060393
691e8b4
c645389
e69869b
b1e9ba4
691e8b4
b1e9ba4
4ef479c
 
 
4060393
4ef479c
 
 
 
 
 
 
 
 
 
 
691e8b4
c0332bf
4060393
691e8b4
e69869b
 
98f2c4f
 
 
691e8b4
5c03320
 
691e8b4
 
 
 
 
 
d4828d9
 
 
 
 
 
 
 
 
 
 
 
e69869b
 
 
691e8b4
fa08413
 
d6ba0ba
d4828d9
db82163
 
 
d4828d9
 
 
 
db82163
 
 
 
 
d4828d9
691e8b4
 
fa08413
691e8b4
1b961be
fa08413
691e8b4
fa08413
 
 
691e8b4
4867300
17e4a36
fa08413
4867300
 
 
 
fa08413
4867300
 
 
 
17e4a36
4867300
 
 
 
17e4a36
4867300
 
 
 
 
 
 
 
 
 
 
17e4a36
4867300
aad9375
691e8b4
4867300
 
 
691e8b4
 
4867300
 
 
 
 
 
691e8b4
 
4867300
 
 
 
691e8b4
4867300
691e8b4
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
import streamlit as st
from openai import OpenAI
import time
import os
import pandas as pd
from datetime import datetime

# Load environment variables
openai_key = os.getenv("openai_key")
assistant_id = os.getenv("ASSISTANT_ID")

# Set up transcript log
transcript_file = "transcripts.xlsx"
if not os.path.exists(transcript_file):
    df = pd.DataFrame(columns=["timestamp", "thread_id", "role", "message"])
    df.to_excel(transcript_file, index=False)

def append_to_transcript(thread_id, role, message):
    df_existing = pd.read_excel(transcript_file)
    new_entry = pd.DataFrame({
        "timestamp": [datetime.now().strftime("%Y-%m-%d %H:%M:%S")],
        "thread_id": [thread_id],
        "role": [role],
        "message": [message]
    })
    updated_df = pd.concat([df_existing, new_entry], ignore_index=True)
    updated_df.to_excel(transcript_file, index=False)

# Configure page
st.set_page_config(page_title="Carfind.co.za AI Assistant", layout="wide")

# Inject custom styling
st.markdown("""
    <style>
    .block-container {padding-top: 1rem; padding-bottom: 0rem;}
    header {visibility: hidden;}
    .st-emotion-cache-18ni7ap {visibility: hidden;}
    .stChatMessage { max-width: 85%; border-radius: 12px; padding: 8px; margin-bottom: 10px; }
    .stChatMessage[data-testid="stChatMessage-user"] { background: #f0f0f0; color: #000000; }
    .stChatMessage[data-testid="stChatMessage-assistant"] { background: #D6E9FE; color: #000000; }
    div[data-testid="column"] button {
        border: none;
        background-color: transparent;
        font-size: 1.4rem;
        margin-top: 18px;
    }

    /* Logo bounce animation */
    @keyframes bounceIn {
        0%   { transform: scale(0.7); opacity: 0; }
        60%  { transform: scale(1.1); opacity: 1; }
        80%  { transform: scale(0.95); }
        100% { transform: scale(1); }
    }

    .carfind-logo {
        animation: bounceIn 0.6s ease-out;
    }
    </style>
""", unsafe_allow_html=True)

# Initialize session
if "thread_id" not in st.session_state:
    st.session_state["thread_id"] = None

# Carfind logo + powered by text (animated)
st.markdown(
    """
    <div style='text-align: center; margin-top: 20px; margin-bottom: -10px;'>
        <span style='display: inline-flex; align-items: center; gap: 8px;'>
            <img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='30' class='carfind-logo'/>
            <span style='font-size: 14px; color: gray;'>Powered by Carfind</span>
        </span>
    </div>
    """,
    unsafe_allow_html=True
)

# Chat input + inline clear button
input_col, clear_col = st.columns([9, 1])

with input_col:
    user_input = st.chat_input("Type your message here...")

with clear_col:
    if st.button("🗑️", key="clear-chat", help="Clear Chat"):
        st.session_state["thread_id"] = None
        st.rerun()

# Chat logic
if openai_key and assistant_id:
    client = OpenAI(api_key=openai_key)

    if user_input:
        if not st.session_state["thread_id"]:
            thread = client.beta.threads.create()
            st.session_state["thread_id"] = thread.id

        client.beta.threads.messages.create(
            thread_id=st.session_state["thread_id"], role="user", content=user_input
        )
        append_to_transcript(st.session_state["thread_id"], "user", user_input)

        try:
            with st.spinner("Thinking and typing... 💭"):
                run = client.beta.threads.runs.create(
                    thread_id=st.session_state["thread_id"], assistant_id=assistant_id
                )
                while True:
                    run_status = client.beta.threads.runs.retrieve(
                        thread_id=st.session_state["thread_id"], run_id=run.id
                    )
                    if run_status.status == "completed":
                        break
                    time.sleep(1)

            messages_response = client.beta.threads.messages.list(
                thread_id=st.session_state["thread_id"]
            )

            assistant_icon_html = "<img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='22' style='vertical-align:middle;'/>"
            messages_sorted = sorted(messages_response.data, key=lambda x: x.created_at, reverse=True)

            for msg in messages_sorted:
                if msg.role == "user":
                    st.markdown(
                        f"<div class='stChatMessage' data-testid='stChatMessage-user'>"
                        f"👤 <strong>You:</strong> {msg.content[0].text.value}</div>",
                        unsafe_allow_html=True
                    )
                else:
                    response_text = msg.content[0].text.value
                    append_to_transcript(st.session_state["thread_id"], "assistant", response_text)
                    st.markdown(
                        f"<div class='stChatMessage' data-testid='stChatMessage-assistant'>"
                        f"{assistant_icon_html} <strong>Carfind Assistant:</strong> {response_text}</div>",
                        unsafe_allow_html=True
                    )

        except Exception as e:
            st.error(f"❌ An error occurred: {str(e)}")
else:
    st.error("⚠️ OpenAI key or Assistant ID not found. Please ensure both are set as Hugging Face secrets.")