Support Qwen3.8-27B Q8 and BF16 processor loading and model discovery - #2301
Draft
marksmeltzer wants to merge 1 commit into
Draft
marksmeltzer wants to merge 1 commit into
marksmeltzer wants to merge 1 commit into
Conversation
Add Q8/BF16 Metal cards, registration coverage, component regressions and public request replay instructions. Carry the ArraysCache.advance dependency correction through Nix without changing dependency pins. Adapt the cache metadata dependency mechanism from Pierre Lamy's mlx-lm commit bb615ebdb5aff33eb931ac0627cae142bd7adbaa (advance hunk only). Implemented with GitHub Copilot under Mark Smeltzer's direction; human code review remains pending. Validate on macOS: Nix runtime/dashboard/test builds, Q8/BF16 real loaders, cache regression, 471 native tests, strict typecheck, Ruff and nix fmt. Historical four-node qualification is not a fresh validation of this upstream port.
marksmeltzer
marked this pull request as ready for review
September 10, 2026 05:56
marksmeltzer
marked this pull request as draft
September 10, 2026 05:56
This was referenced Sep 10, 2026
Open
marksmeltzer
marked this pull request as ready for review
September 10, 2026 07:32
marksmeltzer
marked this pull request as draft
September 10, 2026 17:44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support Qwen3.8-27B Q8 and BF16 processor loading and model discovery
Important
Required dependency for sustained generation: MLX-LM PR #1872
This EXO contribution cannot provide the qualified sustained-decoding path without
the companion ArraysCache correction. This branch temporarily carries that same
correction through its Nix dependency patch; PR #1872 is the upstream MLX-LM change.
Motivation
EXO's
VisionEncodercan fail to initialize the image processor for Qwen-familymodel repositories even when the installed Transformers version has a compatible
processor registered for the model configuration.
On the tested Qwen3.8-27B assets, processor metadata names
Qwen3VLImageProcessor, while Transformers 5.6.2 mapsQwen3_5ConfigtoQwen2VLImageProcessor. The fallback call toAutoImageProcessor.from_pretrainedwithout an explicit model configurationraises an unrecognized-image-processor error. Supplying the model configuration
allows the existing Transformers mapping to resolve the processor.
This proposal combines the processor correction with model discovery for the
Q8 and BF16 variants. Sustained generation also requires the companion MLX-LM
cache correction described below. Short text generation already worked on the
baseline despite the caught processor error; processor initialization is not
the cause of the separate sustained-decoding resource failure.
Changes
AutoConfig.from_pretrainedand pass it to the existing
AutoImageProcessor.from_pretrainedfallback.trust_remote_code=Truesetting on the fallback, anduse it for the added configuration load. This adds a configuration-loading
operation under that trust setting; it is not a security-hardening change.
VisionEncoderloader.mlx-community/Qwen3.8-27B-8bitandmlx-community/Qwen3.8-27B-bf16, with registration coverage.to use these changes from the public PR checkout.
The cards, registration test, regression scripts and Nix dependency carrier are
included in this branch. No downloaded model metadata, weights, sharding,
dependency pins or distributed transport changes are proposed. The cache
correction belongs to MLX-LM; this temporary carrier includes only the adapted
ArraysCache.advance()correction, not unrelated fork changes.Why It Works
The explicit configuration gives Transformers the model type needed for its
registered image-processor fallback. The change uses the library's existing
mapping instead of hard-coding a Qwen processor class or editing downloaded
model metadata.
With the same dependencies and assets, the baseline real EXO loader loaded
460.7 million vision parameters and then failed during processor resolution.
The corrected loader completed successfully. A separate factory-level probe
also processed a 64-by-64 RGB input with the explicit configuration.
These observations establish processor resolution and initialization, not
end-to-end image understanding or pixel-level equivalence between processors.
Compatibility
The added configuration load requires a loadable model configuration in the
selected processor repository. A processor-only repository without one could
previously resolve from processor metadata alone. Source review identified no
affected current EXO card, but universal processor-repository compatibility has
not been established.
Model Cards
The bundled cards make the two exact Hugging Face IDs discoverable through EXO's
normal catalog and placement workflow. They describe the models; they do not
contain weights, download weights by themselves, or fix runtime compatibility.
Users still need access to the model artifacts and enough memory for placement.
Both tested artifacts select the existing
qwen3_5implementation: 48 recurrentlayers and 16 full-attention layers. No new model architecture is introduced.
Card fields follow EXO's schema and the verified artifact configuration. The
cards advertise text/thinking and
MlxMetal, not unqualified vision, CPU or CUDAsupport. Their storage sizes come from the pinned safetensors indexes.
The model revisions in the test table identify the tested weights; a catalog
entry alone does not guarantee that a later download uses that same revision.
The 4-bit variant is outside this contribution's qualification.
Companion MLX-LM PR
Required MLX-LM dependency: PR #1872
The companion correction bounds lazy
ArraysCachelength and padding metadataby attaching it to a populated cache-state tensor with
mx.depends. EXO's testedbatch path evaluates token and logprob outputs without necessarily evaluating
every cache's complete state, which can leave metadata graphs growing during
decoding. This is separate from image-processor selection.
The complete Qwen result reported here used both corrections. Applying only the
processor change and model cards does not reproduce that qualification. The
MLX-LM cache correction is independently useful and does not require the EXO
processor change. The two PRs should link to each other while keeping source
ownership and test claims separate.
Reproducing the Environment
Reproduction starts from this public EXO PR checkout and public model artifacts.
No private repository, internal scripts, local journal or unpublished commit is
a prerequisite. The runtime, dashboard and test-environment Nix builds and
component checks passed on macOS 26.6.1 (25G76). Four-node qualification has not
been repeated on this branch. Full instructions and deterministic request
generation are included in
nix/tests/README.qwen38.mdandnix/tests/qwen-requests.py.exo-explore/exorepository. Use the samePR revision on every participating node, rather than mixing released and
patched EXO processes. Follow EXO's public macOS prerequisites and RDMA setup.
nix/arrays-cache-metadata.patchthrough themlx-lmoverride inpython/parts.nix. Both files are included in this PR. Installing MLX-LM into aseparate virtual environment does not modify EXO's Nix-managed dependency.
nix build path:.#exoand launch that resulting executable (
./result/bin/exo) on each node.All dependency sources and patches must resolve publicly. A
uv run exolaunch does not apply a Nix-only patch override and is not an equivalent
reproduction unless its own MLX-LM dependency is corrected and verified.
its local files discoverable to EXO. Use EXO's supported model storage and
download workflow; machine-specific filesystem paths are not required.
Confirm both catalog IDs are registered. A visible card is not proof that
weights are available or that a model is serving.
nodes with Tensor/JACCL over Thunderbolt/RDMA. Place one variant at a time
and confirm four assigned Ready runners with world size four before sending
requests. Other placement modes and node counts were not qualified here.
consumed by that build, then run sustained text generation for each variant.
The included request generator emits the retained sustained, recall and
cached-extension payloads; all six model/scenario combinations were compared
with the historical JSON and matched exactly. A short response alone does not
exercise the sustained-decode gap.
Public upstream base:
21a54c5ea0230a3bec1e1a786d200126c7e34ec6. The existinguv.lockis unchanged; MLX-LM remains pinned to6a3df6cd6b00a347ee40f12d97a182aaf86ea599with the Nix patch applied. Thehistorical distributed results below are supporting evidence, not fresh
qualification of this upstream port.
Test Plan
Manual Testing
Testing was performed on September 9, 2026 using four Mac Studio M3 Ultra nodes,
with four-way Tensor/JACCL over Thunderbolt/RDMA for distributed controls.
The processor reproduction itself is a component-level check, not a
four-node multimodal inference test.
Historical test environment (not yet reproduced from the public PR branch):
0.3.70, with both corrections applied.0.32.0.dev20260522.0.31.3, fork pinrltakashige/mlx-lm@6a3df6cd6b00a347ee40f12d97a182aaf86ea599.0.4.4; Transformers:5.6.2.Exact model revisions retained for reproduction:
mlx-community/Qwen3.8-27B-8bit815b83c0df8ffd1d1b5244cf75fd6ef14fca9ef9mlx-community/Qwen3.8-27B-bf166f265714824f3c38d4452baa1628aef3d9b9aae9The real loader regression was demonstrated red then green against the Q8
assets, with dependencies and assets held constant. Its source is included as
nix/tests/qwen-vision-regression.py; it takes themodel ID as its argument and calls
detect_vision_from_configandVisionEncoder.ensure_loadedwithout mocking the processor. The cache regressionis included as
nix/tests/arrays-cache-metadata-regression.py.Its 256-step check evaluates a populated cache tensor rather than the complete
cache state, and verifies bounded metadata graphs and numerical values.
Additional controls on the combined candidate:
production baseline. Arithmetic latency was 10.23 seconds versus 10.33 seconds
on the baseline; both context controls completed in approximately 43 seconds.
recall, followed by a cached extension to 243k tokens.
The Qwen sustained results also included a separate MLX-LM cache correction.
They are supporting compatibility observations, not isolated evidence that
this processor change fixes long-generation stability. No full-window,
concurrency, overnight, generated-code correctness, or end-to-end multimodal
claim is made.
Automated Testing
The PR includes both standalone regression scripts, not just their results.
They run locally on an Apple Silicon Mac with the corrected MLX runtime;
neither requires a running EXO service or four-node placement.
nix/tests/arrays-cache-metadata-regression.pycache[0], each metadata graph has at most eight edges and the final state and metadata values are correct.nix/tests/qwen-vision-regression.py MODEL_IDqwen3_5vision detection andVisionEncoder.ensure_loaded(), without a mocked processor. Loads vision weights and may take time and memory.Running the Component Tests
Run from the public PR checkout on macOS, after installing EXO's documented Nix
prerequisites. Use the included scripts and dependency patch/override
described above. Use a normal Python invocation, without
-OorPYTHONOPTIMIZE,because the regressions include assertions.
The runtime virtual environment is exposed by the current Nix package as
exo.venv. Resolve it from this checkout instead of using system Python oruv run, which could select a different MLX-LM build:Expected output:
For the processor test, first obtain the exact model revisions in the table
above. Set
MODEL_ROOTbelow to an absolute local directory with EXO-discoverablemodel directories, such as
mlx-community--Qwen3.8-27B-8bitandmlx-community--Qwen3.8-27B-bf16. The test itself is not a model-download script.Both Q8 and BF16 loader invocations passed on the public-source contribution.
The subshell isolates EXO's user state and restores the caller's environment on
exit. Its temporary home is retained for inspection.
EXO_MODELS_DIRSsuppliesthe local discovery path used by this loader check; clearing the read-only list
is confined to the test process. These are not recommended service settings,
and no model deletion or placement operation is performed by either script.
Expected processor output, one line per completed invocation:
An exception or nonzero exit is a failed check. A growing-metadata assertion
suggests checking whether the selected build actually includes the cache patch;
missing vision metadata suggests checking the model path and complete download.
A processor-resolution exception requires investigation with the exact dependency
versions. Do not treat any of these as a passing skip.
These component checks do not prove sustained generation, model-card registration,
or multimodal inference. Separate registration coverage is in
src/exo/shared/tests/test_qwen38_model_cards.py. Its native-suite invocation andthe opt-in four-node request/replay instructions are in
nix/tests/README.qwen38.md. The request generator does not place models orverify topology; those are explicit manual prerequisites.
Recorded Results
processor correction using the same dependencies and model files.
strict typecheck reported zero errors and warnings; repository lint passed.
Formatting was applied in the native validation copy.
Q8 and BF16 real loaders passed; cache regression passed; both registration
cases passed. Native suite: 471 passed, 3 skipped, 193 deselected. Strict
typecheck: zero errors/warnings; Ruff passed;
nix fmtapplied.src bench toolstargets with a private HOME and EXO_HOME unset. A bare pytest invocation hit
upstream's separate cluster-harness import (
exo_tools); that harness wasnot run. The source-suite approach follows upstream's macOS CI route.
on this upstream port and human code/description review remain pending.
Attribution And AI Disclosure
model-card infrastructure reused by this proposal.
mappings and image-processing implementations reused here. No new image
processor implementation is claimed.
MLX-LM #1632, the maintainer
revision by
zcbenz,thinkroth's analysis in#1641 and
#1642, Pierre Lamy's
bb615ebpatch,and
aidiffuser's subsequent batch-path report#1845. The adapted cache
mechanism is their prior work, not an invention of this submission. Its source
correction belongs in MLX-LM; an EXO dependency carrier must preserve that
attribution. These references do not imply
their authors reviewed or endorsed this PR.
AI assistance included source and prior-art analysis, implementation and
regression drafting, command execution, interpretation of captured test
results, and preparation of this description. The reported tests were
executed by the agent against real software and hardware using deterministic
scripts.
Related issue: #2302