Files
hunjing/backend/app/ai_provider/config/loader.py
T
2026-08-21 16:00:13 +08:00

81 lines
2.7 KiB
Python

from __future__ import annotations
from pathlib import Path
from typing import Any
import yaml
from pydantic import BaseModel
from app.ai_provider.config.models import ModelConfig, ProviderConfig
from app.core.config import settings
class _ModelsFile(BaseModel):
version: int = 1
models: list[ModelConfig]
class _ProvidersFile(BaseModel):
version: int = 1
providers: dict[str, ProviderConfig]
class _PricingFile(BaseModel):
"""pricing.yaml 顶层结构。"""
version: int = 1
pricing: dict[str, dict] = {}
def get_models_config_path() -> Path:
"""返回已解析的 models.yaml 路径(project_root/config/models.yaml)。"""
return settings.project_root / "config" / "models.yaml"
def get_providers_config_path() -> Path:
"""返回已解析的 providers.yaml 路径(project_root/config/providers.yaml)。"""
return settings.project_root / "config" / "providers.yaml"
def load_models_config(path: Path | None = None) -> list[ModelConfig]:
"""从 YAML 文件加载模型配置。如果未指定路径,使用配置中的默认路径。"""
if path is None:
path = get_models_config_path()
if not path.exists():
raise FileNotFoundError(f"Models config not found: {path}")
raw: dict[str, Any] = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
parsed = _ModelsFile.model_validate(raw)
return parsed.models
def load_providers_config(path: Path | None = None) -> dict[str, ProviderConfig]:
"""从 YAML 文件加载提供商配置。如果未指定路径,使用配置中的默认路径。"""
if path is None:
path = get_providers_config_path()
if not path.exists():
raise FileNotFoundError(f"Providers config not found: {path}")
raw: dict[str, Any] = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
# 验证前将字典键注入为 provider 的 name 字段
providers_raw = raw.get("providers", {})
for name, cfg in providers_raw.items():
if isinstance(cfg, dict) and "name" not in cfg:
cfg["name"] = name
parsed = _ProvidersFile.model_validate(raw)
return parsed.providers
def get_pricing_config_path() -> Path:
"""返回 pricing.yaml 路径(project_root/config/pricing.yaml)。"""
return settings.project_root / "config" / "pricing.yaml"
def load_pricing_config(path: Path | None = None) -> dict[str, dict]:
"""从 YAML 文件加载定价配置。"""
if path is None:
path = get_pricing_config_path()
if not path.exists():
return {}
raw: dict[str, Any] = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
parsed = _PricingFile.model_validate(raw)
return parsed.pricing