Files
elizaos--eliza/plugins/plugin-local-inference/docs/gemma4-cutover-plan.md
T
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

11 KiB
Raw Blame History

Gemma 4 cutover + multi-backend libelizainference — living plan

Status doc for the Gemma 4 cutover campaign. Supersedes the research issue #8794 (Gemma is real + shipped; the open questions there are answered below). Continuously updated as milestones land.

Goal

Cut eliza-1 over from the Qwen3.5/3.6 backbone to Gemma 4 entirely (remove Qwen), and make every platform run the fastest in-process backend behind one FFI pipe (libelizainference):

Backend Where §11 status
llama.cpp everywhere (CPU / CUDA / Vulkan-Mali-Adreno / Metal) owned pipe (today)
LiteRT-LM (compiled-in) Android NPU (Tensor / Qualcomm QNN / MediaTek NeuroPilot), opt. desktop/iOS GPU owned pipe
CoreML / MLX (compiled-in) Apple (mac first, iOS later) owned pipe
AICore / Apple Foundation opportunistic fast-path external (not owned)

§11 ("single on-device runtime") is reinterpreted from "llama.cpp-only" to "one managed library, one pipe, no sidecar/subprocess/TCP." LiteRT-LM and MLX are embeddable in-process C++ libraries → linked into libelizainference, exposing the same FFI streaming symbols FfiStreamingRunner already drives. AICore is an out-of-process Android system service (Binder IPC) → it stays an opportunistic adapter like apple-foundation.ts, never the owned backend.

Gemma 4 — validated facts (2026)

Shipped 2026-04-02 (MTP drafters 04-16, 12B Unified 06-03).

  • Sizes: E2B (~2.3B eff / 5.1B w/ embeddings), E4B (~4.5B / 8B), 12B Unified (11.95B dense, encoder-free, 256K ctx, 262,144 vocab), 31B dense, 26B-A4B (MoE, 4B active). E2B ≈ 1.3 GB Q4, 23 GB RAM → mobile tier.
  • Architecture: dense; alternating local sliding-window (512/1024) + global full-attention; dual RoPE; Per-Layer Embeddings (PLE); shared KV cache (last N layers reuse earlier KV). No SSM/Gated-DeltaNet. Dual head dims (global_head_dim + SWA head_dim).
  • MTP: official separate drafter models (speculative decode ~3×, no quality loss). Our catalog's drafterFile? already supports separate-drafter MTP.
  • Modalities: image + audio (USM conformer) + video.
  • NPU fit: dense graphs are NPU-delegate-friendly; LiteRT-LM ships pre-converted Gemma 4 .litertlm bundles. Qwen3.5-hybrid is hostile to NPU delegates — the strongest technical reason to cut over.
  • Our llama.cpp fork already speaks Gemma 4: LLM_ARCH_GEMMA4 + gemma4.cpp / gemma4a.cpp (audio) / gemma4v.cpp (vision) + converter (text/MoE/vision/ audio). It already implements SWA (LLAMA_SWA_TYPE_STANDARD), shared KV (n_kv_shared_layersn_layer_kv_from_start reuse cb), PLE (per_layer_tok_embd), and interleaved-SWA KV (llama_kv_cache_iswa).

RAM / performance: llama.cpp is not optimal for Gemma out of the box

Gemma 4 is notorious for RAM blow-up in stock llama.cpp. Root causes + our levers (several are config, not new kernels — "Gemma already does a lot of this"):

  1. KV-cache layout (the ~40% fix) — landed upstream ~2026-04-05 (align KV memory layout to Gemma's MHA/grouping). Our merge-base is 2026-05-14, so we likely already have it; the M1 sync to upstream master confirms + grabs the rest.
  2. ctx-checkpoints accumulation (#21690) — Gemma-only: server KV checkpoints grow unbounded (64 GB filled in 45 × 16K-prompt). Fix: bound ctx-checkpoints (1/0) + -np 1 in our fused defaults. Pure config.
  3. Windowed SWA KV (swa_full=false)llama_kv_cache_iswa already sizes SWA layers to n_swa (512/1024) + n_ubatch when swa_full=false. Most layers are SWA, so this is the dominant KV saving. Default swa_full=false (it's already plumbed through capacitor-llama/types.ts + the iOS shim).
  4. PLE memoryper_layer_tok_embd is {n_embd_per_layer·n_layer, n_vocab} (~2.8B params for E2B). With mmap ON the OS pages it from disk (≈ LiteRT's "mmap embeddings, keep on disk until needed"). Never force --no-mmap for Gemma; on GPU backends, pin PLE to CPU/mmap rather than copying it to VRAM. (Watch Vulkan #18317: Vulkan can't run mmap=0.)
  5. Prefix-KV reuse caveat (#21468) — Gemma's shared-KV layers log "cache reuse not supported" even with -fa --swa-full. So prefix reuse is partial on shared-KV layers — better than Qwen3.5 (which can't at all) but not free. Our stream_reset_keep work must account for this.

Leverage Google's C++ work, don't reinvent: LiteRT-LM already does PLE-mmap + windowed-SWA + NPU optimally → use it as the in-process backend on capable hardware. For llama.cpp, absorb upstream Gemma memory PRs and set Gemma-aware defaults rather than porting our Qwen kernels blindly.

Where our kernels still add value (M6), re-scoped:

  • TurboQuant low-precision weight quant — orthogonal to KV; applies to the dense FFN/attention weights. Keep.
  • QJL/PolarQuant KV quant — now applied on top of the windowed SWA KV + the global-attention KV (where 256K context still hurts). Re-parameterize from uniform head_dim=128 to Gemma's dual dims (global ~256 + SWA). Validate it still wins after SWA+shared-KV already shrank the cache.
  • Re-run the §8 8/8 kernel verify matrix per buildable backend for the new geometry.

Frozen contracts re-opened (owner-approved 2026-06-22)

  1. Training base lock (model_registry.py, training/AGENTS.md) — Qwen → Gemma 4.
  2. tokenizerFamily "qwen35"→"gemma4"; vocab 248,320 → 262,144 (memory_calc.py).
  3. KV geometry + kernels — head_dim 128 uniform → Gemma dual dims.
  4. Same-file MTP NextN head → Gemma separate drafter GGUF.
  5. EOT <|im_end|><end_of_turn> (3 scorer files).
  6. Abliteration Gated-DeltaNet surgery → dense surgery.
  7. native/AGENTS.md §11 reinterpreted (single lib + single pipe).

eliza-1 v1 is base-not-fine-tuned (releaseState=base-v1) → v1 cutover is swap base + re-optimize, not a retraining run.

Owner directives (2026-06-22)

  • Hard cutover, remove Qwen entirely. Not shipped, no downloaders → no staging.
  • Local stack is ONLY eliza-1 (max-optimized Gemma). No generic single-GGUF engine path, no arbitrary-model selection — remove that machinery (closes #8808; M9). Cloud handles anything not local eliza-1.
  • HF downloads proxy through Eliza Cloud — the cloud holds the HF token and streams files; no HF keys on local/desktop/mobile, no local token UI (re-scopes #8807; M10).
  • HF elizaos/eliza-1 hard cutover to Gemma bundles; purge legacy tiers (0_6b/0_8b/1_7b) (M8).
  • Max-optimize per platform: fastest in-process backend behind one FFI (llama.cpp default; LiteRT NPU on Android; CoreML/MLX on Apple); TurboQuant weight-quant + MTP + Gemma-native SWA/shared-KV/PLE + stock KV; QJL/Polar deprioritized (Gemma KV already minimal).
  • Related issues: #8808 closed (superseded); #8807 + #8809 kept, addressed in M10 (install cloud-proxy + integrity; memory LRU/dynamic-fit/bench).

Milestones (PR per milestone → develop)

  • M1 — llama.cpp upstream sync + PR absorption. Merge ggml-org/master (602 commits ahead of our base; we are 867 ahead with kernels/voice) into the fork; review + absorb all relevant Gemma/MTP/LiteRT/CoreML/AICore/KV/quant PRs (incl. open #21587 Gemma4 BPE SIGSEGV, #24590 Gemma4Assistant memory-fit, #21690 ctx-checkpoints, #21468 cache-reuse). Build + verify Gemma 4 E2B/E4B text+vision+audio+MTP on CPU/CUDA.
  • M2 — Code cutover Qwen→Gemma (registry, catalog/types, memory_calc, EOT, abliterate, AGENTS; remove Qwen; tier map E2B/E4B/12B/31B(/26B-A4B); Gemma-aware runtime defaults: swa_full=false, bounded ctx-checkpoints, mmap-on/PLE-on-CPU).
  • M3 — Multi-backend FFI seam (backend abstraction + backend-selector). Done + verified on Linux. src/llm-backend.h (the LlmBackendSession / LlmBackendFactory interfaces + the llm_backend_context_bundle_dir accessor), src/llm-backend-selector.cpp (registry + env/rank selection, inert-by-default), and the non-invasive eliza_inference_llm_stream_* dispatch (one backend branch inserted above each existing llama.cpp/MTP branch). Compiles + links into the default fused libelizainference.so with the FFI pipe intact and the seam inert (no alternate backend registered → byte-for-byte the prior llama.cpp path). Design: docs/multi-backend-ffi-seam.md.
  • M4 — LiteRT-LM in-process backend (Android NPU delegate ladder). 🧩 Scaffolded, gated -DELIZA_ENABLE_LITERT (OFF default). src/backends/litert-backend.{h,cpp}: full LlmBackendSession/factory against the researched LiteRT-LM C++ API (Engine/Session, NPU→GPU→CPU ladder, text/*.litertlm probe) behind the gate; a no-SDK stub when OFF. CMake adds the source + SDK include/link knobs (ELIZA_LITERT_SDK_DIR/ELIZA_LITERT_LIBS) when enabled. Every hardware assumption tagged DEVICE-VERIFY; needs a Pixel/NPU device + the LiteRT-LM SDK to build + validate.
  • M5 — CoreML/MLX in-process backend (mac first, iOS later). 🧩 Scaffolded, gated -DELIZA_ENABLE_MLX + __APPLE__ (OFF default; FATALs on a non-Apple host). src/backends/mlx-coreml-backend.{h,mm}: MLX-primary (mlx-c decode graph) + CoreML-alternate (stateful MLState KV) sessions behind the gate; a no-SDK stub when OFF. CMake adds the .mm + MLX/CoreML/Metal link knobs when enabled. Tagged DEVICE-VERIFY; needs Apple Silicon + the MLX/CoreML toolchain to build + validate.
  • M6 — Kernel re-optimization for Gemma geometry (TurboQuant weight-quant + QJL/Polar KV-quant on windowed/global KV) across CPU/CUDA/Vulkan-Mali/Metal/NPU
    • low-precision + long context; re-verify 8/8.
  • M7 — Verification everywhere (web / desktop app / Pixel / bench harnesses + PR_EVIDENCE).

What's verifiable in-session vs needs hardware

  • Here (Linux x64 + CUDA): llama.cpp merge + CPU/CUDA builds; Gemma 4 text/vision/audio/MTP gen; code cutover; FFI seam; bench (llama-bench, e2e_loop_bench) on CPU/CUDA; web + desktop-app smoke.
  • Needs Mac: Metal kernels, CoreML/MLX backends, iOS.
  • Needs Pixel/Android device: Vulkan-Mali kernels, LiteRT NPU (Tensor/QNN), on-device tok/s + RSS. (Prior on-device work used adb/CDP on a Pixel 9a.)

Hardware-gated items are scoped + scaffolded here and marked for device verification; nothing is claimed "verified" without the evidence.

Acceptance criteria

  • Fork synced to upstream master; all relevant Gemma/MTP/LiteRT PRs absorbed or rejected-with-reason.
  • Gemma 4 runs through libelizainference (text+vision+audio+MTP) on every buildable backend.
  • Qwen fully removed from the shipped eliza-1 line.
  • Multi-backend selection behind one FFI; LiteRT/MLX/CoreML in-process; AICore/Foundation opportunistic.
  • Gemma-aware RAM defaults set; kernels re-optimized + 8/8 verified per buildable backend; low-precision quant validated.
  • tok/s + RSS + first-token + MTP-acceptance captured per platform; faster-or-justified vs retired Qwen line.
  • Verified on web + desktop app + on-device (as hardware allows; else honestly scoped).
  • eliza-1 branding preserved (users never see "Qwen"/"Gemma").