Serve & MTP Fast-Inference

Serve a fine-tuned GGUF over OpenAI-compatible HTTP, with optional Multi-Token Prediction for lossless 1.4–2.2× speedup on Gemma-4

Serve any fine-tuned GGUF over an OpenAI-compatible HTTP endpoint. For Gemma-4, add MTP to get lossless 1.4–2.2× faster generation — no drafter retraining, one flag.

Diagram

praisonai-train serve

yes

no

📦 model.gguf
fine-tuned

🚀 serve

Gemma-4?

🧠 auto-fetch
MTP drafter

📡 plain serve

💨 OpenAI endpoint
+ speculative decoding

📡 OpenAI endpoint

Quick Start

  1. Serve a trained model

    Point at a GGUF and get an OpenAI-compatible endpoint on 127.0.0.1:8080.

    bash
    pip install "praisonai-train[llm]"
    
    praisonai-train serve --gguf model.gguf
  2. Use it from any OpenAI client

    The endpoint is OpenAI-compatible, so praisonaiagents (and every other OpenAI SDK) talks to it out of the box.

    python
    from praisonaiagents import Agent
    
    agent = Agent(
        instructions="You are a helpful assistant.",
        llm={
            "model": "openai/local",
            "base_url": "http://127.0.0.1:8080/v1",
            "api_key": "not-used",
        },
    )
    agent.start("Explain MTP in one sentence.")
  3. Benchmark and see the MTP win

    --benchmark is a one-shot: it prints tokens-per-second plus draft acceptance for Gemma-4, then exits.

    bash
    praisonai-train serve --gguf gemma4-e4b.gguf --benchmark
  4. Export the GGUF with its MTP drafter

    Pass --mtp-draft when exporting a Gemma-4 model — the stock drafter is fetched and placed next to the GGUF so serve picks it up automatically.

    bash
    praisonai-train export gguf --model-dir lora_model --mtp-draft

How It Works

MTP proposes several tokens with a small drafter, then the fine-tuned model verifies them in one pass — so the output is bitwise identical to plain serving.

Diagram
llama-serverHugging Face Hub_mtp.resolve_drafterpraisonai-train serveUserllama-serverHugging Face Hub_mtp.resolve_drafterpraisonai-train serveUser–gguf gemma4-e4b.ggufis_mtp_supported(model_name)family=gemma-4, size=E4Bfetch_drafter(unsloth/gemma-4-E4B-it-GGUF)MTP/mtp-gemma-4-E4B-it-Q8_0.gguf (~95 MB)–model model.gguf –model-draft mtp.gguf–spec-type draft-mtp –spec-draft-n-max NOpenAI /v1 endpoint on :8080

The drafter is a separate artifact and is never contained in a plain q4_K_M GGUF — that is why the fetch step exists. Verification is done by the fine-tuned target model, so the generation is lossless: identical output, fewer forward passes.

StepWhat happens
Resolve target--gguf or the first non-drafter .gguf under --model-dir
Detect familyBase model name from --base-model, --config, or config.json
Fetch drafterStock MTP GGUF pulled from the Hub for a Gemma-4 target
Launchllama-server starts with the speculative-decoding flags

Configuration Options

Two surfaces: CLI flags on serve, and config-file keys the trainer accepts when you export --mtp-draft.

CLI flags — praisonai-train serve

Provide either --gguf or --model-dir to pick the target.

FlagShortTypeDefaultDescription
--model-dir-dpath—Directory of the trained model — the target GGUF is auto-detected (drafter files are skipped).
--gguf—path—Explicit path to the target GGUF to serve.
--config-cpath—Optional config.yaml for base-model / MTP knobs.
--base-model—str—Base model id used to select the MTP drafter.
--mtp-draft / --no-mtp-draft—boolTrueUse the stock MTP drafter (auto: on when the family supports it).
--spec-draft-n-max—int2Max tokens the MTP drafter proposes per step.
--port—int8080Port for llama-server.
--ngl—int99Number of layers to offload to GPU.
--benchmark—boolFalseRun a one-shot speed benchmark instead of serving.

Config keys — export --mtp-draft

These keys are accepted by the trainer’s config (config.yaml) alongside export.

KeyTypeDefaultDescription
mtp_draftboolFalseFetch and publish the stock MTP drafter alongside the exported GGUF.
mtp_draft_repostrauto (Gemma-4 map)Reserved override for the Hub repo the drafter is fetched from.
mtp_draft_filestrauto (Gemma-4 map)Reserved override for the drafter filename within the repo.
spec_draft_n_maxint2Passed through to llama-server --spec-draft-n-max.

Common Patterns

Serve any GGUF (non-Gemma-4)

Plain serving works for every fine-tuned model. A non-Gemma family falls back to plain serving with a clear message.

bash
praisonai-train serve --gguf qwen-finetune.gguf
text
MTP fast inference isn't available for '<model>' (only the Gemma-4 family). Serving without a drafter.

Serve from a model directory

Point at a directory and the target GGUF is auto-detected (drafter files are skipped).

bash
praisonai-train serve --model-dir lora_model

Benchmark before you ship

--benchmark prints raw tokens/sec and (for Gemma-4) draft acceptance in one line — confirm the MTP win on your box before flipping traffic over.

bash
praisonai-train serve --gguf gemma4-e4b.gguf --benchmark

Talk to it from praisonaiagents

Any Agent that already speaks OpenAI works — point base_url at http://<host>:<port>/v1.

python
from praisonaiagents import Agent

agent = Agent(
    instructions="You are a helpful assistant.",
    llm={
        "model": "openai/local",
        "base_url": "http://127.0.0.1:8080/v1",
        "api_key": "not-used",
    },
)
agent.start("Say hello.")

Supported models

Only Gemma-4 ships a stock MTP drafter. Verified mapping (from _mtp.py):

Base model familyBase repo (Unsloth GGUF)Drafter fileDrafter size (~)
Gemma-4 E2Bunsloth/gemma-4-E2B-it-GGUFMTP/mtp-gemma-4-E2B-it-Q8_0.gguf~40 MB
Gemma-4 E4Bunsloth/gemma-4-E4B-it-GGUFMTP/mtp-gemma-4-E4B-it-Q8_0.gguf~95 MB
Gemma-4 12Bunsloth/gemma-4-12b-it-GGUFMTP/mtp-gemma-4-12b-it-Q8_0.gguf—

The drafter precision is Q8_0 by default; bf16 and f16 variants resolve to BF16 / F16 filenames.

Non-Gemma models (Llama / Qwen / Mistral / Phi / DeepSeek) do not ship MTP drafters. serve --gguf still works on them — just without the speculative-decoding pathway. Do not expect a 1.4× on a Qwen fine-tune.


Field notes


Best Practices

Serve first, benchmark second, ship third

--benchmark catches drafter compatibility and llama.cpp version drift before real traffic hits the endpoint. Run it once on your box, confirm the tok/s and draft-acceptance line, then serve.

Keep MTP opt-in on export

--mtp-draft on export adds a ~95 MB artifact next to your GGUF. Leave it off for size-constrained deploys — you can always fetch the drafter later by serving with --mtp-draft (the default).

Match the drafter's quantization to your compute budget

The default Q8_0 drafter fits comfortably on CPU inference. For edge devices, consider a smaller variant if a matching one is published upstream.

Non-Gemma-4? Plain serve is still useful

Any GGUF from praisonai-train export gguf can be served by this command — MTP is the bonus, not the point. A non-Gemma family falls back to plain serving with a clear message.


Related