File size: 3,209 Bytes
7f9dfed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Any

import yaml


@dataclass(frozen=True)
class ModelInfo:
    """Configured model metadata."""

    config_id: str
    hf_id: str
    display_name: str
    type: str
    parameters_b: float
    backend: str
    context_length: int
    notes: str
    thinking_mode: bool
    gguf: dict[str, Any]
    backend_capabilities: dict[str, list[str]]
    trust_remote_code: bool


def load_model_catalog(path: str) -> dict[str, ModelInfo]:
    raw = yaml.safe_load(Path(path).read_text(encoding="utf-8"))
    catalog = {}
    for config_id, cfg in raw.get("models", {}).items():
        catalog[config_id] = ModelInfo(
            config_id=config_id,
            hf_id=cfg["hf_id"],
            display_name=cfg.get("display_name", config_id),
            type=cfg.get("type", "text"),
            parameters_b=float(cfg.get("parameters_b", 0)),
            backend=cfg.get("backend", "placeholder"),
            context_length=int(cfg.get("context_length", 0)),
            notes=cfg.get("notes", ""),
            thinking_mode=bool(cfg.get("thinking_mode", False)),
            gguf=cfg.get("gguf", {}),
            backend_capabilities={
                backend: list(capabilities)
                for backend, capabilities in cfg.get("backend_capabilities", {}).items()
            },
            trust_remote_code=bool(cfg.get("trust_remote_code", False)),
        )
    return catalog


def model_choices(catalog: dict[str, ModelInfo], model_type: str | None = None) -> list[str]:
    choices = []
    for model in catalog.values():
        if model_type and model.type != model_type:
            continue
        choices.append(model.config_id)
    return choices


def model_summary(model: ModelInfo) -> dict[str, Any]:
    return {
        "config_id": model.config_id,
        "hf_id": model.hf_id,
        "display_name": model.display_name,
        "type": model.type,
        "parameters_b": model.parameters_b,
        "backend": model.backend,
        "context_length": model.context_length,
        "thinking_mode": model.thinking_mode,
        "gguf": model.gguf,
        "backend_capabilities": model.backend_capabilities,
        "trust_remote_code": model.trust_remote_code,
        "notes": model.notes,
    }


def validate_catalog(catalog: dict[str, ModelInfo], max_parameters_b: float = 32) -> list[str]:
    warnings = []
    for model in catalog.values():
        if model.parameters_b > max_parameters_b:
            warnings.append(
                f"{model.config_id} has {model.parameters_b}B parameters, "
                f"above the {max_parameters_b}B limit."
            )
        if model.backend == "placeholder":
            warnings.append(
                f"{model.config_id} uses placeholder backend; real inference is not wired yet."
            )
        if model.backend not in model.backend_capabilities:
            warnings.append(
                f"{model.config_id} has no capability metadata for backend {model.backend}."
            )
        if not model.hf_id:
            warnings.append(f"{model.config_id} is missing hf_id.")
    return warnings