blizzarman/polyglot-tutor
0
1"""LLM client contract.2 3Anything that can turn a chat into text satisfies `LLMClient` — the app, the4exercise generators and the evals only ever depend on this Protocol, never on5a vendor SDK (same pattern for ASR / TTS / storage).6"""7 8from collections.abc import Sequence9from typing import Literal, Protocol, runtime_checkable10 11from pydantic import BaseModel12 13Role = Literal["system", "user", "assistant"]14 15 16class ChatMessage(BaseModel):17 role: Role18 content: str19 20 21class LLMResponse(BaseModel):22 text: str23 model: str24 input_tokens: int | None = None25 output_tokens: int | None = None26 27 28class LLMError(RuntimeError):29 """A completion failed (network, auth, rate limit, provider error...)."""30 31 32@runtime_checkable33class LLMClient(Protocol):34 async def complete(35 self,36 messages: Sequence[ChatMessage],37 *,38 temperature: float = 0.7,39 max_tokens: int = 1024,40 ) -> LLMResponse: ...41 