Spaces:
Running
Running
zach
commited on
Commit
·
f076d8d
1
Parent(s):
bdd90d1
Improve text length validation and make vote buttons flush with audio players
Browse files- pyproject.toml +1 -0
- src/app.py +33 -10
- src/constants.py +4 -1
- src/utils.py +32 -7
pyproject.toml
CHANGED
@@ -45,6 +45,7 @@ ignore = [
|
|
45 |
"PLR0913",
|
46 |
"PLR2004",
|
47 |
"RUF006",
|
|
|
48 |
"TD002",
|
49 |
"TD003",
|
50 |
]
|
|
|
45 |
"PLR0913",
|
46 |
"PLR2004",
|
47 |
"RUF006",
|
48 |
+
"SIM117",
|
49 |
"TD002",
|
50 |
"TD003",
|
51 |
]
|
src/app.py
CHANGED
@@ -35,6 +35,7 @@ from src.utils import (
|
|
35 |
determine_selected_option,
|
36 |
submit_voting_results,
|
37 |
validate_character_description_length,
|
|
|
38 |
)
|
39 |
|
40 |
|
@@ -116,9 +117,12 @@ class App:
|
|
116 |
Raises:
|
117 |
gr.Error: If any API or unexpected errors occur during the TTS synthesis process.
|
118 |
"""
|
119 |
-
|
120 |
-
|
121 |
-
|
|
|
|
|
|
|
122 |
|
123 |
# Select 2 TTS providers based on whether the text has been modified.
|
124 |
text_modified = text != generated_text_state
|
@@ -267,8 +271,8 @@ class App:
|
|
267 |
return (
|
268 |
gr.update(value=None),
|
269 |
gr.update(value=None, autoplay=False),
|
270 |
-
gr.update(value=constants.SELECT_OPTION_A, variant="secondary"),
|
271 |
-
gr.update(value=constants.SELECT_OPTION_B, variant="secondary"),
|
272 |
default_option_map, # Reset option_map_state as a default OptionMap
|
273 |
False,
|
274 |
)
|
@@ -314,12 +318,31 @@ class App:
|
|
314 |
show_copy_button=True,
|
315 |
)
|
316 |
synthesize_speech_button = gr.Button("Synthesize Speech", variant="primary")
|
|
|
317 |
with gr.Row(equal_height=True):
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
return (
|
324 |
text_input,
|
325 |
synthesize_speech_button,
|
|
|
35 |
determine_selected_option,
|
36 |
submit_voting_results,
|
37 |
validate_character_description_length,
|
38 |
+
validate_text_length,
|
39 |
)
|
40 |
|
41 |
|
|
|
117 |
Raises:
|
118 |
gr.Error: If any API or unexpected errors occur during the TTS synthesis process.
|
119 |
"""
|
120 |
+
try:
|
121 |
+
validate_character_description_length(character_description)
|
122 |
+
validate_text_length(text)
|
123 |
+
except ValueError as ve:
|
124 |
+
logger.warning(f"Validation error: {ve}")
|
125 |
+
raise gr.Error(str(ve))
|
126 |
|
127 |
# Select 2 TTS providers based on whether the text has been modified.
|
128 |
text_modified = text != generated_text_state
|
|
|
271 |
return (
|
272 |
gr.update(value=None),
|
273 |
gr.update(value=None, autoplay=False),
|
274 |
+
gr.update(value=constants.SELECT_OPTION_A, variant="secondary", interactive=False),
|
275 |
+
gr.update(value=constants.SELECT_OPTION_B, variant="secondary", interactive=False),
|
276 |
default_option_map, # Reset option_map_state as a default OptionMap
|
277 |
False,
|
278 |
)
|
|
|
318 |
show_copy_button=True,
|
319 |
)
|
320 |
synthesize_speech_button = gr.Button("Synthesize Speech", variant="primary")
|
321 |
+
|
322 |
with gr.Row(equal_height=True):
|
323 |
+
with gr.Column():
|
324 |
+
with gr.Group():
|
325 |
+
option_a_audio_player = gr.Audio(
|
326 |
+
label=constants.OPTION_A_LABEL,
|
327 |
+
type="filepath",
|
328 |
+
interactive=False,
|
329 |
+
)
|
330 |
+
vote_button_a = gr.Button(
|
331 |
+
constants.SELECT_OPTION_A,
|
332 |
+
interactive=False,
|
333 |
+
)
|
334 |
+
with gr.Column():
|
335 |
+
with gr.Group():
|
336 |
+
option_b_audio_player = gr.Audio(
|
337 |
+
label=constants.OPTION_B_LABEL,
|
338 |
+
type="filepath",
|
339 |
+
interactive=False,
|
340 |
+
)
|
341 |
+
vote_button_b = gr.Button(
|
342 |
+
constants.SELECT_OPTION_B,
|
343 |
+
interactive=False,
|
344 |
+
)
|
345 |
+
|
346 |
return (
|
347 |
text_input,
|
348 |
synthesize_speech_button,
|
src/constants.py
CHANGED
@@ -23,7 +23,10 @@ HUME_TO_HUME: ComparisonType = "Hume AI - Hume AI"
|
|
23 |
HUME_TO_ELEVENLABS: ComparisonType = "Hume AI - ElevenLabs"
|
24 |
|
25 |
CHARACTER_DESCRIPTION_MIN_LENGTH: int = 20
|
26 |
-
CHARACTER_DESCRIPTION_MAX_LENGTH: int =
|
|
|
|
|
|
|
27 |
|
28 |
OPTION_A_KEY: OptionKey = "option_a"
|
29 |
OPTION_B_KEY: OptionKey = "option_b"
|
|
|
23 |
HUME_TO_ELEVENLABS: ComparisonType = "Hume AI - ElevenLabs"
|
24 |
|
25 |
CHARACTER_DESCRIPTION_MIN_LENGTH: int = 20
|
26 |
+
CHARACTER_DESCRIPTION_MAX_LENGTH: int = 1000
|
27 |
+
|
28 |
+
TEXT_MIN_LENGTH: int = 100
|
29 |
+
TEXT_MAX_LENGTH: int = 1000
|
30 |
|
31 |
OPTION_A_KEY: OptionKey = "option_a"
|
32 |
OPTION_B_KEY: OptionKey = "option_b"
|
src/utils.py
CHANGED
@@ -71,13 +71,6 @@ def validate_character_description_length(character_description: str) -> None:
|
|
71 |
|
72 |
Raises:
|
73 |
ValueError: If the character description is empty, too short, or exceeds max length.
|
74 |
-
|
75 |
-
Example:
|
76 |
-
>>> validate_character_description_length("This is a character description.")
|
77 |
-
# Passes validation
|
78 |
-
|
79 |
-
>>> validate_character_description_length("")
|
80 |
-
# Raises ValueError: "Voice Description must be at least 20 characters long."
|
81 |
"""
|
82 |
stripped_character_description = character_description.strip()
|
83 |
character_description_length = len(stripped_character_description)
|
@@ -101,6 +94,38 @@ def validate_character_description_length(character_description: str) -> None:
|
|
101 |
logger.debug(f"Character description length validation passed for character_description: {truncated_description}")
|
102 |
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
def _delete_files_older_than(directory: Path, minutes: int = 30) -> None:
|
105 |
"""
|
106 |
Delete all files in the specified directory that are older than a given number of minutes.
|
|
|
71 |
|
72 |
Raises:
|
73 |
ValueError: If the character description is empty, too short, or exceeds max length.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
"""
|
75 |
stripped_character_description = character_description.strip()
|
76 |
character_description_length = len(stripped_character_description)
|
|
|
94 |
logger.debug(f"Character description length validation passed for character_description: {truncated_description}")
|
95 |
|
96 |
|
97 |
+
def validate_text_length(text: str) -> None:
|
98 |
+
"""
|
99 |
+
Validates that a text input is within specified minimum and maximum length limits.
|
100 |
+
|
101 |
+
Args:
|
102 |
+
text (str): The input text to validate.
|
103 |
+
|
104 |
+
Raises:
|
105 |
+
ValueError: If the text is empty, too short, or exceeds max length.
|
106 |
+
"""
|
107 |
+
stripped_text = text.strip()
|
108 |
+
text_length = len(stripped_text)
|
109 |
+
|
110 |
+
logger.debug(f"Voice description length being validated: {text_length} characters")
|
111 |
+
|
112 |
+
if text_length < constants.TEXT_MIN_LENGTH:
|
113 |
+
raise ValueError(
|
114 |
+
f"Your text is too short. Please enter at least "
|
115 |
+
f"{constants.TEXT_MIN_LENGTH} characters. "
|
116 |
+
f"(Current length: {text_length})"
|
117 |
+
)
|
118 |
+
if text_length > constants.TEXT_MAX_LENGTH:
|
119 |
+
raise ValueError(
|
120 |
+
f"Your text is too long. Please limit it to "
|
121 |
+
f"{constants.TEXT_MAX_LENGTH} characters. "
|
122 |
+
f"(Current length: {text_length})"
|
123 |
+
)
|
124 |
+
|
125 |
+
truncated_text = truncate_text(stripped_text)
|
126 |
+
logger.debug(f"Character description length validation passed for text: {truncated_text}")
|
127 |
+
|
128 |
+
|
129 |
def _delete_files_older_than(directory: Path, minutes: int = 30) -> None:
|
130 |
"""
|
131 |
Delete all files in the specified directory that are older than a given number of minutes.
|