Spaces:
Running
Running
zach
commited on
Commit
·
a6d4367
1
Parent(s):
63ef86b
Improve Hume API error handling
Browse files- src/app.py +9 -4
- src/integrations/__init__.py +1 -1
- src/integrations/elevenlabs_api.py +3 -3
- src/integrations/hume_api.py +10 -15
src/app.py
CHANGED
@@ -30,9 +30,10 @@ from src.constants import (
|
|
30 |
from src.integrations import (
|
31 |
AnthropicError,
|
32 |
ElevenLabsError,
|
33 |
-
generate_text_with_claude,
|
34 |
-
|
35 |
-
text_to_speech_with_elevenlabs
|
|
|
36 |
)
|
37 |
from src.theme import CustomTheme
|
38 |
from src.utils import truncate_text, validate_prompt_length
|
@@ -148,7 +149,11 @@ def text_to_speech(prompt: str, generated_text: str) -> tuple[gr.update, gr.upda
|
|
148 |
)
|
149 |
|
150 |
except ElevenLabsError as ee:
|
151 |
-
logger.error(f"ElevenLabsError while synthesizing speech: {str(ee)}")
|
|
|
|
|
|
|
|
|
152 |
return gr.update(value=None), gr.update(value=None), {}, None
|
153 |
|
154 |
except Exception as e:
|
|
|
30 |
from src.integrations import (
|
31 |
AnthropicError,
|
32 |
ElevenLabsError,
|
33 |
+
generate_text_with_claude,
|
34 |
+
HumeError,
|
35 |
+
text_to_speech_with_elevenlabs,
|
36 |
+
text_to_speech_with_hume
|
37 |
)
|
38 |
from src.theme import CustomTheme
|
39 |
from src.utils import truncate_text, validate_prompt_length
|
|
|
149 |
)
|
150 |
|
151 |
except ElevenLabsError as ee:
|
152 |
+
logger.error(f"ElevenLabsError while synthesizing speech from text: {str(ee)}")
|
153 |
+
return gr.update(value=None), gr.update(value=None), {}, None
|
154 |
+
|
155 |
+
except HumeError as he:
|
156 |
+
logger.error(f"HumeError while synthesizing speech from text: {str(he)}")
|
157 |
return gr.update(value=None), gr.update(value=None), {}, None
|
158 |
|
159 |
except Exception as e:
|
src/integrations/__init__.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
from .anthropic_api import generate_text_with_claude, AnthropicError
|
2 |
from .elevenlabs_api import text_to_speech_with_elevenlabs, ElevenLabsError
|
3 |
-
from .hume_api import text_to_speech_with_hume
|
|
|
1 |
from .anthropic_api import generate_text_with_claude, AnthropicError
|
2 |
from .elevenlabs_api import text_to_speech_with_elevenlabs, ElevenLabsError
|
3 |
+
from .hume_api import text_to_speech_with_hume, HumeError
|
src/integrations/elevenlabs_api.py
CHANGED
@@ -104,7 +104,7 @@ def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
|
104 |
Raises:
|
105 |
ElevenLabsError: If there is an error communicating with the ElevenLabs API or processing the response.
|
106 |
"""
|
107 |
-
logger.debug(f'
|
108 |
|
109 |
try:
|
110 |
# Generate audio using the ElevenLabs SDK
|
@@ -132,8 +132,8 @@ def text_to_speech_with_elevenlabs(text: str) -> bytes:
|
|
132 |
return audio
|
133 |
|
134 |
except Exception as e:
|
135 |
-
logger.exception(f'Error
|
136 |
raise ElevenLabsError(
|
137 |
-
message=f'Failed to
|
138 |
original_exception=e,
|
139 |
)
|
|
|
104 |
Raises:
|
105 |
ElevenLabsError: If there is an error communicating with the ElevenLabs API or processing the response.
|
106 |
"""
|
107 |
+
logger.debug(f'Synthesizing speech from text with ElevenLabs. Text length: {len(text)} characters.')
|
108 |
|
109 |
try:
|
110 |
# Generate audio using the ElevenLabs SDK
|
|
|
132 |
return audio
|
133 |
|
134 |
except Exception as e:
|
135 |
+
logger.exception(f'Error synthesizing speech from text with Elevenlabs: {e}')
|
136 |
raise ElevenLabsError(
|
137 |
+
message=f'Failed to synthesize speech from text with ElevenLabs: {e}',
|
138 |
original_exception=e,
|
139 |
)
|
src/integrations/hume_api.py
CHANGED
@@ -12,7 +12,7 @@ Key Features:
|
|
12 |
|
13 |
Classes:
|
14 |
- HumeConfig: Immutable configuration for interacting with the TTS API.
|
15 |
-
-
|
16 |
|
17 |
Functions:
|
18 |
- text_to_speech_with_hume: Converts text to speech using the Hume TTS API with input validation and retry logic.
|
@@ -66,7 +66,7 @@ class HumeConfig:
|
|
66 |
return random.choice(self.voices)
|
67 |
|
68 |
|
69 |
-
class
|
70 |
"""Custom exception for errors related to the Hume TTS API."""
|
71 |
def __init__(self, message: str, original_exception: Optional[Exception] = None):
|
72 |
super().__init__(message)
|
@@ -78,10 +78,11 @@ hume_config = HumeConfig()
|
|
78 |
|
79 |
|
80 |
@retry(
|
81 |
-
stop=stop_after_attempt(
|
82 |
wait=wait_fixed(2),
|
83 |
before=before_log(logger, logging.DEBUG),
|
84 |
after=after_log(logger, logging.DEBUG),
|
|
|
85 |
)
|
86 |
def text_to_speech_with_hume(prompt: str, text: str) -> bytes:
|
87 |
"""
|
@@ -95,7 +96,7 @@ def text_to_speech_with_hume(prompt: str, text: str) -> bytes:
|
|
95 |
bytes: The raw binary audio data for playback.
|
96 |
|
97 |
Raises:
|
98 |
-
|
99 |
"""
|
100 |
logger.debug(f'Processing TTS with Hume. Prompt length: {len(prompt)} characters. Text length: {len(text)} characters.')
|
101 |
|
@@ -114,7 +115,7 @@ def text_to_speech_with_hume(prompt: str, text: str) -> bytes:
|
|
114 |
# Validate response
|
115 |
if response.status_code != 200:
|
116 |
logger.error(f'Hume TTS API Error: {response.status_code} - {response.text[:200]}... (truncated)')
|
117 |
-
raise
|
118 |
|
119 |
# Process audio response
|
120 |
if response.headers.get('Content-Type', '').startswith('audio/'):
|
@@ -123,17 +124,11 @@ def text_to_speech_with_hume(prompt: str, text: str) -> bytes:
|
|
123 |
return audio_data
|
124 |
|
125 |
# Unexpected content type
|
126 |
-
raise
|
127 |
|
128 |
-
except requests.exceptions.RequestException as e:
|
129 |
-
logger.exception('Request to Hume TTS API failed.')
|
130 |
-
raise HumeException(
|
131 |
-
message=f'Failed to communicate with Hume TTS API: {e}',
|
132 |
-
original_exception=e,
|
133 |
-
)
|
134 |
except Exception as e:
|
135 |
-
logger.exception('
|
136 |
-
raise
|
137 |
-
message=f
|
138 |
original_exception=e,
|
139 |
)
|
|
|
12 |
|
13 |
Classes:
|
14 |
- HumeConfig: Immutable configuration for interacting with the TTS API.
|
15 |
+
- HumeError: Custom exception for TTS API-related errors.
|
16 |
|
17 |
Functions:
|
18 |
- text_to_speech_with_hume: Converts text to speech using the Hume TTS API with input validation and retry logic.
|
|
|
66 |
return random.choice(self.voices)
|
67 |
|
68 |
|
69 |
+
class HumeError(Exception):
|
70 |
"""Custom exception for errors related to the Hume TTS API."""
|
71 |
def __init__(self, message: str, original_exception: Optional[Exception] = None):
|
72 |
super().__init__(message)
|
|
|
78 |
|
79 |
|
80 |
@retry(
|
81 |
+
stop=stop_after_attempt(1),
|
82 |
wait=wait_fixed(2),
|
83 |
before=before_log(logger, logging.DEBUG),
|
84 |
after=after_log(logger, logging.DEBUG),
|
85 |
+
reraise=True
|
86 |
)
|
87 |
def text_to_speech_with_hume(prompt: str, text: str) -> bytes:
|
88 |
"""
|
|
|
96 |
bytes: The raw binary audio data for playback.
|
97 |
|
98 |
Raises:
|
99 |
+
HumeError: If there is an error communicating with the Hume TTS API.
|
100 |
"""
|
101 |
logger.debug(f'Processing TTS with Hume. Prompt length: {len(prompt)} characters. Text length: {len(text)} characters.')
|
102 |
|
|
|
115 |
# Validate response
|
116 |
if response.status_code != 200:
|
117 |
logger.error(f'Hume TTS API Error: {response.status_code} - {response.text[:200]}... (truncated)')
|
118 |
+
raise HumeError(f'Hume TTS API responded with status {response.status_code}: {response.text[:200]}')
|
119 |
|
120 |
# Process audio response
|
121 |
if response.headers.get('Content-Type', '').startswith('audio/'):
|
|
|
124 |
return audio_data
|
125 |
|
126 |
# Unexpected content type
|
127 |
+
raise HumeError(f'Unexpected Content-Type: {response.headers.get("Content-Type", "Unknown")}')
|
128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
except Exception as e:
|
130 |
+
logger.exception(f'Error synthesizing speech from text with Hume: {e}')
|
131 |
+
raise HumeError(
|
132 |
+
message=f'Failed to synthesize speech from text with Hume: {e}',
|
133 |
original_exception=e,
|
134 |
)
|