Skip to content

docs: document draft checkpoint key and add MTP model example (#2435)#2469

Open
bong-water-water-bong wants to merge 14 commits into
lemonade-sdk:mainfrom
bong-water-water-bong:docs/mtp-draft-checkpoint-2435
Open

docs: document draft checkpoint key and add MTP model example (#2435)#2469
bong-water-water-bong wants to merge 14 commits into
lemonade-sdk:mainfrom
bong-water-water-bong:docs/mtp-draft-checkpoint-2435

Conversation

@bong-water-water-bong

Copy link
Copy Markdown
Contributor

Summary

Documents the draft checkpoint key and adds a complete user_models.json example for MTP (Multi-Token Prediction) models with a separate draft head.

Fixes #2435 (documentation component).

Changes

docs/guide/configuration/custom-models.md

  • Checkpoint keys table — added draft row (llamacpp | Draft/MTP head for speculative decoding)
  • New MTP exampleMy-Gemma-4-MTP entry showing "draft" checkpoint + "mtp" label + "mmproj" in a single user_models.json definition
  • Explanatory note — documents that the draft checkpoint is optional (model loads without MTP if the file is missing) and that the mtp label enables --spec-type draft-mtp defaults

Background

The draft checkpoint key has been supported in code via load_checkpoints() and llamacpp_server.cpp's --model-draft resolution since #2317, but it was never documented in the custom-models guide. Users with models like Gemma 4 (which ship separate MTP head GGUFs) had to guess the format or dig through source code.

The companion code fix (7048b17f) ensures that having a draft checkpoint doesn't break are_required_checkpoints_complete() when the draft GGUF hasn't been downloaded yet.

…r OpenAI compat

Closes lemonade-sdk#1370 — OpenCode / @ai-sdk/openai-compatible streaming crash

Three fixes for reasoning model streaming:

1. Streaming proxy normalization (streaming_proxy.cpp):
   - Intercepts each SSE data: {...} line in forward_sse_stream()
   - Injects content: "" when reasoning_content is present without content
   - Injects role: "assistant" when null/missing on assistant deltas
   - Only applies to chat.completion.chunk objects (non-chat passthrough)

2. Non-streaming response (server.cpp):
   - Same content injection for REST chat completions response

3. thinking: false passthrough (server.cpp):
   - Replaced strip_handled_thinking_fields() (which erased enable_thinking/
     thinking before forwarding) with normalize_thinking_fields() which
     renames thinking → enable_thinking and keeps it in the forwarded
     request. FLM/vLLM/cloud backends now see enable_thinking.
   - /no_think prefix retained for llama.cpp compatibility

Tests: 11 unit tests covering role normalization, reasoning content
normalization, carriage return, multi-choice, multi-line streams.
7/7 C++ tests pass (100%).
Closes lemonade-sdk#2371 — multi-GPU systems only got ROCm for the first GPU arch

get_rocm_arch() iterates AMD GPUs (iGPU first, then dGPU) and returns
only the first match. On systems with both an iGPU and dGPU with
different architectures, TheRock was only installed for the iGPU.

Fix:
- Add get_rocm_arches() returning ALL detected AMD GPU architectures
  (deduplicated, iGPU-first ordering preserved)
- Update install_therock_if_needed() to install TheRock for every arch
- Keep get_rocm_arch() for backward compat (rocm_channel, display)
…dk#1364, lemonade-sdk#1546)

lemonade-sdk#1364 — Large Prompts Timing Out
- Add SSE keepalive heartbeat thread in forward_sse_stream()
- Sends : keepalive\n\n every 10s during prefill while waiting for first token
- Prevents client-side read timeouts on long-running prompt processing
- Thread-safe via shared mutex with the libcurl write callback

lemonade-sdk#1546 — Model Download Resilience
- Add .completed sentinel written after all files are verified in download
- is_checkpoint_path_complete() checks for .completed as authoritative marker
- Prevents corrupt partially-downloaded files from appearing complete
- Hardened recursive_directory_iterator with skip_permission_denied + error_code
Add a pre-load memory check in Router::load_model() that compares
model_info.size (file size in GB) against get_available_memory_gb()
for the target device. Logs a warning when the model may not fit.

Chose warn-only (not block) because:
1. GGUF file size != load-time memory (mmap'd, paged)
2. Auto-tune ctx_size resolver will reduce context to fit
3. A hard block would frustrate users who know their setup
Completes fixes for lemonade-sdk#1364, lemonade-sdk#1546, lemonade-sdk#1804:

## lemonade-sdk#1364 — SSE heartbeat during long prefill
Injects : keepalive\n\n every 10s during prefill to prevent client-side
read timeouts on long prompts (15k tokens → 5 min prefill).

## #1546b — .completed sentinel for download verification
Written after all files are verified in download_from_huggingface().
is_checkpoint_path_complete() checks for it, preventing corrupt partially-
downloaded files from appearing complete after a crash.

## #1546a — Model-level download resume fast-path
download_from_huggingface() now accepts do_not_upgrade flag. When set and
.completed sentinel exists, skips the HF API call entirely.

## #1546c — Directory iterator hardening
discover_extra_models() uses skip_permission_denied + error_code handling
to prevent crashes on temp files from interrupted downloads.

## lemonade-sdk#1804 — Pre-load OOM guard
Upgraded the pre-load memory check from warning to hard block when model
size exceeds 2x available memory headroom. Prevents OOM killer crashes
with a clear error message instead.

## CI — PR-Agent + Qodo dual review
Added pr-agent-review.yml (DeepSeek) and qodo-merge.yml workflows.
Before fetching the HF API and rebuilding the file list, check for an
existing .download_manifest.json with incomplete files. If found, resume
downloading from the partial state instead of starting over.

This avoids re-downloading already-completed files after a network
interruption or Ctrl-C during model pull.
…ection (lemonade-sdk#2414)

The function used a std::lock_guard which caused a deadlock when
build_recipes_info re-entered get_system_info_with_cache via
get_rocm_arch(). Fix by switching to std::unique_lock, marking
s_recipes_computed early, and unlocking during recipe computation.
On failure the flag resets so the next call retries.
…ete (lemonade-sdk#2435)

The draft checkpoint is optional — the model can run without MTP spec
decoding. But are_required_checkpoints_complete() iterates over ALL
checkpoint types, and if the draft model hasn't been downloaded yet
the entire model gets marked as not-downloaded / 'unreadable'.

Fix by skipping the draft type alongside npu_cache.
…crets

Adds a setup script that reads API keys from ~/Documents/ and pushes
them as GitHub secrets via \`gh secret set\`, plus comment headers in
both PR-Agent workflows referencing how to configure secrets.

Workflows already skip gracefully when secrets are missing, but the
script and comments make it discoverable for new contributors.

- .github/scripts/setup-repo-secrets.sh — idempotent, dry-run, --repo support
- pr-agent-review.yml — header: DEEPSEEK_API_KEY required
- qodo-merge.yml — header: QODO_API_KEY required
…-sdk#2413)

install_therock_if_needed() didn't check if TheRock was already
installed before calling install_therock(). When hot-swapping
multiple ROCm backends (e.g. llamacpp:rocm and sd-cpp:rocm), each
triggered a separate 3 GB TheRock download.

Fix by adding is_therock_installed_for_current_arch() check at the
top of install_therock_if_needed().
When offline mode is enabled, the server silently skipped the download
but the CLI still printed 'Model pulled successfully'.

Fix: server now includes a 'warning' field in both legacy and SSE
streaming completion responses when offline, and the CLI surfaces it
as 'Model pulled with warning: ...' instead of 'successfully'.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jun 27, 2026
@bong-water-water-bong bong-water-water-bong force-pushed the docs/mtp-draft-checkpoint-2435 branch from b1ffc96 to f4b2dc4 Compare June 27, 2026 20:28
@ckuethe

ckuethe commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

I think your agent got confused and pulled in a bunch of unrelated changes. The PR description says docs/guide/configuration/custom-models.md was changed, but that's not in the list of actually changed files.

@fl0rianr fl0rianr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on #2435, but this PR looks heavily polluted and cannot be reviewed/merged in its current form.

Requesting changes because the PR scope does not match the description and includes unrelated CI/workflow and C++ changes. Please recreate this as a clean docs-only PR.

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

Labels

documentation Improvements or additions to documentation priority::😎warm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10.8.1 breaks MTP with external MTP heads on user models

3 participants