Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions docs/api/build_from_gguf.md

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions docs/cli_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ and global cache indices, so dense, MoE, tied-weight, quantized, and unknown
architecture names do not need a runtime registry entry.

Architecture-specific types remain only where the runtime selects different
behavior. `lfm2` uses its legacy convolution-cache implementation. `gpt2` selects
`Gpt_Model`, but Mobius's separate rank-4 key/value cache ABI does not match that
runtime's rank-5 combined-cache contract, so config generation currently fails
closed. `phi3`, `phimoe`, and `phi3small` retain their names only when their config selects
behavior. `lfm2` uses its legacy convolution-cache implementation. `gpt2` uses the
generic decoder because Mobius exports separate rank-4 key/value caches rather than
the specialized `Gpt_Model` rank-5 combined-cache contract. `phi3`, `phimoe`, and
`phi3small` retain their names only when their config selects
LongRoPE, because the released generator uses those names to recompute caches when
generation crosses the short-context threshold. Ordinary Phi-3-family graphs use
`decoder`. Multimodal, audio, encoder-decoder, special-position-ID,
Expand All @@ -197,10 +197,11 @@ dense cache. The deferred state-manifest work is tracked by
Each export also writes `runtime_compatibility.json`. Generic decoder metadata
records the minimum runtime version and the latest stable release exercised by
Mobius (0.15.2); it never emits the unreleased `decoder.state_groups` field.
Generic config availability does not promote a GGUF runtime verdict: the only
runtime-supported GGUF route remains the exact pinned SmolLM F16/CPU package, while
SmolLM2 remains rejected because its GGUF padding-token metadata conflicts with the
official pinned tokenizer.
Generic config availability does not promote a GGUF runtime verdict. Runtime
admission is restricted to exact artifacts named by the generated GGUF evidence
matrix, which now includes GPT-2 and other independently verified decoder routes in
addition to SmolLM. SmolLM2 remains rejected because its GGUF padding-token metadata
conflicts with the official pinned tokenizer.

#### Example

Expand Down
52 changes: 35 additions & 17 deletions src/mobius/integrations/gguf/_arch_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,8 @@
GGUFArchitectureSpec(
gguf_arch="qwen3",
model_type="qwen3",
tensor_map_recipe=("llama",),
tensor_map_recipe=("llama", "moe_qk_norm_extras"),
config_postprocessor="qwen3",
runtime=Support.DEFERRED,
reason=_RUNTIME_VALIDATION_PENDING,
),
Expand Down Expand Up @@ -1042,11 +1043,13 @@
model_type="gpt2",
tensor_map_recipe=("gpt2",),
tensor_processor="gpt2",
runtime=Support.DEFERRED,
runtime=Support.SUPPORTED,
runtime_evidence_ids=("gpt2-q2-k-ort-genai-0.15.2",),
quantized_import=Support.REJECTED,
reason=(
_RUNTIME_VALIDATION_PENDING
+ " Quantization preservation is rejected because canonical GPT-2 GGUF "
"Runtime support is restricted to the exact evidenced GPT-2 Q2_K artifact, "
"explicit-float CPU import route, pinned tokenizer, and ORT GenAI 0.15.2. "
"Quantization preservation is rejected because canonical GPT-2 GGUF "
"projections must be transposed into graph order, and the current packed "
"route cannot transpose values together with their scales and zero-points. "
"Use keep_quantized=False for explicit float import."
Expand Down Expand Up @@ -1610,8 +1613,13 @@
gguf_arch="starcoder2",
model_type="starcoder2",
tensor_map_recipe=("llama",),
runtime=Support.DEFERRED,
reason=_RUNTIME_VALIDATION_PENDING,
config_postprocessor="starcoder2",
runtime=Support.SUPPORTED,
runtime_evidence_ids=("tiny-starcoder2-q2-k-ort-genai-0.15.2",),
reason=(
"Runtime support is restricted to the exact evidenced tiny StarCoder2 Q2_K "
"artifact, explicit-float CPU import route, pinned tokenizer, and ORT GenAI 0.15.2."
),
),
GGUFArchitectureSpec(
gguf_arch="stablelm",
Expand All @@ -1638,8 +1646,12 @@
required_metadata=("attention.layer_norm_epsilon",),
tensor_processor="llama",
llama_qk_permute=True,
runtime=Support.DEFERRED,
reason=_RUNTIME_VALIDATION_PENDING,
runtime=Support.SUPPORTED,
runtime_evidence_ids=("tiny-olmo-q2-k-ort-genai-0.15.2",),
reason=(
"Runtime support is restricted to the exact evidenced tiny OLMo Q2_K artifact, "
"explicit-float CPU import route, pinned tokenizer, and ORT GenAI 0.15.2."
),
),
GGUFArchitectureSpec(
gguf_arch="olmo2",
Expand Down Expand Up @@ -2174,11 +2186,13 @@
tensor_map_recipe=("legacy_layernorm",),
config_postprocessor="exact_legacy_gguf",
required_metadata=("attention.layer_norm_epsilon", "attention.max_alibi_bias"),
runtime=Support.DEFERRED,
runtime=Support.SUPPORTED,
runtime_evidence_ids=("tiny-mpt-q2-k-ort-genai-0.15.2",),
quantized_import=Support.REJECTED,
reason=(
_RUNTIME_VALIDATION_PENDING
+ " The admitted subset rejects learned positions, Q/K norms, KQV clipping, "
"Runtime support is restricted to the exact evidenced tiny MPT Q2_K artifact, "
"explicit-float portable graph, pinned tokenizer, and ORT GenAI 0.15.2. "
"The admitted subset rejects learned positions, Q/K norms, KQV clipping, "
"AWQ activation scales, and inconsistent optional bias families. Quantization "
"preservation is rejected because fused QKV must be split."
),
Expand All @@ -2190,11 +2204,13 @@
tensor_map_recipe=("legacy_layernorm",),
config_postprocessor="exact_legacy_gguf",
required_metadata=("attention.layer_norm_epsilon", "use_parallel_residual"),
runtime=Support.DEFERRED,
runtime=Support.SUPPORTED,
runtime_evidence_ids=("pythia-70m-q2-k-ort-genai-0.15.2",),
quantized_import=Support.REJECTED,
reason=(
_RUNTIME_VALIDATION_PENDING
+ " The admitted subset requires parallel residual MHA. Quantization "
"Runtime support is restricted to the exact evidenced Pythia-70M Q2_K artifact, "
"explicit-float portable graph, pinned tokenizer, and ORT GenAI 0.15.2. "
"The admitted subset requires parallel residual MHA. Quantization "
"preservation is rejected because fused QKV rows must be split."
),
),
Expand Down Expand Up @@ -2336,11 +2352,13 @@
tensor_map_recipe=("starcoder",),
config_postprocessor="conventional_legacy",
required_metadata=("attention.layer_norm_epsilon",),
runtime=Support.DEFERRED,
runtime=Support.SUPPORTED,
runtime_evidence_ids=("tiny-starcoder-q2-k-ort-genai-0.15.2",),
quantized_import=Support.REJECTED,
reason=(
_RUNTIME_VALIDATION_PENDING
+ " Quantization preservation is rejected because StarCoder stores one fused "
"Runtime support is restricted to the exact evidenced tiny StarCoder Q2_K "
"artifact, explicit-float CPU import route, pinned tokenizer, and ORT GenAI "
"0.15.2. Quantization preservation is rejected because StarCoder stores one fused "
"biased MQA projection that must be split for the graph."
),
),
Expand Down
29 changes: 27 additions & 2 deletions src/mobius/integrations/gguf/_config_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,27 @@ def _moe_postprocess(
return dataclasses.replace(config, **updates)


def _qwen3_postprocess(
config: ArchitectureConfig,
metadata: dict[str, Any],
model: Any = None,
) -> ArchitectureConfig:
"""Apply Qwen3's per-head Q/K normalization omitted by GGUF metadata."""
return dataclasses.replace(config, attn_qk_norm=True, attn_qk_norm_full=False)


def _starcoder2_postprocess(
config: ArchitectureConfig,
metadata: dict[str, Any],
model: Any = None,
) -> ArchitectureConfig:
"""Restore StarCoder2's architecture-owned uniform sliding window."""
del metadata, model
if config.sliding_window is not None:
return config
return dataclasses.replace(config, sliding_window=4096)


def _dbrx_postprocess(
config: ArchitectureConfig,
metadata: dict[str, Any],
Expand Down Expand Up @@ -4716,6 +4737,8 @@ def _qwen4exp_postprocess(
"phimoe": _phimoe_postprocess,
"pangu_embedded": _pangu_embedded_postprocess,
"dense_sliding": _dense_sliding_postprocess,
"qwen3": _qwen3_postprocess,
"starcoder2": _starcoder2_postprocess,
"gemma2": _gemma2_postprocess,
"baichuan": _baichuan_postprocess,
"chatglm": _chatglm_postprocess,
Expand Down Expand Up @@ -4764,15 +4787,17 @@ def _default_activation(model_type: str) -> str:
# Most modern models use SiLU/Swish
if model_type == "arcee":
return "relu2"
if model_type in {"gpt2", "starcoder2"}:
# These architectures use tanh-approximate GELU by default. Their GGUF
# metadata omits that architecture-owned choice, so exact GELU is not equivalent.
return "gelu_pytorch_tanh"
gelu_models = {
"bert",
"bloom",
"gpt2",
"gpt_bigcode",
"jais2",
"kclgpt",
"modernbert",
"starcoder2",
"t5",
}
if model_type in gelu_models:
Expand Down
50 changes: 49 additions & 1 deletion src/mobius/integrations/gguf/_config_mapping_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1382,19 +1382,67 @@ def test_gemma_uses_gelu_pytorch_tanh(self, model_type: str) -> None:

assert _default_activation(model_type) == "gelu_pytorch_tanh"

@pytest.mark.parametrize("model_type", ["gpt2", "bloom", "starcoder2", "t5"])
@pytest.mark.parametrize("model_type", ["bloom", "t5"])
def test_gelu_models(self, model_type: str) -> None:
from mobius.integrations.gguf._config_mapping import _default_activation

assert _default_activation(model_type) == "gelu"

@pytest.mark.parametrize("model_type", ["gpt2", "starcoder2"])
def test_architecture_default_uses_tanh_approximate_gelu(self, model_type: str) -> None:
from mobius.integrations.gguf._config_mapping import _default_activation

assert _default_activation(model_type) == "gelu_pytorch_tanh"

@pytest.mark.parametrize("model_type", ["llama", "qwen2", "mistral"])
def test_silu_default(self, model_type: str) -> None:
from mobius.integrations.gguf._config_mapping import _default_activation

assert _default_activation(model_type) == "silu"


def test_qwen3_qk_norm_weights_have_graph_consumers() -> None:
from mobius.integrations.gguf._config_mapping import gguf_to_config

tensor_names = [
"token_embd.weight",
"output.weight",
*[
f"blk.{layer}.{name}.weight"
for layer in range(2)
for name in ("attn_q_norm", "attn_k_norm")
],
]
config = gguf_to_config(_FakeDenseGGUF("qwen3", _dense_metadata("qwen3"), tensor_names))

assert config.attn_qk_norm is True
assert config.attn_qk_norm_full is False
module = registry.get(config.model_type)(config)
for layer in module.model.layers:
assert layer.self_attn.q_norm is not None
assert layer.self_attn.k_norm is not None


@pytest.mark.parametrize(
("metadata_window", "expected_window"),
[(None, 4096), (2048, 2048)],
)
def test_starcoder2_restores_architecture_sliding_window(
metadata_window: int | None,
expected_window: int,
) -> None:
from mobius.integrations.gguf._config_mapping import gguf_to_config

metadata = _dense_metadata("starcoder2")
if metadata_window is not None:
metadata["starcoder2.attention.sliding_window"] = metadata_window
config = gguf_to_config(_FakeDenseGGUF("starcoder2", metadata, []))

assert config.sliding_window == expected_window
module = registry.get(config.model_type)(config)
assert module.model._sliding_window == expected_window


class TestQwen35MtpBlockExclusion:
"""Qwen3.5/3.8 GGUF ``block_count`` includes trailing MTP (nextn) blocks.

Expand Down
5 changes: 4 additions & 1 deletion src/mobius/integrations/gguf/_conventional_decoder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ def test_conventional_decoder_support_and_runtime_verdicts_are_explicit() -> Non
for architecture in _ARCHITECTURES:
spec = get_arch_spec(architecture)
assert spec.is_importable
assert spec.runtime is Support.DEFERRED
expected_runtime = (
Support.SUPPORTED if architecture == "starcoder" else Support.DEFERRED
)
assert spec.runtime is expected_runtime
expected = (
Support.SUPPORTED if architecture in supported_quantized else Support.REJECTED
)
Expand Down
6 changes: 6 additions & 0 deletions src/mobius/integrations/gguf/_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,12 @@ def render_document() -> str:

## Runtime evidence

The first low-cost architecture batch promotes GPT-2, GPT-NeoX/Pythia, MPT, OLMo,
StarCoder, and StarCoder2 using 334,238,976 bytes of GGUF payload and 346,825,051
download bytes including tokenizer assets. Every route is explicit-float only. The
network-free selection, budget, exclusions, and fail-closed candidate reasons are recorded in
`testdata/evidence/gguf_low_cost_runtime_batch.json`.

{_runtime_evidence_table()}

Runtime support above is independent from tokenizer materialization support below.
Expand Down
8 changes: 7 additions & 1 deletion src/mobius/integrations/gguf/_docs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_document_is_exact_generator_output() -> None:

def test_document_is_concise_and_reason_coded() -> None:
document = Path("docs/api/build_from_gguf.md").read_text(encoding="utf-8")
assert len(document.splitlines()) < 545
assert len(document.splitlines()) < 560
assert "RUNTIME_EVIDENCE_PENDING" in document
assert "qwen3.5-0.8b-q4-tokenizer" in document
assert "qwen2.5-0.5b-instruct-q8-tokenizer" in document
Expand Down Expand Up @@ -143,6 +143,12 @@ def test_runtime_support_requires_structured_evidence() -> None:
("qwen2", ("qwen2.5-0.5b-instruct-q8-ort-genai-0.15.2",)),
("lfm2", ("lfm2-350m-f16-ort-genai-0.15.2",)),
("qwen35moe", ("qwen3.5-moe-0.87b-q2-k-ort-genai-0.15.2",)),
("gpt2", ("gpt2-q2-k-ort-genai-0.15.2",)),
("starcoder2", ("tiny-starcoder2-q2-k-ort-genai-0.15.2",)),
("olmo", ("tiny-olmo-q2-k-ort-genai-0.15.2",)),
("mpt", ("tiny-mpt-q2-k-ort-genai-0.15.2",)),
("gptneox", ("pythia-70m-q2-k-ort-genai-0.15.2",)),
("starcoder", ("tiny-starcoder-q2-k-ort-genai-0.15.2",)),
]

pins = {pin.artifact_id for pin in MMPROJ_ARTIFACT_PINS}
Expand Down
5 changes: 4 additions & 1 deletion src/mobius/integrations/gguf/_exact_legacy_decoder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ def test_exact_legacy_config_tensor_and_graph_closure(architecture: str) -> None
"openelm": "openelm",
}[architecture]
)
assert spec.runtime is Support.DEFERRED
expected_runtime = (
Support.SUPPORTED if architecture in {"gptneox", "mpt"} else Support.DEFERRED
)
assert spec.runtime is expected_runtime
if architecture == "ernie4_5":
assert config.rope_interleave

Expand Down
4 changes: 2 additions & 2 deletions src/mobius/integrations/gguf/_quant_capabilities_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@ def test_selected_real_artifacts_stay_within_global_budget() -> None:
assert isinstance(policy, dict)
assert isinstance(artifacts, list)
assert isinstance(lossy, list)
assert len(artifacts) == 4
assert len(artifacts) == 10
assert len(lossy) == 1
selected = sum(int(record["size"]) for record in [*artifacts, *lossy])
assert selected == 2_390_132_320
assert selected == 2_724_371_296
assert selected == policy["selected_artifact_bytes"]
assert selected <= policy["max_selected_artifact_bytes"]
assert lossy[0]["lfs_sha256"] == (
Expand Down
36 changes: 36 additions & 0 deletions src/mobius/integrations/gguf/_route_census.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,42 @@ class RecentPRDependency:
"merged",
"follow-up hardening for sharded GGUF evidence edge cases after PR #656",
),
RecentPRDependency(
672,
"Prove Qwen3.5 MoE GGUF explicit-float runtime route",
"merged",
"Qwen3.5 MoE runtime evidence is complete; exclude it from follow-up evidence batches",
),
RecentPRDependency(
674,
"Keep Nemotron-H GGUF runtime fail-closed with pinned evidence",
"merged",
"Nemotron-H MoE blocker evidence is complete; exclude it from follow-up evidence batches",
),
RecentPRDependency(
677,
"Promote first GGUF text architecture cohort",
"merged",
"the text architecture cohort is merged into the authoritative graph-route census",
),
RecentPRDependency(
678,
"Promote generic GGUF projector cohort",
"merged",
"the generic projector cohort is merged into the authoritative projector census",
),
RecentPRDependency(
679,
"Add exact Hunyuan V3 GGUF graph support",
"merged",
"Hunyuan V3 graph and MTP routes are merged into the authoritative route census",
),
RecentPRDependency(
680,
"Promote first GGUF MoE architecture cohort",
"merged",
"the MoE architecture cohort is merged into the authoritative graph-route census",
),
)

# Reviewed dispositions for routes that cannot advance until Mobius owns a new
Expand Down
Loading
Loading