studio: install macOS llama.cpp prebuilts from the unslothai fork
Route macOS at unslothai/llama.cpp instead of ggml-org/llama.cpp and drop --simple-policy for Darwin, so macOS installs read the fork's published manifest (the macos-arm64 / macos-x64 bundles built with deployment target 13.3) instead of upstream filenames. Upstream's arm64 release binaries are currently stamped minos=26 and fail to load on macOS < 26; the fork bundles load on macOS 13.3+. Non-macOS routing and setup.ps1 are unchanged, and the installer still falls back to upstream and then a source build if the fork lacks a compatible asset. Add a consumer-contract test that the fork's manifest + checksum schema parses and selects both macOS slices.
This commit is contained in:
parent
f213663d5b
commit
86f223a1b9
2 changed files with 199 additions and 3 deletions
|
|
@ -762,7 +762,8 @@ _HOST_SYSTEM="$(uname -s 2>/dev/null || true)"
|
|||
_HOST_MACHINE="$(uname -m 2>/dev/null || true)"
|
||||
|
||||
# Pick the release repo install_llama_prebuilt.py plans against.
|
||||
# unslothai/llama.cpp ships only Linux CUDA bundles, so CPU-only Linux
|
||||
# unslothai/llama.cpp ships the Linux CUDA bundles and the macOS arm64/x64
|
||||
# bundles (deployment target 13.3), so macOS routes there. CPU-only Linux
|
||||
# x86_64 routes to ggml-org for bin-ubuntu-x64.tar.gz. Anything with a
|
||||
# GPU tool installed stays on unslothai (CUDA bundle / ROCm source build).
|
||||
_LINUX_HAS_GPU=false
|
||||
|
|
@ -774,7 +775,7 @@ for _GPU_TOOL in nvidia-smi rocminfo amd-smi hipconfig hipinfo; do
|
|||
done
|
||||
|
||||
if [ "$_HOST_SYSTEM" = "Darwin" ]; then
|
||||
_HELPER_RELEASE_REPO="ggml-org/llama.cpp"
|
||||
_HELPER_RELEASE_REPO="unslothai/llama.cpp"
|
||||
elif [ "$_HOST_SYSTEM" = "Linux" ] \
|
||||
&& [ "$_HOST_MACHINE" = "x86_64" ] \
|
||||
&& [ "$_LINUX_HAS_GPU" = false ]; then
|
||||
|
|
@ -852,8 +853,13 @@ else
|
|||
--install-dir "$LLAMA_CPP_DIR"
|
||||
--llama-tag "$_REQUESTED_LLAMA_TAG"
|
||||
--published-repo "$_HELPER_RELEASE_REPO"
|
||||
--simple-policy
|
||||
)
|
||||
# macOS consumes the fork's published manifest (arm64/x64 bundles); the
|
||||
# simple filename-only policy ignores that manifest, so keep it for the
|
||||
# non-macOS hosts that still resolve assets straight off upstream filenames.
|
||||
if [ "$_HOST_SYSTEM" != "Darwin" ]; then
|
||||
_PREBUILT_CMD+=(--simple-policy)
|
||||
fi
|
||||
if [ -n "${UNSLOTH_LLAMA_RELEASE_TAG:-}" ]; then
|
||||
_PREBUILT_CMD+=(--published-release-tag "$UNSLOTH_LLAMA_RELEASE_TAG")
|
||||
fi
|
||||
|
|
|
|||
190
tests/studio/install/test_macos_release_manifest.py
Normal file
190
tests/studio/install/test_macos_release_manifest.py
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
"""Consumer-contract tests for the self-built macOS llama.cpp mirror release.
|
||||
|
||||
The daily `unsloth-macos-prebuilt` workflow on the unslothai/llama.cpp fork
|
||||
publishes a macOS-only release whose `llama-prebuilt-manifest.json` /
|
||||
`llama-prebuilt-sha256.json` must be selectable by this installer. These tests
|
||||
pin that contract: given a manifest + checksum asset in the shape the workflow
|
||||
emits, the installer parses the bundle, the source-hash shortcut is satisfied,
|
||||
and both macOS slices resolve as published choices with stamped digests.
|
||||
|
||||
No network, no torch, no Mach-O toolchain -- the manifest bytes are synthesized
|
||||
and download I/O is monkeypatched.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
PACKAGE_ROOT = Path(__file__).resolve().parents[3]
|
||||
MODULE_PATH = PACKAGE_ROOT / "studio" / "install_llama_prebuilt.py"
|
||||
SPEC = importlib.util.spec_from_file_location(
|
||||
"studio_install_llama_prebuilt_macos_manifest", MODULE_PATH
|
||||
)
|
||||
assert SPEC is not None and SPEC.loader is not None
|
||||
ILP = importlib.util.module_from_spec(SPEC)
|
||||
sys.modules[SPEC.name] = ILP
|
||||
SPEC.loader.exec_module(ILP)
|
||||
|
||||
REPO = "unslothai/llama.cpp"
|
||||
UPSTREAM_TAG = "b9999"
|
||||
COMMIT = "25b1bc9f0a1b2c3d4e5f60718293a4b5c6d7e8f9"
|
||||
RELEASE_TAG = f"llama-prebuilt-macos-{UPSTREAM_TAG}"
|
||||
ARM64_ASSET = f"llama-{UPSTREAM_TAG}-bin-macos-arm64.tar.gz"
|
||||
X64_ASSET = f"llama-{UPSTREAM_TAG}-bin-macos-x64.tar.gz"
|
||||
EXACT_SOURCE_ASSET = f"llama.cpp-source-commit-{COMMIT}.tar.gz"
|
||||
|
||||
|
||||
def _hex(label):
|
||||
return hashlib.sha256(label.encode()).hexdigest()
|
||||
|
||||
|
||||
def _source_fields():
|
||||
return {
|
||||
"source_repo": "ggml-org/llama.cpp",
|
||||
"source_repo_url": "https://github.com/ggml-org/llama.cpp",
|
||||
"source_ref_kind": "tag",
|
||||
"requested_source_ref": UPSTREAM_TAG,
|
||||
"resolved_source_ref": UPSTREAM_TAG,
|
||||
"source_commit": COMMIT,
|
||||
"source_commit_short": COMMIT[:7],
|
||||
}
|
||||
|
||||
|
||||
def _manifest_bytes():
|
||||
manifest = {
|
||||
"schema_version": 1,
|
||||
"component": "llama.cpp",
|
||||
"upstream_repo": "ggml-org/llama.cpp",
|
||||
"upstream_tag": UPSTREAM_TAG,
|
||||
**_source_fields(),
|
||||
"artifacts": [
|
||||
{
|
||||
"asset_name": ARM64_ASSET,
|
||||
"install_kind": "macos-arm64",
|
||||
"bundle_profile": "macos-metal-arm64",
|
||||
"runtime_line": None,
|
||||
"coverage_class": None,
|
||||
"rank": 50,
|
||||
},
|
||||
{
|
||||
"asset_name": X64_ASSET,
|
||||
"install_kind": "macos-x64",
|
||||
"bundle_profile": "macos-cpu-x64",
|
||||
"runtime_line": None,
|
||||
"coverage_class": None,
|
||||
"rank": 50,
|
||||
},
|
||||
],
|
||||
}
|
||||
return (json.dumps(manifest, indent=2) + "\n").encode("utf-8")
|
||||
|
||||
|
||||
def _checksums_payload(manifest_bytes, *, include_exact_source=True):
|
||||
artifacts = {
|
||||
ARM64_ASSET: {"sha256": _hex(ARM64_ASSET), "repo": REPO, "kind": "macos-arm64-app"},
|
||||
X64_ASSET: {"sha256": _hex(X64_ASSET), "repo": REPO, "kind": "macos-x64-app"},
|
||||
"llama-prebuilt-manifest.json": {
|
||||
"sha256": hashlib.sha256(manifest_bytes).hexdigest(),
|
||||
"repo": REPO,
|
||||
"kind": "published-manifest",
|
||||
},
|
||||
}
|
||||
if include_exact_source:
|
||||
artifacts[EXACT_SOURCE_ASSET] = {
|
||||
"sha256": _hex(EXACT_SOURCE_ASSET),
|
||||
"repo": "ggml-org/llama.cpp",
|
||||
"kind": "exact-source",
|
||||
}
|
||||
return {
|
||||
"schema_version": 1,
|
||||
"component": "llama.cpp",
|
||||
"release_tag": RELEASE_TAG,
|
||||
"upstream_tag": UPSTREAM_TAG,
|
||||
**_source_fields(),
|
||||
"artifacts": artifacts,
|
||||
}
|
||||
|
||||
|
||||
def _release_dict():
|
||||
names = [
|
||||
"llama-prebuilt-manifest.json",
|
||||
"llama-prebuilt-sha256.json",
|
||||
ARM64_ASSET,
|
||||
X64_ASSET,
|
||||
EXACT_SOURCE_ASSET,
|
||||
]
|
||||
return {
|
||||
"tag_name": RELEASE_TAG,
|
||||
"assets": [
|
||||
{"name": n, "browser_download_url": f"https://example/{n}"} for n in names
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def manifest_bytes(monkeypatch):
|
||||
data = _manifest_bytes()
|
||||
# parse_published_release_bundle downloads only the manifest URL.
|
||||
monkeypatch.setattr(ILP, "download_bytes", lambda url, **kw: data)
|
||||
monkeypatch.setattr(ILP, "auth_headers", lambda url: {})
|
||||
return data
|
||||
|
||||
|
||||
def test_bundle_parses_both_slices(manifest_bytes):
|
||||
bundle = ILP.parse_published_release_bundle(REPO, _release_dict())
|
||||
assert bundle is not None
|
||||
assert bundle.upstream_tag == UPSTREAM_TAG
|
||||
assert sorted(a.install_kind for a in bundle.artifacts) == ["macos-arm64", "macos-x64"]
|
||||
assert bundle.source_commit == COMMIT
|
||||
|
||||
|
||||
def test_checksums_parse_and_source_shortcut(manifest_bytes):
|
||||
checksums = ILP.parse_approved_release_checksums(
|
||||
REPO, RELEASE_TAG, _checksums_payload(manifest_bytes)
|
||||
)
|
||||
assert ARM64_ASSET in checksums.artifacts
|
||||
assert X64_ASSET in checksums.artifacts
|
||||
# The exact-commit source archive satisfies validated_checksums_for_bundle
|
||||
# without the legacy llama.cpp-source-<tag>.tar.gz entry.
|
||||
assert ILP.exact_source_archive_hash(checksums) is not None
|
||||
|
||||
|
||||
def test_manifest_sha_cross_check_matches(manifest_bytes):
|
||||
bundle = ILP.parse_published_release_bundle(REPO, _release_dict())
|
||||
checksums = ILP.parse_approved_release_checksums(
|
||||
REPO, RELEASE_TAG, _checksums_payload(manifest_bytes)
|
||||
)
|
||||
manifest_hash = checksums.artifacts.get(bundle.manifest_asset_name)
|
||||
assert manifest_hash is not None
|
||||
assert manifest_hash.sha256 == bundle.manifest_sha256
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["macos-arm64", "macos-x64"])
|
||||
def test_published_choice_selectable_and_stamped(manifest_bytes, kind):
|
||||
bundle = ILP.parse_published_release_bundle(REPO, _release_dict())
|
||||
checksums = ILP.parse_approved_release_checksums(
|
||||
REPO, RELEASE_TAG, _checksums_payload(manifest_bytes)
|
||||
)
|
||||
choice = ILP.published_asset_choice_for_kind(bundle, kind)
|
||||
assert choice is not None
|
||||
assert choice.source_label == "published"
|
||||
assert choice.install_kind == kind
|
||||
stamped = ILP.apply_approved_hashes([choice], checksums)
|
||||
assert stamped
|
||||
assert stamped[0].expected_sha256 == checksums.artifacts[choice.name].sha256
|
||||
|
||||
|
||||
def test_missing_source_hash_is_rejected(manifest_bytes):
|
||||
# No exact-source and no legacy source entry -> require_approved_source_hash
|
||||
# must reject, so we never silently ship a bundle with no approved source.
|
||||
checksums = ILP.parse_approved_release_checksums(
|
||||
REPO, RELEASE_TAG, _checksums_payload(manifest_bytes, include_exact_source=False)
|
||||
)
|
||||
assert ILP.exact_source_archive_hash(checksums) is None
|
||||
with pytest.raises(ILP.PrebuiltFallback):
|
||||
ILP.require_approved_source_hash(checksums, UPSTREAM_TAG)
|
||||
Loading…
Add table
Add a link
Reference in a new issue