85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
"""LLM Config - 配置加载"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
from agentkit.llm.retry import CircuitBreakerConfig, RetryConfig
|
|
|
|
|
|
@dataclass
|
|
class ProviderConfig:
|
|
"""Provider 配置"""
|
|
|
|
api_key: str
|
|
base_url: str
|
|
models: dict[str, dict[str, Any]] = field(default_factory=dict)
|
|
type: str = "openai" # "openai" | "anthropic" | "gemini"
|
|
max_tokens: int = 4096 # Anthropic: default max_tokens
|
|
timeout: float = 120.0 # Anthropic: request timeout
|
|
max_connections: int = 100 # httpx 连接池最大连接数
|
|
max_keepalive_connections: int = 20 # httpx 连接池最大保活连接数
|
|
keepalive_expiry: float = 30.0 # httpx 保活连接过期时间(秒)
|
|
retry: RetryConfig | None = None
|
|
circuit_breaker: CircuitBreakerConfig | None = None
|
|
|
|
|
|
@dataclass
|
|
class LLMConfig:
|
|
"""LLM 配置"""
|
|
|
|
providers: dict[str, ProviderConfig] = field(default_factory=dict)
|
|
model_aliases: dict[str, str] = field(default_factory=dict)
|
|
fallbacks: dict[str, list[str]] = field(default_factory=dict)
|
|
|
|
@classmethod
|
|
def from_yaml(cls, path: str) -> "LLMConfig":
|
|
"""从 YAML 文件加载配置"""
|
|
with open(path, encoding="utf-8") as f:
|
|
data = yaml.safe_load(f)
|
|
return cls.from_dict(data or {})
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: dict) -> "LLMConfig":
|
|
"""从字典加载配置"""
|
|
providers = {}
|
|
for name, pconf in data.get("providers", {}).items():
|
|
retry = None
|
|
retry_data = pconf.get("retry")
|
|
if retry_data:
|
|
retry = RetryConfig(
|
|
max_retries=retry_data.get("max_retries", 3),
|
|
base_delay=retry_data.get("base_delay", 1.0),
|
|
max_delay=retry_data.get("max_delay", 30.0),
|
|
exponential_base=retry_data.get("exponential_base", 2.0),
|
|
)
|
|
|
|
circuit_breaker = None
|
|
cb_data = pconf.get("circuit_breaker")
|
|
if cb_data:
|
|
circuit_breaker = CircuitBreakerConfig(
|
|
failure_threshold=cb_data.get("failure_threshold", 5),
|
|
recovery_timeout=cb_data.get("recovery_timeout", 60.0),
|
|
half_open_max=cb_data.get("half_open_max", 1),
|
|
)
|
|
|
|
providers[name] = ProviderConfig(
|
|
api_key=pconf.get("api_key", ""),
|
|
base_url=pconf.get("base_url", ""),
|
|
models=pconf.get("models", {}),
|
|
type=pconf.get("type", "openai"),
|
|
max_tokens=pconf.get("max_tokens", 4096),
|
|
timeout=pconf.get("timeout", 120.0),
|
|
max_connections=pconf.get("max_connections", 100),
|
|
max_keepalive_connections=pconf.get("max_keepalive_connections", 20),
|
|
keepalive_expiry=pconf.get("keepalive_expiry", 30.0),
|
|
retry=retry,
|
|
circuit_breaker=circuit_breaker,
|
|
)
|
|
return cls(
|
|
providers=providers,
|
|
model_aliases=data.get("model_aliases", {}),
|
|
fallbacks=data.get("fallbacks", {}),
|
|
)
|