e58159fc42
Phase 1: 异常体系统一 - 新增 PlatformError / PlatformErrorType 标准定义 - 改造所有 Provider 异常抛出为 PlatformError - 注册全局 PlatformError exception handler Phase 2: Adapter Protocol - 新增 app/ai/adapters/base.py(PlatformAdapter + SyncCapable + TaskCapable + CallbackCapable) - 新增 app/ai/adapters/constants.py(Method 常量) - 新增 PlatformConfigLoader(config/platform-config.yaml) Phase 3: HTTP Client 统一 - ViduProvider 从 aiohttp 迁移到 httpx(注入方式) - VolcengineCaptionService 改为注入 http_client - lifespan 统一管理所有 Client 创建和关闭 Phase 4: Gateway 骨架 + Adapter 实现 - 新增 ViduAdapter / VolcengineArkAdapter / VolcengineCaptionAdapter - 新增 PlatformGateway(call_sync / submit_task / query_task / handle_webhook) - 新增 LLMGateway(带 Fallback 降级链) - lifespan 注册所有 Adapter 和 Gateway Phase 6: 清理与验证 - 从 Settings 移除 VIDU_BASE_URL / VOLCENGINE_BASE_URL - Provider 改为从 PlatformConfigLoader 读取 base_url - 清理 volcengine_caption_service 全局单例 - config_loader 默认路径改为 platform-config.yaml - Scheduler 注入共享 HTTP client - vidu.py 回调路由使用 Adapter 验签和解析 - ruff 全量通过,应用启动测试通过
136 lines
4.0 KiB
Python
136 lines
4.0 KiB
Python
"""
|
|
平台配置加载器
|
|
==============
|
|
|
|
从 config/platform-config.yaml 加载平台配置,
|
|
包含:平台连接信息、模型列表、方法配置、限流参数。
|
|
|
|
运行时策略(fallback_chains、timeouts、ttl)通过 RuntimeConfig 读取。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
try:
|
|
import yaml
|
|
|
|
YAML_AVAILABLE = True
|
|
except ImportError:
|
|
YAML_AVAILABLE = False
|
|
|
|
|
|
@dataclass
|
|
class MethodConfig:
|
|
"""方法级配置"""
|
|
|
|
name: str
|
|
timeout: int = 30
|
|
max_connections: int = 20
|
|
rate_limit_qps: float = 10.0
|
|
rate_limit_burst: int = 20
|
|
|
|
|
|
@dataclass
|
|
class PlatformConfig:
|
|
"""平台配置"""
|
|
|
|
id: str
|
|
name: str
|
|
provider: str
|
|
base_url: str = ""
|
|
rate_limit_qps: float = 10.0
|
|
rate_limit_burst: int = 20
|
|
models: list[dict[str, Any]] = field(default_factory=list)
|
|
methods: dict[str, MethodConfig] = field(default_factory=dict)
|
|
|
|
|
|
class PlatformConfigLoader:
|
|
"""平台配置加载器
|
|
|
|
从 platform-config.yaml 的 platforms section 加载配置。
|
|
"""
|
|
|
|
DEFAULT_CONFIG_PATH = (
|
|
Path(__file__).parent.parent.parent / "config" / "platform-config.yaml"
|
|
)
|
|
|
|
def __init__(self, config_path: str | None = None):
|
|
self.config_path = Path(config_path) if config_path else self.DEFAULT_CONFIG_PATH
|
|
self._platforms: dict[str, PlatformConfig] = {}
|
|
self._load()
|
|
|
|
def _load(self) -> bool:
|
|
if not self.config_path.exists():
|
|
logger.warning(f"平台配置文件不存在: {self.config_path}")
|
|
return False
|
|
|
|
try:
|
|
with open(self.config_path, encoding="utf-8") as f:
|
|
if YAML_AVAILABLE:
|
|
config = yaml.safe_load(f)
|
|
else:
|
|
import json
|
|
|
|
config = json.load(f)
|
|
|
|
platforms_data = config.get("platforms", {})
|
|
for pid, pdata in platforms_data.items():
|
|
methods: dict[str, MethodConfig] = {}
|
|
for mname, mdata in pdata.get("methods", {}).items():
|
|
rl = mdata.get("rate_limit", {})
|
|
methods[mname] = MethodConfig(
|
|
name=mname,
|
|
timeout=mdata.get("timeout", 30),
|
|
max_connections=mdata.get("max_connections", 20),
|
|
rate_limit_qps=rl.get("qps", 10.0),
|
|
rate_limit_burst=rl.get("burst", 20),
|
|
)
|
|
|
|
prl = pdata.get("rate_limit", {})
|
|
self._platforms[pid] = PlatformConfig(
|
|
id=pid,
|
|
name=pdata.get("name", pid),
|
|
provider=pdata.get("provider", pid),
|
|
base_url=pdata.get("base_url", ""),
|
|
rate_limit_qps=prl.get("qps", 10.0),
|
|
rate_limit_burst=prl.get("burst", 20),
|
|
models=pdata.get("models", []),
|
|
methods=methods,
|
|
)
|
|
|
|
logger.info(f"Platform config loaded: {len(self._platforms)} platforms")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Platform config load failed: {e}")
|
|
return False
|
|
|
|
def get_platform(self, platform_id: str) -> PlatformConfig | None:
|
|
return self._platforms.get(platform_id)
|
|
|
|
def get_all_platforms(self) -> list[PlatformConfig]:
|
|
return list(self._platforms.values())
|
|
|
|
def get_method_config(self, platform_id: str, method: str) -> MethodConfig | None:
|
|
platform = self._platforms.get(platform_id)
|
|
if platform:
|
|
return platform.methods.get(method)
|
|
return None
|
|
|
|
|
|
# 全局单例
|
|
_platform_config_loader: PlatformConfigLoader | None = None
|
|
|
|
|
|
def get_platform_config_loader() -> PlatformConfigLoader:
|
|
global _platform_config_loader
|
|
if _platform_config_loader is None:
|
|
_platform_config_loader = PlatformConfigLoader()
|
|
return _platform_config_loader
|