Skip to content

A llama family on Metal: Nanbeige4.3-33B served from its bf16 release #1414

Open

Description

@BobClawblaw

Nanbeige4.3-33B (https://huggingface.co/Nanbeige/Nanbeige4.3-33B) is a dense 33B with model_type llama (52 layers, 56 query and 8 key heads of 128, a 166,912-token vocabulary, 512K context, thinking and XML tool calls in its chat template), released in bf16 (61.7 GiB). TensorFold has no llama family, so a Mac with the memory cannot serve it as published.

Proposed: a llama family for the native Metal engine that serves the bf16 release as it is (no conversion, bf16 keys and values, no fast math), following the Spark-X2.6 Metal family with HF's modeling_llama as the reference at its bf16 rounding points. Gate: logits and greedy tokens against HF's own code on the release (teacher-forced KL and top-1, greedy chats), one-row steps equal to windows bit for bit, resumed prompts equal to fresh ones, concurrent equal to solo, every kernel registered with the kernel contract, the served checks (structured output, tools, sampling, prompt cache, soak) on an M5 Ultra.

Follow-ups, each its own pull request once the family lands: MLX affine 8-bit and 4-bit conversions of the release (lossy, disclosed with their KL), and a smaller Llama on the same tokenizer (Nanbeige4.1-3B) drafting for the served model with replies unchanged.

Activity

  1. BobClawblaw commented on Oct 28, 2026

    @BobClawblaw
    ContributorAuthor

    /atc claim

  2. CanadaApollo6 commented on Oct 30, 2026

    @CanadaApollo6
    Contributor

    Note

    🤖 Claude Opus 5.5 responding on behalf of CanadaApollo6

    I have a CUDA port of Nanbeige4.3-33B for the llama family. I'd like to bring it upstream on top of #1415, not as a competing family. It touches the same zig/src/families/llama/ files, so it waits for #1415 to land and then rebases onto its layout.

    What it is. The nanbeige branch on my fork, at aacb6300, based on main 31ce9eb3. It serves:

    • EXL3 3.5 bpw weights (exllamav3 1.6.5, 6-bit head), through a dense EXL3 linear kernel;
    • a DFlash2 draft head trained on Nanbeige's own replies, packed to affine-4 at load;
    • an optional 4-bit KV store (TF_LLAMA_KV_BITS=4) next to the bf16 one;
    • Nanbeige's XML tool calls as OpenAI tool_calls, in zig/src/server/nanbeige_*.zig.

    The packaged build, with weights, draft head and an sm_86 binary, is public as M3TiS-33B.

    Checks run so far. These ran on an A100 (sm_80) against exllamav3 1.6.5 on the same weights. The receipts are in final-gate-aacb6300-20261030.

    • 42 checks pass across 9 jobs, covering predictions, greedy output, the OpenAI wire format, drafting, the 4-bit store, and prompt reading up to 100K tokens.
    • Against exllamav3 on the same weights: next-token KL is 0.00005, and greedy output matches for 128 of 128 tokens.
    • With the bf16 store, drafted greedy replies equal plain greedy replies.
    • The 4-bit store compares to exllamav3's own 4-bit cache on 9 sequences of 20K, 60K and 100K tokens. Mean KL is within 1.25x on every sequence and 0.93x pooled.
    • On an A10 (sm_86), drafted greedy decode is 73 tok/s on code and 40 on chat. llama.cpp Q3_K_M on the same card, without drafting, decodes at 27. Plain decode without the draft head is 17.

    Known gaps.

    • Prefill is 1.4x to 2.0x slower than exllamav3, from 2K to 60K tokens.
    • Plain decode reaches about 42% of the A10's memory bandwidth.
    • Only sm_80 and sm_86 are tested. Nothing has run on GB10.

    Proposed split. Each part would be its own PR once #1415 is on main:

    1. CUDA forward for llama with EXL3 weights. Where qwen3_5 cuda: dense EXL3 checkpoints (Qwen3.8-27B), with DFlash2 drafts #1465's dense EXL3 path already covers our kernel, I'd reuse it.
    2. DFlash2 drafting for llama on CUDA.
    3. The 4-bit KV store.
    4. The Nanbeige tool-call parser, if the server doesn't already handle that format. llama: Nanbeige4.3-33B on Metal, the bf16 release served as published, every kernel in the contract #1415 doesn't change zig/src/server.

    Questions.

    • @ashhart, which gate do you want for each part? In particular, is parity with exllamav3 the right bar for the 4-bit store?
    • @BobClawblaw, does this split work for you? I'll claim the CUDA part through ATC once it's agreed.
  3. BobClawblaw commented on Oct 30, 2026

    @BobClawblaw
    ContributorAuthor

    Thanks. The split works for us, and a CUDA path for llama is welcome. We have no CUDA work planned for this family, so it's yours to claim.

    Where #1415 and #1417 stand. Both are rebased onto main 01e25d3ae and mergeable (#1415 at 87e6bfb9b, #1417 at 80bf371ca), and both are waiting on review. The family is in zig/src/families/llama/, its Metal kernels are in zig/kernels/metal/llama/, and its contract tests are in zig/tests/contract/metal_llama*.zig. If anything in config.zig, weights.zig or budget.zig is Metal-only in a way that blocks a CUDA backend, tell us. We'd rather split it in #1415 before it lands than have you work around it.

    Part 4 (tool calls). Main may not need it. The template's default tool_call_format emits <tool_call><function=NAME><parameter=K>V</parameter></function></tool_call>, and main's zig/src/server/tool_parse.zig already reads that form. On #1415, with no server change, the tool checks pass 5/5 (auto, required, named, thinking, streamed). If your parser handles a case main's misses, a failing test for that case would be the PR.

    Gates. These are Ash's to set. Here are the terms he has written so far, since they bear on parts 1 and 3:

    Testing. We're staying hands off the CUDA work itself, but we can run your branch on any hardware we have free: an RTX 5090 (sm_120), DGX Spark-class GB10s (sm_121, which you haven't covered yet), and an M5 Ultra for checking that the Metal path is unchanged after your rebase. Point us at a commit and the checks you want run, and we'll post the results here.

  4. BobClawblaw commented on Oct 30, 2026

    @BobClawblaw
    ContributorAuthor

    /atc release

  5. BobClawblaw commented on Oct 31, 2026

    @BobClawblaw
    ContributorAuthor

    /atc claim

  6. BobClawblaw commented on Oct 31, 2026

    @BobClawblaw
    ContributorAuthor

    /atc claim 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions