jjmandog's picture
""" Jay's Mobile Wash - Complete Mock UI Current Date and Time (UTC): 2025-06-14 00:47:12 Current User's Login: jjmandog Mock UI implementation with all features visualized exactly as they will appear in the production system. For preview purposes only. """ import gradio as gr import datetime import time import json import random import numpy as np import pandas as pd from PIL import Image import os import base64 import uuid from datetime import datetime, timedelta # ====================================================================== # MOCK DATA FOR SIMULATION # ====================================================================== # Mock data for visualization mock_calls = [ {"timestamp": "2025-06-13 21:34:12", "caller": "+15622289429", "duration": "3m 24s", "status": "Jay Answered", "notes": "Booking confirmed"}, {"timestamp": "2025-06-13 20:15:35", "caller": "+13108675309", "duration": "2m 10s", "status": "AI Handled", "notes": "Pricing inquiry"}, {"timestamp": "2025-06-13 19:42:03", "caller": "+15625551234", "duration": "4m 02s", "status": "Jay Answered", "notes": "Scheduled luxury wash"}, {"timestamp": "2025-06-13 18:20:19", "caller": "+18185559876", "duration": "0m 12s", "status": "Spam Blocked", "notes": "Known telemarketer"}, {"timestamp": "2025-06-13 16:55:40", "caller": "+17145552211", "duration": "3m 46s", "status": "AI Handled", "notes": "Booking request"} ] mock_bookings = [ {"ref": "JMW2365", "customer": "John D.", "phone": "+15622289429", "service": "Luxury Wash", "vehicle": "Tesla Model 3", "date": "2025-06-15", "time": "10:00 AM", "address": "2521 E. 4th St, Long Beach", "price": "$130", "status": "Confirmed"}, {"ref": "JMW2366", "customer": "Sarah M.", "phone": "+15625551234", "service": "Basic Wash", "vehicle": "Honda Civic", "date": "2025-06-14", "time": "2:30 PM", "address": "1157 E. Ocean Blvd, Long Beach", "price": "$60", "status": "Pending"}, {"ref": "JMW2367", "customer": "Robert K.", "phone": "+13108675309", "service": "Max Detail", "vehicle": "Cadillac Escalade", "date": "2025-06-16", "time": "9:00 AM", "address": "5244 E. 2nd St, Long Beach", "price": "$210", "status": "Confirmed"} ] mock_sms = [ {"timestamp": "2025-06-13 22:15:22", "contact": "+15622289429", "direction": "incoming", "content": "What time can you come tomorrow for the wash?"}, {"timestamp": "2025-06-13 22:15:45", "contact": "+15622289429", "direction": "outgoing", "content": "Hi John! I have an opening for your Tesla's luxury wash at 10:00 AM tomorrow. Does that work for you?"}, {"timestamp": "2025-06-13 22:16:30", "contact": "+15622289429", "direction": "incoming", "content": "Perfect, see you then"}, {"timestamp": "2025-06-13 22:16:45", "contact": "+15622289429", "direction": "outgoing", "content": "Great! I've confirmed your luxury wash for tomorrow at 10:00 AM at 2521 E. 4th St. See you then! -Jay"} ] # Customer data for searching mock_customers = [ {"name": "John Deere", "phone": "+15622289429", "email": "john.d@example.com", "vehicle": "Tesla Model 3", "total_services": 6, "favorite_service": "Luxury Wash", "last_visit": "2025-06-01"}, {"name": "Sarah Miller", "phone": "+15625551234", "email": "sarah.m@example.com", "vehicle": "Honda Civic", "total_services": 2, "favorite_service": "Basic Wash", "last_visit": "2025-05-15"}, {"name": "Robert King", "phone": "+13108675309", "email": "robert.k@example.com", "vehicle": "Cadillac Escalade", "total_services": 3, "favorite_service": "Max Detail", "last_visit": "2025-05-28"} ] # Mock training data for AI mock_training_samples = [ {"type": "sms", "input": "Do you offer ceramic coating?", "ai_response": "We don't currently offer ceramic coating, but our Max Detail includes a premium wax that offers excellent protection.", "rating": 4}, {"type": "voice", "input": "I need an emergency wash before a meeting", "ai_response": "I understand this is urgent. I can offer you a priority slot today at 3pm, would that work for your meeting?", "emotion": "anxious", "rating": 5}, {"type": "sms", "input": "How much for a normal wash?", "ai_response": "Our Basic Wash is $60 for cars and $70 for SUVs/trucks. It includes exterior wash, soap, scrub and shine. Would you like to schedule one?", "rating": 5} ] # Helper functions for the mock UI def get_mock_stats(): """Get mock statistics for the dashboard""" return { "total_calls": 127, "calls_jay_answered": 85, "calls_ai_handled": 34, "spam_blocked": 8, "active_calls": 0, "sms_received": 312, "bookings_confirmed": 96, "revenue_month": "$12,480" } def mock_system_status(): """Get mock system status information""" return { "twilio": "Connected", "database": "Online", "ai_models": "Operational", "last_update": "2025-06-14 00:12:45", "server_load": "23%", "space_used": "1.2 GB / 5 GB" } # ====================================================================== # MOCK FUNCTIONALITY HANDLERS # ====================================================================== def mock_train_sms(customer_message, expected_response=None, use_correction=False): """Mock SMS training function""" if not customer_message: return "", "", "Please enter a customer message to train the AI" time.sleep(1) # Simulate processing delay # Generate mock AI response based on customer message ai_responses = { "price": "Our Basic Wash is $60 for cars and $70 for SUVs/trucks. Luxury Wash is $130 for cars and $140 for SUVs. Max Detail is $200 for cars and $210 for SUVs. Which service are you interested in?", "book": "I'd be happy to schedule a wash for you! Could you tell me which service you'd like (Basic, Luxury, or Max), what type of vehicle you have, and your preferred date and time?", "time": "We're open from 6AM to 6PM, 7 days a week. When would you like to schedule your service?", "location": "We're a mobile service! We come to your location in Long Beach and surrounding areas. Where would you like us to meet you?", "cancel": "I'm sorry to hear you need to cancel. Would you like to reschedule for another time, or should I remove your appointment completely?" } # Match keywords in customer message message_lower = customer_message.lower() for keyword, response in ai_responses.items(): if keyword in message_lower: ai_response = response break else: ai_response = "Thank you for your message. How can I help you with our mobile wash service today?" # If using correction, use the provided response instead final_response = expected_response if use_correction and expected_response else ai_response return ai_response, final_response if use_correction else "", "AI SMS response trained successfully!" def mock_train_voice(audio_input=None, scenario_type=None, emotion_type=None, notes=None): """Mock voice training function""" if audio_input is None: return { "status": "Please record or upload audio to train the AI", "device": "", "emotion": "", "transcription": "", "ai_response": "" } time.sleep(1.5) # Simulate processing delay # Generate mock training results device = "iPhone" if random.random() > 0.5 else "Computer" # Use provided emotion or detect randomly if emotion_type and emotion_type != "Let AI Detect": emotion = emotion_type else: emotions = ["Neutral", "Happy", "Angry", "Confused", "Frustrated", "Satisfied"] emotion = random.choice(emotions) # Generate mock transcription based on scenario transcriptions = { "General Question": "Hi, I'm wondering what services you offer for a truck?", "Pricing Inquiry": "How much would it cost to get my SUV detailed?", "Booking Request": "I'd like to book a car wash for tomorrow afternoon if possible", "Service Complaint": "My car still has some spots that weren't cleaned properly", "Schedule Change": "I need to move my appointment from Saturday to Sunday", "Location Question": "Do you service the Belmont Shore area?" } transcription = transcriptions.get(scenario_type, "This is a mock transcription of the audio recording.") # Generate response based on emotion and transcription responses = { "Angry": "I understand you're frustrated. I want to address your concerns right away. Let me connect you with Jay directly.", "Confused": "Let me clarify that for you. We offer three levels of service: Basic Wash, Luxury Wash, and Max Detail.", "Happy": "I'm glad to hear that! We always aim to provide excellent service for our customers.", "Neutral": "Thank you for your question. I'd be happy to help you with that today." } ai_response = responses.get(emotion, "Thank you for contacting Jay's Mobile Wash. How can I help you today?") return { "status": "Voice training sample processed successfully!", "device": device, "emotion": emotion, "transcription": transcription, "ai_response": ai_response } def mock_send_sms(phone_number, message_content): """Mock SMS sending function""" if not phone_number or not message_content: return "Error: Please provide both phone number and message content." # Validate phone format if not phone_number.startswith("+"): phone_number = "+" + phone_number # Generate mock SMS ID sms_id = f"SM{uuid.uuid4().hex[:10].upper()}" time.sleep(0.8) # Simulate network delay # Add to mock conversations mock_sms.append({ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "contact": phone_number, "direction": "outgoing", "content": message_content }) return f"SMS sent successfully to {phone_number} (ID: {sms_id})" def mock_create_booking(customer_name, phone, service_type, vehicle_type, date, time, address): """Mock booking creation function""" if not all([customer_name, phone, service_type, vehicle_type, date, time, address]): return "Error: All fields are required to create a booking." # Generate booking reference number booking_ref = f"JMW{int(time.time())}"[-6:] # Calculate price based on service and vehicle type prices = { "Basic Wash": {"Car": "$60", "SUV/Truck": "$70"}, "Luxury Wash": {"Car": "$130", "SUV/Truck": "$140"}, "Max Detail": {"Car": "$200", "SUV/Truck": "$210"} } vehicle_category = "SUV/Truck" if any(v in vehicle_type.lower() for v in ["suv", "truck", "large"]) else "Car" price = prices.get(service_type, {}).get(vehicle_category, "$0") # Create new booking new_booking = { "ref": booking_ref, "customer": customer_name, "phone": phone, "service": service_type, "vehicle": vehicle_type, "date": date, "time": time, "address": address, "price": price, "status": "Pending" } # Add to mock bookings mock_bookings.append(new_booking) time.sleep(1) # Simulate processing delay return f"Booking created successfully! Reference: {booking_ref}" def mock_update_settings(ring_duration, response_time, voice_timeout, ai_fallback_delay): """Mock system settings update function""" time.sleep(0.5) # Simulate processing delay settings_text = ( f"βœ… Timing settings updated successfully!\n\n" f"β€’ Ring Duration: {ring_duration} seconds\n" f"β€’ SMS Response Time: {response_time} seconds\n" f"β€’ Voice Input Timeout: {voice_timeout} seconds\n" f"β€’ AI Fallback Delay: {ai_fallback_delay} seconds\n" f"\nUpdated at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" ) return settings_text def mock_search_customers(search_term): """Mock customer search function""" if not search_term or len(search_term) < 3: return mock_customers search_term = search_term.lower() results = [] for customer in mock_customers: if (search_term in customer["name"].lower() or search_term in customer["phone"] or search_term in customer["email"].lower() or search_term in customer["vehicle"].lower()): results.append(customer) return results if results else [] # ====================================================================== # UI COMPONENTS AND STYLING # ====================================================================== # CSS for styling the UI to match Jay's Mobile Wash branding css = """ /* Jay's Mobile Wash Branding Colors */ :root { --primary: #003366; --secondary: #CC0000; --accent: #0080ff; --light-bg: #f0f6ff; --dark-text: #111827; --light-text: #ffffff; --success: #10b981; --warning: #f59e0b; --error: #ef4444; } /* Overall layout */ body, .gradio-container { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: var(--dark-text); background-color: var(--light-bg); } /* Headings */ h1, h2, h3 { color: var(--primary); font-weight: 600; } /* Statistics cards */ .stat-card { background: white; border-radius: 10px; padding: 15px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin-bottom: 15px; border-left: 4px solid var(--accent); } /* Tabs styling */ .tab-nav { background-color: var(--primary); border-radius: 8px 8px 0 0; } .tab-nav button { color: var(--light-text); } .tab-nav button.selected { background-color: var(--accent); color: var(--light-text); } /* Button styling */ button.primary { background-color: var(--primary); color: var(--light-text); border-radius: 6px; } button.secondary { background-color: var(--accent); color: var(--light-text); border-radius: 6px; } button.danger { background-color: var(--secondary); color: var(--light-text); border-radius: 6px; } /* Tables */ table { border-collapse: separate; border-spacing: 0; width: 100%; border-radius: 8px; overflow: hidden; } th { background-color: var(--primary); color: var(--light-text); padding: 10px; text-align: left; } tr:nth-child(even) { background-color: rgba(0, 128, 255, 0.05); } td { padding: 8px 10px; border-bottom: 1px solid #e5e7eb; } /* Status indicators */ .status-active { color: var(--success); font-weight: 600; } .status-pending { color: var(--warning); font-weight: 600; } .status-error { color: var(--error); font-weight: 600; } /* Header logo */ .logo-header { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; } .logo-header img { height: 40px; } """ # ====================================================================== # MAIN APPLICATION UI CONSTRUCTION # ====================================================================== # Set up the title and theme with gr.Blocks(css=css, theme=gr.themes.Default()) as demo: # Header and logo with gr.Row(): with gr.Column(): gr.Markdown( """<div class="logo-header"> <img src="https://jaysmobilewash.com/wp-content/uploads/2023/06/cropped-JaysLogo.png" alt="Jay's Mobile Wash Logo"/> <h1>Jay's Mobile Wash AI Business System</h1> </div>""" ) # Main navigation tabs with gr.Tabs() as tabs: # DASHBOARD TAB with gr.Tab("πŸ“Š Dashboard"): with gr.Row(): gr.Markdown("### Business Overview") with gr.Row(): with gr.Column(scale=1): # Stats cards stats = get_mock_stats() with gr.Box(elem_classes=["stat-card"]): gr.Markdown(f"#### πŸ“ž Total Calls\n# {stats['total_calls']}") gr.Markdown(f"Jay Answered: {stats['calls_jay_answered']} | AI Handled: {stats['calls_ai_handled']}") with gr.Box(elem_classes=["stat-card"]): gr.Markdown(f"#### πŸ“± SMS Interactions\n# {stats['sms_received']}") ai_response_rate = int((stats['sms_received'] - 30) / stats['sms_received'] * 100) gr.Markdown(f"AI Response Rate: {ai_response_rate}%") with gr.Box(elem_classes=["stat-card"]): gr.Markdown(f"#### πŸ’° Monthly Revenue\n# {stats['revenue_month']}") gr.Markdown(f"Confirmed Bookings: {stats['bookings_confirmed']}") # System status system = mock_system_status() with gr.Box(): gr.Markdown("### System Status") with gr.Row(): gr.Markdown(f"**Twilio:** <span class='status-active'>{system['twilio']}</span>") gr.Markdown(f"**Database:** <span class='status-active'>{system['database']}</span>") gr.Markdown(f"**AI Models:** <span class='status-active'>{system['ai_models']}</span>") with gr.Row(): gr.Markdown(f"**Last Update:** {system['last_update']}") gr.Markdown(f"**Server Load:** {system['server_load']}") gr.Markdown(f"**Storage:** {system['space_used']}") with gr.Column(scale=2): # Call activity and booking calendar with gr.Row(): with gr.Box(): gr.Markdown("### Recent Call Activity") call_table = gr.DataFrame( mock_calls, headers=["Timestamp", "Caller", "Duration", "Status", "Notes"], datatype=["str", "str", "str", "str", "str"], row_count=(5, "fixed"), col_count=(5, "fixed"), ) with gr.Row(): with gr.Box(): gr.Markdown("### Upcoming Bookings") bookings_table = gr.DataFrame( mock_bookings, headers=["Ref", "Customer", "Service", "Date", "Time", "Price", "Status"], datatype=["str", "str", "str", "str", "str", "str", "str"], row_count=(3, "fixed"), col_count=(7, "fixed"), ) with gr.Row(): refresh_dashboard = gr.Button("πŸ”„ Refresh Dashboard") def refresh_dash(): """Mock dashboard refresh""" time.sleep(0.5) return mock_calls, mock_bookings refresh_dashboard.click( refresh_dash, inputs=[], outputs=[call_table, bookings_table] ) # CALL MANAGEMENT TAB with gr.Tab("πŸ“ž Call Management"): with gr.Row(): gr.Markdown("### Call Management Center") with gr.Row(): with gr.Column(): active_calls_box = gr.Textbox( label="Active Calls", value="No active calls at the moment.", lines=1, interactive=False ) call_history_table = gr.DataFrame( mock_calls, headers=["Timestamp", "Caller", "Duration", "Status", "Notes"], datatype=["str", "str", "str", "str", "str"], row_count=(10, "dynamic"), col_count=(5, "fixed"), interactive=False ) with gr.Row(): gr.Markdown("### Call Settings") with gr.Row(): ring_duration = gr.Slider( minimum=10, maximum=60, value=20, step=5, label="Ring Duration Before AI Pickup (seconds)" ) voice_timeout = gr.Slider( minimum=3, maximum=15, value=5, step=1, label="Voice Input Timeout (seconds)" ) with gr.Row(): ai_fallback_delay = gr.Slider( minimum=0, maximum=30, value=5, step=5, label="AI Fallback Delay After Failed Forward (seconds)" ) update_call_settings = gr.Button("πŸ’Ύ Update Call Settings") call_settings_status = gr.Textbox( label="Settings Status", interactive=False, lines=1 ) def update_call_config(ring_dur, voice_to, fallback): """Mock call settings update""" time.sleep(0.5) return f"Call settings updated successfully at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" update_call_settings.click( update_call_config, inputs=[ring_duration, voice_timeout, ai_fallback_delay], outputs=[call_settings_status] ) with gr.Row(): with gr.Accordion("Call Simulation", open=False): gr.Markdown("### Test Call Handling") with gr.Row(): test_caller = gr.Textbox( label="Test Caller Number", placeholder="+15551234567" ) test_scenario = gr.Dropdown( choices=["Normal Call", "Spam Call", "After Hours", "Angry Customer"], label="Test Scenario" ) simulate_call_btn = gr.Button("πŸ“± Simulate Incoming Call") simulation_result = gr.Textbox( label="Simulation Result", interactive=False, lines=5 ) def simulate_call(number, scenario): """Mock call simulation""" if not number: return "Please enter a valid phone number" time.sleep(1) if scenario == "Normal Call": return f"SIMULATED CALL FROM {number}\n\n1. Call received\n2. Forwarded to Jay\n3. Jay answered after 8 seconds\n4. Call duration: 2m 45s\n5. Call completed successfully" elif scenario == "Spam Call": return f"SIMULATED CALL FROM {number}\n\n1. Call received\n2. Spam detection triggered (score: 0.94)\n3. Call blocked automatically\n4. Number added to spam database" elif scenario == "After Hours": return f"SIMULATED CALL FROM {number}\n\n1. Call received\n2. After hours detected (current time: 8:45 PM)\n3. AI assistant provided business hours information\n4. Call duration: 0m 35s" elif scenario == "Angry Customer": return f"SIMULATED CALL FROM {number}\n\n1. Call received\n2. Forwarded to Jay\n3. No answer after 20 seconds\n4. AI assistant picked up\n5. Angry customer detected\n6. Emergency SMS alert sent to Jay\n7. Call duration: 3m 12s" simulate_call_btn.click( simulate_call, inputs=[test_caller, test_scenario], outputs=[simulation_result] ) # SMS MANAGEMENT TAB with gr.Tab("πŸ“± SMS Management"): with gr.Row(): with gr.Column(scale=1): gr.Markdown("### Contacts") contact_search = gr.Textbox( label="Search Contacts", placeholder="Name or phone number..." ) contact_list = gr.Dataframe( [[c["name"], c["phone"]] for c in mock_customers], headers=["Name", "Phone"], datatype=["str", "str"], row_count=(10, "dynamic"), col_count=(2, "fixed"), interactive=False ) def search_contacts(term): """Mock contact search""" results = mock_search_customers(term) return [[c["name"], c["phone"]] for c in results] contact_search.change( search_contacts, inputs=[contact_search], outputs=[contact_list] ) with gr.Column(scale=2): gr.Markdown("### SMS Conversation") conversation_header = gr.Markdown("#### Conversation with: John Deere (+15622289429)") sms_thread = gr.Chatbot( [(msg["content"], None) if msg["direction"] == "incoming" else (None, msg["content"]) for msg in mock_sms], elem_id="sms_thread", height=400, show_label=False ) with gr.Row(): sms_input = gr.Textbox( placeholder="Type your message here...", lines=2, label="" ) send_sms_btn = gr.Button("πŸ“€ Send") sms_status = gr.Textbox( label="Status", interactive=False, value="Ready to send messages", lines=1 ) def send_sms_msg(message, history): """Mock SMS sending""" if not message: return history, "", "Please type a message" # Add outgoing message to history history = history + [(None, message)] # Mock send mock_send_sms("+15622289429", message) time.sleep(1) # Simulate customer reply (random chance) if random.random() > 0.5: replies = ["Ok, thank you!", "Sounds good", "Perfect, see you then", "Thanks for the info"] reply = random.choice(replies) history = history + [(reply, None)] # Add to mock data mock_sms.append({ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "contact": "+15622289429", "direction": "incoming", "content": reply }) return history, "", f"Message sent to +15622289429 at {datetime.now().strftime('%H:%M:%S')}" send_sms_btn.click( send_sms_msg, inputs=[sms_input, sms_thread], outputs=[sms_thread, sms_input, sms_status] ) with gr.Row(): with gr.Box(): gr.Markdown("### SMS Settings") with gr.Row(): response_time = gr.Slider( minimum=1, maximum=30, value=5, step=1, label="Automatic Response Time (seconds)" ) template_selection = gr.Dropdown( choices=["Standard", "Friendly", "Professional", "Concise"], value="Professional", label="Response Style Template" ) update_sms_settings = gr.Button("πŸ’Ύ Update SMS Settings") sms_settings_status = gr.Textbox( label="Settings Status", interactive=False, lines=1 ) update_sms_settings.click( lambda t, s: f"SMS settings updated successfully at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", inputs=[response_time, template_selection], outputs=[sms_settings_status] ) # BOOKING MANAGEMENT TAB with gr.Tab("πŸ“… Booking Management"): with gr.Row(): gr.Markdown("### Manage Bookings") with gr.Row(): with gr.Column(): with gr.Box(): gr.Markdown("### Create New Booking") customer_name = gr.Textbox(label="Customer Name") phone_number = gr.Textbox(label="Phone Number") with gr.Row(): service_type = gr.Dropdown( choices=["Basic Wash", "Luxury Wash", "Max Detail"], label="Service Type" ) vehicle_type = gr.Textbox(label="Vehicle Type") with gr.Row(): service_date = gr.Textbox( label="Date", placeholder="YYYY-MM-DD" ) service_time = gr.Textbox( label="Time", placeholder="HH:MM AM/PM" ) service_address = gr.Textbox( label="Service Address", lines=2 ) create_booking_btn = gr.Button("πŸ“ Create Booking") booking_status = gr.Textbox( label="Booking Status", interactive=False, lines=2 ) create_booking_btn.click( mock_create_booking, inputs=[customer_name, phone_number, service_type, vehicle_type, service_date, service_time, service_address], outputs=[booking_status] ) with gr.Column(): with gr.Box(): gr.Markdown("### Upcoming Bookings") upcoming_bookings = gr.DataFrame( mock_bookings, headers=["Ref", "Customer", "Service", "Date", "Time", "Price", "Status"], datatype=["str", "str", "str", "str", "str", "str", "str"], row_count=(5, "dynamic"), col_count=(7, "fixed"), interactive=False ) with gr.Row(): booking_ref = gr.Textbox( label="Booking Reference", placeholder="Enter booking reference..." ) action = gr.Dropdown( choices=["Confirm", "Cancel", "Reschedule", "Complete", "Send Reminder"], label="Action" ) booking_action_btn = gr.Button("βœ… Apply Action") booking_action_status = gr.Textbox( label="Action Status", interactive=False, lines=1 ) def booking_action(ref, action_type): """Mock booking action""" if not ref: return "Please enter a booking reference" # Check if booking exists booking_exists = any(b["ref"] == ref for b in mock_bookings) if not booking_exists: return f"Booking with reference {ref} not found" time.sleep(0.8) # Mock action results actions = { "Confirm": f"Booking {ref} has been confirmed successfully", "Cancel": f"Booking {ref} has been cancelled", "Reschedule": f"Booking {ref} has been marked for rescheduling", "Complete": f"Booking {ref} has been marked as completed", "Send Reminder": f"Reminder SMS sent to customer for booking {ref}" } return actions.get(action_type, f"Action {action_type} applied to booking {ref}") booking_action_btn.click( booking_action, inputs=[booking_ref, action], outputs=[booking_action_status] ) # AI TRAINING TAB with gr.Tab("🧠 AI Training Center"): gr.Markdown("### Train Your AI Assistant") with gr.Tabs() as training_tabs: # SMS Training with gr.Tab("πŸ“± SMS Training"): gr.Markdown("Train the AI to respond better to customer SMS messages") with gr.Row(): sms_customer_message = gr.Textbox( label="Customer SMS", lines=3, placeholder="Type a message as if from a customer..." ) sms_expected_response = gr.Textbox( label="Expected Response (Optional)", lines=3, placeholder="Provide the correct response if needed" ) use_correction = gr.Checkbox(label="Use correction instead of AI response", value=False) train_sms_button = gr.Button("πŸ€– Train SMS Response") with gr.Row(): sms_ai_response = gr.Textbox(label="AI Generated Response", lines=3) sms_final_response = gr.Textbox(label="Final Training Response", lines=3) sms_training_status = gr.Textbox(label="Training Status") # Example messages for quick testing with gr.Accordion("Example Messages", open=False): example_buttons = [ gr.Button("Price Question"), gr.Button("Booking Request"), gr.Button("Vehicle Question"), gr.Button("Availability Question"), gr.Button("Complaint") ] examples = { "Price Question": "How much does it cost to wash an SUV?", "Booking Request": "I need my car washed tomorrow morning if possible", "Vehicle Question": "Do you wash motorcycles?", "Availability Question": "What times are you available this weekend?", "Complaint": "The wash didn't get all the dirt off my wheels" } for i, btn in enumerate(example_buttons): btn.click( lambda e=list(examples.values())[i]: e, inputs=[], outputs=[sms_customer_message] ) train_sms_button.click( mock_train_sms, inputs=[sms_customer_message, sms_expected_response, use_correction], outputs=[sms_ai_response, sms_final_response, sms_training_status] ) # Voice Training with gr.Tab("🎀 Voice Training"): gr.Markdown("### Advanced Voice Training with Emotional Intelligence") gr.Markdown("Use your iPhone or computer microphone to record customer interactions.") with gr.Row(): # Left column - Recording & Inputs with gr.Column(): audio_input = gr.Audio( source="microphone", type="filepath", label="Record customer voice (iPhone/Computer compatible)" ) scenario_type = gr.Dropdown( choices=["General Question", "Pricing Inquiry", "Booking Request", "Service Complaint", "Schedule Change", "Location Question"], label="Scenario Type", value="General Question" ) emotion_type = gr.Dropdown( choices=["Let AI Detect", "Neutral", "Happy", "Angry", "Confused", "Frustrated", "Satisfied"], label="Customer Emotion", value="Let AI Detect" ) notes = gr.Textbox( label="Training Notes (Optional)", placeholder="Add any special notes for this training sample..." ) train_voice_button = gr.Button("πŸ”Š Process Voice Training", variant="primary") # Right column - Results & Analysis with gr.Column(): with gr.Box(): training_status = gr.Textbox(label="Status") device_detected = gr.Textbox(label="Recording Device") emotion_detected = gr.Textbox(label="Detected Emotion") gr.Markdown("### Transcription & Response") transcription_output = gr.Textbox(label="Customer Speech Transcription", lines=3) response_output = gr.Textbox(label="AI Response", lines=3) # Advanced options with gr.Accordion("Advanced Options", open=False): memory_toggle = gr.Checkbox(label="Enable Memory Across Sessions", value=True) emotion_sensitivity = gr.Slider(minimum=0, maximum=1, value=0.7, label="Emotion Detection Sensitivity") alert_threshold = gr.Dropdown( choices=["Any Negative Emotion", "Only When Angry", "Never"], value="Only When Angry", label="Send Alerts to Jay" ) # Connect button to function train_voice_button.click( mock_train_voice, inputs=[audio_input, scenario_type, emotion_type, notes], outputs={ training_status: lambda x: x["status"], device_detected: lambda x: x["device"], emotion_detected: lambda x: x["emotion"], transcription_output: lambda x: x["transcription"], response_output: lambda x: x["ai_response"] } ) # Call Simulation Training with gr.Tab("πŸ“ž Call Simulation Training"): gr.Markdown("### Train with Simulated Calls") gr.Markdown("Test and improve the call handling system without using real phone calls.") with gr.Row(): with gr.Column(): sim_caller_number = gr.Textbox( label="Simulated Caller Number", placeholder="+15551234567" ) sim_scenario = gr.Dropdown( choices=["New Customer", "Repeat Customer", "Pricing Question", "Booking Request", "Complaint", "Emergency Request", "After Hours Call", "Spam Call", "Wrong Number"], label="Call Scenario", value="New Customer" ) sim_caller_emotion = gr.Dropdown( choices=["Neutral", "Happy", "Angry", "Confused", "Impatient", "Demanding", "Anxious"], label="Caller Emotion", value="Neutral" ) jay_answers = gr.Radio( choices=["Jay Answers", "Jay Doesn't Answer"], label="Call Routing", value="Jay Answers" ) run_simulation_btn = gr.Button("▢️ Run Call Simulation") with gr.Column(): sim_result = gr.Textbox( label="Simulation Result", lines=10, interactive=False ) def simulate_training_call(number, scenario, emotion, jay_answers): """Mock call simulation for training""" time.sleep(1.5) simulation_result = f"CALL SIMULATION RESULTS\n" simulation_result += f"=======================\n\n" simulation_result += f"Caller: {number}\n" simulation_result += f"Scenario: {scenario}\n" simulation_result += f"Emotion: {emotion}\n" simulation_result += f"Jay answers: {'Yes' if jay_answers == 'Jay Answers' else 'No'}\n\n" # Generate scenario-specific results simulation_result += f"Call Timeline:\n" simulation_result += f"1. Call received at {(datetime.now() - timedelta(seconds=60)).strftime('%H:%M:%S')}\n" if jay_answers == "Jay Answers": simulation_result += f"2. Call forwarded to Jay at {(datetime.now() - timedelta(seconds=58)).strftime('%H:%M:%S')}\n" simulation_result += f"3. Jay answered after 8 seconds\n" if emotion == "Angry": simulation_result += f"4. Caller detected as angry - Jay applied de-escalation techniques\n" simulation_result += f"5. Call successfully resolved at {datetime.now().strftime('%H:%M:%S')}\n" simulation_result += f"6. Follow-up SMS sent to confirm resolution\n" else: simulation_result += f"4. Normal conversation handled by Jay\n" simulation_result += f"5. Call completed at {datetime.now().strftime('%H:%M:%S')}\n" else: simulation_result += f"2. Call forwarded to Jay at {(datetime.now() - timedelta(seconds=58)).strftime('%H:%M:%S')}\n" simulation_result += f"3. No answer after 20 seconds\n" simulation_result += f"4. AI assistant picked up call at {(datetime.now() - timedelta(seconds=38)).strftime('%H:%M:%S')}\n" if emotion == "Angry": simulation_result += f"5. Caller detected as angry - AI used emotional de-escalation\n" simulation_result += f"6. Alert SMS sent to Jay\n" simulation_result += f"7. AI collected information and promised urgent callback\n" else: simulation_result += f"5. AI handled {scenario} scenario\n" simulation_result += f"6. AI collected booking information\n" simulation_result += f"7. Booking confirmation sent via SMS\n" simulation_result += f"8. Call completed at {datetime.now().strftime('%H:%M:%S')}\n" simulation_result += f"\nAI Learning Points:\n" simulation_result += f"β€’ Speech pattern for '{emotion}' emotion updated\n" simulation_result += f"β€’ Response timing optimized for {scenario}\n" simulation_result += f"β€’ Knowledge base updated with new {scenario.lower()} handling\n" return simulation_result run_simulation_btn.click( simulate_training_call, inputs=[sim_caller_number, sim_scenario, sim_caller_emotion, jay_answers], outputs=[sim_result] ) # Response Feedback with gr.Tab("⭐ Response Rating & Feedback"): gr.Markdown("### Rate and Improve AI Responses") gr.Markdown("Provide feedback on AI responses to continuously improve the system.") with gr.Row(): with gr.Column(): feedback_type = gr.Radio( choices=["SMS Response", "Voice Response", "Call Handling"], label="Feedback Type", value="SMS Response" ) sample_responses = gr.DataFrame( [[sample["type"], sample["input"][:30] + "...", sample["ai_response"][:30] + "..."] for sample in mock_training_samples], headers=["Type", "Customer Input", "AI Response"], datatype=["str", "str", "str"], row_count=(5, "dynamic"), col_count=(3, "fixed") ) rating = gr.Radio( choices=["1 - Poor", "2 - Below Average", "3 - Average", "4 - Good", "5 - Excellent"], label="Response Rating", value="4 - Good" ) improvement_suggestion = gr.Textbox( label="Improvement Suggestion (Optional)", lines=3, placeholder="Suggest how the response could be improved..." ) submit_feedback_btn = gr.Button("πŸ“ Submit Feedback") with gr.Column(): selected_response = gr.Textbox( label="Selected Response", lines=10, placeholder="Select a response from the list to provide feedback..." ) feedback_status = gr.Textbox( label="Feedback Status", lines=2 ) # AI Learning Chart (Mock) learning_progress = gr.Plot( label="AI Learning Progress" ) def create_mock_learning_chart(): """Create a mock learning progress chart""" import matplotlib.pyplot as plt import numpy as np plt.figure(figsize=(8, 4)) # Mock data dates = ["Jun 1", "Jun 3", "Jun 5", "Jun 7", "Jun 9", "Jun 11", "Jun 13"] accuracy = [0.82, 0.84, 0.86, 0.85, 0.88, 0.90, 0.91] plt.plot(dates, accuracy, marker='o', linewidth=2, color='#003366') plt.title("AI Response Accuracy Over Time") plt.xlabel("Date") plt.ylabel("Accuracy") plt.grid(True, linestyle='--', alpha=0.7) plt.ylim(0.8, 0.95) # Highlight improvement plt.axhline(y=0.85, color='#CC0000', linestyle='--', alpha=0.5) plt.text(dates[2], 0.855, "Training Target", color='#CC0000') return plt def submit_response_feedback(rating, suggestion): """Mock feedback submission""" time.sleep(0.8) rating_value = int(rating.split(" - ")[0]) return f"Feedback submitted successfully! Rating: {rating_value}/5\n" + \ f"The AI will use this feedback to improve future responses." # Auto-populate response when selecting from table def select_response_for_feedback(evt: gr.SelectData, responses): """Select a response from the table""" idx = evt.index[0] if idx < len(mock_training_samples): sample = mock_training_samples[idx] return f"Customer: {sample['input']}\n\nAI Response: {sample['ai_response']}" return "" sample_responses.select( select_response_for_feedback, inputs=[sample_responses], outputs=[selected_response] ) submit_feedback_btn.click( submit_response_feedback, inputs=[rating, improvement_suggestion], outputs=[feedback_status] ) # Show mock learning chart gr.on_load(lambda: create_mock_learning_chart(), outputs=[learning_progress]) # SETTINGS TAB with gr.Tab("βš™οΈ Settings"): with gr.Row(): gr.Markdown("### System Settings") with gr.Tabs() as settings_tabs: # General Settings with gr.Tab("General"): with gr.Row(): with gr.Column(): business_name = gr.Textbox( label="Business Name", value="Jay's Mobile Wash" ) with gr.Row(): business_phone = gr.Textbox( label="Business Phone", value="+18557059842" ) personal_phone = gr.Textbox( label="Jay's Phone", value="+15622289429" ) business_hours = gr.Textbox( label="Business Hours", value="6:00 AM - 6:00 PM" ) business_timezone = gr.Dropdown( choices=["America/Los_Angeles", "America/New_York", "America/Chicago"], label="Timezone", value="America/Los_Angeles" ) save_general_btn = gr.Button("πŸ’Ύ Save General Settings") general_status = gr.Textbox( label="Status", interactive=False, lines=1 ) save_general_btn.click( lambda: f"General settings saved successfully at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", inputs=[], outputs=[general_status] ) with gr.Column(): gr.Markdown("### System Timing Settings") with gr.Row(): ring_duration = gr.Slider( minimum=10, maximum=60, value=20, step=5, label="Ring Duration (seconds)" ) response_time = gr.Slider( minimum=1, maximum=30, value=5, step=1, label="SMS Response Time (seconds)" ) with gr.Row(): voice_timeout = gr.Slider( minimum=3, maximum=15, value=5, step=1, label="Voice Input Timeout (seconds)" ) ai_fallback_delay = gr.Slider( minimum=0, maximum=30, value=5, step=5, label="AI Fallback Delay (seconds)" ) update_timing_btn = gr.Button("⏱️ Update Timing Settings") timing_status = gr.Textbox( label="Status", interactive=False, lines=5 ) update_timing_btn.click( mock_update_settings, inputs=[ring_duration, response_time, voice_timeout, ai_fallback_delay], outputs=[timing_status] ) # API Settings with gr.Tab("API Settings"): with gr.Box(): gr.Markdown("### API Keys & Integrations") with gr.Row(): twilio_sid = gr.Textbox( label="Twilio Account SID", value="AC48c581ecc0e0f57fa4757052a2a1a1ba", type="password" ) twilio_token = gr.Textbox( label="Twilio Auth Token", value="●●●●●●●●●●●●●●●●●●●●●●●●●●●●", type="password" ) with gr.Row(): openai_key = gr.Textbox( label="OpenAI/DeepSeek API Key", value="●●●●●●●●●●●●●●●●●●●●●●●●●●●●", type="password" ) google_key = gr.Textbox( label="Google/Gemini API Key", value="●●●●●●●●●●●●●●●●●●●●●●●●●●●●", type="password" ) test_connection_btn = gr.Button("πŸ”„ Test Connections") api_status = gr.Textbox( label="API Status", interactive=False, lines=4 ) def test_api_connections(): """Mock API connection tests""" time.sleep(1.5) return ("βœ… Twilio: Connected successfully\n" "βœ… OpenAI/DeepSeek: Connected successfully\n" "βœ… Google/Gemini: Connected successfully\n" f"All systems operational as of {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") test_connection_btn.click( test_api_connections, inputs=[], outputs=[api_status] ) # Pricing Settings with gr.Tab("Pricing"): with gr.Box(): gr.Markdown("### Service Pricing") with gr.Row(): gr.Markdown("#### Basic Wash") basic_car_price = gr.Number( label="Car Price ($)", value=60 ) basic_suv_price = gr.Number( label="SUV/Truck Price ($)", value=70 ) with gr.Row(): gr.Markdown("#### Luxury Wash") luxury_car_price = gr.Number( label="Car Price ($)", value=130 ) luxury_suv_price = gr.Number( label="SUV/Truck Price ($)", value=140 ) with gr.Row(): gr.Markdown("#### Max Detail") max_car_price = gr.Number( label="Car Price ($)", value=200 ) max_suv_price = gr.Number( label="SUV/Truck Price ($)", value=210 ) save_pricing_btn = gr.Button("πŸ’° Save Pricing") pricing_status = gr.Textbox( label="Status", interactive=False, lines=1 ) save_pricing_btn.click( lambda: f"Pricing updated successfully at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", inputs=[], outputs=[pricing_status] ) # Appearance with gr.Tab("Appearance"): with gr.Box(): gr.Markdown("### UI Theme Settings") with gr.Row(): primary_color = gr.ColorPicker( label="Primary Color", value="#003366" ) secondary_color = gr.ColorPicker( label="Secondary Color", value="#CC0000" ) accent_color = gr.ColorPicker( label="Accent Color", value="#0080ff" ) with gr.Row(): theme_style = gr.Dropdown( choices=["Light", "Dark", "Auto (System)"], label="Theme Style", value="Light" ) font_family = gr.Dropdown( choices=["Segoe UI", "Arial", "Roboto", "Open Sans"], label="Font Family", value="Segoe UI" ) save_theme_btn = gr.Button("🎨 Save Theme") theme_status = gr.Textbox( label="Status", interactive=False, lines=1 ) save_theme_btn.click( lambda: f"Theme settings saved successfully at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", inputs=[], outputs=[theme_status] ) with gr.Row(): with gr.Accordion("Auto-Learning Configuration", open=False): gr.Markdown("### Configure Continuous Learning") with gr.Row(): auto_update = gr.Checkbox( label="Enable Automatic Model Updates", value=True ) update_frequency = gr.Dropdown( choices=["After Every Interaction", "Hourly", "Daily", "Weekly"], label="Update Frequency", value="Daily" ) with gr.Row(): learning_threshold = gr.Slider( minimum=0.1, maximum=1.0, value=0.7, step=0.1, label="Learning Threshold (confidence level required)" ) memory_retention = gr.Slider( minimum=1, maximum=12, value=6, step=1, label="Memory Retention (months)" ) save_learning_btn = gr.Button("🧠 Save Learning Settings") learning_config_status = gr.Textbox( label="Status", interactive=False, lines=1 ) save_learning_btn.click( lambda: f"Auto-learning configuration saved successfully at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", inputs=[], outputs=[learning_config_status] ) # Footer with gr.Row(): gr.Markdown(""" <div style="text-align: center; margin-top: 20px; padding: 10px; border-top: 1px solid #eee;"> <p>Jay's Mobile Wash AI Business System | Current Version: 1.0.0 | Last Updated: 2025-06-14</p> <p>HuggingFace Space: <a href="https://huggingface.co/spaces/jjmandog/Jayscallcenter">jjmandog/Jayscallcenter</a> | Β© 2025 Jay's Mobile Wash</p> <p><small>Current <p><small>Current Date and Time (UTC): 2025-06-14 00:54:45 | User: jjmandog</small></p> </div> """ ) # Auto-update model logic def auto_update_model(): """Background process to continuously update AI models with new learning""" gr.Info("AI model auto-update process initialized") return "Models set to auto-update based on new training data" # Initialize auto-updating in background auto_update_status = gr.Textbox(visible=False) demo.load(auto_update_model, outputs=auto_update_status) # Launch the UI - for local development if __name__ == "__main__": demo.launch() - Initial Deployment
052dba7 verified