File size: 6,811 Bytes
35205e8 | 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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | from __future__ import annotations
from dataclasses import dataclass
from typing import Iterable
ALL_REASONING_EFFORTS = ("none", "minimal", "low", "medium", "high", "xhigh")
DEFAULT_REASONING_EFFORTS = frozenset(ALL_REASONING_EFFORTS)
@dataclass(frozen=True)
class ModelSpec:
public_id: str
upstream_id: str
aliases: tuple[str, ...]
allowed_efforts: frozenset[str]
variant_efforts: tuple[str, ...]
uses_codex_instructions: bool = False
_MODEL_SPECS = (
ModelSpec(
public_id="gpt-5",
upstream_id="gpt-5",
aliases=("gpt5", "gpt-5-latest"),
allowed_efforts=DEFAULT_REASONING_EFFORTS,
variant_efforts=("high", "medium", "low", "minimal"),
),
ModelSpec(
public_id="gpt-5.1",
upstream_id="gpt-5.1",
aliases=(),
allowed_efforts=frozenset(("low", "medium", "high")),
variant_efforts=("high", "medium", "low"),
),
ModelSpec(
public_id="gpt-5.2",
upstream_id="gpt-5.2",
aliases=("gpt5.2", "gpt-5.2-latest"),
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low"),
),
ModelSpec(
public_id="gpt-5.4",
upstream_id="gpt-5.4",
aliases=("gpt5.4", "gpt-5.4-latest"),
allowed_efforts=frozenset(("none", "low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low", "none"),
),
ModelSpec(
public_id="gpt-5.5",
upstream_id="gpt-5.5",
aliases=("gpt5.5", "gpt-5.5-latest"),
allowed_efforts=frozenset(("none", "low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low", "none"),
),
ModelSpec(
public_id="gpt-5.4-mini",
upstream_id="gpt-5.4-mini",
aliases=("gpt5.4-mini", "gpt-5.4-mini-latest"),
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low"),
),
ModelSpec(
public_id="gpt-5.3-codex",
upstream_id="gpt-5.3-codex",
aliases=("gpt5.3-codex", "gpt-5.3-codex-latest"),
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low"),
uses_codex_instructions=True,
),
ModelSpec(
public_id="gpt-5.3-codex-spark",
upstream_id="gpt-5.3-codex-spark",
aliases=("gpt5.3-codex-spark", "gpt-5.3-codex-spark-latest"),
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low"),
uses_codex_instructions=True,
),
ModelSpec(
public_id="gpt-5-codex",
upstream_id="gpt-5-codex",
aliases=("gpt5-codex", "gpt-5-codex-latest"),
allowed_efforts=DEFAULT_REASONING_EFFORTS,
variant_efforts=("high", "medium", "low"),
uses_codex_instructions=True,
),
ModelSpec(
public_id="gpt-5.2-codex",
upstream_id="gpt-5.2-codex",
aliases=("gpt5.2-codex", "gpt-5.2-codex-latest"),
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low"),
uses_codex_instructions=True,
),
ModelSpec(
public_id="gpt-5.1-codex",
upstream_id="gpt-5.1-codex",
aliases=(),
allowed_efforts=frozenset(("low", "medium", "high")),
variant_efforts=("high", "medium", "low"),
uses_codex_instructions=True,
),
ModelSpec(
public_id="gpt-5.1-codex-max",
upstream_id="gpt-5.1-codex-max",
aliases=(),
allowed_efforts=frozenset(("low", "medium", "high", "xhigh")),
variant_efforts=("xhigh", "high", "medium", "low"),
uses_codex_instructions=True,
),
ModelSpec(
public_id="gpt-5.1-codex-mini",
upstream_id="gpt-5.1-codex-mini",
aliases=(),
allowed_efforts=frozenset(("low", "medium", "high")),
variant_efforts=(),
uses_codex_instructions=True,
),
ModelSpec(
public_id="codex-mini",
upstream_id="codex-mini-latest",
aliases=("codex", "codex-mini-latest"),
allowed_efforts=DEFAULT_REASONING_EFFORTS,
variant_efforts=(),
uses_codex_instructions=True,
),
)
_SPECS_BY_UPSTREAM = {spec.upstream_id: spec for spec in _MODEL_SPECS}
_ALIASES = {}
for _spec in _MODEL_SPECS:
_ALIASES[_spec.public_id] = _spec.upstream_id
for _alias in _spec.aliases:
_ALIASES[_alias] = _spec.upstream_id
def _strip_model_name(model: str | None) -> tuple[str, str | None]:
if not isinstance(model, str):
return "", None
value = model.strip().lower()
if not value:
return "", None
if ":" in value:
base, maybe_effort = value.rsplit(":", 1)
if maybe_effort in DEFAULT_REASONING_EFFORTS:
return base, maybe_effort
for separator in ("-", "_"):
for effort in ALL_REASONING_EFFORTS:
suffix = f"{separator}{effort}"
if value.endswith(suffix):
return value[: -len(suffix)], effort
return value, None
def model_spec_for_name(model: str | None) -> ModelSpec | None:
base, _ = _strip_model_name(model)
upstream_id = _ALIASES.get(base)
if not upstream_id:
return None
return _SPECS_BY_UPSTREAM.get(upstream_id)
def normalize_model_name(model: str | None, debug_model: str | None = None) -> str:
if isinstance(debug_model, str) and debug_model.strip():
return debug_model.strip()
spec = model_spec_for_name(model)
if spec is not None:
return spec.upstream_id
base, _ = _strip_model_name(model)
return base or "gpt-5.4"
def uses_codex_instructions(model: str | None) -> bool:
spec = model_spec_for_name(model)
if spec is not None:
return spec.uses_codex_instructions
return "codex" in ((model or "").strip().lower())
def allowed_efforts_for_model(model: str | None) -> frozenset[str]:
spec = model_spec_for_name(model)
if spec is not None:
return spec.allowed_efforts
return DEFAULT_REASONING_EFFORTS
def extract_reasoning_from_model_name(model: str | None) -> dict[str, str] | None:
_, effort = _strip_model_name(model)
if not effort:
return None
return {"effort": effort}
def list_public_models(expose_reasoning_models: bool = False) -> list[str]:
model_ids: list[str] = []
for spec in _MODEL_SPECS:
model_ids.append(spec.public_id)
if expose_reasoning_models:
model_ids.extend(f"{spec.public_id}-{effort}" for effort in spec.variant_efforts)
return model_ids
def iter_public_models() -> Iterable[ModelSpec]:
return _MODEL_SPECS
|