"""Configuration data models.
This module defines the data classes used for configuration management.
"""
import os
from dataclasses import asdict, dataclass, field
from typing import Any, Dict, List, Optional
from .enums import ProviderType
[docs]
@dataclass
class ModelConfig:
"""Configuration for a specific model.
Attributes:
name: Model identifier (e.g., "gpt-4o", "claude-3-5-sonnet-20241022")
provider: LLM provider
api_key_env_var: Environment variable name for API key
max_tokens: Maximum tokens for this model
temperature: Default temperature (0.0 to 2.0)
top_p: Default top_p sampling parameter
frequency_penalty: Frequency penalty for repetition
presence_penalty: Presence penalty for topic diversity
endpoint: Custom API endpoint (optional)
api_version: API version for provider (e.g., Azure)
deployment_name: Deployment name (for Azure)
timeout: Request timeout in seconds
max_retries: Maximum retry attempts
metadata: Additional metadata
"""
name: str
provider: ProviderType
api_key_env_var: Optional[str] = None
max_tokens: int = 4096
temperature: float = 0.7
top_p: float = 1.0
frequency_penalty: float = 0.0
presence_penalty: float = 0.0
endpoint: Optional[str] = None
api_version: Optional[str] = None
deployment_name: Optional[str] = None
timeout: float = 60.0
max_retries: int = 3
metadata: Dict[str, Any] = field(default_factory=dict)
[docs]
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary, handling enum serialization."""
data = asdict(self)
data["provider"] = self.provider.value
return data
[docs]
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "ModelConfig":
"""Create from dictionary, handling enum deserialization."""
if isinstance(data.get("provider"), str):
data["provider"] = ProviderType(data["provider"])
return cls(**data)
[docs]
@dataclass
class ProviderConfig:
"""Configuration for an LLM provider.
Attributes:
provider: Provider type
api_key: API key (prefer api_key_env_var for security)
api_key_env_var: Environment variable containing API key
base_url: Base URL for API endpoint
organization: Organization ID (for OpenAI)
timeout: Default timeout in seconds
max_retries: Default max retry attempts
rate_limit: Rate limit (requests per minute)
models: Available models for this provider
metadata: Additional provider metadata
"""
provider: ProviderType
api_key: Optional[str] = None
api_key_env_var: Optional[str] = None
base_url: Optional[str] = None
organization: Optional[str] = None
timeout: float = 60.0
max_retries: int = 3
rate_limit: Optional[int] = None
models: List[str] = field(default_factory=list)
metadata: Dict[str, Any] = field(default_factory=dict)
[docs]
def get_api_key(self) -> Optional[str]:
"""Get API key from env var or direct value.
Priority:
1. Environment variable (if set and exists)
2. Direct API key value
"""
if self.api_key_env_var:
env_key = os.getenv(self.api_key_env_var)
if env_key:
return env_key
return self.api_key
[docs]
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary."""
data = asdict(self)
data["provider"] = self.provider.value
return data
[docs]
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "ProviderConfig":
"""Create from dictionary."""
if isinstance(data.get("provider"), str):
data["provider"] = ProviderType(data["provider"])
return cls(**data)
[docs]
@dataclass
class AppConfig:
"""Complete application configuration.
Attributes:
app_name: Application name
default_model: Default model to use
providers: Provider configurations
models: Model configurations
metadata: Additional application metadata
"""
app_name: str
default_model: Optional[str] = None
providers: Dict[ProviderType, ProviderConfig] = field(default_factory=dict)
models: Dict[str, ModelConfig] = field(default_factory=dict)
metadata: Dict[str, Any] = field(default_factory=dict)
[docs]
def to_dict(self) -> Dict[str, Any]:
"""Convert to dictionary."""
data = {
"app_name": self.app_name,
"default_model": self.default_model,
"providers": {p.value: pc.to_dict() for p, pc in self.providers.items()},
"models": {k: mc.to_dict() for k, mc in self.models.items()},
"metadata": self.metadata,
}
return data
[docs]
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "AppConfig":
"""Create from dictionary."""
if "providers" in data:
data["providers"] = {
ProviderType(k) if isinstance(k, str) else k: ProviderConfig.from_dict(
v
)
for k, v in data["providers"].items()
}
if "models" in data:
data["models"] = {
k: ModelConfig.from_dict(v) for k, v in data["models"].items()
}
return cls(**data)