zcbot/core/capabilities.py

72 lines
2.0 KiB
Python

"""模型能力档案: 不同模型的参数差异都收敛到 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 = ""
# 上下文
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: '<family>.<variant>',如 '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)