Skip to content

Add lemon-mlx-engine as a wrapped-server backend (rebase of #2010)#2472

Open
bong-water-water-bong wants to merge 58 commits into
lemonade-sdk:mainfrom
bong-water-water-bong:feat/mlx-engine-rebase
Open

Add lemon-mlx-engine as a wrapped-server backend (rebase of #2010)#2472
bong-water-water-bong wants to merge 58 commits into
lemonade-sdk:mainfrom
bong-water-water-bong:feat/mlx-engine-rebase

Conversation

@bong-water-water-bong

Copy link
Copy Markdown
Contributor

Summary

Rebase of #2010 (which replaced #1717) onto current main. Wires lemon-mlx-engine as the lemon-mlx wrapped-server recipe.

The upstream engine exposes an OpenAI-compatible HTTP API, so this stays within the existing WrappedServer abstraction.

Changes vs #2010

  • Rebased onto main (2026-06-28) — 11 merge conflicts resolved
  • forward_streaming_request updated for new TelemetryCallback parameter
  • populate_static_max_context_windowpopulate_model_metadata rename
  • Backend pins bumped: b1034-stable → b1045-stable (latest release, 2026-06-28)
  • Kept moonshine backend alongside lemon-mlx (both coexist)

Core backend

  • MlxServer (src/cpp/{include,server}/lemon/backends/mlx_server.{h,cpp}) — /v1/chat/completions, /v1/completions, streaming; responses() returns UnsupportedOperationException
  • router.cpp: instantiates MlxServer for lemon-mlx recipes
  • model_types.h, runtime_config.cpp: registers lemon-mlx as a selectable backend

Resolved review items (from #2010 @fl0rianr, @bitgamma, Qodo)

Item Fix
BLOCKING: completions_streaming True but no streaming /v1/completions completions_streaming = False in capabilities.py
BLOCKING: forward_streaming_request unsafe for /v1/completions Early throw guard in MlxServer::forward_streaming_request
P2: CPU support matrix overstated Split system_info.cpp: Linux → x86_64 only; macOS → arm64 only
P2: Unreachable *-preview pins Removed
P2: README CPU row ambiguous Explicit: "x86_64 on Linux; Apple Silicon (arm64) on macOS"
P2: Custom tokenize_quoted_args Replaced with std::istringstream

Performance (b1045-stable, gfx1151)

Model tok/s
Qwen3.6-35B-A3B-MTP q4 63 decode TPS
gfx1201 (R9700) 79 decode TPS (+15% graph replay)

Closes #1642


🤖 Generated with Claude Code

bong-water-water-bong and others added 30 commits April 23, 2026 13:47
Wires lemon-mlx-engine (https://github.com/lemonade-sdk/lemon-mlx-engine)
as a new recipe/backend pair on top of the existing WrappedServer
abstraction. The engine is a subprocess that exposes the OpenAI
chat/completions API, so this PR mostly adds registration glue:

- `MlxServer` class (src/cpp/{include,server}/.../mlx_server.{h,cpp})
  forwarding chat/completions + completions, unsupported for responses.
  Auto-download model refs go directly to the subprocess as positional
  args (MLX resolves HF repo-ids itself), with ROCm builds picking the
  correct per-arch release asset via `SystemInfo::get_rocm_arch()`.
- Registered in `try_get_spec_for_recipe`, `backend_versions.json`
  (pinned at `b1013-stable` for metal/rocm/cpu), `runtime_config`
  (s_backend_names + s_selectable_backends), `model_types`
  (`get_device_type_from_recipe` → GPU default, CPU override in load()),
  and the RECIPE_DEFS support matrix in `system_info.cpp` (Apple
  Silicon metal, Linux AMD rocm on gfx1150/1151/110X/120X, CPU fallback).
- Two sample entries in `server_models.json`
  (`Qwen3-0.6B-MLX` suggested, `Qwen3-4B-MLX` opt-in) plus capabilities
  catalog + `--mlx-engine` backend flag in the test harness so
  `python test/server_llm.py --wrapped-server mlx-engine --backend cpu`
  is a valid invocation.

Smoke: `GET /api/v1/system-info` on Linux gfx1151 reports mlx-engine
with cpu=installable and rocm=installable pointing at
`mlx-engine-b1013-stable-ubuntu-rocm-stable-gfx1151-x64.zip`; metal is
correctly flagged unsupported on Linux.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Geramy asked to rebrand the backend identifier from `mlx-engine` to
`lemon-mlx` — "sounds more market friendly and cool." Applied across
the wrapped-server wiring, system-info metadata, recipe options, and
test harness utilities. Release-asset filenames keep the existing
`mlx-engine-<version>-*.zip` prefix because that is what the
lemonade-sdk/lemon-mlx-engine CI currently produces; backend-name
rename is independent of artifact naming.

Changes:
- `RECIPE_DEFS` entries: `"mlx-engine"` → `"lemon-mlx"` for metal,
  rocm, and cpu variants.
- `s_backend_names` and `s_selectable_backends` in runtime_config.
- `backend_versions.json` key: `mlx-engine` → `lemon-mlx`.
- `server_models.json` recipe strings.
- `WrappedServer` constructor tag: `"lemon-mlx"`.
- `RecipeOptions` keys: `mlx_engine_backend` → `lemon_mlx_backend`,
  `mlx_engine_args` → `lemon_mlx_args` — unmerged PR so no migration
  concern.
- test/utils/capabilities.py + server_base.py: identifier + recipe
  key matches.
- model_types::get_device_type_from_recipe dispatch string.
- backend_utils::try_get_spec_for_recipe dispatch string.
- Log-line and error-message strings for operator readability.

Verification:
- `cmake --build --preset default --target lemond` clean (GCC,
  gfx1151 ROCm-stable userspace).
- `./build/lemond --version` → 10.2.0.

Version bump from `b1013-stable` to the new stable+preview releases
is left as a follow-up once Geramy's CI completes (he flagged it
would finish ~30 min after the original ping).
Geramy landed b1005-preview on lemon-mlx-engine 2026-04-23 16:54Z.
Wire it alongside the existing stable pin (b1013-stable) following
the same 'rocm' / 'rocm-preview' pattern llamacpp already uses in
this file. Users on the preview channel pick up newer engine builds
at kernel-level risk; stable users keep the current pinned behaviour.

No runtime-code change needed — server_info.cpp consults this file
by key; adding '*-preview' keys is transparent to it.
# Conflicts:
#	CMakeLists.txt
#	src/app/src/renderer/recipes/recipeOptionsConfig.ts
#	src/cpp/server/recipe_options.cpp
#	src/cpp/server/router.cpp
#	src/cpp/server/runtime_config.cpp
#	src/cpp/server/system_info.cpp
The preview pins were stale at b1005-preview while stable was at
b1013-stable. Upstream lemon-mlx-engine cuts paired stable/preview tags
at every build, so a preview pin lagging stable by 8 builds was
inconsistent with the release scheme.
The Ubuntu CPU asset ships libopenblas.so.0, liblapacke.so.3, and
libgfortran.so.5 next to the server binary, but the binary has no
DT_RUNPATH, so without LD_LIBRARY_PATH ld.so falls back to system
search and exits 127. The LD_LIBRARY_PATH plumbing already existed
but was gated to the rocm variant only; the cpu variant has the same
bundling pattern. Extend the bundle-dir lookup to all Linux variants
(metal is macOS-only and can't reach this block).

Fixes the "Test .deb - lemon-mlx" CI job, which loaded a Qwen3-0.6B
MLX model and saw the wrapped server die with:
  ./bin/lemon-mlx/cpu/server: error while loading shared libraries:
    libopenblas.so.0: cannot open shared object file
  lemon-mlx process has terminated with exit code: 127

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Upstream lemon-mlx URL-joins the model argument onto
  huggingface.co/api/models/
so an absolute filesystem path produces a 404 like

  huggingface.co/api/models//home/.../hf-cache/hub/models--mlx-community--Qwen3-0.6B-4bit/revision/main

Swap the priority: pass model_info.checkpoint() (HF repo-id) first;
fall back to resolved_path() only when checkpoint is empty (rare
custom-model recipes). HF_HOME is honored by the lemon-mlx process,
so a previously downloaded model is still resolved from the local
cache without an additional download.

Fixes the second CI failure on "Test .deb - lemon-mlx" (after the
previous LD_LIBRARY_PATH fix in d091d88 closed the libopenblas exit
127). The chat-completions test was loading Qwen3-0.6B-MLX and seeing
the wrapped server die with exit code 1 + a 404 on a malformed HF
API URL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lemon-mlx-engine ships no Linux arm64 asset; only ubuntu-cpu-x64.zip
exists for Linux. Without this guard, get_install_params() would
silently download and attempt to run an x64 binary on a Linux arm64
host. Fail fast with a clear message instead.

Closes Codex P2 review comment on mlx_server.cpp.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
lemonade-sdk#1975)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* custom collection models possible
- besides new model also new collections
- lean UI with current design
- can be exported and imported

* polish custom collection UI

- slightly adapt readme.md
- Move the custom collection utility test under test/app

* fix render bug for normal model setup

- deleted old files and adapted for npm test

* adapted to fitting it properly into new omni-router concept pr1842

* 2nd stage adapting towards new concept

* cleaned UI and finilize omni model integration

* visibility and selection and UI fixes
* Rebrand OmniRouter to Lemonade Omni

* Refine documentation

* docs: relocate custom Omni Model sections and align example LLM

- Move "Custom Omni Models" how-to from docs/dev/lemonade-omni.md to
  docs/guide/configuration/custom-models.md as a sibling of the CLI
  "Register an omni collection" subsection. lemonade-omni.md now links
  there.
- Move "Testing custom Omni Models" (automated + manual smoke test)
  from lemonade-omni.md to docs/dev/app.md, adjacent to the existing
  "Testing the Rust host" section.
- examples/lemonade_tools.py: default LLM_MODEL → Qwen3.5-4B-MTP-GGUF
  to match the LMN-Lite-Omni-5.5B LLM component (the comment already
  said "match LMN-Lite-Omni-5.5B").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Rename omni model prefix LMN → LMX (Lemonade Mix)

Switch to the LMX-Omni-<xB>-<class> naming pattern:
- LMN-Halo-Omni-52B → LMX-Omni-52B-Halo
- LMN-Lite-Omni-5.5B → LMX-Omni-5.5B-Lite

LMX stands for "Lemonade Mix". Updated the docs decoder ring,
example script references, model_sizes.py usage example, and the
server_models.json registry keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs/test: post-rebrand consistency sweep

- Fix menu paths: the desktop app's menu bar is File/View/Help, not
  "Lemonade". Updated docs/guide/configuration/custom-models.md and
  docs/dev/app.md to say "File > New Omni Model > Manually", and
  examples/lemonade_tools.py to point to the actual download path
  (Model Manager > Lemonade Omni > LMX-Omni-5.5B-Lite > Download).
- Tighten "desktop apps model list" → "Lemonade desktop app's
  Model Manager" in docs/dev/lemonade-omni.md.
- Update the customCollections test fixture from the legacy
  "Lite Collection" name to the current "LMX-Omni-5.5B-Lite" so the
  built-in-template assertion reflects today's primary name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* model_sizes: forward HF_TOKEN on range fetches

fetch_repo() already attached the Authorization header from HF_TOKEN,
but fetch_range() did not, so the safetensors/GGUF header-parsing
fallback path silently 401'd against gated/private repos even when the
user had set HF_TOKEN. Result: param counts downgraded to unknown when
the HF API didn't already report gguf.total / safetensors.total.

Extract an hf_headers() helper and use it from both call sites so the
auth concern lives in one place and future HF fetches inherit it.

Reported in PR lemonade-sdk#1973 review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Rename desktop category label "Lemonade Omni" → "Lemonade"

Updates both the Model Manager category label and the recipe display
name for collection.omni, plus the two doc mentions of the category.
"Lemonade" alone reads cleaner now that Omni Models are the only
content under this category.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: missing file size in custom models

* Lock the models cache before modifying
bong-water-water-bong and others added 23 commits May 24, 2026 21:49
…view pins

Blockers:
- test/utils/capabilities.py: set completions_streaming=False for lemon-mlx;
  lemon-mlx-engine does not implement SSE streaming on /v1/completions
- mlx_server.cpp: guard forward_streaming_request against /v1/completions
  direct calls that bypass the router capability check

P2 (fl0rianr 2026-05-22):
- system_info.cpp: split lemon-mlx cpu entry — Linux x86_64 only, macOS arm64
  only; matches installer asset reality and get_install_params() guards
- backend_versions.json: remove unreachable *-preview pins (metal/rocm/cpu);
  no config path selects lemon-mlx:*-preview today
- README.md: make CPU row explicit: Linux x86_64 / macOS arm64 (beta)
- mlx_server.cpp: replace custom tokenize_quoted_args with std::istringstream,
  matching the pattern in fastflowlm_server.cpp and vllm_server.cpp
… error for streaming completions

- resolve_mlx_backend: auto-select rocm only for supported GPU families
  (gfx1150, gfx1151, gfx110X, gfx120X), fall back to cpu for RDNA2/gfx103X
- prepare_request: always erase max_completion_tokens after handling it
- forward_streaming_request: write SSE error + sink.done() instead of throw

Co-authored-by: multica-agent <github@multica.ai>
…Intel Mac guard

- Rename MlxServer::SPEC to spec (snake_case convention)
- Move namespace fs and using namespace lemon::utils inside namespace block
- Alphabetize include blocks in mlx_server.cpp
- Add architecture guard for Intel macOS (arm64-only for MLX Metal/CPU)

Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
…DE_MOCK_HARDWARE guard

1. model_manager.cpp: Move fs::file_size() calls outside models_cache_mutex_
   in update_model_in_cache(). Copy resolved paths under lock, release, then
   calculate size. Re-lock briefly to write the rounded size if the cache
   entry is still valid.

2. system_info.cpp: Add LEMONADE_MOCK_HARDWARE=1 env var guard to
   get_system_info_with_cache(). Mock hardware_info.json is now only loaded
   when the env var is explicitly set, preventing unintended mock loading.

3. test_flm_status.py: Set LEMONADE_MOCK_HARDWARE=1 in the environment when
   starting the server with mock hardware.

Co-authored-by: multica-agent <github@multica.ai>
…VRAM > less)

Prior behavior: get_rocm_arch() returned the first available AMD GPU,
which is always the iGPU (added first in the devices array). On systems
with a gfx1036 iGPU + gfx1201 dGPU, this returned 'gfx1036' — causing
all ROCm backends to download binaries for the wrong architecture,
install TheRock for the wrong GPU, and silently fall back to CPU.

New behavior: iterates ALL AMD GPUs and returns the highest-scoring
architecture using a VRAM-based ranking:
- Primary factor: VRAM capacity (more VRAM = better for LLM inference)
- Tiebreaker: dGPU bonus (GPUs with >= 4 GB VRAM are likely discrete)

This mirrors get_cuda_arch() which also iterates all NVIDIA GPUs and
picks the highest compute capability.

Fixes: lemonade-sdk#2296, lemonade-sdk#2319 (GPU selection), helps lemonade-sdk#1787, lemonade-sdk#1991, lemonade-sdk#2002, lemonade-sdk#2371
… on hybrid AMD+NVIDIA laptops

On systems with both AMD iGPU and NVIDIA dGPU, vLLM's platform detection
finds both 'cuda' and 'rocm' plugins and refuses to start with:
  RuntimeError: Only one platform plugin can be activated, but got: ['cuda', 'rocm']

Set VLLM_TARGET_DEVICE=rocm in the vLLM subprocess environment so the
ROCm launcher activates only the ROCm platform plugin and skips the
CUDA/NVML probe.

Closes lemonade-sdk#1863

Co-Authored-By: Claude <noreply@anthropic.com>
…memory crash

On hybrid AMD+NVIDIA systems, llama.cpp's ggml memory budgeter counts
both GPUs' VRAM pools, then tries to allocate the full model on the ROCm
device — exceeding available memory and failing with:
  ggml_backend_cuda_buffer_type_alloc_buffer: cudaMalloc failed: out of memory

Setting CUDA_VISIBLE_DEVICES="" hides the NVIDIA GPU from ggml's memory
calculation while the ROCm backend discovers AMD GPUs through ROCr directly.
User-confirmed workaround on Strix Halo + RTX 3090 Ti.

Closes lemonade-sdk#2074

Co-Authored-By: Claude <noreply@anthropic.com>
…nds, memory guard

Three-layer defense against RyzenAI/NPU inference hangs on memory-constrained
systems (e.g. Qwen3-14B-Hybrid on 24 GB RAM):

B1+B2: Apply default_timeout_seconds_ (300s) fallback to HttpClient::post()
and post_stream(), matching the existing safety net in get(). Previously
post() passed timeout_seconds=0 directly to CURLOPT_TIMEOUT, meaning 0=infinite.
A hung backend would block the HTTP worker thread forever, freezing the UI.

C2: Start the backend watchdog in every backend's load() method (llama.cpp,
vLLM, RyzenAI, Whisper, Moonshine, SD, Kokoro). Only FastFlowLM had it before.
All backends already call stop_backend_watchdog() in unload(). The watchdog
probes /health and resets a hung backend after the grace period (default 90s).

A2: Pre-reject NPU model loads when auto-tune can only reserve the fallback
ctx_size (AUTO_CTX_FALLBACK=4096) and the model exceeds 10 GB. On
memory-constrained systems, the NPU driver's runtime overhead pushes past
the limit during first inference, causing the backend to hang. Rejecting
early gives a clear error instead of a silent hang.

Closes lemonade-sdk#1151

Co-Authored-By: Claude <noreply@anthropic.com>
… cooldown, TDR warning

Three fixes for Vulkan backend hangs on Windows with AMD/Intel iGPUs (lemonade-sdk#2000):

1. Default --no-flash-attn on Windows+Vulkan. Flash attention on Vulkan
   Windows has caused reproducible hangs since llama.cpp b7064 (ggml#17297).
   Users can opt back in with --flash-attn in llamacpp_args.

2. 2-second GPU driver cooldown in ProcessManager::terminate() on Windows,
   matching the existing Linux behavior. Without this, orphaned Vulkan
   command buffers leave the GPU pegged at 90-100% after process
   termination (AMD Adrenalin known issue RN-RAD-WIN-22-11-1).

3. Log warning recommending TdrDelay=30 on Windows iGPU systems. The
   default 2-second TDR timeout is too short for LLM compute — a hung
   dispatch triggers VK_ERROR_DEVICE_LOST and a utilization stall.

Additional upstream fixes needed in llama.cpp/ggml for complete coverage:
- nodes_per_submit=1 on UMA devices (PR#24872)
- Device-lost recovery (destroy-recreate-reload)
- vkDeviceWaitIdle before vkDestroyDevice

References: ggml#21724, ggml#17297, ggml#14105, mpv#16334

Closes lemonade-sdk#2000

Co-Authored-By: Claude <noreply@anthropic.com>
…backends

FastFlowLM had a hardcoded 5-minute timeout (max_attempts=300) that
was not configurable. This prevented loading large models like
GPT-OSS 120B that need more than 5 minutes for GPU offload.

All other backends (llama.cpp, whisper, moonshine, ryzenai, sd, kokoro)
used wait_for_ready(endpoint) with the hardcoded 600s default instead
of passing timeout_seconds=0 to use the configurable global_timeout.

Changes:
- fastflowlm_server.cpp: read HttpClient::get_default_timeout() instead
  of hardcoded 300 — respects config.json global_timeout (default 600s)
- llamacpp/whisper/moonshine/ryzenai/sd/kokoro server files: pass
  timeout_seconds=0 to wait_for_ready() to use global_timeout
- vllm already used HttpClient::get_default_timeout() — unchanged

Users can set global_timeout in config.json or via
POST /api/v1/params {"global_timeout": 1200} for large models.

Closes lemonade-sdk#674

Co-Authored-By: Claude <noreply@anthropic.com>
- pr-agent-review.yml: DeepSeek-powered review on PR open/sync/reopen and @mention comments
- qodo-merge.yml: Qodo Merge (qodo-ai/pr-agent) review on PR open/sync/reopen
- Both gated on DEEPSEEK_API_KEY / QODO_API_KEY secrets being set

Co-Authored-By: Claude <noreply@anthropic.com>
…nade-sdk#1003)

Layer A — metrics_linux.cpp: Skip NPU sensor polling on kernels < 6.19.7.
The amdxdna driver has known deadlock bugs (CVE-2026-23295) where sensor
IOCTLs race with PM runtime suspend/resume, causing complete system freezes
on Strix Halo. On unsafe kernels, get_npu_utilization() returns -1
immediately and logs a one-time warning advising a kernel upgrade.

Layer B — model_manager.cpp + http_client: Cap download bandwidth when the
total download size exceeds 50% of available system memory. On UMA
architectures, download page-cache competes with NPU/GPU DMA buffers for
the same RAM pool. A 70 GB model download can flood the page cache and
starve the NPU driver, triggering OOM kills or system freezes. When
memory is tight, downloads are throttled to ~50 MB/s via
CURLOPT_MAX_RECV_SPEED_LARGE.

Also adds max_recv_speed_bytes to DownloadOptions in http_client.h.

Closes lemonade-sdk#1003

Co-Authored-By: Claude <noreply@anthropic.com>
…k#1792)

post_stream() was applying default_timeout_seconds_ (300s/600s) when
timeout_seconds=0 was passed. But the streaming call chain passes 0
meaning 'infinite timeout' (documented at wrapped_server.cpp:763).

This caused long-running ROCm inference to fail at exactly the default
timeout mark with 'CURL error: Timeout was reached', which the UI
renders as 'Error: No content received from stream'.

Fix: in post_stream(), pass 0L to CURLOPT_TIMEOUT when timeout_seconds
is 0, which libcurl interprets as infinite. Callers who want a finite
timeout should pass a positive value.

Closes lemonade-sdk#1792

Co-Authored-By: Claude <noreply@anthropic.com>
…de-sdk#2180)

Two changes:

1. Reorder RECIPE_DEFS to prefer ROCm over Vulkan on Linux for AMD GPUs.
On systems where both backends are available (HSA runtime + supported GPU
arch), ROCm is now preferred. This avoids the Linux GPU scheduler timeout
entirely, since ROCm compute submissions are not subject to the 2s
RADV/amdgpu scheduler timeout. Vulkan remains as fallback for unsupported
GPUs.

2. Cap Vulkan context size at 65536 on Linux. The amdgpu kernel scheduler
has a ~2s timeout per compute submission (same as Windows TDR). Long
prompt processing (e.g. 262K context) produces submissions that exceed
this, causing VK_ERROR_DEVICE_LOST and a crash with the RADV message
'The CS has been cancelled because the context is lost.'

Closes lemonade-sdk#2180

Co-Authored-By: Claude <noreply@anthropic.com>
Extend max_loaded_models to accept a JSON object with per-device caps
alongside the existing integer format. When an object is provided, the
router enforces per-hardware limits (cpu/gpu/npu) before the per-type
LRU check, so users on heterogeneous systems like Strix Halo can express
limits such as '1 GPU model, 1 NPU model, 2 CPU models'.

Config format (backward compatible):
  Integer:  { "max_loaded_models": 2 }
  Object:   { "max_loaded_models": { "gpu": 1, "npu": 1, "total": 3 } }

Omitted device keys default to unlimited (-1).

Co-Authored-By: Claude <noreply@anthropic.com>
…sdk#2451)

GLM-4.5 GGUF files embed MTP layers (nextn_predict_layers > 0), so the
GGUF capability scanner sets caps.mtp=true, which causes lemonade to
enable speculative decoding (--spec-type draft-mtp).

However, llama.cpp's glm4-moe.cpp graph builder asserts when constructing
the draft model context because the GGUF was not converted with the
multimodal metadata that the graph builder expects:

  glm4-moe.cpp:149: This GGUF does not support multimodal. Please reconvert it.

Fix: strip the 'mtp' label for models whose GGUF architecture contains
'glm4' after capability labels are applied. This is a surgical workaround
until upstream llama.cpp fixes the GLM-4 MoE draft context construction.

Co-Authored-By: Claude <noreply@anthropic.com>
Without these dpkg refuses to overwrite files owned by the other
package when upgrading between lemonade-server and
lemonade-server-minimal, which both ship /usr/local/bin/lemonade-router
and other shared files.

Closes lemonade-sdk#677

Co-Authored-By: Claude <noreply@anthropic.com>
Replay feat/mlx-engine-backend onto fix/rocm-best-gpu (current main).
Resolved conflicts across:
- CMakeLists.txt, model_types.h, backend_utils.cpp, runtime_config.cpp
- recipe_options.cpp, model_manager.cpp, system_info.cpp
- recipeOptions.ts, recipeOptionsConfig.ts (UI)
- README.md, CI workflow, test file

All conflicts resolved by keeping both moonshine and lemon-mlx entries,
HEAD's pinned-saveOptions in UI config, system llamacpp backend row,
and our 11 prior fixes throughout.
…name populate_model_metadata, bump to b1045-stable

- forward_streaming_request now takes TelemetryCallback (6th param)
- populate_static_max_context_window was renamed to populate_model_metadata
- Remove stray brace from merge in runtime_config.cpp
- Bump lemon-mlx backend pins: b1034-stable → b1045-stable
@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.

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

Labels

enhancement New feature or request priority::😎warm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] MLX Engine ROCm backend — 83% faster than Vulkan on Strix Halo

4 participants