74 lines
2.1 KiB
Python
74 lines
2.1 KiB
Python
"""Anthropic Claude provider — uses the official SDK."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
|
|
from .base import ModelInfo, ProviderResponse
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Claude-specific env vars
|
|
# ANTHROPIC_API_KEY is read by the SDK automatically
|
|
CLAUDE_MODEL = os.environ.get("CLAUDE_MODEL", "claude-sonnet-4-20250514")
|
|
|
|
MODELS = {
|
|
"claude-sonnet-4-20250514": ModelInfo(
|
|
id="claude-sonnet-4-20250514",
|
|
vision=True,
|
|
cost_per_input_token=0.000003,
|
|
cost_per_output_token=0.000015,
|
|
notes="Best balance of quality/cost with vision",
|
|
),
|
|
"claude-haiku-4-5-20251001": ModelInfo(
|
|
id="claude-haiku-4-5-20251001",
|
|
vision=True,
|
|
cost_per_input_token=0.0000008,
|
|
cost_per_output_token=0.000004,
|
|
notes="Fastest, cheapest, good for simple brand ID",
|
|
),
|
|
"claude-opus-4-6": ModelInfo(
|
|
id="claude-opus-4-6",
|
|
vision=True,
|
|
cost_per_input_token=0.000015,
|
|
cost_per_output_token=0.000075,
|
|
notes="Highest quality, use for ambiguous cases",
|
|
),
|
|
}
|
|
|
|
|
|
class ClaudeProvider:
|
|
name = "claude"
|
|
models = MODELS
|
|
|
|
def __init__(self):
|
|
from anthropic import Anthropic
|
|
self.client = Anthropic()
|
|
self.model = CLAUDE_MODEL
|
|
|
|
def call(self, image_b64: str, prompt: str) -> ProviderResponse:
|
|
message = self.client.messages.create(
|
|
model=self.model,
|
|
max_tokens=150,
|
|
messages=[{
|
|
"role": "user",
|
|
"content": [
|
|
{
|
|
"type": "image",
|
|
"source": {
|
|
"type": "base64",
|
|
"media_type": "image/jpeg",
|
|
"data": image_b64,
|
|
},
|
|
},
|
|
{"type": "text", "text": prompt},
|
|
],
|
|
}],
|
|
)
|
|
|
|
answer = message.content[0].text.strip()
|
|
total_tokens = message.usage.input_tokens + message.usage.output_tokens
|
|
|
|
return ProviderResponse(answer=answer, total_tokens=total_tokens)
|