Spaces:
Running
Running
zach
commited on
Commit
·
80026d8
1
Parent(s):
97908cd
Update Anthropic integration to be async
Browse files- src/app.py +2 -2
- src/integrations/anthropic_api.py +19 -29
src/app.py
CHANGED
@@ -48,7 +48,7 @@ class App:
|
|
48 |
self.config = config
|
49 |
self.db_session_maker = db_session_maker
|
50 |
|
51 |
-
def _generate_text(
|
52 |
self,
|
53 |
character_description: str,
|
54 |
) -> Tuple[dict, str]:
|
@@ -73,7 +73,7 @@ class App:
|
|
73 |
raise gr.Error(str(ve))
|
74 |
|
75 |
try:
|
76 |
-
generated_text = generate_text_with_claude(character_description, self.config)
|
77 |
logger.info(f"Generated text ({len(generated_text)} characters).")
|
78 |
return gr.update(value=generated_text), generated_text
|
79 |
except AnthropicError as ae:
|
|
|
48 |
self.config = config
|
49 |
self.db_session_maker = db_session_maker
|
50 |
|
51 |
+
async def _generate_text(
|
52 |
self,
|
53 |
character_description: str,
|
54 |
) -> Tuple[dict, str]:
|
|
|
73 |
raise gr.Error(str(ve))
|
74 |
|
75 |
try:
|
76 |
+
generated_text = await generate_text_with_claude(character_description, self.config)
|
77 |
logger.info(f"Generated text ({len(generated_text)} characters).")
|
78 |
return gr.update(value=generated_text), generated_text
|
79 |
except AnthropicError as ae:
|
src/integrations/anthropic_api.py
CHANGED
@@ -1,21 +1,14 @@
|
|
1 |
"""
|
2 |
anthropic_api.py
|
3 |
|
4 |
-
This file defines the interaction with the Anthropic API, focusing on generating text using the Claude
|
5 |
-
It includes functionality for input validation, API request handling, and processing API responses.
|
6 |
|
7 |
Key Features:
|
8 |
- Encapsulates all logic related to the Anthropic API.
|
9 |
-
- Implements retry logic for handling transient API errors.
|
10 |
- Validates the response content to ensure API compatibility.
|
11 |
- Provides detailed logging for debugging and error tracking.
|
12 |
-
|
13 |
-
Classes:
|
14 |
-
- AnthropicConfig: Immutable configuration for interacting with the Anthropic API.
|
15 |
-
- AnthropicError: Custom exception for Anthropic API-related errors.
|
16 |
-
|
17 |
-
Functions:
|
18 |
-
- generate_text_with_claude: Generates text using the Anthropic SDK with input validation and retry logic.
|
19 |
"""
|
20 |
|
21 |
# Standard Library Imports
|
@@ -24,9 +17,9 @@ from dataclasses import dataclass, field
|
|
24 |
from typing import Any, Dict, List, Optional, Union, cast
|
25 |
|
26 |
# Third-Party Library Imports
|
27 |
-
from anthropic import
|
28 |
from anthropic.types import Message, ModelParam, TextBlock, ToolUseBlock
|
29 |
-
from tenacity import after_log, before_log, retry, stop_after_attempt, wait_fixed
|
30 |
|
31 |
# Local Application Imports
|
32 |
from src.config import Config, logger
|
@@ -57,11 +50,9 @@ Your absolute priority is delivering complete, untruncated responses within stri
|
|
57 |
</requirements>
|
58 |
"""
|
59 |
|
60 |
-
|
61 |
@dataclass(frozen=True)
|
62 |
class AnthropicConfig:
|
63 |
-
"""Immutable configuration for interacting with the Anthropic API."""
|
64 |
-
|
65 |
api_key: str = field(init=False)
|
66 |
system_prompt: str = field(init=False)
|
67 |
model: ModelParam = "claude-3-5-sonnet-latest"
|
@@ -83,18 +74,19 @@ class AnthropicConfig:
|
|
83 |
object.__setattr__(self, "system_prompt", computed_prompt)
|
84 |
|
85 |
@property
|
86 |
-
def client(self)
|
87 |
"""
|
88 |
-
Lazy initialization of the Anthropic client.
|
89 |
|
90 |
Returns:
|
91 |
-
|
92 |
"""
|
93 |
-
|
|
|
94 |
|
95 |
def build_expressive_prompt(self, character_description: str) -> str:
|
96 |
"""
|
97 |
-
Constructs and returns a prompt based solely on the provided
|
98 |
The returned prompt is intended to instruct Claude to generate expressive text from a character,
|
99 |
capturing the character's personality and emotional nuance, without including the system prompt.
|
100 |
|
@@ -131,41 +123,39 @@ class UnretryableAnthropicError(AnthropicError):
|
|
131 |
|
132 |
|
133 |
@retry(
|
|
|
134 |
stop=stop_after_attempt(3),
|
135 |
wait=wait_fixed(2),
|
136 |
before=before_log(logger, logging.DEBUG),
|
137 |
after=after_log(logger, logging.DEBUG),
|
138 |
reraise=True,
|
139 |
)
|
140 |
-
def generate_text_with_claude(character_description: str, config: Config) -> str:
|
141 |
"""
|
142 |
-
|
143 |
|
144 |
This function includes retry logic and error translation. It raises a custom
|
145 |
-
UnretryableAnthropicError for API errors
|
146 |
-
for other errors.
|
147 |
|
148 |
Args:
|
149 |
-
character_description (str): The input character description
|
150 |
config (Config): Application configuration including Anthropic settings.
|
151 |
|
152 |
Returns:
|
153 |
str: The generated text.
|
154 |
|
155 |
Raises:
|
156 |
-
UnretryableAnthropicError: For
|
157 |
AnthropicError: For other errors communicating with the Anthropic API.
|
158 |
"""
|
159 |
-
|
160 |
try:
|
161 |
anthropic_config = config.anthropic_config
|
162 |
prompt = anthropic_config.build_expressive_prompt(character_description)
|
163 |
logger.debug(f"Generating text with Claude. Character description length: {len(prompt)} characters.")
|
164 |
|
165 |
-
# Ensure system_prompt is set (guaranteed by __post_init__)
|
166 |
assert anthropic_config.system_prompt is not None, "system_prompt must be set."
|
167 |
|
168 |
-
response: Message = anthropic_config.client.messages.create(
|
169 |
model=anthropic_config.model,
|
170 |
max_tokens=anthropic_config.max_tokens,
|
171 |
system=anthropic_config.system_prompt,
|
|
|
1 |
"""
|
2 |
anthropic_api.py
|
3 |
|
4 |
+
This file defines the asynchronous interaction with the Anthropic API, focusing on generating text using the Claude
|
5 |
+
model. It includes functionality for input validation, asynchronous API request handling, and processing API responses.
|
6 |
|
7 |
Key Features:
|
8 |
- Encapsulates all logic related to the Anthropic API.
|
9 |
+
- Implements asynchronous retry logic for handling transient API errors.
|
10 |
- Validates the response content to ensure API compatibility.
|
11 |
- Provides detailed logging for debugging and error tracking.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
"""
|
13 |
|
14 |
# Standard Library Imports
|
|
|
17 |
from typing import Any, Dict, List, Optional, Union, cast
|
18 |
|
19 |
# Third-Party Library Imports
|
20 |
+
from anthropic import APIError
|
21 |
from anthropic.types import Message, ModelParam, TextBlock, ToolUseBlock
|
22 |
+
from tenacity import after_log, before_log, retry, retry_if_exception, stop_after_attempt, wait_fixed
|
23 |
|
24 |
# Local Application Imports
|
25 |
from src.config import Config, logger
|
|
|
50 |
</requirements>
|
51 |
"""
|
52 |
|
|
|
53 |
@dataclass(frozen=True)
|
54 |
class AnthropicConfig:
|
55 |
+
"""Immutable configuration for interacting with the Anthropic API using the asynchronous client."""
|
|
|
56 |
api_key: str = field(init=False)
|
57 |
system_prompt: str = field(init=False)
|
58 |
model: ModelParam = "claude-3-5-sonnet-latest"
|
|
|
74 |
object.__setattr__(self, "system_prompt", computed_prompt)
|
75 |
|
76 |
@property
|
77 |
+
def client(self):
|
78 |
"""
|
79 |
+
Lazy initialization of the asynchronous Anthropic client.
|
80 |
|
81 |
Returns:
|
82 |
+
AsyncAnthropic: Configured asynchronous client instance.
|
83 |
"""
|
84 |
+
from anthropic import AsyncAnthropic # Import the async client from Anthropic SDK
|
85 |
+
return AsyncAnthropic(api_key=self.api_key)
|
86 |
|
87 |
def build_expressive_prompt(self, character_description: str) -> str:
|
88 |
"""
|
89 |
+
Constructs and returns a prompt based solely on the provided character description.
|
90 |
The returned prompt is intended to instruct Claude to generate expressive text from a character,
|
91 |
capturing the character's personality and emotional nuance, without including the system prompt.
|
92 |
|
|
|
123 |
|
124 |
|
125 |
@retry(
|
126 |
+
retry=retry_if_exception(lambda e: not isinstance(e, UnretryableAnthropicError)),
|
127 |
stop=stop_after_attempt(3),
|
128 |
wait=wait_fixed(2),
|
129 |
before=before_log(logger, logging.DEBUG),
|
130 |
after=after_log(logger, logging.DEBUG),
|
131 |
reraise=True,
|
132 |
)
|
133 |
+
async def generate_text_with_claude(character_description: str, config: Config) -> str:
|
134 |
"""
|
135 |
+
Asynchronously generates text using Claude (Anthropic LLM) via the asynchronous Anthropic SDK.
|
136 |
|
137 |
This function includes retry logic and error translation. It raises a custom
|
138 |
+
UnretryableAnthropicError for unretryable API errors and AnthropicError for other errors.
|
|
|
139 |
|
140 |
Args:
|
141 |
+
character_description (str): The input character description.
|
142 |
config (Config): Application configuration including Anthropic settings.
|
143 |
|
144 |
Returns:
|
145 |
str: The generated text.
|
146 |
|
147 |
Raises:
|
148 |
+
UnretryableAnthropicError: For unretryable API errors.
|
149 |
AnthropicError: For other errors communicating with the Anthropic API.
|
150 |
"""
|
|
|
151 |
try:
|
152 |
anthropic_config = config.anthropic_config
|
153 |
prompt = anthropic_config.build_expressive_prompt(character_description)
|
154 |
logger.debug(f"Generating text with Claude. Character description length: {len(prompt)} characters.")
|
155 |
|
|
|
156 |
assert anthropic_config.system_prompt is not None, "system_prompt must be set."
|
157 |
|
158 |
+
response: Message = await anthropic_config.client.messages.create(
|
159 |
model=anthropic_config.model,
|
160 |
max_tokens=anthropic_config.max_tokens,
|
161 |
system=anthropic_config.system_prompt,
|