mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-08-18 14:28:14 +00:00
fix(models): preserve native catalog contracts
This commit is contained in:
parent
a71661208a
commit
d3d4d03c0f
12 changed files with 333 additions and 26 deletions
|
|
@ -160,7 +160,11 @@ def records_from_payload(
|
|||
normalized = tuple(normalized_records)
|
||||
else:
|
||||
normalized_records: list[ModelCapabilityRecord] = []
|
||||
for item in shape.items(payload):
|
||||
catalog_items = shape.items(payload)
|
||||
select_catalog_items = getattr(reader, "select_catalog_items", None)
|
||||
if callable(select_catalog_items):
|
||||
catalog_items = tuple(select_catalog_items(catalog_items))
|
||||
for item in catalog_items:
|
||||
item_payload = shape.payload_for_item(payload, item)
|
||||
if shape.item_matches(item):
|
||||
if reader is generic_openai:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ labels.
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import math
|
||||
from collections.abc import Iterable, Mapping
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Protocol
|
||||
|
|
@ -139,6 +140,12 @@ def compact_str(value: Any) -> str:
|
|||
return str(value or "").strip()
|
||||
|
||||
|
||||
def identity_str(value: Any) -> str:
|
||||
"""Return a provider identity only when the payload supplied a string."""
|
||||
|
||||
return value.strip() if isinstance(value, str) else ""
|
||||
|
||||
|
||||
def _identity_part(value: Any) -> str:
|
||||
text = compact_str(value).lower()
|
||||
out = []
|
||||
|
|
@ -171,10 +178,7 @@ def stable_model_id_for(vendor: Any, model_id: Any, *, endpoint_id: Any = "", ba
|
|||
|
||||
def model_id_from(raw: Mapping[str, Any], *keys: str) -> str:
|
||||
for key in keys:
|
||||
raw_value = raw.get(key)
|
||||
if not isinstance(raw_value, str):
|
||||
continue
|
||||
value = raw_value.strip()
|
||||
value = identity_str(raw.get(key))
|
||||
if value:
|
||||
return value.removeprefix("models/")
|
||||
return ""
|
||||
|
|
@ -183,6 +187,10 @@ def model_id_from(raw: Mapping[str, Any], *keys: str) -> str:
|
|||
def int_limit(value: Any) -> int | None:
|
||||
if isinstance(value, bool):
|
||||
return None
|
||||
if isinstance(value, float) and (
|
||||
not math.isfinite(value) or not value.is_integer()
|
||||
):
|
||||
return None
|
||||
try:
|
||||
limit = int(value)
|
||||
except (OverflowError, TypeError, ValueError):
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
|
|
@ -12,11 +13,59 @@ from src.model_capability_readers.base import (
|
|||
as_list,
|
||||
as_mapping,
|
||||
compact_str,
|
||||
identity_str,
|
||||
stable_model_id_for,
|
||||
)
|
||||
|
||||
|
||||
vendor = VENDOR_CHATGPT_SUBSCRIPTION
|
||||
_DEFAULT_PRIORITY = 10_000
|
||||
|
||||
|
||||
def _priority_rank(raw: Mapping[str, Any]) -> int | float:
|
||||
value = raw.get("priority")
|
||||
if isinstance(value, bool):
|
||||
return _DEFAULT_PRIORITY
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
if isinstance(value, float) and math.isfinite(value):
|
||||
return value
|
||||
return _DEFAULT_PRIORITY
|
||||
|
||||
|
||||
def _is_hidden(raw: Mapping[str, Any]) -> bool:
|
||||
visibility = raw.get("visibility")
|
||||
return (
|
||||
isinstance(visibility, str)
|
||||
and visibility.strip().lower() in {"hide", "hidden"}
|
||||
)
|
||||
|
||||
|
||||
def select_catalog_items(
|
||||
items: tuple[Mapping[str, Any], ...],
|
||||
) -> tuple[Mapping[str, Any], ...]:
|
||||
"""Apply the provider's visibility, priority, and slug de-duplication."""
|
||||
|
||||
sortable: list[tuple[int | float, str, int, Mapping[str, Any]]] = []
|
||||
passthrough: list[Mapping[str, Any]] = []
|
||||
for position, item in enumerate(items):
|
||||
if _is_hidden(item):
|
||||
continue
|
||||
slug = identity_str(item.get("slug"))
|
||||
if not slug:
|
||||
passthrough.append(item)
|
||||
continue
|
||||
sortable.append((_priority_rank(item), slug, position, item))
|
||||
sortable.sort(key=lambda entry: (entry[0], entry[1], entry[2]))
|
||||
|
||||
selected: list[Mapping[str, Any]] = []
|
||||
seen: set[str] = set()
|
||||
for _, slug, _, item in sortable:
|
||||
if slug not in seen:
|
||||
selected.append(item)
|
||||
seen.add(slug)
|
||||
selected.extend(passthrough)
|
||||
return tuple(selected)
|
||||
|
||||
|
||||
def record_from_model(
|
||||
|
|
@ -25,7 +74,7 @@ def record_from_model(
|
|||
endpoint_id: Any = "",
|
||||
base_url: Any = "",
|
||||
) -> ModelCapabilityRecord | None:
|
||||
model_id = compact_str(raw.get("slug"))
|
||||
model_id = identity_str(raw.get("slug"))
|
||||
if not model_id:
|
||||
return None
|
||||
return ModelCapabilityRecord(
|
||||
|
|
@ -55,7 +104,8 @@ def records_from_payload(
|
|||
values = as_mapping(payload).get("models")
|
||||
return tuple(
|
||||
record
|
||||
for item in as_list(values)
|
||||
if isinstance(item, Mapping)
|
||||
for item in select_catalog_items(
|
||||
tuple(item for item in as_list(values) if isinstance(item, Mapping))
|
||||
)
|
||||
if (record := record_from_model(item, endpoint_id=endpoint_id, base_url=base_url))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from src.model_capability_readers.base import (
|
|||
build_capability,
|
||||
compact_str,
|
||||
deterministic_controls_from_supported_parameters,
|
||||
identity_str,
|
||||
int_limit,
|
||||
stable_model_id_for,
|
||||
)
|
||||
|
|
@ -60,7 +61,7 @@ def record_from_model(
|
|||
endpoint_id: Any = "",
|
||||
base_url: Any = "",
|
||||
) -> ModelCapabilityRecord | None:
|
||||
model_id = compact_str(raw.get("name"))
|
||||
model_id = identity_str(raw.get("name"))
|
||||
if not model_id:
|
||||
return None
|
||||
family = _family(raw)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@ _SUPPORT_CAPABILITIES = {
|
|||
}
|
||||
|
||||
|
||||
def select_catalog_items(
|
||||
items: tuple[Mapping[str, Any], ...],
|
||||
) -> tuple[Mapping[str, Any], ...]:
|
||||
"""Keep picker-enabled models when the catalog advertises any of them."""
|
||||
|
||||
if any(item.get("model_picker_enabled") is True for item in items):
|
||||
return tuple(
|
||||
item for item in items if item.get("model_picker_enabled") is True
|
||||
)
|
||||
return items
|
||||
|
||||
|
||||
def _supports(raw: Mapping[str, Any]) -> Mapping[str, Any]:
|
||||
return as_mapping(as_mapping(raw.get("capabilities")).get("supports"))
|
||||
|
||||
|
|
@ -102,7 +114,7 @@ def records_from_payload(
|
|||
base_url: Any = "",
|
||||
) -> tuple[ModelCapabilityRecord, ...]:
|
||||
records: list[ModelCapabilityRecord] = []
|
||||
for item in openai_model_items(payload):
|
||||
for item in select_catalog_items(openai_model_items(payload)):
|
||||
record = record_from_model(item, endpoint_id=endpoint_id, base_url=base_url)
|
||||
if record:
|
||||
records.append(record)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,12 @@ from collections.abc import Mapping
|
|||
from typing import Any
|
||||
|
||||
from src import model_capabilities as mc
|
||||
from src.model_capability_readers.base import as_list, compact_str, int_limit
|
||||
from src.model_capability_readers.base import (
|
||||
as_list,
|
||||
compact_str,
|
||||
identity_str,
|
||||
int_limit,
|
||||
)
|
||||
|
||||
|
||||
METHOD_GENERATE_CONTENT = "generateContent"
|
||||
|
|
@ -55,7 +60,7 @@ MODEL_FIELD_MAP = {
|
|||
|
||||
|
||||
def google_model_id(raw: Mapping[str, Any]) -> str:
|
||||
value = compact_str(raw.get("baseModelId")) or compact_str(raw.get("name"))
|
||||
value = identity_str(raw.get("baseModelId")) or identity_str(raw.get("name"))
|
||||
return value.removeprefix("models/")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from src.model_capability_readers.base import (
|
|||
VENDOR_HUGGINGFACE,
|
||||
build_capability,
|
||||
compact_str,
|
||||
openai_model_items,
|
||||
model_id_from,
|
||||
stable_model_id_for,
|
||||
)
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ def record_from_model(
|
|||
endpoint_id: Any = "",
|
||||
base_url: Any = "",
|
||||
) -> ModelCapabilityRecord | None:
|
||||
model_id = compact_str(raw.get("modelId") or raw.get("id"))
|
||||
model_id = model_id_from(raw, "modelId", "id")
|
||||
if not model_id:
|
||||
return None
|
||||
return ModelCapabilityRecord(
|
||||
|
|
@ -136,11 +136,15 @@ def records_from_payload(
|
|||
endpoint_id: Any = "",
|
||||
base_url: Any = "",
|
||||
) -> tuple[ModelCapabilityRecord, ...]:
|
||||
if isinstance(payload, Mapping) and (payload.get("modelId") or payload.get("pipeline_tag")):
|
||||
if isinstance(payload, Mapping) and "pipeline_tag" in payload:
|
||||
record = record_from_model(payload, endpoint_id=endpoint_id, base_url=base_url)
|
||||
return (record,) if record else ()
|
||||
if not isinstance(payload, (list, tuple)):
|
||||
return ()
|
||||
records: list[ModelCapabilityRecord] = []
|
||||
for item in openai_model_items(payload):
|
||||
for item in payload:
|
||||
if not isinstance(item, Mapping):
|
||||
continue
|
||||
record = record_from_model(item, endpoint_id=endpoint_id, base_url=base_url)
|
||||
if record:
|
||||
records.append(record)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ from src.model_capability_readers.base import (
|
|||
build_capability,
|
||||
compact_str,
|
||||
deterministic_controls_from_supported_parameters,
|
||||
identity_str,
|
||||
int_limit,
|
||||
merge_unique,
|
||||
model_id_from,
|
||||
|
|
@ -53,10 +54,10 @@ def _server_model_entries(payload: Mapping[str, Any]) -> tuple[Mapping[str, Any]
|
|||
|
||||
def _model_id_from_props(payload: Mapping[str, Any]) -> str:
|
||||
payload = as_mapping(payload)
|
||||
model_alias = compact_str(payload.get("model_alias"))
|
||||
model_alias = identity_str(payload.get("model_alias"))
|
||||
if model_alias:
|
||||
return model_alias
|
||||
model_path = compact_str(payload.get("model_path"))
|
||||
model_path = identity_str(payload.get("model_path"))
|
||||
if model_path:
|
||||
return PurePosixPath(model_path).name
|
||||
return ""
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from src.model_capability_readers.base import (
|
|||
as_mapping,
|
||||
build_capability,
|
||||
compact_str,
|
||||
identity_str,
|
||||
int_limit,
|
||||
merge_unique,
|
||||
model_id_from,
|
||||
|
|
@ -116,7 +117,7 @@ def record_from_show_payload(
|
|||
endpoint_id: Any = "",
|
||||
base_url: Any = "",
|
||||
) -> ModelCapabilityRecord | None:
|
||||
model_id = compact_str(model_id) or model_id_from(payload, "model", "name")
|
||||
model_id = identity_str(model_id) or model_id_from(payload, "model", "name")
|
||||
if not model_id:
|
||||
return None
|
||||
capability_values = payload.get("capabilities")
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ from src.model_capability_readers.base import (
|
|||
VENDOR_SGLANG,
|
||||
as_mapping,
|
||||
build_capability,
|
||||
compact_str,
|
||||
deterministic_controls_from_supported_parameters,
|
||||
identity_str,
|
||||
int_limit,
|
||||
openai_model_items,
|
||||
stable_model_id_for,
|
||||
|
|
@ -26,7 +26,9 @@ vendor = VENDOR_SGLANG
|
|||
|
||||
|
||||
def _model_id(payload: Mapping[str, Any]) -> str:
|
||||
value = compact_str(payload.get("served_model_name") or payload.get("model_path"))
|
||||
value = identity_str(payload.get("served_model_name")) or identity_str(
|
||||
payload.get("model_path")
|
||||
)
|
||||
if not value:
|
||||
return ""
|
||||
return PurePosixPath(value).name if value.startswith("/") else value
|
||||
|
|
|
|||
|
|
@ -229,6 +229,15 @@ GOOGLE_MODELS_SHAPE = ProviderCatalogShape(
|
|||
item_types=(("supportedGenerationMethods", (list, tuple)),),
|
||||
detection_priority=100,
|
||||
)
|
||||
GOOGLE_MODEL_SHAPE = ProviderCatalogShape(
|
||||
shape_id="google.generative-language.model.v1beta",
|
||||
provider_id="google",
|
||||
envelope=ENVELOPE_SINGLE,
|
||||
identity_paths=("baseModelId", "name"),
|
||||
required_item_paths=("supportedGenerationMethods",),
|
||||
item_types=(("supportedGenerationMethods", (list, tuple)),),
|
||||
detection_priority=100,
|
||||
)
|
||||
OLLAMA_TAGS_SHAPE = ProviderCatalogShape(
|
||||
shape_id="ollama.tags.v1",
|
||||
provider_id="ollama",
|
||||
|
|
@ -290,6 +299,17 @@ LLAMACPP_PROPS_SHAPE = ProviderCatalogShape(
|
|||
item_types=(("default_generation_settings", (Mapping,)),),
|
||||
detection_priority=100,
|
||||
)
|
||||
LLAMACPP_MODELS_SHAPE = ProviderCatalogShape(
|
||||
shape_id="llamacpp.models.native.v1",
|
||||
provider_id="llamacpp",
|
||||
envelope=ENVELOPE_MODELS,
|
||||
identity_paths=("id", "name", "model"),
|
||||
required_item_paths=("capabilities",),
|
||||
item_types=(("capabilities", (list, tuple)),),
|
||||
# Model/capability fields are not globally provider-specific. Interpret
|
||||
# them only after explicit llama.cpp endpoint/provider selection.
|
||||
detection_priority=0,
|
||||
)
|
||||
MISTRAL_MODELS_SHAPE = ProviderCatalogShape(
|
||||
shape_id="mistral.models.rich.v1",
|
||||
provider_id="mistral",
|
||||
|
|
@ -325,7 +345,9 @@ ANTHROPIC_MODELS_SHAPE = ProviderCatalogShape(
|
|||
identity_paths=("id",),
|
||||
required_item_paths=("type", "display_name", "created_at"),
|
||||
item_values=(("type", ("model",)),),
|
||||
detection_priority=70,
|
||||
# These model-resource fields are not globally provider-specific. Require
|
||||
# explicit Anthropic endpoint/provider context before assigning identity.
|
||||
detection_priority=0,
|
||||
)
|
||||
CHATGPT_MODELS_SHAPE = ProviderCatalogShape(
|
||||
shape_id="chatgpt-subscription.codex-models.v1",
|
||||
|
|
@ -376,6 +398,15 @@ HUGGINGFACE_MODEL_SHAPE = ProviderCatalogShape(
|
|||
item_types=(("pipeline_tag", (str,)),),
|
||||
detection_priority=0,
|
||||
)
|
||||
HUGGINGFACE_MODELS_LIST_SHAPE = ProviderCatalogShape(
|
||||
shape_id="huggingface.hub.model-info-list.v1",
|
||||
provider_id="huggingface",
|
||||
envelope=ENVELOPE_BARE_LIST,
|
||||
identity_paths=("modelId", "id"),
|
||||
required_item_paths=("pipeline_tag",),
|
||||
item_types=(("pipeline_tag", (str,)),),
|
||||
detection_priority=0,
|
||||
)
|
||||
COHERE_MODELS_SHAPE = ProviderCatalogShape(
|
||||
shape_id="cohere.models.rich.v1",
|
||||
provider_id="cohere",
|
||||
|
|
@ -432,7 +463,7 @@ PROVIDER_SCHEMAS = {
|
|||
"google",
|
||||
aliases=("gemini", "google_ai_studio"),
|
||||
hosts=("generativelanguage.googleapis.com",),
|
||||
shapes=(GOOGLE_MODELS_SHAPE,),
|
||||
shapes=(GOOGLE_MODELS_SHAPE, GOOGLE_MODEL_SHAPE),
|
||||
),
|
||||
"anthropic": _provider(
|
||||
"anthropic",
|
||||
|
|
@ -452,7 +483,7 @@ PROVIDER_SCHEMAS = {
|
|||
"llamacpp": _provider(
|
||||
"llamacpp",
|
||||
aliases=("llama.cpp", "llama_cpp", "llama_server"),
|
||||
shapes=(LLAMACPP_PROPS_SHAPE,),
|
||||
shapes=(LLAMACPP_PROPS_SHAPE, LLAMACPP_MODELS_SHAPE),
|
||||
),
|
||||
"mistral": _provider(
|
||||
"mistral",
|
||||
|
|
@ -480,7 +511,7 @@ PROVIDER_SCHEMAS = {
|
|||
"huggingface",
|
||||
aliases=("hf", "hugging_face"),
|
||||
hosts=("huggingface.co",),
|
||||
shapes=(HUGGINGFACE_MODEL_SHAPE,),
|
||||
shapes=(HUGGINGFACE_MODEL_SHAPE, HUGGINGFACE_MODELS_LIST_SHAPE),
|
||||
),
|
||||
"cohere": _provider(
|
||||
"cohere",
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ def test_native_catalog_shapes_resolve_with_required_provider_context():
|
|||
)
|
||||
|
||||
explicit_context_providers = {
|
||||
"anthropic",
|
||||
"chatgpt_subscription",
|
||||
"cohere",
|
||||
"huggingface",
|
||||
|
|
@ -608,6 +609,139 @@ def test_structured_identity_values_are_not_stringified_into_fallback_records():
|
|||
assert records_from_payload(payload, vendor="future-provider") == ()
|
||||
|
||||
|
||||
def test_native_readers_skip_structured_identity_candidates():
|
||||
google_record = records_from_payload(
|
||||
{
|
||||
"models": [
|
||||
{
|
||||
"baseModelId": {"nested": "bad"},
|
||||
"name": "models/good-google-id",
|
||||
"supportedGenerationMethods": ["embedContent"],
|
||||
}
|
||||
]
|
||||
}
|
||||
)[0]
|
||||
huggingface_record = records_from_payload(
|
||||
{
|
||||
"modelId": {"nested": "bad"},
|
||||
"id": "org/good-hf-id",
|
||||
"pipeline_tag": "text-to-image",
|
||||
},
|
||||
vendor="huggingface",
|
||||
)[0]
|
||||
llamacpp_record = records_from_payload(
|
||||
{
|
||||
"model_alias": {"nested": "bad"},
|
||||
"model_path": "/models/good-llama.gguf",
|
||||
"default_generation_settings": {},
|
||||
"chat_template_caps": {"supports_vision": True},
|
||||
},
|
||||
vendor="llamacpp",
|
||||
)[0]
|
||||
sglang_record = records_from_payload(
|
||||
{
|
||||
"served_model_name": {"nested": "bad"},
|
||||
"model_path": "/models/good-sglang",
|
||||
"is_generation": True,
|
||||
"has_image_understanding": True,
|
||||
},
|
||||
vendor="sglang",
|
||||
)[0]
|
||||
|
||||
assert google_record.model_id == "good-google-id"
|
||||
assert huggingface_record.model_id == "org/good-hf-id"
|
||||
assert llamacpp_record.model_id == "good-llama.gguf"
|
||||
assert sglang_record.model_id == "good-sglang"
|
||||
assert chatgpt_subscription.record_from_model({"slug": {"nested": "bad"}}) is None
|
||||
assert cohere.record_from_model(
|
||||
{"name": {"nested": "bad"}, "endpoints": ["chat"]}
|
||||
) is None
|
||||
|
||||
|
||||
def test_native_singleton_and_bare_list_shapes_reach_their_readers():
|
||||
google_records = records_from_payload(
|
||||
{
|
||||
"name": "models/gemini-embed",
|
||||
"supportedGenerationMethods": ["embedContent"],
|
||||
},
|
||||
vendor="google",
|
||||
)
|
||||
huggingface_records = records_from_payload(
|
||||
[{"modelId": "org/model", "pipeline_tag": "text-generation"}],
|
||||
vendor="huggingface",
|
||||
)
|
||||
llamacpp_records = records_from_payload(
|
||||
{
|
||||
"models": [
|
||||
{
|
||||
"id": "served-model",
|
||||
"capabilities": ["chat", "tools"],
|
||||
}
|
||||
]
|
||||
},
|
||||
vendor="llamacpp",
|
||||
)
|
||||
|
||||
assert google_records[0].model_id == "gemini-embed"
|
||||
assert google_records[0].capability.family == mc.FAMILY_EMBEDDING
|
||||
assert google_records[0].catalog_shape_id == (
|
||||
"google.generative-language.model.v1beta"
|
||||
)
|
||||
assert huggingface_records[0].model_id == "org/model"
|
||||
assert huggingface_records[0].capability.family == mc.FAMILY_CHAT
|
||||
assert huggingface_records[0].catalog_shape_id == (
|
||||
"huggingface.hub.model-info-list.v1"
|
||||
)
|
||||
assert llamacpp_records[0].model_id == "served-model"
|
||||
assert llamacpp_records[0].capability.family == mc.FAMILY_CHAT
|
||||
assert llamacpp_records[0].capability.capabilities == (mc.CAP_TOOL_CALL,)
|
||||
assert llamacpp_records[0].catalog_shape_id == "llamacpp.models.native.v1"
|
||||
|
||||
|
||||
def test_huggingface_openai_serving_envelope_stays_identity_only():
|
||||
payload = {
|
||||
"data": [
|
||||
{
|
||||
"id": "served-model",
|
||||
"pipeline_tag": "text-to-image",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
direct = huggingface.records_from_payload(payload)
|
||||
wrapped = records_from_payload(payload, vendor="huggingface")
|
||||
|
||||
assert direct == ()
|
||||
assert wrapped[0].model_id == "served-model"
|
||||
assert wrapped[0].capability.family == mc.FAMILY_UNKNOWN
|
||||
assert wrapped[0].capability.capabilities == ()
|
||||
assert wrapped[0].fallback is True
|
||||
|
||||
|
||||
def test_generic_model_resource_fields_do_not_infer_anthropic_identity():
|
||||
payload = {
|
||||
"data": [
|
||||
{
|
||||
"id": "foreign-model",
|
||||
"type": "model",
|
||||
"display_name": "Foreign Model",
|
||||
"created_at": "2026-01-01T00:00:00Z",
|
||||
"capabilities": {"tools": True},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
resolution = pcs.resolve_provider(payload)
|
||||
records = records_from_payload(payload)
|
||||
|
||||
assert resolution.provider_id == pcs.PROVIDER_UNKNOWN
|
||||
assert resolution.shape_id == "fallback.models.data.v1"
|
||||
assert resolution.fallback is True
|
||||
assert records[0].vendor == pcs.PROVIDER_UNKNOWN
|
||||
assert records[0].fallback is True
|
||||
assert records[0].capability.capabilities == ()
|
||||
|
||||
|
||||
def test_mistral_reader_maps_per_model_capabilities_without_provider_inheritance():
|
||||
records = mistral.records_from_payload(
|
||||
{
|
||||
|
|
@ -686,6 +820,60 @@ def test_copilot_reader_ignores_unverified_support_aliases():
|
|||
assert record.capability.capabilities == ()
|
||||
|
||||
|
||||
def test_copilot_catalog_uses_picker_selection_with_no_picker_fallback():
|
||||
def payload(*picker_values):
|
||||
return {
|
||||
"data": [
|
||||
{
|
||||
"id": f"model-{index}",
|
||||
"model_picker_enabled": picker_enabled,
|
||||
"capabilities": {"supports": {}},
|
||||
}
|
||||
for index, picker_enabled in enumerate(picker_values)
|
||||
]
|
||||
}
|
||||
|
||||
selected = records_from_payload(payload(False, True, False), vendor="copilot")
|
||||
fallback = records_from_payload(payload(False, False), vendor="copilot")
|
||||
|
||||
assert [record.model_id for record in selected] == ["model-1"]
|
||||
assert [record.model_id for record in fallback] == ["model-0", "model-1"]
|
||||
|
||||
|
||||
def test_chatgpt_catalog_applies_visibility_priority_and_slug_deduplication():
|
||||
records = records_from_payload(
|
||||
{
|
||||
"models": [
|
||||
{"slug": "hidden", "visibility": "hidden", "priority": 0},
|
||||
{"slug": "later", "visibility": "list", "priority": 20},
|
||||
{
|
||||
"slug": "duplicate",
|
||||
"visibility": "list",
|
||||
"priority": 30,
|
||||
"title": "lower-precedence",
|
||||
},
|
||||
{"slug": "first", "visibility": "list", "priority": 1},
|
||||
{
|
||||
"slug": "duplicate",
|
||||
"visibility": "list",
|
||||
"priority": 5,
|
||||
"title": "selected",
|
||||
},
|
||||
{"slug": "unranked", "visibility": "list", "priority": float("inf")},
|
||||
]
|
||||
},
|
||||
vendor="chatgpt_subscription",
|
||||
)
|
||||
|
||||
assert [record.model_id for record in records] == [
|
||||
"first",
|
||||
"duplicate",
|
||||
"later",
|
||||
"unranked",
|
||||
]
|
||||
assert records[1].display_name == "selected"
|
||||
|
||||
|
||||
def test_sglang_model_info_maps_native_generation_flags_only():
|
||||
generation = sglang.records_from_payload(
|
||||
{
|
||||
|
|
@ -746,7 +934,7 @@ def test_sglang_openai_catalog_preserves_only_valid_native_context_limit():
|
|||
]
|
||||
}
|
||||
)[0]
|
||||
for value in (0, True, float("inf"))
|
||||
for value in (0, True, 1.5, float("inf"))
|
||||
]
|
||||
|
||||
assert valid.vendor == "sglang"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue