iajitpanday commited on
Commit
de01ccf
·
verified ·
1 Parent(s): 23403fd

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +207 -0
app.py ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Main Flask application for the AI call assistant system.
3
+ """
4
+
5
+ from flask import Flask, request
6
+ from twilio.twiml.voice_response import VoiceResponse, Gather
7
+ import os
8
+ import requests
9
+ import json
10
+ import logging
11
+ from datetime import datetime
12
+ from utils import transcribe_audio, classify_intent, get_rag_response, text_to_speech, get_fallback_response
13
+
14
+ # Configure logging
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler("call_assistant.log"),
20
+ logging.StreamHandler()
21
+ ]
22
+ )
23
+ logger = logging.getLogger(__name__)
24
+
25
+ app = Flask(__name__)
26
+
27
+ # Twilio credentials
28
+ TWILIO_ACCOUNT_SID = "ACacb8e8cc6de0f7d6c6b9c9f252a38c67"
29
+ TWILIO_AUTH_TOKEN = "1b2826409367e9799262553538489e54"
30
+ TWILIO_PHONE_NUMBER = "+19704064410"
31
+
32
+ # Hugging Face Space URL
33
+ HF_SPACE_URL = "https://huggingface.co/spaces/iajitpanday/vBot-1.5"
34
+
35
+ # Session storage (in production, replace with a database)
36
+ call_sessions = {}
37
+
38
+ @app.route("/", methods=['GET'])
39
+ def index():
40
+ return "AI Call Assistant is running!"
41
+
42
+ @app.route("/answer", methods=['POST'])
43
+ def answer_call():
44
+ """Handle incoming Twilio calls"""
45
+ call_sid = request.values.get('CallSid')
46
+ caller = request.values.get('From', 'Unknown')
47
+
48
+ logger.info(f"Received call from {caller} with SID: {call_sid}")
49
+
50
+ # Initialize session for this call
51
+ call_sessions[call_sid] = {
52
+ 'caller': caller,
53
+ 'start_time': datetime.now().isoformat(),
54
+ 'conversation': []
55
+ }
56
+
57
+ response = VoiceResponse()
58
+
59
+ # Welcome message
60
+ response.say("Hello! Thank you for calling. How can I help you today?")
61
+
62
+ # Gather speech input
63
+ gather = Gather(input='speech',
64
+ action='/process_speech',
65
+ method='POST',
66
+ speechTimeout='auto',
67
+ speechModel='phone_call',
68
+ language='en-US')
69
+
70
+ response.append(gather)
71
+
72
+ # If no input is received
73
+ response.say("I didn't hear anything. Please call back when you're ready.")
74
+ response.hangup()
75
+
76
+ return str(response)
77
+
78
+ @app.route("/process_speech", methods=['POST'])
79
+ def process_speech():
80
+ """Process speech input from the caller"""
81
+ call_sid = request.values.get('CallSid')
82
+ speech_result = request.values.get('SpeechResult', '')
83
+
84
+ logger.info(f"Call {call_sid} - Speech input: {speech_result}")
85
+
86
+ if call_sid in call_sessions:
87
+ call_sessions[call_sid]['conversation'].append({
88
+ 'role': 'user',
89
+ 'content': speech_result,
90
+ 'timestamp': datetime.now().isoformat()
91
+ })
92
+
93
+ # Process with Whisper for better transcription (optional if Twilio's is good enough)
94
+ recording_url = request.values.get('RecordingUrl')
95
+ if recording_url:
96
+ enhanced_transcription = transcribe_audio(recording_url)
97
+ if enhanced_transcription and len(enhanced_transcription) > len(speech_result):
98
+ speech_result = enhanced_transcription
99
+
100
+ # Classify intent and get response
101
+ intent, confidence = classify_intent(speech_result)
102
+
103
+ logger.info(f"Call {call_sid} - Detected intent: {intent} (confidence: {confidence})")
104
+
105
+ # Get response from RAG system
106
+ if confidence >= 0.6:
107
+ response_text = get_rag_response(speech_result, intent, HF_SPACE_URL)
108
+ else:
109
+ response_text = get_fallback_response()
110
+
111
+ if call_sid in call_sessions:
112
+ call_sessions[call_sid]['conversation'].append({
113
+ 'role': 'assistant',
114
+ 'content': response_text,
115
+ 'timestamp': datetime.now().isoformat()
116
+ })
117
+
118
+ # Create TwiML response
119
+ response = VoiceResponse()
120
+ response.say(response_text)
121
+
122
+ # Ask if there's anything else
123
+ response.redirect('/anything_else')
124
+
125
+ return str(response)
126
+
127
+ @app.route("/anything_else", methods=['POST'])
128
+ def anything_else():
129
+ """Ask if there's anything else the caller needs help with"""
130
+ call_sid = request.values.get('CallSid')
131
+
132
+ response = VoiceResponse()
133
+
134
+ response.say("Is there anything else I can help you with today?")
135
+
136
+ # Gather speech input
137
+ gather = Gather(input='speech',
138
+ action='/handle_followup',
139
+ method='POST',
140
+ speechTimeout='auto',
141
+ speechModel='phone_call')
142
+ response.append(gather)
143
+
144
+ # If no input is received
145
+ response.say("Thank you for calling. Have a great day!")
146
+ response.hangup()
147
+
148
+ return str(response)
149
+
150
+ @app.route("/handle_followup", methods=['POST'])
151
+ def handle_followup():
152
+ """Handle the caller's follow-up response"""
153
+ call_sid = request.values.get('CallSid')
154
+ speech_result = request.values.get('SpeechResult', '')
155
+
156
+ logger.info(f"Call {call_sid} - Follow-up response: {speech_result}")
157
+
158
+ # Simple yes/no detection
159
+ if any(word in speech_result.lower() for word in ["yes", "yeah", "sure", "please", "correct"]):
160
+ response = VoiceResponse()
161
+ response.say("Great! How else can I help you today?")
162
+
163
+ # Gather speech input again
164
+ gather = Gather(input='speech',
165
+ action='/process_speech',
166
+ method='POST',
167
+ speechTimeout='auto',
168
+ speechModel='phone_call')
169
+ response.append(gather)
170
+
171
+ # If no input is received
172
+ response.say("I didn't hear anything. Thank you for calling. Goodbye!")
173
+ response.hangup()
174
+
175
+ else:
176
+ response = VoiceResponse()
177
+ response.say("Thank you for calling. Have a great day!")
178
+
179
+ # Save conversation log before hanging up
180
+ if call_sid in call_sessions:
181
+ call_sessions[call_sid]['end_time'] = datetime.now().isoformat()
182
+ # In production, save this to a database
183
+ logger.info(f"Call {call_sid} completed - Conversation log saved")
184
+
185
+ response.hangup()
186
+
187
+ return str(response)
188
+
189
+ @app.route("/call_status", methods=['POST'])
190
+ def call_status():
191
+ """Handle call status updates from Twilio"""
192
+ call_sid = request.values.get('CallSid')
193
+ call_status = request.values.get('CallStatus')
194
+
195
+ logger.info(f"Call {call_sid} status: {call_status}")
196
+
197
+ # If call ended abnormally, save the log
198
+ if call_status in ['completed', 'busy', 'failed', 'no-answer', 'canceled']:
199
+ if call_sid in call_sessions:
200
+ call_sessions[call_sid]['end_time'] = datetime.now().isoformat()
201
+ call_sessions[call_sid]['final_status'] = call_status
202
+ # In production, save this to a database
203
+
204
+ return "OK"
205
+
206
+ if __name__ == "__main__":
207
+ app.run(debug=True, host='0.0.0.0', port=5000)