SPB Git

spb/wp26_uqo

Public
1.8 KB · 44 lines python
1# Author: Simon-Pierre Boucher — simon-pierre.boucher@uqo.ca2"""Anthropic Claude adapter (official SDK, structured outputs via output_config.format, adaptive thinking)."""3from __future__ import annotations45import os6from typing import Any78from pydantic import BaseModel910from .base import LLMProvider, json_schema_for111213class AnthropicProvider(LLMProvider):14    name = "anthropic"1516    def __init__(self, **kw):17        super().__init__(**kw)18        import anthropic1920        if not os.environ.get("ANTHROPIC_API_KEY"):21            raise RuntimeError("ANTHROPIC_API_KEY not set")22        self.client = anthropic.AsyncAnthropic(max_retries=self.max_retries, timeout=self.timeout_s)2324    async def _raw_complete(self, *, system: str, user: str, schema: type[BaseModel], model: str, effort: str, max_tokens: int) -> tuple[str, dict[str, Any]]:25        resp = await self.client.messages.create(26            model=model,27            max_tokens=max_tokens,28            system=[{"type": "text", "text": system, "cache_control": {"type": "ephemeral"}}],29            messages=[{"role": "user", "content": user}],30            thinking={"type": "adaptive"},31            output_config={"effort": effort, "format": {"type": "json_schema", "schema": json_schema_for(schema)}},32        )33        if resp.stop_reason == "refusal":34            raise RuntimeError(f"refusal: {getattr(resp, 'stop_details', None)}")35        text = next((b.text for b in resp.content if b.type == "text"), "")36        u = resp.usage37        return text, {38            "input_tokens": u.input_tokens + (u.cache_read_input_tokens or 0) + (u.cache_creation_input_tokens or 0),39            "output_tokens": u.output_tokens,40            "cached_tokens": u.cache_read_input_tokens or 0,41            "request_id": getattr(resp, "_request_id", None),42            "stop_reason": resp.stop_reason,43        }44
Files · main
Menu

Theme