Pamudu13 commited on
Commit
e4c2725
·
verified ·
1 Parent(s): b471d49

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +369 -0
app.py ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import base64
4
+ from datetime import datetime
5
+ import requests
6
+ import trello
7
+ from dotenv import load_dotenv
8
+ import urllib3
9
+ import wave
10
+ import audioop
11
+ import io
12
+ import speech_recognition as sr
13
+
14
+ # Disable SSL warning
15
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
16
+
17
+ # Load environment variables from .env file
18
+ load_dotenv()
19
+
20
+ SAMBANOVA_API_KEY = "34115dcb-baab-4390-ab5c-e501666f9f4e"
21
+ SAMBANOVA_URL = "https://api.sambanova.ai/v1/chat/completions"
22
+
23
+ # Initialize Trello client
24
+ trello_client = trello.TrelloClient(
25
+ api_key=os.getenv('TRELLO_API_KEY'),
26
+ token=os.getenv('TRELLO_TOKEN')
27
+ )
28
+
29
+ def get_trello_members():
30
+ """Get all members from Trello workspace"""
31
+ try:
32
+ boards = trello_client.list_boards()
33
+ if not boards:
34
+ raise Exception("No Trello boards found")
35
+
36
+ board = boards[0]
37
+ members = board.get_members()
38
+ return {(member.full_name or member.username): member.id for member in members}
39
+ except Exception as e:
40
+ print(f"Error fetching Trello members: {str(e)}")
41
+ return {}
42
+
43
+ def process_audio_data(audio_path):
44
+ """Process WAV audio file"""
45
+ try:
46
+ with wave.open(audio_path, 'rb') as wav_file:
47
+ # Get audio parameters
48
+ n_channels = wav_file.getnchannels()
49
+ sampwidth = wav_file.getsampwidth()
50
+ framerate = wav_file.getframerate()
51
+ n_frames = wav_file.getnframes()
52
+
53
+ # Read audio data
54
+ audio_data = wav_file.readframes(n_frames)
55
+
56
+ # Convert to mono if stereo
57
+ if n_channels == 2:
58
+ audio_data = audioop.tomono(audio_data, sampwidth, 1, 1)
59
+
60
+ # Convert to 16-bit if needed
61
+ if sampwidth != 2:
62
+ audio_data = audioop.lin2lin(audio_data, sampwidth, 2)
63
+
64
+ # Resample to 16kHz if needed
65
+ if framerate != 16000:
66
+ audio_data, _ = audioop.ratecv(audio_data, 2, 1, framerate, 16000, None)
67
+ framerate = 16000
68
+
69
+ return audio_data, framerate
70
+
71
+ except Exception as e:
72
+ print(f"Error processing audio: {str(e)}")
73
+ raise
74
+
75
+ def transcribe_audio(audio_file):
76
+ """Convert audio to text using Speech Recognition"""
77
+ try:
78
+ # Initialize recognizer
79
+ recognizer = sr.Recognizer()
80
+
81
+ # Handle different audio input formats
82
+ if isinstance(audio_file, tuple):
83
+ audio_path = audio_file[0]
84
+ else:
85
+ audio_path = audio_file
86
+
87
+ print(f"Processing audio file: {audio_path}")
88
+
89
+ try:
90
+ # Load the audio file
91
+ with sr.AudioFile(audio_path) as source:
92
+ # Adjust for ambient noise
93
+ recognizer.adjust_for_ambient_noise(source)
94
+ # Read the audio data
95
+ audio_data = recognizer.record(source)
96
+
97
+ # Perform the transcription with increased timeout
98
+ text = recognizer.recognize_google(
99
+ audio_data,
100
+ language='en-US',
101
+ show_all=False,
102
+ with_confidence=False
103
+ )
104
+
105
+ if not text:
106
+ raise Exception("No transcription results returned")
107
+
108
+ return text.strip()
109
+
110
+ except sr.UnknownValueError:
111
+ raise Exception("Speech could not be understood. Please try speaking more clearly.")
112
+ except sr.RequestError as e:
113
+ raise Exception(f"Could not request results from Google Speech Recognition service; {e}")
114
+
115
+ except Exception as e:
116
+ print(f"Transcription error details: {str(e)}")
117
+ raise Exception(f"Transcription error: {str(e)}")
118
+
119
+ def improve_task_description(text):
120
+ """Improve and summarize task description using SambaNova API"""
121
+ try:
122
+ prompt = f"""Please improve and structure this task description for better clarity and actionability:
123
+
124
+ Original task: {text}
125
+
126
+ Please provide:
127
+ 1. A clear, concise task title
128
+ 2. Key objectives
129
+ 3. Suggested deadline (if not specified)
130
+ 4. Any important details or requirements
131
+ """
132
+
133
+ headers = {
134
+ 'Authorization': f'Bearer {SAMBANOVA_API_KEY}',
135
+ 'Content-Type': 'application/json'
136
+ }
137
+
138
+ data = {
139
+ 'messages': [
140
+ {'role': 'user', 'content': prompt}
141
+ ],
142
+ 'model': 'Meta-Llama-3.1-8B-Instruct',
143
+ 'max_tokens': 2000,
144
+ 'temperature': 0.7
145
+ }
146
+
147
+ response = requests.post(
148
+ SAMBANOVA_URL,
149
+ headers=headers,
150
+ json=data,
151
+ verify=False,
152
+ timeout=620
153
+ )
154
+
155
+ if response.status_code != 200:
156
+ raise Exception(f"SambaNova API request failed: {response.text}")
157
+
158
+ improved_text = response.json()['choices'][0]['message']['content']
159
+ return improved_text
160
+ except Exception as e:
161
+ raise Exception(f"Error improving task description: {str(e)}")
162
+
163
+ def create_trello_card(task_description, selected_members):
164
+ """Create a Trello card with the improved task description"""
165
+ try:
166
+ boards = trello_client.list_boards()
167
+ if not boards:
168
+ raise Exception("No Trello boards found")
169
+
170
+ board = boards[0]
171
+ print(f"Using board: {board.name}") # Debug print
172
+
173
+ lists = board.list_lists()
174
+ if not lists:
175
+ raise Exception("No lists found in the board")
176
+
177
+ todo_list = lists[0]
178
+ print(f"Using list: {todo_list.name}") # Debug print
179
+
180
+ # Create card with improved description
181
+ card = todo_list.add_card(
182
+ name=task_description.split('\n')[0], # First line as title
183
+ desc=task_description
184
+ )
185
+
186
+ # Debug prints
187
+ print(f"Selected members: {selected_members}")
188
+ print(f"Member types: {[type(m) for m in selected_members]}")
189
+
190
+ # Assign members to card
191
+ if selected_members:
192
+ for member_id in selected_members:
193
+ try:
194
+ card.add_member(member_id)
195
+ except Exception as e:
196
+ print(f"Error adding member {member_id}: {str(e)}")
197
+
198
+ return card.url
199
+ except Exception as e:
200
+ print(f"Trello card creation error details: {str(e)}")
201
+ raise Exception(f"Error creating Trello card: {str(e)}")
202
+
203
+ def process_input(input_text, selected_members):
204
+ """Process input text and create Trello card"""
205
+ try:
206
+ # Improve the task description
207
+ improved_description = improve_task_description(input_text)
208
+
209
+ # Create Trello card
210
+ card_url = create_trello_card(improved_description, selected_members)
211
+
212
+ # Get member names for display
213
+ members_dict = get_trello_members()
214
+ member_names = [name for name, mid in members_dict.items()
215
+ if mid in selected_members]
216
+
217
+ return f"""
218
+ Original Input:
219
+ --------------
220
+ {input_text}
221
+
222
+ Improved Task Description:
223
+ ------------------------
224
+ {improved_description}
225
+
226
+ Task Created in Trello:
227
+ ----------------------
228
+ Assigned to: {', '.join(member_names) if member_names else 'Not assigned'}
229
+ Card URL: {card_url}
230
+ """
231
+ except Exception as e:
232
+ return f"Error processing input: {str(e)}"
233
+
234
+ def process_audio(audio_file, selected_members):
235
+ """Process audio input and create Trello card"""
236
+ try:
237
+ if audio_file is None:
238
+ return "Error: No audio file or text provided"
239
+ print(f"Audio file type: {type(audio_file)}") # Debug print
240
+ print(f"Audio file content: {audio_file}") # Debug print
241
+ text = transcribe_audio(audio_file)
242
+
243
+ return process_input(text, selected_members)
244
+ except Exception as e:
245
+ print(f"Audio processing error details: {str(e)}") # Debug print
246
+ return f"Error processing audio: {str(e)}"
247
+
248
+ def process_audio_with_members(audio, selected_members):
249
+ """Process audio with selected members"""
250
+ try:
251
+ if audio is None:
252
+ return "Error: Please provide an audio input (record or upload)"
253
+
254
+ print(f"Received audio input: {type(audio)}")
255
+ print(f"Audio content: {audio}")
256
+
257
+ # Convert selected member names to member IDs
258
+ members_dict = get_trello_members()
259
+ selected_member_ids = []
260
+ for name in (selected_members or []):
261
+ if name in members_dict:
262
+ selected_member_ids.append(members_dict[name])
263
+ else:
264
+ print(f"Warning: Member {name} not found in members dictionary")
265
+
266
+ try:
267
+ result = process_audio(audio, selected_member_ids)
268
+ return result
269
+ except Exception as e:
270
+ error_msg = str(e)
271
+ if "Speech could not be understood" in error_msg:
272
+ return "Could not understand the speech. Please try again with clearer audio."
273
+ elif "Could not request results" in error_msg:
274
+ return "Network error. Please check your internet connection and try again."
275
+ else:
276
+ return f"Error processing audio: {error_msg}"
277
+
278
+ except Exception as e:
279
+ print(f"Error in process_audio_with_members: {str(e)}")
280
+ return f"Error processing audio with members: {str(e)}"
281
+
282
+ def process_text_with_members(text, selected_members):
283
+ """Process text with selected members"""
284
+ try:
285
+ # Convert selected member names to member IDs
286
+ members_dict = get_trello_members()
287
+ # Debug prints
288
+ print(f"Members dict: {members_dict}")
289
+ print(f"Selected members: {selected_members}")
290
+
291
+ selected_member_ids = []
292
+ for name in (selected_members or []):
293
+ if name in members_dict:
294
+ selected_member_ids.append(members_dict[name])
295
+ else:
296
+ print(f"Warning: Member {name} not found in members dictionary")
297
+
298
+ return process_input(text, selected_member_ids)
299
+ except Exception as e:
300
+ print(f"Error in process_text_with_members: {str(e)}")
301
+ return f"Error processing text with members: {str(e)}"
302
+
303
+ # Create Gradio interface
304
+ with gr.Blocks(title="TaskWhisper - Smart Task Manager") as interface:
305
+ gr.Markdown("# 🎙️ TaskWhisper - Smart Task Manager")
306
+ gr.Markdown("Record audio or type your task. The AI will help improve and structure your task description.")
307
+
308
+ # Get Trello members for the dropdown
309
+ members = get_trello_members()
310
+
311
+ with gr.Tab("Audio Input"):
312
+ audio_input = gr.Audio(
313
+ label="Record or Upload Audio",
314
+ sources=["microphone", "upload"],
315
+ type="filepath",
316
+ format="wav",
317
+ interactive=True
318
+ )
319
+ gr.Markdown("""
320
+ *Instructions:*
321
+ - Use microphone to record directly
322
+ - Or upload an audio file (WAV format)
323
+ - Speak clearly for better results
324
+ - Keep background noise minimal
325
+ """)
326
+ member_dropdown_audio = gr.Dropdown(
327
+ choices=list(members.keys()),
328
+ multiselect=True,
329
+ label="Assign to Members",
330
+ info="Select one or more members to assign the task",
331
+ value=[]
332
+ )
333
+ audio_button = gr.Button("Process Audio")
334
+
335
+ with gr.Tab("Text Input"):
336
+ text_input = gr.Textbox(
337
+ lines=3,
338
+ placeholder="Type your task here (e.g., 'Need to prepare quarterly report with sales data by next Friday')",
339
+ label="Text Input"
340
+ )
341
+ member_dropdown_text = gr.Dropdown(
342
+ choices=list(members.keys()),
343
+ multiselect=True,
344
+ label="Assign to Members",
345
+ info="Select one or more members to assign the task",
346
+ value=[] # Initialize with empty selection
347
+ )
348
+ text_button = gr.Button("Process Text")
349
+
350
+ output = gr.Textbox(
351
+ label="Task Details",
352
+ lines=15
353
+ )
354
+
355
+ # Set up event handlers
356
+ audio_button.click(
357
+ fn=process_audio_with_members,
358
+ inputs=[audio_input, member_dropdown_audio],
359
+ outputs=output
360
+ )
361
+
362
+ text_button.click(
363
+ fn=process_text_with_members,
364
+ inputs=[text_input, member_dropdown_text],
365
+ outputs=output
366
+ )
367
+
368
+ if __name__ == "__main__":
369
+ interface.launch(share=True)