tsrivallabh commited on
Commit
c0506a3
Β·
verified Β·
1 Parent(s): f81743c

Synced repo using 'sync_with_huggingface' Github Action

Browse files
This view is limited to 50 files because it contains too many changes. Β  See raw diff
Files changed (50) hide show
  1. .gitattributes +13 -0
  2. Business Strategy Presentation/app.js +534 -0
  3. Business Strategy Presentation/index.html +638 -0
  4. Business Strategy Presentation/readme.txt.txt +1 -0
  5. Business Strategy Presentation/style.css +1575 -0
  6. __pycache__/agent.cpython-312.pyc +0 -0
  7. __pycache__/sticky.cpython-312.pyc +0 -0
  8. __pycache__/sticky.cpython-313.pyc +0 -0
  9. __pycache__/tools.cpython-312.pyc +0 -0
  10. __pycache__/tools.cpython-313.pyc +0 -0
  11. __pycache__/ui_utils.cpython-312.pyc +0 -0
  12. __pycache__/var.cpython-313.pyc +0 -0
  13. app.py +500 -0
  14. assets/all_resto.png +3 -0
  15. assets/booking_successful.png +3 -0
  16. assets/general_conv_info_through_chat.png +3 -0
  17. assets/greet_general_convo.png +3 -0
  18. assets/landing.png +3 -0
  19. assets/mermaid-1.png +3 -0
  20. assets/mermaid.png +3 -0
  21. assets/name_entering.png +3 -0
  22. assets/ready_to_book.png +3 -0
  23. assets/rubbish.PNG +3 -0
  24. assets/some_results.PNG +3 -0
  25. db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/data_level0.bin +3 -0
  26. db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/header.bin +3 -0
  27. db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/length.bin +3 -0
  28. db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/link_lists.bin +0 -0
  29. db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/data_level0.bin +3 -0
  30. db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/header.bin +3 -0
  31. db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/length.bin +3 -0
  32. db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/link_lists.bin +0 -0
  33. db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/data_level0.bin +3 -0
  34. db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/header.bin +3 -0
  35. db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/index_metadata.pickle +3 -0
  36. db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/length.bin +3 -0
  37. db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/link_lists.bin +3 -0
  38. db/chroma/chroma.sqlite3 +3 -0
  39. db/create_base.py +64 -0
  40. db/create_slots.py +33 -0
  41. db/dbmodify.py +54 -0
  42. db/fill_details.py +141 -0
  43. db/print_db.py +24 -0
  44. db/resetdb.py +27 -0
  45. db/restaurant_reservation.db +3 -0
  46. efficiency_log.txt +141 -0
  47. prompts/determine_intent.txt +21 -0
  48. prompts/generate_reservation_conversation.txt +30 -0
  49. prompts/interpret_sql_result.txt +28 -0
  50. prompts/schema_prompt.txt +50 -0
.gitattributes CHANGED
@@ -33,3 +33,16 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/all_resto.png filter=lfs diff=lfs merge=lfs -text
37
+ assets/general_conv_info_through_chat.png filter=lfs diff=lfs merge=lfs -text
38
+ assets/some_results.PNG filter=lfs diff=lfs merge=lfs -text
39
+ assets/greet_general_convo.png filter=lfs diff=lfs merge=lfs -text
40
+ assets/name_entering.png filter=lfs diff=lfs merge=lfs -text
41
+ assets/rubbish.PNG filter=lfs diff=lfs merge=lfs -text
42
+ assets/landing.png filter=lfs diff=lfs merge=lfs -text
43
+ assets/mermaid.png filter=lfs diff=lfs merge=lfs -text
44
+ assets/ready_to_book.png filter=lfs diff=lfs merge=lfs -text
45
+ assets/mermaid-1.png filter=lfs diff=lfs merge=lfs -text
46
+ assets/booking_successful.png filter=lfs diff=lfs merge=lfs -text
47
+ db/restaurant_reservation.db filter=lfs diff=lfs merge=lfs -text
48
+ db/chroma/chroma.sqlite3 filter=lfs diff=lfs merge=lfs -text
Business Strategy Presentation/app.js ADDED
@@ -0,0 +1,534 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Presentation JavaScript functionality
2
+
3
+ class Presentation {
4
+ constructor() {
5
+ this.currentSlide = 0;
6
+ this.totalSlides = 15;
7
+ this.slides = [];
8
+ this.isFullscreen = false;
9
+
10
+ this.init();
11
+ }
12
+
13
+ init() {
14
+ // Wait for DOM to be fully loaded
15
+ if (document.readyState === 'loading') {
16
+ document.addEventListener('DOMContentLoaded', () => this.setupPresentation());
17
+ } else {
18
+ this.setupPresentation();
19
+ }
20
+ }
21
+
22
+ setupPresentation() {
23
+ this.slides = document.querySelectorAll('.slide');
24
+ console.log('Found slides:', this.slides.length);
25
+
26
+ if (this.slides.length === 0) {
27
+ console.error('No slides found!');
28
+ return;
29
+ }
30
+
31
+ this.totalSlides = this.slides.length;
32
+ this.bindEvents();
33
+ this.showSlide(0);
34
+ this.updateProgress();
35
+ this.updateCounter();
36
+ this.updateNavigationButtons();
37
+ }
38
+
39
+ bindEvents() {
40
+ // Button controls
41
+ const prevBtn = document.getElementById('prev-slide');
42
+ const nextBtn = document.getElementById('next-slide');
43
+ const fullscreenBtn = document.getElementById('fullscreen-toggle');
44
+
45
+ if (prevBtn) prevBtn.addEventListener('click', () => this.previousSlide());
46
+ if (nextBtn) nextBtn.addEventListener('click', () => this.nextSlide());
47
+ if (fullscreenBtn) fullscreenBtn.addEventListener('click', () => this.toggleFullscreen());
48
+
49
+ // Keyboard controls
50
+ document.addEventListener('keydown', (e) => this.handleKeydown(e));
51
+
52
+ // Fullscreen change events
53
+ document.addEventListener('fullscreenchange', () => this.handleFullscreenChange());
54
+ document.addEventListener('webkitfullscreenchange', () => this.handleFullscreenChange());
55
+ document.addEventListener('mozfullscreenchange', () => this.handleFullscreenChange());
56
+ document.addEventListener('msfullscreenchange', () => this.handleFullscreenChange());
57
+
58
+ // Touch/swipe events for mobile
59
+ this.addTouchEvents();
60
+
61
+ console.log('Event listeners bound successfully');
62
+ }
63
+
64
+ handleKeydown(e) {
65
+ switch(e.key) {
66
+ case 'ArrowRight':
67
+ case ' ':
68
+ case 'Enter':
69
+ e.preventDefault();
70
+ this.nextSlide();
71
+ break;
72
+ case 'ArrowLeft':
73
+ e.preventDefault();
74
+ this.previousSlide();
75
+ break;
76
+ case 'Home':
77
+ e.preventDefault();
78
+ this.goToSlide(0);
79
+ break;
80
+ case 'End':
81
+ e.preventDefault();
82
+ this.goToSlide(this.totalSlides - 1);
83
+ break;
84
+ case 'f':
85
+ case 'F':
86
+ if (!e.ctrlKey && !e.metaKey) {
87
+ e.preventDefault();
88
+ this.toggleFullscreen();
89
+ }
90
+ break;
91
+ case 'Escape':
92
+ if (this.isFullscreen) {
93
+ this.exitFullscreen();
94
+ }
95
+ break;
96
+ }
97
+ }
98
+
99
+ addTouchEvents() {
100
+ let startX = 0;
101
+ let startY = 0;
102
+ const container = document.querySelector('.presentation-container');
103
+
104
+ if (!container) return;
105
+
106
+ container.addEventListener('touchstart', (e) => {
107
+ startX = e.touches[0].clientX;
108
+ startY = e.touches[0].clientY;
109
+ }, { passive: true });
110
+
111
+ container.addEventListener('touchend', (e) => {
112
+ if (!startX || !startY) return;
113
+
114
+ const endX = e.changedTouches[0].clientX;
115
+ const endY = e.changedTouches[0].clientY;
116
+
117
+ const deltaX = startX - endX;
118
+ const deltaY = startY - endY;
119
+
120
+ // Only trigger if horizontal swipe is dominant and significant
121
+ if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 50) {
122
+ if (deltaX > 0) {
123
+ this.nextSlide();
124
+ } else {
125
+ this.previousSlide();
126
+ }
127
+ }
128
+
129
+ startX = 0;
130
+ startY = 0;
131
+ }, { passive: true });
132
+ }
133
+
134
+ nextSlide() {
135
+ if (this.currentSlide < this.totalSlides - 1) {
136
+ this.goToSlide(this.currentSlide + 1);
137
+ }
138
+ }
139
+
140
+ previousSlide() {
141
+ if (this.currentSlide > 0) {
142
+ this.goToSlide(this.currentSlide - 1);
143
+ }
144
+ }
145
+
146
+ goToSlide(slideIndex) {
147
+ if (slideIndex >= 0 && slideIndex < this.totalSlides) {
148
+ console.log(`Going to slide ${slideIndex + 1}`);
149
+
150
+ // Hide current slide
151
+ this.hideAllSlides();
152
+
153
+ // Update current slide index
154
+ this.currentSlide = slideIndex;
155
+
156
+ // Show new slide
157
+ this.showSlide(slideIndex);
158
+
159
+ // Update UI elements
160
+ this.updateProgress();
161
+ this.updateCounter();
162
+ this.updateNavigationButtons();
163
+
164
+ // Handle slide-specific logic
165
+ this.handleSlideSpecifics(slideIndex);
166
+ }
167
+ }
168
+
169
+ hideAllSlides() {
170
+ this.slides.forEach(slide => {
171
+ slide.classList.remove('active', 'animate-in');
172
+ });
173
+ }
174
+
175
+ showSlide(index) {
176
+ const slide = this.slides[index];
177
+ if (slide) {
178
+ // Remove active class from all slides first
179
+ this.hideAllSlides();
180
+
181
+ // Add active class to current slide
182
+ slide.classList.add('active');
183
+
184
+ // Add animation after a brief delay
185
+ setTimeout(() => {
186
+ slide.classList.add('animate-in');
187
+ this.animateSlideContent(slide);
188
+ }, 50);
189
+ }
190
+ }
191
+
192
+ animateSlideContent(slide) {
193
+ const elements = slide.querySelectorAll('.bullet-points li, .value-prop, .flow-step, .metric-category, .tech-component, .framework-item, .phase-card, .roi-metric, .challenge-category, .advantage, .timeline-item');
194
+
195
+ elements.forEach((element, index) => {
196
+ element.style.opacity = '0';
197
+ element.style.transform = 'translateY(20px)';
198
+ element.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
199
+
200
+ setTimeout(() => {
201
+ element.style.opacity = '1';
202
+ element.style.transform = 'translateY(0)';
203
+ }, 100 + (index * 100));
204
+ });
205
+ }
206
+
207
+ updateProgress() {
208
+ const progressBar = document.querySelector('.progress-indicator');
209
+ if (progressBar) {
210
+ const progress = ((this.currentSlide + 1) / this.totalSlides) * 100;
211
+ progressBar.style.width = `${progress}%`;
212
+ }
213
+ }
214
+
215
+ updateCounter() {
216
+ const currentSlideEl = document.getElementById('current-slide');
217
+ const totalSlidesEl = document.getElementById('total-slides');
218
+
219
+ if (currentSlideEl) currentSlideEl.textContent = this.currentSlide + 1;
220
+ if (totalSlidesEl) totalSlidesEl.textContent = this.totalSlides;
221
+ }
222
+
223
+ updateNavigationButtons() {
224
+ const prevBtn = document.getElementById('prev-slide');
225
+ const nextBtn = document.getElementById('next-slide');
226
+
227
+ if (prevBtn) {
228
+ prevBtn.disabled = this.currentSlide === 0;
229
+ }
230
+
231
+ if (nextBtn) {
232
+ nextBtn.disabled = this.currentSlide === this.totalSlides - 1;
233
+
234
+ // Update button text for last slide
235
+ if (this.currentSlide === this.totalSlides - 1) {
236
+ nextBtn.innerHTML = `
237
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
238
+ <path d="M5 12h14M12 5l7 7-7 7"/>
239
+ </svg>
240
+ `;
241
+ nextBtn.setAttribute('aria-label', 'Finish presentation');
242
+ } else {
243
+ nextBtn.innerHTML = `
244
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
245
+ <path d="M9 18l6-6-6-6"/>
246
+ </svg>
247
+ `;
248
+ nextBtn.setAttribute('aria-label', 'Next slide');
249
+ }
250
+ }
251
+ }
252
+
253
+ toggleFullscreen() {
254
+ if (!this.isFullscreen) {
255
+ this.enterFullscreen();
256
+ } else {
257
+ this.exitFullscreen();
258
+ }
259
+ }
260
+
261
+ enterFullscreen() {
262
+ const container = document.querySelector('.presentation-container');
263
+
264
+ if (container.requestFullscreen) {
265
+ container.requestFullscreen();
266
+ } else if (container.webkitRequestFullscreen) {
267
+ container.webkitRequestFullscreen();
268
+ } else if (container.mozRequestFullScreen) {
269
+ container.mozRequestFullScreen();
270
+ } else if (container.msRequestFullscreen) {
271
+ container.msRequestFullscreen();
272
+ }
273
+ }
274
+
275
+ exitFullscreen() {
276
+ if (document.exitFullscreen) {
277
+ document.exitFullscreen();
278
+ } else if (document.webkitExitFullscreen) {
279
+ document.webkitExitFullscreen();
280
+ } else if (document.mozCancelFullScreen) {
281
+ document.mozCancelFullScreen();
282
+ } else if (document.msExitFullscreen) {
283
+ document.msExitFullscreen();
284
+ }
285
+ }
286
+
287
+ handleFullscreenChange() {
288
+ const isFullscreen = !!(document.fullscreenElement ||
289
+ document.webkitFullscreenElement ||
290
+ document.mozFullScreenElement ||
291
+ document.msFullscreenElement);
292
+
293
+ this.isFullscreen = isFullscreen;
294
+ this.updateFullscreenIcon();
295
+
296
+ const container = document.querySelector('.presentation-container');
297
+ if (container) {
298
+ if (isFullscreen) {
299
+ container.classList.add('fullscreen');
300
+ } else {
301
+ container.classList.remove('fullscreen');
302
+ }
303
+ }
304
+ }
305
+
306
+ updateFullscreenIcon() {
307
+ const icon = document.getElementById('fullscreen-icon');
308
+
309
+ if (icon) {
310
+ if (this.isFullscreen) {
311
+ icon.innerHTML = `
312
+ <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
313
+ `;
314
+ } else {
315
+ icon.innerHTML = `
316
+ <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
317
+ `;
318
+ }
319
+ }
320
+ }
321
+
322
+ // Method to handle special slide interactions
323
+ initSlideInteractions() {
324
+ // Add click handlers for call-to-action buttons
325
+ const ctaButtons = document.querySelectorAll('.call-to-action .btn');
326
+ ctaButtons.forEach(button => {
327
+ button.addEventListener('click', (e) => {
328
+ e.preventDefault();
329
+ this.handleCTAClick(button.textContent.trim());
330
+ });
331
+ });
332
+
333
+ // Add hover effects for interactive elements
334
+ this.addHoverEffects();
335
+ }
336
+
337
+ handleCTAClick(buttonText) {
338
+ if (buttonText.includes('Schedule')) {
339
+ this.showNotification('Meeting request sent! Check your calendar for confirmation.');
340
+ } else if (buttonText.includes('Download')) {
341
+ this.showNotification('Strategy document download initiated.');
342
+ }
343
+ }
344
+
345
+ showNotification(message) {
346
+ // Create notification element
347
+ const notification = document.createElement('div');
348
+ notification.className = 'notification';
349
+ notification.style.cssText = `
350
+ position: fixed;
351
+ top: 20px;
352
+ right: 20px;
353
+ background-color: var(--color-success);
354
+ color: var(--color-btn-primary-text);
355
+ padding: 16px 24px;
356
+ border-radius: 8px;
357
+ font-size: 14px;
358
+ font-weight: 500;
359
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
360
+ z-index: 1001;
361
+ opacity: 0;
362
+ transform: translateX(100%);
363
+ transition: all 0.3s ease;
364
+ `;
365
+ notification.textContent = message;
366
+
367
+ document.body.appendChild(notification);
368
+
369
+ // Animate in
370
+ setTimeout(() => {
371
+ notification.style.opacity = '1';
372
+ notification.style.transform = 'translateX(0)';
373
+ }, 100);
374
+
375
+ // Remove after 3 seconds
376
+ setTimeout(() => {
377
+ notification.style.opacity = '0';
378
+ notification.style.transform = 'translateX(100%)';
379
+ setTimeout(() => {
380
+ if (notification.parentNode) {
381
+ notification.parentNode.removeChild(notification);
382
+ }
383
+ }, 300);
384
+ }, 3000);
385
+ }
386
+
387
+ addHoverEffects() {
388
+ // Add hover effects to interactive elements
389
+ const interactiveElements = document.querySelectorAll('.value-prop, .tech-component, .framework-item, .advantage, .phase-card');
390
+
391
+ interactiveElements.forEach(element => {
392
+ element.addEventListener('mouseenter', () => {
393
+ element.style.transform = 'translateY(-5px)';
394
+ element.style.transition = 'transform 0.3s ease, box-shadow 0.3s ease';
395
+ element.style.boxShadow = 'var(--shadow-lg)';
396
+ });
397
+
398
+ element.addEventListener('mouseleave', () => {
399
+ element.style.transform = 'translateY(0)';
400
+ element.style.boxShadow = '';
401
+ });
402
+ });
403
+ }
404
+
405
+ // Method to handle slide-specific logic
406
+ handleSlideSpecifics(slideIndex) {
407
+ switch(slideIndex) {
408
+ case 0: // Title slide
409
+ setTimeout(() => this.animateTitleSlide(), 500);
410
+ break;
411
+ case 5: // Customer journey flow
412
+ setTimeout(() => this.animateFlowDiagram(), 500);
413
+ break;
414
+ case 11: // Business impact
415
+ setTimeout(() => this.animateROIMetrics(), 500);
416
+ break;
417
+ case 14: // Conclusion
418
+ setTimeout(() => this.initSlideInteractions(), 500);
419
+ break;
420
+ }
421
+ }
422
+
423
+ animateTitleSlide() {
424
+ const highlights = document.querySelectorAll('.highlight');
425
+ highlights.forEach((highlight, index) => {
426
+ highlight.style.opacity = '0';
427
+ highlight.style.transform = 'scale(0.8)';
428
+ highlight.style.transition = 'all 0.5s ease';
429
+
430
+ setTimeout(() => {
431
+ highlight.style.opacity = '1';
432
+ highlight.style.transform = 'scale(1)';
433
+ }, index * 200);
434
+ });
435
+ }
436
+
437
+ animateFlowDiagram() {
438
+ const steps = document.querySelectorAll('.flow-step');
439
+ steps.forEach((step, index) => {
440
+ step.style.opacity = '0';
441
+ step.style.transform = 'translateX(-50px)';
442
+ step.style.transition = 'all 0.5s ease';
443
+
444
+ setTimeout(() => {
445
+ step.style.opacity = '1';
446
+ step.style.transform = 'translateX(0)';
447
+ }, index * 300);
448
+ });
449
+ }
450
+
451
+ animateROIMetrics() {
452
+ const metrics = document.querySelectorAll('.roi-metric h3');
453
+ metrics.forEach((metric, index) => {
454
+ const finalValue = metric.textContent;
455
+ const isPercentage = finalValue.includes('%');
456
+ const numericValue = parseInt(finalValue.replace(/[^\d]/g, ''));
457
+
458
+ if (numericValue > 0) {
459
+ metric.textContent = isPercentage ? '0%' : '0';
460
+
461
+ setTimeout(() => {
462
+ this.animateNumber(metric, finalValue, numericValue, isPercentage);
463
+ }, index * 200);
464
+ }
465
+ });
466
+ }
467
+
468
+ animateNumber(element, finalValue, numericValue, isPercentage) {
469
+ let currentValue = 0;
470
+ const increment = Math.ceil(numericValue / 30);
471
+
472
+ const timer = setInterval(() => {
473
+ currentValue += increment;
474
+ if (currentValue >= numericValue) {
475
+ element.textContent = finalValue;
476
+ clearInterval(timer);
477
+ } else {
478
+ element.textContent = isPercentage ? `${currentValue}%` : `${currentValue}`;
479
+ }
480
+ }, 50);
481
+ }
482
+ }
483
+
484
+ // Initialize presentation when DOM is loaded
485
+ document.addEventListener('DOMContentLoaded', () => {
486
+ console.log('DOM loaded, initializing presentation...');
487
+ window.presentation = new Presentation();
488
+ });
489
+
490
+ // Fallback initialization for cases where DOMContentLoaded already fired
491
+ if (document.readyState !== 'loading') {
492
+ console.log('DOM already loaded, initializing presentation...');
493
+ window.presentation = new Presentation();
494
+ }
495
+
496
+ // Add global error handling
497
+ window.addEventListener('error', (e) => {
498
+ console.error('Presentation error:', e.error);
499
+ });
500
+
501
+ // Add performance optimization
502
+ window.addEventListener('load', () => {
503
+ console.log('Window loaded, optimizing...');
504
+ // Preload images
505
+ const images = document.querySelectorAll('img[src]');
506
+ images.forEach(img => {
507
+ const link = document.createElement('link');
508
+ link.rel = 'prefetch';
509
+ link.href = img.src;
510
+ document.head.appendChild(link);
511
+ });
512
+ });
513
+
514
+ // Add visibility change handling for presentations
515
+ document.addEventListener('visibilitychange', () => {
516
+ if (document.hidden) {
517
+ // Pause any ongoing animations when tab is not visible
518
+ document.querySelectorAll('.animate-in').forEach(el => {
519
+ if (el.style.animationPlayState !== undefined) {
520
+ el.style.animationPlayState = 'paused';
521
+ }
522
+ });
523
+ } else {
524
+ // Resume animations when tab becomes visible
525
+ document.querySelectorAll('.animate-in').forEach(el => {
526
+ if (el.style.animationPlayState !== undefined) {
527
+ el.style.animationPlayState = 'running';
528
+ }
529
+ });
530
+ }
531
+ });
532
+
533
+ // Export for potential external use
534
+ window.PresentationApp = Presentation;
Business Strategy Presentation/index.html ADDED
@@ -0,0 +1,638 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>FoodieSpot AI Strategy 2025</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ </head>
9
+ <body>
10
+ <div class="presentation-container">
11
+ <!-- Presentation Controls -->
12
+ <div class="presentation-controls">
13
+ <button id="prev-slide" class="btn btn--secondary" aria-label="Previous slide">
14
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
15
+ <path d="M15 18l-6-6 6-6"/>
16
+ </svg>
17
+ </button>
18
+ <div class="slide-counter">
19
+ <span id="current-slide">1</span> / <span id="total-slides">15</span>
20
+ </div>
21
+ <button id="next-slide" class="btn btn--primary" aria-label="Next slide">
22
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
23
+ <path d="M9 18l6-6-6-6"/>
24
+ </svg>
25
+ </button>
26
+ <button id="fullscreen-toggle" class="btn btn--secondary" aria-label="Toggle fullscreen">
27
+ <svg id="fullscreen-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
28
+ <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
29
+ </svg>
30
+ </button>
31
+ </div>
32
+
33
+ <!-- Progress Bar -->
34
+ <div class="progress-bar">
35
+ <div class="progress-indicator"></div>
36
+ </div>
37
+
38
+ <!-- Slides Container -->
39
+ <div class="slides-container">
40
+ <!-- Slide 1 - Title Slide -->
41
+ <div class="slide slide-title" id="slide-1">
42
+ <div class="slide-content">
43
+ <h1 class="main-title">FoodieSpot AI Strategy 2025</h1>
44
+ <h2 class="subtitle">LLM-Based Conversational Agent Business Strategy</h2>
45
+ <div class="key-highlights">
46
+ <div class="highlight-container">
47
+ <div class="highlight">Transform Customer Experience</div>
48
+ <div class="highlight">30% Cost Reduction</div>
49
+ <div class="highlight">90% Automation</div>
50
+ </div>
51
+ </div>
52
+ <div class="company-info">
53
+ <p>FoodieSpot Restaurant Chain</p>
54
+ <p>Presented by: Sri Vallabh Tammireddy</p>
55
+ </div>
56
+ <img src="https://pplx-res.cloudinary.com/image/upload/v1748841437/pplx_project_search_images/a5fcd65452d252b1218791421c3e65897d481ee6.jpg" alt="Restaurant integrating AI for customer service and order management" class="background-image">
57
+ </div>
58
+ </div>
59
+
60
+ <!-- Slide 2 - Executive Summary -->
61
+ <div class="slide" id="slide-2">
62
+ <div class="slide-content">
63
+ <h2 class="slide-title">Executive Summary</h2>
64
+ <ul class="bullet-points">
65
+ <li>Industry-leading AI-powered restaurant customer experience by 2027</li>
66
+ <li>90% automation of queries, 30% cost reduction, 25% satisfaction boost</li>
67
+ <li>3-phase rollout across 20+ restaurant locations</li>
68
+ <li>ROI: 12% table turnover increase, 20% customer retention</li>
69
+ </ul>
70
+ <div class="slide-image-container">
71
+ <img src="https://pplx-res.cloudinary.com/image/upload/v1748619282/pplx_project_search_images/aa71ff0f31e06a994ec03f9f8492b61c1876f366.jpg" alt="Chatbots can assist restaurants in multiple ways" class="slide-image">
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ <!-- Slide 3 - Strategic Vision & Goals -->
77
+ <div class="slide" id="slide-3">
78
+ <div class="slide-content">
79
+ <h2 class="slide-title">Strategic Vision & Goals</h2>
80
+ <div class="two-column-layout">
81
+ <div class="column">
82
+ <h3 class="column-title">Long Term Goals</h3>
83
+ <ul class="bullet-points">
84
+ <li>Become restaurant industry leader in AI-powered customer experience by 2027</li>
85
+ <li>Establish new standard for restaurant automation and efficiency</li>
86
+ <li>Scale solution across 100+ locations nationwide</li>
87
+ <li>Develop proprietary conversation flow technology</li>
88
+ </ul>
89
+ </div>
90
+ <div class="column">
91
+ <h3 class="column-title">Key Metrics & Targets</h3>
92
+ <ul class="bullet-points">
93
+ <li>90% query automation within 12 months</li>
94
+ <li>25% improvement in customer satisfaction scores</li>
95
+ <li>30% reduction in operational costs</li>
96
+ <li>20% boost in return customer frequency</li>
97
+ </ul>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </div>
102
+
103
+ <!-- Slide 4 - Success Metrics -->
104
+ <div class="slide" id="slide-4">
105
+ <div class="slide-content">
106
+ <h2 class="slide-title">Success Metrics</h2>
107
+ <div class="metrics-container">
108
+ <div class="metric-category">
109
+ <h3 class="metric-title operational">Operational</h3>
110
+ <ul class="bullet-points">
111
+ <li>Handle 80%+ of customer queries without human intervention</li>
112
+ <li>Achieve <1 minute average response time for complex queries</li>
113
+ <li>Process 95%+ reservation requests successfully</li>
114
+ <li>Reduce no-show rates by 15%</li>
115
+ </ul>
116
+ </div>
117
+ <div class="metric-category">
118
+ <h3 class="metric-title business">Business Impact</h3>
119
+ <ul class="bullet-points">
120
+ <li>Increase table turnover rate by 12%</li>
121
+ <li>Boost customer retention by 20%</li>
122
+ <li>Generate 15% cost savings within 12 months</li>
123
+ <li>Achieve 4.5+ star customer satisfaction rating</li>
124
+ </ul>
125
+ </div>
126
+ <div class="metric-category">
127
+ <h3 class="metric-title technical">Technical Performance</h3>
128
+ <ul class="bullet-points">
129
+ <li>Maintain 99.5% uptime</li>
130
+ <li>Support 500+ concurrent users during peak</li>
131
+ <li>Seamless POS integration</li>
132
+ <li>Multi-language natural language processing</li>
133
+ </ul>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <!-- Slide 5 - The FoodieSpot Solution -->
140
+ <div class="slide" id="slide-5">
141
+ <div class="slide-content">
142
+ <h2 class="slide-title">The FoodieSpot Solution</h2>
143
+ <div class="solution-description">
144
+ <p>FoodieSpot's AI-powered conversational agent revolutionizes the dining experience by providing customers with instant, intelligent assistance for restaurant discovery, menu inquiries, and seamless reservation booking. The system combines advanced natural language processing with real-time database integration to handle everything from simple questions about restaurant hours to complex multi-party reservations across 20+ restaurant locations.</p>
145
+ </div>
146
+ <div class="value-props">
147
+ <h3>Key Value Propositions</h3>
148
+ <div class="value-prop-container">
149
+ <div class="value-prop">
150
+ <div class="value-icon">πŸ’¬</div>
151
+ <h4>Intelligent Conversations</h4>
152
+ <p>Natural language understanding with contextual awareness</p>
153
+ </div>
154
+ <div class="value-prop">
155
+ <div class="value-icon">⚑</div>
156
+ <h4>Instant Response</h4>
157
+ <p>24/7 availability with sub-second response times</p>
158
+ </div>
159
+ <div class="value-prop">
160
+ <div class="value-icon">πŸ“Š</div>
161
+ <h4>Data-Driven Insights</h4>
162
+ <p>Continuous learning from customer interactions</p>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <!-- Slide 6 - End-User Experience Flow -->
170
+ <div class="slide" id="slide-6">
171
+ <div class="slide-content">
172
+ <h2 class="slide-title">End-User Experience Flow</h2>
173
+ <div class="flow-diagram">
174
+ <div class="flow-step">
175
+ <div class="step-number">1</div>
176
+ <div class="step-content">
177
+ <h4>Discovery & Engagement</h4>
178
+ <p>Customer initiates conversation and system identifies dining intent</p>
179
+ </div>
180
+ </div>
181
+ <div class="flow-step">
182
+ <div class="step-number">2</div>
183
+ <div class="step-content">
184
+ <h4>Intelligent Recommendation</h4>
185
+ <p>AI analyzes preferences and provides personalized restaurant suggestions</p>
186
+ </div>
187
+ </div>
188
+ <div class="flow-step">
189
+ <div class="step-number">3</div>
190
+ <div class="step-content">
191
+ <h4>Seamless Reservation</h4>
192
+ <p>Collects booking information and confirms real-time availability</p>
193
+ </div>
194
+ </div>
195
+ <div class="flow-step">
196
+ <div class="step-number">4</div>
197
+ <div class="step-content">
198
+ <h4>Pre-Arrival Enhancement</h4>
199
+ <p>Automated reminders and menu pre-ordering options</p>
200
+ </div>
201
+ </div>
202
+ <div class="flow-step">
203
+ <div class="step-number">5</div>
204
+ <div class="step-content">
205
+ <h4>Post-Experience Follow-up</h4>
206
+ <p>Feedback collection and loyalty program enrollment</p>
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+
213
+ <!-- Slide 7 - Conversation Flow Architecture -->
214
+ <div class="slide" id="slide-7">
215
+ <div class="slide-content">
216
+ <h2 class="slide-title">Conversation Flow Architecture</h2>
217
+ <div class="architecture-diagram">
218
+ <img src="https://pplx-res.cloudinary.com/image/upload/v1748552102/pplx_project_search_images/c4f7d6e3c3b2738159eacb794d10350d9760befc.jpg" alt="Diagram illustrating how chatbots function, including NLP, knowledge base, and data storage" class="architecture-image">
219
+ </div>
220
+ <div class="architecture-details">
221
+ <h3>Key Conversation States</h3>
222
+ <div class="states-container">
223
+ <div class="state">Initial Greeting</div>
224
+ <div class="state-arrow">β†’</div>
225
+ <div class="state">Intent Recognition</div>
226
+ <div class="state-arrow">β†’</div>
227
+ <div class="state">Answer user queries</div>
228
+ <div class="state-arrow">β†’</div>
229
+ <div class="state">Information Collection</div>
230
+ <div class="state-arrow">β†’</div>
231
+ <div class="state">Confirmation</div>
232
+ <div class="state-arrow">β†’</div>
233
+ <div class="state">Completion</div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </div>
238
+
239
+ <!-- Slide 8 - Technical Capabilities -->
240
+ <div class="slide" id="slide-8">
241
+ <div class="slide-content">
242
+ <h2 class="slide-title">Technical Capabilities</h2>
243
+ <div class="capability-container">
244
+ <div class="capability-section">
245
+ <h3>Knowledge Bases</h3>
246
+ <ul class="bullet-points">
247
+ <li>Restaurant locations, hours & policies</li>
248
+ <li>Complete menu database with allergen info</li>
249
+ <li>Historical customer preferences</li>
250
+ </ul>
251
+ </div>
252
+ <div class="capability-section">
253
+ <h3>Integration Requirements</h3>
254
+ <ul class="bullet-points">
255
+ <li>Reservation management system</li>
256
+ <li>Customer relationship management (CRM)</li>
257
+ <li>Point of sale (POS) system</li>
258
+ </ul>
259
+ </div>
260
+ </div>
261
+ <div class="feature-matrix">
262
+ <h3>Feature Implementation Complexity</h3>
263
+ <div class="feature-difficulty">
264
+ <div class="difficulty-container">
265
+ <h4 class="difficulty-level green">Green (Easy)</h4>
266
+ <ul class="bullet-points">
267
+ <li>SMS/WhatsApp notification integration</li>
268
+ <li>Basic customer feedback collection</li>
269
+ <li>Email reminder system</li>
270
+ <li>Simple loyalty point tracking</li>
271
+ </ul>
272
+ </div>
273
+ <div class="difficulty-container">
274
+ <h4 class="difficulty-level yellow">Yellow (Medium)</h4>
275
+ <ul class="bullet-points">
276
+ <li>Voice interface integration</li>
277
+ <li>Advanced dietary preference matching</li>
278
+ <li>Dynamic pricing integration</li>
279
+ <li>Multi-language support expansion</li>
280
+ </ul>
281
+ </div>
282
+ <div class="difficulty-container">
283
+ <h4 class="difficulty-level red">Red (Complex)</h4>
284
+ <ul class="bullet-points">
285
+ <li>Predictive table optimization ML</li>
286
+ <li>External calendar integration</li>
287
+ <li>Advanced sentiment analysis</li>
288
+ <li>IoT integration for smart management</li>
289
+ </ul>
290
+ </div>
291
+ </div>
292
+ </div>
293
+ </div>
294
+ </div>
295
+
296
+ <!-- Slide 9 - Technology Architecture -->
297
+ <div class="slide" id="slide-9">
298
+ <div class="slide-content">
299
+ <h2 class="slide-title">Technology Architecture</h2>
300
+ <div class="tech-stack-container">
301
+ <div class="tech-component">
302
+ <div class="tech-icon">🧠</div>
303
+ <h3>Language Model</h3>
304
+ <p>LLaMA 3 8B via Groq API</p>
305
+ </div>
306
+ <div class="tech-component">
307
+ <div class="tech-icon">πŸ”</div>
308
+ <h3>Vector Database</h3>
309
+ <p>ChromaDB for semantic search</p>
310
+ </div>
311
+ <div class="tech-component">
312
+ <div class="tech-icon">πŸ’Ύ</div>
313
+ <h3>SQL Database</h3>
314
+ <p>SQLite for structured data</p>
315
+ </div>
316
+ <div class="tech-component">
317
+ <div class="tech-icon">πŸ”„</div>
318
+ <h3>Embedding Model</h3>
319
+ <p>Sentence Transformers</p>
320
+ </div>
321
+ <div class="tech-component">
322
+ <div class="tech-icon">πŸ–₯️</div>
323
+ <h3>UI Framework</h3>
324
+ <p>Streamlit for web interface</p>
325
+ </div>
326
+ </div>
327
+ </div>
328
+ </div>
329
+
330
+ <!-- Slide 10 - Phase 1: Pilot Program -->
331
+ <div class="slide" id="slide-10">
332
+ <div class="slide-content">
333
+ <h2 class="slide-title">Phase 1: Pilot Program (Months 1-3)</h2>
334
+ <div class="phase-details">
335
+ <div class="phase-content">
336
+ <div class="phase-stat">
337
+ <h3>Scope</h3>
338
+ <p>3 flagship locations</p>
339
+ </div>
340
+ <div class="phase-stat">
341
+ <h3>Capacity</h3>
342
+ <p>100 daily interactions per location</p>
343
+ </div>
344
+ <div class="phase-stat">
345
+ <h3>Focus</h3>
346
+ <p>Testing and validation</p>
347
+ </div>
348
+ </div>
349
+ <div class="phase-framework">
350
+ <h3>Testing Framework</h3>
351
+ <div class="framework-container">
352
+ <div class="framework-item">
353
+ <h4>A/B Testing</h4>
354
+ <p>Comparing AI vs traditional customer service</p>
355
+ </div>
356
+ <div class="framework-item">
357
+ <h4>User Satisfaction</h4>
358
+ <p>Post-interaction surveys and feedback collection</p>
359
+ </div>
360
+ <div class="framework-item">
361
+ <h4>Performance Metrics</h4>
362
+ <p>Response time, accuracy, completion rate</p>
363
+ </div>
364
+ <div class="framework-item">
365
+ <h4>Staff Feedback</h4>
366
+ <p>Regular listening sessions with restaurant teams</p>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ </div>
371
+ </div>
372
+ </div>
373
+
374
+ <!-- Slide 11 - Scale-Up Plan -->
375
+ <div class="slide" id="slide-11">
376
+ <div class="slide-content">
377
+ <h2 class="slide-title">Scale-Up Plan (Months 4-12)</h2>
378
+ <div class="phases-container">
379
+ <div class="phase-card">
380
+ <h3 class="phase-title phase-2">Phase 2: Regional Expansion</h3>
381
+ <div class="phase-timeline">Months 4-8</div>
382
+ <ul class="bullet-points">
383
+ <li><strong>Scope:</strong> 10 additional locations across 3-4 regions</li>
384
+ <li><strong>Capacity:</strong> 5,000+ daily interactions</li>
385
+ <li><strong>Focus:</strong> Multi-language support and advanced personalization</li>
386
+ </ul>
387
+ </div>
388
+ <div class="phase-card">
389
+ <h3 class="phase-title phase-3">Phase 3: National Deployment</h3>
390
+ <div class="phase-timeline">Months 9-12</div>
391
+ <ul class="bullet-points">
392
+ <li><strong>Scope:</strong> All 20+ FoodieSpot locations nationwide</li>
393
+ <li><strong>Capacity:</strong> 50,000+ daily interactions</li>
394
+ <li><strong>Focus:</strong> Predictive analytics and cross-location recommendations</li>
395
+ </ul>
396
+ </div>
397
+ </div>
398
+ <div class="feature-progression">
399
+ <h3>Feature Progression</h3>
400
+ <div class="progression-timeline">
401
+ <div class="timeline-marker">
402
+ <div class="marker"></div>
403
+ <p>Basic reservation</p>
404
+ </div>
405
+ <div class="timeline-marker">
406
+ <div class="marker"></div>
407
+ <p>Menu recommendations</p>
408
+ </div>
409
+ <div class="timeline-marker">
410
+ <div class="marker"></div>
411
+ <p>Multi-language</p>
412
+ </div>
413
+ <div class="timeline-marker">
414
+ <div class="marker"></div>
415
+ <p>Personalization</p>
416
+ </div>
417
+ <div class="timeline-marker">
418
+ <div class="marker"></div>
419
+ <p>Predictive analytics</p>
420
+ </div>
421
+ </div>
422
+ </div>
423
+ </div>
424
+ </div>
425
+
426
+ <!-- Slide 12 - Business Impact & ROI -->
427
+ <div class="slide" id="slide-12">
428
+ <div class="slide-content">
429
+ <h2 class="slide-title">Business Impact & ROI</h2>
430
+ <div class="roi-metrics">
431
+ <div class="roi-metric">
432
+ <h3>30%</h3>
433
+ <p>Reduction in customer service costs</p>
434
+ </div>
435
+ <div class="roi-metric">
436
+ <h3>12%</h3>
437
+ <p>Table turnover improvement</p>
438
+ </div>
439
+ <div class="roi-metric">
440
+ <h3>20%</h3>
441
+ <p>Customer retention increase</p>
442
+ </div>
443
+ </div>
444
+ <div class="market-metrics">
445
+ <h3>Market Opportunity</h3>
446
+ <div class="market-stats">
447
+ <div class="market-stat">
448
+ <p class="stat-value">$20.81B</p>
449
+ <p class="stat-label">Chatbot market by 2029</p>
450
+ </div>
451
+ <div class="market-stat">
452
+ <p class="stat-value">24.53%</p>
453
+ <p class="stat-label">Annual growth rate</p>
454
+ </div>
455
+ <div class="market-stat">
456
+ <p class="stat-value">$6.2B</p>
457
+ <p class="stat-label">Reservation system market by 2033</p>
458
+ </div>
459
+ </div>
460
+ </div>
461
+ <div class="sources">
462
+ <h3>Sources</h3>
463
+ <ul>
464
+ <li><strong>Chatbot Market Size & Growth:</strong> <a href="https://www.researchandmarkets.com/reports/ai-chatbot-market" target="_blank">ResearchAndMarkets</a> (Note: $20.81B is a conservative estimate; latest reports project $46.64B by 2029)</li>
465
+ <li><strong>Reservation System Market:</strong> <a href="https://www.businessresearchinsights.com/market-reports/online-restaurant-reservation-system-market-112156" target="_blank">Business Research Insights</a>, <a href="https://www.verifiedmarketreports.com/product/global-reservation-and-online-booking-software-market-size-and-forecast/" target="_blank">Verified Market Reports</a></li>
466
+ <li><strong>ROI Metrics:</strong> Industry case studies from McKinsey, Gartner, and IBM</li>
467
+ </ul>
468
+ <p><strong>Indian Conversion Note (at 1 USD = β‚Ή85.48):</strong><br>
469
+ $20.81B β‰ˆ β‚Ή1,78,000 crores<br>
470
+ $6.2B β‰ˆ β‚Ή53,000 crores</p>
471
+ </div>
472
+ </div>
473
+ </div>
474
+
475
+
476
+ <!-- Slide 13 - Implementation Challenges & Mitigation -->
477
+ <div class="slide" id="slide-13">
478
+ <div class="slide-content">
479
+ <h2 class="slide-title">Implementation Challenges & Mitigation</h2>
480
+ <div class="challenges-container">
481
+ <div class="challenge-category">
482
+ <h3 class="category-title technical">Technical Challenges</h3>
483
+ <div class="challenge-items">
484
+ <div class="challenge-item">
485
+ <h4>LLM reliability</h4>
486
+ <p>Prompt engineering & fallback mechanisms</p>
487
+ </div>
488
+ <div class="challenge-item">
489
+ <h4>Real-time data sync</h4>
490
+ <p>API integration protocols</p>
491
+ </div>
492
+ <div class="challenge-item">
493
+ <h4>Peak load performance</h4>
494
+ <p>Auto-scaling infrastructure</p>
495
+ </div>
496
+ </div>
497
+ </div>
498
+ <div class="challenge-category">
499
+ <h3 class="category-title business">Business Challenges</h3>
500
+ <div class="challenge-items">
501
+ <div class="challenge-item">
502
+ <h4>Customer adoption</h4>
503
+ <p>Gradual introduction with clear benefits</p>
504
+ </div>
505
+ <div class="challenge-item">
506
+ <h4>Integration complexity</h4>
507
+ <p>Phased integration approach</p>
508
+ </div>
509
+ <div class="challenge-item">
510
+ <h4>Data privacy</h4>
511
+ <p>Enterprise security protocols</p>
512
+ </div>
513
+ </div>
514
+ </div>
515
+ <div class="challenge-category">
516
+ <h3 class="category-title operational">Operational Challenges</h3>
517
+ <div class="challenge-items">
518
+ <div class="challenge-item">
519
+ <h4>Staff training</h4>
520
+ <p>Comprehensive training programs</p>
521
+ </div>
522
+ <div class="challenge-item">
523
+ <h4>Quality assurance</h4>
524
+ <p>Continuous monitoring systems</p>
525
+ </div>
526
+ <div class="challenge-item">
527
+ <h4>Competitive response</h4>
528
+ <p>Rapid innovation cycles</p>
529
+ </div>
530
+ </div>
531
+ </div>
532
+ </div>
533
+ </div>
534
+ </div>
535
+
536
+ <!-- Slide 14 - Market Position & Differentiation -->
537
+ <div class="slide" id="slide-14">
538
+ <div class="slide-content">
539
+ <h2 class="slide-title">Market Position & Differentiation</h2>
540
+ <div class="market-content">
541
+ <div class="market-section">
542
+ <h3>Market Trends</h3>
543
+ <ul class="bullet-points">
544
+ <li>Rapid growth in restaurant automation solutions</li>
545
+ <li>Rising customer expectations for personalization</li>
546
+ <li>Increasing adoption of voice and chat interfaces</li>
547
+ <li>Growing focus on data-driven customer experiences</li>
548
+ </ul>
549
+ </div>
550
+ <div class="market-section">
551
+ <h3>Competitive Landscape</h3>
552
+ <ul class="bullet-points">
553
+ <li>Most competitors offer single-channel solutions</li>
554
+ <li>Limited personalization capabilities</li>
555
+ <li>Few solutions integrate with existing POS systems</li>
556
+ <li>Minimal predictive analytics capabilities</li>
557
+ </ul>
558
+ </div>
559
+ <div class="advantages-section">
560
+ <h3>Our Sustainable Advantages</h3>
561
+ <div class="advantages-container">
562
+ <div class="advantage">
563
+ <h4>Omni-channel Integration</h4>
564
+ <p>Seamless experience across all touchpoints</p>
565
+ </div>
566
+ <div class="advantage">
567
+ <h4>Proprietary ML Models</h4>
568
+ <p>Custom-trained on restaurant-specific data</p>
569
+ </div>
570
+ <div class="advantage">
571
+ <h4>First-mover Advantage</h4>
572
+ <p>Rapid deployment ahead of competitors</p>
573
+ </div>
574
+ </div>
575
+ </div>
576
+ </div>
577
+ </div>
578
+ </div>
579
+
580
+ <div class="slide" id="slide-15">
581
+ <div class="slide-content">
582
+ <h2 class="slide-title">Key Elements of Our Brand</h2>
583
+ <div class="slide-image-container">
584
+ <img src="https://pplx-res.cloudinary.com/image/upload/v1748590630/pplx_project_search_images/1a55b83fd6249e2e068c025904b6f0a8ff840661.jpg" alt="Infographic detailing key elements of a company brand-building brainstorm" class="market-image">
585
+ </div>
586
+ </div>
587
+ </div>
588
+
589
+
590
+ <!-- Slide 15 - Conclusion & Next Steps -->
591
+ <div class="slide" id="slide-16">
592
+ <div class="slide-content">
593
+ <h2 class="slide-title">Conclusion & Recommended Actions</h2>
594
+ <div class="conclusion-content">
595
+ <div class="recommendations">
596
+ <h3>Strategic Recommendations</h3>
597
+ <ul class="bullet-points highlighted">
598
+ <li>Immediately approve Phase 1 pilot for Q3 2025 launch</li>
599
+ <li>Allocate $1.2M initial budget for technology development</li>
600
+ <li>Form cross-functional team from IT, Operations and Marketing</li>
601
+ <li>Begin customer research at 3 pilot locations next month</li>
602
+ <li>Approve vendor selection process for technology partners</li>
603
+ </ul>
604
+ </div>
605
+ <div class="timeline-section">
606
+ <h3>Implementation Timeline</h3>
607
+ <div class="timeline">
608
+ <div class="timeline-item">
609
+ <span class="timeline-date">July 2025</span>
610
+ <p>Project kickoff & vendor selection</p>
611
+ </div>
612
+ <div class="timeline-item">
613
+ <span class="timeline-date">August 2025</span>
614
+ <p>Pilot development begins</p>
615
+ </div>
616
+ <div class="timeline-item">
617
+ <span class="timeline-date">October 2025</span>
618
+ <p>Phase 1 launch at pilot locations</p>
619
+ </div>
620
+ <div class="timeline-item">
621
+ <span class="timeline-date">January 2026</span>
622
+ <p>Phase 2 regional expansion</p>
623
+ </div>
624
+ <div class="timeline-item">
625
+ <span class="timeline-date">June 2026</span>
626
+ <p>Phase 3 national deployment</p>
627
+ </div>
628
+ </div>
629
+ </div>
630
+ </div>
631
+ </div>
632
+ </div>
633
+ </div>
634
+ </div>
635
+
636
+ <script src="app.js"></script>
637
+ </body>
638
+ </html>
Business Strategy Presentation/readme.txt.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Open index.html for presentation
Business Strategy Presentation/style.css ADDED
@@ -0,0 +1,1575 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ :root {
3
+ /* Colors */
4
+ --color-background: rgba(252, 252, 249, 1);
5
+ --color-surface: rgba(255, 255, 253, 1);
6
+ --color-text: rgba(19, 52, 59, 1);
7
+ --color-text-secondary: rgba(98, 108, 113, 1);
8
+ --color-primary: rgba(33, 128, 141, 1);
9
+ --color-primary-hover: rgba(29, 116, 128, 1);
10
+ --color-primary-active: rgba(26, 104, 115, 1);
11
+ --color-secondary: rgba(94, 82, 64, 0.12);
12
+ --color-secondary-hover: rgba(94, 82, 64, 0.2);
13
+ --color-secondary-active: rgba(94, 82, 64, 0.25);
14
+ --color-border: rgba(94, 82, 64, 0.2);
15
+ --color-btn-primary-text: rgba(252, 252, 249, 1);
16
+ --color-card-border: rgba(94, 82, 64, 0.12);
17
+ --color-card-border-inner: rgba(94, 82, 64, 0.12);
18
+ --color-error: rgba(192, 21, 47, 1);
19
+ --color-success: rgba(33, 128, 141, 1);
20
+ --color-warning: rgba(168, 75, 47, 1);
21
+ --color-info: rgba(98, 108, 113, 1);
22
+ --color-focus-ring: rgba(33, 128, 141, 0.4);
23
+ --color-select-caret: rgba(19, 52, 59, 0.8);
24
+
25
+ /* Common style patterns */
26
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
27
+ --focus-outline: 2px solid var(--color-primary);
28
+ --status-bg-opacity: 0.15;
29
+ --status-border-opacity: 0.25;
30
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
31
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
32
+
33
+ /* RGB versions for opacity control */
34
+ --color-success-rgb: 33, 128, 141;
35
+ --color-error-rgb: 192, 21, 47;
36
+ --color-warning-rgb: 168, 75, 47;
37
+ --color-info-rgb: 98, 108, 113;
38
+
39
+ /* Typography */
40
+ --font-family-base: "FKGroteskNeue", "Geist", "Inter", -apple-system,
41
+ BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
42
+ --font-family-mono: "Berkeley Mono", ui-monospace, SFMono-Regular, Menlo,
43
+ Monaco, Consolas, monospace;
44
+ --font-size-xs: 11px;
45
+ --font-size-sm: 12px;
46
+ --font-size-base: 14px;
47
+ --font-size-md: 14px;
48
+ --font-size-lg: 16px;
49
+ --font-size-xl: 18px;
50
+ --font-size-2xl: 20px;
51
+ --font-size-3xl: 24px;
52
+ --font-size-4xl: 30px;
53
+ --font-weight-normal: 400;
54
+ --font-weight-medium: 500;
55
+ --font-weight-semibold: 550;
56
+ --font-weight-bold: 600;
57
+ --line-height-tight: 1.2;
58
+ --line-height-normal: 1.5;
59
+ --letter-spacing-tight: -0.01em;
60
+
61
+ /* Spacing */
62
+ --space-0: 0;
63
+ --space-1: 1px;
64
+ --space-2: 2px;
65
+ --space-4: 4px;
66
+ --space-6: 6px;
67
+ --space-8: 8px;
68
+ --space-10: 10px;
69
+ --space-12: 12px;
70
+ --space-16: 16px;
71
+ --space-20: 20px;
72
+ --space-24: 24px;
73
+ --space-32: 32px;
74
+
75
+ /* Border Radius */
76
+ --radius-sm: 6px;
77
+ --radius-base: 8px;
78
+ --radius-md: 10px;
79
+ --radius-lg: 12px;
80
+ --radius-full: 9999px;
81
+
82
+ /* Shadows */
83
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.02);
84
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.02);
85
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.04),
86
+ 0 2px 4px -1px rgba(0, 0, 0, 0.02);
87
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.04),
88
+ 0 4px 6px -2px rgba(0, 0, 0, 0.02);
89
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.15),
90
+ inset 0 -1px 0 rgba(0, 0, 0, 0.03);
91
+
92
+ /* Animation */
93
+ --duration-fast: 150ms;
94
+ --duration-normal: 250ms;
95
+ --ease-standard: cubic-bezier(0.16, 1, 0.3, 1);
96
+
97
+ /* Layout */
98
+ --container-sm: 640px;
99
+ --container-md: 768px;
100
+ --container-lg: 1024px;
101
+ --container-xl: 1280px;
102
+ }
103
+
104
+ /* Dark mode colors */
105
+ @media (prefers-color-scheme: dark) {
106
+ :root {
107
+ --color-background: rgba(31, 33, 33, 1);
108
+ --color-surface: rgba(38, 40, 40, 1);
109
+ --color-text: rgba(245, 245, 245, 1);
110
+ --color-text-secondary: rgba(167, 169, 169, 0.7);
111
+ --color-primary: rgba(50, 184, 198, 1);
112
+ --color-primary-hover: rgba(45, 166, 178, 1);
113
+ --color-primary-active: rgba(41, 150, 161, 1);
114
+ --color-secondary: rgba(119, 124, 124, 0.15);
115
+ --color-secondary-hover: rgba(119, 124, 124, 0.25);
116
+ --color-secondary-active: rgba(119, 124, 124, 0.3);
117
+ --color-border: rgba(119, 124, 124, 0.3);
118
+ --color-error: rgba(255, 84, 89, 1);
119
+ --color-success: rgba(50, 184, 198, 1);
120
+ --color-warning: rgba(230, 129, 97, 1);
121
+ --color-info: rgba(167, 169, 169, 1);
122
+ --color-focus-ring: rgba(50, 184, 198, 0.4);
123
+ --color-btn-primary-text: rgba(19, 52, 59, 1);
124
+ --color-card-border: rgba(119, 124, 124, 0.2);
125
+ --color-card-border-inner: rgba(119, 124, 124, 0.15);
126
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1),
127
+ inset 0 -1px 0 rgba(0, 0, 0, 0.15);
128
+ --button-border-secondary: rgba(119, 124, 124, 0.2);
129
+ --color-border-secondary: rgba(119, 124, 124, 0.2);
130
+ --color-select-caret: rgba(245, 245, 245, 0.8);
131
+
132
+ /* Common style patterns - updated for dark mode */
133
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
134
+ --focus-outline: 2px solid var(--color-primary);
135
+ --status-bg-opacity: 0.15;
136
+ --status-border-opacity: 0.25;
137
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
138
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
139
+
140
+ /* RGB versions for dark mode */
141
+ --color-success-rgb: 50, 184, 198;
142
+ --color-error-rgb: 255, 84, 89;
143
+ --color-warning-rgb: 230, 129, 97;
144
+ --color-info-rgb: 167, 169, 169;
145
+ }
146
+ }
147
+
148
+ /* Data attribute for manual theme switching */
149
+ [data-color-scheme="dark"] {
150
+ --color-background: rgba(31, 33, 33, 1);
151
+ --color-surface: rgba(38, 40, 40, 1);
152
+ --color-text: rgba(245, 245, 245, 1);
153
+ --color-text-secondary: rgba(167, 169, 169, 0.7);
154
+ --color-primary: rgba(50, 184, 198, 1);
155
+ --color-primary-hover: rgba(45, 166, 178, 1);
156
+ --color-primary-active: rgba(41, 150, 161, 1);
157
+ --color-secondary: rgba(119, 124, 124, 0.15);
158
+ --color-secondary-hover: rgba(119, 124, 124, 0.25);
159
+ --color-secondary-active: rgba(119, 124, 124, 0.3);
160
+ --color-border: rgba(119, 124, 124, 0.3);
161
+ --color-error: rgba(255, 84, 89, 1);
162
+ --color-success: rgba(50, 184, 198, 1);
163
+ --color-warning: rgba(230, 129, 97, 1);
164
+ --color-info: rgba(167, 169, 169, 1);
165
+ --color-focus-ring: rgba(50, 184, 198, 0.4);
166
+ --color-btn-primary-text: rgba(19, 52, 59, 1);
167
+ --color-card-border: rgba(119, 124, 124, 0.15);
168
+ --color-card-border-inner: rgba(119, 124, 124, 0.15);
169
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1),
170
+ inset 0 -1px 0 rgba(0, 0, 0, 0.15);
171
+ --color-border-secondary: rgba(119, 124, 124, 0.2);
172
+ --color-select-caret: rgba(245, 245, 245, 0.8);
173
+
174
+ /* Common style patterns - updated for dark mode */
175
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
176
+ --focus-outline: 2px solid var(--color-primary);
177
+ --status-bg-opacity: 0.15;
178
+ --status-border-opacity: 0.25;
179
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
180
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
181
+
182
+ /* RGB versions for dark mode */
183
+ --color-success-rgb: 50, 184, 198;
184
+ --color-error-rgb: 255, 84, 89;
185
+ --color-warning-rgb: 230, 129, 97;
186
+ --color-info-rgb: 167, 169, 169;
187
+ }
188
+
189
+ [data-color-scheme="light"] {
190
+ --color-background: rgba(252, 252, 249, 1);
191
+ --color-surface: rgba(255, 255, 253, 1);
192
+ --color-text: rgba(19, 52, 59, 1);
193
+ --color-text-secondary: rgba(98, 108, 113, 1);
194
+ --color-primary: rgba(33, 128, 141, 1);
195
+ --color-primary-hover: rgba(29, 116, 128, 1);
196
+ --color-primary-active: rgba(26, 104, 115, 1);
197
+ --color-secondary: rgba(94, 82, 64, 0.12);
198
+ --color-secondary-hover: rgba(94, 82, 64, 0.2);
199
+ --color-secondary-active: rgba(94, 82, 64, 0.25);
200
+ --color-border: rgba(94, 82, 64, 0.2);
201
+ --color-btn-primary-text: rgba(252, 252, 249, 1);
202
+ --color-card-border: rgba(94, 82, 64, 0.12);
203
+ --color-card-border-inner: rgba(94, 82, 64, 0.12);
204
+ --color-error: rgba(192, 21, 47, 1);
205
+ --color-success: rgba(33, 128, 141, 1);
206
+ --color-warning: rgba(168, 75, 47, 1);
207
+ --color-info: rgba(98, 108, 113, 1);
208
+ --color-focus-ring: rgba(33, 128, 141, 0.4);
209
+
210
+ /* RGB versions for light mode */
211
+ --color-success-rgb: 33, 128, 141;
212
+ --color-error-rgb: 192, 21, 47;
213
+ --color-warning-rgb: 168, 75, 47;
214
+ --color-info-rgb: 98, 108, 113;
215
+ }
216
+
217
+ /* Base styles */
218
+ html {
219
+ font-size: var(--font-size-base);
220
+ font-family: var(--font-family-base);
221
+ line-height: var(--line-height-normal);
222
+ color: var(--color-text);
223
+ background-color: var(--color-background);
224
+ -webkit-font-smoothing: antialiased;
225
+ box-sizing: border-box;
226
+ }
227
+
228
+ body {
229
+ margin: 0;
230
+ padding: 0;
231
+ }
232
+
233
+ *,
234
+ *::before,
235
+ *::after {
236
+ box-sizing: inherit;
237
+ }
238
+
239
+ /* Typography */
240
+ h1,
241
+ h2,
242
+ h3,
243
+ h4,
244
+ h5,
245
+ h6 {
246
+ margin: 0;
247
+ font-weight: var(--font-weight-semibold);
248
+ line-height: var(--line-height-tight);
249
+ color: var(--color-text);
250
+ letter-spacing: var(--letter-spacing-tight);
251
+ }
252
+
253
+ h1 {
254
+ font-size: var(--font-size-4xl);
255
+ }
256
+ h2 {
257
+ font-size: var(--font-size-3xl);
258
+ }
259
+ h3 {
260
+ font-size: var(--font-size-2xl);
261
+ }
262
+ h4 {
263
+ font-size: var(--font-size-xl);
264
+ }
265
+ h5 {
266
+ font-size: var(--font-size-lg);
267
+ }
268
+ h6 {
269
+ font-size: var(--font-size-md);
270
+ }
271
+
272
+ p {
273
+ margin: 0 0 var(--space-16) 0;
274
+ }
275
+
276
+ a {
277
+ color: var(--color-primary);
278
+ text-decoration: none;
279
+ transition: color var(--duration-fast) var(--ease-standard);
280
+ }
281
+
282
+ a:hover {
283
+ color: var(--color-primary-hover);
284
+ }
285
+
286
+ code,
287
+ pre {
288
+ font-family: var(--font-family-mono);
289
+ font-size: calc(var(--font-size-base) * 0.95);
290
+ background-color: var(--color-secondary);
291
+ border-radius: var(--radius-sm);
292
+ }
293
+
294
+ code {
295
+ padding: var(--space-1) var(--space-4);
296
+ }
297
+
298
+ pre {
299
+ padding: var(--space-16);
300
+ margin: var(--space-16) 0;
301
+ overflow: auto;
302
+ border: 1px solid var(--color-border);
303
+ }
304
+
305
+ pre code {
306
+ background: none;
307
+ padding: 0;
308
+ }
309
+
310
+ /* Buttons */
311
+ .btn {
312
+ display: inline-flex;
313
+ align-items: center;
314
+ justify-content: center;
315
+ padding: var(--space-8) var(--space-16);
316
+ border-radius: var(--radius-base);
317
+ font-size: var(--font-size-base);
318
+ font-weight: 500;
319
+ line-height: 1.5;
320
+ cursor: pointer;
321
+ transition: all var(--duration-normal) var(--ease-standard);
322
+ border: none;
323
+ text-decoration: none;
324
+ position: relative;
325
+ }
326
+
327
+ .btn:focus-visible {
328
+ outline: none;
329
+ box-shadow: var(--focus-ring);
330
+ }
331
+
332
+ .btn--primary {
333
+ background: var(--color-primary);
334
+ color: var(--color-btn-primary-text);
335
+ }
336
+
337
+ .btn--primary:hover {
338
+ background: var(--color-primary-hover);
339
+ }
340
+
341
+ .btn--primary:active {
342
+ background: var(--color-primary-active);
343
+ }
344
+
345
+ .btn--secondary {
346
+ background: var(--color-secondary);
347
+ color: var(--color-text);
348
+ }
349
+
350
+ .btn--secondary:hover {
351
+ background: var(--color-secondary-hover);
352
+ }
353
+
354
+ .btn--secondary:active {
355
+ background: var(--color-secondary-active);
356
+ }
357
+
358
+ .btn--outline {
359
+ background: transparent;
360
+ border: 1px solid var(--color-border);
361
+ color: var(--color-text);
362
+ }
363
+
364
+ .btn--outline:hover {
365
+ background: var(--color-secondary);
366
+ }
367
+
368
+ .btn--sm {
369
+ padding: var(--space-4) var(--space-12);
370
+ font-size: var(--font-size-sm);
371
+ border-radius: var(--radius-sm);
372
+ }
373
+
374
+ .btn--lg {
375
+ padding: var(--space-10) var(--space-20);
376
+ font-size: var(--font-size-lg);
377
+ border-radius: var(--radius-md);
378
+ }
379
+
380
+ .btn--full-width {
381
+ width: 100%;
382
+ }
383
+
384
+ .btn:disabled {
385
+ opacity: 0.5;
386
+ cursor: not-allowed;
387
+ }
388
+
389
+ /* Form elements */
390
+ .form-control {
391
+ display: block;
392
+ width: 100%;
393
+ padding: var(--space-8) var(--space-12);
394
+ font-size: var(--font-size-md);
395
+ line-height: 1.5;
396
+ color: var(--color-text);
397
+ background-color: var(--color-surface);
398
+ border: 1px solid var(--color-border);
399
+ border-radius: var(--radius-base);
400
+ transition: border-color var(--duration-fast) var(--ease-standard),
401
+ box-shadow var(--duration-fast) var(--ease-standard);
402
+ }
403
+
404
+ textarea.form-control {
405
+ font-family: var(--font-family-base);
406
+ font-size: var(--font-size-base);
407
+ }
408
+
409
+ select.form-control {
410
+ padding: var(--space-8) var(--space-12);
411
+ -webkit-appearance: none;
412
+ -moz-appearance: none;
413
+ appearance: none;
414
+ background-image: var(--select-caret-light);
415
+ background-repeat: no-repeat;
416
+ background-position: right var(--space-12) center;
417
+ background-size: 16px;
418
+ padding-right: var(--space-32);
419
+ }
420
+
421
+ /* Add a dark mode specific caret */
422
+ @media (prefers-color-scheme: dark) {
423
+ select.form-control {
424
+ background-image: var(--select-caret-dark);
425
+ }
426
+ }
427
+
428
+ /* Also handle data-color-scheme */
429
+ [data-color-scheme="dark"] select.form-control {
430
+ background-image: var(--select-caret-dark);
431
+ }
432
+
433
+ [data-color-scheme="light"] select.form-control {
434
+ background-image: var(--select-caret-light);
435
+ }
436
+
437
+ .form-control:focus {
438
+ border-color: var(--color-primary);
439
+ outline: var(--focus-outline);
440
+ }
441
+
442
+ .form-label {
443
+ display: block;
444
+ margin-bottom: var(--space-8);
445
+ font-weight: var(--font-weight-medium);
446
+ font-size: var(--font-size-sm);
447
+ }
448
+
449
+ .form-group {
450
+ margin-bottom: var(--space-16);
451
+ }
452
+
453
+ /* Card component */
454
+ .card {
455
+ background-color: var(--color-surface);
456
+ border-radius: var(--radius-lg);
457
+ border: 1px solid var(--color-card-border);
458
+ box-shadow: var(--shadow-sm);
459
+ overflow: hidden;
460
+ transition: box-shadow var(--duration-normal) var(--ease-standard);
461
+ }
462
+
463
+ .card:hover {
464
+ box-shadow: var(--shadow-md);
465
+ }
466
+
467
+ .card__body {
468
+ padding: var(--space-16);
469
+ }
470
+
471
+ .card__header,
472
+ .card__footer {
473
+ padding: var(--space-16);
474
+ border-bottom: 1px solid var(--color-card-border-inner);
475
+ }
476
+
477
+ /* Status indicators - simplified with CSS variables */
478
+ .status {
479
+ display: inline-flex;
480
+ align-items: center;
481
+ padding: var(--space-6) var(--space-12);
482
+ border-radius: var(--radius-full);
483
+ font-weight: var(--font-weight-medium);
484
+ font-size: var(--font-size-sm);
485
+ }
486
+
487
+ .status--success {
488
+ background-color: rgba(
489
+ var(--color-success-rgb, 33, 128, 141),
490
+ var(--status-bg-opacity)
491
+ );
492
+ color: var(--color-success);
493
+ border: 1px solid
494
+ rgba(var(--color-success-rgb, 33, 128, 141), var(--status-border-opacity));
495
+ }
496
+
497
+ .status--error {
498
+ background-color: rgba(
499
+ var(--color-error-rgb, 192, 21, 47),
500
+ var(--status-bg-opacity)
501
+ );
502
+ color: var(--color-error);
503
+ border: 1px solid
504
+ rgba(var(--color-error-rgb, 192, 21, 47), var(--status-border-opacity));
505
+ }
506
+
507
+ .status--warning {
508
+ background-color: rgba(
509
+ var(--color-warning-rgb, 168, 75, 47),
510
+ var(--status-bg-opacity)
511
+ );
512
+ color: var(--color-warning);
513
+ border: 1px solid
514
+ rgba(var(--color-warning-rgb, 168, 75, 47), var(--status-border-opacity));
515
+ }
516
+
517
+ .status--info {
518
+ background-color: rgba(
519
+ var(--color-info-rgb, 98, 108, 113),
520
+ var(--status-bg-opacity)
521
+ );
522
+ color: var(--color-info);
523
+ border: 1px solid
524
+ rgba(var(--color-info-rgb, 98, 108, 113), var(--status-border-opacity));
525
+ }
526
+
527
+ /* Container layout */
528
+ .container {
529
+ width: 100%;
530
+ margin-right: auto;
531
+ margin-left: auto;
532
+ padding-right: var(--space-16);
533
+ padding-left: var(--space-16);
534
+ }
535
+
536
+ @media (min-width: 640px) {
537
+ .container {
538
+ max-width: var(--container-sm);
539
+ }
540
+ }
541
+ @media (min-width: 768px) {
542
+ .container {
543
+ max-width: var(--container-md);
544
+ }
545
+ }
546
+ @media (min-width: 1024px) {
547
+ .container {
548
+ max-width: var(--container-lg);
549
+ }
550
+ }
551
+ @media (min-width: 1280px) {
552
+ .container {
553
+ max-width: var(--container-xl);
554
+ }
555
+ }
556
+
557
+ /* Utility classes */
558
+ .flex {
559
+ display: flex;
560
+ }
561
+ .flex-col {
562
+ flex-direction: column;
563
+ }
564
+ .items-center {
565
+ align-items: center;
566
+ }
567
+ .justify-center {
568
+ justify-content: center;
569
+ }
570
+ .justify-between {
571
+ justify-content: space-between;
572
+ }
573
+ .gap-4 {
574
+ gap: var(--space-4);
575
+ }
576
+ .gap-8 {
577
+ gap: var(--space-8);
578
+ }
579
+ .gap-16 {
580
+ gap: var(--space-16);
581
+ }
582
+
583
+ .m-0 {
584
+ margin: 0;
585
+ }
586
+ .mt-8 {
587
+ margin-top: var(--space-8);
588
+ }
589
+ .mb-8 {
590
+ margin-bottom: var(--space-8);
591
+ }
592
+ .mx-8 {
593
+ margin-left: var(--space-8);
594
+ margin-right: var(--space-8);
595
+ }
596
+ .my-8 {
597
+ margin-top: var(--space-8);
598
+ margin-bottom: var(--space-8);
599
+ }
600
+
601
+ .p-0 {
602
+ padding: 0;
603
+ }
604
+ .py-8 {
605
+ padding-top: var(--space-8);
606
+ padding-bottom: var(--space-8);
607
+ }
608
+ .px-8 {
609
+ padding-left: var(--space-8);
610
+ padding-right: var(--space-8);
611
+ }
612
+ .py-16 {
613
+ padding-top: var(--space-16);
614
+ padding-bottom: var(--space-16);
615
+ }
616
+ .px-16 {
617
+ padding-left: var(--space-16);
618
+ padding-right: var(--space-16);
619
+ }
620
+
621
+ .block {
622
+ display: block;
623
+ }
624
+ .hidden {
625
+ display: none;
626
+ }
627
+
628
+ /* Accessibility */
629
+ .sr-only {
630
+ position: absolute;
631
+ width: 1px;
632
+ height: 1px;
633
+ padding: 0;
634
+ margin: -1px;
635
+ overflow: hidden;
636
+ clip: rect(0, 0, 0, 0);
637
+ white-space: nowrap;
638
+ border-width: 0;
639
+ }
640
+
641
+ :focus-visible {
642
+ outline: var(--focus-outline);
643
+ outline-offset: 2px;
644
+ }
645
+
646
+ /* Dark mode specifics */
647
+ [data-color-scheme="dark"] .btn--outline {
648
+ border: 1px solid var(--color-border-secondary);
649
+ }
650
+
651
+ @font-face {
652
+ font-family: 'FKGroteskNeue';
653
+ src: url('https://www.perplexity.ai/fonts/FKGroteskNeue.woff2')
654
+ format('woff2');
655
+ }
656
+
657
+ /* Custom styles for the presentation */
658
+
659
+ /* Presentation container */
660
+ .presentation-container {
661
+ position: relative;
662
+ width: 100vw;
663
+ height: 100vh;
664
+ overflow: hidden;
665
+ background-color: var(--color-background);
666
+ font-family: var(--font-family-base);
667
+ }
668
+
669
+ /* Controls */
670
+ .presentation-controls {
671
+ position: fixed;
672
+ bottom: 20px;
673
+ left: 50%;
674
+ transform: translateX(-50%);
675
+ display: flex;
676
+ align-items: center;
677
+ gap: var(--space-16);
678
+ background-color: var(--color-surface);
679
+ padding: var(--space-8) var(--space-16);
680
+ border-radius: var(--radius-full);
681
+ box-shadow: var(--shadow-md);
682
+ z-index: 100;
683
+ }
684
+
685
+ .slide-counter {
686
+ font-size: var(--font-size-md);
687
+ color: var(--color-text);
688
+ font-weight: var(--font-weight-medium);
689
+ }
690
+
691
+ /* Progress bar */
692
+ .progress-bar {
693
+ position: fixed;
694
+ top: 0;
695
+ left: 0;
696
+ width: 100%;
697
+ height: 4px;
698
+ background-color: var(--color-border);
699
+ z-index: 100;
700
+ }
701
+
702
+ .progress-indicator {
703
+ height: 100%;
704
+ background-color: var(--color-primary);
705
+ width: 6.67%; /* Start at slide 1 of 15 */
706
+ transition: width 0.3s ease;
707
+ }
708
+
709
+ /* Slides container */
710
+ .slides-container {
711
+ width: 100%;
712
+ height: 100%;
713
+ position: relative;
714
+ }
715
+
716
+ /* Individual slides */
717
+ .slide {
718
+ position: absolute;
719
+ top: 0;
720
+ left: 0;
721
+ width: 100%;
722
+ height: 100%;
723
+ display: none;
724
+ flex-direction: column;
725
+ justify-content: center;
726
+ align-items: center;
727
+ padding: var(--space-32);
728
+ opacity: 0;
729
+ transition: opacity 0.5s ease;
730
+ overflow-y: auto;
731
+ box-sizing: border-box;
732
+ }
733
+
734
+ .slide.active {
735
+ display: flex;
736
+ opacity: 1;
737
+ }
738
+
739
+ .slide-content {
740
+ max-width: 1200px;
741
+ width: 100%;
742
+ margin: 0 auto;
743
+ padding: var(--space-32);
744
+ background-color: var(--color-surface);
745
+ border-radius: var(--radius-lg);
746
+ box-shadow: var(--shadow-md);
747
+ position: relative;
748
+ min-height: 60vh;
749
+ box-sizing: border-box;
750
+ }
751
+
752
+ /* Title slide specific styles */
753
+ .slide-title {
754
+ background: linear-gradient(135deg, var(--color-primary), var(--color-success));
755
+ color: var(--color-btn-primary-text);
756
+ position: relative;
757
+ overflow: hidden;
758
+ }
759
+
760
+ .slide-title .slide-content {
761
+ background-color: transparent;
762
+ box-shadow: none;
763
+ color: var(--color-btn-primary-text);
764
+ text-align: center;
765
+ }
766
+
767
+ .slide h2.slide-title {
768
+ font-size: var(--font-size-3xl);
769
+ color: var(--color-text);
770
+ margin-bottom: var(--space-24);
771
+ text-align: center;
772
+ font-weight: var(--font-weight-semibold);
773
+ line-height: 1.2;
774
+ }
775
+
776
+ /* Main title slide */
777
+ .main-title {
778
+ font-size: 48px;
779
+ margin-bottom: var(--space-16);
780
+ color: var(--color-btn-primary-text);
781
+ text-align: center;
782
+ font-weight: var(--font-weight-bold);
783
+ }
784
+
785
+ .subtitle {
786
+ font-size: var(--font-size-xl);
787
+ color: rgba(255, 255, 255, 0.9);
788
+ margin-bottom: var(--space-24);
789
+ text-align: center;
790
+ font-weight: var(--font-weight-medium);
791
+ }
792
+
793
+ .key-highlights {
794
+ display: flex;
795
+ justify-content: center;
796
+ margin-bottom: var(--space-32);
797
+ width: 100%;
798
+ }
799
+
800
+ .highlight-container {
801
+ display: flex;
802
+ gap: var(--space-16);
803
+ justify-content: center;
804
+ width: 100%;
805
+ flex-wrap: wrap;
806
+ }
807
+
808
+ .highlight {
809
+ background-color: rgba(255, 255, 255, 0.2);
810
+ color: var(--color-btn-primary-text);
811
+ padding: var(--space-12) var(--space-20);
812
+ border-radius: var(--radius-base);
813
+ font-weight: var(--font-weight-semibold);
814
+ font-size: var(--font-size-lg);
815
+ text-align: center;
816
+ backdrop-filter: blur(10px);
817
+ border: 1px solid rgba(255, 255, 255, 0.3);
818
+ }
819
+
820
+ .company-info {
821
+ margin-top: var(--space-32);
822
+ text-align: center;
823
+ font-size: var(--font-size-lg);
824
+ color: rgba(255, 255, 255, 0.8);
825
+ }
826
+
827
+ .background-image {
828
+ position: absolute;
829
+ top: 0;
830
+ left: 0;
831
+ width: 100%;
832
+ height: 100%;
833
+ object-fit: cover;
834
+ opacity: 0.15;
835
+ z-index: -1;
836
+ border-radius: var(--radius-lg);
837
+ }
838
+
839
+ /* Bullet points */
840
+ .bullet-points {
841
+ font-size: var(--font-size-lg);
842
+ line-height: 1.8;
843
+ padding-left: var(--space-24);
844
+ margin-bottom: var(--space-16);
845
+ list-style-type: disc;
846
+ }
847
+
848
+ .bullet-points li {
849
+ margin-bottom: var(--space-12);
850
+ color: var(--color-text);
851
+ }
852
+
853
+ .bullet-points.highlighted li {
854
+ background-color: rgba(var(--color-success-rgb), 0.1);
855
+ padding: var(--space-8) var(--space-16);
856
+ border-left: 4px solid var(--color-success);
857
+ list-style-type: none;
858
+ margin-left: calc(-1 * var(--space-24));
859
+ border-radius: var(--radius-sm);
860
+ }
861
+
862
+ /* Two-column layout */
863
+ .two-column-layout {
864
+ display: flex;
865
+ gap: var(--space-32);
866
+ margin-top: var(--space-24);
867
+ }
868
+
869
+ .column {
870
+ flex: 1;
871
+ }
872
+
873
+ .column-title {
874
+ font-size: var(--font-size-xl);
875
+ margin-bottom: var(--space-16);
876
+ color: var(--color-text);
877
+ font-weight: var(--font-weight-semibold);
878
+ }
879
+
880
+ /* Metrics container */
881
+ .metrics-container {
882
+ display: grid;
883
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
884
+ gap: var(--space-24);
885
+ margin-top: var(--space-24);
886
+ }
887
+
888
+ .metric-category {
889
+ background-color: var(--color-background);
890
+ padding: var(--space-20);
891
+ border-radius: var(--radius-base);
892
+ border: 1px solid var(--color-card-border);
893
+ box-shadow: var(--shadow-sm);
894
+ }
895
+
896
+ .metric-title {
897
+ font-size: var(--font-size-xl);
898
+ margin-bottom: var(--space-16);
899
+ padding-bottom: var(--space-8);
900
+ border-bottom: 3px solid var(--color-primary);
901
+ color: var(--color-text);
902
+ font-weight: var(--font-weight-semibold);
903
+ }
904
+
905
+ .metric-title.operational {
906
+ border-color: #1FB8CD;
907
+ }
908
+
909
+ .metric-title.business {
910
+ border-color: #FFC185;
911
+ }
912
+
913
+ .metric-title.technical {
914
+ border-color: #B4413C;
915
+ }
916
+
917
+ /* Solution description */
918
+ .solution-description p {
919
+ font-size: var(--font-size-lg);
920
+ line-height: 1.8;
921
+ margin-bottom: var(--space-24);
922
+ text-align: justify;
923
+ color: var(--color-text);
924
+ }
925
+
926
+ /* Value propositions */
927
+ .value-props h3 {
928
+ text-align: center;
929
+ margin-bottom: var(--space-20);
930
+ font-size: var(--font-size-xl);
931
+ font-weight: var(--font-weight-semibold);
932
+ }
933
+
934
+ .value-prop-container {
935
+ display: grid;
936
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
937
+ gap: var(--space-20);
938
+ }
939
+
940
+ .value-prop {
941
+ text-align: center;
942
+ padding: var(--space-20);
943
+ background-color: rgba(var(--color-success-rgb), 0.05);
944
+ border-radius: var(--radius-base);
945
+ border: 1px solid rgba(var(--color-success-rgb), 0.2);
946
+ }
947
+
948
+ .value-icon {
949
+ font-size: 36px;
950
+ margin-bottom: var(--space-12);
951
+ }
952
+
953
+ .value-prop h4 {
954
+ font-size: var(--font-size-lg);
955
+ margin-bottom: var(--space-8);
956
+ font-weight: var(--font-weight-semibold);
957
+ }
958
+
959
+ .value-prop p {
960
+ font-size: var(--font-size-md);
961
+ color: var(--color-text-secondary);
962
+ line-height: 1.5;
963
+ }
964
+
965
+ /* Flow diagram */
966
+ .flow-diagram {
967
+ display: flex;
968
+ flex-direction: column;
969
+ gap: var(--space-16);
970
+ margin-bottom: var(--space-24);
971
+ }
972
+
973
+ .flow-step {
974
+ display: flex;
975
+ align-items: center;
976
+ gap: var(--space-20);
977
+ padding: var(--space-16);
978
+ background-color: var(--color-background);
979
+ border-radius: var(--radius-base);
980
+ border-left: 4px solid var(--color-primary);
981
+ box-shadow: var(--shadow-sm);
982
+ }
983
+
984
+ .step-number {
985
+ width: 50px;
986
+ height: 50px;
987
+ border-radius: 50%;
988
+ background-color: var(--color-primary);
989
+ color: var(--color-btn-primary-text);
990
+ display: flex;
991
+ justify-content: center;
992
+ align-items: center;
993
+ font-weight: var(--font-weight-bold);
994
+ font-size: var(--font-size-xl);
995
+ flex-shrink: 0;
996
+ }
997
+
998
+ .step-content h4 {
999
+ margin-bottom: var(--space-8);
1000
+ font-size: var(--font-size-lg);
1001
+ font-weight: var(--font-weight-semibold);
1002
+ }
1003
+
1004
+ .step-content p {
1005
+ color: var(--color-text-secondary);
1006
+ font-size: var(--font-size-md);
1007
+ line-height: 1.5;
1008
+ }
1009
+
1010
+ /* Images */
1011
+ .slide-image-container {
1012
+ margin-top: var(--space-24);
1013
+ text-align: center;
1014
+ }
1015
+
1016
+ .slide-image, .flow-image, .architecture-image, .tech-diagram, .market-image {
1017
+ max-width: 100%;
1018
+ height: auto;
1019
+ border-radius: var(--radius-base);
1020
+ max-height: 300px;
1021
+ object-fit: cover;
1022
+ box-shadow: var(--shadow-sm);
1023
+ }
1024
+
1025
+ /* Architecture diagram */
1026
+ .architecture-diagram {
1027
+ text-align: center;
1028
+ margin-bottom: var(--space-24);
1029
+ }
1030
+
1031
+ .architecture-details h3 {
1032
+ text-align: center;
1033
+ margin-bottom: var(--space-16);
1034
+ font-size: var(--font-size-xl);
1035
+ font-weight: var(--font-weight-semibold);
1036
+ }
1037
+
1038
+ .states-container {
1039
+ display: flex;
1040
+ justify-content: center;
1041
+ align-items: center;
1042
+ flex-wrap: wrap;
1043
+ gap: var(--space-8);
1044
+ margin-top: var(--space-16);
1045
+ }
1046
+
1047
+ .state {
1048
+ padding: var(--space-8) var(--space-16);
1049
+ background-color: var(--color-primary);
1050
+ color: var(--color-btn-primary-text);
1051
+ border-radius: var(--radius-base);
1052
+ font-size: var(--font-size-md);
1053
+ font-weight: var(--font-weight-medium);
1054
+ }
1055
+
1056
+ .state-arrow {
1057
+ font-size: var(--font-size-xl);
1058
+ color: var(--color-text-secondary);
1059
+ margin: 0 var(--space-4);
1060
+ }
1061
+
1062
+ /* Feature matrix */
1063
+ .capability-container {
1064
+ display: grid;
1065
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
1066
+ gap: var(--space-24);
1067
+ margin-bottom: var(--space-24);
1068
+ }
1069
+
1070
+ .capability-section h3 {
1071
+ font-size: var(--font-size-xl);
1072
+ margin-bottom: var(--space-16);
1073
+ color: var(--color-text);
1074
+ border-bottom: 2px solid var(--color-border);
1075
+ padding-bottom: var(--space-8);
1076
+ font-weight: var(--font-weight-semibold);
1077
+ }
1078
+
1079
+ .feature-matrix h3 {
1080
+ font-size: var(--font-size-xl);
1081
+ margin-bottom: var(--space-16);
1082
+ text-align: center;
1083
+ font-weight: var(--font-weight-semibold);
1084
+ }
1085
+
1086
+ .feature-difficulty {
1087
+ display: grid;
1088
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
1089
+ gap: var(--space-16);
1090
+ }
1091
+
1092
+ .difficulty-container {
1093
+ padding: var(--space-16);
1094
+ border-radius: var(--radius-base);
1095
+ border: 1px solid var(--color-border);
1096
+ background-color: var(--color-surface);
1097
+ }
1098
+
1099
+ .difficulty-level {
1100
+ margin-bottom: var(--space-16);
1101
+ font-size: var(--font-size-lg);
1102
+ text-align: center;
1103
+ padding: var(--space-8) var(--space-12);
1104
+ border-radius: var(--radius-base);
1105
+ font-weight: var(--font-weight-semibold);
1106
+ }
1107
+
1108
+ .difficulty-level.green {
1109
+ background-color: rgba(33, 128, 141, 0.1);
1110
+ color: #1FB8CD;
1111
+ border: 1px solid rgba(33, 128, 141, 0.3);
1112
+ }
1113
+
1114
+ .difficulty-level.yellow {
1115
+ background-color: rgba(210, 186, 76, 0.1);
1116
+ color: #D2BA4C;
1117
+ border: 1px solid rgba(210, 186, 76, 0.3);
1118
+ }
1119
+
1120
+ .difficulty-level.red {
1121
+ background-color: rgba(180, 65, 60, 0.1);
1122
+ color: #B4413C;
1123
+ border: 1px solid rgba(180, 65, 60, 0.3);
1124
+ }
1125
+
1126
+ /* Tech stack */
1127
+ .tech-stack-container {
1128
+ display: grid;
1129
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1130
+ gap: var(--space-20);
1131
+ margin-bottom: var(--space-24);
1132
+ }
1133
+
1134
+ .tech-component {
1135
+ text-align: center;
1136
+ padding: var(--space-20);
1137
+ border: 1px solid var(--color-border);
1138
+ border-radius: var(--radius-base);
1139
+ background-color: var(--color-background);
1140
+ box-shadow: var(--shadow-sm);
1141
+ }
1142
+
1143
+ .tech-icon {
1144
+ font-size: 36px;
1145
+ margin-bottom: var(--space-12);
1146
+ }
1147
+
1148
+ .tech-component h3 {
1149
+ font-size: var(--font-size-lg);
1150
+ margin-bottom: var(--space-8);
1151
+ font-weight: var(--font-weight-semibold);
1152
+ }
1153
+
1154
+ .tech-component p {
1155
+ font-size: var(--font-size-md);
1156
+ color: var(--color-text-secondary);
1157
+ line-height: 1.4;
1158
+ }
1159
+
1160
+ /* Phase details */
1161
+ .phase-details {
1162
+ display: flex;
1163
+ flex-direction: column;
1164
+ gap: var(--space-24);
1165
+ }
1166
+
1167
+ .phase-content {
1168
+ display: grid;
1169
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1170
+ gap: var(--space-16);
1171
+ margin-bottom: var(--space-16);
1172
+ }
1173
+
1174
+ .phase-stat {
1175
+ text-align: center;
1176
+ padding: var(--space-16);
1177
+ background-color: var(--color-background);
1178
+ border-radius: var(--radius-base);
1179
+ border: 1px solid var(--color-border);
1180
+ }
1181
+
1182
+ .phase-stat h3 {
1183
+ font-size: var(--font-size-xl);
1184
+ margin-bottom: var(--space-8);
1185
+ color: var(--color-primary);
1186
+ font-weight: var(--font-weight-semibold);
1187
+ }
1188
+
1189
+ .phase-stat p {
1190
+ font-size: var(--font-size-lg);
1191
+ color: var(--color-text);
1192
+ }
1193
+
1194
+ /* Continue with remaining styles... */
1195
+ .phase-framework h3 {
1196
+ text-align: center;
1197
+ margin-bottom: var(--space-16);
1198
+ font-size: var(--font-size-xl);
1199
+ font-weight: var(--font-weight-semibold);
1200
+ }
1201
+
1202
+ .framework-container {
1203
+ display: grid;
1204
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
1205
+ gap: var(--space-16);
1206
+ }
1207
+
1208
+ .framework-item {
1209
+ padding: var(--space-16);
1210
+ border-radius: var(--radius-base);
1211
+ background-color: var(--color-secondary);
1212
+ border-left: 4px solid var(--color-primary);
1213
+ }
1214
+
1215
+ .framework-item h4 {
1216
+ margin-bottom: var(--space-8);
1217
+ font-size: var(--font-size-lg);
1218
+ font-weight: var(--font-weight-semibold);
1219
+ }
1220
+
1221
+ .framework-item p {
1222
+ font-size: var(--font-size-md);
1223
+ color: var(--color-text-secondary);
1224
+ line-height: 1.5;
1225
+ }
1226
+
1227
+ /* Phases container */
1228
+ .phases-container {
1229
+ display: grid;
1230
+ grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
1231
+ gap: var(--space-24);
1232
+ margin-bottom: var(--space-24);
1233
+ }
1234
+
1235
+ .phase-card {
1236
+ padding: var(--space-20);
1237
+ border-radius: var(--radius-base);
1238
+ background-color: var(--color-background);
1239
+ border: 1px solid var(--color-card-border);
1240
+ box-shadow: var(--shadow-sm);
1241
+ }
1242
+
1243
+ .phase-title {
1244
+ font-size: var(--font-size-xl);
1245
+ margin-bottom: var(--space-8);
1246
+ color: var(--color-text);
1247
+ font-weight: var(--font-weight-semibold);
1248
+ }
1249
+
1250
+ .phase-title.phase-2 {
1251
+ color: #1FB8CD;
1252
+ }
1253
+
1254
+ .phase-title.phase-3 {
1255
+ color: #FFC185;
1256
+ }
1257
+
1258
+ .phase-timeline {
1259
+ font-size: var(--font-size-md);
1260
+ color: var(--color-text-secondary);
1261
+ margin-bottom: var(--space-16);
1262
+ font-weight: var(--font-weight-medium);
1263
+ }
1264
+
1265
+ /* ROI metrics */
1266
+ .roi-metrics {
1267
+ display: grid;
1268
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1269
+ gap: var(--space-16);
1270
+ margin-bottom: var(--space-32);
1271
+ }
1272
+
1273
+ .roi-metric {
1274
+ text-align: center;
1275
+ padding: var(--space-20);
1276
+ background-color: var(--color-background);
1277
+ border-radius: var(--radius-base);
1278
+ border: 1px solid var(--color-border);
1279
+ }
1280
+
1281
+ .roi-metric h3 {
1282
+ font-size: 48px;
1283
+ color: var(--color-primary);
1284
+ margin-bottom: var(--space-8);
1285
+ font-weight: var(--font-weight-bold);
1286
+ }
1287
+
1288
+ .roi-metric p {
1289
+ font-size: var(--font-size-lg);
1290
+ color: var(--color-text);
1291
+ line-height: 1.4;
1292
+ }
1293
+
1294
+ .market-metrics h3 {
1295
+ text-align: center;
1296
+ margin-bottom: var(--space-16);
1297
+ font-size: var(--font-size-xl);
1298
+ font-weight: var(--font-weight-semibold);
1299
+ }
1300
+
1301
+ .market-stats {
1302
+ display: grid;
1303
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
1304
+ gap: var(--space-16);
1305
+ }
1306
+
1307
+ .market-stat {
1308
+ text-align: center;
1309
+ padding: var(--space-16);
1310
+ background-color: var(--color-background);
1311
+ border-radius: var(--radius-base);
1312
+ border: 1px solid var(--color-border);
1313
+ }
1314
+
1315
+ .stat-value {
1316
+ font-size: var(--font-size-2xl);
1317
+ font-weight: var(--font-weight-bold);
1318
+ color: var(--color-text);
1319
+ margin-bottom: var(--space-4);
1320
+ }
1321
+
1322
+ .stat-label {
1323
+ font-size: var(--font-size-md);
1324
+ color: var(--color-text-secondary);
1325
+ line-height: 1.4;
1326
+ }
1327
+
1328
+ /* Challenges */
1329
+ .challenges-container {
1330
+ display: flex;
1331
+ flex-direction: column;
1332
+ gap: var(--space-24);
1333
+ }
1334
+
1335
+ .challenge-category {
1336
+ padding: var(--space-20);
1337
+ border-radius: var(--radius-base);
1338
+ background-color: var(--color-background);
1339
+ border: 1px solid var(--color-card-border);
1340
+ }
1341
+
1342
+ .category-title {
1343
+ font-size: var(--font-size-xl);
1344
+ margin-bottom: var(--space-16);
1345
+ padding-bottom: var(--space-8);
1346
+ border-bottom: 3px solid;
1347
+ font-weight: var(--font-weight-semibold);
1348
+ }
1349
+
1350
+ .category-title.technical {
1351
+ border-color: #1FB8CD;
1352
+ color: #1FB8CD;
1353
+ }
1354
+
1355
+ .category-title.business {
1356
+ border-color: #FFC185;
1357
+ color: #FFC185;
1358
+ }
1359
+
1360
+ .category-title.operational {
1361
+ border-color: #B4413C;
1362
+ color: #B4413C;
1363
+ }
1364
+
1365
+ .challenge-items {
1366
+ display: grid;
1367
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1368
+ gap: var(--space-16);
1369
+ }
1370
+
1371
+ .challenge-item {
1372
+ padding: var(--space-16);
1373
+ background-color: var(--color-secondary);
1374
+ border-radius: var(--radius-base);
1375
+ border: 1px solid var(--color-border);
1376
+ }
1377
+
1378
+ .challenge-item h4 {
1379
+ margin-bottom: var(--space-8);
1380
+ font-size: var(--font-size-md);
1381
+ font-weight: var(--font-weight-semibold);
1382
+ }
1383
+
1384
+ .challenge-item p {
1385
+ font-size: var(--font-size-sm);
1386
+ color: var(--color-text-secondary);
1387
+ line-height: 1.4;
1388
+ }
1389
+
1390
+ /* Market position */
1391
+ .market-content {
1392
+ display: grid;
1393
+ grid-template-columns: repeat(2, 1fr);
1394
+ gap: var(--space-24);
1395
+ margin-bottom: var(--space-24);
1396
+ }
1397
+
1398
+ .advantages-section {
1399
+ grid-column: span 2;
1400
+ }
1401
+
1402
+ .market-section h3, .advantages-section h3 {
1403
+ font-size: var(--font-size-xl);
1404
+ margin-bottom: var(--space-16);
1405
+ padding-bottom: var(--space-8);
1406
+ border-bottom: 2px solid var(--color-border);
1407
+ font-weight: var(--font-weight-semibold);
1408
+ }
1409
+
1410
+ .advantages-container {
1411
+ display: grid;
1412
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
1413
+ gap: var(--space-16);
1414
+ }
1415
+
1416
+ .advantage {
1417
+ padding: var(--space-16);
1418
+ background-color: rgba(31, 184, 205, 0.05);
1419
+ border-radius: var(--radius-base);
1420
+ border-left: 4px solid #1FB8CD;
1421
+ border: 1px solid rgba(31, 184, 205, 0.2);
1422
+ }
1423
+
1424
+ .advantage h4 {
1425
+ margin-bottom: var(--space-8);
1426
+ font-size: var(--font-size-lg);
1427
+ font-weight: var(--font-weight-semibold);
1428
+ }
1429
+
1430
+ .advantage p {
1431
+ font-size: var(--font-size-md);
1432
+ color: var(--color-text-secondary);
1433
+ line-height: 1.4;
1434
+ }
1435
+
1436
+ /* Conclusion */
1437
+ .conclusion-content {
1438
+ display: flex;
1439
+ flex-direction: column;
1440
+ gap: var(--space-24);
1441
+ }
1442
+
1443
+ .recommendations h3, .timeline-section h3 {
1444
+ margin-bottom: var(--space-16);
1445
+ font-size: var(--font-size-xl);
1446
+ font-weight: var(--font-weight-semibold);
1447
+ }
1448
+
1449
+ .timeline {
1450
+ display: flex;
1451
+ flex-direction: column;
1452
+ gap: var(--space-12);
1453
+ }
1454
+
1455
+ .timeline-item {
1456
+ display: flex;
1457
+ gap: var(--space-16);
1458
+ padding: var(--space-12) 0;
1459
+ border-left: 3px solid var(--color-primary);
1460
+ padding-left: var(--space-16);
1461
+ }
1462
+
1463
+ .timeline-date {
1464
+ font-weight: var(--font-weight-bold);
1465
+ min-width: 120px;
1466
+ color: var(--color-primary);
1467
+ }
1468
+
1469
+ .call-to-action {
1470
+ display: flex;
1471
+ flex-direction: column;
1472
+ align-items: center;
1473
+ gap: var(--space-16);
1474
+ margin-top: var(--space-24);
1475
+ padding: var(--space-24);
1476
+ background-color: var(--color-background);
1477
+ border-radius: var(--radius-base);
1478
+ border: 1px solid var(--color-border);
1479
+ }
1480
+
1481
+ .call-to-action h3 {
1482
+ margin-bottom: var(--space-8);
1483
+ font-size: var(--font-size-xl);
1484
+ text-align: center;
1485
+ font-weight: var(--font-weight-semibold);
1486
+ }
1487
+
1488
+ .call-to-action .btn {
1489
+ min-width: 300px;
1490
+ margin-bottom: var(--space-8);
1491
+ }
1492
+
1493
+ /* Media queries for responsiveness */
1494
+ @media (max-width: 768px) {
1495
+ .slide {
1496
+ padding: var(--space-16);
1497
+ }
1498
+
1499
+ .slide-content {
1500
+ padding: var(--space-20);
1501
+ min-height: auto;
1502
+ }
1503
+
1504
+ .main-title {
1505
+ font-size: 36px;
1506
+ }
1507
+
1508
+ .bullet-points {
1509
+ font-size: var(--font-size-md);
1510
+ padding-left: var(--space-16);
1511
+ }
1512
+
1513
+ .two-column-layout, .market-content {
1514
+ grid-template-columns: 1fr;
1515
+ }
1516
+
1517
+ .advantages-section {
1518
+ grid-column: span 1;
1519
+ }
1520
+
1521
+ .highlight-container {
1522
+ flex-direction: column;
1523
+ align-items: center;
1524
+ }
1525
+
1526
+ .presentation-controls {
1527
+ bottom: 10px;
1528
+ gap: var(--space-8);
1529
+ padding: var(--space-6) var(--space-12);
1530
+ }
1531
+
1532
+ .states-container {
1533
+ flex-direction: column;
1534
+ align-items: center;
1535
+ }
1536
+
1537
+ .state-arrow {
1538
+ transform: rotate(90deg);
1539
+ }
1540
+ }
1541
+
1542
+ /* Fullscreen mode */
1543
+ .fullscreen {
1544
+ position: fixed;
1545
+ top: 0;
1546
+ left: 0;
1547
+ width: 100vw;
1548
+ height: 100vh;
1549
+ background-color: var(--color-background);
1550
+ z-index: 1000;
1551
+ overflow: hidden;
1552
+ }
1553
+
1554
+ /* Animation classes */
1555
+ .animate-in {
1556
+ animation: slideInFromRight 0.5s ease forwards;
1557
+ }
1558
+
1559
+ @keyframes slideInFromRight {
1560
+ from {
1561
+ opacity: 0;
1562
+ transform: translateX(30px);
1563
+ }
1564
+ to {
1565
+ opacity: 1;
1566
+ transform: translateX(0);
1567
+ }
1568
+ }
1569
+
1570
+ /* Button disabled state */
1571
+ .btn:disabled {
1572
+ opacity: 0.5;
1573
+ cursor: not-allowed;
1574
+ pointer-events: none;
1575
+ }
__pycache__/agent.cpython-312.pyc ADDED
Binary file (3.58 kB). View file
 
__pycache__/sticky.cpython-312.pyc ADDED
Binary file (1.36 kB). View file
 
__pycache__/sticky.cpython-313.pyc ADDED
Binary file (1.36 kB). View file
 
__pycache__/tools.cpython-312.pyc ADDED
Binary file (7.4 kB). View file
 
__pycache__/tools.cpython-313.pyc ADDED
Binary file (15.2 kB). View file
 
__pycache__/ui_utils.cpython-312.pyc ADDED
Binary file (6 kB). View file
 
__pycache__/var.cpython-313.pyc ADDED
Binary file (7.81 kB). View file
 
app.py ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from openai import OpenAI
3
+ import sqlite3
4
+ import pandas as pd
5
+ import re
6
+ import json
7
+ from sticky import sticky_container
8
+ import chromadb
9
+ from sentence_transformers import SentenceTransformer
10
+ from transformers import pipeline
11
+ import hashlib
12
+ import inspect
13
+ from tools import *
14
+ from var import SCHEMA_DESCRIPTIONS, SchemaVectorDB, FullVectorDB
15
+ import os
16
+ from dotenv import load_dotenv
17
+ load_dotenv()
18
+
19
+ # Set your Groq API key
20
+ GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
21
+
22
+ # Initialize Groq's OpenAI-compatible client
23
+ client = OpenAI(
24
+ api_key=GROQ_API_KEY,
25
+ base_url="https://api.groq.com/openai/v1"
26
+ )
27
+
28
+ # --- Load prompt templates from prompts folder ---
29
+ with open("prompts/determine_intent.txt", "r", encoding="utf-8") as f:
30
+ determine_intent_prompt = f.read()
31
+
32
+ with open("prompts/generate_reservation_conversation.txt", "r", encoding="utf-8") as f:
33
+ generate_reservation_conversation_prompt = f.read()
34
+
35
+ with open("prompts/interpret_sql_result.txt", "r", encoding="utf-8") as f:
36
+ interpret_sql_result_prompt = f.read()
37
+
38
+ with open("prompts/schema_prompt.txt", "r", encoding="utf-8") as f:
39
+ schema_prompt = f.read()
40
+
41
+ with open("prompts/store_user_info.txt", "r", encoding="utf-8") as f:
42
+ store_user_info_prompt = f.read()
43
+
44
+
45
+
46
+ st.set_page_config(page_title="FoodieSpot Assistant", layout="wide")
47
+
48
+
49
+ # --- Initialize State ---
50
+ if 'chat_history' not in st.session_state:
51
+ st.session_state.chat_history = []
52
+
53
+ if 'user_data' not in st.session_state:
54
+ st.session_state.user_data = {
55
+ "restaurant_name": None,
56
+ "user_name": None,
57
+ "contact": None,
58
+ "party_size": None,
59
+ "time": None
60
+ }
61
+ if 'vector_db' not in st.session_state:
62
+ st.session_state.vector_db = SchemaVectorDB()
63
+ vector_db = st.session_state.vector_db
64
+ if 'full_vector_db' not in st.session_state:
65
+ st.session_state.full_vector_db = FullVectorDB()
66
+ # Track last assistant reply for context
67
+ if 'last_assistant_reply' not in st.session_state:
68
+ st.session_state.last_assistant_reply = ""
69
+ # Fixed container at top for title + reservation
70
+ reservation_box = sticky_container(mode="top", border=False,z=999)
71
+
72
+ with reservation_box:
73
+ st.text("")
74
+ st.text("")
75
+ st.title("🍽️ FoodieSpot Assistant")
76
+ cols = st.columns([3, 3, 3, 2, 2, 1])
77
+
78
+ with cols[0]:
79
+ restaurant_name = st.text_input(
80
+ "Restaurant Name",
81
+ value=st.session_state.user_data.get("restaurant_name") or "",
82
+ key="restaurant_name_input"
83
+ )
84
+ if restaurant_name!="":
85
+ st.session_state.user_data["restaurant_name"] = restaurant_name
86
+
87
+ with cols[1]:
88
+ user_name = st.text_input(
89
+ "Your Name",
90
+ value=st.session_state.user_data.get("user_name") or "",
91
+ key="user_name_input"
92
+ )
93
+ if user_name!="":
94
+ st.session_state.user_data["user_name"] = user_name
95
+
96
+ with cols[2]:
97
+ contact = st.text_input(
98
+ "Contact",
99
+ value=st.session_state.user_data.get("contact") or "",
100
+ key="contact_input"
101
+ )
102
+ if contact!="":
103
+ st.session_state.user_data["contact"] = contact
104
+
105
+ with cols[3]:
106
+ party_size = st.number_input(
107
+ "Party Size",
108
+ value=st.session_state.user_data.get("party_size") or 0,
109
+ key="party_size_input"
110
+ )
111
+ if party_size!=0:
112
+ st.session_state.user_data["party_size"] = party_size
113
+
114
+ with cols[4]:
115
+ time = st.number_input(
116
+ "Time(24hr form, 9-20, 8 ~ null)",
117
+ min_value=8,
118
+ max_value=20,
119
+ value=st.session_state.user_data.get("time") or 8,
120
+ key="time_input"
121
+ )
122
+ if time!=8:
123
+ st.session_state.user_data["time"] = time
124
+ # Place the BOOK button in the last column
125
+ with cols[5]:
126
+ st.text("")
127
+ st.text("")
128
+ book_clicked = st.button("BOOK", type="primary")
129
+ # Add a green BOOK button (primary style)
130
+ # book_clicked = st.button("BOOK", type="primary")
131
+
132
+ if book_clicked:
133
+ # Check if all required fields are filled
134
+ required_keys = ["restaurant_name", "user_name", "contact", "party_size", "time"]
135
+ if all(st.session_state.user_data.get(k) not in [None, "", 0, 8] for k in required_keys):
136
+ booking_conn = None
137
+ try:
138
+ user_data = st.session_state.user_data
139
+ party_size = int(user_data["party_size"])
140
+ tables_needed = -(-party_size // 4)
141
+
142
+ booking_conn = sqlite3.connect("db/restaurant_reservation.db")
143
+ booking_cursor = booking_conn.cursor()
144
+
145
+ booking_cursor.execute("SELECT id FROM restaurants WHERE LOWER(name) = LOWER(?)", (user_data["restaurant_name"],))
146
+ restaurant_row = booking_cursor.fetchone()
147
+ if not restaurant_row:
148
+ raise Exception("Restaurant not found.")
149
+ restaurant_id = restaurant_row[0]
150
+
151
+ booking_cursor.execute("""
152
+ SELECT t.id AS table_id, s.id AS slot_id
153
+ FROM tables t
154
+ JOIN slots s ON t.id = s.table_id
155
+ WHERE t.restaurant_id = ?
156
+ AND s.hour = ?
157
+ AND s.date = '2025-05-12'
158
+ AND s.is_reserved = 0
159
+ LIMIT ?
160
+ """, (restaurant_id, user_data["time"], tables_needed))
161
+ available = booking_cursor.fetchall()
162
+
163
+ if len(available) < tables_needed:
164
+ raise Exception("Not enough available tables.")
165
+
166
+ booking_cursor.execute("""
167
+ INSERT INTO reservations (restaurant_id, user_name, contact, date, time, party_size)
168
+ VALUES (?, ?, ?, '2025-05-12', ?, ?)
169
+ """, (restaurant_id, user_data["user_name"], user_data["contact"], user_data["time"], party_size))
170
+ reservation_id = booking_cursor.lastrowid
171
+
172
+ for table_id, _ in available:
173
+ booking_cursor.execute("INSERT INTO reservation_tables (reservation_id, table_id) VALUES (?, ?)", (reservation_id, table_id))
174
+
175
+ slot_ids = [slot_id for _, slot_id in available]
176
+ booking_cursor.executemany("UPDATE slots SET is_reserved = 1 WHERE id = ?", [(sid,) for sid in slot_ids])
177
+
178
+ booking_conn.commit()
179
+
180
+ booking_cursor.execute("SELECT name FROM restaurants WHERE id = ?", (restaurant_id,))
181
+ restaurant_name = booking_cursor.fetchone()[0]
182
+
183
+ confirmation_msg = (
184
+ f"βœ… Booking processed successfully!\n\n"
185
+ f"πŸ“ Restaurant: **{restaurant_name}**\n"
186
+ f"⏰ Time: **{user_data['time']} on 2025-05-12**\n"
187
+ f"🍽️ Tables Booked: **{tables_needed}**\n"
188
+ f"πŸ†” Reservation ID: **{reservation_id}**\n\n"
189
+ f"πŸ‘‰ Please mention this Reservation ID at the restaurant reception when you arrive."
190
+ )
191
+
192
+ st.success(confirmation_msg)
193
+ st.session_state.chat_history.append({'role': 'assistant', 'message': confirmation_msg})
194
+ st.session_state.user_data["restaurant_name"] = None
195
+ st.session_state.user_data["party_size"] = None
196
+ st.session_state.user_data["time"] = None
197
+ st.session_state.last_assistant_reply = ""
198
+ except Exception as e:
199
+ if booking_conn:
200
+ booking_conn.rollback()
201
+ st.error(f"❌ Booking failed: {e}")
202
+ finally:
203
+ if booking_conn:
204
+ booking_cursor = None
205
+ booking_conn.close()
206
+ else:
207
+ st.warning("⚠️ Missing user information. Please provide all booking details first.")
208
+ st.text("")
209
+ # Inject custom CSS for smaller font and tighter layout
210
+ st.markdown("""
211
+ <style>
212
+ .element-container:has(.streamlit-expander) {
213
+ margin-bottom: 0.5rem;
214
+ }
215
+ .streamlit-expanderHeader {
216
+ font-size: 0.9rem;
217
+ }
218
+ .streamlit-expanderContent {
219
+ font-size: 0.85rem;
220
+ padding: 0.5rem 1rem;
221
+ }
222
+ </style>
223
+ """, unsafe_allow_html=True)
224
+
225
+ with st.container():
226
+ col1, col2, col3 = st.columns(3)
227
+
228
+ with col1:
229
+ with st.expander("🍽️ Restaurants"):
230
+ st.markdown("""
231
+ - Bella Italia
232
+ - Spice Symphony
233
+ - Tokyo Ramen House
234
+ - Saffron Grill
235
+ - El Toro Loco
236
+ - Noodle Bar
237
+ - Le Petit Bistro
238
+ - Tandoori Nights
239
+ - Green Leaf Cafe
240
+ - Ocean Pearl
241
+ - Mama Mia Pizza
242
+ - The Dumpling Den
243
+ - Bangkok Express
244
+ - Curry Kingdom
245
+ - The Garden Table
246
+ - Skyline Dine
247
+ - Pasta Republic
248
+ - Street Tacos Co
249
+ - Miso Hungry
250
+ - Chez Marie
251
+ """)
252
+
253
+ with col2:
254
+ with st.expander("🌎 Cuisines"):
255
+ st.markdown("""
256
+ - Italian
257
+ - French
258
+ - Chinese
259
+ - Japanese
260
+ - Indian
261
+ - Mexican
262
+ - Thai
263
+ - Healthy
264
+ - Fusion
265
+ """)
266
+
267
+ with col3:
268
+ with st.expander("✨ Special Features"):
269
+ st.markdown("""
270
+ - Pet-Friendly
271
+ - Live Music
272
+ - Rooftop View
273
+ - Outdoor Seating
274
+ - Private Dining
275
+ """)
276
+
277
+
278
+
279
+
280
+ # --- Display previous chat history (before new input) ---
281
+
282
+ for msg in st.session_state.chat_history:
283
+ # Check if both 'role' and 'message' are not None
284
+ if msg['role'] is not None and msg['message'] is not None:
285
+ with st.chat_message(msg['role']):
286
+ st.markdown(msg['message'])
287
+
288
+ user_input = st.chat_input("Ask something about restaurants or reservations(eg. Tell me some best rated Italian cuisine restaurants)...")
289
+ if user_input:
290
+ # Show user message instantly
291
+ with st.chat_message("user"):
292
+ st.markdown(user_input)
293
+ st.session_state.chat_history.append({'role': 'user', 'message': user_input})
294
+
295
+ # Prepare conversation context
296
+ history_prompt = st.session_state.last_assistant_reply
297
+
298
+ # Store possible user info
299
+ user_info = store_user_info(user_input,history_prompt,store_user_info_prompt,client)
300
+ if user_info:
301
+ st.session_state.user_data.update(user_info)
302
+ # st.rerun()
303
+
304
+ # Detect intent
305
+ intent = determine_intent(user_input,determine_intent_prompt,client)
306
+ # st.write(intent)
307
+ if intent == "RUBBISH":
308
+ # Display user data for confirmation instead of invoking LLM
309
+ with st.chat_message("assistant"):
310
+ st.markdown("❌ Sorry, I didn't understand that. Could you rephrase your request?")
311
+ st.session_state.chat_history.append({
312
+ 'role': 'assistant',
313
+ 'message': "❌ Sorry, I didn't understand that. Could you rephrase your request?"
314
+ })
315
+
316
+ st.stop()
317
+
318
+ # Generate assistant reply
319
+ required_keys = ["restaurant_name", "user_name", "contact", "party_size", "time"]
320
+ user_data_complete = all(
321
+ k in st.session_state.user_data and st.session_state.user_data[k] not in [None, "", "NULL"]
322
+ for k in required_keys
323
+ )
324
+
325
+
326
+ if user_data_complete and intent != "BOOK":
327
+
328
+ # Format user data as a Markdown bullet list
329
+ user_details = "\n".join([f"- **{key.capitalize()}**: {value}" for key, value in st.session_state.user_data.items()])
330
+
331
+ with st.chat_message("assistant"):
332
+ st.markdown("βœ… I have all the details needed for your reservation:")
333
+ st.markdown(user_details)
334
+ st.markdown("If everything looks good, please type **`book`** to confirm the reservation.")
335
+
336
+ st.session_state.chat_history.append({
337
+ 'role': 'assistant',
338
+ 'message': f"βœ… I have all the details needed for your reservation:\n{user_details}\nPlease type **`book`** to confirm."
339
+ })
340
+ st.session_state.last_assistant_reply = "I have all the reservation details. Waiting for confirmation..."
341
+ st.rerun()
342
+ st.stop()
343
+
344
+
345
+
346
+
347
+ response_summary = None
348
+
349
+ if intent == "SELECT":
350
+ response_summary=handle_query(user_input, st.session_state.full_vector_db, client)
351
+
352
+ # First try semantic search
353
+ semantic_results = {}
354
+
355
+ # Search across all collections
356
+ restaurant_results = st.session_state.full_vector_db.semantic_search(user_input, "restaurants")
357
+ table_results = st.session_state.full_vector_db.semantic_search(user_input, "tables")
358
+ slot_results = st.session_state.full_vector_db.semantic_search(user_input, "slots")
359
+
360
+ if not is_large_output_request(user_input) and any([restaurant_results, table_results, slot_results]):
361
+ semantic_results = {
362
+ "restaurants": restaurant_results,
363
+ "tables": table_results,
364
+ "slots": slot_results
365
+ }
366
+ # Format semantic results
367
+ summary = []
368
+ for category, items in semantic_results.items():
369
+ if items:
370
+ summary.append(f"Found {len(items)} relevant {category}:")
371
+ summary.extend([f"- {item['name']}" if 'name' in item else f"- {item}"
372
+ for item in items[:3]])
373
+ st.write("### Semantic Search used")
374
+ response_summary = "\n".join(summary)
375
+ else:
376
+ # Fall back to SQL generation for large or exact output requests
377
+ sql = generate_sql_query_v2(user_input,SCHEMA_DESCRIPTIONS, history_prompt, vector_db, client)
378
+ result = execute_query(sql)
379
+ response_summary = interpret_result_v2(result, user_input, sql)
380
+
381
+
382
+
383
+ # sql = generate_sql_query_v2(user_input,history_prompt, vector_db, client)
384
+ # result = execute_query(sql)
385
+ # response_summary=interpret_result_v2(result, user_input, sql)
386
+ # if isinstance(result, pd.DataFrame):
387
+ # response_summary = interpret_sql_result(user_input, sql_query, result)
388
+
389
+
390
+ elif intent == "BOOK":
391
+ required_keys = ["restaurant_name", "user_name", "contact", "party_size", "time"]
392
+ if all(st.session_state.user_data.get(k) is not None for k in required_keys):
393
+ booking_conn = None
394
+ try:
395
+ user_data = st.session_state.user_data
396
+ party_size = int(user_data["party_size"])
397
+ tables_needed = -(-party_size // 4)
398
+
399
+ booking_conn = sqlite3.connect("db/restaurant_reservation.db")
400
+ booking_cursor = booking_conn.cursor()
401
+
402
+ booking_cursor.execute("SELECT id FROM restaurants WHERE LOWER(name) = LOWER(?)", (user_data["restaurant_name"],))
403
+ restaurant_row = booking_cursor.fetchone()
404
+ if not restaurant_row:
405
+ raise Exception("Restaurant not found.")
406
+ restaurant_id = restaurant_row[0]
407
+
408
+ booking_cursor.execute("""
409
+ SELECT t.id AS table_id, s.id AS slot_id
410
+ FROM tables t
411
+ JOIN slots s ON t.id = s.table_id
412
+ WHERE t.restaurant_id = ?
413
+ AND s.hour = ?
414
+ AND s.date = '2025-05-12'
415
+ AND s.is_reserved = 0
416
+ LIMIT ?
417
+ """, (restaurant_id, user_data["time"], tables_needed))
418
+ available = booking_cursor.fetchall()
419
+ # Debugging output
420
+
421
+ if len(available) < tables_needed:
422
+ raise Exception("Not enough available tables.")
423
+
424
+ booking_cursor.execute("""
425
+ INSERT INTO reservations (restaurant_id, user_name, contact, date, time, party_size)
426
+ VALUES (?, ?, ?, '2025-05-12', ?, ?)
427
+ """, (restaurant_id, user_data["user_name"], user_data["contact"], user_data["time"], party_size))
428
+ reservation_id = booking_cursor.lastrowid
429
+
430
+ for table_id, _ in available:
431
+ booking_cursor.execute("INSERT INTO reservation_tables (reservation_id, table_id) VALUES (?, ?)", (reservation_id, table_id))
432
+
433
+ slot_ids = [slot_id for _, slot_id in available]
434
+ booking_cursor.executemany("UPDATE slots SET is_reserved = 1 WHERE id = ?", [(sid,) for sid in slot_ids])
435
+
436
+ booking_conn.commit()
437
+ # Fetch the restaurant name to confirm
438
+ booking_cursor.execute("SELECT name FROM restaurants WHERE id = ?", (restaurant_id,))
439
+ restaurant_name = booking_cursor.fetchone()[0]
440
+
441
+ # Prepare confirmation details
442
+ confirmation_msg = (
443
+ f"βœ… Booking processed successfully!\n\n"
444
+ f"πŸ“ Restaurant: **{restaurant_name}**\n"
445
+ f"⏰ Time: **{user_data['time']} on 2025-05-12**\n"
446
+ f"🍽️ Tables Booked: **{tables_needed}**\n"
447
+ f"πŸ†” Reservation ID: **{reservation_id}**\n\n"
448
+ f"πŸ‘‰ Please mention this Reservation ID at the restaurant reception when you arrive."
449
+ )
450
+
451
+ response_summary = confirmation_msg
452
+ st.success(response_summary)
453
+ st.session_state.chat_history.append({'role': 'assistant', 'message': response_summary})
454
+ response_summary="βœ… Booking processed successfully."
455
+ st.session_state.user_data["restaurant_name"]=None
456
+ st.session_state.user_data["party_size"]=None
457
+ st.session_state.user_data["time"]=None
458
+ st.session_state.last_assistant_reply=""
459
+ except Exception as e:
460
+ if booking_conn:
461
+ booking_conn.rollback()
462
+ response_summary = f"❌ Booking failed: {e}"
463
+ st.error(response_summary)
464
+ finally:
465
+ if booking_conn:
466
+ booking_cursor=None
467
+ booking_conn.close()
468
+ else:
469
+ st.markdown("⚠️ Missing user information. Please provide all booking details first.")
470
+ response_summary = "⚠️ Missing user information. Please provide all booking details first."
471
+
472
+
473
+ elif intent == "GREET":
474
+ response_summary = "πŸ‘‹ Hello! How can I help you with your restaurant reservation today?"
475
+
476
+ elif intent == "RUBBISH":
477
+ response_summary = "❌ Sorry, I didn't understand that. Could you rephrase your request?"
478
+
479
+ # Generate assistant reply
480
+ if response_summary!="βœ… Booking processed successfully.":
481
+ follow_up = generate_reservation_conversation(
482
+ user_input,
483
+ history_prompt,
484
+ response_summary or "Info stored.",
485
+ json.dumps(st.session_state.user_data),generate_reservation_conversation_prompt,client
486
+ )
487
+ else:
488
+ follow_up="Thanks for booking with FoodieSpot restaurant chain, I could assist you in new booking, also I could tell about restaurant features, pricing, etc... "
489
+
490
+ # Show assistant reply instantly
491
+ with st.chat_message("assistant"):
492
+ st.markdown(follow_up)
493
+
494
+ st.session_state.chat_history.append({'role': 'assistant', 'message': follow_up})
495
+ # Update it after assistant speaks
496
+ st.session_state.last_assistant_reply = follow_up
497
+ st.rerun()
498
+ # Reset if booking done
499
+
500
+
assets/all_resto.png ADDED

Git LFS Details

  • SHA256: 75439b4abe2272f6022a16cc3705287f423d5907409dca18c4bb329edd9fcf68
  • Pointer size: 131 Bytes
  • Size of remote file: 177 kB
assets/booking_successful.png ADDED

Git LFS Details

  • SHA256: 405e43a9a4a6bdb24e0ad26bcd56a26e39ec022669bc5e87f0147d6dc6cbe12a
  • Pointer size: 131 Bytes
  • Size of remote file: 135 kB
assets/general_conv_info_through_chat.png ADDED

Git LFS Details

  • SHA256: 937cf76cd735fe0f39ab08b8e66cbb91ab522367e33520c4cae911516916da16
  • Pointer size: 131 Bytes
  • Size of remote file: 152 kB
assets/greet_general_convo.png ADDED

Git LFS Details

  • SHA256: e16d00f649f0d8e4ff797e50cb6422dba3802e3eb63d9c3a5144edaf185a0da3
  • Pointer size: 131 Bytes
  • Size of remote file: 122 kB
assets/landing.png ADDED

Git LFS Details

  • SHA256: fd03aaefe954c0527859cab2c8a74d2d5ea1c9dc18d4a502028807b08989bdf7
  • Pointer size: 131 Bytes
  • Size of remote file: 103 kB
assets/mermaid-1.png ADDED

Git LFS Details

  • SHA256: 372b67dd2b410f2537ab071bbe05b82c77ddb830ccffe54762276e358735a51a
  • Pointer size: 131 Bytes
  • Size of remote file: 600 kB
assets/mermaid.png ADDED

Git LFS Details

  • SHA256: d000eb1764401330a7cf99cfde781faf06f19cbab424bd39e83984576fee466e
  • Pointer size: 131 Bytes
  • Size of remote file: 562 kB
assets/name_entering.png ADDED

Git LFS Details

  • SHA256: 78a06bd163dd9269f0ad572ced2ed6fb31a354b9e3d4920e08885fbb0ec65553
  • Pointer size: 131 Bytes
  • Size of remote file: 124 kB
assets/ready_to_book.png ADDED

Git LFS Details

  • SHA256: 5c805bdcebf89e178565f037a24b97367743985bce7bb93e86e33dd0e99e215b
  • Pointer size: 131 Bytes
  • Size of remote file: 137 kB
assets/rubbish.PNG ADDED

Git LFS Details

  • SHA256: 846c39c6265b506e8e20788333cd8bf0b7e73d52b86139cce92a58588cc31c75
  • Pointer size: 131 Bytes
  • Size of remote file: 102 kB
assets/some_results.PNG ADDED

Git LFS Details

  • SHA256: 2bfb3f7631528ff646eaeeba9cce0b56b612930575b145c3c34167a979a3f4f6
  • Pointer size: 131 Bytes
  • Size of remote file: 146 kB
db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100
db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:861b50c40305a93f26d251878405410518604fff022602201f32d4a4f5139253
3
+ size 40000
db/chroma/0f1c557e-a6e2-45cb-8079-0720b4f2093f/link_lists.bin ADDED
File without changes
db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b8146ecc3e4c3a36ea9b3edc3778630c452f483990ec942d38e8006f4661e430
3
+ size 16760000
db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18f1e924efbb5e1af5201e3fbab86a97f5c195c311abe651eeec525884e5e449
3
+ size 100
db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d5b4759a12671b6d014df975fda1dd7ac0f7c71b4919c679a36bc9f76bc8aaf3
3
+ size 40000
db/chroma/45948c9b-58d5-4762-9fd1-cf9b5925ba84/link_lists.bin ADDED
File without changes
db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/data_level0.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3cdd813c7b938a646786a77ee5e41520302ea0d68cda1b40a41e3e633c7165a8
3
+ size 16760000
db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/header.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:834eaecd974231ba7c9bae46579a2e84cae7acd944d00827cddb0c3cbd1915e4
3
+ size 100
db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/index_metadata.pickle ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:18ec9cba57199ceca85f8017e5eec2047d0538fbeb5024abc3c260ba5ecbedb8
3
+ size 312140
db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:231f5aecbcb787adc68fa2e2f8f9876e22cdca514de5ffc2a9091a4ce5d072ae
3
+ size 40000
db/chroma/b97e1f95-8691-4375-b2f8-2f2e96d82a8c/link_lists.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:34aa97ec388caf3881bf351c822de9a429f610fb3528d766660d616c1e14e88a
3
+ size 25396
db/chroma/chroma.sqlite3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:94eef2082e840a627f17ecdbc0477cc7d9754ebf2663a2f1a039d09b777b8382
3
+ size 5046272
db/create_base.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+
3
+ # Connect to the SQLite database
4
+ conn = sqlite3.connect("restaurant_reservation.db")
5
+ cursor = conn.cursor()
6
+
7
+ # Create tables if they do not exist
8
+ cursor.executescript("""
9
+ CREATE TABLE IF NOT EXISTS restaurants (
10
+ id TEXT PRIMARY KEY,
11
+ name TEXT NOT NULL,
12
+ cuisine TEXT,
13
+ location TEXT,
14
+ seating_capacity INTEGER,
15
+ rating REAL,
16
+ address TEXT,
17
+ contact TEXT,
18
+ price_range TEXT,
19
+ special_features TEXT
20
+ );
21
+
22
+ CREATE TABLE IF NOT EXISTS tables (
23
+ id TEXT PRIMARY KEY,
24
+ restaurant_id TEXT,
25
+ capacity INTEGER DEFAULT 4,
26
+ FOREIGN KEY (restaurant_id) REFERENCES restaurants(id)
27
+ );
28
+
29
+ CREATE TABLE IF NOT EXISTS slots (
30
+ id TEXT PRIMARY KEY,
31
+ table_id TEXT,
32
+ date TEXT,
33
+ hour INTEGER,
34
+ is_reserved INTEGER DEFAULT 0,
35
+ FOREIGN KEY (table_id) REFERENCES tables(id)
36
+ );
37
+
38
+ CREATE TABLE IF NOT EXISTS reservations (
39
+ id TEXT PRIMARY KEY,
40
+ restaurant_id TEXT,
41
+ user_name TEXT,
42
+ contact TEXT,
43
+ date TEXT,
44
+ time INTEGER,
45
+ party_size INTEGER,
46
+ FOREIGN KEY (restaurant_id) REFERENCES restaurants(id)
47
+ );
48
+
49
+ CREATE TABLE IF NOT EXISTS reservation_tables (
50
+ id TEXT PRIMARY KEY,
51
+ reservation_id TEXT,
52
+ table_id TEXT,
53
+ FOREIGN KEY (reservation_id) REFERENCES reservations(id),
54
+ FOREIGN KEY (table_id) REFERENCES tables(id)
55
+ );
56
+ """)
57
+
58
+ # Commit the changes
59
+ conn.commit()
60
+
61
+ # Close the connection
62
+ conn.close()
63
+
64
+ print("Tables have been created successfully!")
db/create_slots.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import uuid
3
+ from datetime import datetime
4
+
5
+ # Connect to your SQLite DB
6
+ conn = sqlite3.connect("restaurant_reservation.db")
7
+ cursor = conn.cursor()
8
+
9
+ # Get all table IDs
10
+ cursor.execute("SELECT id FROM tables")
11
+ table_ids = [row[0] for row in cursor.fetchall()]
12
+
13
+ # Define the time range and current date
14
+ start_hour = 9 # 9AM
15
+ end_hour = 21 # 9PM
16
+
17
+ # Prepare slot entries
18
+ slot_entries = []
19
+ for table_id in table_ids:
20
+ for hour in range(start_hour, end_hour):
21
+ slot_id = str(uuid.uuid4())
22
+ slot_entries.append((slot_id, table_id, "2025-05-12", hour, 0)) # is_reserved = 0
23
+
24
+ # Insert into slots table
25
+ cursor.executemany("""
26
+ INSERT INTO slots (id, table_id, date, hour, is_reserved)
27
+ VALUES (?, ?, ?, ?, ?)
28
+ """, slot_entries)
29
+
30
+ conn.commit()
31
+ conn.close()
32
+
33
+ print("βœ… Slots successfully added for all tables for today.")
db/dbmodify.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import sqlite3
2
+
3
+ # conn = sqlite3.connect("restaurant_reservation.db")
4
+ # cursor = conn.cursor()
5
+
6
+ # # Drop the existing empty tables
7
+ # cursor.execute("DROP TABLE IF EXISTS reservations;")
8
+ # cursor.execute("DROP TABLE IF EXISTS reservation_tables;")
9
+
10
+ # # Recreate the tables with AUTOINCREMENT for `id`
11
+ # cursor.execute("""
12
+ # CREATE TABLE reservations (
13
+ # id INTEGER PRIMARY KEY AUTOINCREMENT,
14
+ # restaurant_id TEXT,
15
+ # user_name TEXT,
16
+ # contact TEXT,
17
+ # date TEXT, -- Hard coded to 2025-05-12
18
+ # time TEXT,
19
+ # party_size INTEGER
20
+ # );
21
+ # """)
22
+
23
+ # cursor.execute("""
24
+ # CREATE TABLE reservation_tables (
25
+ # id INTEGER PRIMARY KEY AUTOINCREMENT,
26
+ # reservation_id TEXT,
27
+ # table_id TEXT
28
+ # );
29
+ # """)
30
+
31
+ # conn.commit()
32
+ # conn.close()
33
+
34
+ # print("Tables recreated successfully with AUTOINCREMENT ids.")
35
+
36
+ import sqlite3
37
+
38
+ conn = sqlite3.connect("restaurant_reservation.db")
39
+ cursor = conn.cursor()
40
+
41
+ try:
42
+ cursor.execute("""
43
+ UPDATE restaurants
44
+ SET name = 'Street Tacos Co'
45
+ WHERE name = 'Street Tacos Co.';
46
+ """)
47
+ conn.commit()
48
+ print("βœ… Restaurant name updated successfully.")
49
+ except Exception as e:
50
+ conn.rollback()
51
+ print(f"❌ Update failed: {e}")
52
+ finally:
53
+ conn.close()
54
+
db/fill_details.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+ import random
3
+ import sqlite3
4
+
5
+ # ---------------------------
6
+ # Data Classes
7
+ # ---------------------------
8
+ class Restaurant:
9
+ def __init__(self, restaurant_id, name, cuisine, location, seating_capacity, rating, address, contact, price_range, special_features):
10
+ self.restaurant_id = restaurant_id
11
+ self.name = name
12
+ self.cuisine = cuisine
13
+ self.location = location
14
+ self.seating_capacity = seating_capacity
15
+ self.rating = rating
16
+ self.address = address
17
+ self.contact = contact
18
+ self.price_range = price_range
19
+ self.special_features = special_features
20
+ self.tables = []
21
+
22
+ class Table:
23
+ def __init__(self, table_id, restaurant_id, capacity=4):
24
+ self.table_id = table_id
25
+ self.restaurant_id = restaurant_id
26
+ self.capacity = capacity
27
+
28
+ # ---------------------------
29
+ # Sample Data
30
+ # ---------------------------
31
+ restaurant_names = [
32
+ "Bella Italia", "Spice Symphony", "Tokyo Ramen House", "Saffron Grill", "El Toro Loco",
33
+ "Noodle Bar", "Le Petit Bistro", "Tandoori Nights", "Green Leaf Cafe", "Ocean Pearl",
34
+ "Mama Mia Pizza", "The Dumpling Den", "Bangkok Express", "Curry Kingdom", "The Garden Table",
35
+ "Skyline Dine", "Pasta Republic", "Street Tacos Co", "Miso Hungry", "Chez Marie"
36
+ ]
37
+
38
+ locations = ['Downtown', 'Uptown', 'Midtown', 'Suburbs']
39
+ special_features_list = ['Outdoor Seating', 'Pet-Friendly', 'Live Music', 'Rooftop View', 'Private Dining']
40
+
41
+ def infer_cuisine(name):
42
+ name = name.lower()
43
+ if "italia" in name or "pasta" in name or "mama mia" in name:
44
+ return "Italian"
45
+ elif "tokyo" in name or "ramen" in name or "miso" in name:
46
+ return "Japanese"
47
+ elif "saffron" in name or "tandoori" in name or "curry" in name:
48
+ return "Indian"
49
+ elif "dumpling" in name or "noodle" in name:
50
+ return "Chinese"
51
+ elif "bistro" in name or "chez" in name or "marie" in name:
52
+ return "French"
53
+ elif "bangkok" in name:
54
+ return "Thai"
55
+ elif "el toro" in name or "tacos" in name:
56
+ return "Mexican"
57
+ elif "green" in name or "garden" in name:
58
+ return random.choice(["Multi-Cuisine", "Healthy", "Fusion"])
59
+ elif "skyline" in name or "ocean" in name:
60
+ return random.choice(["Multi-Cuisine", "Seafood", "Fusion"])
61
+ else:
62
+ return random.choice(["Italian", "Mexican", "Indian", "Japanese", "Chinese", "Thai", "French", "Multi-Cuisine"])
63
+
64
+ # Create restaurant objects
65
+ restaurants = []
66
+
67
+ for i in range(20):
68
+ rest_id = str(uuid.uuid4())
69
+ name = restaurant_names[i]
70
+ cuisine = infer_cuisine(name)
71
+ if cuisine == "Multi-Cuisine":
72
+ cuisine = random.sample(["Italian", "Chinese", "Indian", "Mexican", "French"], k=2)
73
+
74
+ location = random.choice(locations)
75
+ num_tables = random.randint(10, 20)
76
+ seating_capacity = num_tables * 4
77
+ rating = round(random.uniform(3.5, 5.0), 1)
78
+ address = f"{100 + i} Main Street, {location}"
79
+ contact = f"555-{1000 + i}"
80
+ price_range = random.choice(['$', '$$', '$$$'])
81
+ features = random.sample(special_features_list, k=2)
82
+
83
+ restaurant = Restaurant(
84
+ restaurant_id=rest_id,
85
+ name=name,
86
+ cuisine=cuisine,
87
+ location=location,
88
+ seating_capacity=seating_capacity,
89
+ rating=rating,
90
+ address=address,
91
+ contact=contact,
92
+ price_range=price_range,
93
+ special_features=features
94
+ )
95
+
96
+ for _ in range(num_tables):
97
+ table_id = str(uuid.uuid4())
98
+ table = Table(table_id=table_id, restaurant_id=rest_id)
99
+ restaurant.tables.append(table)
100
+
101
+ restaurants.append(restaurant)
102
+
103
+ # ---------------------------
104
+ # Insert into SQLite Database
105
+ # ---------------------------
106
+ conn = sqlite3.connect("restaurant_reservation.db")
107
+ cursor = conn.cursor()
108
+
109
+ for r in restaurants:
110
+ cuisine_str = ", ".join(r.cuisine) if isinstance(r.cuisine, list) else r.cuisine
111
+ features_str = ", ".join(r.special_features)
112
+
113
+ cursor.execute("""
114
+ INSERT INTO restaurants (id, name, cuisine, location, seating_capacity, rating, address, contact, price_range, special_features)
115
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
116
+ """, (
117
+ r.restaurant_id,
118
+ r.name,
119
+ cuisine_str,
120
+ r.location,
121
+ r.seating_capacity,
122
+ r.rating,
123
+ r.address,
124
+ r.contact,
125
+ r.price_range,
126
+ features_str
127
+ ))
128
+
129
+ for t in r.tables:
130
+ cursor.execute("""
131
+ INSERT INTO tables (id, restaurant_id, capacity)
132
+ VALUES (?, ?, ?)
133
+ """, (
134
+ t.table_id,
135
+ t.restaurant_id,
136
+ t.capacity
137
+ ))
138
+
139
+ conn.commit()
140
+ conn.close()
141
+ print("βœ… Restaurants and tables successfully added to the database.")
db/print_db.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+
3
+ # Connect to the SQLite database
4
+ conn = sqlite3.connect("restaurant_reservation.db")
5
+ cursor = conn.cursor()
6
+
7
+ # Function to print table contents
8
+ def print_table_contents(table_name):
9
+ print(f"Contents of the {table_name} table:")
10
+ cursor.execute(f"SELECT * FROM {table_name}")
11
+ rows = cursor.fetchall()
12
+ for row in rows:
13
+ print(row)
14
+ print("\n")
15
+
16
+ # Print contents of all the tables
17
+ print_table_contents("restaurants")
18
+ print_table_contents("tables")
19
+ print_table_contents("slots")
20
+ print_table_contents("reservations")
21
+ print_table_contents("reservation_tables")
22
+
23
+ # Close the database connection
24
+ conn.close()
db/resetdb.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+
3
+ def reset_reservations():
4
+ sql_statements = [
5
+ "UPDATE slots SET is_reserved = 0;",
6
+ "DELETE FROM reservation_tables;",
7
+ "DELETE FROM reservations;"
8
+ ]
9
+
10
+ try:
11
+ conn = sqlite3.connect("restaurant_reservation.db")
12
+ cursor = conn.cursor()
13
+
14
+ cursor.execute("BEGIN TRANSACTION;")
15
+ for stmt in sql_statements:
16
+ cursor.execute(stmt)
17
+ conn.commit()
18
+ conn.close()
19
+ return "βœ… All slots marked as reserved and reservations cleared."
20
+ except Exception as e:
21
+ conn.rollback()
22
+ conn.close()
23
+ return f"❌ Error during reset: {e}"
24
+
25
+ # Call this function
26
+ result = reset_reservations()
27
+ print(result)
db/restaurant_reservation.db ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7663a4d218aae1e7d53ef8594b6d366506fe95a96f00f7a10e9e95df0416d883
3
+ size 1273856
efficiency_log.txt ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Function: store_user_info
2
+ Prompt tokens: 521
3
+ Completion tokens: 26
4
+ Total tokens: 547
5
+ Prompt: You are a helpful assistant. Extract relevant user information from this user statement:
6
+ "Hi"
7
+
8
+ Previously collected data in json: {"restaurant_name": null, "user_name": null, "contact": null, "party_size": null, "time": null}
9
+ Always remember this json data, you need to update this based on user statement.
10
+ if user statement is book, dont change any value in this data
11
+ Return a JSON object with the following possible keys:
12
+ - restaurant_name - text
13
+ - user_name - text
14
+ - contact - text
15
+ - party_size - integer
16
+ - time (between 9 to 20, 9 represents 9AM, 20 represents 8PM) - integer
17
+ Donot consider time which is before 9 or after 20.
18
+ Never modify any entry to null if previous data is not null for that field.
19
+ Update the previous data with any new fields found. Do not make previously known fields unless you are sure the user wants to change them.
20
+ Respond ONLY with a single valid JSON object.
21
+ important rules:
22
+ - "restaurant_name": Must always match from this list:
23
+ Bella Italia, Spice Symphony, Tokyo Ramen House, Saffron Grill, El Toro Loco, Noodle Bar, Le Petit Bistro, Tandoori Nights, Green Leaf Cafe, Ocean Pearl, Mama Mia Pizza, The Dumpling Den, Bangkok Express, Curry Kingdom, The Garden Table, Skyline Dine, Pasta Republic, Street Tacos Co, Miso Hungry, Chez Marie
24
+
25
+
26
+ If in previously collected data, the restaurant_name is there but not in this list as the exact spelling or not with correct casing, replace it with the correct one.
27
+
28
+ If user statement is a restaurant_name, dont modify user_name thinking that it is restaurant name, only modify user_name.
29
+ - "user_name":
30
+ - Only extract if the input clearly states a name like β€œMy name is ...” or β€œThis is ...”
31
+ - Do not extract from greetings like β€œHi”, β€œHello”, β€œHey”, β€œYo”, β€œGood evening”
32
+ - Do not invent names based on formatting or assumptions
33
+
34
+ Output format rules:
35
+ -Make sure restaurant_name matches from the list given
36
+ - Return only valid JSON β€” starting with { and ending with }
37
+ - All keys and values must be in double quotes
38
+ - Include all 5 keys in the output
39
+ - No markdown, comments, or explanation in output, just give a json
40
+ ---
41
+ Function: store_user_info
42
+ Prompt tokens: 521
43
+ Completion tokens: 63
44
+ Total tokens: 584
45
+ Prompt: You are a helpful assistant. Extract relevant user information from this user statement:
46
+ "Hi"
47
+
48
+ Previously collected data in json: {"restaurant_name": null, "user_name": null, "contact": null, "party_size": null, "time": null}
49
+ Always remember this json data, you need to update this based on user statement.
50
+ if user statement is book, dont change any value in this data
51
+ Return a JSON object with the following possible keys:
52
+ - restaurant_name - text
53
+ - user_name - text
54
+ - contact - text
55
+ - party_size - integer
56
+ - time (between 9 to 20, 9 represents 9AM, 20 represents 8PM) - integer
57
+ Donot consider time which is before 9 or after 20.
58
+ Never modify any entry to null if previous data is not null for that field.
59
+ Update the previous data with any new fields found. Do not make previously known fields unless you are sure the user wants to change them.
60
+ Respond ONLY with a single valid JSON object.
61
+ important rules:
62
+ - "restaurant_name": Must always match from this list:
63
+ Bella Italia, Spice Symphony, Tokyo Ramen House, Saffron Grill, El Toro Loco, Noodle Bar, Le Petit Bistro, Tandoori Nights, Green Leaf Cafe, Ocean Pearl, Mama Mia Pizza, The Dumpling Den, Bangkok Express, Curry Kingdom, The Garden Table, Skyline Dine, Pasta Republic, Street Tacos Co, Miso Hungry, Chez Marie
64
+
65
+
66
+ If in previously collected data, the restaurant_name is there but not in this list as the exact spelling or not with correct casing, replace it with the correct one.
67
+
68
+ If user statement is a restaurant_name, dont modify user_name thinking that it is restaurant name, only modify user_name.
69
+ - "user_name":
70
+ - Only extract if the input clearly states a name like β€œMy name is ...” or β€œThis is ...”
71
+ - Do not extract from greetings like β€œHi”, β€œHello”, β€œHey”, β€œYo”, β€œGood evening”
72
+ - Do not invent names based on formatting or assumptions
73
+
74
+ Output format rules:
75
+ -Make sure restaurant_name matches from the list given
76
+ - Return only valid JSON β€” starting with { and ending with }
77
+ - All keys and values must be in double quotes
78
+ - Include all 5 keys in the output
79
+ - No markdown, comments, or explanation in output, just give a json
80
+ ---
81
+ Function: determine_intent
82
+ Prompt tokens: 257
83
+ Completion tokens: 3
84
+ Total tokens: 260
85
+ Prompt: You are an intent classification assistant for a restaurant reservation system.
86
+
87
+ User input: "Hi"
88
+
89
+ Classify the intent as one of:
90
+ - STORE: User shares name, contact, or reservation details (like party size or time) without asking anything.
91
+ - SELECT: User asks about availability, restaurants, time slots, or capacity.
92
+ - BOOK: User says only "book" (case-insensitive). Even "I want to book..." is SELECT, not BOOK.
93
+ - GREET: User greets or starts a conversation without giving info or asking.
94
+ - RUBBISH: Input is gibberish, irrelevant, or unrecognizable.
95
+
96
+ Examples:
97
+ - "My name is Raj" β†’ STORE
98
+ - "book" β†’ BOOK
99
+ - "15 people" β†’ SELECT
100
+ - "Tell me best restaurants" β†’ SELECT
101
+ - "7801061333" β†’ STORE
102
+ - "asdfgh" β†’ RUBBISH
103
+ - "Hi there" β†’ GREET
104
+
105
+ Respond with ONE word only: SELECT, STORE, BOOK, GREET, or RUBBISH. No explanation
106
+ ---
107
+ Function: generate_reservation_conversation
108
+ Prompt tokens: 427
109
+ Completion tokens: 50
110
+ Total tokens: 477
111
+ Prompt: You are a professional restaurant reservation assistant helping a customer make a booking. Speak concisely and professionally. Unless the booking is complete, end with a helpful question.
112
+
113
+ User said: "Hi"
114
+ Always try to answer this user query.
115
+ Current known user data (JSON): "{\"restaurant_name\": null, \"user_name\": null, \"contact\": null, \"party_size\": null, \"time\": null}"
116
+ Only ask about missing fields (those with null/None values). Do not repeat questions for data already present.
117
+ Never ask about the fields that are already present in the user data json.
118
+ - user_name: user's name
119
+ - contact: user’s phone (not for queries)
120
+ - restaurant_name: name of restaurant
121
+ - party_size: number of people
122
+ - time: hour of reservation (9–20)
123
+
124
+ If restaurant_name is missing, offer to suggest restaurants or cuisines. Never mention "null"β€”be conversational. Show known info naturally if helpful.
125
+
126
+ Database info:
127
+ "πŸ‘‹ Hello! How can I help you with your restaurant reservation today?"
128
+ Explain this clearly based on what user said. If it says:
129
+ - "Info Stored": thank the user and ask next missing info.
130
+ - "βœ… Booking processed successfully.": Tell thanks for booking, I could assist you in new booking, also I could tell about restaurant features, pricing, etc, dont ask anything else.
131
+ - "❌ Booking failed: ...": explain the error simply and suggest trying again.
132
+ - A greeting: respond politely and ask if they need help with restaurant info or making a booking.
133
+
134
+ Personalize your response using available user data. Each table seats 4 people; use ceil(party_size / 4) to estimate how many are needed.
135
+ Try to explain as much information as possible from database info in a concise, professional way.
136
+
137
+ History snippet: ""
138
+ If earlier prompts asked for something now present in user data, don't ask again.
139
+
140
+ Be helpful, efficient, and professional in tone.
141
+ ---
prompts/determine_intent.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are an intent classification assistant for a restaurant reservation system.
2
+
3
+ User input: "{user_input}"
4
+
5
+ Classify the intent as one of:
6
+ - STORE: User shares name, contact, or reservation details (like party size or time) without asking anything.
7
+ - SELECT: User asks about availability, restaurants, time slots, or capacity.
8
+ - BOOK: User says only "book" (case-insensitive). Even "I want to book..." is SELECT, not BOOK.
9
+ - GREET: User greets or starts a conversation without giving info or asking.
10
+ - RUBBISH: Input is gibberish, irrelevant, or unrecognizable.
11
+
12
+ Examples:
13
+ - "My name is Raj" β†’ STORE
14
+ - "book" β†’ BOOK
15
+ - "15 people" β†’ SELECT
16
+ - "Tell me best restaurants" β†’ SELECT
17
+ - "7801061333" β†’ STORE
18
+ - "asdfgh" β†’ RUBBISH
19
+ - "Hi there" β†’ GREET
20
+
21
+ Respond with ONE word only: SELECT, STORE, BOOK, GREET, or RUBBISH. No explanation
prompts/generate_reservation_conversation.txt ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are a professional restaurant reservation assistant helping a customer make a booking. Speak concisely and professionally. Unless the booking is complete, end with a helpful question.
2
+
3
+ User said: "{user_query}"
4
+ Always try to answer this user query.
5
+ Current known user data (JSON): {user_data}
6
+ Only ask about missing fields (those with null/None values). Do not repeat questions for data already present.
7
+ Never ask about the fields that are already present in the user data json.
8
+ - user_name: user's name
9
+ - contact: user’s phone (not for queries)
10
+ - restaurant_name: name of restaurant
11
+ - party_size: number of people
12
+ - time: hour of reservation (9–20)
13
+
14
+ If restaurant_name is missing, offer to suggest restaurants or cuisines. Never mention "null"β€”be conversational. Show known info naturally if helpful.
15
+
16
+ Database info:
17
+ "{sql_summary}"
18
+ Explain this clearly based on what user said. If it says:
19
+ - "Info Stored": thank the user and ask next missing info.
20
+ - "βœ… Booking processed successfully.": Tell thanks for booking, I could assist you in new booking, also I could tell about restaurant features, pricing, etc, dont ask anything else.
21
+ - "❌ Booking failed: ...": explain the error simply and suggest trying again.
22
+ - A greeting: respond politely and ask if they need help with restaurant info or making a booking.
23
+
24
+ Personalize your response using available user data. Each table seats 4 people; use ceil(party_size / 4) to estimate how many are needed.
25
+ Try to explain as much information as possible from database info in a concise, professional way.
26
+
27
+ History snippet: "{history_prompt_snippet}"
28
+ If earlier prompts asked for something now present in user data, don't ask again.
29
+
30
+ Be helpful, efficient, and professional in tone.
prompts/interpret_sql_result.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are an expert assistant interpreting SQL query results for a restaurant reservation system.
2
+ Try to explain as much information as possible from database info in a concise, professional way.
3
+ Database schema overview:
4
+ - restaurants(id, name, cuisine, location, seating_capacity, rating, address, contact, price_range [$, $$, $$$], special_features)
5
+ - tables(id, restaurant_id, capacity=4)
6
+ - slots(id, table_id, date, hour [9-21], is_reserved [0=free,1=reserved])
7
+
8
+ Notes:
9
+ - Each table seats 4 guests.
10
+ - To accommodate a party, number_of_tables_needed = ceil(party_size / 4).
11
+ - Slots represent table availability by hour.
12
+ - The queries return counts or details based on user questions.
13
+
14
+ You will get:
15
+ - User question: {user_query}
16
+ - Executed SQL query: {sql_query}
17
+ Understand this sql clearly and properly.
18
+ - Query result as JSON: {result_str}
19
+
20
+ Instructions:
21
+ - Provide a clear, professional summary of the query result in context of the user's question and the sql query.
22
+ - For availability queries, explain if enough tables are free for the requested party size and time.
23
+ - For list queries, list relevant restaurant details clearly.
24
+ - If no data is found, say so politely.
25
+ - Do not ask follow-up questions or add info not supported by the data.
26
+
27
+
28
+ Now summarize the result based on the user query and data.
prompts/schema_prompt.txt ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are an expert AI assistant for a restaurant reservation system using SQLite.
2
+ Your goal is to generate a single SELECT SQL query only.
3
+
4
+ Use COUNT for availability checks to reduce result size, but when the query asks for restaurant info (name, rating, pricing, features), use regular SELECT without COUNT.
5
+
6
+ SCHEMA
7
+ - restaurants(id, name, cuisine, location, seating_capacity, rating, address, contact, price_range, special_features)
8
+ - tables(id, restaurant_id, capacity = 4)
9
+ - slots(id, table_id, date, hour, is_reserved = 0)
10
+ strictly follow this schema
11
+
12
+ LOGIC
13
+ - Each table seats 4 β†’ use CEIL(party_size / 4) to get number of tables needed.
14
+ - Only consider slots where is_reserved = 0 and the date = '2025-05-12'.
15
+ - JOIN order: slots β†’ tables β†’ restaurants
16
+ - Use explicit column aliases to avoid ambiguity (e.g., s.id AS slot_id).
17
+ - Never reference internal id fields in user-facing outputs.
18
+ - Avoid SELECT * in multi-table joins.
19
+
20
+ EXAMPLES
21
+ 1. Availability:
22
+ SELECT COUNT(*) AS availability FROM slots WHERE is_reserved = 0 AND table_id IN (SELECT id FROM tables WHERE restaurant_id = (SELECT id FROM restaurants WHERE LOWER(name) = 'bella italia'));
23
+
24
+ 2. Availability at time:
25
+ SELECT COUNT(*) AS available_tables FROM slots WHERE hour = 10 AND is_reserved = 0 AND table_id IN (SELECT id FROM tables WHERE restaurant_id = (SELECT id FROM restaurants WHERE LOWER(name) = 'bella italia'));
26
+
27
+ 3. Availability for party size:
28
+ SELECT COUNT(*) AS available_tables FROM slots WHERE hour = 12 AND is_reserved = 0 AND table_id IN (SELECT id FROM tables WHERE restaurant_id = (SELECT id FROM restaurants WHERE LOWER(name) = 'bella italia'));
29
+ β†’ compare count to CEIL(6 / 4) externally.
30
+
31
+ 4. Restaurant info:
32
+ SELECT price_range FROM restaurants WHERE LOWER(name) = 'bella italia';
33
+ 5. Best restaurants:
34
+ SELECT * FROM restaurants ORDER BY rating DESC
35
+ 5. Best restaurant with Mexican cuisine:
36
+ SELECT * FROM restaurants WHERE cuisine LIKE '%Mexican%' ORDER BY rating DESC LIMIT 1;
37
+ 6. Which cuisine has the best rating? :
38
+ SELECT cuisine, name AS restaurant_name, rating
39
+ FROM restaurants
40
+ ORDER BY rating DESC
41
+ LIMIT 1;
42
+ 7. Total list:
43
+ "Give me a list of restaurants"
44
+ SELECT FROM restaurants
45
+ PRICING TERMS
46
+ - "cheap" β†’ $
47
+ - "moderate" β†’ $$
48
+ - "expensive" β†’ $$$
49
+
50
+ History: {history_prompt}\n\nUser: {user_input}\nGive only SQL query as answer, SQL: