8000 llama.cpp: embed a pinned web UI (the build fetched HF's moving `latest`) by bryan-minimal · Pull Request #879 · gominimal/pkgs · GitHub
[go: up one dir, main page]

Skip to content

llama.cpp: embed a pinned web UI (the build fetched HF's moving latest) - #879

Merged
bryan-minimal merged 5 commits into
mainfrom
llama.cpp/no-native
Oct 23, 2026
Merged

bryan-minimal merged 5 commits into
mainfrom
llama.cpp/no-native

Conversation

@bryan-minimal
@bryan-minimal bryan-minimal commented Oct 15, 2026 •
Copy link
Copy Markdown
Member

Makes llama.cpp reproducible by embedding a pinned web UI instead of whatever Hugging Face serves as latest at build time.

Cause. Diffing the published llama.cpp artifacts of two world rebuilds showed libllama-server-impl.so differing in 31% of its bytes with an identical symbol set. It isn't -march=native: ggml already defaults GGML_NATIVE OFF when SOURCE_DATE_EPOCH is set (ggml/CMakeLists.txt:105-110; the build log prints "Setting GGML_NATIVE_DEFAULT to OFF"). It's the embedded web UI (llama-ui, linked into that library):

  • scripts/ui-assets.cmake downloads dist.tar.gz from Hugging Face during the build.
  • The tarball has no .git, so the build number is 0. The b0 lookup 404s, and the script falls back to the moving latest tag. A session build logged UI: downloading from latest.
  • latest today is 2e4be821…; b10357's UI is 68f883c9…. Each rebuild embedded whatever was current.

Fix

  • The b10357 UI is a second Source. It's mirrored to gs://minimal-staging-archives/ggml-org/llama-ui/b10357-dist.tar.gz, and its sha256 matches upstream's published dist.tar.gz.sha256. build.sh unpacks it into tools/ui/dist, which the script uses first. -DLLAMA_BUILD_UI=OFF -DLLAMA_USE_PREBUILT_UI=OFF turn off the npm and HF paths.
  • The script gzips each asset without -n, so the header records the file's mtime. The asset mtimes are pinned to 1980-01-01. The sandbox's SOURCE_DATE_EPOCH (0) is out of range for gzip, which exits 2 on it; the first attempt failed that way.
  • -DGGML_NATIVE=OFF stays as a guard, and its comment now says so.
  • The UI Source URL follows version, but its sha256 must be bumped by hand. The updater only rewrites the first sha256; a stale one fails closed.

Verified

  • A remote session double build ran two --rebuild builds with 399 C++ compiles each. All 16 output files hashed identical, including libllama-server-impl.so (2e17b64a…) and llama-server.
  • Both logs show UI: using pre-built assets and no download.
  • nickel format --check, bash -n and mip dump --packages are clean.

Not in this PR: arm64's plain -march=armv8-a leaves out the dotprod, fp16, i8mm and SVE kernels. That's #975, which proposes ggml's runtime CPU variants.

How t 8000 he UI hash was cross-checked

b10357's scripts/ui-assets.cmake (hf_download, lines 183-248) fetches https://huggingface.co/buckets/ggml-org/llama-ui/resolve/b<N>/dist.tar.gz and verifies it against the sibling dist.tar.gz.sha256 before use. I fetched both directly on 2026-10-22 and compared them with the pin and the mirror:

curl -sSL -o dist.tar.gz        'https://huggingface.co/buckets/ggml-org/llama-ui/resolve/b10357/dist.tar.gz?download=true'
curl -sSL -o dist.tar.gz.sha256 'https://huggingface.co/buckets/ggml-org/llama-ui/resolve/b10357/dist.tar.gz.sha256?download=true'
cat dist.tar.gz.sha256          # 68f883c9592b049e696a0837359a46f59ac3236188510bf92b477917a76f6dbc  dist.tar.gz
shasum -a 256 dist.tar.gz       # 68f883c9592b049e696a0837359a46f59ac3236188510bf92b477917a76f6dbc
gcloud storage cat gs://minimal-staging-archives/ggml-org/llama-ui/b10357-dist.tar.gz | shasum -a 256
                                # 68f883c9592b049e696a0837359a46f59ac3236188510bf92b477917a76f6dbc

All three agree, and they equal the pin in build.ncl.

HF buckets are Xet storage, not a git repo, so there's no revision commit. The object's immutable identity, from the response headers:

  • x-xet-hash / x-linked-etag: b3345b4fbdbe854a5f68b33b1e11abd2cddbae5c186d0c3d78405b0157da861f
  • x-linked-size: 3,074,915 bytes
  • last-modified: 2026-08-11 05:36:17 GMT, 19 minutes after the b10357 release was published (05:17:49Z, commit 689e227d)

build.json says b0000. b10357's tools/ui/scripts/vite-plugin-build-info.ts:26 writes LLAMA_BUILD_NUMBER || 'b0000'. So the published bundle was built without that env var set, and b0000 is the plugin's default, not a different build. The UI shows it only as a label.

🤖 Generated with Claude Code

…t the build host's CPU

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@bryan-minimal
bryan-minimal requested a review from a team as a code owner October 15, 2026 01:29
@coderabbitai
coderabbitai Bot commented Oct 15, 2026 •
Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Or wait 9 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 66 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 735d135 and dcf7f7e.

📒 Files selected for processing: 2
  • packages/llama.cpp/build.ncl
  • packages/llama.cpp/build.sh
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this is the fix for the diff.

  • Likely a no-op. At b10357, ggml/CMakeLists.txt:105-110 already defaults GGML_NATIVE to OFF whenever SOURCE_DATE_EPOCH is set, and the sandbox always sets it. The build log should already show "Setting GGML_NATIVE_DEFAULT to OFF".
  • It can't explain the diff anyway. -march=native only applies to ggml-cpu (ggml/src/ggml-cpu/CMakeLists.txt:733), but the differing file is libllama-server-impl.so. The comment at build.sh:13-16 states a cause that doesn't hold.
  • Likely real cause: libllama-server-impl.so links llama-ui, the embedded web UI. By default the build tries to download dist.tar.gz from Hugging Face, falling back to a moving latest when there is no build number (no .git in the tarball; scripts/ui-assets.cmake:183-197). It also gzips the assets without -n (:269). That fits "31% of bytes changed, identical symbols", and it's an unpinned download.
    • Please check the log for "UI: downloading".
    • Then try -DLLAMA_BUILD_UI=OFF -DLLAMA_USE_PREBUILT_UI=OFF, or a pinned UI source.

Keeping -DGGML_NATIVE=OFF as a guard is harmless; just reword the comment. Separately, arm64's plain -march=armv8-a leaves out dotprod, fp16 and i8mm, a large speed cost that predates this PR and is worth its own issue.


Generated by Claude Code

bryan-minimal and others added 2 commits October 21, 2026 19:08
The prod-pair diff wasn't -march=native: ggml already defaults GGML_NATIVE
OFF when SOURCE_DATE_EPOCH is set (the log says so). It was the embedded web
UI. scripts/ui-assets.cmake downloads dist.tar.gz from Hugging Face at
build time, and with no .git in the tarball the build number is 0, so it
falls back to the moving `latest` (a session build logged "UI: downloading
from latest"; latest is now 2e4be821…, not b10357's 68f883c9â
8000
€¦).

- The b10357 UI is a pinned Source (mirrored to minimal-staging-archives,
  sha256 = upstream's dist.tar.gz.sha256), unpacked into tools/ui/dist,
  which the script uses first. LLAMA_BUILD_UI=OFF and
  LLAMA_USE_PREBUILT_UI=OFF switch off the npm and HF paths.
- Asset mtimes pinned to 1980-01-01: the script gzips without -n, and the
  sandbox's SOURCE_DATE_EPOCH (0) is out of range for gzip, which exits 2.
- GGML_NATIVE=OFF kept, with the comment reworded as a guard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bryan-minimal bryan-minimal changed the title llama.cpp: GGML_NATIVE=OFF (codegen followed the build host CPU, not the declared -march) llama.cpp: embed a pinned web UI (the build fetched HF's moving latest) Oct 22, 2026
@bryan-minimal
Copy link
Copy Markdown
Member Author

Thanks @norrietaylor, you were right on every point. Addressed in 03aa8a5, on top of a merge of main (ba7c118):

  • No-op: confirmed. A session build of the old recipe printed Setting GGML_NATIVE_DEFAULT to OFF. -DGGML_NATIVE=OFF stays as a guard, and the comment now says so.
  • Real cause: confirmed. The same log has UI: download dist.tar.gz from b0 failed followed by UI: downloading from latest … archive verified and extracted, so the sandbox did reach Hugging Face. latest is now 2e4be821…, while b10357's UI is 68f883c9….
  • Fix: I pinned the UI instead of dropping it, so llama-server keeps its web UI.
    • The b10357 dist.tar.gz is a sha256-pinned Source, mirrored to minimal-staging-archives and matching upstream's .sha256. build.sh unpacks it into tools/ui/dist, which the script uses first.
    • -DLLAMA_BUILD_UI=OFF -DLLAMA_USE_PREBUILT_UI=OFF switch off the npm and HF paths.
    • For the gzip without -n, the asset mtimes are pinned. That had a catch: the sandbox's SOURCE_DATE_EPOCH is 0, and gzip rejects that ("file timestamp out of range", exit 2), so they're pinned to 1980-01-01 instead.
  • Verified: a remote session ran two --rebuild builds with 399 C++ compiles each, and all 16 output files are byte-identical, libllama-server-impl.so included.
  • arm64 -march=armv8-a: filed as llama.cpp: arm64 build leaves out dotprod/fp16/i8mm/SVE kernels (use ggml CPU variants) #975. It proposes GGML_BACKEND_DL + GGML_CPU_ALL_VARIANTS (runtime dispatch, as upstream's releases do), which also fixes the x86 -v3 floor.

One thing this turned up: llama.cpp declares no network needs, yet its build reached Hugging Face both in the session and, judging by the diff, on the prod builders. So builds without needs aren't actually offline.

🤖 Generated with Claude Code

@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This fixes the real cause.

  • tools/ui/dist is used first (ui-assets.cmake:298-302), before the npm or Hugging Face paths, and build.sh fails if index.html is missing, so the build can't fall back to a network fetch.
  • The touch -d @315532800 pins the mtimes that gzip stores.
  • The mirror hashes to the pinned 68f883c9….
  • The GGML_NATIVE comment now correctly calls it a guard.
  • arm64 is split out to #975.

Nits:

  • I couldn't compare the pin with upstream's dist.tar.gz.sha256 (HF is blocked for me), and the bundle's build.json says b0000. A line in the PR on how you cross-checked the hash would help.
  • The updater only rewrites the first sha256, so automatic bumps will fail on the UI source until it knows about it. It fails safely.
  • license_spdx = "MIT" doesn't reflect the Apache-2.0 code (pdf.js) in the embedded bundle. This predates the PR.

Generated by Claude Code

license_spdx was "MIT", but the binary also ships the llama-ui bundle
(402 npm packages: Apache-2.0 pdf.js/dexie/…, BSD-3/2, ISC, 0BSD,
Unlicense) and vendored public-domain/Unlicense C (miniaudio, stb,
sheredom). Declare the full expression and list the components; notice
files are pkgs#994.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bryan-minimal
Copy link
Copy Markdown
Member Author

Thanks @norrietaylor. All three nits are addressed in dcf7f7e, on top of a merge of main (61606c8):

  1. UI hash cross-check: the PR body has a new section, "How the UI hash was cross-checked", with the exact commands.
    • Upstream's own dist.tar.gz.sha256 for b10357, the Hugging Face bytes and our gs:// mirror all hash to the pinned 68f883c9…6dbc (3,074,915 bytes).
    • HF buckets have no git revision. The section records the object's immutable x-xet-hash (b3345b4f…a861f) and its last-modified time, 19 minutes after the b10357 release, so you can check it without HF access.
    • build.json's b0000 is the default in tools/ui/scripts/vite-plugin-build-info.ts:26 (LLAMA_BUILD_NUMBER || 'b0000'): upstream built the published bundle without that env var. It isn't a different build.
  2. The updater rewrites only the first sha256: agreed, and it fails closed. On a bump, the UI Source keeps b10357's hash, the new b<N>-dist.tar.gz doesn't match, and the build fails. The bump PR's "Additional pinned sources not updated" list names the UI Source, so a reviewer sees it. A pkgmgr change to re-pin every version-keyed Source is in progress, so I've left the recipe as it is.
  3. License: it's now MIT AND Apache-2.0 AND BSD-3-Clause AND BSD-2-Clause AND ISC AND 0BSD AND Unlicense, with a comment listing which component carries which licence.
    • Derivation: I took the transitive closure of the UI's runtime dependencies from b10357's tools/ui/package-lock.json: 402 packages.
      • Apache-2.0: pdfjs-dist, dexie, @internationalized/date, @swc/helpers, @chevrotain/types, aria-query, axobject-query.
      • BSD-3-Clause: highlight.js and the d3 modules. BSD-2-Clause: entities, json-schema-typed.
      • DOMPurify is MPL-2.0 OR Apache-2.0; I took Apache-2.0.
      • robust-predicates is Unlicense and tslib 0BSD.
      • The five packages with no licence field in the lock are MIT per their repos. The KaTeX fonts embedded in the CSS are MIT.
    • Vendored C++: cpp-httplib and nlohmann are MIT; miniaudio, stb and sheredom are public domain or Unlicense.
    • Not fixed here: the minified bundle ships no licence texts or NOTICE files; only pdf.js's header survives. Generating them belongs at bump time from the lockfile, so I filed it as llama.cpp: ship third-party license notices for the embedded web UI (Apache-2.0/BSD/ISC/MIT) #994 rather than widening this PR.

Only attrs changed, so there's no rebuild; nickel format --check, bash -n and mip dump are clean. The ruleset doesn't dismiss approvals on push, so your approval stands.

🤖 Generated with Claude Code

@bryan-minimal
bryan-minimal added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit 2c316bd Oct 23, 2026
11 checks passed
@bryan-minimal
bryan-minimal deleted the llama.cpp/no-native branch October 23, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0