mtplx 2.7.0__tar.gz → 2.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mtplx-2.7.0 → mtplx-2.7.2}/CHANGELOG.md +79 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/PKG-INFO +1 -1
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/descriptors.py +4 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cli.py +2 -1
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/forge.py +77 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/public.py +5 -2
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/diagnostics.py +5 -5
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/hf_loader.py +6 -4
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/model_catalog.py +18 -12
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/profiles.py +3 -2
- mtplx-2.7.2/mtplx/reasoning_effort.py +37 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/openai.py +7 -16
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/version.py +2 -2
- mtplx-2.7.2/mtplx/vision_graft.py +372 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/PKG-INFO +1 -1
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/SOURCES.txt +3 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/pyproject.toml +1 -1
- mtplx-2.7.2/scripts/graft_vision_tower.py +69 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/pillar_gate_qa.py +16 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/release_macos_v1.sh +7 -1
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_artifacts.py +85 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compressed_tensors.py +24 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_forge_cli.py +178 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_public_cli.py +25 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen38_family.py +56 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_server_openai.py +20 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/CITATION.cff +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/LICENSE +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/MANIFEST.in +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/NOTICE +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/README.md +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/a3b_compiled_target_prefix.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/a3b_mtp_batch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/a3b_whole_moe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/adaptive.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/app_settings.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/arrays_cache_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/artifacts.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/attention_context.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/attention_split.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/deepseek_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/gemma4_assistant.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/glm_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/hy_v3_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/mimo_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/nemotron_h_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/qwen3_next.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/registry.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/step3p5_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batched_decode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/admission.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/buckets.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/scheduler.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/state.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/code_eval.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/programming_prompts.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/aime_2026.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/calibration_coding.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/default.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/flappy.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/long_code.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/long_code_uncapped.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/python_modules_long.jsonl +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/aime.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/batch_equivalence.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/capture_commit_equivalence.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/competitor_baselines.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/contract_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/harness.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp1_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp1_sampler_smoke.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_adaptive.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_chain_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_depth_grid.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_depth_sweep.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_tree_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/multi_qmv_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/preflight.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/runtime_smoke.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/session_bank.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/truth.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/verify_profile.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/verify_qmm_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/verify_ratio.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/schema.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/validators/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/validators/aime.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/validators/basic.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/block_attention.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_bank/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_bank/codec.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_bank/cold_tier.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_state.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/chat_encode_cache.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/chat_encoding.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/forge_mixed_convert.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/compile_state.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/compiled_forward.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/compressed_tensors.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/config.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/constants.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/constrained.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/context_copy.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/correctors/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/correctors/diagonal_affine.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/correctors/low_rank.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/daemon_client.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/_static/assets/index-CRP90ECi.js +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/_static/assets/index-DYvLRZ33.css +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/_static/index.html +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_v4_adaptive_width.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_v4_attention_island.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_v4_attn_proj_wide_m3.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/default_models.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/draft_lm_head.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/draft_sampling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/engine_session.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/env.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/errors.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/expert_layout.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/fan_mode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/fast_sampling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/gdn_capture.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/gemma4_pair.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/generation.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/glm_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/graphbank.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/hardware.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/hy_v3_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernel_selfcheck.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/a3b_whole_moe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/copy_leaf.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/fused_norm.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/gdn_blocked_prefill.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/gdn_tape_headquarter.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_decode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_dense_mlp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_gated_oproj.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_combine.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_gather_gemm.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_merged.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_shared.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_swiglu.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_prefill_moe_combine.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_prefill_qk_rope.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_prefill_router.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_qk_rope_sliding.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_qk_yarn_full.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_qkvg_fused.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_residual_router.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_route_csort.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_router_topk.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_sdpa_2pass.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_sdpa_pair.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_steel_attn.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/lm_head_topk.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/logits_topk.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/native_gdn_tail.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_2pass.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_2pass_paged.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_2pass_paged_q8.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_gqa_packed.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/verify_mlp_fused.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kpi/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kpi/reference_vllm.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kpi/runtime_kpis.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kv_quant.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/laguna_alt_step.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/laguna_compiled_step.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/lfm2_fast.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/loop_guard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/metadata_scrub.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mimo_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/model_scheduler.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/deepseek_v4.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/laguna.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/laguna_config.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/laguna_fused.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/moe_packed_projections.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_activation_stats.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_adapters.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_batch_numerics.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/native_mlp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/nax_verify.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/nemotron_h_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/opencode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/optimization_profiles.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/pi.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/prefill_bench.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/progress_heartbeat.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/proj_quant.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/proposal_reranker.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/qwen3_5_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/qwen_row_owned_router.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ragged_attention.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ragged_kv_cache.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/reasoning_codecs.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/request_capture.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/retrieval.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/roofline_profile.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/runtime.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/runtime_options.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/sampling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/dashboard_state.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/mtp_batch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/adapter.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/thinking.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/tool_calling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server_urls.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/session_bank.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/speculative.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/step3p5_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/swival.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/templates/qwen36_froggeric_v19/chat_template.jinja +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/templates/qwen36_froggeric_v21_3/chat_template.jinja +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/thermal.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/thermal_sidecar.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/thinking_guard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/trace_parity.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/turboquant.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/banner.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/chat_printer.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/download_progress.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/onboarding.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/panels.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/progress.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vendored_arrays_cache.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vendored_hy_v3.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/verify_kernels.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/verify_qmv.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/processing.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/qwen3_vl_tower.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/splice.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/dependency_links.txt +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/entry_points.txt +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/requires.txt +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/top_level.txt +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/agent_user_path_qa.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/aime_serve_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/aime_shape_memory_bench.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/code_eval_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/collect_mtp_activation_stats.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/collect_mtp_hidden_calib.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/combine_mtp_adapters.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/compiled_verify_exactness.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/convert_step37_to_mtplx_step3p5.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_adaptive_width_arms.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_adaptive_width_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attention_island_arms.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attention_island_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attn_proj_wide_m3_arms.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attn_proj_wide_m3_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_build_mtp_model.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_decode_verify.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_dispatch_census.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_guard_window.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_logits_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_moe_tail_arms.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_moe_tail_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_moe_tail_guarded_bracket.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_mtp_bind_check.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_mtpk_bench.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_op_census.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_smoke_generate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_sparse_gate_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_validate_moe_tail_k3_bracket.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/eval_mtp_corrector.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/filter_mtp_adapter.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/fp16_turbo_exactness_20260707.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/fresh_venv_smoke.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/gauntlet_scoreboard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/hygiene_scan.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/install_macos.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/install_preview_global.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/kvcache_exactness_audit_20260703.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/kvcache_soak_20260703.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/kvcache_warm_probe_20260703.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/make_fp16_precision_sibling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/midform_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/oc_tap.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/oc_tap_diff.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/abba_final.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/accept_depth_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/arm_runner.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/forward_depth_bisect.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/longgen_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/loop_degradation_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/paired_longgen.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/sdpa_microbench.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/snapshot_tail.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/opencode_concurrency_qa.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/phase0h_paged_verifier_exactness.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/probe_mlx_pr3026_qsdpa.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/probe_mx_compile_buckets.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/probe_paged_gqa_sdpa_routes.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/candidate_truecold_20260703.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/cold_pair_recheck.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/competitors_20260703.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/decode_gap_matrix.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/hermes_pty_driver.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/omlx_probe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/pi_pty_driver.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/pillar_ab_20260703.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/tool_gauntlet_20260703.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/quality_fp16_parent_logitdiff_20260707.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/qwen35b_mtp_batch_evalplus_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/qwen35b_mtp_batch_numerics_attribution.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/qwen35b_mtp_batch_numerics_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/r1_chisquare_verifier_correctness.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/run_context_degradation_diagnostics.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/serve_openai_mtplx.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/session_cache_followup_qa.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/session_forensics.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/sparkle_rehearsal_kit.sh +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/step_acceptance.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/step_smoke.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/train_mtp_adapter_c4.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/validate_step_mtp_injector.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/scripts/walltime-lab/run_project.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/setup.cfg +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_compiled_target_prefix.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_mtp_batch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_mtp_batch_driver.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_whole_moe.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_adaptive.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_aime_serve_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_app_cli_env_parity.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ar_batch_penalties.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_arrays_cache_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_attention_split.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_background_warmup.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_batched_decode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_batching_foundation.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_bracket_tool_rescue.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cache_bank.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cache_state.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_chat_encode_cache.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cli_parity_tools.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_client_controls_default.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_code_eval.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_code_eval_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_prefix_ram_shadow.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_disk_usage_scan.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_foreground_yield.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_min_useful_matched.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_write_budget.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compile_state.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compiled_ar_wiring.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compiled_forward.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_config.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_config_profile_precedence.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_constrained.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_context_copy_stats.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_context_degradation_profiles.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_correctors.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cost_depth_policy.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_daemon_client.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_dashboard_endpoints.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_adaptive_width_bracket.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_adaptive_width_policy.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attention_island.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attention_island_bracket.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attn_proj_wide_m3.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attn_proj_wide_m3_bracket.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_decode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_dtypes.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_indexer.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_kernel_paths.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_loader.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_moe_tail.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_moe_tail_bracket.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_mtp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_new_math.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_o_lora.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_parity.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_sinkhorn_kernel.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_spec.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_swiglu_clamp.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_default_models.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_device_draft_core.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_diagnostics.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_download_progress.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_draft_lm_head.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_endpoint_probe_hygiene.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_engine_session_concurrency.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_engine_session_env.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_env_flag_parsing.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_fast_sampling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_forge_mixed_convert.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_blocked_prefill.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_boundary_retention.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_capture_rows.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_postconv_fusion.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_postconv_impl_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_tape_headquarter.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_generation_store_on_prefill.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_generation_sustained.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_graphbank_compiled_verify.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_greedy_draft_coupling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hf_loader.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hy_v3_mtp_backend.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hy_v3_mtp_graft.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hygiene_scan.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_idle_postcommit_subagent.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_kernel_selfcheck.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_alt_step.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_compiled_step.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_fused.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_model.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_steel_attn.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_lazy_snapshot_cow.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_lfm2_descriptor_resolution.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_lfm2_fast.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_loop_guard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_max_idle_watchdog.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_max_lifecycle.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_memory_pressure_guard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_metadata_scrub.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_metal_memory_caps.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_midform_gate.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_model_catalog.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_model_scheduler.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_model_scheduler_persistence.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_moe_force_unsorted.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_moe_packed_projections.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_activation_stats.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_adapters.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_alias_load_path.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_batch_numerics.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_batch_serving.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_depth_n.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_depth_sweep.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_payload_guards.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_weightless_degrade.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_nax_verify.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_no_mlx_imports.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_omlx_bridge.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_onboarding.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_openai_bridge.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_opencode.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_optimization_profiles.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_orphan_tool_markup.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_passive_probe_telemetry.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_penalties.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_penalty_request_wiring.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_persistent_replay.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_phase0h_paged_verifier_exactness.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_policy_fingerprint_stability.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_arrival_wait.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_cross_session_yield.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_prefix_reuse.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_resolve_for_request.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_tools_plumbing.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_wait.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_wait_integration.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_pre_first_token_telemetry.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prefill_bench.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prefill_chunk_defaults.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prefill_tps_regression.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_profiles.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_proj_quant.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prompt_encoding.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen35b_mtp_batch_evalplus_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen35b_mtp_batch_numerics_attribution.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen35b_mtp_batch_numerics_guarded.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen3_5_mtp_backend.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen3_5_mtp_object_level.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen_row_owned_router.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ragged_kv_cache.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_reasoning_stream_split.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_request_capture.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_retrieval.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_runtime_deepseek_v4_o_lora.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_runtime_kpis.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_runtime_model_alias.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_sampling.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_scoped_reasoning_history.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_sdpa_gqa_packed.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_session_bank.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_session_bank_env_caps.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_session_bank_restore_aliasing.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_snapshot_free_rejection_repair.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ssd_boundary_repersist.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stable_prefix_boundary.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stats_footer_scope.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_step3p5_mtp_patch.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stream_guard_env.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stream_stall_watchdog.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_sustained_long_context_qa.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_thermal.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_thermal_sidecar.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_thinking_guard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_tool_aware_stream_translator.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_tool_call_hidden_guard_and_key_repair.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_tool_nested_args_streaming.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_trace_parity.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_turboquant.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_turboquant_fallback.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ui_progress.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_validators.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vision_restore_span_guard.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vision_session_cache.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vision_tower.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vllm_reference.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/README.md +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/__init__.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/build.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/constants.py +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/copy_blocks.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/float8.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/gather_kv_cache.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/kv_scale_update.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/pagedattention.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/reshape_and_cache.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/utils.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/copy_blocks.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/float8.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/gather_kv_cache.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/gdn_linear_attention.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/kv_scale_update.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/pagedattention.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/reshape_and_cache.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/turboquant.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/utils.metal +0 -0
- {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/paged_ops.cpp +0 -0
|
@@ -4,6 +4,83 @@ All notable user-facing changes to MTPLX. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.7.2] - 2026-08-16
|
|
8
|
+
|
|
9
|
+
An emergency fix for `mtplx pull`: on 2.7.1 and older, re-pulling a repo that
|
|
10
|
+
changed upstream — such as the Qwen 3.8 repos re-published on 2026-08-15 with
|
|
11
|
+
their vision towers restored — can corrupt the local copy. Upgrade before
|
|
12
|
+
pulling.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **The Qwen 3.8 Hugging Face artifacts can see again (#263).** All six
|
|
17
|
+
published 3.8 repos (Bare Speed, Optimized Speed, Optimized Quality and
|
|
18
|
+
their FP16 siblings) shipped without their vision towers: the forge
|
|
19
|
+
`mlx_lm.convert` lane serializes only the text model, so the 333
|
|
20
|
+
`model.visual.*` tensors, `vision_config`, and the preprocessor sidecars
|
|
21
|
+
were silently dropped. The repos were re-published on 2026-08-15 with the
|
|
22
|
+
official bf16 tower grafted back as an index-registered
|
|
23
|
+
`model-vision.safetensors` (byte-for-byte from `Qwen/Qwen3.8-27B`; language
|
|
24
|
+
and MTP tensors untouched). Existing installs pick the delta up with
|
|
25
|
+
`mtplx pull`; images, `/health` `vision.enabled`, prompt caching with
|
|
26
|
+
images, and MTP decode were verified on all six builds. Thanks to
|
|
27
|
+
@kjellix for the report and the proven graft procedure.
|
|
28
|
+
- **Forge keeps vision towers from now on.** `mtplx forge build` grafts the
|
|
29
|
+
source's vision tower, `vision_config`, and preprocessor sidecars into the
|
|
30
|
+
converted artifact on every lane (`mtplx/vision_graft.py`), and fails
|
|
31
|
+
closed when a source that declares `vision_config` would produce a blind
|
|
32
|
+
artifact. A repair script for already-forged artifacts ships as
|
|
33
|
+
`scripts/graft_vision_tower.py`, and the pillar gate now asserts
|
|
34
|
+
`vision.enabled` before the vision-cache check so a blind build fails
|
|
35
|
+
loudly with the real cause.
|
|
36
|
+
- **`mtplx pull` no longer corrupts files that changed upstream (#258,
|
|
37
|
+
#234).** The
|
|
38
|
+
progress downloader treated a size-mismatched *complete* local file as a
|
|
39
|
+
resumable partial and byte-range-appended the remote tail onto the old
|
|
40
|
+
content — updating a repo in place (for example the restored 3.8 vision
|
|
41
|
+
indexes) corrupted `config.json` and `model.safetensors.index.json` and
|
|
42
|
+
left the local copy unloadable until re-downloaded. Stale files are now
|
|
43
|
+
discarded and re-fetched whole; genuine `*.incomplete` partials still
|
|
44
|
+
resume. **Users on ≤2.7.1 should upgrade before pulling repaired repos**;
|
|
45
|
+
a failed pull from an older build is recovered by deleting the corrupt
|
|
46
|
+
`config.json` + `model.safetensors.index.json` and pulling again.
|
|
47
|
+
|
|
48
|
+
## [2.7.1] - 2026-08-15
|
|
49
|
+
|
|
50
|
+
Clears the 2.7.0 known-issues list: `xhigh` is now selectable everywhere it is
|
|
51
|
+
offered, and the app's KV cache quantization toggle reaches Qwen 3.8.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- **`xhigh` no longer bounces back to `medium` in the app.** Choosing it in
|
|
56
|
+
Inference settings while the model was running, or running
|
|
57
|
+
`mtplx config set reasoning_effort xhigh`, was rejected: those two writing
|
|
58
|
+
surfaces carried their own hardcoded effort list that stopped at `high`,
|
|
59
|
+
while the request path already knew `xhigh`. Because the live-settings POST
|
|
60
|
+
is all-or-nothing, one unknown level threw away the whole payload and the
|
|
61
|
+
picker snapped back to the family default. All four writing surfaces
|
|
62
|
+
(serve/CLI `--reasoning-effort`, `mtplx config set`, the live-settings POST)
|
|
63
|
+
now read one shared vocabulary in `mtplx/reasoning_effort.py`, and narrowing
|
|
64
|
+
to what the loaded model actually supports stays where it belongs — the
|
|
65
|
+
family's own `effort_levels`.
|
|
66
|
+
- **The app's KV cache quantization toggle now applies to Qwen 3.8.** The
|
|
67
|
+
launch gate listed only `qwen3_5`/`qwen3_6`, so a 3.8 launch exported
|
|
68
|
+
nothing while Settings showed `q8`.
|
|
69
|
+
- **`mtplx doctor` names the model it actually checks** instead of hardcoding
|
|
70
|
+
the previous default, and turbo's profile note reports the real compiled
|
|
71
|
+
verify fence (32,768, raised from 12,288 in 2.7.0) rather than the stale one.
|
|
72
|
+
- **A built app can no longer rank below the release it supersedes.** Sparkle
|
|
73
|
+
orders updates by `CFBundleVersion` alone, and the number derived from the
|
|
74
|
+
version was narrow enough that 2.7.1 computed lower than the 2.7.0 that
|
|
75
|
+
shipped — so a fresh build offered 2.7.0 to itself as an update. The
|
|
76
|
+
derivation now has room for the whole version and the appcast reads its
|
|
77
|
+
number back off the built bundle instead of being told one separately.
|
|
78
|
+
|
|
79
|
+
### Still open from 2.7.0
|
|
80
|
+
|
|
81
|
+
- With reasoning switched off in a plain chat with no tools, Qwen 3.8 can
|
|
82
|
+
still emit a stray tool call and cut the turn short. Keep thinking on.
|
|
83
|
+
|
|
7
84
|
## [2.7.0] - 2026-08-15
|
|
8
85
|
|
|
9
86
|
Qwen3.8 support 🎉. Qwen3.8-27B came out on 2026-08-14; this release runs it
|
|
@@ -1338,6 +1415,8 @@ working as one product. Full notes:
|
|
|
1338
1415
|
completions, and Anthropic `stop_sequences`) and `/v1/completions`
|
|
1339
1416
|
streams tokens as they are generated with real finish reasons.
|
|
1340
1417
|
|
|
1418
|
+
[2.7.2]: https://github.com/youssofal/MTPLX/releases/tag/v2.7.2
|
|
1419
|
+
[2.7.1]: https://github.com/youssofal/MTPLX/releases/tag/v2.7.1
|
|
1341
1420
|
[2.7.0]: https://github.com/youssofal/MTPLX/releases/tag/v2.7.0
|
|
1342
1421
|
[2.6.0]: https://github.com/youssofal/MTPLX/releases/tag/v2.6.0
|
|
1343
1422
|
[2.5.4]: https://github.com/youssofal/MTPLX/releases/tag/v2.5.4
|
|
@@ -82,6 +82,10 @@ class ReasoningCodec:
|
|
|
82
82
|
supported: bool = True
|
|
83
83
|
modes: tuple[str, ...] = ("auto", "on", "off")
|
|
84
84
|
history_policy: str = "preserve_when_enabled"
|
|
85
|
+
# Drawn from mtplx.reasoning_effort.REASONING_EFFORT_LEVELS: the app
|
|
86
|
+
# renders these verbatim, so a level outside that vocabulary is one the
|
|
87
|
+
# user can pick and no writing surface will accept
|
|
88
|
+
# (test_reasoning_effort_vocabulary_covers_every_family pins it).
|
|
85
89
|
effort_levels: tuple[str, ...] = ()
|
|
86
90
|
default_effort: str | None = None
|
|
87
91
|
|
|
@@ -23,6 +23,7 @@ from .profiles import (
|
|
|
23
23
|
list_profiles,
|
|
24
24
|
resolve_profile_name,
|
|
25
25
|
)
|
|
26
|
+
from .reasoning_effort import REASONING_EFFORT_CHOICES
|
|
26
27
|
from .runtime_options import canonicalize_flag_tokens, normalize_paged_kv_quantization
|
|
27
28
|
from .version import DISPLAY_VERSION, __version__
|
|
28
29
|
|
|
@@ -573,7 +574,7 @@ def _add_reasoning_arg(
|
|
|
573
574
|
def _add_reasoning_effort_arg(parser: argparse.ArgumentParser) -> None:
|
|
574
575
|
parser.add_argument(
|
|
575
576
|
"--reasoning-effort",
|
|
576
|
-
choices=
|
|
577
|
+
choices=list(REASONING_EFFORT_CHOICES),
|
|
577
578
|
default="auto",
|
|
578
579
|
help=(
|
|
579
580
|
"Reasoning effort for models that expose levels, such as Qwen 3.8 "
|
|
@@ -1028,6 +1028,9 @@ def _cmd_build(args: Any) -> int:
|
|
|
1028
1028
|
if _cancel_requested(args.run_id):
|
|
1029
1029
|
raise ForgeError("forge cancelled", code=130)
|
|
1030
1030
|
|
|
1031
|
+
_ensure_vision_tower(source_path, destination)
|
|
1032
|
+
_validate_vision_payload(source_path, destination)
|
|
1033
|
+
|
|
1031
1034
|
_calibrate_sidecar(
|
|
1032
1035
|
source_path,
|
|
1033
1036
|
destination,
|
|
@@ -1767,6 +1770,51 @@ def _validate_mtp_sidecar_payload(destination: Path) -> dict[str, Any] | None:
|
|
|
1767
1770
|
return audit
|
|
1768
1771
|
|
|
1769
1772
|
|
|
1773
|
+
def _ensure_vision_tower(source: Path, destination: Path) -> None:
|
|
1774
|
+
"""Restore the vision tower that text-only convert lanes drop.
|
|
1775
|
+
|
|
1776
|
+
``mlx_lm.convert`` serializes only the text model, so multimodal sources
|
|
1777
|
+
lose their vision tensors, ``vision_config``, and preprocessor sidecars
|
|
1778
|
+
(issue #263). Graft them back from the source directory. A no-op for
|
|
1779
|
+
text-only sources and for lanes (mirror, compressed-tensors) that already
|
|
1780
|
+
preserved the tower.
|
|
1781
|
+
"""
|
|
1782
|
+
if not source.is_dir():
|
|
1783
|
+
return
|
|
1784
|
+
from mtplx.vision_graft import VisionGraftError, graft_vision_tower
|
|
1785
|
+
|
|
1786
|
+
try:
|
|
1787
|
+
report = graft_vision_tower(source, destination, verify_load=True)
|
|
1788
|
+
except VisionGraftError as exc:
|
|
1789
|
+
raise ForgeError(f"vision tower graft failed: {exc}") from exc
|
|
1790
|
+
if report.get("status") == "grafted":
|
|
1791
|
+
_err(
|
|
1792
|
+
f"[forge] restored vision tower: {report.get('tensors')} tensors "
|
|
1793
|
+
f"({report.get('bytes')} bytes) in {report.get('vision_file')}"
|
|
1794
|
+
)
|
|
1795
|
+
|
|
1796
|
+
|
|
1797
|
+
def _validate_vision_payload(source: Path, destination: Path) -> None:
|
|
1798
|
+
"""Fail closed when a multimodal source produced a blind artifact."""
|
|
1799
|
+
if not source.is_dir():
|
|
1800
|
+
return
|
|
1801
|
+
try:
|
|
1802
|
+
source_config = _load_json(source / "config.json")
|
|
1803
|
+
except Exception:
|
|
1804
|
+
return
|
|
1805
|
+
if not isinstance(source_config, dict) or not isinstance(
|
|
1806
|
+
source_config.get("vision_config"), dict
|
|
1807
|
+
):
|
|
1808
|
+
return
|
|
1809
|
+
from mtplx.vision import vision_spec_for_model_dir
|
|
1810
|
+
|
|
1811
|
+
if vision_spec_for_model_dir(destination) is None:
|
|
1812
|
+
raise ForgeError(
|
|
1813
|
+
"source declares vision_config but the forged artifact resolves no "
|
|
1814
|
+
"vision tower; the convert lane dropped it (issue #263)"
|
|
1815
|
+
)
|
|
1816
|
+
|
|
1817
|
+
|
|
1770
1818
|
def _audit_mtp_sidecar_payload(mtp_path: Path) -> dict[str, Any]:
|
|
1771
1819
|
problems: list[str] = []
|
|
1772
1820
|
try:
|
|
@@ -2922,6 +2970,9 @@ def _stamp_runtime_metadata(
|
|
|
2922
2970
|
metadata["mtp_sidecar"] = inspection.mtp.sidecar_format
|
|
2923
2971
|
else:
|
|
2924
2972
|
metadata.setdefault("mtp_sidecar", "mtp.safetensors")
|
|
2973
|
+
vision_stamp = _vision_metadata_stamp(model_path)
|
|
2974
|
+
if vision_stamp is not None:
|
|
2975
|
+
metadata["vision"] = vision_stamp
|
|
2925
2976
|
metadata["base_trunk"] = source_repo
|
|
2926
2977
|
metadata.setdefault("artifact_role", "forge-local")
|
|
2927
2978
|
metadata["forge_provenance"] = {
|
|
@@ -2939,6 +2990,32 @@ def _stamp_runtime_metadata(
|
|
|
2939
2990
|
return metadata
|
|
2940
2991
|
|
|
2941
2992
|
|
|
2993
|
+
def _vision_metadata_stamp(model_path: Path) -> dict[str, Any] | None:
|
|
2994
|
+
"""Provenance for artifacts that carry a vision tower, or None."""
|
|
2995
|
+
from mtplx.vision import resolve_vision_prefix
|
|
2996
|
+
|
|
2997
|
+
index_path = model_path / "model.safetensors.index.json"
|
|
2998
|
+
if not index_path.exists():
|
|
2999
|
+
return None
|
|
3000
|
+
try:
|
|
3001
|
+
index = _load_json(index_path)
|
|
3002
|
+
except Exception:
|
|
3003
|
+
return None
|
|
3004
|
+
weight_map = index.get("weight_map") if isinstance(index, dict) else None
|
|
3005
|
+
if not isinstance(weight_map, dict):
|
|
3006
|
+
return None
|
|
3007
|
+
prefix = resolve_vision_prefix(weight_map)
|
|
3008
|
+
if prefix is None:
|
|
3009
|
+
return None
|
|
3010
|
+
vision_keys = [key for key in weight_map if str(key).startswith(prefix)]
|
|
3011
|
+
shards = sorted({str(weight_map[key]) for key in vision_keys})
|
|
3012
|
+
return {
|
|
3013
|
+
"tensor_count": len(vision_keys),
|
|
3014
|
+
"prefix": prefix,
|
|
3015
|
+
"shards": shards,
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
|
|
2942
3019
|
def _speed_evidence(rows: list[dict[str, Any]]) -> dict[str, Any]:
|
|
2943
3020
|
winner = _winning_row(rows)
|
|
2944
3021
|
ar_row = next((row for row in rows if row.get("depth") == 0), None)
|
|
@@ -125,6 +125,7 @@ from mtplx.profiles import (
|
|
|
125
125
|
restore_profile_env,
|
|
126
126
|
runtime_env_with_contract_overrides,
|
|
127
127
|
)
|
|
128
|
+
from mtplx.reasoning_effort import REASONING_EFFORT_CHOICES
|
|
128
129
|
from mtplx.server_urls import (
|
|
129
130
|
bind_label,
|
|
130
131
|
connect_host_for_bind,
|
|
@@ -14347,8 +14348,10 @@ def cmd_config_public(args: Any) -> int:
|
|
|
14347
14348
|
)
|
|
14348
14349
|
if key == "reasoning" and value not in {"auto", "on", "off"}:
|
|
14349
14350
|
raise SystemExit("reasoning must be auto, on, or off")
|
|
14350
|
-
if key == "reasoning_effort" and value not in
|
|
14351
|
-
raise SystemExit(
|
|
14351
|
+
if key == "reasoning_effort" and value not in REASONING_EFFORT_CHOICES:
|
|
14352
|
+
raise SystemExit(
|
|
14353
|
+
"reasoning_effort must be " + ", ".join(REASONING_EFFORT_CHOICES)
|
|
14354
|
+
)
|
|
14352
14355
|
if key in {
|
|
14353
14356
|
"max_active_requests",
|
|
14354
14357
|
"decode_batch_max",
|
|
@@ -26,7 +26,7 @@ from mtplx.profiles import DEFAULT_HF_MODEL_ID, DEFAULT_PROFILE_NAME
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
GIB = 1024**3
|
|
29
|
-
DEFAULT_SPEED_MODEL_SIZE_BYTES =
|
|
29
|
+
DEFAULT_SPEED_MODEL_SIZE_BYTES = 21_313_949_792 # Qwen3.8-27B Optimized Speed (Hub bytes, incl. restored vision tower #263)
|
|
30
30
|
MIN_RECOMMENDED_MEMORY_BYTES = 48 * GIB
|
|
31
31
|
SUPPORT_MACOS_MAJOR = 14
|
|
32
32
|
SUPPORT_PYTHON = (3, 11)
|
|
@@ -441,7 +441,7 @@ def build_diagnostic_checks(
|
|
|
441
441
|
},
|
|
442
442
|
"default model available in the HF cache or as the verified local startup model",
|
|
443
443
|
model_cache_fix,
|
|
444
|
-
"https://huggingface.co/
|
|
444
|
+
f"https://huggingface.co/{DEFAULT_HF_MODEL_ID}",
|
|
445
445
|
f"mtplx pull {DEFAULT_HF_MODEL_ID}",
|
|
446
446
|
)
|
|
447
447
|
)
|
|
@@ -452,9 +452,9 @@ def build_diagnostic_checks(
|
|
|
452
452
|
"fail" if stale else "pass",
|
|
453
453
|
"error",
|
|
454
454
|
DEFAULT_HF_MODEL_ID,
|
|
455
|
-
"Youssofal/
|
|
455
|
+
"a published Youssofal/... repo (not a local mtplx/ or models/ path)",
|
|
456
456
|
"Pull the default model, or pass --model to serve a different one.",
|
|
457
|
-
"https://huggingface.co/
|
|
457
|
+
f"https://huggingface.co/{DEFAULT_HF_MODEL_ID}",
|
|
458
458
|
f"mtplx pull {DEFAULT_HF_MODEL_ID}",
|
|
459
459
|
)
|
|
460
460
|
)
|
|
@@ -481,7 +481,7 @@ def build_diagnostic_checks(
|
|
|
481
481
|
hf_observed,
|
|
482
482
|
"default Hugging Face repo is reachable from this machine",
|
|
483
483
|
"Check network/HF auth or verify the model repo is public.",
|
|
484
|
-
"https://huggingface.co/
|
|
484
|
+
f"https://huggingface.co/{DEFAULT_HF_MODEL_ID}",
|
|
485
485
|
f"mtplx pull {DEFAULT_HF_MODEL_ID}",
|
|
486
486
|
)
|
|
487
487
|
)
|
|
@@ -637,10 +637,12 @@ def _download_repo_file(
|
|
|
637
637
|
|
|
638
638
|
partial = target.with_name(target.name + ".incomplete")
|
|
639
639
|
if target.exists():
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
640
|
+
# A size-mismatched final file is a stale version of a file that
|
|
641
|
+
# changed upstream (e.g. a repaired index gaining vision entries),
|
|
642
|
+
# not an interrupted download. Resuming from it would append the
|
|
643
|
+
# remote tail onto old content and corrupt the file, so discard it.
|
|
644
|
+
# Only a leftover *.incomplete partial may be range-resumed.
|
|
645
|
+
target.unlink()
|
|
644
646
|
existing = partial.stat().st_size if partial.exists() else 0
|
|
645
647
|
if expected_size is not None and existing > expected_size:
|
|
646
648
|
partial.unlink()
|
|
@@ -128,8 +128,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
|
|
|
128
128
|
),
|
|
129
129
|
hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Bare-Speed",
|
|
130
130
|
# Exact byte sum of the published HF repo files (2026-08-15 tree API;
|
|
131
|
-
# three trunk shards + bf16 MTP sidecar +
|
|
132
|
-
|
|
131
|
+
# three trunk shards + bf16 MTP sidecar + restored bf16 vision tower
|
|
132
|
+
# (#263) + tokenizer + card).
|
|
133
|
+
size_bytes=16_924_164_062,
|
|
133
134
|
# Measured 2026-08-14: request-log MLX high-water 19.6 GiB during
|
|
134
135
|
# quiet-window 2.4k-context serving (boot + Flappy arms + rung).
|
|
135
136
|
peak_memory_gib=20.0,
|
|
@@ -150,8 +151,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
|
|
|
150
151
|
),
|
|
151
152
|
hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed",
|
|
152
153
|
# Exact byte sum of the published HF repo files (2026-08-15 tree API;
|
|
153
|
-
# module_overrides recipe, 5.807 bits/weight, bf16 MTP sidecar
|
|
154
|
-
|
|
154
|
+
# module_overrides recipe, 5.807 bits/weight, bf16 MTP sidecar,
|
|
155
|
+
# restored bf16 vision tower (#263)).
|
|
156
|
+
size_bytes=21_313_949_792,
|
|
155
157
|
# Measured 2026-08-14: request-log MLX high-water 24.6 GiB during
|
|
156
158
|
# quiet-window 2.4k-context serving (boot + Flappy arms + rung).
|
|
157
159
|
peak_memory_gib=25.0,
|
|
@@ -169,8 +171,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
|
|
|
169
171
|
"8-bit dynamic quant. Good coding speeds and perfect quality."
|
|
170
172
|
),
|
|
171
173
|
hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Quality",
|
|
172
|
-
# Exact byte sum of the published HF repo files (2026-08-15 tree API
|
|
173
|
-
|
|
174
|
+
# Exact byte sum of the published HF repo files (2026-08-15 tree API;
|
|
175
|
+
# includes the restored bf16 vision tower, #263).
|
|
176
|
+
size_bytes=30_370_840_073,
|
|
174
177
|
# Measured 2026-08-14: request-log MLX high-water 32.9 GiB during
|
|
175
178
|
# quiet-window 2.4k-context serving (boot + Flappy arms + rung).
|
|
176
179
|
peak_memory_gib=33.0,
|
|
@@ -193,8 +196,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
|
|
|
193
196
|
"coding tasks. FP16 build for M1 and M2 Macs."
|
|
194
197
|
),
|
|
195
198
|
hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Bare-Speed-FP16",
|
|
196
|
-
# Exact byte sum of the
|
|
197
|
-
|
|
199
|
+
# Exact byte sum of the published HF repo files (2026-08-15 tree API;
|
|
200
|
+
# includes the restored bf16 vision tower, #263).
|
|
201
|
+
size_bytes=16_924_647_669,
|
|
198
202
|
# Same packs and tensor bytes as the parent; peak carried over.
|
|
199
203
|
peak_memory_gib=20.0,
|
|
200
204
|
recommended_tiers=frozenset({LEGACY_TIER}),
|
|
@@ -213,8 +217,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
|
|
|
213
217
|
"FP16 build for M1 and M2 Macs. Recommended."
|
|
214
218
|
),
|
|
215
219
|
hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed-FP16",
|
|
216
|
-
# Exact byte sum of the
|
|
217
|
-
|
|
220
|
+
# Exact byte sum of the published HF repo files (2026-08-15 tree API;
|
|
221
|
+
# includes the restored bf16 vision tower, #263).
|
|
222
|
+
size_bytes=21_314_434_309,
|
|
218
223
|
# Same packs and tensor bytes as the parent; peak carried over.
|
|
219
224
|
peak_memory_gib=25.0,
|
|
220
225
|
recommended_tiers=frozenset({LEGACY_TIER}),
|
|
@@ -232,8 +237,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
|
|
|
232
237
|
"FP16 build for M1 and M2 Macs."
|
|
233
238
|
),
|
|
234
239
|
hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Quality-FP16",
|
|
235
|
-
# Exact byte sum of the
|
|
236
|
-
|
|
240
|
+
# Exact byte sum of the published HF repo files (2026-08-15 tree API;
|
|
241
|
+
# includes the restored bf16 vision tower, #263).
|
|
242
|
+
size_bytes=30_371_326_040,
|
|
237
243
|
# Same packs and tensor bytes as the parent; peak carried over.
|
|
238
244
|
peak_memory_gib=33.0,
|
|
239
245
|
recommended_tiers=frozenset({LEGACY_TIER}),
|
|
@@ -553,8 +553,9 @@ TURBO_PROFILE = RuntimeProfile(
|
|
|
553
553
|
"4-bit and 8-bit affine models; 6-bit models silently run the "
|
|
554
554
|
"stock path.",
|
|
555
555
|
"Compiled verify engages on 4-bit and 8-bit affine trunks at "
|
|
556
|
-
"contexts <=
|
|
557
|
-
"quantizations/contexts run the eager verify
|
|
556
|
+
"contexts <= 32768 (parity2-validated on both; fence raised from "
|
|
557
|
+
"12288 in 2.7.0); other quantizations/contexts run the eager verify "
|
|
558
|
+
"path unchanged.",
|
|
558
559
|
"Measured 2026-07-02/03 on M5 Max chat lane (app-launch flags, "
|
|
559
560
|
"thinking on): 27B Optimized-Speed 44.7 -> 58-60 tok/s (vk_k "
|
|
560
561
|
"within ~2% of the retired dflash-port kernel both directions); "
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Canonical MTPLX reasoning-effort vocabulary shared by CLI and server code.
|
|
2
|
+
|
|
3
|
+
Each model family declares the subset it supports through its
|
|
4
|
+
``ReasoningCodec.effort_levels``, and that subset is exactly what the app's
|
|
5
|
+
effort picker renders. Every *writing* surface — serve/CLI argparse,
|
|
6
|
+
``mtplx config set``, and the live-settings POST — must therefore accept this
|
|
7
|
+
whole vocabulary and leave the per-family narrowing to the one place that
|
|
8
|
+
knows which model is loaded (``_reasoning_effort_for_state``).
|
|
9
|
+
|
|
10
|
+
Surfaces that inline their own list go stale the moment a family ships a new
|
|
11
|
+
level. That is how 2.7.0 shipped with Qwen 3.8's ``xhigh`` bouncing back to
|
|
12
|
+
``medium``: the request path knew the level, the live-settings coercer did
|
|
13
|
+
not, and because that POST is all-or-nothing the app's whole settings payload
|
|
14
|
+
was rejected.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Ordered low to high.
|
|
23
|
+
REASONING_EFFORT_LEVELS = ("low", "medium", "high", "xhigh")
|
|
24
|
+
# "auto" is not a level; it means "use the loaded family's default_effort".
|
|
25
|
+
REASONING_EFFORT_AUTO = "auto"
|
|
26
|
+
REASONING_EFFORT_CHOICES = (REASONING_EFFORT_AUTO, *REASONING_EFFORT_LEVELS)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def normalize_reasoning_effort(
|
|
30
|
+
value: Any, *, default: str = REASONING_EFFORT_AUTO
|
|
31
|
+
) -> str:
|
|
32
|
+
effort = str(value or default).strip().lower()
|
|
33
|
+
if effort not in REASONING_EFFORT_CHOICES:
|
|
34
|
+
raise ValueError(
|
|
35
|
+
"reasoning_effort must be one of: " + ", ".join(REASONING_EFFORT_CHOICES)
|
|
36
|
+
)
|
|
37
|
+
return effort
|
|
@@ -83,6 +83,7 @@ from mtplx.mtp_batch_numerics import (
|
|
|
83
83
|
)
|
|
84
84
|
from mtplx.backends.descriptors import (
|
|
85
85
|
BackendDescriptor,
|
|
86
|
+
ReasoningCodec,
|
|
86
87
|
assistant_target_distribution_choices,
|
|
87
88
|
descriptor_for_backend_id,
|
|
88
89
|
descriptor_for_model,
|
|
@@ -111,6 +112,10 @@ from mtplx.gemma4_pair import (
|
|
|
111
112
|
resolve_gemma4_pair_paths,
|
|
112
113
|
)
|
|
113
114
|
from mtplx.model_scheduler import ModelWorkScheduler
|
|
115
|
+
from mtplx.reasoning_effort import (
|
|
116
|
+
REASONING_EFFORT_CHOICES,
|
|
117
|
+
normalize_reasoning_effort as _normalize_reasoning_effort,
|
|
118
|
+
)
|
|
114
119
|
from mtplx.retrieval import RetrievalError, RetrievalTrustError
|
|
115
120
|
from mtplx.sampling import SamplerConfig
|
|
116
121
|
from mtplx.profiles import (
|
|
@@ -13286,12 +13291,7 @@ def _coerce_setting(name: str, value: Any) -> Any:
|
|
|
13286
13291
|
)
|
|
13287
13292
|
return text
|
|
13288
13293
|
if name == "reasoning_effort":
|
|
13289
|
-
|
|
13290
|
-
if text not in {"auto", "low", "medium", "high"}:
|
|
13291
|
-
raise ValueError(
|
|
13292
|
-
"reasoning_effort must be 'auto', 'low', 'medium', or 'high'"
|
|
13293
|
-
)
|
|
13294
|
-
return text
|
|
13294
|
+
return _normalize_reasoning_effort(value)
|
|
13295
13295
|
return value
|
|
13296
13296
|
|
|
13297
13297
|
|
|
@@ -21727,15 +21727,6 @@ def _thinking_enabled_for_request(
|
|
|
21727
21727
|
)
|
|
21728
21728
|
|
|
21729
21729
|
|
|
21730
|
-
def _normalize_reasoning_effort(value: Any, *, default: str = "auto") -> str:
|
|
21731
|
-
effort = str(value or default).strip().lower()
|
|
21732
|
-
if effort not in {"auto", "low", "medium", "high", "xhigh"}:
|
|
21733
|
-
raise ValueError(
|
|
21734
|
-
"reasoning_effort must be one of: auto, low, medium, high, xhigh"
|
|
21735
|
-
)
|
|
21736
|
-
return effort
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
21730
|
def _reasoning_effort_for_state(
|
|
21740
21731
|
state: ServerState,
|
|
21741
21732
|
*,
|
|
@@ -29022,7 +29013,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
|
29022
29013
|
)
|
|
29023
29014
|
parser.add_argument(
|
|
29024
29015
|
"--reasoning-effort",
|
|
29025
|
-
choices=
|
|
29016
|
+
choices=list(REASONING_EFFORT_CHOICES),
|
|
29026
29017
|
default="auto",
|
|
29027
29018
|
help=(
|
|
29028
29019
|
"Backend reasoning effort. Qwen 3.8 exposes xhigh/medium/low "
|