IAMTFRMZA commited on
Commit
53b56c5
Β·
verified Β·
1 Parent(s): a589322

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -68
app.py CHANGED
@@ -47,24 +47,25 @@ st.markdown("""
47
  }
48
  .car-spec-output {
49
  font-family: "Segoe UI", sans-serif;
50
- font-size: 14px;
51
  background-color: #ffffff;
52
  color: #003B6F;
53
- padding: 20px;
54
  border-radius: 10px;
55
  box-shadow: 0 4px 12px rgba(0,0,0,0.05);
56
- border-left: 5px solid #0071BC;
57
- line-height: 1.6;
58
  }
59
  .spec-table {
60
  width: 100%;
61
  border-collapse: collapse;
62
- margin-top: 15px;
63
- margin-bottom: 20px;
 
64
  }
65
  .spec-table th, .spec-table td {
66
  border: 1px solid #ddd;
67
- padding: 10px 12px;
68
  text-align: left;
69
  }
70
  .spec-table th {
@@ -75,9 +76,9 @@ st.markdown("""
75
  background-color: #f7f9fc;
76
  }
77
  .icon {
78
- width: 16px;
79
  vertical-align: middle;
80
- margin-right: 6px;
81
  }
82
  </style>
83
  """, unsafe_allow_html=True)
@@ -85,13 +86,14 @@ st.markdown("""
85
  st.markdown("""
86
  <div style='text-align: center; margin-top: 20px; margin-bottom: -10px;'>
87
  <span style='display: inline-flex; align-items: center; gap: 8px;'>
88
- <img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='30' class='carfind-logo'/>
89
- <span style='font-size: 14px; color: gray;'>Powered by Carfind</span>
90
  </span>
91
  </div>
92
  """, unsafe_allow_html=True)
93
 
94
- # πŸ” Firebase Chat Functions
 
95
  def get_or_create_thread_id():
96
  doc_ref = db.collection("users").document(user_id)
97
  doc = doc_ref.get()
@@ -113,33 +115,23 @@ def save_message(role, content):
113
  })
114
 
115
  def display_chat_history():
116
- messages = db.collection("users").document(user_id).collection("messages") \
117
- .order_by("timestamp").stream()
118
-
119
- assistant_icon_html = "<img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='22' style='vertical-align:middle;'/>"
120
  for msg in list(messages)[::-1]:
121
  data = msg.to_dict()
122
  if data["role"] == "user":
123
- st.markdown(
124
- f"<div class='stChatMessage' data-testid='stChatMessage-user'>"
125
- f"πŸ‘€ <strong>You:</strong> {data['content']}</div>", unsafe_allow_html=True
126
- )
127
  else:
128
- st.markdown(
129
- f"<div class='stChatMessage' data-testid='stChatMessage-assistant'>"
130
- f"{assistant_icon_html} <strong>Carfind Assistant:</strong> {data['content']}</div>",
131
- unsafe_allow_html=True
132
- )
133
 
134
- # πŸ› Tabs: AI Chat | Car Identifier
135
  tab1, tab2 = st.tabs(["AI Chat", "What car is that?"])
136
 
137
- # πŸ€– AI Chat Tab
138
  with tab1:
139
  input_col, clear_col = st.columns([9, 1])
140
  with input_col:
141
  user_input = st.chat_input("Type your message here...")
142
-
143
  with clear_col:
144
  if st.button("πŸ—‘οΈ", key="clear-chat", help="Clear Chat"):
145
  try:
@@ -151,14 +143,12 @@ with tab1:
151
  st.rerun()
152
  except Exception as e:
153
  st.error(f"Failed to clear chat: {e}")
154
-
155
  thread_id = get_or_create_thread_id()
156
  display_chat_history()
157
 
158
  if user_input:
159
  client.beta.threads.messages.create(thread_id=thread_id, role="user", content=user_input)
160
  save_message("user", user_input)
161
-
162
  with st.spinner("Thinking and typing... πŸ’­"):
163
  run = client.beta.threads.runs.create(thread_id=thread_id, assistant_id=assistant_id)
164
  while True:
@@ -166,7 +156,6 @@ with tab1:
166
  if run_status.status == "completed":
167
  break
168
  time.sleep(1)
169
-
170
  messages_response = client.beta.threads.messages.list(thread_id=thread_id)
171
  latest_response = sorted(messages_response.data, key=lambda x: x.created_at)[-1]
172
  assistant_message = latest_response.content[0].text.value
@@ -174,78 +163,50 @@ with tab1:
174
  time.sleep(0.5)
175
  st.rerun()
176
 
177
- # πŸš— "What car is that?" Tab
178
  with tab2:
179
  uploaded_image = st.file_uploader("Upload an image of a car and let Ai identify it for you", type=["jpg", "jpeg", "png"])
180
-
181
  if uploaded_image:
182
  col1, col2 = st.columns([1.2, 1.8])
183
-
184
  with col1:
185
  image = Image.open(uploaded_image)
186
  st.image(image, caption="Uploaded Image", use_container_width=True)
187
-
188
  with col2:
189
  try:
190
  image_thread = client.beta.threads.create()
191
  file_response = client.files.create(file=uploaded_image, purpose="assistants")
192
-
193
  client.beta.threads.messages.create(
194
  thread_id=image_thread.id,
195
  role="user",
196
  content=[
197
- {
198
- "type": "image_file",
199
- "image_file": {"file_id": file_response.id}
200
- },
201
- {
202
- "type": "text",
203
- "text": "Please identify this car from the image and include a full vehicle specification table, a short overview of the car, and who it's recommended for."
204
- }
205
  ]
206
  )
207
-
208
- run = client.beta.threads.runs.create(
209
- thread_id=image_thread.id,
210
- assistant_id=assistant_id
211
- )
212
-
213
  with st.spinner("πŸ” Analyzing image and identifying the car..."):
214
  while True:
215
- run_status = client.beta.threads.runs.retrieve(
216
- thread_id=image_thread.id,
217
- run_id=run.id
218
- )
219
  if run_status.status == "completed":
220
  break
221
  time.sleep(1)
222
-
223
  messages = client.beta.threads.messages.list(thread_id=image_thread.id)
224
  assistant_message = messages.data[0].content[0].text.value
225
-
226
  cleaned_message = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', assistant_message)
227
  cleaned_message = cleaned_message.replace("###", "<h4 style='margin-bottom: 10px;'>").replace("\n", "<br>")
228
-
229
- # Extract markdown table (if present)
230
  if '|' in cleaned_message:
231
  lines = cleaned_message.split('<br>')
232
- html_table = """<table class='spec-table'>"""
233
  for line in lines:
234
- if '|' in line:
235
  cells = line.strip('|').split('|')
236
  row_html = '<tr>' + ''.join(f'<td>{cell.strip()}</td>' for cell in cells) + '</tr>'
237
  html_table += row_html
238
- else:
239
  html_table += f"</table><p>{line}</p><table class='spec-table'>"
240
  html_table += "</table>"
241
  cleaned_message = html_table
242
-
243
  st.success("βœ… Identification Complete")
244
- st.markdown(f"""
245
- <div class='car-spec-output'>
246
- {cleaned_message}
247
- </div>
248
- """, unsafe_allow_html=True)
249
-
250
  except Exception as e:
251
  st.error(f"❌ Error during image analysis: {str(e)}")
 
47
  }
48
  .car-spec-output {
49
  font-family: "Segoe UI", sans-serif;
50
+ font-size: 10px;
51
  background-color: #ffffff;
52
  color: #003B6F;
53
+ padding: 18px;
54
  border-radius: 10px;
55
  box-shadow: 0 4px 12px rgba(0,0,0,0.05);
56
+ border-left: 4px solid #0071BC;
57
+ line-height: 1.5;
58
  }
59
  .spec-table {
60
  width: 100%;
61
  border-collapse: collapse;
62
+ margin-top: 12px;
63
+ margin-bottom: 16px;
64
+ font-size: 10px;
65
  }
66
  .spec-table th, .spec-table td {
67
  border: 1px solid #ddd;
68
+ padding: 6px 8px;
69
  text-align: left;
70
  }
71
  .spec-table th {
 
76
  background-color: #f7f9fc;
77
  }
78
  .icon {
79
+ width: 14px;
80
  vertical-align: middle;
81
+ margin-right: 5px;
82
  }
83
  </style>
84
  """, unsafe_allow_html=True)
 
86
  st.markdown("""
87
  <div style='text-align: center; margin-top: 20px; margin-bottom: -10px;'>
88
  <span style='display: inline-flex; align-items: center; gap: 8px;'>
89
+ <img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='28' class='carfind-logo'/>
90
+ <span style='font-size: 12px; color: gray;'>Powered by Carfind</span>
91
  </span>
92
  </div>
93
  """, unsafe_allow_html=True)
94
 
95
+ # Firebase Chat Functions
96
+
97
  def get_or_create_thread_id():
98
  doc_ref = db.collection("users").document(user_id)
99
  doc = doc_ref.get()
 
115
  })
116
 
117
  def display_chat_history():
118
+ messages = db.collection("users").document(user_id).collection("messages").order_by("timestamp").stream()
119
+ assistant_icon_html = "<img src='https://www.carfind.co.za/images/Carfind-Icon.svg' width='20' style='vertical-align:middle;'/>"
 
 
120
  for msg in list(messages)[::-1]:
121
  data = msg.to_dict()
122
  if data["role"] == "user":
123
+ st.markdown(f"<div class='stChatMessage' data-testid='stChatMessage-user'>πŸ‘€ <strong>You:</strong> {data['content']}</div>", unsafe_allow_html=True)
 
 
 
124
  else:
125
+ st.markdown(f"<div class='stChatMessage' data-testid='stChatMessage-assistant'>{assistant_icon_html} <strong>Carfind Assistant:</strong> {data['content']}</div>", unsafe_allow_html=True)
 
 
 
 
126
 
127
+ # Tabs: AI Chat | Car Identifier
128
  tab1, tab2 = st.tabs(["AI Chat", "What car is that?"])
129
 
130
+ # AI Chat Tab
131
  with tab1:
132
  input_col, clear_col = st.columns([9, 1])
133
  with input_col:
134
  user_input = st.chat_input("Type your message here...")
 
135
  with clear_col:
136
  if st.button("πŸ—‘οΈ", key="clear-chat", help="Clear Chat"):
137
  try:
 
143
  st.rerun()
144
  except Exception as e:
145
  st.error(f"Failed to clear chat: {e}")
 
146
  thread_id = get_or_create_thread_id()
147
  display_chat_history()
148
 
149
  if user_input:
150
  client.beta.threads.messages.create(thread_id=thread_id, role="user", content=user_input)
151
  save_message("user", user_input)
 
152
  with st.spinner("Thinking and typing... πŸ’­"):
153
  run = client.beta.threads.runs.create(thread_id=thread_id, assistant_id=assistant_id)
154
  while True:
 
156
  if run_status.status == "completed":
157
  break
158
  time.sleep(1)
 
159
  messages_response = client.beta.threads.messages.list(thread_id=thread_id)
160
  latest_response = sorted(messages_response.data, key=lambda x: x.created_at)[-1]
161
  assistant_message = latest_response.content[0].text.value
 
163
  time.sleep(0.5)
164
  st.rerun()
165
 
166
+ # Car Image Tab
167
  with tab2:
168
  uploaded_image = st.file_uploader("Upload an image of a car and let Ai identify it for you", type=["jpg", "jpeg", "png"])
 
169
  if uploaded_image:
170
  col1, col2 = st.columns([1.2, 1.8])
 
171
  with col1:
172
  image = Image.open(uploaded_image)
173
  st.image(image, caption="Uploaded Image", use_container_width=True)
 
174
  with col2:
175
  try:
176
  image_thread = client.beta.threads.create()
177
  file_response = client.files.create(file=uploaded_image, purpose="assistants")
 
178
  client.beta.threads.messages.create(
179
  thread_id=image_thread.id,
180
  role="user",
181
  content=[
182
+ {"type": "image_file", "image_file": {"file_id": file_response.id}},
183
+ {"type": "text", "text": "Please identify this car from the image and include a clean HTML-styled specification table without Year or Mileage fields, and avoid markdown or dotted lines."}
 
 
 
 
 
 
184
  ]
185
  )
186
+ run = client.beta.threads.runs.create(thread_id=image_thread.id, assistant_id=assistant_id)
 
 
 
 
 
187
  with st.spinner("πŸ” Analyzing image and identifying the car..."):
188
  while True:
189
+ run_status = client.beta.threads.runs.retrieve(thread_id=image_thread.id, run_id=run.id)
 
 
 
190
  if run_status.status == "completed":
191
  break
192
  time.sleep(1)
 
193
  messages = client.beta.threads.messages.list(thread_id=image_thread.id)
194
  assistant_message = messages.data[0].content[0].text.value
 
195
  cleaned_message = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', assistant_message)
196
  cleaned_message = cleaned_message.replace("###", "<h4 style='margin-bottom: 10px;'>").replace("\n", "<br>")
 
 
197
  if '|' in cleaned_message:
198
  lines = cleaned_message.split('<br>')
199
+ html_table = "<table class='spec-table'>"
200
  for line in lines:
201
+ if '|' in line and '---' not in line and 'Year' not in line and 'Mileage' not in line:
202
  cells = line.strip('|').split('|')
203
  row_html = '<tr>' + ''.join(f'<td>{cell.strip()}</td>' for cell in cells) + '</tr>'
204
  html_table += row_html
205
+ elif '|' not in line:
206
  html_table += f"</table><p>{line}</p><table class='spec-table'>"
207
  html_table += "</table>"
208
  cleaned_message = html_table
 
209
  st.success("βœ… Identification Complete")
210
+ st.markdown(f"<div class='car-spec-output'>{cleaned_message}</div>", unsafe_allow_html=True)
 
 
 
 
 
211
  except Exception as e:
212
  st.error(f"❌ Error during image analysis: {str(e)}")