abdo-Mansour commited on
Commit
f08d5a9
Β·
1 Parent(s): a1ad8cb
Files changed (2) hide show
  1. .gradio/certificate.pem +31 -0
  2. app.py +448 -11
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
3
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
4
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
5
+ WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
6
+ ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
7
+ MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
8
+ h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
9
+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
10
+ A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
11
+ T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
12
+ B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
13
+ B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
14
+ KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
15
+ OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
16
+ jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
17
+ qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
18
+ rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
19
+ HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
20
+ hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
21
+ ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
22
+ 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
23
+ NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
24
+ ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
25
+ TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
26
+ jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
27
+ oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
28
+ 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
29
+ mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
30
+ emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
31
+ -----END CERTIFICATE-----
app.py CHANGED
@@ -1,21 +1,458 @@
1
  import gradio as gr
2
- from gradio import ChatMessage
 
 
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- def interact_with_agent(prompt, messages):
7
- messages.append(ChatMessage(role="user", content=prompt))
8
- yield messages
 
 
 
 
 
 
 
 
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
 
 
 
 
11
 
12
- with gr.Blocks() as demo:
13
- chatbot = gr.Chatbot(label="Agent",
14
- msg_format="messages",
15
- avatar_images=(None, "https://em-content.zobj.net/source/twitter/53/robot-face_1f916.png"))
16
- text_input = gr.Textbox(lines=1, label="Chat Message")
17
- text_input.submit(interact_with_agent, [text_input, chatbot], [chatbot])
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
 
20
  if __name__ == "__main__":
21
- demo.launch()
 
 
 
 
 
 
1
  import gradio as gr
2
+ import json
3
+ import time
4
+ from typing import List, Dict, Tuple
5
 
6
+ # Sample product data for demonstration
7
+ SAMPLE_PRODUCTS = [
8
+ {
9
+ "productName": "Wireless Noise-Cancelling Headphones",
10
+ "productLink": "https://example.com/headphones",
11
+ "productPrice": "$199.99",
12
+ "productImageLink": "https://via.placeholder.com/300x200/667eea/ffffff?text=Headphones"
13
+ },
14
+ {
15
+ "productName": "Smart Fitness Watch",
16
+ "productLink": "https://example.com/smartwatch",
17
+ "productPrice": "$299.99",
18
+ "productImageLink": "https://via.placeholder.com/300x200/764ba2/ffffff?text=Smartwatch"
19
+ },
20
+ {
21
+ "productName": "Ergonomic Office Chair",
22
+ "productLink": "https://example.com/chair",
23
+ "productPrice": "$449.99",
24
+ "productImageLink": "https://via.placeholder.com/300x200/06b6d4/ffffff?text=Office+Chair"
25
+ }
26
+ ]
27
 
28
+ def format_product_card(product: Dict) -> str:
29
+ """Format a single product as HTML card"""
30
+ return f"""
31
+ <div class="product-card" style="
32
+ background: rgba(45, 55, 72, 0.8);
33
+ border-radius: 15px;
34
+ padding: 18px;
35
+ margin-bottom: 18px;
36
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
37
+ border: 1px solid rgba(102, 126, 234, 0.2);
38
+ transition: all 0.3s ease;
39
+ backdrop-filter: blur(10px);
40
+ ">
41
+ <img src="{product['productImageLink']}"
42
+ style="width: 100%; height: 130px; object-fit: cover; border-radius: 10px; margin-bottom: 15px;
43
+ border: 1px solid rgba(102, 126, 234, 0.1);"
44
+ alt="{product['productName']}">
45
+ <div style="font-weight: 600; color: #f7fafc; margin-bottom: 10px; font-size: 1rem; line-height: 1.4;">
46
+ {product['productName']}
47
+ </div>
48
+ <div style="font-size: 1.2rem; font-weight: 700; color: #4ade80; margin-bottom: 12px; text-shadow: 0 0 10px rgba(74, 222, 128, 0.3);">
49
+ {product['productPrice']}
50
+ </div>
51
+ <a href="{product['productLink']}" target="_blank"
52
+ style="color: white; text-decoration: none; font-size: 0.9rem; font-weight: 500;
53
+ padding: 8px 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
54
+ border-radius: 20px; display: inline-block; transition: all 0.3s ease;
55
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); border: 1px solid rgba(102, 126, 234, 0.3);">
56
+ View Product β†’
57
+ </a>
58
+ </div>
59
+ """
60
 
61
+ def format_products_html(products: List[Dict]) -> str:
62
+ """Format all products as HTML"""
63
+ if not products:
64
+ return """
65
+ <div style="display: flex; flex-direction: column; align-items: center;
66
+ justify-content: center; height: 300px; color: #cbd5e0; text-align: center;">
67
+ <div style="font-size: 4rem; margin-bottom: 20px; filter: drop-shadow(0 0 10px rgba(102, 126, 234, 0.3));">πŸ›οΈ</div>
68
+ <h4 style="margin-bottom: 10px; color: #f7fafc; font-weight: 600;">No products yet</h4>
69
+ <p style="color: #cbd5e0; opacity: 0.8;">Start chatting to get personalized recommendations!</p>
70
+ </div>
71
+ """
72
 
73
+ products_html = ""
74
+ for product in products:
75
+ products_html += format_product_card(product)
76
+
77
+ return f"""
78
+ <div style="max-height: 600px; overflow-y: auto; padding-right: 10px;">
79
+ {products_html}
80
+ </div>
81
+ """
82
+
83
+ def simulate_ai_agent(message: str, history: List[Tuple[str, str]]) -> Tuple[str, str]:
84
+ """
85
+ Simulate your AI agent response
86
+ Replace this with your actual LlamaIndex agent logic
87
+
88
+ Returns: (response_text, products_html)
89
+ """
90
+ # Simulate processing time
91
+ time.sleep(2)
92
+
93
+ # Sample responses based on keywords
94
+ if "laptop" in message.lower() or "computer" in message.lower():
95
+ response = "Great! I found some excellent laptops for programming and gaming within your budget. These models offer fantastic performance and great value."
96
+ products = [
97
+ {
98
+ "productName": "ASUS TUF Gaming Laptop - RTX 3060",
99
+ "productLink": "https://example.com/asus-gaming",
100
+ "productPrice": "$899.99",
101
+ "productImageLink": "https://via.placeholder.com/300x200/667eea/ffffff?text=ASUS+TUF"
102
+ },
103
+ {
104
+ "productName": "Acer Nitro 5 Gaming Laptop",
105
+ "productLink": "https://example.com/acer-nitro5",
106
+ "productPrice": "$799.99",
107
+ "productImageLink": "https://via.placeholder.com/300x200/764ba2/ffffff?text=Acer+Nitro"
108
+ },
109
+ {
110
+ "productName": "HP Pavilion Gaming 15",
111
+ "productLink": "https://example.com/hp-pavilion",
112
+ "productPrice": "$749.99",
113
+ "productImageLink": "https://via.placeholder.com/300x200/06b6d4/ffffff?text=HP+Pavilion"
114
+ }
115
+ ]
116
+ elif "headphone" in message.lower() or "audio" in message.lower():
117
+ response = "Perfect! I've found some top-rated headphones with excellent sound quality and noise cancellation."
118
+ products = [
119
+ {
120
+ "productName": "Sony WH-1000XM4 Wireless Headphones",
121
+ "productLink": "https://example.com/sony-wh1000xm4",
122
+ "productPrice": "$279.99",
123
+ "productImageLink": "https://via.placeholder.com/300x200/667eea/ffffff?text=Sony+WH1000XM4"
124
+ },
125
+ {
126
+ "productName": "Bose QuietComfort 45",
127
+ "productLink": "https://example.com/bose-qc45",
128
+ "productPrice": "$329.99",
129
+ "productImageLink": "https://via.placeholder.com/300x200/764ba2/ffffff?text=Bose+QC45"
130
+ }
131
+ ]
132
+ else:
133
+ response = "I understand you're looking for something specific! Let me find the best options for you based on your requirements."
134
+ products = SAMPLE_PRODUCTS
135
+
136
+ products_html = format_products_html(products)
137
+
138
+ return response, products_html
139
+
140
+ def chat_interface(message: str, history: List[Tuple[str, str]], products_state: str) -> Tuple[List[Tuple[str, str]], str, str]:
141
+ """Handle chat interaction and update products"""
142
+ if not message.strip():
143
+ return history, products_state, ""
144
+
145
+ # Get AI response and products
146
+ ai_response, new_products_html = simulate_ai_agent(message, history)
147
+
148
+ # Update chat history
149
+ history.append((message, ai_response))
150
+
151
+ return history, new_products_html, ""
152
+
153
+ # Custom CSS for dark mode gradient styling
154
+ custom_css = """
155
+ /* Dark mode variables */
156
+ :root {
157
+ --bg-primary: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
158
+ --bg-secondary: linear-gradient(135deg, #2d3748 0%, #1a202c 100%);
159
+ --bg-card: rgba(45, 55, 72, 0.8);
160
+ --bg-chat: rgba(26, 32, 44, 0.9);
161
+ --text-primary: #f7fafc;
162
+ --text-secondary: #cbd5e0;
163
+ --accent-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
164
+ --accent-glow: rgba(102, 126, 234, 0.3);
165
+ --border-color: rgba(102, 126, 234, 0.2);
166
+ --shadow-dark: 0 10px 30px rgba(0, 0, 0, 0.4);
167
+ }
168
+
169
+ /* Main container styling */
170
+ .gradio-container {
171
+ background: var(--bg-primary) !important;
172
+ min-height: 100vh;
173
+ color: var(--text-primary) !important;
174
+ }
175
+
176
+ /* Override Gradio's default backgrounds */
177
+ .gradio-container .block {
178
+ background: transparent !important;
179
+ border: none !important;
180
+ }
181
+
182
+ /* Header styling */
183
+ .header-text {
184
+ background: var(--accent-primary);
185
+ color: white !important;
186
+ padding: 25px;
187
+ border-radius: 20px;
188
+ text-align: center;
189
+ margin-bottom: 25px;
190
+ box-shadow: var(--shadow-dark);
191
+ border: 1px solid var(--border-color);
192
+ backdrop-filter: blur(10px);
193
+ }
194
+
195
+ /* Products panel styling */
196
+ .products-panel {
197
+ background: var(--bg-card) !important;
198
+ border-radius: 20px !important;
199
+ padding: 25px !important;
200
+ box-shadow: var(--shadow-dark) !important;
201
+ border: 1px solid var(--border-color) !important;
202
+ backdrop-filter: blur(10px) !important;
203
+ }
204
+
205
+ /* Chat panel styling */
206
+ .chat-panel {
207
+ background: var(--bg-chat) !important;
208
+ border-radius: 20px !important;
209
+ box-shadow: var(--shadow-dark) !important;
210
+ border: 1px solid var(--border-color) !important;
211
+ backdrop-filter: blur(10px) !important;
212
+ padding: 25px !important;
213
+ }
214
+
215
+ /* Chatbot container */
216
+ .chatbot {
217
+ background: rgba(26, 32, 44, 0.6) !important;
218
+ border-radius: 15px !important;
219
+ border: 1px solid var(--border-color) !important;
220
+ box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.3) !important;
221
+ backdrop-filter: blur(5px) !important;
222
+ }
223
+
224
+ /* Chat messages styling */
225
+ .chatbot .message {
226
+ background: transparent !important;
227
+ }
228
+
229
+ /* User messages */
230
+ .chatbot .message.user {
231
+ background: var(--accent-primary) !important;
232
+ color: white !important;
233
+ border-radius: 18px 18px 5px 18px !important;
234
+ padding: 12px 18px !important;
235
+ margin: 8px 0 !important;
236
+ box-shadow: 0 4px 15px var(--accent-glow) !important;
237
+ border: 1px solid rgba(102, 126, 234, 0.3) !important;
238
+ }
239
+
240
+ /* Bot messages */
241
+ .chatbot .message.bot {
242
+ background: rgba(45, 55, 72, 0.8) !important;
243
+ color: var(--text-primary) !important;
244
+ border-radius: 18px 18px 18px 5px !important;
245
+ padding: 12px 18px !important;
246
+ margin: 8px 0 !important;
247
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2) !important;
248
+ border: 1px solid var(--border-color) !important;
249
+ backdrop-filter: blur(5px) !important;
250
+ }
251
+
252
+ /* Input styling */
253
+ .chatbot-input textarea {
254
+ background: rgba(26, 32, 44, 0.8) !important;
255
+ border: 2px solid var(--border-color) !important;
256
+ border-radius: 25px !important;
257
+ padding: 15px 20px !important;
258
+ font-size: 16px !important;
259
+ color: var(--text-primary) !important;
260
+ backdrop-filter: blur(5px) !important;
261
+ box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.2) !important;
262
+ }
263
 
264
+ .chatbot-input textarea::placeholder {
265
+ color: var(--text-secondary) !important;
266
+ opacity: 0.7;
267
+ }
268
 
269
+ .chatbot-input textarea:focus {
270
+ border-color: #667eea !important;
271
+ box-shadow: 0 0 0 3px var(--accent-glow) !important;
272
+ background: rgba(26, 32, 44, 0.9) !important;
273
+ }
 
274
 
275
+ /* Button styling */
276
+ .chatbot-submit {
277
+ background: var(--accent-primary) !important;
278
+ border: none !important;
279
+ border-radius: 25px !important;
280
+ padding: 15px 25px !important;
281
+ color: white !important;
282
+ font-weight: 600 !important;
283
+ box-shadow: 0 4px 15px var(--accent-glow) !important;
284
+ border: 1px solid rgba(102, 126, 234, 0.3) !important;
285
+ transition: all 0.3s ease !important;
286
+ }
287
+
288
+ .chatbot-submit:hover {
289
+ transform: translateY(-2px) !important;
290
+ box-shadow: 0 6px 20px var(--accent-glow) !important;
291
+ filter: brightness(1.1) !important;
292
+ }
293
+
294
+ /* Scrollbar styling */
295
+ ::-webkit-scrollbar {
296
+ width: 10px;
297
+ }
298
+
299
+ ::-webkit-scrollbar-track {
300
+ background: rgba(26, 32, 44, 0.3);
301
+ border-radius: 5px;
302
+ }
303
+
304
+ ::-webkit-scrollbar-thumb {
305
+ background: var(--accent-primary);
306
+ border-radius: 5px;
307
+ border: 2px solid rgba(26, 32, 44, 0.3);
308
+ }
309
+
310
+ ::-webkit-scrollbar-thumb:hover {
311
+ background: linear-gradient(135deg, #7c3aed 0%, #8b5cf6 100%);
312
+ }
313
+
314
+ /* Product cards hover effect */
315
+ .product-card:hover {
316
+ transform: translateY(-3px) !important;
317
+ box-shadow: 0 12px 30px rgba(102, 126, 234, 0.2) !important;
318
+ }
319
+
320
+ /* Text color overrides */
321
+ .products-panel h3,
322
+ .products-panel p,
323
+ .chat-panel h3 {
324
+ color: var(--text-primary) !important;
325
+ }
326
+
327
+ /* Gradio component overrides */
328
+ .gr-form {
329
+ background: transparent !important;
330
+ }
331
+
332
+ .gr-box {
333
+ background: transparent !important;
334
+ border: none !important;
335
+ }
336
+
337
+ /* Fix input group styling */
338
+ .gr-group {
339
+ background: transparent !important;
340
+ }
341
+
342
+ /* Textarea wrapper */
343
+ .gr-textbox {
344
+ background: transparent !important;
345
+ }
346
+
347
+ /* Button wrapper */
348
+ .gr-button {
349
+ background: transparent !important;
350
+ }
351
+
352
+ /* Chat interface specific fixes */
353
+ .chatbot-container {
354
+ background: transparent !important;
355
+ }
356
+
357
+ /* Message bubble improvements */
358
+ .chatbot .message-row {
359
+ margin: 10px 0 !important;
360
+ }
361
+
362
+ /* Better spacing for chat */
363
+ .chatbot .chat-container {
364
+ padding: 15px !important;
365
+ }
366
+ """
367
+
368
+ # Create the Gradio interface
369
+ with gr.Blocks(css=custom_css, title="Buyverse - AI Shopping Agent", theme=gr.themes.Soft()) as demo:
370
+
371
+ # Header
372
+ gr.HTML("""
373
+ <div class="header-text">
374
+ <h1 style="font-size: 2.8rem; margin-bottom: 12px; font-weight: 700; text-shadow: 0 0 20px rgba(255,255,255,0.3);">πŸ›οΈ Buyverse</h1>
375
+ <p style="font-size: 1.3rem; opacity: 0.95; text-shadow: 0 0 10px rgba(255,255,255,0.2);">Your AI-Powered Shopping Assistant</p>
376
+ </div>
377
+ """)
378
+
379
+ # Main layout with two columns
380
+ with gr.Row():
381
+ # Left column - Products (30% width)
382
+ with gr.Column(scale=3, elem_classes=["products-panel"]):
383
+ gr.HTML("""
384
+ <div style="margin-bottom: 20px;">
385
+ <h3 style="color: #f7fafc; font-size: 1.4rem; font-weight: 600; margin-bottom: 10px; display: flex; align-items: center;
386
+ text-shadow: 0 0 10px rgba(102, 126, 234, 0.3);">
387
+ πŸ›’ Recommended Products
388
+ </h3>
389
+ <p style="color: #cbd5e0; font-size: 1rem; opacity: 0.9;">AI-curated items based on your needs</p>
390
+ </div>
391
+ """)
392
+
393
+ # Products display area
394
+ products_display = gr.HTML(
395
+ format_products_html([]),
396
+ elem_id="products-container"
397
+ )
398
+
399
+ # Right column - Chat (70% width)
400
+ with gr.Column(scale=7, elem_classes=["chat-panel"]):
401
+ gr.HTML("""
402
+ <div style="padding: 25px 0; border-bottom: 1px solid rgba(102, 126, 234, 0.2); margin-bottom: 25px;">
403
+ <h3 style="color: #f7fafc; font-size: 1.4rem; font-weight: 600; display: flex; align-items: center;
404
+ text-shadow: 0 0 10px rgba(102, 126, 234, 0.3);">
405
+ πŸ’¬ Chat with AI Assistant
406
+ </h3>
407
+ </div>
408
+ """)
409
+
410
+ # Chat interface
411
+ chatbot = gr.Chatbot(
412
+ value=[("", "πŸ‘‹ Hello! I'm your personal shopping assistant. Tell me what you're looking for and I'll help you find the perfect products. Whether it's electronics, clothing, home goods, or anything else - just describe your needs and budget!")],
413
+ height=500,
414
+ show_label=False,
415
+ elem_classes=["chatbot"],
416
+ bubble_full_width=False,
417
+ render_markdown=True
418
+ )
419
+
420
+ # Input area
421
+ with gr.Row():
422
+ msg = gr.Textbox(
423
+ placeholder="Tell me what you're shopping for...",
424
+ show_label=False,
425
+ scale=4,
426
+ lines=1,
427
+ elem_classes=["chatbot-input"]
428
+ )
429
+ submit = gr.Button(
430
+ "Send πŸš€",
431
+ scale=1,
432
+ elem_classes=["chatbot-submit"]
433
+ )
434
+
435
+ # State to store products
436
+ products_state = gr.State(format_products_html([]))
437
+
438
+ # Handle chat interactions
439
+ msg.submit(
440
+ fn=chat_interface,
441
+ inputs=[msg, chatbot, products_state],
442
+ outputs=[chatbot, products_display, msg]
443
+ )
444
+
445
+ submit.click(
446
+ fn=chat_interface,
447
+ inputs=[msg, chatbot, products_state],
448
+ outputs=[chatbot, products_display, msg]
449
+ )
450
 
451
+ # Launch the app
452
  if __name__ == "__main__":
453
+ demo.launch(
454
+ share=True,
455
+ server_name="0.0.0.0",
456
+ server_port=7860,
457
+ show_error=True
458
+ )