"""模型能力档案: 不同模型的参数差异都收敛到 yaml,加新模型不用改代码。""" from __future__ import annotations from dataclasses import dataclass, field, fields from pathlib import Path from typing import List import yaml @dataclass class ModelCapabilities: model_id: str = "" family: str = "" variant: str = "" display_name: str = "" # UI 展示用,如 "DeepSeek V4 Flash";空时前端 fallback 拼 family.variant # 上下文 max_context: int = 128_000 reliable_context: int = 64_000 max_output: int = 4096 # Tool calling parallel_tools: bool = False tool_calling_quality: str = "good" # 思考模式 thinking_mode: bool = False reasoning_effort_levels: List[str] = field(default_factory=list) default_reasoning_effort: str = "" # 代码 / 沙盒 code_quality: str = "good" enable_run_python: bool = False # 工程参数 max_iterations: int = 50 optimal_temperature: float = 0.3 # provider 特性 prompt_caching: bool = False extended_thinking: bool = False # API 接入 api_base: str = "" api_key_env: str = "" @classmethod def load(cls, name: str, models_dir: Path) -> "ModelCapabilities": """name: '.',如 'deepseek_v4.flash'。""" if "." in name: family, variant = name.split(".", 1) else: family, variant = name, "default" path = Path(models_dir) / f"{family}.yaml" if not path.exists(): raise FileNotFoundError(f"模型档案不存在: {path}") data = yaml.safe_load(path.read_text(encoding="utf-8")) or {} variants = data.get("variants", {}) if variant not in variants: raise ValueError( f"档案 {path} 没有 variant={variant};可选: {list(variants)}" ) var = variants[variant] valid_keys = {f.name for f in fields(cls)} kwargs = {k: v for k, v in var.items() if k in valid_keys} kwargs["family"] = data.get("family", family) kwargs["variant"] = variant return cls(**kwargs)