SPB Git

spb/ai-atlas

Public
22.1 KB · 361 lines python
1"""Model identity ontology — the rules that separate a MODEL (release) from its ARTIFACTS (checkpoints, conversions, quantisations),2its EVALUATION VARIANTS (reasoning-effort settings of the same weights) and its FAMILY.34    MODEL FAMILY   Llama 4 · Qwen3.6 · Claude · Gemini5      └ MODEL      Llama 4 Maverick · Qwen3.6-35B-A3B · Claude Fable 5.16          └ ARTIFACT  meta-llama/Llama-4-Maverick-17B-128E-Instruct (official checkpoint) · unsloth/…-GGUF (third-party quantisation)7              └ DEPLOYMENT  OpenRouter meta-llama/llama-4-maverick · Together meta-llama/Llama-4-Maverick  (= prices rows)89Everything here is deterministic string analysis. It never *asserts* a relation on its own: the resolution service uses these10signals together with identifiers, organisations, `base_model` metadata and dates, and parks anything ambiguous in the review queue.11"""12from __future__ import annotations1314import re15from dataclasses import dataclass, field1617# ---------------------------------------------------------------------------------------------- quantisation / precision formats18QUANT_FORMATS: dict[str, str] = {19    # token (lowercase, matched on word boundaries) → canonical format20    "gguf": "gguf", "ggml": "gguf", "q2_k": "gguf", "q3_k_m": "gguf", "q4_k_m": "gguf", "q4_k_s": "gguf", "q5_k_m": "gguf", "q6_k": "gguf", "q8_0": "gguf",21    "q4_0": "gguf", "q4_1": "gguf", "q5_0": "gguf", "iq4_xs": "gguf", "iq3_m": "gguf", "iq2_m": "gguf", "ud-q4_k_xl": "gguf",22    "awq": "awq", "w4a16": "awq", "gptq": "gptq", "exl2": "exl2", "exl3": "exl3", "mlx": "mlx", "onnx": "onnx", "openvino": "openvino", "coreml": "coreml",23    "tensorrt": "tensorrt", "trt": "tensorrt", "trt-llm": "tensorrt", "bnb": "bnb", "bitsandbytes": "bnb", "nf4": "bnb", "4bit": "int4", "8bit": "int8",24    "int4": "int4", "int8": "int8", "w8a8": "int8", "w8a16": "int8", "fp8": "fp8", "fp8-kv": "fp8", "e4m3": "fp8", "nvfp4": "nvfp4", "mxfp4": "mxfp4",25    "mxfp8": "mxfp8", "fp4": "fp4", "quark": "quark", "quantized": "quantized", "quant": "quantized", "qat": "qat", "hqq": "hqq", "aqlm": "aqlm", "eetq": "eetq",26    "smoothquant": "smoothquant", "compressed-tensors": "compressed-tensors", "marlin": "gptq", "gptq-int4": "gptq", "autoround": "autoround",27    "2bit": "int2", "3bit": "int3", "5bit": "int5", "6bit": "int6", "2-bit": "int2", "3-bit": "int3", "4-bit": "int4", "5-bit": "int5", "6-bit": "int6", "8-bit": "int8",28}29# Full-precision dtype tokens: a "-BF16" or "-FP16" repo is a *conversion/packaging* of the same weights, not a quantisation.30PRECISION_FORMATS = {"bf16", "fp16", "fp32", "f16", "f32", "float16", "bfloat16", "half"}31ARTIFACT_PACKAGING = {"safetensors", "pytorch", "pth", "ckpt", "jax", "flax", "tf", "tflite", "litert", "gguf", "mlx", "onnx", "coreml", "openvino", "tensorrt"}3233# Third-party organisations that (almost) only publish conversions/quantisations of other people's models.34CONVERTER_ORGS = {35    "unsloth", "bartowski", "mlx-community", "thebloke", "lmstudio-community", "qwen-community", "mradermacher", "quantfactory", "nousresearch-quant",36    "mistral-community", "turboderp", "casperhansen", "neuralmagic", "redhatai", "amd", "intel", "nvidia-quant", "ggml-org", "second-state",37    "mlx-vision", "cortexso", "gaianet", "bunnycore", "dranger003", "ubergarm", "anthracite-org", "modelcloud", "jinaai-quant", "ai-forever-quant",38    "lmstudio", "ollama", "ggerganov", "mlc-ai", "onnx-community", "onnxmodelzoo", "kaitchup", "thedrummer-quant",39}4041# ---------------------------------------------------------------------------------------------- evaluation-effort variants (same weights, different setting)42# Suffixes appended by evaluators (Artificial Analysis, LiveBench…) to a model slug to denote a *configuration* of the model.43EFFORT_SUFFIXES: dict[str, dict[str, str]] = {44    "xhigh": {"reasoning_effort": "xhigh"}, "x-high": {"reasoning_effort": "xhigh"}, "extra-high": {"reasoning_effort": "xhigh"},45    "high": {"reasoning_effort": "high"}, "medium": {"reasoning_effort": "medium"}, "low": {"reasoning_effort": "low"}, "minimal": {"reasoning_effort": "minimal"},46    "max-effort": {"reasoning_effort": "max"}, "high-effort": {"reasoning_effort": "high"}, "low-effort": {"reasoning_effort": "low"},47    "medium-effort": {"reasoning_effort": "medium"}, "xhigh-effort": {"reasoning_effort": "xhigh"},48    "thinking": {"reasoning": "on"}, "reasoning": {"reasoning": "on"}, "think": {"reasoning": "on"}, "thinking-on": {"reasoning": "on"},49    "non-reasoning": {"reasoning": "off"}, "no-reasoning": {"reasoning": "off"}, "non-thinking": {"reasoning": "off"}, "nothink": {"reasoning": "off"},50    "no-think": {"reasoning": "off"}, "no-thinking": {"reasoning": "off"}, "thinking-off": {"reasoning": "off"}, "without-thinking": {"reasoning": "off"},51    "with-thinking": {"reasoning": "on"},52    "adaptive": {"reasoning": "adaptive"}, "adaptive-reasoning": {"reasoning": "adaptive"},53    # NOT effort suffixes although evaluators sometimes use them: "max" (Qwen3-Max, GPT-5.1-Codex-Max are models), "fast" (Grok 4.1 Fast),54    # "instant" (Claude Instant) — they name a model tier, so they are only recognised in the explicit "-max-effort" form above.55    "thinking-16k": {"reasoning": "on", "thinking_budget": "16k"}, "thinking-32k": {"reasoning": "on", "thinking_budget": "32k"},56    "thinking-64k": {"reasoning": "on", "thinking_budget": "64k"}, "thinking-128k": {"reasoning": "on", "thinking_budget": "128k"},57    "thinking-8k": {"reasoning": "on", "thinking_budget": "8k"}, "thinking-4k": {"reasoning": "on", "thinking_budget": "4k"}, "thinking-1k": {"reasoning": "on", "thinking_budget": "1k"},58}59# order matters: try the longest compound suffixes first60_EFFORT_ORDERED = sorted(EFFORT_SUFFIXES, key=len, reverse=True)61_EFFORT_RE = re.compile(r"[-_ ](" + "|".join(re.escape(s) for s in _EFFORT_ORDERED) + r")$", re.I)62# LiveBench-style budgets: "32k-thinking", "24k-think", "default-think(ing)"63_BUDGET_RE = re.compile(r"[-_ ]((\d+)k)[-_ ]?(thinking|think)$", re.I)64_DEFAULT_THINK_RE = re.compile(r"[-_ ](default[-_ ]?(thinking|think))$", re.I)65_MAX_EFFORT_SUFFIXES = 3     # "claude-opus-4-5-20251101-thinking-64k-high-effort" → thinking-64k + high-effort66# Words that are *part of a model name*, never an effort suffix, when they precede the suffix (e.g. "Kimi K2 Thinking" is a distinct release).67OFFICIAL_THINKING_RELEASES = {"kimi-k2-thinking", "qwen3-235b-a22b-thinking-2507", "qwen3-30b-a3b-thinking-2507", "qwen3-4b-thinking-2507", "glm-4.5-air-thinking",68                              "gemini-2.5-flash-thinking", "grok-3-mini-thinking", "gemini-2-0-flash-thinking-exp-1219", "gemini-2-0-flash-thinking-exp-01-21"}6970# ---------------------------------------------------------------------------------------------- name analysis71_SIZE_RE = re.compile(r"(?<![a-z0-9])(\d+(?:\.\d+)?)\s?([bmt])(?![a-z])", re.I)          # 70B 3.8B 235B 1.5T 350M72_ACTIVE_RE = re.compile(r"(?<![a-z0-9])(\d+(?:\.\d+)?)\s?[bmt]\s?-?a(\d+(?:\.\d+)?)\s?([bmt])(?![a-z])", re.I)   # 35B-A3B73_DATE_RE = re.compile(r"(?<!\d)(20\d{2})[-_.]?(0[1-9]|1[0-2])[-_.]?(0[1-9]|[12]\d|3[01])(?!\d)")   # 2024062074_MMDD_RE = re.compile(r"(?<![0-9])(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])(?![0-9])")                   # 0905 / 0324 (release snapshots)75_YYMM_RE = re.compile(r"(?<![0-9])(2[3-9])(0[1-9]|1[0-2])(?![0-9])")                                 # 2507 (Qwen-style)76_TRAILING_VARIANT_WORDS = {"instruct", "it", "chat", "base", "sft", "dpo", "rl", "hf", "preview", "exp", "experimental", "latest", "beta", "alpha", "v1", "v2", "v3",77                           "mtp", "distill", "distilled", "uncensored", "abliterated", "heretic", "merge"}78_TOKEN_SPLIT = re.compile(r"[\s_/]+|(?<=[a-z])(?=[A-Z][a-z])")798081@dataclass82class NameAnalysis:83    raw: str84    repo_org: str | None = None                    # "unsloth" in "unsloth/Qwen3.6-35B-A3B-GGUF"85    repo_name: str | None = None                   # "Qwen3.6-35B-A3B-GGUF"86    base_key: str = ""                             # normalised key with quant/precision/effort tokens removed: "qwen3.6-35b-a3b"87    quant_formats: list[str] = field(default_factory=list)     # ["gguf"]88    precision: str | None = None                   # "bf16" when only a precision tag is present89    is_quantized: bool = False90    is_conversion: bool = False                    # packaging/precision conversion without quantisation (BF16 repack, MLX fp16, ONNX)91    from_converter_org: bool = False92    effort: dict[str, str] = field(default_factory=dict)       # {"reasoning_effort": "xhigh"} when an evaluator suffix was stripped93    effort_suffix: str | None = None94    parameter_count: int | None = None95    active_parameter_count: int | None = None96    snapshot_date: str | None = None               # "2024-06-20" / "2025-09" style date embedded in the name97    family_hint: str | None = None                 # "Qwen3.6", "Llama 4", "Claude", "Gemini 2.5"9899    @property100    def is_artifact(self) -> bool:101        return self.is_quantized or self.is_conversion102103    @property104    def is_effort_variant(self) -> bool:105        return bool(self.effort)106107108def _to_count(num: str, unit: str) -> int:109    mult = {"m": 1e6, "b": 1e9, "t": 1e12}[unit.lower()]110    return int(round(float(num) * mult))111112113def analyze_model_name(raw: str) -> NameAnalysis:114    """Deterministic analysis of a model / repository name."""115    a = NameAnalysis(raw=raw.strip())116    name = a.raw117    if "/" in name and " " not in name.split("/")[0]:118        org, _, rest = name.partition("/")119        a.repo_org, a.repo_name = org.strip(), rest.strip()120        name = rest121        a.from_converter_org = org.strip().lower() in CONVERTER_ORGS122    low = re.sub(r"[\s_]+", "-", name.lower().strip())123    low = re.sub(r"[()\[\]]+", "-", low).strip("-")124    low = re.sub(r"-{2,}", "-", low)125126    # evaluator effort suffixes (up to three, e.g. "-thinking-64k-high-effort"), only when the stem is not itself an official "Thinking" release127    stripped: list[str] = []128    for _ in range(_MAX_EFFORT_SUFFIXES):129        if low in OFFICIAL_THINKING_RELEASES:130            break131        m = _BUDGET_RE.search(low)              # "-32k-thinking" before the bare "-thinking"132        if m:133            a.effort = {"reasoning": "on", "thinking_budget": m.group(1).lower(), **a.effort}134            stripped.insert(0, m.group(0)[1:].lower())135            low = low[: m.start()]136            continue137        m = _DEFAULT_THINK_RE.search(low)138        if m:139            a.effort = {"reasoning": "on", **a.effort}140            stripped.insert(0, m.group(1).lower())141            low = low[: m.start()]142            continue143        m = _EFFORT_RE.search(low)144        if m:145            suffix = m.group(1).lower()146            a.effort = {**EFFORT_SUFFIXES[suffix], **a.effort}147            stripped.insert(0, suffix)148            low = low[: m.start()]149            continue150        break151    if stripped:152        a.effort_suffix = "-".join(stripped)153154    # sizes155    am = _ACTIVE_RE.search(low)156    if am:157        a.parameter_count = _to_count(am.group(1), low[am.start(1) + len(am.group(1)):].strip()[0])158        a.active_parameter_count = _to_count(am.group(2), am.group(3))159    else:160        sizes = _SIZE_RE.findall(low)161        if sizes:162            counts = [_to_count(n, u) for n, u in sizes]163            a.parameter_count = max(counts)164165    # dates embedded in the name166    dm = _DATE_RE.search(low)167    if dm:168        a.snapshot_date = f"{dm.group(1)}-{dm.group(2)}-{dm.group(3)}"169    else:170        ym = _YYMM_RE.search(low)171        if ym and not _SIZE_RE.search(ym.group(0)):172            a.snapshot_date = f"20{ym.group(1)}-{ym.group(2)}"173174    # quantisation / precision tokens175    tokens = [t for t in re.split(r"[-_\s./()\[\]]+", low) if t]176    quant: list[str] = []177    precision = None178    kept: list[str] = []179    for t in tokens:180        if t in QUANT_FORMATS:181            quant.append(QUANT_FORMATS[t])182            continue183        if t in PRECISION_FORMATS:184            precision = t185            continue186        if re.fullmatch(r"(w\d+a\d+|q\d(_[a-z0-9]+)*|iq\d(_[a-z0-9]+)*|\d-?bit|int\d|fp\d|nvfp\d|mxfp\d)", t):187            quant.append(QUANT_FORMATS.get(t, "quantized"))188            continue189        kept.append(t)190    # "GGUF" / "MLX" packaging counts as artifact even without a bit-width; "MLX-8bit" is quantised191    a.quant_formats = sorted(set(quant))192    a.precision = precision193    a.is_quantized = any(q not in ("onnx", "coreml", "openvino", "tensorrt", "mlx", "gguf") for q in a.quant_formats) or "gguf" in a.quant_formats194    a.is_conversion = (not a.is_quantized) and (bool(a.quant_formats) or precision is not None or (a.from_converter_org and bool(a.repo_org)))195    if "mlx" in a.quant_formats and any(q.startswith("int") for q in a.quant_formats):196        a.is_quantized = True197198    a.base_key = "-".join(kept).strip("-")199    a.family_hint = family_hint(name)200    return a201202203# ---------------------------------------------------------------------------------------------- family inference204_FAMILY_PATTERNS: list[tuple[re.Pattern[str], str]] = [205    (re.compile(r"\bclaude\b", re.I), "Claude"),206    (re.compile(r"\bgpt[- ]?(oss)\b", re.I), "gpt-oss"),207    (re.compile(r"\b(chat)?gpt[- ]?\d", re.I), "GPT"),208    (re.compile(r"\bo[1-9](-| |$|mini|pro)", re.I), "OpenAI o-series"),209    (re.compile(r"\bgemini\b", re.I), "Gemini"),210    (re.compile(r"\bgemma(?=\d|\b)", re.I), "Gemma"),211    (re.compile(r"\bpalm\b", re.I), "PaLM"),212    (re.compile(r"\bllama(?=\d|\b)", re.I), "Llama"),213    (re.compile(r"\bmistral\b", re.I), "Mistral"),214    (re.compile(r"\bmixtral\b", re.I), "Mixtral"),215    (re.compile(r"\bministral\b", re.I), "Ministral"),216    (re.compile(r"\b(codestral|devstral|magistral|pixtral|voxtral)\b", re.I), None),  # own families, name = family217    (re.compile(r"\bqwen(?=\d|\b)|\bqwq\b|\bqvq\b", re.I), "Qwen"),218    (re.compile(r"\bdeepseek\b", re.I), "DeepSeek"),219    (re.compile(r"\bkimi\b", re.I), "Kimi"),220    (re.compile(r"\bglm(?=\d|\b)|\bchatglm\b", re.I), "GLM"),221    (re.compile(r"\bgrok\b", re.I), "Grok"),222    (re.compile(r"\bcommand\b", re.I), "Command"),223    (re.compile(r"\baya\b", re.I), "Aya"),224    (re.compile(r"\bphi(?=\d|\b)", re.I), "Phi"),225    (re.compile(r"\bnemotron\b", re.I), "Nemotron"),226    (re.compile(r"\bgranite\b", re.I), "Granite"),227    (re.compile(r"\bolmo(?=\d|\b)", re.I), "OLMo"),228    (re.compile(r"\bmolmo\b", re.I), "Molmo"),229    (re.compile(r"\bfalcon\b", re.I), "Falcon"),230    (re.compile(r"\byi\b", re.I), "Yi"),231    (re.compile(r"\bminimax\b", re.I), "MiniMax"),232    (re.compile(r"\bhunyuan\b", re.I), "Hunyuan"),233    (re.compile(r"\bernie\b", re.I), "ERNIE"),234    (re.compile(r"\bseed\b", re.I), "Seed"),235    (re.compile(r"\bdoubao\b", re.I), "Doubao"),236    (re.compile(r"\bstep\b", re.I), "Step"),237    (re.compile(r"\binternlm(?=\d|\b)|\binternvl(?=\d|\b)", re.I), "InternLM"),238    (re.compile(r"\bjamba\b", re.I), "Jamba"),239    (re.compile(r"\blfm(?=\d|\b)", re.I), "LFM"),240    (re.compile(r"\bexaone(?=\d|\b)", re.I), "EXAONE"),241    (re.compile(r"\bsolar\b", re.I), "Solar"),242    (re.compile(r"\bnova\b", re.I), "Nova"),243    (re.compile(r"\btitan\b", re.I), "Titan"),244    (re.compile(r"\bsonar\b", re.I), "Sonar"),245    (re.compile(r"\bstable[- ]?diffusion\b|\bsdxl\b|\bsd3\b", re.I), "Stable Diffusion"),246    (re.compile(r"\bflux\b", re.I), "FLUX"),247    (re.compile(r"\bwhisper\b", re.I), "Whisper"),248    (re.compile(r"\bdall[- ]?e\b", re.I), "DALL·E"),249    (re.compile(r"\bsora\b", re.I), "Sora"),250    (re.compile(r"\bveo\b", re.I), "Veo"),251    (re.compile(r"\bimagen\b", re.I), "Imagen"),252    (re.compile(r"\bcogito\b", re.I), "Cogito"),253    (re.compile(r"\bhermes\b", re.I), "Hermes"),254    (re.compile(r"\bsmol(lm|vlm)\b", re.I), "SmolLM"),255    (re.compile(r"\bbert\b", re.I), "BERT"),256    (re.compile(r"\bt5\b", re.I), "T5"),257    (re.compile(r"\bclip\b", re.I), "CLIP"),258    (re.compile(r"\bembed(ding)?\b", re.I), None),259    (re.compile(r"\brerank\b", re.I), None),260]261_FAMILY_VERSION_RE = re.compile(r"^(?P<fam>[A-Za-z][A-Za-z·\-]*?)[\s\-]?(?P<ver>\d+(?:\.\d+)?)", re.I)262263264def family_hint(name: str) -> str | None:265    """Family label without a version ("Qwen", "Llama", "Claude"). Versioned families ("Llama 3.1") are `family_release_hint`."""266    n = name.split("/")[-1]267    for pat, fam in _FAMILY_PATTERNS:268        if pat.search(n):269            if fam is None:270                m = pat.search(n)271                return m.group(0).title() if m else None272            return fam273    return None274275276def family_release_hint(name: str) -> str | None:277    """Versioned family ("Llama 3.1", "Qwen3.6", "Gemini 2.5", "Claude 4") when the name carries a version right after the family word."""278    fam = family_hint(name)279    if not fam:280        return None281    n = name.split("/")[-1]282    # version = digits right after the family word, optionally ".minor" or "-minor" (AA/OpenRouter slugs write 5.4 as 5-4);283    # a number followed by a size unit (38B, 235B, 1.5T) is a parameter count, never a version.284    m = re.search(re.escape(fam.split(" ")[0]) + r"[\s\-]?(\d+)(?![0-9]*\.?\d*[bmt](?![a-z]))(?:[.\-](\d+)(?![0-9]*[bmt](?![a-z])))?(?![0-9])", n, re.I)285    if m:286        version = m.group(1) + (f".{m.group(2)}" if m.group(2) else "")287        joined = fam in ("Qwen", "GLM", "Phi", "Yi", "Step") or re.search(re.escape(fam) + r"\d", n, re.I)288        return f"{fam}{version}" if joined else f"{fam} {version}"289    return fam290291292def variant_key(name: str) -> str:293    """Grouping key for near-duplicates: analysed base key + parameter count, ignoring org prefixes, quant/precision/effort tokens,294    separators and trailing 'instruct/chat/it' words. `Qwen3.6-35B-A3B`, `unsloth/Qwen3.6-35B-A3B-GGUF`, `Qwen3.6 35B A3B FP8` → same key."""295    a = analyze_model_name(name)296    toks = [t for t in a.base_key.split("-") if t and t not in _TRAILING_VARIANT_WORDS]297    return "-".join(toks)298299300# ---------------------------------------------------------------------------------------------- official organisations per family301# family root (lowercase `family_hint`) → organisation slugs / hub org names (lowercase) that publish the *official* checkpoints.302# A repository under one of these orgs is the model (or its official checkpoint), never a third-party artifact.303FAMILY_ORGS: dict[str, tuple[str, ...]] = {304    "llama": ("meta-llama", "meta", "meta-ai", "facebook"), "qwen": ("qwen", "alibaba", "alibaba-cloud", "alibaba-qwen"), "gemma": ("google", "google-deepmind"),305    "gemini": ("google", "google-deepmind"), "palm": ("google",), "claude": ("anthropic",), "gpt": ("openai",), "gpt-oss": ("openai",), "openai o-series": ("openai",),306    "whisper": ("openai",), "dall·e": ("openai",), "sora": ("openai",), "deepseek": ("deepseek-ai", "deepseek"), "kimi": ("moonshotai", "moonshot-ai", "moonshot"),307    "glm": ("zai-org", "thudm", "zhipu-ai", "z-ai", "zhipu"), "mistral": ("mistralai", "mistral-ai", "mistral"), "mixtral": ("mistralai", "mistral-ai", "mistral"),308    "ministral": ("mistralai", "mistral-ai", "mistral"), "codestral": ("mistralai", "mistral-ai", "mistral"), "devstral": ("mistralai", "mistral-ai", "mistral"),309    "magistral": ("mistralai", "mistral-ai", "mistral"), "pixtral": ("mistralai", "mistral-ai", "mistral"), "voxtral": ("mistralai", "mistral-ai", "mistral"),310    "phi": ("microsoft",), "grok": ("xai", "x-ai", "xai-org"), "command": ("cohereforai", "cohere", "coherelabs", "cohere-labs"), "aya": ("cohereforai", "cohere", "coherelabs"),311    "nemotron": ("nvidia",), "granite": ("ibm-granite", "ibm"), "olmo": ("allenai", "ai2"), "molmo": ("allenai", "ai2"), "falcon": ("tiiuae", "tii"), "yi": ("01-ai",),312    "minimax": ("minimaxai", "minimax"), "hunyuan": ("tencent", "tencent-hunyuan"), "ernie": ("baidu",), "seed": ("bytedance-seed", "bytedance"), "doubao": ("bytedance",),313    "step": ("stepfun-ai", "stepfun"), "internlm": ("internlm", "shanghai-ai-laboratory", "opengvlab"), "jamba": ("ai21labs", "ai21"), "lfm": ("liquidai", "liquid-ai"),314    "exaone": ("lgai-exaone", "lg-ai-research"), "solar": ("upstage",), "nova": ("amazon", "aws"), "titan": ("amazon", "aws"), "sonar": ("perplexity-ai", "perplexity"),315    "stable diffusion": ("stabilityai", "stability-ai"), "flux": ("black-forest-labs",), "veo": ("google",), "imagen": ("google",), "cogito": ("deepcogito",),316    "hermes": ("nousresearch",), "smollm": ("huggingfacetb", "hugging-face"), "bert": ("google", "google-bert"), "t5": ("google", "google-t5"), "clip": ("openai",),317}318319320def official_orgs(name: str) -> tuple[str, ...]:321    """Official organisation slugs for the family the name belongs to (empty when unknown)."""322    fam = family_hint(name)323    return FAMILY_ORGS.get(fam.lower(), ()) if fam else ()324325326def is_official_org(repo_org: str | None, name: str) -> bool:327    return bool(repo_org) and repo_org.lower() in official_orgs(name)328329330def effort_config(name: str, config: dict | None) -> dict:331    """Result configuration for an evaluation-effort variant: the effort dict (`reasoning_effort`, `reasoning`, `thinking_budget`) is merged332    into the config and the evaluator's variant slug is kept as `aa_variant_slug` so folded results stay distinguishable. Names that are333    not effort variants return the config unchanged."""334    cfg = dict(config or {})335    a = analyze_model_name(name)336    if not a.is_effort_variant:337        return cfg338    for k, v in a.effort.items():339        cfg.setdefault(k, v)340    slug = cfg.get("aa_slug") or a.raw.split("/")[-1].strip().lower().replace(" ", "-")341    cfg.setdefault("aa_variant_slug", slug)342    return cfg343344345def base_name(name: str) -> str:346    """The name with the evaluator effort suffix removed ("gpt-5-4-mini-medium" → "gpt-5-4-mini", "Claude Sonnet 4 (no thinking)" →347    "Claude Sonnet 4"); unchanged when not a variant."""348    a = analyze_model_name(name)349    if not a.is_effort_variant or not a.effort_suffix:350        return name.strip()351    n = name.strip()352    # the suffix was detected on a normalised form (spaces/underscores/parentheses → "-"): strip it from the raw name with the same tolerance353    tokens = [re.escape(t) for t in a.effort_suffix.split("-") if t]354    pattern = r"[\s\-_(]+" + r"[\s\-_]*".join(tokens) + r"[)\s]*$"355    out = re.sub(pattern, "", n, flags=re.I)356    return out.strip().rstrip("-_ (").strip() or n357358359__all__ = ["ARTIFACT_PACKAGING", "CONVERTER_ORGS", "EFFORT_SUFFIXES", "FAMILY_ORGS", "NameAnalysis", "PRECISION_FORMATS", "QUANT_FORMATS", "analyze_model_name",360           "base_name", "effort_config", "family_hint", "family_release_hint", "is_official_org", "official_orgs", "variant_key"]361
Files · afabc36216d003b383d172abe2f5ecd612a1e4ec
Menu

Theme