IAMTFRMZA commited on
Commit
2060f4b
Β·
verified Β·
1 Parent(s): e39a43f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -66
app.py CHANGED
@@ -1,34 +1,35 @@
1
  import streamlit as st
2
  from openai import OpenAI
 
3
  import time
4
  import os
5
- import pandas as pd
6
  import uuid
7
- from datetime import datetime
8
-
9
- # Firebase setup
10
  import firebase_admin
11
  from firebase_admin import credentials, firestore
12
 
 
13
  if not firebase_admin._apps:
14
  cred = credentials.Certificate("firebase-service-account.json")
15
  firebase_admin.initialize_app(cred)
16
 
17
  db = firestore.client()
18
 
19
- # OpenAI setup
20
  openai_key = os.getenv("openai_key")
21
  assistant_id = os.getenv("ASSISTANT_ID")
22
 
 
 
 
23
  st.set_page_config(page_title="Carfind.co.za AI Assistant", layout="wide")
24
 
25
- # Session + Firebase user ID
26
  if "user_id" not in st.session_state:
27
  st.session_state["user_id"] = str(uuid.uuid4())
28
 
29
  user_id = st.session_state["user_id"]
30
 
31
- # Styling + Branding
32
  st.markdown("""
33
  <style>
34
  .block-container {padding-top: 1rem; padding-bottom: 0rem;}
@@ -36,16 +37,10 @@ st.markdown("""
36
  .stChatMessage { max-width: 85%; border-radius: 12px; padding: 8px; margin-bottom: 10px; }
37
  .stChatMessage[data-testid="stChatMessage-user"] { background: #f0f0f0; color: #000000; }
38
  .stChatMessage[data-testid="stChatMessage-assistant"] { background: #D6E9FE; color: #000000; }
39
- div[data-testid="column"] button {
40
- border: none;
41
- background-color: transparent;
42
- font-size: 1.4rem;
43
- margin-top: 18px;
44
- }
45
  @keyframes bounceIn {
46
- 0% { transform: scale(0.7); opacity: 0; }
47
- 60% { transform: scale(1.1); opacity: 1; }
48
- 80% { transform: scale(0.95); }
49
  100% { transform: scale(1); }
50
  }
51
  .carfind-logo {
@@ -63,37 +58,13 @@ st.markdown("""
63
  </div>
64
  """, unsafe_allow_html=True)
65
 
66
- # Chat input + Clear Chat button
67
- input_col, clear_col = st.columns([9, 1])
68
- with input_col:
69
- user_input = st.chat_input("Type your message here...")
70
-
71
- with clear_col:
72
- if st.button("πŸ—‘οΈ", key="clear-chat", help="Clear Chat"):
73
- try:
74
- # Delete messages
75
- user_doc_ref = db.collection("users").document(user_id)
76
- message_collection = user_doc_ref.collection("messages").stream()
77
- for msg in message_collection:
78
- msg.reference.delete()
79
- # Delete user doc
80
- user_doc_ref.delete()
81
-
82
- # Clear session and rerun
83
- st.session_state.clear()
84
- st.rerun()
85
-
86
- except Exception as e:
87
- st.error(f"Failed to clear chat: {e}")
88
-
89
- # Create or load thread ID from Firebase
90
  def get_or_create_thread_id():
91
  doc_ref = db.collection("users").document(user_id)
92
  doc = doc_ref.get()
93
  if doc.exists:
94
  return doc.to_dict()["thread_id"]
95
  else:
96
- client = OpenAI(api_key=openai_key)
97
  thread = client.beta.threads.create()
98
  doc_ref.set({
99
  "thread_id": thread.id,
@@ -101,7 +72,6 @@ def get_or_create_thread_id():
101
  })
102
  return thread.id
103
 
104
- # Save message to Firestore
105
  def save_message(role, content):
106
  db.collection("users").document(user_id).collection("messages").add({
107
  "role": role,
@@ -109,16 +79,12 @@ def save_message(role, content):
109
  "timestamp": firestore.SERVER_TIMESTAMP
110
  })
111
 
112
- # Display past chat messages (latest at the top)
113
  def display_chat_history():
114
  messages = db.collection("users").document(user_id).collection("messages") \
115
  .order_by("timestamp").stream()
116
 
117
- messages_list = list(messages)[::-1] # Reverse to show latest first
118
-
119
  assistant_icon_html = "<img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='22' style='vertical-align:middle;'/>"
120
-
121
- for msg in messages_list:
122
  data = msg.to_dict()
123
  if data["role"] == "user":
124
  st.markdown(
@@ -132,29 +98,38 @@ def display_chat_history():
132
  unsafe_allow_html=True
133
  )
134
 
135
- # OpenAI assistant interaction
136
- if openai_key and assistant_id:
137
- client = OpenAI(api_key=openai_key)
138
- thread_id = get_or_create_thread_id()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
 
140
  display_chat_history()
141
 
142
  if user_input:
143
- client.beta.threads.messages.create(
144
- thread_id=thread_id, role="user", content=user_input
145
- )
146
  save_message("user", user_input)
147
 
148
  with st.spinner("Thinking and typing... πŸ’­"):
149
- run = client.beta.threads.runs.create(
150
- thread_id=thread_id,
151
- assistant_id=assistant_id
152
- )
153
  while True:
154
- run_status = client.beta.threads.runs.retrieve(
155
- thread_id=thread_id,
156
- run_id=run.id
157
- )
158
  if run_status.status == "completed":
159
  break
160
  time.sleep(1)
@@ -163,8 +138,74 @@ if openai_key and assistant_id:
163
  latest_response = sorted(messages_response.data, key=lambda x: x.created_at)[-1]
164
  assistant_message = latest_response.content[0].text.value
165
  save_message("assistant", assistant_message)
166
-
167
- time.sleep(0.5) # Ensure Firestore timestamps sort properly
168
  st.rerun()
169
- else:
170
- st.error("⚠️ OpenAI key or Assistant ID not found. Please set them as Hugging Face secrets.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  from openai import OpenAI
3
+ from PIL import Image
4
  import time
5
  import os
 
6
  import uuid
 
 
 
7
  import firebase_admin
8
  from firebase_admin import credentials, firestore
9
 
10
+ # πŸ” Firebase setup
11
  if not firebase_admin._apps:
12
  cred = credentials.Certificate("firebase-service-account.json")
13
  firebase_admin.initialize_app(cred)
14
 
15
  db = firestore.client()
16
 
17
+ # πŸ” OpenAI setup
18
  openai_key = os.getenv("openai_key")
19
  assistant_id = os.getenv("ASSISTANT_ID")
20
 
21
+ client = OpenAI(api_key=openai_key)
22
+
23
+ # 🌐 Streamlit Config
24
  st.set_page_config(page_title="Carfind.co.za AI Assistant", layout="wide")
25
 
26
+ # 🎯 Session + User ID
27
  if "user_id" not in st.session_state:
28
  st.session_state["user_id"] = str(uuid.uuid4())
29
 
30
  user_id = st.session_state["user_id"]
31
 
32
+ # πŸ–ΌοΈ Branding + Styling
33
  st.markdown("""
34
  <style>
35
  .block-container {padding-top: 1rem; padding-bottom: 0rem;}
 
37
  .stChatMessage { max-width: 85%; border-radius: 12px; padding: 8px; margin-bottom: 10px; }
38
  .stChatMessage[data-testid="stChatMessage-user"] { background: #f0f0f0; color: #000000; }
39
  .stChatMessage[data-testid="stChatMessage-assistant"] { background: #D6E9FE; color: #000000; }
 
 
 
 
 
 
40
  @keyframes bounceIn {
41
+ 0% { transform: scale(0.7); opacity: 0; }
42
+ 60% { transform: scale(1.1); opacity: 1; }
43
+ 80% { transform: scale(0.95); }
44
  100% { transform: scale(1); }
45
  }
46
  .carfind-logo {
 
58
  </div>
59
  """, unsafe_allow_html=True)
60
 
61
+ # πŸ” Firebase Chat Functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  def get_or_create_thread_id():
63
  doc_ref = db.collection("users").document(user_id)
64
  doc = doc_ref.get()
65
  if doc.exists:
66
  return doc.to_dict()["thread_id"]
67
  else:
 
68
  thread = client.beta.threads.create()
69
  doc_ref.set({
70
  "thread_id": thread.id,
 
72
  })
73
  return thread.id
74
 
 
75
  def save_message(role, content):
76
  db.collection("users").document(user_id).collection("messages").add({
77
  "role": role,
 
79
  "timestamp": firestore.SERVER_TIMESTAMP
80
  })
81
 
 
82
  def display_chat_history():
83
  messages = db.collection("users").document(user_id).collection("messages") \
84
  .order_by("timestamp").stream()
85
 
 
 
86
  assistant_icon_html = "<img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='22' style='vertical-align:middle;'/>"
87
+ for msg in list(messages)[::-1]:
 
88
  data = msg.to_dict()
89
  if data["role"] == "user":
90
  st.markdown(
 
98
  unsafe_allow_html=True
99
  )
100
 
101
+ # 🧭 Tabs: AI Chat | Car Identifier
102
+ tab1, tab2 = st.tabs(["πŸ€– AI Chat", "πŸš— What car is that?"])
103
+
104
+ # πŸ€– AI Chat Tab
105
+ with tab1:
106
+ input_col, clear_col = st.columns([9, 1])
107
+ with input_col:
108
+ user_input = st.chat_input("Type your message here...")
109
+
110
+ with clear_col:
111
+ if st.button("πŸ—‘οΈ", key="clear-chat", help="Clear Chat"):
112
+ try:
113
+ user_doc_ref = db.collection("users").document(user_id)
114
+ for msg in user_doc_ref.collection("messages").stream():
115
+ msg.reference.delete()
116
+ user_doc_ref.delete()
117
+ st.session_state.clear()
118
+ st.rerun()
119
+ except Exception as e:
120
+ st.error(f"Failed to clear chat: {e}")
121
 
122
+ thread_id = get_or_create_thread_id()
123
  display_chat_history()
124
 
125
  if user_input:
126
+ client.beta.threads.messages.create(thread_id=thread_id, role="user", content=user_input)
 
 
127
  save_message("user", user_input)
128
 
129
  with st.spinner("Thinking and typing... πŸ’­"):
130
+ run = client.beta.threads.runs.create(thread_id=thread_id, assistant_id=assistant_id)
 
 
 
131
  while True:
132
+ run_status = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
 
 
 
133
  if run_status.status == "completed":
134
  break
135
  time.sleep(1)
 
138
  latest_response = sorted(messages_response.data, key=lambda x: x.created_at)[-1]
139
  assistant_message = latest_response.content[0].text.value
140
  save_message("assistant", assistant_message)
141
+ time.sleep(0.5)
 
142
  st.rerun()
143
+
144
+ # πŸš— What car is that? Tab
145
+ with tab2:
146
+ st.header("πŸ–ΌοΈ Upload a Car Image for Identification")
147
+ uploaded_image = st.file_uploader("Upload an image of a car", type=["jpg", "jpeg", "png"])
148
+
149
+ if uploaded_image:
150
+ col1, col2 = st.columns([1.2, 1.8])
151
+
152
+ with col1:
153
+ image = Image.open(uploaded_image)
154
+ st.image(image, caption="Uploaded Image", use_container_width=True)
155
+
156
+ with col2:
157
+ try:
158
+ image_thread = client.beta.threads.create()
159
+ file_response = client.files.create(file=uploaded_image, purpose="assistants")
160
+
161
+ client.beta.threads.messages.create(
162
+ thread_id=image_thread.id,
163
+ role="user",
164
+ content=[
165
+ {
166
+ "type": "image_file",
167
+ "image_file": {"file_id": file_response.id}
168
+ },
169
+ {
170
+ "type": "text",
171
+ "text": "Please identify this car from the image."
172
+ }
173
+ ]
174
+ )
175
+
176
+ run = client.beta.threads.runs.create(
177
+ thread_id=image_thread.id,
178
+ assistant_id=assistant_id
179
+ )
180
+
181
+ with st.spinner("πŸ” Analyzing image and identifying the car..."):
182
+ while True:
183
+ run_status = client.beta.threads.runs.retrieve(
184
+ thread_id=image_thread.id,
185
+ run_id=run.id
186
+ )
187
+ if run_status.status == "completed":
188
+ break
189
+ time.sleep(1)
190
+
191
+ messages = client.beta.threads.messages.list(thread_id=image_thread.id)
192
+ assistant_message = messages.data[0].content[0].text.value
193
+
194
+ st.success("βœ… Identification Complete")
195
+ st.markdown(f"""
196
+ <div style='
197
+ font-size: 15px;
198
+ background-color: #1a1f25;
199
+ color: #ffffff;
200
+ padding: 18px 20px;
201
+ border-radius: 10px;
202
+ border-left: 6px solid #4CAF50;
203
+ box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
204
+ '>
205
+ <span style='font-size: 18px; font-weight: bold;'>πŸ” Identified Car Details:</span><br><br>
206
+ {assistant_message}
207
+ </div>
208
+ """, unsafe_allow_html=True)
209
+
210
+ except Exception as e:
211
+ st.error(f"❌ Error during image analysis: {str(e)}")