Spaces:
Running
Running
zach
commited on
Commit
·
fc05e1d
1
Parent(s):
229217f
Improve Anthropic API error handling
Browse files- src/app.py +29 -7
- src/integrations/__init__.py +3 -3
- src/integrations/anthropic_api.py +6 -13
src/app.py
CHANGED
@@ -28,6 +28,7 @@ from src.constants import (
|
|
28 |
VOTE_FOR_OPTION_TWO
|
29 |
)
|
30 |
from src.integrations import (
|
|
|
31 |
generate_text_with_claude,
|
32 |
text_to_speech_with_hume,
|
33 |
text_to_speech_with_elevenlabs
|
@@ -50,23 +51,44 @@ def validate_and_generate_text(prompt: str) -> tuple[Union[str, gr.update], gr.u
|
|
50 |
- The generated text or an error message.
|
51 |
- The updated state of the "Generate" button.
|
52 |
"""
|
|
|
53 |
try:
|
54 |
-
validate_prompt_length(prompt, PROMPT_MAX_LENGTH, PROMPT_MIN_LENGTH)
|
55 |
except ValueError as ve:
|
56 |
logger.warning(f'Validation error: {ve}')
|
57 |
-
|
|
|
58 |
|
|
|
59 |
try:
|
60 |
generated_text = generate_text_with_claude(prompt)
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
63 |
|
64 |
logger.info(f'Generated text ({len(generated_text)} characters).')
|
65 |
-
return gr.update(value=generated_text), gr.update(interactive=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
|
|
67 |
except Exception as e:
|
68 |
-
logger.error(f'
|
69 |
-
|
|
|
|
|
|
|
|
|
70 |
|
71 |
|
72 |
|
|
|
28 |
VOTE_FOR_OPTION_TWO
|
29 |
)
|
30 |
from src.integrations import (
|
31 |
+
AnthropicError,
|
32 |
generate_text_with_claude,
|
33 |
text_to_speech_with_hume,
|
34 |
text_to_speech_with_elevenlabs
|
|
|
51 |
- The generated text or an error message.
|
52 |
- The updated state of the "Generate" button.
|
53 |
"""
|
54 |
+
# Local prompt validation
|
55 |
try:
|
56 |
+
validate_prompt_length(prompt, PROMPT_MAX_LENGTH, PROMPT_MIN_LENGTH)
|
57 |
except ValueError as ve:
|
58 |
logger.warning(f'Validation error: {ve}')
|
59 |
+
# Show validation error to user, re-enable the "Generate" button
|
60 |
+
return str(ve), gr.update(interactive=True)
|
61 |
|
62 |
+
# Call the Anthropic API to generate text
|
63 |
try:
|
64 |
generated_text = generate_text_with_claude(prompt)
|
65 |
+
|
66 |
+
# Optionally handle empty or unusual responses
|
67 |
+
if not generated_text.strip():
|
68 |
+
logger.warning("Anthropic API returned an empty response.")
|
69 |
+
return "Error: Anthropic API returned an empty response.", gr.update(interactive=True)
|
70 |
|
71 |
logger.info(f'Generated text ({len(generated_text)} characters).')
|
72 |
+
return gr.update(value=generated_text), gr.update(interactive=False)
|
73 |
+
|
74 |
+
# Handle Anthropic-specific errors
|
75 |
+
except AnthropicError as ae:
|
76 |
+
# You can log the internal error details
|
77 |
+
logger.error(f'AnthropicError while generating text: {str(ae)}')
|
78 |
+
# Return an error message about Anthropic API failing to generate text, re-enable the "Generate" button
|
79 |
+
return (
|
80 |
+
"Error: There was an issue communicating with the Anthropic API. Please try again later.",
|
81 |
+
gr.update(interactive=True),
|
82 |
+
)
|
83 |
|
84 |
+
# Catch any other unexpected exceptions
|
85 |
except Exception as e:
|
86 |
+
logger.error(f'Unexpected error while generating text: {e}')
|
87 |
+
# Return a generic catch-all error message, re-enable the "Generate" button
|
88 |
+
return (
|
89 |
+
"Error: Failed to generate text. Please try again.",
|
90 |
+
gr.update(interactive=True),
|
91 |
+
)
|
92 |
|
93 |
|
94 |
|
src/integrations/__init__.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
from .anthropic_api import generate_text_with_claude
|
2 |
-
from .
|
3 |
-
from .
|
|
|
1 |
+
from .anthropic_api import generate_text_with_claude, AnthropicError
|
2 |
+
from .elevenlabs_api import text_to_speech_with_elevenlabs
|
3 |
+
from .hume_api import text_to_speech_with_hume
|
src/integrations/anthropic_api.py
CHANGED
@@ -97,10 +97,11 @@ anthropic_config = AnthropicConfig()
|
|
97 |
wait=wait_fixed(2),
|
98 |
before=before_log(logger, logging.DEBUG),
|
99 |
after=after_log(logger, logging.DEBUG),
|
|
|
100 |
)
|
101 |
def generate_text_with_claude(prompt: str) -> str:
|
102 |
"""
|
103 |
-
Generates text using Claude via the Anthropic SDK.
|
104 |
|
105 |
Args:
|
106 |
prompt (str): The input prompt for Claude.
|
@@ -109,18 +110,11 @@ def generate_text_with_claude(prompt: str) -> str:
|
|
109 |
str: The generated text.
|
110 |
|
111 |
Raises:
|
112 |
-
ValueError: If the prompt exceeds the maximum allowed length.
|
113 |
AnthropicError: If there is an error communicating with the Anthropic API.
|
114 |
-
|
115 |
-
Example:
|
116 |
-
>>> generate_text_with_claude("Write a haiku about nature.")
|
117 |
-
"Gentle waves crashing, / Whispering secrets softly, / Infinite blue skies."
|
118 |
-
|
119 |
-
>>> generate_text_with_claude("")
|
120 |
-
"The prompt exceeds the maximum allowed length of 500 characters. Your prompt contains 512 characters."
|
121 |
"""
|
122 |
logger.debug(f'Generating text with Claude. Prompt length: {len(prompt)} characters.')
|
123 |
|
|
|
124 |
try:
|
125 |
response: Message = anthropic_config.client.messages.create(
|
126 |
model=anthropic_config.model,
|
@@ -137,7 +131,6 @@ def generate_text_with_claude(prompt: str) -> str:
|
|
137 |
|
138 |
# Process response content
|
139 |
blocks: Union[List[TextBlock], TextBlock, None] = response.content
|
140 |
-
|
141 |
if isinstance(blocks, list):
|
142 |
result = '\n\n'.join(block.text for block in blocks if isinstance(block, TextBlock))
|
143 |
logger.debug(f'Processed response from list: {truncate_text(result)}')
|
@@ -148,12 +141,12 @@ def generate_text_with_claude(prompt: str) -> str:
|
|
148 |
|
149 |
logger.warning(f'Unexpected response type: {type(blocks)}')
|
150 |
return str(blocks or 'No content generated.')
|
151 |
-
|
152 |
except Exception as e:
|
153 |
-
logger.exception(f'Error generating text with
|
154 |
raise AnthropicError(
|
155 |
message=(
|
156 |
-
f'Error generating text with
|
157 |
f'HTTP Status: {getattr(response, "status", "N/A")}. '
|
158 |
f'Prompt (truncated): {truncate_text(prompt)}. '
|
159 |
f'Model: {anthropic_config.model}, Max tokens: {anthropic_config.max_tokens}'
|
|
|
97 |
wait=wait_fixed(2),
|
98 |
before=before_log(logger, logging.DEBUG),
|
99 |
after=after_log(logger, logging.DEBUG),
|
100 |
+
reraise=True
|
101 |
)
|
102 |
def generate_text_with_claude(prompt: str) -> str:
|
103 |
"""
|
104 |
+
Generates text using Claude (Anthropic LLM) via the Anthropic SDK.
|
105 |
|
106 |
Args:
|
107 |
prompt (str): The input prompt for Claude.
|
|
|
110 |
str: The generated text.
|
111 |
|
112 |
Raises:
|
|
|
113 |
AnthropicError: If there is an error communicating with the Anthropic API.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
"""
|
115 |
logger.debug(f'Generating text with Claude. Prompt length: {len(prompt)} characters.')
|
116 |
|
117 |
+
response = None
|
118 |
try:
|
119 |
response: Message = anthropic_config.client.messages.create(
|
120 |
model=anthropic_config.model,
|
|
|
131 |
|
132 |
# Process response content
|
133 |
blocks: Union[List[TextBlock], TextBlock, None] = response.content
|
|
|
134 |
if isinstance(blocks, list):
|
135 |
result = '\n\n'.join(block.text for block in blocks if isinstance(block, TextBlock))
|
136 |
logger.debug(f'Processed response from list: {truncate_text(result)}')
|
|
|
141 |
|
142 |
logger.warning(f'Unexpected response type: {type(blocks)}')
|
143 |
return str(blocks or 'No content generated.')
|
144 |
+
|
145 |
except Exception as e:
|
146 |
+
logger.exception(f'Error generating text with Anthropic: {e}')
|
147 |
raise AnthropicError(
|
148 |
message=(
|
149 |
+
f'Error generating text with Anthropic: {e}. '
|
150 |
f'HTTP Status: {getattr(response, "status", "N/A")}. '
|
151 |
f'Prompt (truncated): {truncate_text(prompt)}. '
|
152 |
f'Model: {anthropic_config.model}, Max tokens: {anthropic_config.max_tokens}'
|