"""Abstract LLM adapter interface; model-agnostic for orchestrator and agents.""" from abc import ABC, abstractmethod from typing import Any class LLMAdapter(ABC): """ Abstract adapter for LLM completion. Implementations should handle: - openai/ - OpenAI API (GPT-4, etc.) - anthropic/ - Anthropic API (Claude, etc.) - local/ - Local models (Ollama, etc.) """ @abstractmethod def complete( self, messages: list[dict[str, str]], **kwargs: Any, ) -> str: """ Return completion text for the given messages. Args: messages: List of message dicts with 'role' and 'content' keys. **kwargs: Provider-specific options (e.g., temperature, max_tokens). Returns: The model's response text. """ ... def complete_structured( self, messages: list[dict[str, str]], schema: dict[str, Any] | None = None, **kwargs: Any, ) -> Any: """ Return structured (JSON) output. Default implementation returns None; subclasses may override to use provider-specific JSON modes (e.g., OpenAI's response_format). Args: messages: List of message dicts with 'role' and 'content' keys. schema: Optional JSON schema for response validation. **kwargs: Provider-specific options. Returns: Parsed JSON response or None if not supported/parsing fails. """ return None