Feat/custom llama prebuilt (#4771)
* update logic to incorporate custom prebuilt installs * bug fixes * update for review comments * fix tags * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Separate test changes from main PR Move test file changes out of this PR to keep the diff focused on the install_llama_prebuilt.py and setup script changes. Test updates will be submitted in a follow-up PR. * Fix branch ref normalization and harden JSON parsing - Add checkout_friendly_ref() to strip refs/heads/ prefix from branch refs before emitting them in SourceBuildPlan. git clone --branch does not accept fully qualified refs like refs/heads/main. - Apply normalization in source_build_plan_for_release() and the direct-ref fallback in resolve_source_build_plan(). - Allow validated_checksums_for_bundle() to accept releases that carry only an exact-commit source archive without the legacy upstream-tag source tarball. - Add 2>/dev/null || true guards to all inline python -c JSON parsing in setup.sh so a malformed payload does not abort the script under set -e. * Fix Windows CUDA asset ordering and tag ref normalization - Reorder windows_cuda_upstream_asset_names to prefer the main binary archive (llama-{tag}-bin-win-cuda-*) over the cudart sidecar archive (cudart-llama-bin-win-cuda-*). The cudart ZIP only contains CUDA runtime DLLs, not llama-server or llama-quantize binaries. - Extend checkout_friendly_ref to also strip refs/tags/ prefix for tag refs, matching the refs/heads/ handling for branch refs. * Simplify JSON parsing consistency in setup.sh Use json.load(sys.stdin) consistently for all inline JSON parsing in setup.sh, instead of the more complex json.loads(raw) pattern on the install-tag resolution path. The 2>/dev/null || true guard already handles empty/malformed input gracefully. * Fix source build plan fallback for commit ref kind in PR #4771 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Han <daniel@unsloth.ai> Co-authored-by: Daniel Han <danielhanchen@gmail.com>
This commit is contained in:
parent
b20efc370a
commit
1ce8a8e7cd
3 changed files with 857 additions and 100 deletions
|
|
@ -28,7 +28,7 @@ import urllib.parse
|
|||
import urllib.request
|
||||
import zipfile
|
||||
from contextlib import contextmanager
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
try:
|
||||
from filelock import FileLock, Timeout as FileLockTimeout
|
||||
|
|
@ -59,7 +59,6 @@ def env_int(name: str, default: int, *, minimum: int | None = None) -> int:
|
|||
return value
|
||||
|
||||
|
||||
APPROVED_PREBUILT_LLAMA_TAG = "b8508"
|
||||
DEFAULT_LLAMA_TAG = os.environ.get("UNSLOTH_LLAMA_TAG", "latest")
|
||||
DEFAULT_PUBLISHED_REPO = os.environ.get(
|
||||
"UNSLOTH_LLAMA_RELEASE_REPO", "unslothai/llama.cpp"
|
||||
|
|
@ -151,10 +150,18 @@ class PublishedReleaseBundle:
|
|||
repo: str
|
||||
release_tag: str
|
||||
upstream_tag: str
|
||||
assets: dict[str, str]
|
||||
manifest_asset_name: str
|
||||
artifacts: list[PublishedLlamaArtifact]
|
||||
selection_log: list[str]
|
||||
manifest_sha256: str | None = None
|
||||
source_repo: str | None = None
|
||||
source_repo_url: str | None = None
|
||||
source_ref_kind: str | None = None
|
||||
requested_source_ref: str | None = None
|
||||
resolved_source_ref: str | None = None
|
||||
source_commit: str | None = None
|
||||
source_commit_short: str | None = None
|
||||
assets: dict[str, str] = field(default_factory = dict)
|
||||
manifest_asset_name: str = DEFAULT_PUBLISHED_MANIFEST_ASSET
|
||||
artifacts: list[PublishedLlamaArtifact] = field(default_factory = list)
|
||||
selection_log: list[str] = field(default_factory = list)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -188,8 +195,14 @@ class ApprovedReleaseChecksums:
|
|||
repo: str
|
||||
release_tag: str
|
||||
upstream_tag: str
|
||||
source_commit: str | None
|
||||
artifacts: dict[str, ApprovedArtifactHash]
|
||||
source_repo: str | None = None
|
||||
source_repo_url: str | None = None
|
||||
source_ref_kind: str | None = None
|
||||
requested_source_ref: str | None = None
|
||||
resolved_source_ref: str | None = None
|
||||
source_commit: str | None = None
|
||||
source_commit_short: str | None = None
|
||||
artifacts: dict[str, ApprovedArtifactHash] = field(default_factory = dict)
|
||||
|
||||
|
||||
@dataclass(frozen = True)
|
||||
|
|
@ -198,6 +211,19 @@ class ResolvedPublishedRelease:
|
|||
checksums: ApprovedReleaseChecksums
|
||||
|
||||
|
||||
@dataclass(frozen = True)
|
||||
class SourceBuildPlan:
|
||||
source_url: str
|
||||
source_ref: str
|
||||
source_ref_kind: str
|
||||
compatibility_upstream_tag: str
|
||||
source_repo: str | None = None
|
||||
source_repo_url: str | None = None
|
||||
requested_source_ref: str | None = None
|
||||
resolved_source_ref: str | None = None
|
||||
source_commit: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen = True)
|
||||
class InstallReleasePlan:
|
||||
requested_tag: str
|
||||
|
|
@ -270,7 +296,7 @@ def is_busy_lock_error(exc: BaseException) -> bool:
|
|||
|
||||
|
||||
def log(message: str) -> None:
|
||||
print(f"[llama-prebuilt] {message}")
|
||||
print(f"[llama-prebuilt] {message}", file = sys.stderr)
|
||||
|
||||
|
||||
def log_lines(lines: Iterable[str]) -> None:
|
||||
|
|
@ -358,6 +384,10 @@ def source_archive_logical_name(upstream_tag: str) -> str:
|
|||
return f"llama.cpp-source-{upstream_tag}.tar.gz"
|
||||
|
||||
|
||||
def exact_source_archive_logical_name(source_commit: str) -> str:
|
||||
return f"llama.cpp-source-commit-{source_commit}.tar.gz"
|
||||
|
||||
|
||||
def sha256_file(path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as handle:
|
||||
|
|
@ -366,6 +396,10 @@ def sha256_file(path: Path) -> str:
|
|||
return digest.hexdigest()
|
||||
|
||||
|
||||
def sha256_bytes(data: bytes) -> str:
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
|
||||
|
||||
def normalize_sha256_digest(value: str | None) -> str | None:
|
||||
if not isinstance(value, str) or not value:
|
||||
return None
|
||||
|
|
@ -377,6 +411,156 @@ def normalize_sha256_digest(value: str | None) -> str | None:
|
|||
return lowered
|
||||
|
||||
|
||||
def normalize_source_ref_kind(value: str | None) -> str | None:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
normalized = value.strip().lower()
|
||||
if normalized in {"tag", "branch", "pull", "commit", "custom"}:
|
||||
return normalized
|
||||
return None
|
||||
|
||||
|
||||
def normalize_source_commit(value: str | None) -> str | None:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
normalized = value.strip().lower()
|
||||
if len(normalized) < 7 or len(normalized) > 40:
|
||||
return None
|
||||
if any(ch not in "0123456789abcdef" for ch in normalized):
|
||||
return None
|
||||
return normalized
|
||||
|
||||
|
||||
def validate_schema_version(payload: dict[str, Any], *, label: str) -> None:
|
||||
schema_version = payload.get("schema_version")
|
||||
if schema_version is None:
|
||||
return
|
||||
try:
|
||||
normalized = int(schema_version)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise RuntimeError(f"{label} schema_version was not an integer") from exc
|
||||
if normalized != 1:
|
||||
raise RuntimeError(f"{label} schema_version={normalized} is unsupported")
|
||||
|
||||
|
||||
def repo_slug_from_source(value: str | None) -> str | None:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
normalized = value.strip()
|
||||
if not normalized:
|
||||
return None
|
||||
normalized = normalized.removesuffix(".git")
|
||||
if normalized.startswith("https://github.com/"):
|
||||
slug = normalized[len("https://github.com/") :]
|
||||
elif normalized.startswith("http://github.com/"):
|
||||
slug = normalized[len("http://github.com/") :]
|
||||
elif normalized.startswith("git@github.com:"):
|
||||
slug = normalized[len("git@github.com:") :]
|
||||
else:
|
||||
slug = normalized
|
||||
slug = slug.strip("/")
|
||||
parts = slug.split("/")
|
||||
if len(parts) != 2 or not all(parts):
|
||||
return None
|
||||
return f"{parts[0]}/{parts[1]}"
|
||||
|
||||
|
||||
def source_url_from_repo_slug(repo_slug: str | None) -> str | None:
|
||||
if not isinstance(repo_slug, str) or not repo_slug:
|
||||
return None
|
||||
return f"https://github.com/{repo_slug}"
|
||||
|
||||
|
||||
def source_repo_clone_url(repo: str | None, repo_url: str | None) -> str | None:
|
||||
if isinstance(repo_url, str) and repo_url.strip():
|
||||
return repo_url.strip().removesuffix(".git")
|
||||
return source_url_from_repo_slug(repo_slug_from_source(repo))
|
||||
|
||||
|
||||
def infer_source_ref_kind(ref: str | None) -> str:
|
||||
if not isinstance(ref, str):
|
||||
return "tag"
|
||||
normalized = ref.strip()
|
||||
lowered = normalized.lower()
|
||||
if not normalized:
|
||||
return "tag"
|
||||
if lowered.startswith("refs/pull/") or lowered.startswith("pull/"):
|
||||
return "pull"
|
||||
if (
|
||||
lowered.startswith("refs/heads/")
|
||||
or lowered in {"main", "master", "head"}
|
||||
or lowered.startswith("origin/")
|
||||
):
|
||||
return "branch"
|
||||
normalized_commit = normalize_source_commit(normalized)
|
||||
if normalized_commit is not None:
|
||||
return "commit"
|
||||
return "tag"
|
||||
|
||||
|
||||
def normalized_ref_aliases(ref: str | None) -> set[str]:
|
||||
if not isinstance(ref, str):
|
||||
return set()
|
||||
normalized = ref.strip()
|
||||
if not normalized:
|
||||
return set()
|
||||
aliases = {normalized}
|
||||
lowered = normalized.lower()
|
||||
commit = normalize_source_commit(normalized)
|
||||
if commit is not None:
|
||||
aliases.add(commit)
|
||||
if lowered.startswith("refs/heads/"):
|
||||
aliases.add(normalized.split("/", 2)[2])
|
||||
elif "/" not in normalized and infer_source_ref_kind(normalized) == "branch":
|
||||
aliases.add(f"refs/heads/{normalized}")
|
||||
if lowered.startswith("refs/pull/"):
|
||||
aliases.add(normalized.removeprefix("refs/"))
|
||||
elif lowered.startswith("pull/"):
|
||||
aliases.add(f"refs/{normalized}")
|
||||
return aliases
|
||||
|
||||
|
||||
def refs_match(candidate_ref: str | None, requested_ref: str | None) -> bool:
|
||||
candidate_aliases = normalized_ref_aliases(candidate_ref)
|
||||
requested_aliases = normalized_ref_aliases(requested_ref)
|
||||
if not candidate_aliases or not requested_aliases:
|
||||
return False
|
||||
if candidate_aliases & requested_aliases:
|
||||
return True
|
||||
candidate_commit = normalize_source_commit(candidate_ref)
|
||||
requested_commit = normalize_source_commit(requested_ref)
|
||||
if candidate_commit and requested_commit:
|
||||
return candidate_commit.startswith(
|
||||
requested_commit
|
||||
) or requested_commit.startswith(candidate_commit)
|
||||
return False
|
||||
|
||||
|
||||
def checkout_friendly_ref(ref_kind: str | None, ref: str | None) -> str | None:
|
||||
"""Normalize a source ref to a form that ``git clone --branch`` accepts.
|
||||
|
||||
Fully qualified branch refs like ``refs/heads/main`` are stripped to
|
||||
``main``; tag refs like ``refs/tags/b8508`` are stripped to ``b8508``.
|
||||
Pull refs like ``refs/pull/123/head`` are left as-is since they are
|
||||
always fetched explicitly rather than cloned with ``--branch``.
|
||||
"""
|
||||
if not isinstance(ref, str) or not ref:
|
||||
return ref
|
||||
lowered = ref.lower()
|
||||
if ref_kind == "branch" and lowered.startswith("refs/heads/"):
|
||||
return ref.split("/", 2)[2]
|
||||
if ref_kind == "tag" and lowered.startswith("refs/tags/"):
|
||||
return ref.split("/", 2)[2]
|
||||
return ref
|
||||
|
||||
|
||||
def windows_cuda_upstream_asset_names(llama_tag: str, runtime: str) -> list[str]:
|
||||
return [
|
||||
f"llama-{llama_tag}-bin-win-cuda-{runtime}-x64.zip",
|
||||
f"cudart-llama-bin-win-cuda-{runtime}-x64.zip",
|
||||
]
|
||||
|
||||
|
||||
def format_byte_count(num_bytes: float) -> str:
|
||||
units = ["B", "KiB", "MiB", "GiB", "TiB"]
|
||||
value = float(num_bytes)
|
||||
|
|
@ -537,13 +721,21 @@ def download_bytes(
|
|||
|
||||
|
||||
def fetch_json(url: str) -> Any:
|
||||
data = download_bytes(
|
||||
url,
|
||||
timeout = 30,
|
||||
headers = github_api_headers(url)
|
||||
if is_github_api_url(url)
|
||||
else auth_headers(url),
|
||||
)
|
||||
try:
|
||||
data = download_bytes(
|
||||
url,
|
||||
timeout = 30,
|
||||
headers = github_api_headers(url)
|
||||
if is_github_api_url(url)
|
||||
else auth_headers(url),
|
||||
)
|
||||
except urllib.error.HTTPError as exc:
|
||||
if exc.code == 403 and is_github_api_url(url):
|
||||
hint = ""
|
||||
if not (os.environ.get("GH_TOKEN") or os.environ.get("GITHUB_TOKEN")):
|
||||
hint = "; set GH_TOKEN or GITHUB_TOKEN to avoid GitHub API rate limits"
|
||||
raise RuntimeError(f"GitHub API returned 403 for {url}{hint}") from exc
|
||||
raise
|
||||
if not data:
|
||||
raise RuntimeError(f"downloaded empty JSON payload from {url}")
|
||||
try:
|
||||
|
|
@ -648,6 +840,14 @@ def upstream_source_archive_urls(tag: str) -> list[str]:
|
|||
]
|
||||
|
||||
|
||||
def commit_source_archive_urls(repo: str, source_commit: str) -> list[str]:
|
||||
encoded_commit = urllib.parse.quote(source_commit, safe = "")
|
||||
return [
|
||||
f"https://codeload.github.com/{repo}/tar.gz/{encoded_commit}",
|
||||
f"https://github.com/{repo}/archive/{encoded_commit}.tar.gz",
|
||||
]
|
||||
|
||||
|
||||
def github_release_assets(repo: str, tag: str) -> dict[str, str]:
|
||||
payload = fetch_json(
|
||||
f"https://api.github.com/repos/{repo}/releases/tags/{urllib.parse.quote(tag, safe = '')}"
|
||||
|
|
@ -984,13 +1184,35 @@ def parse_published_release_bundle(
|
|||
|
||||
# Mixed repos are filtered by an explicit release-side manifest rather than
|
||||
# by release tag or asset filename conventions.
|
||||
manifest_payload = fetch_json(manifest_url)
|
||||
manifest_bytes = download_bytes(
|
||||
manifest_url,
|
||||
timeout = 30,
|
||||
headers = auth_headers(manifest_url),
|
||||
)
|
||||
manifest_sha256 = sha256_bytes(manifest_bytes)
|
||||
try:
|
||||
manifest_payload = json.loads(manifest_bytes.decode("utf-8"))
|
||||
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
||||
raise RuntimeError(
|
||||
f"published manifest {DEFAULT_PUBLISHED_MANIFEST_ASSET} was not valid JSON"
|
||||
) from exc
|
||||
if not isinstance(manifest_payload, dict):
|
||||
raise RuntimeError(
|
||||
f"published manifest {DEFAULT_PUBLISHED_MANIFEST_ASSET} was not a JSON object"
|
||||
)
|
||||
validate_schema_version(
|
||||
manifest_payload,
|
||||
label = f"published manifest {DEFAULT_PUBLISHED_MANIFEST_ASSET} in {repo}@{release_tag}",
|
||||
)
|
||||
component = manifest_payload.get("component")
|
||||
upstream_tag = manifest_payload.get("upstream_tag")
|
||||
source_repo = manifest_payload.get("source_repo")
|
||||
source_repo_url = manifest_payload.get("source_repo_url")
|
||||
source_ref_kind = normalize_source_ref_kind(manifest_payload.get("source_ref_kind"))
|
||||
requested_source_ref = manifest_payload.get("requested_source_ref")
|
||||
resolved_source_ref = manifest_payload.get("resolved_source_ref")
|
||||
source_commit = normalize_source_commit(manifest_payload.get("source_commit"))
|
||||
source_commit_short = manifest_payload.get("source_commit_short")
|
||||
if component != "llama.cpp":
|
||||
return None
|
||||
if not isinstance(upstream_tag, str) or not upstream_tag:
|
||||
|
|
@ -1021,10 +1243,32 @@ def parse_published_release_bundle(
|
|||
f"published_release: manifest={DEFAULT_PUBLISHED_MANIFEST_ASSET}",
|
||||
f"published_release: upstream_tag={upstream_tag}",
|
||||
]
|
||||
if isinstance(source_repo, str) and source_repo:
|
||||
selection_log.append(f"published_release: source_repo={source_repo}")
|
||||
if source_commit:
|
||||
selection_log.append(f"published_release: source_commit={source_commit}")
|
||||
return PublishedReleaseBundle(
|
||||
repo = repo,
|
||||
release_tag = release_tag,
|
||||
upstream_tag = upstream_tag,
|
||||
manifest_sha256 = manifest_sha256,
|
||||
source_repo = source_repo
|
||||
if isinstance(source_repo, str) and source_repo
|
||||
else None,
|
||||
source_repo_url = source_repo_url
|
||||
if isinstance(source_repo_url, str) and source_repo_url
|
||||
else None,
|
||||
source_ref_kind = source_ref_kind,
|
||||
requested_source_ref = requested_source_ref
|
||||
if isinstance(requested_source_ref, str) and requested_source_ref
|
||||
else None,
|
||||
resolved_source_ref = resolved_source_ref
|
||||
if isinstance(resolved_source_ref, str) and resolved_source_ref
|
||||
else None,
|
||||
source_commit = source_commit,
|
||||
source_commit_short = source_commit_short
|
||||
if isinstance(source_commit_short, str) and source_commit_short
|
||||
else None,
|
||||
assets = assets,
|
||||
manifest_asset_name = DEFAULT_PUBLISHED_MANIFEST_ASSET,
|
||||
artifacts = artifacts,
|
||||
|
|
@ -1041,6 +1285,10 @@ def parse_approved_release_checksums(
|
|||
raise RuntimeError(
|
||||
f"published checksum asset {DEFAULT_PUBLISHED_SHA256_ASSET} was not a JSON object"
|
||||
)
|
||||
validate_schema_version(
|
||||
payload,
|
||||
label = f"published checksum asset {DEFAULT_PUBLISHED_SHA256_ASSET}",
|
||||
)
|
||||
if payload.get("component") != "llama.cpp":
|
||||
raise RuntimeError(
|
||||
f"published checksum asset {DEFAULT_PUBLISHED_SHA256_ASSET} did not describe llama.cpp"
|
||||
|
|
@ -1090,13 +1338,33 @@ def parse_approved_release_checksums(
|
|||
kind = kind_value if isinstance(kind_value, str) and kind_value else None,
|
||||
)
|
||||
|
||||
source_commit = payload.get("source_commit")
|
||||
source_commit = normalize_source_commit(payload.get("source_commit"))
|
||||
source_commit_short = payload.get("source_commit_short")
|
||||
source_repo = payload.get("source_repo")
|
||||
source_repo_url = payload.get("source_repo_url")
|
||||
source_ref_kind = normalize_source_ref_kind(payload.get("source_ref_kind"))
|
||||
requested_source_ref = payload.get("requested_source_ref")
|
||||
resolved_source_ref = payload.get("resolved_source_ref")
|
||||
return ApprovedReleaseChecksums(
|
||||
repo = repo,
|
||||
release_tag = release_tag,
|
||||
upstream_tag = upstream_tag,
|
||||
source_commit = source_commit
|
||||
if isinstance(source_commit, str) and source_commit
|
||||
source_repo = source_repo
|
||||
if isinstance(source_repo, str) and source_repo
|
||||
else None,
|
||||
source_repo_url = source_repo_url
|
||||
if isinstance(source_repo_url, str) and source_repo_url
|
||||
else None,
|
||||
source_ref_kind = source_ref_kind,
|
||||
requested_source_ref = requested_source_ref
|
||||
if isinstance(requested_source_ref, str) and requested_source_ref
|
||||
else None,
|
||||
resolved_source_ref = resolved_source_ref
|
||||
if isinstance(resolved_source_ref, str) and resolved_source_ref
|
||||
else None,
|
||||
source_commit = source_commit,
|
||||
source_commit_short = source_commit_short
|
||||
if isinstance(source_commit_short, str) and source_commit_short
|
||||
else None,
|
||||
artifacts = artifacts,
|
||||
)
|
||||
|
|
@ -1390,10 +1658,36 @@ def validated_checksums_for_bundle(
|
|||
repo: str, bundle: PublishedReleaseBundle
|
||||
) -> ApprovedReleaseChecksums:
|
||||
checksums = load_approved_release_checksums(repo, bundle.release_tag)
|
||||
require_approved_source_hash(checksums, bundle.upstream_tag)
|
||||
manifest_hash = checksums.artifacts.get(bundle.manifest_asset_name)
|
||||
if manifest_hash is not None and bundle.manifest_sha256 is not None:
|
||||
if manifest_hash.sha256 != bundle.manifest_sha256:
|
||||
raise PrebuiltFallback(
|
||||
"published manifest checksum did not match the approved checksum asset"
|
||||
)
|
||||
# Accept bundles that carry only an exact-commit source archive
|
||||
# (e.g. llama.cpp-source-commit-<sha>.tar.gz) without requiring the
|
||||
# legacy llama.cpp-source-<upstream_tag>.tar.gz entry.
|
||||
if exact_source_archive_hash(checksums) is None:
|
||||
require_approved_source_hash(checksums, bundle.upstream_tag)
|
||||
return checksums
|
||||
|
||||
|
||||
def published_release_matches_request(
|
||||
bundle: PublishedReleaseBundle, requested_ref: str
|
||||
) -> bool:
|
||||
if requested_ref == "latest":
|
||||
return True
|
||||
for candidate in (
|
||||
bundle.upstream_tag,
|
||||
bundle.requested_source_ref,
|
||||
bundle.resolved_source_ref,
|
||||
bundle.source_commit,
|
||||
):
|
||||
if refs_match(candidate, requested_ref):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def resolve_published_release(
|
||||
requested_tag: str | None,
|
||||
published_repo: str,
|
||||
|
|
@ -1404,10 +1698,7 @@ def resolve_published_release(
|
|||
|
||||
if published_release_tag:
|
||||
bundle = pinned_published_release_bundle(repo, published_release_tag)
|
||||
if (
|
||||
normalized_requested != "latest"
|
||||
and bundle.upstream_tag != normalized_requested
|
||||
):
|
||||
if not published_release_matches_request(bundle, normalized_requested):
|
||||
raise PrebuiltFallback(
|
||||
"published release "
|
||||
f"{repo}@{published_release_tag} targeted upstream tag {bundle.upstream_tag}, "
|
||||
|
|
@ -1420,10 +1711,7 @@ def resolve_published_release(
|
|||
|
||||
skipped_invalid = 0
|
||||
for bundle in iter_published_release_bundles(repo):
|
||||
if (
|
||||
normalized_requested != "latest"
|
||||
and bundle.upstream_tag != normalized_requested
|
||||
):
|
||||
if not published_release_matches_request(bundle, normalized_requested):
|
||||
continue
|
||||
try:
|
||||
checksums = validated_checksums_for_bundle(repo, bundle)
|
||||
|
|
@ -1460,10 +1748,7 @@ def iter_resolved_published_releases(
|
|||
|
||||
if published_release_tag:
|
||||
bundle = pinned_published_release_bundle(repo, published_release_tag)
|
||||
if (
|
||||
normalized_requested != "latest"
|
||||
and bundle.upstream_tag != normalized_requested
|
||||
):
|
||||
if not published_release_matches_request(bundle, normalized_requested):
|
||||
raise PrebuiltFallback(
|
||||
"published release "
|
||||
f"{repo}@{published_release_tag} targeted upstream tag {bundle.upstream_tag}, "
|
||||
|
|
@ -1479,10 +1764,7 @@ def iter_resolved_published_releases(
|
|||
skipped_invalid = 0
|
||||
yielded_valid = False
|
||||
for bundle in iter_published_release_bundles(repo):
|
||||
if (
|
||||
normalized_requested != "latest"
|
||||
and bundle.upstream_tag != normalized_requested
|
||||
):
|
||||
if not published_release_matches_request(bundle, normalized_requested):
|
||||
continue
|
||||
matched_any = True
|
||||
try:
|
||||
|
|
@ -1520,6 +1802,7 @@ def iter_resolved_published_releases(
|
|||
def resolve_requested_llama_tag(
|
||||
requested_tag: str | None,
|
||||
published_repo: str = "",
|
||||
published_release_tag: str = "",
|
||||
) -> str:
|
||||
"""Resolve a llama.cpp tag for source-build fallback.
|
||||
|
||||
|
|
@ -1547,6 +1830,7 @@ def resolve_requested_llama_tag(
|
|||
return resolve_published_release(
|
||||
"latest",
|
||||
published_repo,
|
||||
published_release_tag,
|
||||
).bundle.upstream_tag
|
||||
except Exception:
|
||||
pass
|
||||
|
|
@ -1566,6 +1850,125 @@ def resolve_requested_install_tag(
|
|||
).bundle.upstream_tag
|
||||
|
||||
|
||||
def exact_source_archive_hash(
|
||||
checksums: ApprovedReleaseChecksums,
|
||||
) -> ApprovedArtifactHash | None:
|
||||
if not checksums.source_commit:
|
||||
return None
|
||||
return checksums.artifacts.get(
|
||||
exact_source_archive_logical_name(checksums.source_commit)
|
||||
)
|
||||
|
||||
|
||||
def source_clone_url_from_checksums(checksums: ApprovedReleaseChecksums) -> str | None:
|
||||
return source_repo_clone_url(checksums.source_repo, checksums.source_repo_url)
|
||||
|
||||
|
||||
def source_build_plan_for_release(
|
||||
release: ResolvedPublishedRelease,
|
||||
) -> SourceBuildPlan:
|
||||
checksums = release.checksums
|
||||
exact_source = exact_source_archive_hash(checksums)
|
||||
source_repo = checksums.source_repo or release.bundle.source_repo
|
||||
source_repo_url = checksums.source_repo_url or release.bundle.source_repo_url
|
||||
requested_source_ref = (
|
||||
checksums.requested_source_ref or release.bundle.requested_source_ref
|
||||
)
|
||||
resolved_source_ref = (
|
||||
checksums.resolved_source_ref or release.bundle.resolved_source_ref
|
||||
)
|
||||
source_commit = checksums.source_commit or release.bundle.source_commit
|
||||
source_ref_kind = checksums.source_ref_kind or release.bundle.source_ref_kind
|
||||
source_url = source_repo_clone_url(source_repo, source_repo_url)
|
||||
if exact_source is not None and source_url and source_commit:
|
||||
return SourceBuildPlan(
|
||||
source_url = source_url,
|
||||
source_ref = source_commit,
|
||||
source_ref_kind = "commit",
|
||||
compatibility_upstream_tag = release.bundle.upstream_tag,
|
||||
source_repo = source_repo,
|
||||
source_repo_url = source_repo_url,
|
||||
requested_source_ref = requested_source_ref,
|
||||
resolved_source_ref = resolved_source_ref,
|
||||
source_commit = source_commit,
|
||||
)
|
||||
source_ref = checkout_friendly_ref(
|
||||
source_ref_kind, resolved_source_ref or requested_source_ref
|
||||
)
|
||||
if (
|
||||
source_url
|
||||
and source_ref
|
||||
and source_ref_kind in {"tag", "branch", "pull", "commit"}
|
||||
):
|
||||
return SourceBuildPlan(
|
||||
source_url = source_url,
|
||||
source_ref = source_ref,
|
||||
source_ref_kind = source_ref_kind,
|
||||
compatibility_upstream_tag = release.bundle.upstream_tag,
|
||||
source_repo = source_repo,
|
||||
source_repo_url = source_repo_url,
|
||||
requested_source_ref = requested_source_ref,
|
||||
resolved_source_ref = resolved_source_ref,
|
||||
source_commit = source_commit,
|
||||
)
|
||||
return SourceBuildPlan(
|
||||
source_url = source_url_from_repo_slug(UPSTREAM_REPO)
|
||||
or "https://github.com/ggml-org/llama.cpp",
|
||||
source_ref = release.bundle.upstream_tag,
|
||||
source_ref_kind = "tag",
|
||||
compatibility_upstream_tag = release.bundle.upstream_tag,
|
||||
source_repo = source_repo,
|
||||
source_repo_url = source_repo_url,
|
||||
requested_source_ref = requested_source_ref,
|
||||
resolved_source_ref = resolved_source_ref,
|
||||
source_commit = source_commit,
|
||||
)
|
||||
|
||||
|
||||
def resolve_source_build_plan(
|
||||
requested_tag: str | None,
|
||||
published_repo: str,
|
||||
published_release_tag: str = "",
|
||||
) -> SourceBuildPlan:
|
||||
normalized_requested = normalized_requested_llama_tag(requested_tag)
|
||||
if normalized_requested != "latest":
|
||||
try:
|
||||
release = resolve_published_release(
|
||||
normalized_requested,
|
||||
published_repo,
|
||||
published_release_tag,
|
||||
)
|
||||
return source_build_plan_for_release(release)
|
||||
except Exception:
|
||||
pass
|
||||
inferred_kind = infer_source_ref_kind(normalized_requested)
|
||||
return SourceBuildPlan(
|
||||
source_url = "https://github.com/ggml-org/llama.cpp",
|
||||
source_ref = checkout_friendly_ref(inferred_kind, normalized_requested)
|
||||
or normalized_requested,
|
||||
source_ref_kind = inferred_kind,
|
||||
compatibility_upstream_tag = normalized_requested,
|
||||
)
|
||||
|
||||
if published_repo:
|
||||
try:
|
||||
release = resolve_published_release(
|
||||
"latest",
|
||||
published_repo,
|
||||
published_release_tag,
|
||||
)
|
||||
return source_build_plan_for_release(release)
|
||||
except Exception:
|
||||
pass
|
||||
latest_tag = latest_upstream_release_tag()
|
||||
return SourceBuildPlan(
|
||||
source_url = "https://github.com/ggml-org/llama.cpp",
|
||||
source_ref = latest_tag,
|
||||
source_ref_kind = "tag",
|
||||
compatibility_upstream_tag = latest_tag,
|
||||
)
|
||||
|
||||
|
||||
def run_capture(
|
||||
command: list[str],
|
||||
*,
|
||||
|
|
@ -1883,25 +2286,31 @@ def windows_cuda_attempts(
|
|||
attempts: list[AssetChoice] = []
|
||||
for runtime_line in runtime_order:
|
||||
runtime = runtime_by_line[runtime_line]
|
||||
upstream_name = f"llama-{llama_tag}-bin-win-cuda-{runtime}-x64.zip"
|
||||
asset_url = upstream_assets.get(upstream_name)
|
||||
if not asset_url:
|
||||
selected_name = None
|
||||
asset_url = None
|
||||
for candidate_name in windows_cuda_upstream_asset_names(llama_tag, runtime):
|
||||
asset_url = upstream_assets.get(candidate_name)
|
||||
if asset_url:
|
||||
selected_name = candidate_name
|
||||
break
|
||||
if not asset_url or not selected_name:
|
||||
selection_log.append(
|
||||
f"windows_cuda_selection: skip missing asset {upstream_name}"
|
||||
"windows_cuda_selection: skip missing assets "
|
||||
+ ",".join(windows_cuda_upstream_asset_names(llama_tag, runtime))
|
||||
)
|
||||
continue
|
||||
attempts.append(
|
||||
AssetChoice(
|
||||
repo = UPSTREAM_REPO,
|
||||
tag = llama_tag,
|
||||
name = upstream_name,
|
||||
name = selected_name,
|
||||
url = asset_url,
|
||||
source_label = "upstream",
|
||||
install_kind = "windows-cuda",
|
||||
runtime_line = runtime_line,
|
||||
selection_log = list(selection_log)
|
||||
+ [
|
||||
f"windows_cuda_selection: selected {upstream_name} runtime={runtime}"
|
||||
f"windows_cuda_selection: selected {selected_name} runtime={runtime}"
|
||||
],
|
||||
)
|
||||
)
|
||||
|
|
@ -2353,18 +2762,26 @@ def copy_directory_contents(source_dir: Path, destination: Path) -> None:
|
|||
|
||||
|
||||
def hydrate_source_tree(
|
||||
upstream_tag: str,
|
||||
source_ref: str,
|
||||
install_dir: Path,
|
||||
work_dir: Path,
|
||||
*,
|
||||
source_repo: str = UPSTREAM_REPO,
|
||||
expected_sha256: str,
|
||||
source_label: str | None = None,
|
||||
exact_source: bool = False,
|
||||
) -> None:
|
||||
archive_path = work_dir / f"llama.cpp-source-{upstream_tag}.tar.gz"
|
||||
source_urls = upstream_source_archive_urls(upstream_tag)
|
||||
archive_path = work_dir / f"llama.cpp-source-{source_ref}.tar.gz"
|
||||
source_urls = (
|
||||
commit_source_archive_urls(source_repo, source_ref)
|
||||
if exact_source
|
||||
else upstream_source_archive_urls(source_ref)
|
||||
)
|
||||
label = source_label or f"llama.cpp source tree for {source_ref}"
|
||||
extract_dir = Path(tempfile.mkdtemp(prefix = "source-extract-", dir = work_dir))
|
||||
|
||||
try:
|
||||
log(f"downloading llama.cpp source tree for upstream tag {upstream_tag}")
|
||||
log(f"downloading {label}")
|
||||
last_exc: Exception | None = None
|
||||
downloaded = False
|
||||
for index, source_url in enumerate(source_urls):
|
||||
|
|
@ -2377,7 +2794,7 @@ def hydrate_source_tree(
|
|||
source_url,
|
||||
archive_path,
|
||||
expected_sha256 = expected_sha256,
|
||||
label = f"llama.cpp source tree for {upstream_tag}",
|
||||
label = label,
|
||||
)
|
||||
downloaded = True
|
||||
break
|
||||
|
|
@ -2410,9 +2827,7 @@ def hydrate_source_tree(
|
|||
except PrebuiltFallback:
|
||||
raise
|
||||
except Exception as exc:
|
||||
raise PrebuiltFallback(
|
||||
f"failed to hydrate upstream llama.cpp source tree for {upstream_tag}: {exc}"
|
||||
) from exc
|
||||
raise PrebuiltFallback(f"failed to hydrate {label}: {exc}") from exc
|
||||
finally:
|
||||
remove_tree(extract_dir)
|
||||
|
||||
|
|
@ -3451,10 +3866,32 @@ def apply_approved_hashes(
|
|||
attempts: Iterable[AssetChoice],
|
||||
checksums: ApprovedReleaseChecksums,
|
||||
) -> list[AssetChoice]:
|
||||
def approved_hash_for_attempt(attempt: AssetChoice) -> ApprovedArtifactHash | None:
|
||||
approved = checksums.artifacts.get(attempt.name)
|
||||
if approved is not None:
|
||||
return approved
|
||||
if (
|
||||
isinstance(attempt.tag, str)
|
||||
and attempt.tag
|
||||
and attempt.tag != checksums.upstream_tag
|
||||
and attempt.name.startswith("llama-")
|
||||
):
|
||||
legacy_prefix = f"llama-{attempt.tag}-"
|
||||
compatibility_prefix = f"llama-{checksums.upstream_tag}-"
|
||||
compatibility_name = (
|
||||
attempt.name.replace(legacy_prefix, compatibility_prefix, 1)
|
||||
if attempt.name.startswith(legacy_prefix)
|
||||
else attempt.name
|
||||
)
|
||||
approved = checksums.artifacts.get(compatibility_name)
|
||||
if approved is not None:
|
||||
return approved
|
||||
return None
|
||||
|
||||
approved_attempts: list[AssetChoice] = []
|
||||
missing_assets: list[str] = []
|
||||
for attempt in attempts:
|
||||
approved = checksums.artifacts.get(attempt.name)
|
||||
approved = approved_hash_for_attempt(attempt)
|
||||
if approved is None:
|
||||
missing_assets.append(attempt.name)
|
||||
continue
|
||||
|
|
@ -3481,6 +3918,39 @@ def require_approved_source_hash(
|
|||
return approved_source
|
||||
|
||||
|
||||
def preferred_source_archive(
|
||||
checksums: ApprovedReleaseChecksums, llama_tag: str
|
||||
) -> tuple[str, str, ApprovedArtifactHash, bool]:
|
||||
exact_source = exact_source_archive_hash(checksums)
|
||||
exact_repo = repo_slug_from_source(checksums.source_repo) or repo_slug_from_source(
|
||||
checksums.source_repo_url
|
||||
)
|
||||
if exact_source is not None and exact_repo and checksums.source_commit:
|
||||
return (
|
||||
exact_repo,
|
||||
checksums.source_commit,
|
||||
exact_source,
|
||||
True,
|
||||
)
|
||||
legacy = require_approved_source_hash(checksums, llama_tag)
|
||||
return (
|
||||
UPSTREAM_REPO,
|
||||
llama_tag,
|
||||
legacy,
|
||||
False,
|
||||
)
|
||||
|
||||
|
||||
def selected_source_archive_metadata(
|
||||
checksums: ApprovedReleaseChecksums,
|
||||
llama_tag: str,
|
||||
) -> tuple[str, str | None]:
|
||||
_source_repo, _source_ref, source_archive, _exact_source = preferred_source_archive(
|
||||
checksums, llama_tag
|
||||
)
|
||||
return source_archive.asset_name, source_archive.sha256
|
||||
|
||||
|
||||
def resolve_install_attempts(
|
||||
llama_tag: str,
|
||||
host: HostInfo,
|
||||
|
|
@ -3583,10 +4053,10 @@ def write_prebuilt_metadata(
|
|||
approved_checksums: ApprovedReleaseChecksums,
|
||||
prebuilt_fallback_used: bool,
|
||||
) -> None:
|
||||
source_archive = approved_checksums.artifacts.get(
|
||||
source_archive_logical_name(llama_tag)
|
||||
source_asset_name, source_sha256 = selected_source_archive_metadata(
|
||||
approved_checksums,
|
||||
llama_tag,
|
||||
)
|
||||
source_sha256 = source_archive.sha256 if source_archive is not None else None
|
||||
fingerprint_payload = {
|
||||
"published_repo": approved_checksums.repo,
|
||||
"release_tag": release_tag,
|
||||
|
|
@ -3594,6 +4064,7 @@ def write_prebuilt_metadata(
|
|||
"asset": choice.name,
|
||||
"asset_sha256": choice.expected_sha256,
|
||||
"source": choice.source_label,
|
||||
"source_asset": source_asset_name,
|
||||
"source_sha256": source_sha256,
|
||||
"runtime_line": choice.runtime_line,
|
||||
"bundle_profile": choice.bundle_profile,
|
||||
|
|
@ -3612,8 +4083,15 @@ def write_prebuilt_metadata(
|
|||
"asset": choice.name,
|
||||
"asset_sha256": choice.expected_sha256,
|
||||
"source": choice.source_label,
|
||||
"source_asset": source_asset_name,
|
||||
"source_sha256": source_sha256,
|
||||
"source_commit": approved_checksums.source_commit,
|
||||
"source_commit_short": approved_checksums.source_commit_short,
|
||||
"source_repo": approved_checksums.source_repo,
|
||||
"source_repo_url": approved_checksums.source_repo_url,
|
||||
"source_ref_kind": approved_checksums.source_ref_kind,
|
||||
"requested_source_ref": approved_checksums.requested_source_ref,
|
||||
"resolved_source_ref": approved_checksums.resolved_source_ref,
|
||||
"bundle_profile": choice.bundle_profile,
|
||||
"runtime_line": choice.runtime_line,
|
||||
"coverage_class": choice.coverage_class,
|
||||
|
|
@ -3635,10 +4113,10 @@ def expected_install_fingerprint(
|
|||
) -> str | None:
|
||||
if not choice.expected_sha256:
|
||||
return None
|
||||
source_archive = approved_checksums.artifacts.get(
|
||||
source_archive_logical_name(llama_tag)
|
||||
source_asset_name, source_sha256 = selected_source_archive_metadata(
|
||||
approved_checksums,
|
||||
llama_tag,
|
||||
)
|
||||
source_sha256 = source_archive.sha256 if source_archive is not None else None
|
||||
payload = {
|
||||
"published_repo": approved_checksums.repo,
|
||||
"release_tag": release_tag,
|
||||
|
|
@ -3646,6 +4124,7 @@ def expected_install_fingerprint(
|
|||
"asset": choice.name,
|
||||
"asset_sha256": choice.expected_sha256,
|
||||
"source": choice.source_label,
|
||||
"source_asset": source_asset_name,
|
||||
"source_sha256": source_sha256,
|
||||
"runtime_line": choice.runtime_line,
|
||||
"bundle_profile": choice.bundle_profile,
|
||||
|
|
@ -3817,19 +4296,27 @@ def validate_prebuilt_choice(
|
|||
prebuilt_fallback_used: bool,
|
||||
quantized_path: Path,
|
||||
) -> tuple[Path, Path]:
|
||||
source_archive = approved_checksums.artifacts.get(
|
||||
source_archive_logical_name(llama_tag)
|
||||
source_repo, source_ref, source_archive, exact_source = preferred_source_archive(
|
||||
approved_checksums, llama_tag
|
||||
)
|
||||
if source_archive is None:
|
||||
raise PrebuiltFallback(
|
||||
f"approved checksum asset did not contain source archive {source_archive_logical_name(llama_tag)}"
|
||||
if exact_source:
|
||||
log(
|
||||
f"hydrating exact llama.cpp source for {source_repo}@{source_ref} into {install_dir}"
|
||||
)
|
||||
log(f"hydrating upstream llama.cpp source for {llama_tag} into {install_dir}")
|
||||
else:
|
||||
log(f"hydrating upstream llama.cpp source for {llama_tag} into {install_dir}")
|
||||
hydrate_source_tree(
|
||||
llama_tag,
|
||||
source_ref,
|
||||
install_dir,
|
||||
work_dir,
|
||||
source_repo = source_repo,
|
||||
expected_sha256 = source_archive.sha256,
|
||||
source_label = (
|
||||
f"llama.cpp source tree for {source_repo}@{source_ref}"
|
||||
if exact_source
|
||||
else f"llama.cpp source tree for {llama_tag}"
|
||||
),
|
||||
exact_source = exact_source,
|
||||
)
|
||||
log(f"overlaying prebuilt bundle {choice.name} into {install_dir}")
|
||||
server_path, quantize_path = install_from_archives(
|
||||
|
|
@ -4087,30 +4574,103 @@ def parse_args() -> argparse.Namespace:
|
|||
"selected by the current published-release policy."
|
||||
),
|
||||
)
|
||||
resolve_group.add_argument(
|
||||
"--resolve-source-build",
|
||||
nargs = "?",
|
||||
const = "latest",
|
||||
help = ("Resolve the source-build fallback plan."),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output-format",
|
||||
choices = ("plain", "json"),
|
||||
default = "plain",
|
||||
help = "Resolver output format. Defaults to plain.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def emit_resolver_output(payload: dict[str, Any], *, output_format: str) -> None:
|
||||
if output_format == "json":
|
||||
print(json.dumps(payload, sort_keys = True))
|
||||
return
|
||||
if "llama_tag" in payload:
|
||||
print(payload["llama_tag"])
|
||||
return
|
||||
if {
|
||||
"source_url",
|
||||
"source_ref_kind",
|
||||
"source_ref",
|
||||
}.issubset(payload):
|
||||
print(
|
||||
"\t".join(
|
||||
(
|
||||
str(payload["source_url"]),
|
||||
str(payload["source_ref_kind"]),
|
||||
str(payload["source_ref"]),
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
print(json.dumps(payload, sort_keys = True))
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
if args.resolve_llama_tag is not None:
|
||||
# Pass published_repo so the resolver prefers the Unsloth release tag
|
||||
# (tested/approved) over the upstream ggml-org bleeding-edge tag.
|
||||
print(resolve_requested_llama_tag(args.resolve_llama_tag, args.published_repo))
|
||||
resolved = resolve_requested_llama_tag(
|
||||
args.resolve_llama_tag,
|
||||
args.published_repo,
|
||||
args.published_release_tag or "",
|
||||
)
|
||||
emit_resolver_output(
|
||||
{
|
||||
"requested_tag": normalized_requested_llama_tag(args.resolve_llama_tag),
|
||||
"llama_tag": resolved,
|
||||
},
|
||||
output_format = args.output_format,
|
||||
)
|
||||
return EXIT_SUCCESS
|
||||
|
||||
if args.resolve_install_tag is not None:
|
||||
print(
|
||||
resolve_requested_install_tag(
|
||||
args.resolve_install_tag,
|
||||
args.published_release_tag or "",
|
||||
args.published_repo,
|
||||
)
|
||||
resolved = resolve_requested_install_tag(
|
||||
args.resolve_install_tag,
|
||||
args.published_release_tag or "",
|
||||
args.published_repo,
|
||||
)
|
||||
emit_resolver_output(
|
||||
{
|
||||
"requested_tag": normalized_requested_llama_tag(
|
||||
args.resolve_install_tag
|
||||
),
|
||||
"llama_tag": resolved,
|
||||
},
|
||||
output_format = args.output_format,
|
||||
)
|
||||
return EXIT_SUCCESS
|
||||
|
||||
if args.resolve_source_build is not None:
|
||||
plan = resolve_source_build_plan(
|
||||
args.resolve_source_build,
|
||||
args.published_repo,
|
||||
args.published_release_tag or "",
|
||||
)
|
||||
emit_resolver_output(
|
||||
{
|
||||
"requested_tag": normalized_requested_llama_tag(
|
||||
args.resolve_source_build
|
||||
),
|
||||
"source_url": plan.source_url,
|
||||
"source_ref_kind": plan.source_ref_kind,
|
||||
"source_ref": plan.source_ref,
|
||||
"compatibility_upstream_tag": plan.compatibility_upstream_tag,
|
||||
},
|
||||
output_format = args.output_format,
|
||||
)
|
||||
return EXIT_SUCCESS
|
||||
|
||||
if not args.install_dir:
|
||||
raise SystemExit(
|
||||
"install_llama_prebuilt.py: --install-dir is required unless --resolve-llama-tag or --resolve-install-tag is used"
|
||||
"install_llama_prebuilt.py: --install-dir is required unless --resolve-llama-tag, --resolve-install-tag, or --resolve-source-build is used"
|
||||
)
|
||||
install_prebuilt(
|
||||
install_dir = Path(args.install_dir).expanduser().resolve(),
|
||||
|
|
|
|||
145
studio/setup.ps1
145
studio/setup.ps1
|
|
@ -1604,6 +1604,9 @@ $LlamaPr = if ($env:UNSLOTH_LLAMA_PR) { $env:UNSLOTH_LLAMA_PR.Trim() } else { ""
|
|||
$LlamaPrForce = if ($env:UNSLOTH_LLAMA_PR_FORCE) { $env:UNSLOTH_LLAMA_PR_FORCE.Trim() } else { $DefaultLlamaPrForce }
|
||||
$LlamaSource = if ($env:UNSLOTH_LLAMA_SOURCE) { $env:UNSLOTH_LLAMA_SOURCE.Trim() } else { $DefaultLlamaSource }
|
||||
if ($LlamaSource.EndsWith('.git')) { $LlamaSource = $LlamaSource.Substring(0, $LlamaSource.Length - 4) }
|
||||
$ResolvedSourceUrl = $LlamaSource
|
||||
$ResolvedSourceRef = $RequestedLlamaTag
|
||||
$ResolvedSourceRefKind = "tag"
|
||||
|
||||
if ($LlamaSource -ne "https://github.com/ggml-org/llama.cpp") {
|
||||
step "llama.cpp" "custom source: $LlamaSource -- forcing source build" "Yellow"
|
||||
|
|
@ -1623,6 +1626,9 @@ if ($LlamaPr) {
|
|||
}
|
||||
step "llama.cpp" "UNSLOTH_LLAMA_PR=$LlamaPr -- will build from PR head" "Yellow"
|
||||
$ResolvedLlamaTag = "pr-$LlamaPr"
|
||||
$ResolvedSourceUrl = $LlamaSource
|
||||
$ResolvedSourceRef = "pr-$LlamaPr"
|
||||
$ResolvedSourceRefKind = "pull"
|
||||
$NeedLlamaSourceBuild = $true
|
||||
$SkipPrebuiltInstall = $true
|
||||
} elseif ($SkipPrebuiltInstall) {
|
||||
|
|
@ -1630,12 +1636,16 @@ if ($LlamaPr) {
|
|||
# prebuilt release resolution. When building from a custom fork, the fork
|
||||
# may not carry upstream bNNNN tags.
|
||||
if ($LlamaSource -eq "https://github.com/ggml-org/llama.cpp") {
|
||||
$resolveTagArgs = @("--resolve-llama-tag", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo)
|
||||
$resolveTagArgs = @("--resolve-llama-tag", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo, "--output-format", "json")
|
||||
if ($env:UNSLOTH_LLAMA_RELEASE_TAG) { $resolveTagArgs += @("--published-release-tag", $env:UNSLOTH_LLAMA_RELEASE_TAG) }
|
||||
$fallbackOutput = & python "$PSScriptRoot\install_llama_prebuilt.py" @resolveTagArgs 2>$null
|
||||
$fallbackExit = $LASTEXITCODE
|
||||
$ResolvedLlamaTag = if ($fallbackExit -eq 0 -and $fallbackOutput) {
|
||||
($fallbackOutput | Select-Object -Last 1).ToString().Trim()
|
||||
try {
|
||||
(($fallbackOutput | Out-String) | ConvertFrom-Json).llama_tag
|
||||
} catch {
|
||||
$RequestedLlamaTag
|
||||
}
|
||||
} else {
|
||||
$RequestedLlamaTag
|
||||
}
|
||||
|
|
@ -1643,30 +1653,42 @@ if ($LlamaPr) {
|
|||
$ResolvedLlamaTag = $RequestedLlamaTag
|
||||
}
|
||||
} else {
|
||||
$resolveInstallArgs = @("--resolve-install-tag", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo)
|
||||
$resolveInstallArgs = @("--resolve-install-tag", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo, "--output-format", "json")
|
||||
if ($env:UNSLOTH_LLAMA_RELEASE_TAG) { $resolveInstallArgs += @("--published-release-tag", $env:UNSLOTH_LLAMA_RELEASE_TAG) }
|
||||
$resolveOutput = & python "$PSScriptRoot\install_llama_prebuilt.py" @resolveInstallArgs 2>&1
|
||||
$resolveErrorLog = New-TemporaryFile
|
||||
$resolveOutput = & python "$PSScriptRoot\install_llama_prebuilt.py" @resolveInstallArgs 2>$resolveErrorLog
|
||||
$resolveExit = $LASTEXITCODE
|
||||
$ResolvedLlamaTag = if ($resolveOutput) { ($resolveOutput | Select-Object -Last 1).ToString().Trim() } else { "" }
|
||||
$ResolvedLlamaTag = if ($resolveOutput) {
|
||||
try {
|
||||
(($resolveOutput | Out-String) | ConvertFrom-Json).llama_tag
|
||||
} catch {
|
||||
""
|
||||
}
|
||||
} else { "" }
|
||||
if ($resolveExit -ne 0 -or [string]::IsNullOrWhiteSpace($ResolvedLlamaTag)) {
|
||||
Write-Host ""
|
||||
substep "Failed to resolve a published llama.cpp release via $HelperReleaseRepo" "Yellow"
|
||||
Write-LlamaFailureLog -Output ($resolveOutput | Out-String)
|
||||
Write-LlamaFailureLog -Output (Get-Content -Raw $resolveErrorLog)
|
||||
# Resolve the llama.cpp tag for source-build fallback. Pass --published-repo
|
||||
# so the resolver prefers the latest usable Unsloth-published upstream tag
|
||||
# before falling back to the bleeding-edge ggml-org/llama.cpp tag.
|
||||
$resolveFallbackArgs = @("--resolve-llama-tag", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo)
|
||||
$resolveFallbackArgs = @("--resolve-llama-tag", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo, "--output-format", "json")
|
||||
if ($env:UNSLOTH_LLAMA_RELEASE_TAG) { $resolveFallbackArgs += @("--published-release-tag", $env:UNSLOTH_LLAMA_RELEASE_TAG) }
|
||||
$fallbackOutput = & python "$PSScriptRoot\install_llama_prebuilt.py" @resolveFallbackArgs 2>$null
|
||||
$fallbackExit = $LASTEXITCODE
|
||||
$ResolvedLlamaTag = if ($fallbackExit -eq 0 -and $fallbackOutput) {
|
||||
($fallbackOutput | Select-Object -Last 1).ToString().Trim()
|
||||
try {
|
||||
(($fallbackOutput | Out-String) | ConvertFrom-Json).llama_tag
|
||||
} catch {
|
||||
$RequestedLlamaTag
|
||||
}
|
||||
} else {
|
||||
$RequestedLlamaTag
|
||||
}
|
||||
$NeedLlamaSourceBuild = $true
|
||||
$SkipPrebuiltInstall = $true
|
||||
}
|
||||
Remove-Item $resolveErrorLog -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
|
|
@ -1875,14 +1897,34 @@ if (-not $NeedLlamaSourceBuild) {
|
|||
[Environment]::SetEnvironmentVariable('CudaToolkitDir', "$CudaToolkitRoot\", 'Process')
|
||||
}
|
||||
|
||||
if (-not $LlamaPr) {
|
||||
if ($LlamaSource -eq "https://github.com/ggml-org/llama.cpp") {
|
||||
$resolveSourceArgs = @("--resolve-source-build", $RequestedLlamaTag, "--published-repo", $HelperReleaseRepo, "--output-format", "json")
|
||||
if ($env:UNSLOTH_LLAMA_RELEASE_TAG) { $resolveSourceArgs += @("--published-release-tag", $env:UNSLOTH_LLAMA_RELEASE_TAG) }
|
||||
$sourcePlanOutput = & python "$PSScriptRoot\install_llama_prebuilt.py" @resolveSourceArgs 2>$null
|
||||
$sourcePlanExit = $LASTEXITCODE
|
||||
if ($sourcePlanExit -eq 0 -and $sourcePlanOutput) {
|
||||
try {
|
||||
$sourcePlan = ($sourcePlanOutput | Out-String) | ConvertFrom-Json
|
||||
$ResolvedSourceUrl = $sourcePlan.source_url
|
||||
$ResolvedSourceRefKind = $sourcePlan.source_ref_kind
|
||||
$ResolvedSourceRef = $sourcePlan.source_ref
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($ResolvedSourceUrl)) { $ResolvedSourceUrl = $LlamaSource }
|
||||
if ([string]::IsNullOrWhiteSpace($ResolvedSourceRef)) { $ResolvedSourceRef = $ResolvedLlamaTag }
|
||||
}
|
||||
|
||||
# -- Step A: Clone or pull llama.cpp --
|
||||
|
||||
$UseConcreteRef = ($ResolvedLlamaTag -ne "latest" -and -not [string]::IsNullOrWhiteSpace($ResolvedLlamaTag))
|
||||
$UseConcreteRef = ($ResolvedSourceRef -ne "latest" -and -not [string]::IsNullOrWhiteSpace($ResolvedSourceRef))
|
||||
|
||||
if (Test-Path (Join-Path $LlamaCppDir ".git")) {
|
||||
Write-Host " Syncing llama.cpp to $ResolvedLlamaTag..." -ForegroundColor Gray
|
||||
Write-Host " Syncing llama.cpp to $ResolvedSourceRef..." -ForegroundColor Gray
|
||||
# Always sync the remote URL so switching between default/fork sources works
|
||||
Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir remote set-url origin "$LlamaSource.git" } | Out-Null
|
||||
Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir remote set-url origin "$ResolvedSourceUrl.git" } | Out-Null
|
||||
if ($LlamaPr) {
|
||||
$gitFetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir fetch --depth 1 origin "pull/$LlamaPr/head" }
|
||||
if ($gitFetchExit -ne 0) {
|
||||
|
|
@ -1897,8 +1939,34 @@ if (-not $NeedLlamaSourceBuild) {
|
|||
Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir clean -fdx } | Out-Null
|
||||
}
|
||||
}
|
||||
} elseif ($ResolvedSourceRefKind -eq "pull") {
|
||||
$gitFetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir fetch --depth 1 origin $ResolvedSourceRef }
|
||||
if ($gitFetchExit -ne 0) {
|
||||
substep "git fetch failed -- using existing source" "Yellow"
|
||||
} else {
|
||||
$gitCheckoutExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir checkout -B unsloth-llama-build FETCH_HEAD }
|
||||
if ($gitCheckoutExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git checkout"
|
||||
} else {
|
||||
Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir clean -fdx } | Out-Null
|
||||
}
|
||||
}
|
||||
} elseif ($ResolvedSourceRefKind -eq "commit") {
|
||||
$gitFetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir fetch --depth 1 origin $ResolvedSourceRef }
|
||||
if ($gitFetchExit -ne 0) {
|
||||
substep "git fetch failed -- using existing source" "Yellow"
|
||||
} else {
|
||||
$gitCheckoutExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir checkout -B unsloth-llama-build FETCH_HEAD }
|
||||
if ($gitCheckoutExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git checkout"
|
||||
} else {
|
||||
Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir clean -fdx } | Out-Null
|
||||
}
|
||||
}
|
||||
} elseif ($UseConcreteRef) {
|
||||
$gitFetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir fetch --depth 1 origin $ResolvedLlamaTag }
|
||||
$gitFetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $LlamaCppDir fetch --depth 1 origin $ResolvedSourceRef }
|
||||
if ($gitFetchExit -ne 0) {
|
||||
substep "git fetch failed -- using existing source" "Yellow"
|
||||
} else {
|
||||
|
|
@ -1925,8 +1993,9 @@ if (-not $NeedLlamaSourceBuild) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host " Cloning llama.cpp @ $ResolvedLlamaTag..." -ForegroundColor Gray
|
||||
Write-Host " Cloning llama.cpp @ $ResolvedSourceRef..." -ForegroundColor Gray
|
||||
$buildTmp = "$LlamaCppDir.build.$PID"
|
||||
$null = New-Item -ItemType Directory -Force -Path (Split-Path $LlamaCppDir -Parent)
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
if ($LlamaPr) {
|
||||
$cloneExit = Invoke-SetupCommand -AlwaysQuiet { git clone --depth 1 "$LlamaSource.git" $buildTmp }
|
||||
|
|
@ -1951,12 +2020,58 @@ if (-not $NeedLlamaSourceBuild) {
|
|||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
}
|
||||
} elseif ($ResolvedSourceRefKind -eq "pull") {
|
||||
$cloneExit = Invoke-SetupCommand -AlwaysQuiet { git clone --depth 1 "$ResolvedSourceUrl.git" $buildTmp }
|
||||
if ($cloneExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git clone"
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
if ($BuildOk) {
|
||||
$fetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $buildTmp fetch --depth 1 origin $ResolvedSourceRef }
|
||||
if ($fetchExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git fetch source PR ref"
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
}
|
||||
if ($BuildOk) {
|
||||
$checkoutExit = Invoke-SetupCommand -AlwaysQuiet { git -C $buildTmp checkout -B unsloth-llama-build FETCH_HEAD }
|
||||
if ($checkoutExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git checkout source PR ref"
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
}
|
||||
} elseif ($ResolvedSourceRefKind -eq "commit") {
|
||||
$cloneExit = Invoke-SetupCommand -AlwaysQuiet { git clone --depth 1 "$ResolvedSourceUrl.git" $buildTmp }
|
||||
if ($cloneExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git clone"
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
if ($BuildOk) {
|
||||
$fetchExit = Invoke-SetupCommand -AlwaysQuiet { git -C $buildTmp fetch --depth 1 origin $ResolvedSourceRef }
|
||||
if ($fetchExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git fetch source commit"
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
}
|
||||
if ($BuildOk) {
|
||||
$checkoutExit = Invoke-SetupCommand -AlwaysQuiet { git -C $buildTmp checkout -B unsloth-llama-build FETCH_HEAD }
|
||||
if ($checkoutExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
$FailedStep = "git checkout source commit"
|
||||
if (Test-Path $buildTmp) { Remove-Item -Recurse -Force $buildTmp }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$cloneArgs = @("clone", "--depth", "1")
|
||||
if ($UseConcreteRef) {
|
||||
$cloneArgs += @("--branch", $ResolvedLlamaTag)
|
||||
$cloneArgs += @("--branch", $ResolvedSourceRef)
|
||||
}
|
||||
$cloneArgs += @("$LlamaSource.git", $buildTmp)
|
||||
$cloneArgs += @("$ResolvedSourceUrl.git", $buildTmp)
|
||||
$cloneExit = Invoke-SetupCommand -AlwaysQuiet { git @cloneArgs }
|
||||
if ($cloneExit -ne 0) {
|
||||
$BuildOk = $false
|
||||
|
|
|
|||
102
studio/setup.sh
102
studio/setup.sh
|
|
@ -485,6 +485,9 @@ _LLAMA_PR="${UNSLOTH_LLAMA_PR:-}"
|
|||
_LLAMA_PR_FORCE="${UNSLOTH_LLAMA_PR_FORCE:-${_DEFAULT_LLAMA_PR_FORCE}}"
|
||||
_LLAMA_SOURCE="${UNSLOTH_LLAMA_SOURCE:-${_DEFAULT_LLAMA_SOURCE}}"
|
||||
_LLAMA_SOURCE="${_LLAMA_SOURCE%.git}" # normalize: strip trailing .git
|
||||
_RESOLVED_SOURCE_URL="$_LLAMA_SOURCE"
|
||||
_RESOLVED_SOURCE_REF="$_REQUESTED_LLAMA_TAG"
|
||||
_RESOLVED_SOURCE_REF_KIND="tag"
|
||||
|
||||
# Non-default source URL forces source build (fork has different code than prebuilt).
|
||||
if [ "$_LLAMA_SOURCE" != "https://github.com/ggml-org/llama.cpp" ]; then
|
||||
|
|
@ -507,6 +510,9 @@ if [ -n "$_LLAMA_PR" ]; then
|
|||
fi
|
||||
step "llama.cpp" "UNSLOTH_LLAMA_PR=$_LLAMA_PR -- will build from PR head" "$C_WARN"
|
||||
_RESOLVED_LLAMA_TAG="pr-$_LLAMA_PR"
|
||||
_RESOLVED_SOURCE_URL="$_LLAMA_SOURCE"
|
||||
_RESOLVED_SOURCE_REF="pr-$_LLAMA_PR"
|
||||
_RESOLVED_SOURCE_REF_KIND="pull"
|
||||
_NEED_LLAMA_SOURCE_BUILD=true
|
||||
_SKIP_PREBUILT_INSTALL=true
|
||||
elif [ "${_SKIP_PREBUILT_INSTALL:-false}" = true ]; then
|
||||
|
|
@ -516,14 +522,22 @@ elif [ "${_SKIP_PREBUILT_INSTALL:-false}" = true ]; then
|
|||
# only when the source is the default ggml-org repo.
|
||||
if [ "$_LLAMA_SOURCE" = "https://github.com/ggml-org/llama.cpp" ]; then
|
||||
_RESOLVE_TAG_ARGS=(--resolve-llama-tag "$_REQUESTED_LLAMA_TAG" --published-repo "$_HELPER_RELEASE_REPO")
|
||||
_RESOLVE_TAG_ARGS+=(--output-format json)
|
||||
if [ -n "${UNSLOTH_LLAMA_RELEASE_TAG:-}" ]; then
|
||||
_RESOLVE_TAG_ARGS+=(--published-release-tag "$UNSLOTH_LLAMA_RELEASE_TAG")
|
||||
fi
|
||||
set +e
|
||||
_RESOLVED_LLAMA_TAG="$(python "$SCRIPT_DIR/install_llama_prebuilt.py" "${_RESOLVE_TAG_ARGS[@]}" 2>/dev/null)"
|
||||
_RESOLVE_TAG_JSON="$(python "$SCRIPT_DIR/install_llama_prebuilt.py" "${_RESOLVE_TAG_ARGS[@]}" 2>/dev/null)"
|
||||
_RESOLVE_UPSTREAM_STATUS=$?
|
||||
set -e
|
||||
if [ "$_RESOLVE_UPSTREAM_STATUS" -ne 0 ] || [ -z "$_RESOLVED_LLAMA_TAG" ]; then
|
||||
if [ "$_RESOLVE_UPSTREAM_STATUS" -eq 0 ] && [ -n "${_RESOLVE_TAG_JSON:-}" ]; then
|
||||
_RESOLVED_LLAMA_TAG="$(
|
||||
printf '%s' "$_RESOLVE_TAG_JSON" | python -c 'import json,sys; print(json.load(sys.stdin).get("llama_tag",""))' 2>/dev/null || true
|
||||
)"
|
||||
else
|
||||
_RESOLVED_LLAMA_TAG=""
|
||||
fi
|
||||
if [ -z "$_RESOLVED_LLAMA_TAG" ]; then
|
||||
_RESOLVED_LLAMA_TAG="$_REQUESTED_LLAMA_TAG"
|
||||
fi
|
||||
else
|
||||
|
|
@ -531,17 +545,22 @@ elif [ "${_SKIP_PREBUILT_INSTALL:-false}" = true ]; then
|
|||
fi
|
||||
else
|
||||
_RESOLVE_INSTALL_ARGS=(--resolve-install-tag "$_REQUESTED_LLAMA_TAG" --published-repo "$_HELPER_RELEASE_REPO")
|
||||
_RESOLVE_INSTALL_ARGS+=(--output-format json)
|
||||
if [ -n "${UNSLOTH_LLAMA_RELEASE_TAG:-}" ]; then
|
||||
_RESOLVE_INSTALL_ARGS+=(--published-release-tag "$UNSLOTH_LLAMA_RELEASE_TAG")
|
||||
fi
|
||||
_RESOLVE_LLAMA_LOG="$(mktemp)"
|
||||
set +e
|
||||
python "$SCRIPT_DIR/install_llama_prebuilt.py" \
|
||||
"${_RESOLVE_INSTALL_ARGS[@]}" >"$_RESOLVE_LLAMA_LOG" 2>&1
|
||||
_RESOLVE_INSTALL_JSON="$(
|
||||
python "$SCRIPT_DIR/install_llama_prebuilt.py" \
|
||||
"${_RESOLVE_INSTALL_ARGS[@]}" 2>"$_RESOLVE_LLAMA_LOG"
|
||||
)"
|
||||
_RESOLVE_LLAMA_STATUS=$?
|
||||
set -e
|
||||
if [ "$_RESOLVE_LLAMA_STATUS" -eq 0 ]; then
|
||||
_RESOLVED_LLAMA_TAG="$(tail -n 1 "$_RESOLVE_LLAMA_LOG" | tr -d '\r')"
|
||||
_RESOLVED_LLAMA_TAG="$(
|
||||
printf '%s' "${_RESOLVE_INSTALL_JSON:-}" | python -c 'import json,sys; print(json.load(sys.stdin).get("llama_tag",""))' 2>/dev/null || true
|
||||
)"
|
||||
else
|
||||
_RESOLVED_LLAMA_TAG=""
|
||||
fi
|
||||
|
|
@ -553,13 +572,21 @@ else
|
|||
# so the resolver prefers the latest usable Unsloth-published upstream tag
|
||||
# before falling back to the bleeding-edge ggml-org/llama.cpp tag.
|
||||
_RESOLVE_FALLBACK_ARGS=(--resolve-llama-tag "$_REQUESTED_LLAMA_TAG" --published-repo "$_HELPER_RELEASE_REPO")
|
||||
_RESOLVE_FALLBACK_ARGS+=(--output-format json)
|
||||
if [ -n "${UNSLOTH_LLAMA_RELEASE_TAG:-}" ]; then
|
||||
_RESOLVE_FALLBACK_ARGS+=(--published-release-tag "$UNSLOTH_LLAMA_RELEASE_TAG")
|
||||
fi
|
||||
_RESOLVED_LLAMA_TAG="$(python "$SCRIPT_DIR/install_llama_prebuilt.py" "${_RESOLVE_FALLBACK_ARGS[@]}" 2>/dev/null)"
|
||||
_RESOLVE_FALLBACK_JSON="$(python "$SCRIPT_DIR/install_llama_prebuilt.py" "${_RESOLVE_FALLBACK_ARGS[@]}" 2>/dev/null)"
|
||||
_RESOLVE_UPSTREAM_STATUS=$?
|
||||
set -e
|
||||
if [ "$_RESOLVE_UPSTREAM_STATUS" -ne 0 ] || [ -z "$_RESOLVED_LLAMA_TAG" ]; then
|
||||
if [ "$_RESOLVE_UPSTREAM_STATUS" -eq 0 ] && [ -n "${_RESOLVE_FALLBACK_JSON:-}" ]; then
|
||||
_RESOLVED_LLAMA_TAG="$(
|
||||
printf '%s' "$_RESOLVE_FALLBACK_JSON" | python -c 'import json,sys; print(json.load(sys.stdin).get("llama_tag",""))' 2>/dev/null || true
|
||||
)"
|
||||
else
|
||||
_RESOLVED_LLAMA_TAG=""
|
||||
fi
|
||||
if [ -z "$_RESOLVED_LLAMA_TAG" ]; then
|
||||
_RESOLVED_LLAMA_TAG="$_REQUESTED_LLAMA_TAG"
|
||||
fi
|
||||
_NEED_LLAMA_SOURCE_BUILD=true
|
||||
|
|
@ -701,7 +728,40 @@ else
|
|||
step "llama.cpp" "skipped (git not found)" "$C_WARN"
|
||||
[ -f "$LLAMA_SERVER_BIN" ] || _LLAMA_CPP_DEGRADED=true
|
||||
else
|
||||
if [ -z "$_LLAMA_PR" ]; then
|
||||
if [ "$_LLAMA_SOURCE" = "https://github.com/ggml-org/llama.cpp" ]; then
|
||||
_RESOLVE_SOURCE_ARGS=(--resolve-source-build "$_REQUESTED_LLAMA_TAG" --published-repo "$_HELPER_RELEASE_REPO")
|
||||
_RESOLVE_SOURCE_ARGS+=(--output-format json)
|
||||
if [ -n "${UNSLOTH_LLAMA_RELEASE_TAG:-}" ]; then
|
||||
_RESOLVE_SOURCE_ARGS+=(--published-release-tag "$UNSLOTH_LLAMA_RELEASE_TAG")
|
||||
fi
|
||||
set +e
|
||||
_SOURCE_BUILD_PLAN="$(python "$SCRIPT_DIR/install_llama_prebuilt.py" "${_RESOLVE_SOURCE_ARGS[@]}" 2>/dev/null)"
|
||||
_RESOLVE_SOURCE_STATUS=$?
|
||||
set -e
|
||||
if [ "$_RESOLVE_SOURCE_STATUS" -eq 0 ] && [ -n "$_SOURCE_BUILD_PLAN" ]; then
|
||||
_RESOLVED_SOURCE_URL="$(
|
||||
printf '%s' "$_SOURCE_BUILD_PLAN" | python -c 'import json,sys; print(json.load(sys.stdin).get("source_url",""))' 2>/dev/null || true
|
||||
)"
|
||||
_RESOLVED_SOURCE_REF_KIND="$(
|
||||
printf '%s' "$_SOURCE_BUILD_PLAN" | python -c 'import json,sys; print(json.load(sys.stdin).get("source_ref_kind",""))' 2>/dev/null || true
|
||||
)"
|
||||
_RESOLVED_SOURCE_REF="$(
|
||||
printf '%s' "$_SOURCE_BUILD_PLAN" | python -c 'import json,sys; print(json.load(sys.stdin).get("source_ref",""))' 2>/dev/null || true
|
||||
)"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$_RESOLVED_SOURCE_URL" ]; then
|
||||
_RESOLVED_SOURCE_URL="$_LLAMA_SOURCE"
|
||||
fi
|
||||
if [ -z "$_RESOLVED_SOURCE_REF" ]; then
|
||||
_RESOLVED_SOURCE_REF="$_RESOLVED_LLAMA_TAG"
|
||||
fi
|
||||
fi
|
||||
verbose_substep "source build repo: $_RESOLVED_SOURCE_URL"
|
||||
verbose_substep "source build ref: ${_RESOLVED_SOURCE_REF:-latest} (${_RESOLVED_SOURCE_REF_KIND})"
|
||||
BUILD_OK=true
|
||||
mkdir -p "$(dirname "$LLAMA_CPP_DIR")"
|
||||
_BUILD_TMP="${LLAMA_CPP_DIR}.build.$$"
|
||||
rm -rf "$_BUILD_TMP"
|
||||
if [ -n "$_LLAMA_PR" ]; then
|
||||
|
|
@ -715,12 +775,34 @@ else
|
|||
run_quiet_no_exit "checkout PR #$_LLAMA_PR" \
|
||||
git -C "$_BUILD_TMP" checkout "pr-$_LLAMA_PR" || BUILD_OK=false
|
||||
fi
|
||||
elif [ "$_RESOLVED_SOURCE_REF_KIND" = "pull" ] && [ -n "$_RESOLVED_SOURCE_REF" ]; then
|
||||
run_quiet_no_exit "clone llama.cpp" \
|
||||
git clone --depth 1 "${_RESOLVED_SOURCE_URL}.git" "$_BUILD_TMP" || BUILD_OK=false
|
||||
if [ "$BUILD_OK" = true ]; then
|
||||
run_quiet_no_exit "fetch source PR ref" \
|
||||
git -C "$_BUILD_TMP" fetch --depth 1 origin "$_RESOLVED_SOURCE_REF" || BUILD_OK=false
|
||||
fi
|
||||
if [ "$BUILD_OK" = true ]; then
|
||||
run_quiet_no_exit "checkout source PR ref" \
|
||||
git -C "$_BUILD_TMP" checkout -B unsloth-llama-build FETCH_HEAD || BUILD_OK=false
|
||||
fi
|
||||
elif [ "$_RESOLVED_SOURCE_REF_KIND" = "commit" ] && [ -n "$_RESOLVED_SOURCE_REF" ]; then
|
||||
run_quiet_no_exit "clone llama.cpp" \
|
||||
git clone --depth 1 "${_RESOLVED_SOURCE_URL}.git" "$_BUILD_TMP" || BUILD_OK=false
|
||||
if [ "$BUILD_OK" = true ]; then
|
||||
run_quiet_no_exit "fetch source commit" \
|
||||
git -C "$_BUILD_TMP" fetch --depth 1 origin "$_RESOLVED_SOURCE_REF" || BUILD_OK=false
|
||||
fi
|
||||
if [ "$BUILD_OK" = true ]; then
|
||||
run_quiet_no_exit "checkout source commit" \
|
||||
git -C "$_BUILD_TMP" checkout -B unsloth-llama-build FETCH_HEAD || BUILD_OK=false
|
||||
fi
|
||||
else
|
||||
_CLONE_ARGS=(git clone --depth 1)
|
||||
if [ "$_RESOLVED_LLAMA_TAG" != "latest" ] && [ -n "$_RESOLVED_LLAMA_TAG" ]; then
|
||||
_CLONE_ARGS+=(--branch "$_RESOLVED_LLAMA_TAG")
|
||||
if [ "$_RESOLVED_SOURCE_REF" != "latest" ] && [ -n "$_RESOLVED_SOURCE_REF" ]; then
|
||||
_CLONE_ARGS+=(--branch "$_RESOLVED_SOURCE_REF")
|
||||
fi
|
||||
_CLONE_ARGS+=("${_LLAMA_SOURCE}.git" "$_BUILD_TMP")
|
||||
_CLONE_ARGS+=("${_RESOLVED_SOURCE_URL}.git" "$_BUILD_TMP")
|
||||
run_quiet_no_exit "clone llama.cpp" \
|
||||
"${_CLONE_ARGS[@]}" || BUILD_OK=false
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue