Review of services (AsyncGenerator, Fatal=True)

This commit is contained in:
Mark Backman
2025-11-26 12:15:23 -05:00
parent 54ff49c4fc
commit b57a9d2546
10 changed files with 17 additions and 21 deletions

View File

@@ -472,7 +472,7 @@ class AsyncAIHttpTTSService(TTSService):
async with self._session.post(url, json=payload, headers=headers) as response: async with self._session.post(url, json=payload, headers=headers) as response:
if response.status != 200: if response.status != 200:
error_text = await response.text() error_text = await response.text()
await self.push_error(error_msg=f"Async API error: {error_text}") yield ErrorFrame(error=f"Async API error: {error_text}")
raise Exception(f"Async API returned status {response.status}: {error_text}") raise Exception(f"Async API returned status {response.status}: {error_text}")
audio_data = await response.read() audio_data = await response.read()
@@ -488,7 +488,7 @@ class AsyncAIHttpTTSService(TTSService):
yield frame yield frame
except Exception as e: except Exception as e:
await self.push_error(exception=e) yield ErrorFrame(error=f"{self} error: {e}")
finally: finally:
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()
yield TTSStoppedFrame() yield TTSStoppedFrame()

View File

@@ -703,7 +703,7 @@ class CartesiaHttpTTSService(TTSService):
async with session.post(url, json=payload, headers=headers) as response: async with session.post(url, json=payload, headers=headers) as response:
if response.status != 200: if response.status != 200:
error_text = await response.text() error_text = await response.text()
await self.push_error(error_msg=f"Cartesia API error: {error_text}") yield ErrorFrame(error=f"Cartesia API error: {error_text}")
raise Exception(f"Cartesia API returned status {response.status}: {error_text}") raise Exception(f"Cartesia API returned status {response.status}: {error_text}")
audio_data = await response.read() audio_data = await response.read()
@@ -719,7 +719,7 @@ class CartesiaHttpTTSService(TTSService):
yield frame yield frame
except Exception as e: except Exception as e:
await self.push_error(exception=e) yield ErrorFrame(error=f"{self} error: {e}")
finally: finally:
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()
yield TTSStoppedFrame() yield TTSStoppedFrame()

View File

@@ -630,8 +630,7 @@ class GladiaSTTService(STTService):
self._reconnection_attempts += 1 self._reconnection_attempts += 1
if self._reconnection_attempts > self._max_reconnection_attempts: if self._reconnection_attempts > self._max_reconnection_attempts:
await self.push_error( await self.push_error(
error_msg=f"Max reconnection attempts ({self._max_reconnection_attempts}) reached", error_msg=f"Max reconnection attempts ({self._max_reconnection_attempts}) reached"
fatal=True,
) )
self._should_reconnect = False self._should_reconnect = False
return False return False

View File

@@ -1255,7 +1255,7 @@ class GeminiLiveLLMService(LLMService):
f"Max consecutive failures ({MAX_CONSECUTIVE_FAILURES}) reached, " f"Max consecutive failures ({MAX_CONSECUTIVE_FAILURES}) reached, "
"treating as fatal error" "treating as fatal error"
) )
await self.push_error(error_msg=error_msg, exception=error, fatal=True) await self.push_error(error_msg=error_msg, exception=error)
return False return False
else: else:
logger.info( logger.info(
@@ -1742,7 +1742,7 @@ class GeminiLiveLLMService(LLMService):
# state management, and that exponential backoff for retries can have # state management, and that exponential backoff for retries can have
# cost/stability implications for a service cluster, let's just treat a # cost/stability implications for a service cluster, let's just treat a
# send-side error as fatal. # send-side error as fatal.
await self.push_error(ErrorFrame(error=f"{self} Send error: {error}", fatal=True)) await self.push_error(ErrorFrame(error=f"{self} Send error: {error}"))
def create_context_aggregator( def create_context_aggregator(
self, self,

View File

@@ -995,7 +995,7 @@ class GoogleTTSService(GoogleBaseTTSService):
yield frame yield frame
except Exception as e: except Exception as e:
await self.push_error(exception=e) yield ErrorFrame(error=f"{self} error: {e}")
class GeminiTTSService(GoogleBaseTTSService): class GeminiTTSService(GoogleBaseTTSService):

View File

@@ -287,7 +287,7 @@ class HumeTTSService(WordTTSService):
self._cumulative_time = utterance_duration self._cumulative_time = utterance_duration
except Exception as e: except Exception as e:
await self.push_error(exception=e) yield ErrorFrame(error=f"{self} error: {e}")
finally: finally:
# Ensure TTFB timer is stopped even on early failures # Ensure TTFB timer is stopped even on early failures
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()

View File

@@ -337,7 +337,7 @@ class MiniMaxHttpTTSService(TTSService):
continue continue
except Exception as e: except Exception as e:
await self.push_error(exception=e) yield ErrorFrame(error=f"{self} error: {e}")
finally: finally:
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()
yield TTSStoppedFrame() yield TTSStoppedFrame()

View File

@@ -275,7 +275,7 @@ class SarvamSTTService(STTService):
await self._socket_client.translate(**method_kwargs) await self._socket_client.translate(**method_kwargs)
except Exception as e: except Exception as e:
await self.push_error(error_msg=f"Error sending audio to Sarvam: {e}", exception=e) yield ErrorFrame(error=f"{self} error: {e}")
yield None yield None

View File

@@ -254,7 +254,7 @@ class SarvamHttpTTSService(TTSService):
async with self._session.post(url, json=payload, headers=headers) as response: async with self._session.post(url, json=payload, headers=headers) as response:
if response.status != 200: if response.status != 200:
error_text = await response.text() error_text = await response.text()
await self.push_error(error_msg=f"Sarvam API error: {error_text}") yield ErrorFrame(error=f"Sarvam API error: {error_text}")
return return
response_data = await response.json() response_data = await response.json()
@@ -263,7 +263,7 @@ class SarvamHttpTTSService(TTSService):
# Decode base64 audio data # Decode base64 audio data
if "audios" not in response_data or not response_data["audios"]: if "audios" not in response_data or not response_data["audios"]:
await self.push_error(error_msg="No audio data received") yield ErrorFrame(error="No audio data received")
return return
# Get the first audio (there should be only one for single text input) # Get the first audio (there should be only one for single text input)
@@ -284,7 +284,7 @@ class SarvamHttpTTSService(TTSService):
yield frame yield frame
except Exception as e: except Exception as e:
await self.push_error(error_msg=f"Error generating TTS: {e}", exception=e) yield ErrorFrame(error=f"{self} error: {e}")
finally: finally:
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()
yield TTSStoppedFrame() yield TTSStoppedFrame()

View File

@@ -174,16 +174,13 @@ class SpeechmaticsTTSService(TTSService):
except (ValueError, ArithmeticError): except (ValueError, ArithmeticError):
yield ErrorFrame( yield ErrorFrame(
error=f"{self} Service unavailable [503] (attempts {attempt})", error=f"{self} Service unavailable [503] (attempts {attempt})"
fatal=True,
) )
return return
# != 200 : Error # != 200 : Error
if response.status != 200: if response.status != 200:
yield ErrorFrame( yield ErrorFrame(error=f"{self} Service unavailable [{response.status}]")
error=f"{self} Service unavailable [{response.status}]", fatal=True
)
return return
# Update Pipecat metrics # Update Pipecat metrics
@@ -225,7 +222,7 @@ class SpeechmaticsTTSService(TTSService):
break break
except Exception as e: except Exception as e:
yield ErrorFrame(error=f"{self}: Error generating TTS: {e}", fatal=True) yield ErrorFrame(error=f"{self}: Error generating TTS: {e}")
finally: finally:
# Emit the TTS stopped frame # Emit the TTS stopped frame
yield TTSStoppedFrame() yield TTSStoppedFrame()