""" Base Model Adapter. Abstract base class for model-specific context formatting. """ from abc import ABC, abstractmethod from typing import Any, ClassVar from ..types import BaseContext, ContextType class ModelAdapter(ABC): """ Abstract base adapter for model-specific context formatting. Each adapter knows how to format contexts for optimal understanding by a specific LLM family (Claude, OpenAI, etc.). """ # Model name patterns this adapter handles MODEL_PATTERNS: ClassVar[list[str]] = [] @classmethod def matches_model(cls, model: str) -> bool: """ Check if this adapter handles the given model. Args: model: Model name to check Returns: True if this adapter handles the model """ model_lower = model.lower() return any(pattern in model_lower for pattern in cls.MODEL_PATTERNS) @abstractmethod def format( self, contexts: list[BaseContext], **kwargs: Any, ) -> str: """ Format contexts for the target model. Args: contexts: List of contexts to format **kwargs: Additional formatting options Returns: Formatted context string """ ... @abstractmethod def format_type( self, contexts: list[BaseContext], context_type: ContextType, **kwargs: Any, ) -> str: """ Format contexts of a specific type. Args: contexts: List of contexts of the same type context_type: The type of contexts **kwargs: Additional formatting options Returns: Formatted string for this context type """ ... def get_type_order(self) -> list[ContextType]: """ Get the preferred order of context types. Returns: List of context types in preferred order """ return [ ContextType.SYSTEM, ContextType.TASK, ContextType.KNOWLEDGE, ContextType.CONVERSATION, ContextType.TOOL, ] def group_by_type( self, contexts: list[BaseContext] ) -> dict[ContextType, list[BaseContext]]: """ Group contexts by their type. Args: contexts: List of contexts to group Returns: Dictionary mapping context type to list of contexts """ by_type: dict[ContextType, list[BaseContext]] = {} for context in contexts: ct = context.get_type() if ct not in by_type: by_type[ct] = [] by_type[ct].append(context) return by_type def get_separator(self) -> str: """ Get the separator between context sections. Returns: Separator string """ return "\n\n" class DefaultAdapter(ModelAdapter): """ Default adapter for unknown models. Uses simple plain-text formatting with minimal structure. """ MODEL_PATTERNS: ClassVar[list[str]] = [] # Fallback adapter @classmethod def matches_model(cls, model: str) -> bool: """Always returns True as fallback.""" return True def format( self, contexts: list[BaseContext], **kwargs: Any, ) -> str: """Format contexts as plain text.""" if not contexts: return "" by_type = self.group_by_type(contexts) parts: list[str] = [] for ct in self.get_type_order(): if ct in by_type: formatted = self.format_type(by_type[ct], ct, **kwargs) if formatted: parts.append(formatted) return self.get_separator().join(parts) def format_type( self, contexts: list[BaseContext], context_type: ContextType, **kwargs: Any, ) -> str: """Format contexts of a type as plain text.""" if not contexts: return "" content = "\n\n".join(c.content for c in contexts) if context_type == ContextType.SYSTEM: return content elif context_type == ContextType.TASK: return f"Task:\n{content}" elif context_type == ContextType.KNOWLEDGE: return f"Reference Information:\n{content}" elif context_type == ContextType.CONVERSATION: return f"Previous Conversation:\n{content}" elif context_type == ContextType.TOOL: return f"Tool Results:\n{content}" return content