MickMick102 commited on
Commit
377f697
·
1 Parent(s): 423d8c5

feat: Enhance audio processing and transcription features

Browse files
app.py CHANGED
@@ -8,7 +8,7 @@ import numpy as np
8
  import sys
9
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
10
  from backend.tts import synthesize_text
11
- from backend.asr import transcribe_audio
12
  from backend.utils import preprocess_audio, is_valid_turn, preprocess_audio_simplified
13
  from backend.main import stream_chat_response
14
  import json
@@ -240,9 +240,26 @@ def response(audio: tuple[int, np.ndarray] | None, conversation_history):
240
  print(f"Audio preprocessing failed: {audio_err}")
241
  print(f"------------------------")
242
  return
 
 
 
 
 
 
 
 
 
243
 
 
 
 
 
 
 
 
244
  t0 = time.time()
245
- transcription = transcribe_audio( processed_audio)
 
246
  t_asr = time.time() - t0
247
  print(f"ASR: {t_asr:.4f}s")
248
 
@@ -250,7 +267,6 @@ def response(audio: tuple[int, np.ndarray] | None, conversation_history):
250
  print("No valid transcription; skipping response generation.")
251
  print(f"------------------------")
252
  return
253
-
254
  user_turn = {"role": "user", "content": transcription}
255
  print(f"User: {transcription}")
256
  if is_valid_turn(user_turn):
@@ -434,13 +450,13 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="orange", second
434
  fn=ReplyOnPause(
435
  response,
436
  algo_options=AlgoOptions(
437
- audio_chunk_duration=1.0,
438
- started_talking_threshold=0.85,
439
- speech_threshold=0.6
440
  ),
441
  model_options=SileroVadOptions(
442
- threshold=0.6,
443
- min_speech_duration_ms=300,
444
  max_speech_duration_s=float("inf"),
445
  min_silence_duration_ms=1200,
446
  ),
 
8
  import sys
9
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
10
  from backend.tts import synthesize_text
11
+ from backend.asr import transcribe_audio, transcribe_typhoon
12
  from backend.utils import preprocess_audio, is_valid_turn, preprocess_audio_simplified
13
  from backend.main import stream_chat_response
14
  import json
 
240
  print(f"Audio preprocessing failed: {audio_err}")
241
  print(f"------------------------")
242
  return
243
+
244
+ silence_duration_s = 0.2
245
+
246
+ # Calculate the number of samples corresponding to the silence duration
247
+ silence_samples = int(16000 * silence_duration_s)
248
+
249
+ # Create a silent audio segment (an array of zeros)
250
+ # Ensure the dtype matches your processed audio for compatibility
251
+ leading_silence = np.zeros(silence_samples, dtype=np.float32)
252
 
253
+ # Prepend the silence to the beginning of your processed audio
254
+ audio_with_padding = np.concatenate([leading_silence, processed_audio])
255
+
256
+ print(f"Added {silence_duration_s}s of silence. New shape: {audio_with_padding.shape}")
257
+
258
+ file_name = "temp.wav"
259
+ sf.write(file_name, audio_with_padding, sr)
260
  t0 = time.time()
261
+ transcription = transcribe_typhoon(file_name)
262
+ # transcription = transcribe_audio( "debug_processed.wav")
263
  t_asr = time.time() - t0
264
  print(f"ASR: {t_asr:.4f}s")
265
 
 
267
  print("No valid transcription; skipping response generation.")
268
  print(f"------------------------")
269
  return
 
270
  user_turn = {"role": "user", "content": transcription}
271
  print(f"User: {transcription}")
272
  if is_valid_turn(user_turn):
 
450
  fn=ReplyOnPause(
451
  response,
452
  algo_options=AlgoOptions(
453
+ audio_chunk_duration=1.5,
454
+ started_talking_threshold=0.35,
455
+ speech_threshold=0.2
456
  ),
457
  model_options=SileroVadOptions(
458
+ threshold=0.65,
459
+ min_speech_duration_ms=200,
460
  max_speech_duration_s=float("inf"),
461
  min_silence_duration_ms=1200,
462
  ),
backend/asr.py CHANGED
@@ -170,6 +170,15 @@ def _transcribe_with_gpt(audio_array: np.ndarray) -> str:
170
 
171
  _ASR_TYPHOON = _initialize_typhoon_pipeline()
172
 
 
 
 
 
 
 
 
 
 
173
 
174
  def transcribe_audio(audio_array: np.ndarray) -> str:
175
  """Transcribe user audio with the best available backend based on the current stage."""
 
170
 
171
  _ASR_TYPHOON = _initialize_typhoon_pipeline()
172
 
173
+ def transcribe_typhoon(path: str) -> str:
174
+ text = _ASR_TYPHOON.transcribe(path)
175
+ if text[0].text:
176
+ return text[0].text
177
+ else :
178
+ print(text)
179
+ return ""
180
+
181
+
182
 
183
  def transcribe_audio(audio_array: np.ndarray) -> str:
184
  """Transcribe user audio with the best available backend based on the current stage."""
backend/main.py CHANGED
@@ -114,7 +114,7 @@ async def _stream_chat_async(history: List[Dict[str, str]], message: str) -> Asy
114
  # limited_conversation = full_conversation[-7:]
115
  # else:
116
  # limited_conversation = full_conversation
117
- limited_comversation = full_conversation
118
  response_generator = llm_analyzer.generate_normal_response(limited_conversation)
119
 
120
  async for chunk in response_generator:
 
114
  # limited_conversation = full_conversation[-7:]
115
  # else:
116
  # limited_conversation = full_conversation
117
+ limited_conversation = full_conversation
118
  response_generator = llm_analyzer.generate_normal_response(limited_conversation)
119
 
120
  async for chunk in response_generator:
backend/systemprompt.py CHANGED
@@ -90,12 +90,16 @@ Stage 1: Consult
90
  Stage 2: Buying and get info:
91
  - This phrase when user comfirm that they want to buy the promotion or product.
92
  - Ask how many product do they want.
93
- - After get quantity, call the "summary_order" will return the promotion_id,quantity and total_price. Confirm user again that the info is correct. **Do not tell promotion_id to the user, map to the name of the promotion in the promotion description.
94
- - After user confirm the order, now ask about personal data for the shipping [full name in thai, shipping address, Customer telephone number]. ask until get all the data. Note that the input is from the asr system so the address can be inaccurate, so u can make assumption(the address must be in Thailand), if not sure, you can ask the user back for the clarification.
 
95
  - After get all the personal data, confirm user 1 last time that the info is correct.
96
  Stage 3: Send order to the backend system
97
  - After all the info correct, call "purchase_product" to send order to the system
98
  - if successful, tell user that the order is successful, if not call "call_admin"
 
 
 
99
 
100
  ## Notes:
101
  - Do not give a image or any link to the user.
 
90
  Stage 2: Buying and get info:
91
  - This phrase when user comfirm that they want to buy the promotion or product.
92
  - Ask how many product do they want.
93
+ - After get quantity, call the "summary_order" will return the promotion_id,quantity and total_price. Confirm user again that the info is correct. **Do not tell promotion_id to the user, map to the name of the promotion in the promotion description. state the user that "เก็ยเงินปลายทาง" is the only payment method available.
94
+ - After user confirm the order, now ask about personal data for the shipping [name, surname, shipping address, postal code and customer telephone number].
95
+ - Ask step by step slowly start from name then surname then address then postal code then telephone number, Ask until get all the data. Note that the input is from the asr system so the address can be inaccurate, so u can make assumption(the address must be in Thailand), if not sure, you can ask the user back for the clarification.
96
  - After get all the personal data, confirm user 1 last time that the info is correct.
97
  Stage 3: Send order to the backend system
98
  - After all the info correct, call "purchase_product" to send order to the system
99
  - if successful, tell user that the order is successful, if not call "call_admin"
100
+ Stage 4: After sales service
101
+ - Thank user for buying the product, and ask them to wait for the product to arrive in 5-7 days.
102
+ - Then ask if they have any question about the product or the order.
103
 
104
  ## Notes:
105
  - Do not give a image or any link to the user.
backend/tools.py CHANGED
@@ -65,9 +65,13 @@ TOOL_DEFINITIONS =[
65
  "type": "integer",
66
  "description": "Quantity the user wants to buy.",
67
  },
68
- "user_name": {
69
  "type": "string",
70
- "description": "Customer full name in Thai.",
 
 
 
 
71
  },
72
  "address": {
73
  "type": "string",
@@ -78,7 +82,7 @@ TOOL_DEFINITIONS =[
78
  "description": "Customer telephone number.",
79
  },
80
  },
81
- "required": ["promotion_id", "quantity", "user_name", "address", "tel"],
82
  },
83
  },
84
  },
@@ -186,7 +190,8 @@ def call_admin(cause: str, chat_history : Dict[str, str]):
186
  def purchase_product(
187
  promotion_id: str,
188
  quantity: int,
189
- user_name: str,
 
190
  address: str,
191
  tel: str,
192
  ) -> Dict[str, Any]:
@@ -197,7 +202,7 @@ def purchase_product(
197
  payload = {
198
  "promotion_id": promotion_id,
199
  "quantity": quantity,
200
- "user_name": user_name,
201
  "address": address,
202
  "tel": tel
203
  }
 
65
  "type": "integer",
66
  "description": "Quantity the user wants to buy.",
67
  },
68
+ "name": {
69
  "type": "string",
70
+ "description": "Customer name in Thai.",
71
+ },
72
+ "surname": {
73
+ "type": "string",
74
+ "description": "Customer surname in Thai.",
75
  },
76
  "address": {
77
  "type": "string",
 
82
  "description": "Customer telephone number.",
83
  },
84
  },
85
+ "required": ["promotion_id", "quantity", "name","surname", "address", "tel"],
86
  },
87
  },
88
  },
 
190
  def purchase_product(
191
  promotion_id: str,
192
  quantity: int,
193
+ name: str,
194
+ surname: str,
195
  address: str,
196
  tel: str,
197
  ) -> Dict[str, Any]:
 
202
  payload = {
203
  "promotion_id": promotion_id,
204
  "quantity": quantity,
205
+ "user_name": name + " " + surname,
206
  "address": address,
207
  "tel": tel
208
  }
backend/utils.py CHANGED
@@ -98,7 +98,7 @@ def audiosegment_to_numpy(audio, target_sample_rate=16000):
98
  return samples.astype(np.float32)
99
 
100
 
101
- def preprocess_audio(audio, target_channels=1, target_frame_rate=16000):
102
  """
103
  Ensures the audio is mono, target sample rate, and normalized to [-1, 1].
104
 
@@ -107,7 +107,12 @@ def preprocess_audio(audio, target_channels=1, target_frame_rate=16000):
107
  Returns:
108
  tuple: (target_frame_rate, normalized_audio)
109
  """
 
 
110
  sample_rate, audio_array = audio
 
 
 
111
  print(audio_array)
112
  print(audio_array[0])
113
  print(len(audio_array[0]))
 
98
  return samples.astype(np.float32)
99
 
100
 
101
+ def preprocess_audio(audio, target_channels=1, target_sr=16000):
102
  """
103
  Ensures the audio is mono, target sample rate, and normalized to [-1, 1].
104
 
 
107
  Returns:
108
  tuple: (target_frame_rate, normalized_audio)
109
  """
110
+ target_frame_rate = target_sr
111
+
112
  sample_rate, audio_array = audio
113
+ #save audio array for debug
114
+ with open("debug_audio_array.npy", "wb") as f:
115
+ np.save(f, audio_array)
116
  print(audio_array)
117
  print(audio_array[0])
118
  print(len(audio_array[0]))