60 lines
1.6 KiB
Python
60 lines
1.6 KiB
Python
"""Anthropic (Claude) provider implementation."""
|
|
|
|
import logging
|
|
|
|
import anthropic
|
|
|
|
from .base import AIProvider, AIResponse, Message
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AnthropicProvider(AIProvider):
|
|
"""Anthropic Claude API provider."""
|
|
|
|
def __init__(self, api_key: str, model: str = "claude-sonnet-4-20250514") -> None:
|
|
self.client = anthropic.AsyncAnthropic(api_key=api_key)
|
|
self.model = model
|
|
|
|
@property
|
|
def provider_name(self) -> str:
|
|
return "anthropic"
|
|
|
|
async def generate(
|
|
self,
|
|
messages: list[Message],
|
|
system_prompt: str | None = None,
|
|
max_tokens: int = 1024,
|
|
temperature: float = 0.7,
|
|
) -> AIResponse:
|
|
"""Generate a response using Claude."""
|
|
# Build messages list (Anthropic format)
|
|
api_messages = [{"role": m.role, "content": m.content} for m in messages]
|
|
|
|
logger.debug(f"Sending {len(api_messages)} messages to Anthropic")
|
|
|
|
response = await self.client.messages.create(
|
|
model=self.model,
|
|
max_tokens=max_tokens,
|
|
temperature=temperature,
|
|
system=system_prompt or "",
|
|
messages=api_messages, # type: ignore[arg-type]
|
|
)
|
|
|
|
# Extract text from response
|
|
content = ""
|
|
for block in response.content:
|
|
if block.type == "text":
|
|
content += block.text
|
|
|
|
usage = {
|
|
"input_tokens": response.usage.input_tokens,
|
|
"output_tokens": response.usage.output_tokens,
|
|
}
|
|
|
|
return AIResponse(
|
|
content=content,
|
|
model=response.model,
|
|
usage=usage,
|
|
)
|