jjmandog commited on
Commit
2a42ccf
Β·
verified Β·
1 Parent(s): 2662b83

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -47
app.py CHANGED
@@ -1,7 +1,7 @@
1
  #!/usr/bin/env python3
2
  """
3
- πŸš— JAY'S MOBILE WASH - HUGGINGFACE SPACES COMPATIBLE
4
- iPhone Forwarding + AI Assistant - Optimized for HuggingFace deployment
5
  """
6
 
7
  import os
@@ -14,6 +14,9 @@ from datetime import datetime, timedelta
14
  from collections import defaultdict
15
  from threading import Lock
16
  import gradio as gr
 
 
 
17
 
18
  # Load environment variables
19
  from dotenv import load_dotenv
@@ -157,7 +160,6 @@ class SimpleAI:
157
 
158
  def generate_response(self, user_input, context=None):
159
  """Generate AI response"""
160
-
161
  intent = self.detect_intent(user_input)
162
  sentiment = self.analyze_sentiment(user_input)
163
 
@@ -246,22 +248,22 @@ BUSINESS INFO:
246
  # Initialize AI processor
247
  ai = SimpleAI()
248
 
249
- # Flask app for webhooks (runs in background)
250
- from flask import Flask, request
251
-
252
- flask_app = Flask(__name__)
253
 
254
- @flask_app.route('/voice/incoming', methods=['POST'])
255
- def handle_voice():
256
  """Handle incoming voice calls"""
257
  try:
 
 
258
  if not signalwire_client or not VoiceResponse:
259
- return "Service unavailable", 503
260
 
261
- call_sid = request.form.get('CallSid')
262
- from_number = request.form.get('From')
263
- to_number = request.form.get('To')
264
- forwarded_from = request.form.get('ForwardedFrom')
265
 
266
  # Detect forwarding
267
  is_forwarded = bool(forwarded_from) or (to_number == SIGNALWIRE_PHONE)
@@ -302,29 +304,32 @@ def handle_voice():
302
  response.say("I didn't catch that. Let me connect you with Jay.", voice='alice')
303
  response.dial(JAY_PHONE, timeout=30)
304
 
305
- return str(response)
306
 
307
  except Exception as e:
308
  logger.error(f"Voice error: {e}")
309
  response = VoiceResponse()
310
  response.say("Technical issue. Connecting you with Jay.", voice='alice')
311
  response.dial(JAY_PHONE, timeout=30)
312
- return str(response)
313
 
314
- @flask_app.route('/voice/process', methods=['POST'])
315
- def process_speech():
316
  """Process customer speech"""
317
  try:
318
- call_sid = request.args.get('call_sid')
319
- is_forwarded = request.args.get('forwarded') == 'True'
320
- speech_result = request.form.get('SpeechResult', '')
321
- confidence = float(request.form.get('Confidence', '0.0'))
 
 
 
322
 
323
  if not speech_result or confidence < 0.4:
324
  response = VoiceResponse()
325
  response.say("I didn't understand clearly. Let me connect you with Jay.", voice='alice')
326
  response.dial(JAY_PHONE, timeout=30)
327
- return str(response)
328
 
329
  # Analyze intent
330
  intent = ai.detect_intent(speech_result)
@@ -334,7 +339,7 @@ def process_speech():
334
  response = VoiceResponse()
335
  response.say("Let me connect you with Jay right away.", voice='alice')
336
  response.dial(JAY_PHONE, timeout=30)
337
- return str(response)
338
 
339
  # Generate AI response
340
  context = {'forwarded': is_forwarded, 'call_sid': call_sid}
@@ -354,22 +359,24 @@ def process_speech():
354
  )
355
 
356
  response.say("Thank you for calling Jay's Mobile Wash! Have a great day!", voice='alice')
357
- return str(response)
358
 
359
  except Exception as e:
360
  logger.error(f"Speech processing error: {e}")
361
  response = VoiceResponse()
362
  response.say("Technical issue. Connecting with Jay.", voice='alice')
363
  response.dial(JAY_PHONE, timeout=30)
364
- return str(response)
365
 
366
- @flask_app.route('/sms/incoming', methods=['POST'])
367
- def handle_sms():
368
  """Handle incoming SMS"""
369
  try:
370
- message_sid = request.form.get('MessageSid')
371
- from_number = request.form.get('From')
372
- message_body = request.form.get('Body', '').strip()
 
 
373
 
374
  # Log the SMS
375
  sms_entry = {
@@ -383,7 +390,8 @@ def handle_sms():
383
  system_state.increment('sms_today')
384
 
385
  if not message_body:
386
- return send_sms("Hi! How can I help you with Jay's Mobile Wash today?", from_number)
 
387
 
388
  # Analyze message
389
  intent = ai.detect_intent(message_body)
@@ -395,7 +403,8 @@ def handle_sms():
395
  'jay' in message_body.lower()):
396
 
397
  response_text = f"I'll have Jay respond to you personally. For immediate assistance, call {JAY_PHONE}."
398
- return send_sms(response_text, from_number)
 
399
 
400
  # Generate AI response
401
  ai_response = ai.generate_response(message_body, {'sms': True})
@@ -406,13 +415,15 @@ def handle_sms():
406
 
407
  system_state.increment('ai_responses')
408
 
409
- return send_sms(ai_response, from_number)
 
410
 
411
  except Exception as e:
412
  logger.error(f"SMS error: {e}")
413
- return send_sms("Thanks for your message! Jay will get back to you soon.", from_number)
 
414
 
415
- def send_sms(message, to_number):
416
  """Send SMS response"""
417
  try:
418
  if signalwire_client:
@@ -431,13 +442,11 @@ def send_sms(message, to_number):
431
  }
432
  system_state.add_sms_log(sms_entry)
433
 
434
- return str(MessagingResponse()) if MessagingResponse else ""
435
  except Exception as e:
436
  logger.error(f"SMS send error: {e}")
437
- return ""
438
 
439
- @flask_app.route('/health')
440
- def health_check():
441
  """Health check endpoint"""
442
  health = {
443
  'status': 'healthy',
@@ -584,12 +593,12 @@ def test_ai_response(message):
584
  except Exception as e:
585
  return f"Error testing AI response: {e}"
586
 
587
- # Start Flask app in background thread
588
- def run_flask():
589
- flask_app.run(host='0.0.0.0', port=7860, debug=False)
590
 
591
- flask_thread = threading.Thread(target=run_flask, daemon=True)
592
- flask_thread.start()
593
 
594
  # Create Gradio Interface
595
  with gr.Blocks(
@@ -672,6 +681,7 @@ with gr.Blocks(
672
 
673
  - **SignalWire:** {'βœ… Connected' if signalwire_client else '❌ Not configured'}
674
  - **DeepSeek AI:** {'βœ… Connected' if DEEPSEEK_API_KEY else '⚠️ Using fallback responses'}
 
675
  - **Health Check:** [/health](./health)
676
  """)
677
 
@@ -691,8 +701,8 @@ if __name__ == "__main__":
691
  print(f"🌐 SignalWire: {'βœ… Connected' if signalwire_client else '❌ Not configured'}")
692
  print(f"🧠 DeepSeek: {'βœ… Connected' if DEEPSEEK_API_KEY else '❌ Not configured'}")
693
  print("="*60)
694
- print("πŸš€ Starting Gradio interface...")
695
- print("πŸ“ž Flask webhooks running on port 7860")
696
  print("="*60)
697
 
698
  interface.launch(
 
1
  #!/usr/bin/env python3
2
  """
3
+ πŸš— JAY'S MOBILE WASH - GRADIO + FASTAPI VERSION
4
+ iPhone Forwarding + AI Assistant - HuggingFace Spaces Optimized
5
  """
6
 
7
  import os
 
14
  from collections import defaultdict
15
  from threading import Lock
16
  import gradio as gr
17
+ from fastapi import FastAPI, Request, Form
18
+ from fastapi.responses import PlainTextResponse
19
+ import uvicorn
20
 
21
  # Load environment variables
22
  from dotenv import load_dotenv
 
160
 
161
  def generate_response(self, user_input, context=None):
162
  """Generate AI response"""
 
163
  intent = self.detect_intent(user_input)
164
  sentiment = self.analyze_sentiment(user_input)
165
 
 
248
  # Initialize AI processor
249
  ai = SimpleAI()
250
 
251
+ # FastAPI app for webhooks
252
+ fastapi_app = FastAPI()
 
 
253
 
254
+ @fastapi_app.post("/voice/incoming")
255
+ async def handle_voice(request: Request):
256
  """Handle incoming voice calls"""
257
  try:
258
+ form = await request.form()
259
+
260
  if not signalwire_client or not VoiceResponse:
261
+ return PlainTextResponse("Service unavailable", status_code=503)
262
 
263
+ call_sid = form.get('CallSid')
264
+ from_number = form.get('From')
265
+ to_number = form.get('To')
266
+ forwarded_from = form.get('ForwardedFrom')
267
 
268
  # Detect forwarding
269
  is_forwarded = bool(forwarded_from) or (to_number == SIGNALWIRE_PHONE)
 
304
  response.say("I didn't catch that. Let me connect you with Jay.", voice='alice')
305
  response.dial(JAY_PHONE, timeout=30)
306
 
307
+ return PlainTextResponse(str(response), media_type="application/xml")
308
 
309
  except Exception as e:
310
  logger.error(f"Voice error: {e}")
311
  response = VoiceResponse()
312
  response.say("Technical issue. Connecting you with Jay.", voice='alice')
313
  response.dial(JAY_PHONE, timeout=30)
314
+ return PlainTextResponse(str(response), media_type="application/xml")
315
 
316
+ @fastapi_app.post("/voice/process")
317
+ async def process_speech(request: Request):
318
  """Process customer speech"""
319
  try:
320
+ form = await request.form()
321
+ query_params = request.query_params
322
+
323
+ call_sid = query_params.get('call_sid')
324
+ is_forwarded = query_params.get('forwarded') == 'True'
325
+ speech_result = form.get('SpeechResult', '')
326
+ confidence = float(form.get('Confidence', '0.0'))
327
 
328
  if not speech_result or confidence < 0.4:
329
  response = VoiceResponse()
330
  response.say("I didn't understand clearly. Let me connect you with Jay.", voice='alice')
331
  response.dial(JAY_PHONE, timeout=30)
332
+ return PlainTextResponse(str(response), media_type="application/xml")
333
 
334
  # Analyze intent
335
  intent = ai.detect_intent(speech_result)
 
339
  response = VoiceResponse()
340
  response.say("Let me connect you with Jay right away.", voice='alice')
341
  response.dial(JAY_PHONE, timeout=30)
342
+ return PlainTextResponse(str(response), media_type="application/xml")
343
 
344
  # Generate AI response
345
  context = {'forwarded': is_forwarded, 'call_sid': call_sid}
 
359
  )
360
 
361
  response.say("Thank you for calling Jay's Mobile Wash! Have a great day!", voice='alice')
362
+ return PlainTextResponse(str(response), media_type="application/xml")
363
 
364
  except Exception as e:
365
  logger.error(f"Speech processing error: {e}")
366
  response = VoiceResponse()
367
  response.say("Technical issue. Connecting with Jay.", voice='alice')
368
  response.dial(JAY_PHONE, timeout=30)
369
+ return PlainTextResponse(str(response), media_type="application/xml")
370
 
371
+ @fastapi_app.post("/sms/incoming")
372
+ async def handle_sms(request: Request):
373
  """Handle incoming SMS"""
374
  try:
375
+ form = await request.form()
376
+
377
+ message_sid = form.get('MessageSid')
378
+ from_number = form.get('From')
379
+ message_body = form.get('Body', '').strip()
380
 
381
  # Log the SMS
382
  sms_entry = {
 
390
  system_state.increment('sms_today')
391
 
392
  if not message_body:
393
+ await send_sms("Hi! How can I help you with Jay's Mobile Wash today?", from_number)
394
+ return PlainTextResponse(str(MessagingResponse()) if MessagingResponse else "", media_type="application/xml")
395
 
396
  # Analyze message
397
  intent = ai.detect_intent(message_body)
 
403
  'jay' in message_body.lower()):
404
 
405
  response_text = f"I'll have Jay respond to you personally. For immediate assistance, call {JAY_PHONE}."
406
+ await send_sms(response_text, from_number)
407
+ return PlainTextResponse(str(MessagingResponse()) if MessagingResponse else "", media_type="application/xml")
408
 
409
  # Generate AI response
410
  ai_response = ai.generate_response(message_body, {'sms': True})
 
415
 
416
  system_state.increment('ai_responses')
417
 
418
+ await send_sms(ai_response, from_number)
419
+ return PlainTextResponse(str(MessagingResponse()) if MessagingResponse else "", media_type="application/xml")
420
 
421
  except Exception as e:
422
  logger.error(f"SMS error: {e}")
423
+ await send_sms("Thanks for your message! Jay will get back to you soon.", from_number)
424
+ return PlainTextResponse(str(MessagingResponse()) if MessagingResponse else "", media_type="application/xml")
425
 
426
+ async def send_sms(message, to_number):
427
  """Send SMS response"""
428
  try:
429
  if signalwire_client:
 
442
  }
443
  system_state.add_sms_log(sms_entry)
444
 
 
445
  except Exception as e:
446
  logger.error(f"SMS send error: {e}")
 
447
 
448
+ @fastapi_app.get("/health")
449
+ async def health_check():
450
  """Health check endpoint"""
451
  health = {
452
  'status': 'healthy',
 
593
  except Exception as e:
594
  return f"Error testing AI response: {e}"
595
 
596
+ # Start FastAPI in background thread
597
+ def run_fastapi():
598
+ uvicorn.run(fastapi_app, host="0.0.0.0", port=8000, log_level="info")
599
 
600
+ fastapi_thread = threading.Thread(target=run_fastapi, daemon=True)
601
+ fastapi_thread.start()
602
 
603
  # Create Gradio Interface
604
  with gr.Blocks(
 
681
 
682
  - **SignalWire:** {'βœ… Connected' if signalwire_client else '❌ Not configured'}
683
  - **DeepSeek AI:** {'βœ… Connected' if DEEPSEEK_API_KEY else '⚠️ Using fallback responses'}
684
+ - **FastAPI Webhooks:** βœ… Running on port 8000
685
  - **Health Check:** [/health](./health)
686
  """)
687
 
 
701
  print(f"🌐 SignalWire: {'βœ… Connected' if signalwire_client else '❌ Not configured'}")
702
  print(f"🧠 DeepSeek: {'βœ… Connected' if DEEPSEEK_API_KEY else '❌ Not configured'}")
703
  print("="*60)
704
+ print("πŸš€ Starting Gradio interface on port 7860...")
705
+ print("πŸ“ž FastAPI webhooks running on port 8000")
706
  print("="*60)
707
 
708
  interface.launch(