Refactor JIT kernel and expert-pack directory layout (#36704)

This commit is contained in:
Xiaoyu Zhang
2026-08-29 07:41:25 +08:00
committed by GitHub
parent 50bc1a3767
commit db6f0a9d53
25 changed files with 90 additions and 55 deletions
@@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
#include <sgl_kernel/tensor.h> // For TensorMatcher, SymbolicSize, SymbolicDevice
#include <sgl_kernel/utils.h> // For div_ceil, RuntimeCheck
@@ -1,3 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
#include <sgl_kernel/tensor.h>
#include <sgl_kernel/utils.h>
@@ -1,3 +0,0 @@
from sglang.kernels.jit.minicpm_sala.get_block_table import get_block_table
__all__ = ["get_block_table"]
+1
View File
@@ -28,6 +28,7 @@ _GROUPS = (
"layernorm",
"mamba",
"memory",
"minicpm_sala",
"mm",
"moe",
"quantization",
@@ -16,7 +16,7 @@ def _jit_add_constant_module(constant: int) -> Module:
return load_jit(
"add_constant",
*args,
cuda_files=["add_constant.cuh"],
cuda_files=["elementwise/add_constant.cuh"],
cuda_wrappers=[("add_constant", f"add_constant<{args}>")],
)
@@ -0,0 +1,24 @@
"""MiniCPM-SALA kernels."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from sglang.kernels.ops.minicpm_sala.get_block_table import get_block_table
def __getattr__(name: str) -> Any:
if name == "get_block_table":
from sglang.kernels.ops.minicpm_sala.get_block_table import get_block_table
globals()[name] = get_block_table
return get_block_table
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
def __dir__() -> list[str]:
return sorted(set(globals()) | set(__all__))
__all__ = ["get_block_table"]
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
from typing import TYPE_CHECKING
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
def _jit_ngram_embedding_module() -> Module:
return load_jit(
"ngram_embedding",
cuda_files=["ngram_embedding.cuh"],
cuda_files=["speculative/ngram_embedding.cuh"],
cuda_wrappers=[
("compute_n_gram_ids", "&NgramEmbeddingKernel::compute_n_gram_ids"),
(
@@ -25,7 +25,7 @@ if TYPE_CHECKING:
from sglang.srt.model_executor.model_runner import ModelRunner
from sglang.kernels.jit.minicpm_sala import get_block_table
from sglang.kernels.ops.minicpm_sala import get_block_table
from sglang.srt.layers.attention.minicpm.sparse_utils import (
CompressionLevelMetadata,
MiniCPMSparseMetadata,
@@ -0,0 +1 @@
"""Expert-pack build, inspection, and validation utilities."""
+637
View File
@@ -0,0 +1,637 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import hashlib
import json
import os
import re
import shutil
import subprocess
import sys
import time
from datetime import datetime, timezone
from pathlib import Path
import gguf
try:
from .format import (
ENTRY_STRUCT,
FLAG_IDENTITY_PAYLOAD,
FLAG_TRIPLET_OBJECTS,
HEADER_STRUCT,
ROLE_NAMES,
IndexEntry,
PackHeader,
align_up,
inspect_pack,
sha256_file,
write_index,
)
except ImportError:
from format import ( # type: ignore[no-redef]
ENTRY_STRUCT,
FLAG_IDENTITY_PAYLOAD,
FLAG_TRIPLET_OBJECTS,
HEADER_STRUCT,
ROLE_NAMES,
IndexEntry,
PackHeader,
align_up,
inspect_pack,
sha256_file,
write_index,
)
FORMAT = "SGLANG-EXPERTPACK-v1"
EXPERT_RE = re.compile(
r"^blk\.(?P<layer>\d+)\.ffn_(?P<role>gate|up|down)_exps\.weight$"
)
COPY_CHUNK_BYTES = 16 * 1024 * 1024
def now() -> str:
return datetime.now(timezone.utc).isoformat()
def write_json_atomic(path: Path, value: object) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_name(path.name + ".tmp")
with temporary.open("w", encoding="utf-8", newline="\n") as stream:
json.dump(value, stream, ensure_ascii=False, indent=2, sort_keys=True)
stream.write("\n")
stream.flush()
os.fsync(stream.fileno())
os.replace(temporary, path)
directory_fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY)
try:
os.fsync(directory_fd)
finally:
os.close(directory_fd)
def hash_range(stream, offset: int, nbytes: int) -> str:
digest = hashlib.sha256()
stream.seek(offset)
remaining = nbytes
while remaining:
chunk = stream.read(min(remaining, COPY_CHUNK_BYTES))
if not chunk:
raise EOFError(
f"short read at source offset {offset}, {remaining} bytes remain"
)
digest.update(chunk)
remaining -= len(chunk)
return digest.hexdigest()
def copy_range(source_fd: int, output, offset: int, nbytes: int) -> str:
digest = hashlib.sha256()
copied = 0
while copied < nbytes:
chunk = os.pread(
source_fd, min(COPY_CHUNK_BYTES, nbytes - copied), offset + copied
)
if not chunk:
raise EOFError(f"short read at source offset {offset + copied}")
output.write(chunk)
digest.update(chunk)
copied += len(chunk)
return digest.hexdigest()
def load_inventory(
path: Path, source: Path, expected_sha256: str
) -> tuple[dict, list[dict], dict]:
rows = [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines()]
headers = [row for row in rows if row.get("kind") == "source"]
summaries = [row for row in rows if row.get("kind") == "summary"]
tensors = [row for row in rows if row.get("kind") == "tensor"]
if len(headers) != 1 or len(summaries) != 1:
raise ValueError(
"inventory must contain exactly one source and one summary record"
)
header = headers[0]
if Path(header["path"]).resolve() != source.resolve():
raise ValueError("inventory source path does not match --source")
if header.get("source_sha256") != expected_sha256 or not header.get(
"payload_hashes"
):
raise ValueError(
"inventory is not a full-hash inventory for the requested source"
)
if int(header["size"]) != source.stat().st_size:
raise ValueError("inventory source size does not match the source file")
if len(tensors) != int(header["tensor_count"]):
raise ValueError("inventory tensor count does not match its header")
if any(not row.get("sha256") for row in tensors):
raise ValueError("inventory contains a tensor without a payload hash")
return header, tensors, summaries[0]
def create_inventory(source: Path, source_sha256: str) -> tuple[dict, list[dict], dict]:
reader = gguf.GGUFReader(source, "r")
tensors = []
inventory_digest = hashlib.sha256()
with source.open("rb", buffering=0) as stream:
for tensor in sorted(reader.tensors, key=lambda item: item.name):
record = {
"kind": "tensor",
"name": tensor.name,
"shape": [int(value) for value in tensor.shape.tolist()],
"type": tensor.tensor_type.name,
"type_id": int(tensor.tensor_type),
"offset": int(tensor.data_offset),
"nbytes": int(tensor.n_bytes),
"sha256": hash_range(
stream, int(tensor.data_offset), int(tensor.n_bytes)
),
}
encoded = json.dumps(record, sort_keys=True).encode("utf-8") + b"\n"
inventory_digest.update(encoded)
tensors.append(record)
header = {
"kind": "source",
"path": str(source.resolve()),
"size": source.stat().st_size,
"source_sha256": source_sha256,
"gguf_data_offset": int(reader.data_offset),
"gguf_alignment": int(reader.alignment),
"tensor_count": len(tensors),
"metadata_count": len(reader.fields),
"payload_hashes": True,
}
summary = {
"kind": "summary",
"tensor_count": len(tensors),
"inventory_sha256": inventory_digest.hexdigest(),
}
return header, tensors, summary
def validate_inventory_against_reader(source: Path, tensors: list[dict]) -> None:
reader = gguf.GGUFReader(source, "r")
actual = {
tensor.name: {
"shape": [int(value) for value in tensor.shape.tolist()],
"type": tensor.tensor_type.name,
"type_id": int(tensor.tensor_type),
"offset": int(tensor.data_offset),
"nbytes": int(tensor.n_bytes),
}
for tensor in reader.tensors
}
recorded = {row["name"]: row for row in tensors}
if set(actual) != set(recorded):
raise ValueError("inventory tensor names do not match the GGUF reader")
for name, value in actual.items():
if any(value[field] != recorded[name].get(field) for field in value):
raise ValueError(f"inventory metadata mismatch for tensor {name}")
ordered = sorted(tensors, key=lambda row: int(row["offset"]))
previous_end = 0
for row in ordered:
offset = int(row["offset"])
end = offset + int(row["nbytes"])
if offset < previous_end or end > source.stat().st_size:
raise ValueError(f"invalid or overlapping source range for {row['name']}")
previous_end = end
def generation(model_digest: str, source_digest: str, layer: int, expert: int) -> int:
value = hashlib.sha256(
f"{model_digest}:{source_digest}:{layer}:{expert}".encode("ascii")
).digest()
return int.from_bytes(value[:8], "little") or 1
def tool_sha256() -> str:
digest = hashlib.sha256()
for path in (Path(__file__), Path(__file__).with_name("format.py")):
digest.update(path.name.encode("ascii") + b"\0")
digest.update(path.read_bytes())
return digest.hexdigest()
def git_sha() -> str:
try:
return subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=Path(__file__).resolve().parent,
check=True,
capture_output=True,
text=True,
).stdout.strip()
except (OSError, subprocess.CalledProcessError):
return "unknown"
def build(args: argparse.Namespace) -> dict[str, object]:
started_at = now()
started_monotonic = time.monotonic()
source = args.source.resolve(strict=True)
output = args.output.resolve()
manifest_path = args.manifest.resolve()
checkpoint_path = args.checkpoint.resolve()
partial_path = output.with_name(output.name + ".partial")
output.parent.mkdir(parents=True, exist_ok=True)
manifest_path.parent.mkdir(parents=True, exist_ok=True)
if output.exists():
raise ValueError(f"completed output already exists: {output}")
if args.config_blob is not None:
if sha256_file(args.config_blob.resolve(strict=True)) != args.config_sha256:
raise ValueError("DeepSeek config hash does not match its digest")
actual_source_sha256 = sha256_file(source)
if actual_source_sha256 != args.source_sha256:
raise ValueError(
f"source SHA-256 mismatch: expected {args.source_sha256}, got {actual_source_sha256}"
)
if args.inventory is None:
inventory_header, tensors, inventory_summary = create_inventory(
source, actual_source_sha256
)
else:
inventory_header, tensors, inventory_summary = load_inventory(
args.inventory.resolve(strict=True), source, actual_source_sha256
)
validate_inventory_against_reader(source, tensors)
expert_tensors: dict[tuple[int, str], dict] = {}
for row in tensors:
match = EXPERT_RE.fullmatch(row["name"])
if match is not None:
key = int(match.group("layer")), match.group("role")
if key in expert_tensors:
raise ValueError(f"duplicate routed-expert tensor {key}")
expert_tensors[key] = row
expected_tensor_keys = {
(layer, role) for layer in range(args.num_layers) for role in ROLE_NAMES
}
if set(expert_tensors) != expected_tensor_keys:
missing = sorted(expected_tensor_keys - set(expert_tensors))
extra = sorted(set(expert_tensors) - expected_tensor_keys)
raise ValueError(
f"routed-expert tensor coverage mismatch: missing={missing[:8]} extra={extra[:8]}"
)
role_bytes = set()
for (layer, role), row in expert_tensors.items():
shape = [int(value) for value in row["shape"]]
if len(shape) != 3 or shape[-1] != args.num_experts:
raise ValueError(
f"unexpected expert shape for layer={layer} role={role}: {shape}"
)
if int(row["nbytes"]) % args.num_experts:
raise ValueError(f"expert tensor is not evenly sliceable: {row['name']}")
slice_bytes = int(row["nbytes"]) // args.num_experts
block_size, type_size = gguf.GGML_QUANT_SIZES[
gguf.GGMLQuantizationType(int(row["type_id"]))
]
logical_elements = 1
for dimension in shape[:-1]:
logical_elements *= dimension
expected_bytes = logical_elements // block_size * type_size
if logical_elements % block_size or slice_bytes != expected_bytes:
raise ValueError(
f"quantized slice size mismatch for {row['name']}: {slice_bytes} != {expected_bytes}"
)
role_bytes.add(slice_bytes)
if len(role_bytes) != 1:
raise ValueError(
f"triplet v1 requires uniform role sizes, got {sorted(role_bytes)}"
)
role_nbytes = role_bytes.pop()
object_count = args.num_layers * args.num_experts
object_payload_bytes = role_nbytes * len(ROLE_NAMES)
object_stride = align_up(object_payload_bytes, args.alignment)
index_count = object_count * len(ROLE_NAMES)
data_start = align_up(
HEADER_STRUCT.size + index_count * ENTRY_STRUCT.size, args.alignment
)
expected_pack_bytes = data_start + object_count * object_stride
header = PackHeader(
flags=FLAG_IDENTITY_PAYLOAD | FLAG_TRIPLET_OBJECTS,
index_count=index_count,
data_start=data_start,
alignment=args.alignment,
num_layers=args.num_layers,
num_experts=args.num_experts,
top_k=args.top_k,
role_count=len(ROLE_NAMES),
model_identity_sha256=args.model_identity_sha256,
source_blob_sha256=actual_source_sha256,
config_sha256=args.config_sha256,
)
header_raw = header.pack()
existing_bytes = (
partial_path.stat().st_size if args.resume and partial_path.exists() else 0
)
remaining_bytes = max(expected_pack_bytes - existing_bytes, 0)
free_bytes = shutil.disk_usage(output.parent).free
safety_bytes = int(args.safety_margin_gib * 1024**3)
if free_bytes < remaining_bytes + safety_bytes:
raise OSError(
f"insufficient free space: free={free_bytes}, remaining_pack={remaining_bytes}, "
f"safety={safety_bytes}"
)
if args.resume:
checkpoint = json.loads(checkpoint_path.read_text(encoding="utf-8"))
if checkpoint.get("status") != "in_progress":
raise ValueError("resume checkpoint is not in progress")
for field, expected in (
("source_sha256", actual_source_sha256),
("model_identity_sha256", args.model_identity_sha256),
("config_sha256", args.config_sha256),
("tool_sha256", tool_sha256()),
("expected_pack_bytes", expected_pack_bytes),
):
if checkpoint.get(field) != expected:
raise ValueError(f"resume checkpoint {field} mismatch")
completed_layers = [int(value) for value in checkpoint["completed_layers"]]
if completed_layers != list(range(len(completed_layers))):
raise ValueError("completed layers in checkpoint are not a prefix")
entries = [IndexEntry.from_dict(value) for value in checkpoint["entries"]]
stream = partial_path.open("r+b", buffering=0)
if stream.read(len(header_raw)) != header_raw:
raise ValueError("partial pack header does not match the requested build")
pack_end = int(checkpoint["pack_end"])
if partial_path.stat().st_size < pack_end:
raise ValueError("partial pack is shorter than its checkpoint")
stream.truncate(pack_end)
stream.seek(pack_end)
else:
if partial_path.exists() or checkpoint_path.exists() or manifest_path.exists():
raise ValueError(
"build outputs already exist; use --resume for an in-progress build"
)
completed_layers = []
entries: list[IndexEntry] = []
stream = partial_path.open("x+b", buffering=0)
stream.write(header_raw)
stream.truncate(data_start)
stream.seek(data_start)
checkpoint = {
"format": FORMAT + "-checkpoint",
"version": 1,
"status": "in_progress",
"started_at": started_at,
"source_sha256": actual_source_sha256,
"model_identity_sha256": args.model_identity_sha256,
"config_sha256": args.config_sha256,
"tool_sha256": tool_sha256(),
"expected_pack_bytes": expected_pack_bytes,
"completed_layers": [],
"pack_end": data_start,
"entries": [],
}
write_json_atomic(checkpoint_path, checkpoint)
source_fd = os.open(source, os.O_RDONLY)
try:
for layer in range(len(completed_layers), args.num_layers):
layer_entries = []
for expert in range(args.num_experts):
object_ordinal = layer * args.num_experts + expert
object_offset = data_start + object_ordinal * object_stride
if stream.tell() != object_offset:
raise ValueError(
f"pack cursor mismatch: {stream.tell()} != {object_offset}"
)
object_generation = generation(
args.model_identity_sha256, actual_source_sha256, layer, expert
)
for role in ROLE_NAMES:
tensor = expert_tensors[(layer, role)]
source_slice_offset = int(tensor["offset"]) + expert * role_nbytes
pack_offset = stream.tell()
slice_sha256 = copy_range(
source_fd, stream, source_slice_offset, role_nbytes
)
dtype_id = int(tensor["type_id"])
block_size = int(
gguf.GGML_QUANT_SIZES[gguf.GGMLQuantizationType(dtype_id)][0]
)
entry = IndexEntry(
layer=layer,
expert=expert,
role=role,
dtype_id=dtype_id,
dtype=str(tensor["type"]),
tensor_name=str(tensor["name"]),
source_tensor_offset=int(tensor["offset"]),
source_tensor_nbytes=int(tensor["nbytes"]),
source_slice_offset=source_slice_offset,
source_slice_nbytes=role_nbytes,
pack_offset=pack_offset,
pack_nbytes=role_nbytes,
source_tensor_sha256=str(tensor["sha256"]),
source_slice_sha256=slice_sha256,
checksum=slice_sha256,
shape=tuple(int(value) for value in tensor["shape"][:-1]),
quant_scheme=str(tensor["type"]),
transform_id="identity-v1",
block_size=block_size,
generation=object_generation,
)
entry.pack()
layer_entries.append(entry)
padding = object_stride - object_payload_bytes
if padding:
stream.write(bytes(padding))
stream.flush()
os.fsync(stream.fileno())
entries.extend(layer_entries)
checkpoint["completed_layers"].append(layer)
checkpoint["pack_end"] = stream.tell()
checkpoint["entries"] = [entry.to_dict() for entry in entries]
write_json_atomic(checkpoint_path, checkpoint)
print(
f"completed layer {layer}/{args.num_layers - 1}: pack_end={stream.tell()}",
file=sys.stderr,
flush=True,
)
if stream.tell() != expected_pack_bytes:
raise ValueError(
f"final pack size mismatch: {stream.tell()} != {expected_pack_bytes}"
)
index_sha256 = write_index(stream, header, entries)
stream.flush()
os.fsync(stream.fileno())
finally:
os.close(source_fd)
stream.close()
pack_sha256 = sha256_file(partial_path)
reader = gguf.GGUFReader(source, "r")
with source.open("rb", buffering=0) as source_stream:
source_metadata_sha256 = hash_range(source_stream, 0, int(reader.data_offset))
routed_names = {row["name"] for row in expert_tensors.values()}
tensor_manifest = []
for tensor in sorted(tensors, key=lambda row: row["name"]):
routed = tensor["name"] in routed_names
tensor_manifest.append(
{
"name": tensor["name"],
"shape": tensor["shape"],
"type": tensor["type"],
"type_id": tensor["type_id"],
"source_offset": tensor["offset"],
"source_nbytes": tensor["nbytes"],
"source_payload_sha256": tensor["sha256"],
"category": "routed_expert" if routed else "non_routed",
"mapping": "expert_pack_identity" if routed else "gguf_direct_identity",
"scale_storage": (
"inline_quant_block"
if tensor["type"] == "MXFP4"
else "tensor_native"
),
}
)
manifest = {
"format": FORMAT,
"version": 1,
"complete": True,
"created_at": now(),
"layout": "triplet_identity",
"role_order": list(ROLE_NAMES),
"alignment": args.alignment,
"pack_path": str(output),
"pack_size": expected_pack_bytes,
"pack_sha256": pack_sha256,
"header_bytes": header.header_bytes,
"index_count": index_count,
"index_entry_bytes": header.entry_bytes,
"index_sha256": index_sha256,
"data_start": data_start,
"object_count": object_count,
"object_payload_bytes": object_payload_bytes,
"object_stride": object_stride,
"role_bytes": role_nbytes,
"payload_bytes": index_count * role_nbytes,
"padding_bytes": expected_pack_bytes - data_start - index_count * role_nbytes,
"model": {
"ref": args.model_ref,
"model_identity_sha256": args.model_identity_sha256,
"config_sha256": args.config_sha256,
"num_layers": args.num_layers,
"num_routed_experts": args.num_experts,
"top_k": args.top_k,
"single_gpu": True,
},
"source": {
"path": str(source),
"size": source.stat().st_size,
"sha256": actual_source_sha256,
"gguf_data_offset": int(reader.data_offset),
"gguf_metadata_sha256": source_metadata_sha256,
"inventory_path": str(args.inventory.resolve()) if args.inventory else None,
"inventory_sha256": inventory_summary.get("inventory_sha256"),
"tensor_count": len(tensors),
},
"coverage": {
"layers": list(range(args.num_layers)),
"experts_per_layer": args.num_experts,
"roles": list(ROLE_NAMES),
"routed_tensor_count": len(routed_names),
"non_routed_tensor_count": len(tensors) - len(routed_names),
},
"transform": {
"id": "identity-v1",
"description": "Contiguous source bytes; no dequantization, requantization, or value transform",
"reversible": True,
"tool_sha256": tool_sha256(),
},
"builder": {
"git_sha": git_sha(),
"python": sys.version,
"command": " ".join(sys.argv),
"started_at": started_at,
"elapsed_s": time.monotonic() - started_monotonic,
},
"tensors": tensor_manifest,
}
os.replace(partial_path, output)
write_json_atomic(manifest_path, manifest)
checkpoint["status"] = "complete"
checkpoint["completed_at"] = now()
checkpoint["manifest_sha256"] = sha256_file(manifest_path)
checkpoint["pack_sha256"] = pack_sha256
write_json_atomic(checkpoint_path, checkpoint)
return manifest
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Build an auditable SGLang expert pack from GGUF"
)
parser.add_argument("--source", type=Path)
parser.add_argument("--source-sha256")
parser.add_argument("--inventory", type=Path)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--manifest", type=Path)
parser.add_argument("--checkpoint", type=Path)
parser.add_argument("--model-ref", default="deepseek-v4-flash")
parser.add_argument("--model-identity-sha256")
parser.add_argument("--config-blob", type=Path)
parser.add_argument("--config-sha256")
parser.add_argument("--num-layers", type=int, default=43)
parser.add_argument("--num-experts", type=int, default=256)
parser.add_argument("--top-k", type=int, default=6)
parser.add_argument("--alignment", type=int, default=4096)
parser.add_argument("--safety-margin-gib", type=float, default=16.0)
parser.add_argument("--resume", action="store_true")
parser.add_argument("--inspect", action="store_true")
parser.add_argument("--limit", type=int, default=12)
args = parser.parse_args()
if args.inspect:
return args
for name in ("source", "source_sha256", "model_identity_sha256", "config_sha256"):
if getattr(args, name) is None:
parser.error(f"--{name.replace('_', '-')} is required when building")
args.manifest = args.manifest or args.output.with_name(
args.output.name + ".manifest.json"
)
args.checkpoint = args.checkpoint or args.output.with_name(
args.output.name + ".checkpoint.json"
)
if args.num_layers <= 0 or args.num_experts <= 0 or args.top_k <= 0:
parser.error("model dimensions and top-k must be positive")
align_up(0, args.alignment)
return args
def main() -> int:
args = parse_args()
if args.inspect:
inspect_pack(args.output, args.limit)
return 0
manifest = build(args)
print(
json.dumps(
{
"pack": manifest["pack_path"],
"pack_sha256": manifest["pack_sha256"],
"manifest": str(args.manifest.resolve()),
"objects": manifest["object_count"],
"entries": manifest["index_count"],
"pack_size": manifest["pack_size"],
},
sort_keys=True,
)
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+315
View File
@@ -0,0 +1,315 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import hashlib
import json
import struct
from dataclasses import dataclass
from pathlib import Path
from typing import BinaryIO, Iterable
MAGIC = b"SGLANG-EXPERTPACK-v1\0\0\0\0"
VERSION = 1
ROLE_NAMES = ("gate", "up", "down")
ROLE_IDS = {name: index for index, name in enumerate(ROLE_NAMES)}
FLAG_IDENTITY_PAYLOAD = 1 << 0
FLAG_TRIPLET_OBJECTS = 1 << 1
# magic, version, header bytes, entry bytes, flags, index count, data start,
# alignment, layer count, expert count, top-k, role count, and three digests.
HEADER_STRUCT = struct.Struct("<24sIIIIQQQIIII32s32s32s")
# layer, expert, role, rank, GGML dtype id, dtype, tensor name, six ranges,
# source tensor/slice and pack hashes, logical role shape, quant/transform,
# quant block size, and generation.
ENTRY_STRUCT = struct.Struct("<HHBBH16s80sQQQQQQ32s32s32s4Q16s16sQQ")
def align_up(value: int, alignment: int) -> int:
if alignment <= 0 or alignment & (alignment - 1):
raise ValueError("alignment must be a positive power of two")
return (value + alignment - 1) // alignment * alignment
def sha256_file(path: Path, chunk_bytes: int = 16 * 1024 * 1024) -> str:
digest = hashlib.sha256()
with path.open("rb", buffering=0) as stream:
while chunk := stream.read(chunk_bytes):
digest.update(chunk)
return digest.hexdigest()
def parse_sha256(value: str, field: str) -> bytes:
if len(value) != 64:
raise ValueError(f"{field} must be a 64-character SHA-256 digest")
try:
result = bytes.fromhex(value)
except ValueError as exc:
raise ValueError(f"{field} must be a hexadecimal SHA-256 digest") from exc
if len(result) != 32:
raise ValueError(f"{field} must decode to 32 bytes")
return result
def encode_fixed(value: str, size: int, field: str) -> bytes:
encoded = value.encode("utf-8")
if len(encoded) >= size:
raise ValueError(f"{field} is too long for its {size}-byte field: {value!r}")
return encoded + bytes(size - len(encoded))
def decode_fixed(value: bytes) -> str:
return value.split(b"\0", 1)[0].decode("utf-8")
@dataclass(frozen=True)
class PackHeader:
flags: int
index_count: int
data_start: int
alignment: int
num_layers: int
num_experts: int
top_k: int
role_count: int
model_identity_sha256: str
source_blob_sha256: str
config_sha256: str
@property
def header_bytes(self) -> int:
return HEADER_STRUCT.size
@property
def entry_bytes(self) -> int:
return ENTRY_STRUCT.size
def pack(self) -> bytes:
if self.role_count != len(ROLE_NAMES):
raise ValueError(f"role_count must be {len(ROLE_NAMES)}")
expected_entries = self.num_layers * self.num_experts * self.role_count
if self.index_count != expected_entries:
raise ValueError(
f"index_count {self.index_count} does not match {expected_entries}"
)
minimum_data_start = self.header_bytes + self.index_count * self.entry_bytes
if self.data_start < minimum_data_start or self.data_start % self.alignment:
raise ValueError("data_start is too small or is not aligned")
return HEADER_STRUCT.pack(
MAGIC,
VERSION,
self.header_bytes,
self.entry_bytes,
self.flags,
self.index_count,
self.data_start,
self.alignment,
self.num_layers,
self.num_experts,
self.top_k,
self.role_count,
parse_sha256(self.model_identity_sha256, "model_identity_sha256"),
parse_sha256(self.source_blob_sha256, "source_blob_sha256"),
parse_sha256(self.config_sha256, "config_sha256"),
)
@classmethod
def unpack(cls, raw: bytes) -> PackHeader:
if len(raw) != HEADER_STRUCT.size:
raise ValueError("expert-pack header is truncated")
(
magic,
version,
header_bytes,
entry_bytes,
flags,
index_count,
data_start,
alignment,
num_layers,
num_experts,
top_k,
role_count,
model_identity_digest,
source_digest,
config_digest,
) = HEADER_STRUCT.unpack(raw)
if magic != MAGIC:
raise ValueError("expert-pack magic does not match")
if version != VERSION:
raise ValueError(f"unsupported expert-pack version {version}")
if header_bytes != HEADER_STRUCT.size or entry_bytes != ENTRY_STRUCT.size:
raise ValueError(
"expert-pack struct sizes do not match this implementation"
)
result = cls(
flags=flags,
index_count=index_count,
data_start=data_start,
alignment=alignment,
num_layers=num_layers,
num_experts=num_experts,
top_k=top_k,
role_count=role_count,
model_identity_sha256=model_identity_digest.hex(),
source_blob_sha256=source_digest.hex(),
config_sha256=config_digest.hex(),
)
result.pack()
return result
@dataclass(frozen=True)
class IndexEntry:
layer: int
expert: int
role: str
dtype_id: int
dtype: str
tensor_name: str
source_tensor_offset: int
source_tensor_nbytes: int
source_slice_offset: int
source_slice_nbytes: int
pack_offset: int
pack_nbytes: int
source_tensor_sha256: str
source_slice_sha256: str
checksum: str
shape: tuple[int, ...]
quant_scheme: str
transform_id: str
block_size: int
generation: int
@property
def key(self) -> tuple[int, int, int]:
return self.layer, self.expert, ROLE_IDS[self.role]
def pack(self) -> bytes:
if self.role not in ROLE_IDS:
raise ValueError(f"unknown expert role {self.role!r}")
if not 0 <= self.layer <= 0xFFFF or not 0 <= self.expert <= 0xFFFF:
raise ValueError("layer/expert does not fit the pack index")
if not 0 <= self.dtype_id <= 0xFFFF:
raise ValueError("dtype_id does not fit the pack index")
if not 1 <= len(self.shape) <= 4 or any(value <= 0 for value in self.shape):
raise ValueError(f"invalid role shape {self.shape}")
dims = self.shape + (0,) * (4 - len(self.shape))
return ENTRY_STRUCT.pack(
self.layer,
self.expert,
ROLE_IDS[self.role],
len(self.shape),
self.dtype_id,
encode_fixed(self.dtype, 16, "dtype"),
encode_fixed(self.tensor_name, 80, "tensor_name"),
self.source_tensor_offset,
self.source_tensor_nbytes,
self.source_slice_offset,
self.source_slice_nbytes,
self.pack_offset,
self.pack_nbytes,
parse_sha256(self.source_tensor_sha256, "source_tensor_sha256"),
parse_sha256(self.source_slice_sha256, "source_slice_sha256"),
parse_sha256(self.checksum, "checksum"),
*dims,
encode_fixed(self.quant_scheme, 16, "quant_scheme"),
encode_fixed(self.transform_id, 16, "transform_id"),
self.block_size,
self.generation,
)
@classmethod
def unpack(cls, raw: bytes) -> IndexEntry:
if len(raw) != ENTRY_STRUCT.size:
raise ValueError("expert-pack index entry is truncated")
values = ENTRY_STRUCT.unpack(raw)
role_id = values[2]
rank = values[3]
if role_id >= len(ROLE_NAMES) or not 1 <= rank <= 4:
raise ValueError("expert-pack index contains an invalid role or rank")
shape = tuple(values[16 : 16 + rank])
return cls(
layer=values[0],
expert=values[1],
role=ROLE_NAMES[role_id],
dtype_id=values[4],
dtype=decode_fixed(values[5]),
tensor_name=decode_fixed(values[6]),
source_tensor_offset=values[7],
source_tensor_nbytes=values[8],
source_slice_offset=values[9],
source_slice_nbytes=values[10],
pack_offset=values[11],
pack_nbytes=values[12],
source_tensor_sha256=values[13].hex(),
source_slice_sha256=values[14].hex(),
checksum=values[15].hex(),
shape=shape,
quant_scheme=decode_fixed(values[20]),
transform_id=decode_fixed(values[21]),
block_size=values[22],
generation=values[23],
)
def to_dict(self) -> dict[str, object]:
value = dict(self.__dict__)
value["shape"] = list(self.shape)
return value
@classmethod
def from_dict(cls, value: dict[str, object]) -> IndexEntry:
fields = dict(value)
fields["shape"] = tuple(int(item) for item in fields["shape"])
return cls(**fields)
def read_header(stream: BinaryIO) -> PackHeader:
stream.seek(0)
return PackHeader.unpack(stream.read(HEADER_STRUCT.size))
def read_index(stream: BinaryIO, header: PackHeader) -> list[IndexEntry]:
stream.seek(header.header_bytes)
entries = []
for _ in range(header.index_count):
entries.append(IndexEntry.unpack(stream.read(header.entry_bytes)))
return entries
def write_index(
stream: BinaryIO, header: PackHeader, entries: Iterable[IndexEntry]
) -> str:
ordered = sorted(entries, key=lambda entry: entry.key)
if len(ordered) != header.index_count:
raise ValueError(
f"expected {header.index_count} index entries, got {len(ordered)}"
)
digest = hashlib.sha256()
stream.seek(header.header_bytes)
for entry in ordered:
raw = entry.pack()
stream.write(raw)
digest.update(raw)
return digest.hexdigest()
def inspect_pack(path: Path, limit: int = 12) -> dict[str, object]:
with path.open("rb", buffering=0) as stream:
header = read_header(stream)
entries = read_index(stream, header)
summary = {
"path": str(path.resolve()),
"size": path.stat().st_size,
"header": header.__dict__,
"role_counts": {
role: sum(entry.role == role for entry in entries) for role in ROLE_NAMES
},
"payload_bytes": sum(entry.pack_nbytes for entry in entries),
"entries": [entry.to_dict() for entry in entries[:limit]],
}
print(json.dumps(summary, indent=2, sort_keys=True))
return summary
+738
View File
@@ -0,0 +1,738 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Structural inventory and adapter manifest for Kimi K3 GGUF expert packs."""
from __future__ import annotations
import hashlib
import json
import os
import re
import struct
import subprocess
from collections.abc import Callable, Iterable
from contextlib import ExitStack
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, BinaryIO
FORMAT = "SGLANG-KIMI-GGMLMOEPACK-ADAPTER-v1"
PACK_MAGIC = b"GGMLMOEPACKv1\0\0\0"
PACK_VERSION = 1
PACK_HEADER = struct.Struct("<16sIIQQ")
PACK_ENTRY = struct.Struct("<128siIQQ")
PACK_ALIGNMENT = 4096
ROLE_ORDER = ("up", "gate", "down")
EXPERT_RE = re.compile(
r"^blk\.(?P<layer>\d+)\.ffn_(?P<role>up|gate|down)_exps\.weight$"
)
SHARD_RE = re.compile(r"-(?P<number>\d{5})-of-(?P<count>\d{5})\.gguf$")
COPY_CHUNK_BYTES = 16 * 1024 * 1024
@dataclass(frozen=True)
class KimiK3Spec:
num_hidden_layers: int
first_k_dense_replace: int
num_experts: int
top_k: int
num_shared_experts: int
hidden_size: int
routed_expert_hidden_size: int
moe_intermediate_size: int
hidden_act: str
active_moe_layer_ids: tuple[int, ...]
@classmethod
def from_config(cls, config: dict[str, Any]) -> KimiK3Spec:
text_config = config.get("text_config", config)
num_hidden_layers = int(text_config["num_hidden_layers"])
first_dense = int(text_config["first_k_dense_replace"])
active_layers = tuple(range(first_dense, num_hidden_layers))
result = cls(
num_hidden_layers=num_hidden_layers,
first_k_dense_replace=first_dense,
num_experts=int(text_config["num_experts"]),
top_k=int(text_config["num_experts_per_token"]),
num_shared_experts=int(text_config["num_shared_experts"]),
hidden_size=int(text_config["hidden_size"]),
routed_expert_hidden_size=int(text_config["routed_expert_hidden_size"]),
moe_intermediate_size=int(text_config["moe_intermediate_size"]),
hidden_act=str(text_config["hidden_act"]),
active_moe_layer_ids=active_layers,
)
result.validate_kimi_k3()
return result
def validate_kimi_k3(self) -> None:
expected = {
"num_hidden_layers": 93,
"first_k_dense_replace": 1,
"num_experts": 896,
"top_k": 16,
"num_shared_experts": 2,
"hidden_size": 7168,
"routed_expert_hidden_size": 3584,
"moe_intermediate_size": 3072,
"hidden_act": "situ",
}
actual = {
"num_hidden_layers": self.num_hidden_layers,
"first_k_dense_replace": self.first_k_dense_replace,
"num_experts": self.num_experts,
"top_k": self.top_k,
"num_shared_experts": self.num_shared_experts,
"hidden_size": self.hidden_size,
"routed_expert_hidden_size": self.routed_expert_hidden_size,
"moe_intermediate_size": self.moe_intermediate_size,
"hidden_act": self.hidden_act,
}
if actual != expected:
raise ValueError(
"Kimi K3 model invariants do not match the audited model: "
f"expected={expected}, actual={actual}"
)
expected_layers = tuple(range(1, 93))
if self.active_moe_layer_ids != expected_layers:
raise ValueError("Kimi K3 active MoE layers must be exactly 1..92")
@dataclass(frozen=True)
class TensorRecord:
name: str
shape: tuple[int, ...]
dtype: str
dtype_id: int
shard_index: int
shard_path: str
data_offset: int
nbytes: int
@property
def expert_key(self) -> tuple[int, str] | None:
match = EXPERT_RE.fullmatch(self.name)
if match is None:
return None
return int(match.group("layer")), match.group("role")
@dataclass(frozen=True)
class PackEntryRecord:
tensor_name: str
expert: int
offset: int
nbytes: int
def _field_value(reader: Any, name: str) -> Any:
field = reader.fields.get(name)
if field is None:
raise ValueError(f"GGUF metadata is missing required field {name!r}")
return field.contents()
def _sha256_range(stream: BinaryIO, offset: int, nbytes: int) -> str:
digest = hashlib.sha256()
stream.seek(offset)
remaining = nbytes
while remaining:
chunk = stream.read(min(COPY_CHUNK_BYTES, remaining))
if not chunk:
raise EOFError(f"short read at offset {offset}; {remaining} bytes remain")
digest.update(chunk)
remaining -= len(chunk)
return digest.hexdigest()
def sha256_file(path: Path) -> str:
with path.open("rb", buffering=0) as stream:
return _sha256_range(stream, 0, path.stat().st_size)
def canonical_sha256(value: Any) -> str:
encoded = json.dumps(
value, ensure_ascii=False, sort_keys=True, separators=(",", ":")
).encode("utf-8")
return hashlib.sha256(encoded).hexdigest()
def write_json_atomic(path: Path, value: Any) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
temporary = path.with_name(path.name + ".tmp")
with temporary.open("w", encoding="utf-8", newline="\n") as stream:
json.dump(value, stream, ensure_ascii=False, indent=2, sort_keys=True)
stream.write("\n")
stream.flush()
os.fsync(stream.fileno())
os.replace(temporary, path)
def discover_gguf_shards(directory: Path) -> list[Path]:
directory = directory.resolve(strict=True)
candidates = sorted(directory.glob("*.gguf"))
if not candidates:
raise ValueError(f"no GGUF files found in {directory}")
numbered: list[tuple[int, int, Path]] = []
for path in candidates:
match = SHARD_RE.search(path.name)
if match is None:
raise ValueError(f"GGUF shard name does not contain NNNNN-of-NNNNN: {path}")
numbered.append((int(match.group("number")), int(match.group("count")), path))
counts = {count for _, count, _ in numbered}
if len(counts) != 1:
raise ValueError(f"GGUF shard filenames disagree on split count: {counts}")
count = counts.pop()
numbers = [number for number, _, _ in numbered]
if count != len(numbered) or sorted(numbers) != list(range(1, count + 1)):
raise ValueError(
f"GGUF shard set is incomplete: count={count}, numbers={sorted(numbers)}"
)
return [path for _, _, path in sorted(numbered)]
def _git_sha(repo: Path | None) -> str:
if repo is None:
return "unknown"
try:
return subprocess.run(
["git", "rev-parse", "HEAD"],
cwd=repo,
check=True,
capture_output=True,
text=True,
).stdout.strip()
except (OSError, subprocess.CalledProcessError):
return "unknown"
def scan_gguf_shards(
paths: list[Path], *, full_source_hashes: bool = False
) -> tuple[list[dict[str, Any]], list[TensorRecord], dict[str, Any]]:
import gguf
shard_records: list[dict[str, Any]] = []
tensors: list[TensorRecord] = []
seen_names: set[str] = set()
split_count: int | None = None
split_tensor_count: int | None = None
architecture: str | None = None
for shard_index, path in enumerate(paths):
reader = gguf.GGUFReader(str(path), mode="r")
shard_split_count = int(_field_value(reader, "split.count"))
shard_split_no = int(_field_value(reader, "split.no"))
shard_tensor_count = int(_field_value(reader, "split.tensors.count"))
shard_architecture = str(_field_value(reader, "general.architecture"))
if shard_split_no != shard_index:
raise ValueError(
f"GGUF split.no mismatch for {path}: {shard_split_no} != {shard_index}"
)
if split_count is None:
split_count = shard_split_count
split_tensor_count = shard_tensor_count
architecture = shard_architecture
elif (
split_count != shard_split_count
or split_tensor_count != shard_tensor_count
or architecture != shard_architecture
):
raise ValueError(f"GGUF split metadata mismatch at {path}")
metadata_nbytes = int(reader.data_offset)
with path.open("rb", buffering=0) as stream:
metadata_sha256 = _sha256_range(stream, 0, metadata_nbytes)
shard_record: dict[str, Any] = {
"index": shard_index,
"path": str(path.resolve()),
"size": path.stat().st_size,
"metadata_nbytes": metadata_nbytes,
"metadata_sha256": metadata_sha256,
"tensor_count": len(reader.tensors),
}
if full_source_hashes:
shard_record["sha256"] = sha256_file(path)
shard_records.append(shard_record)
for tensor in reader.tensors:
if tensor.name in seen_names:
raise ValueError(f"duplicate GGUF tensor across shards: {tensor.name}")
seen_names.add(tensor.name)
tensors.append(
TensorRecord(
name=tensor.name,
shape=tuple(int(value) for value in tensor.shape.tolist()),
dtype=tensor.tensor_type.name,
dtype_id=int(tensor.tensor_type),
shard_index=shard_index,
shard_path=str(path.resolve()),
data_offset=int(tensor.data_offset),
nbytes=int(tensor.n_bytes),
)
)
del reader
if split_count != len(paths):
raise ValueError(f"GGUF split.count={split_count}, found {len(paths)} files")
if split_tensor_count != len(tensors):
raise ValueError(
f"GGUF split.tensors.count={split_tensor_count}, found {len(tensors)}"
)
if architecture != "kimi-k3":
raise ValueError(f"expected GGUF architecture 'kimi-k3', got {architecture!r}")
summary = {
"architecture": architecture,
"shard_count": len(paths),
"tensor_count": len(tensors),
"total_bytes": sum(item["size"] for item in shard_records),
"full_source_hashes": full_source_hashes,
}
return shard_records, tensors, summary
def validate_expert_tensors(
tensors: Iterable[TensorRecord], spec: KimiK3Spec
) -> dict[tuple[int, str], TensorRecord]:
expert_tensors: dict[tuple[int, str], TensorRecord] = {}
for tensor in tensors:
key = tensor.expert_key
if key is None:
continue
if key in expert_tensors:
raise ValueError(f"duplicate routed expert tensor {key}")
expert_tensors[key] = tensor
expected_keys = {
(layer, role) for layer in spec.active_moe_layer_ids for role in ROLE_ORDER
}
if set(expert_tensors) != expected_keys:
missing = sorted(expected_keys - set(expert_tensors))
extra = sorted(set(expert_tensors) - expected_keys)
raise ValueError(
f"routed expert tensor coverage mismatch: missing={missing[:8]}, "
f"extra={extra[:8]}"
)
expected_layout = {
"up": ((spec.routed_expert_hidden_size, spec.moe_intermediate_size), "Q2_K"),
"gate": (
(spec.routed_expert_hidden_size, spec.moe_intermediate_size),
"Q2_K",
),
"down": (
(spec.moe_intermediate_size, spec.routed_expert_hidden_size),
"Q3_K",
),
}
for (layer, role), tensor in expert_tensors.items():
expected_shape, expected_dtype = expected_layout[role]
if tensor.shape != (*expected_shape, spec.num_experts):
raise ValueError(
f"unexpected expert shape for {(layer, role)}: {tensor.shape}"
)
if tensor.dtype != expected_dtype:
raise ValueError(
f"unexpected expert dtype for {(layer, role)}: {tensor.dtype}"
)
if tensor.nbytes % spec.num_experts:
raise ValueError(f"expert tensor is not evenly sliceable: {tensor.name}")
return expert_tensors
def _decode_name(raw: bytes) -> str:
try:
return raw.split(b"\0", 1)[0].decode("utf-8")
except UnicodeDecodeError as exc:
raise ValueError("expert-pack tensor name is not valid UTF-8") from exc
def _read_pack_entry(stream: BinaryIO, digest: hashlib._Hash) -> PackEntryRecord:
raw = stream.read(PACK_ENTRY.size)
if len(raw) != PACK_ENTRY.size:
raise ValueError("GGML expert-pack index is truncated")
digest.update(raw)
name, expert, reserved, offset, nbytes = PACK_ENTRY.unpack(raw)
if reserved != 0:
raise ValueError("GGML expert-pack reserved entry field must be zero")
return PackEntryRecord(_decode_name(name), expert, offset, nbytes)
def _compare_ranges(
pack_stream: BinaryIO,
pack_entry: PackEntryRecord,
tensor: TensorRecord,
expert_bytes: int,
) -> None:
source_offset = tensor.data_offset + pack_entry.expert * expert_bytes
with Path(tensor.shard_path).open("rb", buffering=0) as source_stream:
source_stream.seek(source_offset)
pack_stream.seek(pack_entry.offset)
remaining = expert_bytes
while remaining:
size = min(COPY_CHUNK_BYTES, remaining)
source_chunk = source_stream.read(size)
pack_chunk = pack_stream.read(size)
if source_chunk != pack_chunk or len(source_chunk) != size:
raise ValueError(
"expert-pack payload does not match GGUF source for "
f"{pack_entry.tensor_name} expert {pack_entry.expert}"
)
remaining -= size
def validate_ggml_moe_pack(
path: Path,
expert_tensors: dict[tuple[int, str], TensorRecord],
spec: KimiK3Spec,
*,
payload_samples: int = 6,
full_pack_hash: bool = False,
) -> dict[str, Any]:
path = path.resolve(strict=True)
expected_count = len(spec.active_moe_layer_ids) * spec.num_experts * len(ROLE_ORDER)
file_size = path.stat().st_size
index_digest = hashlib.sha256()
role_summary: dict[str, dict[str, Any]] = {}
sample_indices = set()
if payload_samples > 0:
if payload_samples == 1:
sample_indices.add(0)
else:
sample_indices.update(
round(index * (expected_count - 1) / (payload_samples - 1))
for index in range(payload_samples)
)
sampled_entries: list[tuple[PackEntryRecord, TensorRecord, int]] = []
object_bytes: int | None = None
object_start: int | None = None
previous_end = 0
with path.open("rb", buffering=0) as stream:
raw_header = stream.read(PACK_HEADER.size)
if len(raw_header) != PACK_HEADER.size:
raise ValueError("GGML expert-pack header is truncated")
index_digest.update(raw_header)
magic, version, header_size, index_count, data_start = PACK_HEADER.unpack(
raw_header
)
if magic != PACK_MAGIC or version != PACK_VERSION:
raise ValueError("GGML expert-pack magic or version does not match")
if header_size != PACK_HEADER.size:
raise ValueError("GGML expert-pack header size does not match")
if index_count != expected_count:
raise ValueError(
f"GGML expert-pack has {index_count} entries; expected {expected_count}"
)
minimum_data_start = PACK_HEADER.size + index_count * PACK_ENTRY.size
if data_start < minimum_data_start or data_start % PACK_ALIGNMENT:
raise ValueError("GGML expert-pack data_start is invalid or unaligned")
previous_end = data_start
for index in range(index_count):
entry = _read_pack_entry(stream, index_digest)
object_index, physical_role_id = divmod(index, len(ROLE_ORDER))
active_layer_index, expected_expert = divmod(object_index, spec.num_experts)
expected_layer = spec.active_moe_layer_ids[active_layer_index]
expected_role = ROLE_ORDER[physical_role_id]
match = EXPERT_RE.fullmatch(entry.tensor_name)
if match is None:
raise ValueError(f"invalid expert tensor name: {entry.tensor_name!r}")
actual_key = (int(match.group("layer")), match.group("role"))
expected_key = (expected_layer, expected_role)
if actual_key != expected_key or entry.expert != expected_expert:
raise ValueError(
"GGML expert-pack is not complete expert-major up/gate/down "
f"layout at index {index}: expected={(*expected_key, expected_expert)}, "
f"actual={(*actual_key, entry.expert)}"
)
tensor = expert_tensors[expected_key]
expert_bytes = tensor.nbytes // spec.num_experts
if entry.nbytes != expert_bytes:
raise ValueError(
f"expert-pack byte size mismatch for index {index}: "
f"{entry.nbytes} != {expert_bytes}"
)
if entry.offset % PACK_ALIGNMENT:
raise ValueError(f"expert-pack entry {index} is not 4 KiB aligned")
if entry.offset < previous_end or entry.offset + entry.nbytes > file_size:
raise ValueError(
f"expert-pack entry {index} overlaps or is out of range"
)
previous_end = entry.offset + entry.nbytes
summary = role_summary.setdefault(
expected_role,
{
"dtype": tensor.dtype,
"dtype_id": tensor.dtype_id,
"logical_shape": list(tensor.shape[:2]),
"expert_bytes": expert_bytes,
"entry_count": 0,
"payload_bytes": 0,
},
)
if summary["expert_bytes"] != expert_bytes:
raise ValueError(f"variable expert bytes for role {expected_role}")
summary["entry_count"] += 1
summary["payload_bytes"] += entry.nbytes
if physical_role_id == 0:
object_start = entry.offset
elif physical_role_id == len(ROLE_ORDER) - 1:
assert object_start is not None
span = entry.offset + entry.nbytes - object_start
if object_bytes is None:
object_bytes = span
elif object_bytes != span:
raise ValueError("expert-pack object spans are not fixed size")
if index in sample_indices:
sampled_entries.append((entry, tensor, expert_bytes))
if previous_end != file_size:
raise ValueError(
f"expert-pack has unexplained trailing bytes: {file_size - previous_end}"
)
for entry, tensor, expert_bytes in sampled_entries:
_compare_ranges(stream, entry, tensor, expert_bytes)
assert object_bytes is not None
result: dict[str, Any] = {
"path": str(path),
"size": file_size,
"magic": PACK_MAGIC.rstrip(b"\0").decode("ascii"),
"version": PACK_VERSION,
"header_bytes": PACK_HEADER.size,
"entry_bytes": PACK_ENTRY.size,
"index_count": expected_count,
"data_start": data_start,
"alignment": PACK_ALIGNMENT,
"index_sha256": index_digest.hexdigest(),
"physical_role_order": list(ROLE_ORDER),
"active_moe_layer_ids": list(spec.active_moe_layer_ids),
"num_experts": spec.num_experts,
"top_k": spec.top_k,
"object_bytes": object_bytes,
"roles": role_summary,
"payload_samples_verified": len(sampled_entries),
"full_pack_hash": full_pack_hash,
}
if full_pack_hash:
result["sha256"] = sha256_file(path)
return result
def _align_up(value: int, alignment: int = PACK_ALIGNMENT) -> int:
return (value + alignment - 1) // alignment * alignment
def _pack_layout(
expert_tensors: dict[tuple[int, str], TensorRecord], spec: KimiK3Spec
) -> tuple[list[tuple[PackEntryRecord, TensorRecord]], int, int]:
index_count = len(spec.active_moe_layer_ids) * spec.num_experts * len(ROLE_ORDER)
data_start = _align_up(PACK_HEADER.size + index_count * PACK_ENTRY.size)
offset = data_start
entries: list[tuple[PackEntryRecord, TensorRecord]] = []
for layer in spec.active_moe_layer_ids:
for expert in range(spec.num_experts):
for role in ROLE_ORDER:
tensor = expert_tensors[(layer, role)]
expert_bytes = tensor.nbytes // spec.num_experts
offset = _align_up(offset)
entries.append(
(
PackEntryRecord(tensor.name, expert, offset, expert_bytes),
tensor,
)
)
offset += expert_bytes
return entries, data_start, offset
def estimate_ggml_moe_pack_size(
expert_tensors: dict[tuple[int, str], TensorRecord], spec: KimiK3Spec
) -> int:
return _pack_layout(expert_tensors, spec)[2]
def _copy_tensor_slice(
source: BinaryIO, output: BinaryIO, offset: int, nbytes: int
) -> None:
source.seek(offset)
remaining = nbytes
while remaining:
chunk = source.read(min(COPY_CHUNK_BYTES, remaining))
if not chunk:
raise EOFError(
f"short GGUF read at offset {offset}; {remaining} bytes remain"
)
output.write(chunk)
remaining -= len(chunk)
def write_ggml_moe_pack(
path: Path,
expert_tensors: dict[tuple[int, str], TensorRecord],
spec: KimiK3Spec,
*,
progress: Callable[[int, int], None] | None = None,
) -> int:
entries, data_start, final_size = _pack_layout(expert_tensors, spec)
path = path.resolve()
partial = path.with_name(path.name + ".partial")
if path.exists():
raise FileExistsError(f"refusing to overwrite existing Expert Pack: {path}")
if partial.exists():
raise FileExistsError(f"partial Expert Pack already exists: {partial}")
path.parent.mkdir(parents=True, exist_ok=True)
with ExitStack() as stack:
sources = {
source_path: stack.enter_context(Path(source_path).open("rb", buffering=0))
for source_path in {tensor.shard_path for _, tensor in entries}
}
output = stack.enter_context(partial.open("xb", buffering=0))
output.write(
PACK_HEADER.pack(
PACK_MAGIC,
PACK_VERSION,
PACK_HEADER.size,
len(entries),
data_start,
)
)
for entry, _ in entries:
encoded_name = entry.tensor_name.encode("utf-8")
if len(encoded_name) >= 128:
raise ValueError(
f"expert tensor name is too long for the Pack index: {entry.tensor_name}"
)
output.write(
PACK_ENTRY.pack(
encoded_name.ljust(128, b"\0"),
entry.expert,
0,
entry.offset,
entry.nbytes,
)
)
output.write(bytes(data_start - output.tell()))
total = len(entries)
for index, (entry, tensor) in enumerate(entries, start=1):
padding = entry.offset - output.tell()
if padding < 0:
raise RuntimeError("Expert Pack layout moved backwards")
if padding:
output.write(bytes(padding))
source_offset = tensor.data_offset + entry.expert * (
tensor.nbytes // spec.num_experts
)
_copy_tensor_slice(
sources[tensor.shard_path], output, source_offset, entry.nbytes
)
if progress is not None and (index % 1024 == 0 or index == total):
progress(index, total)
output.flush()
os.fsync(output.fileno())
if partial.stat().st_size != final_size:
raise RuntimeError(
f"generated Expert Pack size {partial.stat().st_size} != {final_size}"
)
os.replace(partial, path)
return final_size
def create_manifest(
*,
gguf_dir: Path,
expert_pack: Path,
model_config: Path,
tokenizer_dir: Path,
payload_samples: int = 6,
full_source_hashes: bool = False,
full_pack_hash: bool = False,
repo: Path | None = None,
) -> dict[str, Any]:
config = json.loads(model_config.read_text(encoding="utf-8"))
spec = KimiK3Spec.from_config(config)
shard_paths = discover_gguf_shards(gguf_dir)
shard_records, tensors, source_summary = scan_gguf_shards(
shard_paths, full_source_hashes=full_source_hashes
)
expert_tensors = validate_expert_tensors(tensors, spec)
pack = validate_ggml_moe_pack(
expert_pack,
expert_tensors,
spec,
payload_samples=payload_samples,
full_pack_hash=full_pack_hash,
)
tokenizer_files = []
for path in sorted(tokenizer_dir.resolve(strict=True).iterdir()):
if path.is_file():
tokenizer_files.append(
{
"name": path.name,
"size": path.stat().st_size,
"sha256": sha256_file(path),
}
)
tensor_records = [
{
"name": tensor.name,
"shape": list(tensor.shape),
"dtype": tensor.dtype,
"dtype_id": tensor.dtype_id,
"shard_index": tensor.shard_index,
"data_offset": tensor.data_offset,
"nbytes": tensor.nbytes,
}
for tensor in sorted(tensors, key=lambda item: item.name)
]
source_inventory = {
"summary": source_summary,
"shards": shard_records,
"tensors": tensor_records,
}
model = {
"config_path": str(model_config.resolve()),
"config_sha256": sha256_file(model_config),
"architecture": "KimiLinearForCausalLM",
"num_hidden_layers": spec.num_hidden_layers,
"active_moe_layer_ids": list(spec.active_moe_layer_ids),
"num_experts": spec.num_experts,
"num_experts_per_token": spec.top_k,
"num_shared_experts": spec.num_shared_experts,
"hidden_size": spec.hidden_size,
"routed_expert_hidden_size": spec.routed_expert_hidden_size,
"moe_intermediate_size": spec.moe_intermediate_size,
"hidden_act": spec.hidden_act,
}
return {
"complete": True,
"format": FORMAT,
"created_at": datetime.now(timezone.utc).isoformat(),
"sglang_git_sha": _git_sha(repo),
"hard_constraints": {
"top_k": 16,
"top_k_is_immutable": True,
"all_selected_experts_must_execute": True,
"expert_pruning_allowed": False,
"requantization_allowed": False,
},
"model": model,
"source": {
**source_inventory,
"inventory_sha256": canonical_sha256(source_inventory),
},
"expert_pack": pack,
"tokenizer": {
"path": str(tokenizer_dir.resolve()),
"files": tokenizer_files,
"inventory_sha256": canonical_sha256(tokenizer_files),
},
"verification": {
"structure": "complete",
"payload_samples": payload_samples,
"full_source_hashes": full_source_hashes,
"full_pack_hash": full_pack_hash,
},
}
@@ -0,0 +1,266 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Validate or build the DeepSeek expert-pack used by the RTX 5090 benchmark."""
from __future__ import annotations
import argparse
import hashlib
import json
import subprocess
import sys
from pathlib import Path
try:
from .format import read_header
except ImportError:
from format import read_header # type: ignore[no-redef]
FORMAT = "SGLANG-EXPERTPACK-v1"
EXPERT_PACK_FILENAME = "DeepSeek-V4-Flash.expert-pack"
def sha256_file(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def write_json_atomic(path: Path, value: object) -> None:
temporary = path.with_name(path.name + ".tmp")
temporary.write_text(
json.dumps(value, ensure_ascii=False, indent=2, sort_keys=True) + "\n",
encoding="utf-8",
)
temporary.replace(path)
def normalize_manifest_identity(manifest_path: Path, manifest: dict) -> None:
model = manifest["model"]
normalized_model = {
"ref": model["ref"],
"model_identity_sha256": model["model_identity_sha256"],
"config_sha256": model["config_sha256"],
"num_layers": model["num_layers"],
"num_routed_experts": model["num_routed_experts"],
"top_k": model["top_k"],
"single_gpu": model["single_gpu"],
}
if model != normalized_model:
manifest["model"] = normalized_model
write_json_atomic(manifest_path, manifest)
def artifact_paths(source: Path) -> tuple[Path, Path, Path]:
pack = source.parent / EXPERT_PACK_FILENAME
manifest = source.parent / f"{EXPERT_PACK_FILENAME}.manifest.json"
checkpoint = source.parent / f"{EXPERT_PACK_FILENAME}.checkpoint.json"
return pack, manifest, checkpoint
def validate_pack(
pack: Path, manifest_path: Path, expected_source: Path | None = None
) -> tuple[bool, str, dict | None]:
try:
pack = pack.resolve(strict=True)
manifest_path = manifest_path.resolve(strict=True)
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
if manifest.get("format") != FORMAT or manifest.get("complete") is not True:
raise ValueError(
"manifest is not a completed SGLANG-EXPERTPACK-v1 manifest"
)
if Path(manifest["pack_path"]).resolve() != pack:
raise ValueError(
"manifest pack_path does not match the fixed expert-pack path"
)
if pack.stat().st_size != int(manifest["pack_size"]):
raise ValueError("pack size does not match manifest")
source = Path(manifest["source"]["path"]).resolve(strict=True)
if expected_source is not None and source != expected_source.resolve(
strict=True
):
raise ValueError("manifest source path does not match --gguf")
if source.stat().st_size != int(manifest["source"]["size"]):
raise ValueError("source GGUF size does not match manifest")
with pack.open("rb", buffering=0) as stream:
header = read_header(stream)
stream.seek(header.header_bytes)
raw_index = stream.read(header.index_count * header.entry_bytes)
if len(raw_index) != header.index_count * header.entry_bytes:
raise ValueError("pack index is truncated")
if hashlib.sha256(raw_index).hexdigest() != manifest["index_sha256"]:
raise ValueError("pack index SHA-256 does not match manifest")
model = manifest["model"]
model_identity_sha256 = model.get(
"model_identity_sha256", header.model_identity_sha256
)
model["model_identity_sha256"] = model_identity_sha256
expected = (
(header.index_count, manifest["index_count"], "index count"),
(header.data_start, manifest["data_start"], "data start"),
(header.num_layers, model["num_layers"], "layer count"),
(header.num_experts, model["num_routed_experts"], "expert count"),
(header.top_k, model["top_k"], "top-k"),
(
header.source_blob_sha256,
manifest["source"]["sha256"],
"source digest",
),
(
header.model_identity_sha256,
model_identity_sha256,
"model identity digest",
),
(header.config_sha256, model["config_sha256"], "config digest"),
)
for actual, wanted, label in expected:
if actual != wanted:
raise ValueError(f"pack header {label} does not match manifest")
return True, "header, index, source path and sizes are valid", manifest
except Exception as exc:
return False, str(exc), None
def load_build_inputs(args: argparse.Namespace) -> dict[str, object]:
source = args.gguf.resolve(strict=True)
expert_pack, expert_pack_manifest, checkpoint = artifact_paths(source)
model_config_path = args.model_config.resolve(strict=True)
model_config = json.loads(model_config_path.read_text(encoding="utf-8"))
source_sha256 = sha256_file(source)
config_sha256 = sha256_file(model_config_path)
model_identity = hashlib.sha256(
f"sglang-deepseek-expert-pack-v1:{source_sha256}:{config_sha256}".encode(
"ascii"
)
).hexdigest()
return {
"source": source,
"source_sha256": source_sha256,
"expert_pack": expert_pack,
"expert_pack_manifest": expert_pack_manifest,
"checkpoint": checkpoint,
"config_blob": model_config_path,
"config_sha256": config_sha256,
"model_identity_sha256": model_identity,
"num_layers": int(model_config["num_hidden_layers"]),
"num_experts": int(model_config["n_routed_experts"]),
"top_k": int(model_config["num_experts_per_tok"]),
}
def remove_invalid_outputs(pack: Path, manifest: Path, checkpoint: Path) -> None:
for path in (pack, manifest, pack.with_name(pack.name + ".partial"), checkpoint):
if path.exists():
print(f"EXPERT_PACK_REMOVE_INVALID path={path}", flush=True)
path.unlink()
def build_pack(args: argparse.Namespace, inputs: dict[str, object]) -> None:
build_script = Path(__file__).with_name("build.py")
expert_pack = Path(inputs["expert_pack"])
manifest = Path(inputs["expert_pack_manifest"])
checkpoint = Path(inputs["checkpoint"])
partial = expert_pack.with_name(expert_pack.name + ".partial")
resume = partial.is_file() and checkpoint.is_file() and not expert_pack.exists()
if not resume:
remove_invalid_outputs(expert_pack, manifest, checkpoint)
command = [
sys.executable,
str(build_script),
"--source",
str(inputs["source"]),
"--source-sha256",
str(inputs["source_sha256"]),
"--output",
str(expert_pack),
"--manifest",
str(manifest),
"--checkpoint",
str(checkpoint),
"--model-ref",
args.model_ref,
"--model-identity-sha256",
str(inputs["model_identity_sha256"]),
"--config-blob",
str(inputs["config_blob"]),
"--config-sha256",
str(inputs["config_sha256"]),
"--num-layers",
str(inputs["num_layers"]),
"--num-experts",
str(inputs["num_experts"]),
"--top-k",
str(inputs["top_k"]),
"--alignment",
str(args.alignment),
"--safety-margin-gib",
str(args.safety_margin_gib),
]
if args.inventory and args.inventory.is_file():
command.extend(("--inventory", str(args.inventory.resolve())))
if resume:
command.append("--resume")
print(
f"EXPERT_PACK_BUILD_START output={expert_pack} resume={str(resume).lower()}",
flush=True,
)
subprocess.run(command, check=True)
print(f"EXPERT_PACK_BUILD_COMPLETE output={expert_pack}", flush=True)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--gguf", type=Path, required=True)
parser.add_argument("--model-config", type=Path, required=True)
parser.add_argument("--inventory", type=Path)
parser.add_argument("--model-ref", default="deepseek-v4-flash")
parser.add_argument("--alignment", type=int, default=4096)
parser.add_argument("--safety-margin-gib", type=float, default=16.0)
parser.add_argument("--check-only", action="store_true")
args = parser.parse_args()
return args
def main() -> int:
args = parse_args()
source = args.gguf.resolve(strict=True)
expert_pack, expert_pack_manifest, _ = artifact_paths(source)
valid, reason, manifest = validate_pack(expert_pack, expert_pack_manifest, source)
if valid and manifest is not None:
normalize_manifest_identity(expert_pack_manifest, manifest)
print(f"EXPERT_PACK_VALID path={expert_pack} detail={reason}", flush=True)
return 0
print(f"EXPERT_PACK_INVALID path={expert_pack} detail={reason}", flush=True)
if args.check_only:
return 1
existing_valid, existing_reason, existing_manifest = validate_pack(
expert_pack, expert_pack_manifest
)
if existing_valid and existing_manifest is not None:
existing_source = Path(existing_manifest["source"]["path"])
raise RuntimeError(
f"the fixed expert-pack already belongs to a different GGUF: {existing_source}; "
f"move the requested GGUF to its own directory instead of overwriting {expert_pack}"
)
inputs = load_build_inputs(args)
build_pack(args, inputs)
valid, reason, manifest = validate_pack(expert_pack, expert_pack_manifest, source)
if not valid or manifest is None:
raise RuntimeError(f"generated expert-pack failed validation: {reason}")
normalize_manifest_identity(expert_pack_manifest, manifest)
print(f"EXPERT_PACK_READY path={expert_pack} detail={reason}", flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Prepare a small, zero-copy Kimi K3 GGUF/expert-pack adapter manifest."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
try:
from .kimi_ggml import create_manifest, write_json_atomic
except ImportError:
from kimi_ggml import create_manifest, write_json_atomic # type: ignore[no-redef]
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--gguf-dir", type=Path, required=True)
parser.add_argument("--expert-pack", type=Path, required=True)
parser.add_argument("--model-config", type=Path, required=True)
parser.add_argument("--tokenizer-dir", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument(
"--payload-samples",
type=int,
default=6,
help="Evenly spaced pack entries compared byte-for-byte with GGUF (default: 6).",
)
parser.add_argument("--full-source-hashes", action="store_true")
parser.add_argument("--full-pack-hash", action="store_true")
return parser.parse_args()
def main() -> int:
args = parse_args()
if args.payload_samples < 0:
raise ValueError("--payload-samples must be non-negative")
repo = Path(__file__).resolve().parent
manifest = create_manifest(
gguf_dir=args.gguf_dir,
expert_pack=args.expert_pack,
model_config=args.model_config.resolve(strict=True),
tokenizer_dir=args.tokenizer_dir,
payload_samples=args.payload_samples,
full_source_hashes=args.full_source_hashes,
full_pack_hash=args.full_pack_hash,
repo=repo,
)
write_json_atomic(args.output.resolve(), manifest)
summary = {
"manifest": str(args.output.resolve()),
"format": manifest["format"],
"source_shards": manifest["source"]["summary"]["shard_count"],
"source_tensors": manifest["source"]["summary"]["tensor_count"],
"pack_entries": manifest["expert_pack"]["index_count"],
"pack_index_sha256": manifest["expert_pack"]["index_sha256"],
"top_k": manifest["hard_constraints"]["top_k"],
"payload_samples_verified": manifest["expert_pack"]["payload_samples_verified"],
}
print(json.dumps(summary, indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as exc:
print(f"error: {exc}", file=sys.stderr)
raise SystemExit(1)
@@ -0,0 +1,125 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Validate or build the Kimi K3 expert pack derived from GGUF shards."""
from __future__ import annotations
import argparse
import fcntl
import json
import shutil
from pathlib import Path
try:
from .kimi_ggml import (
SHARD_RE,
KimiK3Spec,
discover_gguf_shards,
estimate_ggml_moe_pack_size,
scan_gguf_shards,
validate_expert_tensors,
validate_ggml_moe_pack,
write_ggml_moe_pack,
)
except ImportError:
from kimi_ggml import ( # type: ignore[no-redef]
SHARD_RE,
KimiK3Spec,
discover_gguf_shards,
estimate_ggml_moe_pack_size,
scan_gguf_shards,
validate_expert_tensors,
validate_ggml_moe_pack,
write_ggml_moe_pack,
)
def expert_pack_path(gguf: Path) -> Path:
match = SHARD_RE.search(gguf.name)
if match is None:
raise ValueError(f"Kimi GGUF name is not a numbered shard: {gguf}")
return gguf.parent / f"{gguf.name[: match.start()]}.expert-major.pack"
def validate_pack(pack: Path, expert_tensors: dict, spec: KimiK3Spec) -> str:
result = validate_ggml_moe_pack(
pack, expert_tensors, spec, payload_samples=6, full_pack_hash=False
)
return (
f"entries={result['index_count']} size={result['size']} "
f"samples={result['payload_samples_verified']}"
)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--gguf", type=Path, required=True)
parser.add_argument("--model-config", type=Path, required=True)
parser.add_argument("--safety-margin-gib", type=float, default=2.0)
parser.add_argument("--check-only", action="store_true")
return parser.parse_args()
def main() -> int:
args = parse_args()
gguf = args.gguf.expanduser().resolve(strict=True)
model_config = args.model_config.expanduser().resolve(strict=True)
if args.safety_margin_gib < 0:
raise ValueError("--safety-margin-gib must be non-negative")
shards = discover_gguf_shards(gguf.parent)
if gguf not in shards:
raise ValueError(f"--gguf is not part of the discovered shard set: {gguf}")
config = json.loads(model_config.read_text(encoding="utf-8"))
spec = KimiK3Spec.from_config(config)
_, tensors, _ = scan_gguf_shards(shards)
expert_tensors = validate_expert_tensors(tensors, spec)
pack = expert_pack_path(gguf)
partial = pack.with_name(pack.name + ".partial")
lock_path = pack.with_name(pack.name + ".lock")
with lock_path.open("w") as lock:
fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
try:
detail = validate_pack(pack, expert_tensors, spec)
except (OSError, ValueError) as exc:
print(f"EXPERT_PACK_INVALID path={pack} detail={exc}", flush=True)
if args.check_only:
return 1
else:
print(f"EXPERT_PACK_VALID path={pack} {detail}", flush=True)
return 0
for path in (pack, partial):
if path.exists():
print(f"EXPERT_PACK_REMOVE_INVALID path={path}", flush=True)
path.unlink()
estimated_size = estimate_ggml_moe_pack_size(expert_tensors, spec)
safety_margin = int(args.safety_margin_gib * 1024**3)
available = shutil.disk_usage(pack.parent).free
if available < estimated_size + safety_margin:
raise OSError(
f"insufficient space for Kimi Expert Pack: available={available}, "
f"required={estimated_size + safety_margin}"
)
print(
f"EXPERT_PACK_BUILD_START output={pack} size={estimated_size}",
flush=True,
)
def report_progress(completed: int, total: int) -> None:
print(
f"EXPERT_PACK_BUILD_PROGRESS completed={completed} total={total}",
flush=True,
)
write_ggml_moe_pack(pack, expert_tensors, spec, progress=report_progress)
detail = validate_pack(pack, expert_tensors, spec)
print(f"EXPERT_PACK_READY path={pack} {detail}", flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+337
View File
@@ -0,0 +1,337 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import argparse
import hashlib
import json
import random
import time
from pathlib import Path
try:
from .format import (
ROLE_NAMES,
IndexEntry,
read_header,
read_index,
sha256_file,
)
except ImportError:
from format import ( # type: ignore[no-redef]
ROLE_NAMES,
IndexEntry,
read_header,
read_index,
sha256_file,
)
CHUNK_BYTES = 16 * 1024 * 1024
def hash_range(stream, offset: int, nbytes: int) -> str:
digest = hashlib.sha256()
stream.seek(offset)
remaining = nbytes
while remaining:
chunk = stream.read(min(remaining, CHUNK_BYTES))
if not chunk:
raise EOFError(f"short read at offset {offset}; {remaining} bytes remain")
digest.update(chunk)
remaining -= len(chunk)
return digest.hexdigest()
def compare_ranges(source, pack, entry: IndexEntry) -> None:
remaining = entry.pack_nbytes
source_offset = entry.source_slice_offset
pack_offset = entry.pack_offset
while remaining:
length = min(remaining, CHUNK_BYTES)
source.seek(source_offset)
pack.seek(pack_offset)
source_data = source.read(length)
pack_data = pack.read(length)
if len(source_data) != length or len(pack_data) != length:
raise EOFError(f"short source/pack read for entry {entry.key}")
if source_data != pack_data:
raise ValueError(f"source/pack bytes differ for entry {entry.key}")
source_offset += length
pack_offset += length
remaining -= length
def validate(args: argparse.Namespace) -> dict[str, object]:
started = time.monotonic()
pack_path = args.pack.resolve(strict=True)
manifest_path = args.manifest.resolve(strict=True)
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
if manifest.get("format") != "SGLANG-EXPERTPACK-v1" or not manifest.get("complete"):
raise ValueError("manifest is not a complete SGLANG-EXPERTPACK-v1 manifest")
if Path(manifest["pack_path"]).resolve() != pack_path:
raise ValueError("manifest pack path does not match --pack")
if pack_path.stat().st_size != int(manifest["pack_size"]):
raise ValueError("pack size does not match manifest")
source_path = (
args.source.resolve(strict=True)
if args.source is not None
else Path(manifest["source"]["path"]).resolve(strict=True)
)
if source_path.stat().st_size != int(manifest["source"]["size"]):
raise ValueError("source size does not match manifest")
with pack_path.open("rb", buffering=0) as pack:
header = read_header(pack)
index_start = header.header_bytes
pack.seek(index_start)
raw_index = pack.read(header.index_count * header.entry_bytes)
if len(raw_index) != header.index_count * header.entry_bytes:
raise ValueError("pack index is truncated")
if hashlib.sha256(raw_index).hexdigest() != manifest["index_sha256"]:
raise ValueError("pack index SHA-256 does not match manifest")
entries = read_index(pack, header)
model = manifest["model"]
source = manifest["source"]
for actual, expected, field in (
(
header.model_identity_sha256,
model["model_identity_sha256"],
"model identity digest",
),
(header.source_blob_sha256, source["sha256"], "source digest"),
(header.config_sha256, model["config_sha256"], "config digest"),
(header.num_layers, model["num_layers"], "layer count"),
(header.num_experts, model["num_routed_experts"], "expert count"),
(header.top_k, model["top_k"], "top-k"),
(header.index_count, manifest["index_count"], "index count"),
(header.data_start, manifest["data_start"], "data start"),
(header.alignment, manifest["alignment"], "alignment"),
):
if actual != expected:
raise ValueError(f"pack header {field} does not match manifest")
expected_keys = {
(layer, expert, role)
for layer in range(header.num_layers)
for expert in range(header.num_experts)
for role in ROLE_NAMES
}
by_key = {(entry.layer, entry.expert, entry.role): entry for entry in entries}
if len(by_key) != len(entries) or set(by_key) != expected_keys:
raise ValueError("pack index does not have exact layer/expert/role coverage")
tensor_map = {tensor["name"]: tensor for tensor in manifest["tensors"]}
non_routed = [
tensor for tensor in manifest["tensors"] if tensor["category"] == "non_routed"
]
routed = [
tensor
for tensor in manifest["tensors"]
if tensor["category"] == "routed_expert"
]
if len(non_routed) != manifest["coverage"]["non_routed_tensor_count"]:
raise ValueError("non-routed tensor coverage does not match manifest summary")
if len(routed) != manifest["coverage"]["routed_tensor_count"]:
raise ValueError("routed tensor coverage does not match manifest summary")
ranges = []
object_stride = int(manifest["object_stride"])
for layer in range(header.num_layers):
for expert in range(header.num_experts):
object_entries = [by_key[(layer, expert, role)] for role in ROLE_NAMES]
expected_object_start = (
header.data_start
+ (layer * header.num_experts + expert) * object_stride
)
if object_entries[0].pack_offset != expected_object_start:
raise ValueError(
f"object {(layer, expert)} is not at its expected aligned offset"
)
if expected_object_start % header.alignment:
raise ValueError(f"object {(layer, expert)} is not aligned")
cursor = expected_object_start
generations = set()
for entry in object_entries:
entry.pack()
tensor = tensor_map.get(entry.tensor_name)
if tensor is None or tensor["category"] != "routed_expert":
raise ValueError(
f"entry {entry.key} does not map to a routed tensor"
)
if (
entry.pack_offset != cursor
or entry.pack_nbytes != entry.source_slice_nbytes
):
raise ValueError(
f"entry {entry.key} breaks identity triplet layout"
)
if (
entry.transform_id != "identity-v1"
or entry.checksum != entry.source_slice_sha256
):
raise ValueError(
f"entry {entry.key} is not an auditable identity transform"
)
if entry.source_tensor_offset != tensor["source_offset"]:
raise ValueError(f"entry {entry.key} source tensor offset mismatch")
if entry.source_tensor_nbytes != tensor["source_nbytes"]:
raise ValueError(f"entry {entry.key} source tensor size mismatch")
if entry.source_tensor_sha256 != tensor["source_payload_sha256"]:
raise ValueError(f"entry {entry.key} source tensor hash mismatch")
expected_slice_offset = (
entry.source_tensor_offset + expert * entry.source_slice_nbytes
)
if entry.source_slice_offset != expected_slice_offset:
raise ValueError(f"entry {entry.key} source slice offset mismatch")
if entry.source_slice_offset + entry.source_slice_nbytes > (
entry.source_tensor_offset + entry.source_tensor_nbytes
):
raise ValueError(f"entry {entry.key} source slice is out of bounds")
ranges.append(
(
entry.pack_offset,
entry.pack_offset + entry.pack_nbytes,
entry.key,
)
)
generations.add(entry.generation)
cursor += entry.pack_nbytes
if len(generations) != 1:
raise ValueError(
f"object {(layer, expert)} has inconsistent generations"
)
if cursor > expected_object_start + object_stride:
raise ValueError(f"object {(layer, expert)} exceeds its stride")
ranges.sort()
previous_end = header.data_start
for start, end, key in ranges:
if start < previous_end or end > pack_path.stat().st_size:
raise ValueError(f"overlapping or out-of-range pack entry {key}")
previous_end = end
bytes_hashed = 0
pack_hash_ok = None
if args.full_pack_hash:
pack_hash_ok = sha256_file(pack_path) == manifest["pack_sha256"]
bytes_hashed += pack_path.stat().st_size
if not pack_hash_ok:
raise ValueError("full pack SHA-256 does not match manifest")
entry_hash_count = 0
if args.full_pack_entry_hashes:
with pack_path.open("rb", buffering=0) as pack:
for entry in sorted(entries, key=lambda value: value.pack_offset):
if (
hash_range(pack, entry.pack_offset, entry.pack_nbytes)
!= entry.checksum
):
raise ValueError(
f"pack payload checksum mismatch for entry {entry.key}"
)
bytes_hashed += entry.pack_nbytes
entry_hash_count += 1
source_tensor_hash_count = 0
if args.full_source_tensor_hashes:
with source_path.open("rb", buffering=0) as source_stream:
for tensor in sorted(
manifest["tensors"], key=lambda value: value["source_offset"]
):
digest = hash_range(
source_stream,
int(tensor["source_offset"]),
int(tensor["source_nbytes"]),
)
if digest != tensor["source_payload_sha256"]:
raise ValueError(
f"source tensor hash mismatch for {tensor['name']}"
)
bytes_hashed += int(tensor["source_nbytes"])
source_tensor_hash_count += 1
source_file_hash_ok = None
if args.full_source_file_hash:
source_file_hash_ok = sha256_file(source_path) == source["sha256"]
bytes_hashed += source_path.stat().st_size
if not source_file_hash_ok:
raise ValueError("full source file SHA-256 does not match manifest")
sample_count = min(args.source_range_samples, len(entries))
sampled_entries = []
if sample_count:
seed = int(source["sha256"][:16], 16)
sampled_entries = random.Random(seed).sample(entries, sample_count)
with (
source_path.open("rb", buffering=0) as source_stream,
pack_path.open("rb", buffering=0) as pack_stream,
):
for entry in sampled_entries:
compare_ranges(source_stream, pack_stream, entry)
bytes_hashed += entry.pack_nbytes * 2
elapsed_s = time.monotonic() - started
result = {
"status": "PASS",
"pack": str(pack_path),
"manifest": str(manifest_path),
"source": str(source_path),
"layers": header.num_layers,
"experts_per_layer": header.num_experts,
"top_k": header.top_k,
"index_count": len(entries),
"object_count": header.num_layers * header.num_experts,
"non_routed_tensor_count": len(non_routed),
"routed_tensor_count": len(routed),
"full_pack_hash": pack_hash_ok,
"full_pack_entry_hash_count": entry_hash_count,
"full_source_tensor_hash_count": source_tensor_hash_count,
"full_source_file_hash": source_file_hash_ok,
"source_range_compare_count": len(sampled_entries),
"bytes_verified": bytes_hashed,
"elapsed_s": elapsed_s,
"verified_mib_s": bytes_hashed / 1024**2 / elapsed_s if bytes_hashed else None,
}
if args.report is not None:
args.report.parent.mkdir(parents=True, exist_ok=True)
args.report.write_text(
json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8"
)
return result
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Validate SGLANG-EXPERTPACK-v1")
parser.add_argument("--pack", type=Path, required=True)
parser.add_argument("--manifest", type=Path, required=True)
parser.add_argument("--source", type=Path)
parser.add_argument("--source-range-samples", type=int, default=96)
parser.add_argument("--full-pack-hash", action="store_true")
parser.add_argument("--full-pack-entry-hashes", action="store_true")
parser.add_argument("--full-source-tensor-hashes", action="store_true")
parser.add_argument("--full-source-file-hash", action="store_true")
parser.add_argument("--full", action="store_true")
parser.add_argument("--report", type=Path)
args = parser.parse_args()
if args.source_range_samples < 0:
parser.error("--source-range-samples must be non-negative")
if args.full:
args.full_pack_hash = True
args.full_pack_entry_hashes = True
args.full_source_tensor_hashes = True
args.full_source_file_hash = True
return args
def main() -> int:
args = parse_args()
print(json.dumps(validate(args), indent=2, sort_keys=True))
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -114,14 +114,19 @@ def _expert_pack_path(gguf: Path) -> Path:
return gguf.parent / f"{gguf.name[: match.start()]}.expert-major.pack"
def _repo_root() -> Path:
for candidate in Path(__file__).resolve().parents:
if (candidate / "tools" / "expert_pack" / "prepare_kimi_pack.py").is_file():
return candidate
raise RuntimeError(
"expert_pack cannot auto-build Kimi artifacts from an installed package; "
"run from an SGLang source checkout"
def _expert_pack_tools_dir() -> Path:
tools_dir = Path(__file__).with_name("expert_pack")
required_tools = (
"prepare_deepseek_pack.py",
"prepare_kimi_manifest.py",
"prepare_kimi_pack.py",
)
missing = [name for name in required_tools if not (tools_dir / name).is_file()]
if missing:
raise RuntimeError(
"expert_pack preparation tools are missing: " + ", ".join(missing)
)
return tools_dir
def ensure_kimi_assets(
@@ -144,26 +149,26 @@ def ensure_kimi_assets(
manifest = artifact_dir / "kimi-k3-expert-pack.manifest.json"
tokenizer = resolve_kimi_tokenizer(gguf, tokenizer_dir)
lock_path = pack.with_name(pack.name + ".startup.lock")
repo = _repo_root()
tools_dir = _expert_pack_tools_dir()
with lock_path.open("w") as lock:
fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
model_dir = prepare_kimi_model_metadata(tokenizer, artifact_dir)
subprocess.run(
[
sys.executable,
str(repo / "tools" / "expert_pack" / "prepare_kimi_pack.py"),
str(tools_dir / "prepare_kimi_pack.py"),
"--gguf",
str(gguf),
"--model-config",
str(model_dir / "config.json"),
],
cwd=repo,
cwd=tools_dir,
check=True,
)
subprocess.run(
[
sys.executable,
str(repo / "tools" / "expert_pack" / "prepare_kimi_manifest.py"),
str(tools_dir / "prepare_kimi_manifest.py"),
"--gguf-dir",
str(gguf_dir),
"--expert-pack",
@@ -177,7 +182,7 @@ def ensure_kimi_assets(
"--payload-samples",
"6",
],
cwd=repo,
cwd=tools_dir,
check=True,
)
return {
@@ -480,9 +485,9 @@ def _deepseek_digest(value: object, field: str) -> str:
def _prepare_deepseek_pack(
source: Path, model_config: Path, repo: Path
source: Path, model_config: Path, tools_dir: Path
) -> tuple[Path, Path]:
tool = repo / "tools" / "expert_pack" / "prepare_deepseek_pack.py"
tool = tools_dir / "prepare_deepseek_pack.py"
if not tool.is_file():
raise FileNotFoundError(f"missing DeepSeek Expert Pack preparer: {tool}")
subprocess.run(
@@ -494,7 +499,7 @@ def _prepare_deepseek_pack(
"--model-config",
str(model_config),
],
cwd=repo,
cwd=tools_dir,
check=True,
)
return (
@@ -514,14 +519,14 @@ def prepare_raw_deepseek_server_args(
source = Path(cfg.model_path).expanduser().resolve(strict=True)
if not source.is_file():
return
repo = _repo_root()
tools_dir = _expert_pack_tools_dir()
artifact_dir = _deepseek_artifact_dir_for_source(source).resolve()
lock_path = artifact_dir / "deepseek-v4-startup.lock"
artifact_dir.mkdir(parents=True, exist_ok=True)
with lock_path.open("w") as lock:
fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
model_config = _prepare_deepseek_model_metadata(source, artifact_dir)
pack, manifest = _prepare_deepseek_pack(source, model_config, repo)
pack, manifest = _prepare_deepseek_pack(source, model_config, tools_dir)
manifest_value = json.loads(manifest.read_text(encoding="utf-8"))
source_value = manifest_value.get("source") or {}
model_value = manifest_value.get("model") or {}