distributed-gguf-runtime: add CMake skeleton, gRPC harness, split-GGUF provisioning, performance contracts
DGR-019 Lock alpha/beta performance contracts (evidence + contract framework) DGR-020 Run controlled whole-model GGUF baseline (benchmark results & contracts) DGR-024 Real generated-gRPC protocol harness (shard_runtime_server.py + tests) DGR-026 split-GGUF provisioning outside /home (provision script + manifest + tests) DGR-028 Numbered patch-stack apply & verify (llama_cpp_dependency.py + UPSTREAM_LOCK.json) DGR-029 Native CMake skeleton + deterministic CPU lane (UPSTREAM_LOCK.json + cmake gating) New modules: packages/node/meshnet_node/dgr_performance/ — performance contract framework packages/node/meshnet_node/split_gguf/ — split-GGUF manifest & provisioning scripts/provision_split_gguf.py — artifact provisioning CLI tests/test_dgr_performance_contract.py — contract validation tests tests/test_split_gguf_manifest.py — manifest tests tests/test_split_gguf_provision.py — provisioning tests tests/test_shard_runtime_harness.py — gRPC harness tests
This commit is contained in:
47
packages/node/meshnet_node/dgr_performance/__init__.py
Normal file
47
packages/node/meshnet_node/dgr_performance/__init__.py
Normal file
@@ -0,0 +1,47 @@
|
||||
"""DGR-019 — the locked alpha/beta performance contract.
|
||||
|
||||
Four lanes feed the DeepSeek V4 Flash release gates: controlled safetensors
|
||||
and whole-model GGUF are already locked by DGR-001
|
||||
(:mod:`meshnet_node.performance_contract`); dense distributed GGUF and V4
|
||||
Flash distributed are locked here, alongside the alpha (DGR-054) and beta
|
||||
(DGR-070) gate thresholds that read them back.
|
||||
|
||||
Nothing here runs a benchmark or loads a model. This package is the contract
|
||||
DGR-020, DGR-044, DGR-054, and DGR-070 are judged against.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .contract import (
|
||||
ALPHA_VERDICTS,
|
||||
BETA_VERDICTS,
|
||||
CONTRACT_ID,
|
||||
CONTRACT_SCHEMA_VERSION,
|
||||
CONTRACT_V1_SHA256,
|
||||
NEWLY_LOCKED_LANES,
|
||||
REFERENCED_LANES,
|
||||
REQUIRED_LANES,
|
||||
AlphaBetaContract,
|
||||
DgrPerformanceContractError,
|
||||
compute_contract_digest,
|
||||
load_contract,
|
||||
parse_contract,
|
||||
seal_contract,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"ALPHA_VERDICTS",
|
||||
"BETA_VERDICTS",
|
||||
"CONTRACT_ID",
|
||||
"CONTRACT_SCHEMA_VERSION",
|
||||
"CONTRACT_V1_SHA256",
|
||||
"NEWLY_LOCKED_LANES",
|
||||
"REFERENCED_LANES",
|
||||
"REQUIRED_LANES",
|
||||
"AlphaBetaContract",
|
||||
"DgrPerformanceContractError",
|
||||
"compute_contract_digest",
|
||||
"load_contract",
|
||||
"parse_contract",
|
||||
"seal_contract",
|
||||
]
|
||||
323
packages/node/meshnet_node/dgr_performance/contract.py
Normal file
323
packages/node/meshnet_node/dgr_performance/contract.py
Normal file
@@ -0,0 +1,323 @@
|
||||
"""The locked DGR-019 alpha/beta performance contract.
|
||||
|
||||
Four benchmark lanes feed the DeepSeek V4 Flash release gates: controlled
|
||||
safetensors, whole-model GGUF, dense distributed GGUF, and V4 Flash
|
||||
distributed. The first two are already locked by DGR-001
|
||||
(:mod:`meshnet_node.performance_contract`); this module locks the other two,
|
||||
plus the alpha (DGR-054) and beta (DGR-070) gate thresholds that read them
|
||||
back.
|
||||
|
||||
The contract is written down *before* any distributed implementation
|
||||
produces a number (DGR-019), so ``contract_sha256`` is verified the same way
|
||||
:mod:`meshnet_node.glm_alpha.contract` verifies its own alpha contract: the
|
||||
document's canonical content is re-hashed on every load and compared against
|
||||
a digest pinned independently in code. A hand-edited "the threshold was
|
||||
always 5%" mutation is rejected, not silently trusted. An amendment requires
|
||||
a new ``contract_id``/``contract_version`` under human review; the superseded
|
||||
contract is retained.
|
||||
|
||||
Alpha's useful-speed threshold carries one additional property no other
|
||||
threshold here has: ``human_approval``. The numeric ratios are locked now,
|
||||
but DGR-054 (the alpha gate) may not treat useful-speed as satisfied on the
|
||||
ratio alone — a human must approve the observed ratio against real evidence.
|
||||
That is a property of *how the threshold may be used*, not a weaker
|
||||
threshold, and it is asserted structurally by :func:`parse_contract`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from importlib.resources import files
|
||||
from pathlib import Path
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Mapping
|
||||
|
||||
CONTRACT_SCHEMA_VERSION = 1
|
||||
CONTRACT_VERSION = 1
|
||||
CONTRACT_ID = "dgr-alpha-beta-performance/v1"
|
||||
CONTRACT_V1_SHA256 = "cb5a482a8f142bf45b1dd401743d408acbfe5f85bab86023144a8c9485ac6379"
|
||||
|
||||
_CONTRACT_RESOURCE = "alpha-beta-contract-v1.json"
|
||||
|
||||
DIGEST_FIELD = "contract_sha256"
|
||||
|
||||
REQUIRED_LANES: tuple[str, ...] = (
|
||||
"controlled-safetensors",
|
||||
"whole-model-gguf",
|
||||
"dense-distributed-gguf",
|
||||
"v4-flash-distributed",
|
||||
)
|
||||
|
||||
# Lanes DGR-019 locks directly; the other two are already locked by DGR-001
|
||||
# (meshnet_node.performance_contract) and are referenced, not re-defined.
|
||||
NEWLY_LOCKED_LANES: tuple[str, ...] = ("dense-distributed-gguf", "v4-flash-distributed")
|
||||
REFERENCED_LANES: tuple[str, ...] = ("controlled-safetensors", "whole-model-gguf")
|
||||
|
||||
ALPHA_VERDICTS: tuple[str, ...] = ("alpha", "optimize", "stop")
|
||||
BETA_VERDICTS: tuple[str, ...] = ("beta", "targeted-optimization", "stop-rollback")
|
||||
|
||||
REQUIRED_TOP_LEVEL_SECTIONS: tuple[str, ...] = (
|
||||
"prompt_set",
|
||||
"sampling",
|
||||
"lanes",
|
||||
"gain_attribution",
|
||||
"certification_scenarios",
|
||||
"alpha",
|
||||
"beta",
|
||||
)
|
||||
|
||||
|
||||
class DgrPerformanceContractError(ValueError):
|
||||
"""Raised when the alpha/beta performance contract is missing, malformed, or mutated."""
|
||||
|
||||
|
||||
def canonical_sha256(value: Any) -> str:
|
||||
"""SHA-256 over canonical JSON — the repository's digest convention."""
|
||||
payload = json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
||||
return hashlib.sha256(payload.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def contract_signing_payload(document: Mapping[str, Any]) -> dict:
|
||||
"""The contract content the digest covers: everything except the digest itself."""
|
||||
unsigned = dict(document)
|
||||
unsigned.pop(DIGEST_FIELD, None)
|
||||
return unsigned
|
||||
|
||||
|
||||
def compute_contract_digest(document: Mapping[str, Any]) -> str:
|
||||
return canonical_sha256(_thaw_json(contract_signing_payload(document)))
|
||||
|
||||
|
||||
def _freeze_json(value: Any) -> Any:
|
||||
if isinstance(value, Mapping):
|
||||
return MappingProxyType({str(key): _freeze_json(item) for key, item in value.items()})
|
||||
if isinstance(value, list):
|
||||
return tuple(_freeze_json(item) for item in value)
|
||||
return value
|
||||
|
||||
|
||||
def _thaw_json(value: Any) -> Any:
|
||||
if isinstance(value, Mapping):
|
||||
return {str(key): _thaw_json(item) for key, item in value.items()}
|
||||
if isinstance(value, tuple):
|
||||
return [_thaw_json(item) for item in value]
|
||||
return value
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AlphaBetaContract:
|
||||
"""A locked, digest-bound alpha/beta performance contract."""
|
||||
|
||||
schema_version: int
|
||||
contract_version: int
|
||||
contract_id: str
|
||||
locked_at: str
|
||||
locked_by: str
|
||||
lanes: Mapping[str, Mapping[str, Any]]
|
||||
gain_attribution: Mapping[str, Any]
|
||||
certification_scenarios: Mapping[str, Any]
|
||||
alpha: Mapping[str, Any]
|
||||
beta: Mapping[str, Any]
|
||||
amendment_policy: str
|
||||
digest: str
|
||||
raw: Mapping[str, Any]
|
||||
source: str = "<memory>"
|
||||
|
||||
def lane(self, name: str) -> Mapping[str, Any]:
|
||||
if name not in self.lanes:
|
||||
raise DgrPerformanceContractError(f"lane {name!r} is missing from {self.source}")
|
||||
return self.lanes[name]
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return _thaw_json(self.raw)
|
||||
|
||||
|
||||
def parse_contract(data: Any, source: str = "<memory>") -> AlphaBetaContract:
|
||||
"""Validate a contract document and verify it has not been mutated since locking."""
|
||||
if not isinstance(data, Mapping):
|
||||
raise DgrPerformanceContractError(f"contract root in {source} must be a JSON object")
|
||||
|
||||
schema_version = data.get("schema_version")
|
||||
if (
|
||||
not isinstance(schema_version, int)
|
||||
or isinstance(schema_version, bool)
|
||||
or schema_version != CONTRACT_SCHEMA_VERSION
|
||||
):
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} declares contract schema version {schema_version!r}, but this node "
|
||||
f"reads version {CONTRACT_SCHEMA_VERSION}"
|
||||
)
|
||||
|
||||
contract_version = data.get("contract_version")
|
||||
if (
|
||||
not isinstance(contract_version, int)
|
||||
or isinstance(contract_version, bool)
|
||||
or contract_version != CONTRACT_VERSION
|
||||
):
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} declares contract version {contract_version!r}, but this node reads "
|
||||
f"version {CONTRACT_VERSION}"
|
||||
)
|
||||
|
||||
contract_id = data.get("contract_id")
|
||||
if contract_id != CONTRACT_ID:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} declares contract_id {contract_id!r}, but this node is locked to "
|
||||
f"{CONTRACT_ID!r}"
|
||||
)
|
||||
|
||||
for field in ("locked_at", "locked_by"):
|
||||
value = data.get(field)
|
||||
if not isinstance(value, str) or not value.strip():
|
||||
raise DgrPerformanceContractError(f"{source} must carry a non-empty {field}")
|
||||
|
||||
if not data.get("locked_before_target_execution"):
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} does not assert locked_before_target_execution; a contract written "
|
||||
"after the results are known is not a contract"
|
||||
)
|
||||
|
||||
declared = data.get(DIGEST_FIELD)
|
||||
if not isinstance(declared, str) or not declared:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} carries no {DIGEST_FIELD}; an unsealed contract cannot prove it "
|
||||
"predates the results it judges"
|
||||
)
|
||||
|
||||
computed = compute_contract_digest(data)
|
||||
if computed != declared:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} has been modified since it was locked: its content hashes to "
|
||||
f"{computed}, but it declares {declared}. Thresholds are locked before "
|
||||
"benchmark result ingestion and may not be weakened afterwards. To change them, "
|
||||
"open a new contract_id under human review; do not edit this one."
|
||||
)
|
||||
|
||||
missing_sections = [
|
||||
name for name in REQUIRED_TOP_LEVEL_SECTIONS if not isinstance(data.get(name), Mapping)
|
||||
]
|
||||
if missing_sections:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} is missing locked section(s) {missing_sections}"
|
||||
)
|
||||
|
||||
lanes = data["lanes"]
|
||||
missing_lanes = [name for name in REQUIRED_LANES if name not in lanes]
|
||||
if missing_lanes:
|
||||
raise DgrPerformanceContractError(f"{source} is missing lane(s) {missing_lanes}")
|
||||
for name in REFERENCED_LANES:
|
||||
if not lanes[name].get("locked_elsewhere"):
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} lane {name!r} must reference its existing DGR-001 lock, not "
|
||||
"re-define one"
|
||||
)
|
||||
for name in NEWLY_LOCKED_LANES:
|
||||
for required_field in ("prompt_ids", "hardware", "metrics", "certification_scenarios"):
|
||||
if required_field not in lanes[name]:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} lane {name!r} is missing {required_field!r}"
|
||||
)
|
||||
|
||||
alpha = data["alpha"]
|
||||
alpha_verdicts = alpha.get("verdicts")
|
||||
if not isinstance(alpha_verdicts, list) or list(alpha_verdicts) != list(ALPHA_VERDICTS):
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} alpha.verdicts must be exactly {list(ALPHA_VERDICTS)}"
|
||||
)
|
||||
human_approval = alpha.get("useful_speed", {}).get("human_approval")
|
||||
if not isinstance(human_approval, Mapping) or human_approval.get("required") is not True:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} alpha.useful_speed.human_approval.required must be true; alpha "
|
||||
"requires a human-approved useful-speed threshold, not an automatic one"
|
||||
)
|
||||
|
||||
beta = data["beta"]
|
||||
beta_verdicts = beta.get("verdicts")
|
||||
if not isinstance(beta_verdicts, list) or list(beta_verdicts) != list(BETA_VERDICTS):
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} beta.verdicts must be exactly {list(BETA_VERDICTS)}"
|
||||
)
|
||||
missing_beta_axes = [
|
||||
axis for axis in ("concurrency", "long_context", "failure", "sustained_throughput")
|
||||
if axis not in beta
|
||||
]
|
||||
if missing_beta_axes:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} beta is missing axis/axes {missing_beta_axes}"
|
||||
)
|
||||
|
||||
amendment_policy = data.get("amendment_policy")
|
||||
if not isinstance(amendment_policy, str) or not amendment_policy.strip():
|
||||
raise DgrPerformanceContractError(f"{source} must state its amendment policy")
|
||||
|
||||
if declared != CONTRACT_V1_SHA256:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} is a re-sealed mutation of {CONTRACT_ID}: digest {declared} does not "
|
||||
f"match the trusted pre-execution digest {CONTRACT_V1_SHA256}. An amendment "
|
||||
"requires a new supported contract identity under human review."
|
||||
)
|
||||
|
||||
frozen = _freeze_json(data)
|
||||
|
||||
return AlphaBetaContract(
|
||||
schema_version=schema_version,
|
||||
contract_version=contract_version,
|
||||
contract_id=contract_id,
|
||||
locked_at=str(data["locked_at"]),
|
||||
locked_by=str(data["locked_by"]),
|
||||
lanes=frozen["lanes"],
|
||||
gain_attribution=frozen["gain_attribution"],
|
||||
certification_scenarios=frozen["certification_scenarios"],
|
||||
alpha=frozen["alpha"],
|
||||
beta=frozen["beta"],
|
||||
amendment_policy=amendment_policy,
|
||||
digest=declared,
|
||||
raw=frozen,
|
||||
source=source,
|
||||
)
|
||||
|
||||
|
||||
def load_contract(path: Path | None = None) -> AlphaBetaContract:
|
||||
"""Load the packaged alpha/beta performance contract, or one at ``path``."""
|
||||
if path is not None:
|
||||
source = str(path)
|
||||
try:
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
except OSError as exc:
|
||||
raise DgrPerformanceContractError(f"cannot read {source}: {exc.strerror or exc}") from exc
|
||||
else:
|
||||
source = f"packaged {_CONTRACT_RESOURCE}"
|
||||
try:
|
||||
raw = (
|
||||
files("meshnet_node.dgr_performance")
|
||||
.joinpath("data", _CONTRACT_RESOURCE)
|
||||
.read_text(encoding="utf-8")
|
||||
)
|
||||
except (OSError, FileNotFoundError, ModuleNotFoundError) as exc:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} is missing from this node installation ({type(exc).__name__})"
|
||||
) from exc
|
||||
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise DgrPerformanceContractError(
|
||||
f"{source} is not valid JSON: {exc.msg} at line {exc.lineno} column {exc.colno}"
|
||||
) from exc
|
||||
|
||||
return parse_contract(data, source=source)
|
||||
|
||||
|
||||
def seal_contract(document: Mapping[str, Any]) -> dict:
|
||||
"""Return the document with a freshly computed digest.
|
||||
|
||||
This is the only supported way to produce a contract file. It is
|
||||
deliberately not called at load time: sealing on load would turn every
|
||||
mutation into a valid contract, which is precisely the property the
|
||||
digest exists to deny.
|
||||
"""
|
||||
sealed = dict(document)
|
||||
sealed[DIGEST_FIELD] = compute_contract_digest(document)
|
||||
return sealed
|
||||
@@ -0,0 +1,287 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"contract_version": 1,
|
||||
"contract_id": "dgr-alpha-beta-performance/v1",
|
||||
"locked_at": "2026-07-22",
|
||||
"locked_by": "DGR-019",
|
||||
"locked_before_target_execution": true,
|
||||
"prompt_set": {
|
||||
"id": "dgr-fixed-prompt-set-v1",
|
||||
"prompts": [
|
||||
{
|
||||
"id": "short-instruction",
|
||||
"text": "Summarize the following changelog entry in one sentence: Added distributed layer-range execution for GGUF shards using range-aware tensor ownership.",
|
||||
"context_class": "short"
|
||||
},
|
||||
{
|
||||
"id": "code-completion",
|
||||
"text": "def fibonacci(n):\n \"\"\"Return the nth Fibonacci number.\"\"\"\n",
|
||||
"context_class": "short"
|
||||
},
|
||||
{
|
||||
"id": "multi-step-reasoning",
|
||||
"text": "A route has three shards, each holding a contiguous layer range. If shard A owns layers 0-13, shard B owns layers 14-27, and shard C owns layers 28-42, how many layers does each shard own and which shard is the tail?",
|
||||
"context_class": "short"
|
||||
},
|
||||
{
|
||||
"id": "long-context-fill",
|
||||
"text": "Repeat the phrase 'the route holds a contiguous layer range' 1024 times, then answer: which node owns the tail?",
|
||||
"context_class": "long",
|
||||
"notes": "Beta long-context lane only; the driver expands this template to the locked context_tokens length rather than the literal text carrying that many tokens in this document."
|
||||
}
|
||||
]
|
||||
},
|
||||
"sampling": {
|
||||
"temperature": 0.0,
|
||||
"top_p": 1.0,
|
||||
"top_k": 1,
|
||||
"seed": 1234,
|
||||
"notes": "Greedy by construction, matching meshnet_node.recipe_benchmark.SamplingPolicy defaults: sampling noise must never be indistinguishable from a quantization, transport, or batching effect."
|
||||
},
|
||||
"lanes": {
|
||||
"controlled-safetensors": {
|
||||
"role": "reference recipe",
|
||||
"locked_elsewhere": true,
|
||||
"contract_module": "meshnet_node.performance_contract",
|
||||
"contract_id": "dgr-001-controlled-whole-model-baseline-v1",
|
||||
"contract_schema_version": 1,
|
||||
"notes": "Already locked by DGR-001/performance_contract.py (contract_version=1, immutable ContractThresholds). This document does not re-lock or duplicate those thresholds; it references them so the four lanes are enumerated in one place."
|
||||
},
|
||||
"whole-model-gguf": {
|
||||
"role": "single-node quantization/model-fit comparison against controlled-safetensors",
|
||||
"locked_elsewhere": true,
|
||||
"contract_module": "meshnet_node.performance_contract",
|
||||
"contract_id": "dgr-001-controlled-whole-model-baseline-v1",
|
||||
"contract_schema_version": 1,
|
||||
"notes": "Same locked contract as controlled-safetensors; this is the reference recipe's counterpart lane, not a separate threshold set."
|
||||
},
|
||||
"dense-distributed-gguf": {
|
||||
"role": "multi-shard Meshnet Inference Route running a dense (non-MoE) architecture's GGUF weights across a real multi-machine route via the ShardEngine/native worker",
|
||||
"reference_baseline": "the existing production Meshnet distributed Route Session running the same dense model over safetensors on the same node topology and network",
|
||||
"prompt_ids": [
|
||||
"short-instruction",
|
||||
"code-completion",
|
||||
"multi-step-reasoning"
|
||||
],
|
||||
"context_tokens": 2048,
|
||||
"output_tokens": 128,
|
||||
"concurrency_levels": [
|
||||
1,
|
||||
4
|
||||
],
|
||||
"hardware": {
|
||||
"topology": "named certification scenario only: 2-4-stage or 10-plus-stage real multi-machine route",
|
||||
"network": "same LAN/WAN class as the existing production route it is compared against",
|
||||
"device_class": "generic; not hardcoded to one backend. CPU/CUDA/ROCm/Vulkan/Metal lanes are certified separately per RALPH-CONTEXT.md and only advertised once real-hardware-certified"
|
||||
},
|
||||
"metrics": [
|
||||
"ttft_p50_ms",
|
||||
"ttft_p95_ms",
|
||||
"prefill_tokens_per_sec",
|
||||
"decode_tokens_per_sec",
|
||||
"aggregate_decode_tokens_per_sec",
|
||||
"latency_p50_ms",
|
||||
"latency_p95_ms",
|
||||
"seam_bytes",
|
||||
"seam_latency_ms",
|
||||
"queue_wait_ms",
|
||||
"peak_rss_bytes",
|
||||
"peak_vram_bytes",
|
||||
"failures"
|
||||
],
|
||||
"certification_scenarios": {
|
||||
"stage_count": [
|
||||
"2-4-stage",
|
||||
"10-plus-stage"
|
||||
],
|
||||
"quantization": [
|
||||
"Q4_K_M",
|
||||
"Q8_0",
|
||||
"bf16-reference"
|
||||
]
|
||||
}
|
||||
},
|
||||
"v4-flash-distributed": {
|
||||
"role": "full DeepSeek V4 Flash (43 main layers plus reserved MTP; mHC 4x4096 boundary; 256 routed + 1 shared experts, six routed active) distributed route across a named certification stage-count scenario, MTP reserved and off",
|
||||
"reference_baseline": "the existing production Meshnet distributed Route Session running DeepSeek V4 Flash over safetensors on the same node topology and network, where available; otherwise dense-distributed-gguf runtime/transport overhead is reported as an explicit limitation until DGR-044 pins a safetensors V4 baseline",
|
||||
"prompt_ids": [
|
||||
"short-instruction",
|
||||
"code-completion",
|
||||
"multi-step-reasoning"
|
||||
],
|
||||
"alpha_context_tokens": 4096,
|
||||
"alpha_output_tokens": 128,
|
||||
"alpha_concurrency_levels": [
|
||||
1,
|
||||
4
|
||||
],
|
||||
"beta_context_tokens": 16384,
|
||||
"beta_output_tokens": 512,
|
||||
"beta_concurrency_levels": [
|
||||
1,
|
||||
4,
|
||||
8,
|
||||
16
|
||||
],
|
||||
"beta_prompt_ids": [
|
||||
"short-instruction",
|
||||
"code-completion",
|
||||
"multi-step-reasoning",
|
||||
"long-context-fill"
|
||||
],
|
||||
"hardware": {
|
||||
"topology": "named certification scenario only: 2-4-stage or 10-plus-stage real multi-machine route",
|
||||
"network": "same LAN/WAN class as the existing production route it is compared against",
|
||||
"device_class": "generic; not hardcoded to one backend. CPU/CUDA/ROCm/Vulkan/Metal lanes are certified separately per RALPH-CONTEXT.md and only advertised once real-hardware-certified",
|
||||
"mtp": "reserved and off for alpha; ownership contract, implementation, and benchmark are required before beta per RALPH-CONTEXT.md"
|
||||
},
|
||||
"metrics": [
|
||||
"ttft_p50_ms",
|
||||
"ttft_p95_ms",
|
||||
"prefill_tokens_per_sec",
|
||||
"decode_tokens_per_sec",
|
||||
"aggregate_decode_tokens_per_sec",
|
||||
"latency_p50_ms",
|
||||
"latency_p95_ms",
|
||||
"seam_bytes",
|
||||
"seam_latency_ms",
|
||||
"queue_wait_ms",
|
||||
"peak_rss_bytes",
|
||||
"peak_vram_bytes",
|
||||
"failures",
|
||||
"mtp_enabled"
|
||||
],
|
||||
"certification_scenarios": {
|
||||
"stage_count": [
|
||||
"2-4-stage",
|
||||
"10-plus-stage"
|
||||
],
|
||||
"quantization": [
|
||||
"Q4_K_M",
|
||||
"Q8_0",
|
||||
"bf16-reference"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"gain_attribution": {
|
||||
"quantization_model_fit_metrics": [
|
||||
"resident_memory_ratio",
|
||||
"artifact_size_ratio",
|
||||
"exact_match_rate",
|
||||
"mean_similarity",
|
||||
"peak_rss_bytes",
|
||||
"peak_vram_bytes"
|
||||
],
|
||||
"runtime_transport_batching_kernel_metrics": [
|
||||
"decode_speedup",
|
||||
"ttft_ratio",
|
||||
"aggregate_throughput_speedup",
|
||||
"seam_bytes",
|
||||
"seam_latency_ms",
|
||||
"queue_wait_ms",
|
||||
"prefill_tokens_per_sec"
|
||||
],
|
||||
"rule": "A speed or fit claim must cite which axis moved it: a quantization/model-fit change (recipe swap, weight format) or a runtime/transport/batching/kernel change (ShardEngine, gRPC transport, batching, GGML kernel). A distributed-lane win may not be attributed to quantization when the reference recipe already used the same quantization, and a quantization win may not be attributed to distribution or transport."
|
||||
},
|
||||
"certification_scenarios": {
|
||||
"quantization": {
|
||||
"names": [
|
||||
"Q4_K_M",
|
||||
"Q8_0",
|
||||
"bf16-reference"
|
||||
],
|
||||
"rule": "Named certification-scenario labels only. No product or runtime code path may branch on, default to, or hardcode a specific quantization string; quantization is a dynamic recipe input per RALPH-CONTEXT.md."
|
||||
},
|
||||
"stage_count": {
|
||||
"names": [
|
||||
"2-4-stage",
|
||||
"10-plus-stage"
|
||||
],
|
||||
"rule": "Named certification-scenario labels only, matching DGR-053/DGR-061/DGR-062/DGR-067. No product or runtime code path may hardcode a stage-count range or assume exactly one of these layouts."
|
||||
}
|
||||
},
|
||||
"alpha": {
|
||||
"applies_to_lane": "v4-flash-distributed",
|
||||
"reference_baseline_lane": "dense-distributed-gguf",
|
||||
"correctness": {
|
||||
"min_greedy_token_agreement": 0.9,
|
||||
"min_mean_state_cosine_similarity": 0.999,
|
||||
"forbid_nonfinite_tensors": true,
|
||||
"require_fail_closed_on_fingerprint_mismatch": true,
|
||||
"require_active_moe_routing": true,
|
||||
"require_active_hash_routing_first_three_layers": true,
|
||||
"dense_attention_fallback_satisfies_alpha": false
|
||||
},
|
||||
"useful_speed": {
|
||||
"min_decode_speedup_vs_reference_baseline": 1.25,
|
||||
"max_ttft_ratio_vs_reference_baseline": 1.25,
|
||||
"min_aggregate_throughput_speedup_at_top_concurrency": 1.25,
|
||||
"quality_pass_with_speed_fail_verdict": "stop",
|
||||
"human_approval": {
|
||||
"required": true,
|
||||
"approved": false,
|
||||
"approved_by": null,
|
||||
"approved_at": null,
|
||||
"approval_note": "The ratios above are the proposed useful-speed floor, held at the same 25% margin already locked for the whole-model contract (DGR-001/v1, meshnet_node.performance_contract.ContractThresholds). Alpha certification (DGR-054) may not treat useful-speed as satisfied on ratios alone: a human must explicitly approve the observed ratio against real DGR-020/dense/V4 evidence, and this record is the audit trail for that approval."
|
||||
}
|
||||
},
|
||||
"mtp": {
|
||||
"reserved": true,
|
||||
"enabled_for_alpha": false,
|
||||
"ownership_contract_and_benchmark_required_before_beta": true
|
||||
},
|
||||
"failure_tolerance": {
|
||||
"max_failure_rate": 0.0
|
||||
},
|
||||
"verdicts": [
|
||||
"alpha",
|
||||
"optimize",
|
||||
"stop"
|
||||
],
|
||||
"stop_condition": "Stop DeepSeek V4 Flash alpha certification when correctness fails (greedy token agreement, mean state cosine similarity, nonfinite tensors, or fail-closed fingerprint checks), or when useful-speed is not both numerically satisfied and explicitly human-approved against the reference baseline lane under this plan. A quality pass with a speed fail is always 'stop', never 'optimize' — see performance.quality_pass_with_speed_fail_verdict."
|
||||
},
|
||||
"beta": {
|
||||
"applies_to_lane": "v4-flash-distributed",
|
||||
"adds": [
|
||||
"concurrency",
|
||||
"long_context",
|
||||
"failure",
|
||||
"sustained_throughput"
|
||||
],
|
||||
"concurrency": {
|
||||
"levels": [
|
||||
1,
|
||||
4,
|
||||
8,
|
||||
16
|
||||
],
|
||||
"min_aggregate_throughput_speedup_at_max_concurrency": 1.25,
|
||||
"max_fairness_deviation": 0.2
|
||||
},
|
||||
"long_context": {
|
||||
"context_tokens": 16384,
|
||||
"min_greedy_token_agreement": 0.9,
|
||||
"max_ttft_seconds_at_context": 600
|
||||
},
|
||||
"failure": {
|
||||
"consecutive_clean_cold_starts": 2,
|
||||
"require_worker_loss_aborts_route": true,
|
||||
"require_cache_miss_and_reprefill_on_route_change": true,
|
||||
"forbid_silent_kv_migration": true,
|
||||
"synthetic_workers_satisfy_beta": false
|
||||
},
|
||||
"sustained_throughput": {
|
||||
"min_duration_minutes": 30,
|
||||
"max_throughput_degradation_ratio": 0.1
|
||||
},
|
||||
"verdicts": [
|
||||
"beta",
|
||||
"targeted-optimization",
|
||||
"stop-rollback"
|
||||
],
|
||||
"stop_condition": "Stop or roll back DeepSeek V4 Flash beta when any beta-only threshold fails (concurrency fairness/throughput, long-context correctness or TTFT, failure-recovery semantics, or sustained-throughput degradation), when a required stage-count or quantization certification scenario has no real-hardware evidence, or when MTP evidence is missing given MTP is required before beta per RALPH-CONTEXT.md."
|
||||
},
|
||||
"amendment_policy": "Thresholds are locked before target execution and may not be weakened, moved, or reinterpreted after results are known. A change requires a new contract_id and contract_version under human review, and the superseded contract is retained. This applies independently of alpha.useful_speed.human_approval, which records sign-off on an observed ratio against these unchanged thresholds, not a change to the thresholds themselves.",
|
||||
"contract_sha256": "cb5a482a8f142bf45b1dd401743d408acbfe5f85bab86023144a8c9485ac6379"
|
||||
}
|
||||
@@ -33,6 +33,7 @@ portability — identical to ``CHECKSUM_ALGORITHM_CRC32C`` in the schema.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
@@ -101,10 +102,12 @@ class WireCapture:
|
||||
with self._lock:
|
||||
self.responses.append(bytes(raw))
|
||||
|
||||
def to_dict(self) -> dict[str, list[str]]:
|
||||
def to_dict(self) -> dict[str, list[str] | str]:
|
||||
return {
|
||||
"requests": [r.hex() for r in self.requests],
|
||||
"responses": [r.hex() for r in self.responses],
|
||||
"requests_sha256": hashlib.sha256(b"".join(self.requests)).hexdigest(),
|
||||
"responses_sha256": hashlib.sha256(b"".join(self.responses)).hexdigest(),
|
||||
}
|
||||
|
||||
|
||||
|
||||
39
packages/node/meshnet_node/split_gguf/__init__.py
Normal file
39
packages/node/meshnet_node/split_gguf/__init__.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""Exact split-GGUF artifact manifest and mounted-drive provisioning (DGR-026)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .manifest import (
|
||||
SourceArtifact,
|
||||
SplitArtifactManifest,
|
||||
SplitArtifactManifestError,
|
||||
SplitFile,
|
||||
TokenizerRef,
|
||||
load_split_artifact_manifest,
|
||||
parse_split_artifact_manifest,
|
||||
)
|
||||
from .provision import (
|
||||
ProvisionResult,
|
||||
SplitProvisionError,
|
||||
http_split_fetcher,
|
||||
local_directory_fetcher,
|
||||
provision_split_artifact,
|
||||
reject_home_path,
|
||||
verify_provisioned_split_artifact,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"SourceArtifact",
|
||||
"SplitArtifactManifest",
|
||||
"SplitArtifactManifestError",
|
||||
"SplitFile",
|
||||
"TokenizerRef",
|
||||
"load_split_artifact_manifest",
|
||||
"parse_split_artifact_manifest",
|
||||
"ProvisionResult",
|
||||
"SplitProvisionError",
|
||||
"http_split_fetcher",
|
||||
"local_directory_fetcher",
|
||||
"provision_split_artifact",
|
||||
"reject_home_path",
|
||||
"verify_provisioned_split_artifact",
|
||||
]
|
||||
323
packages/node/meshnet_node/split_gguf/manifest.py
Normal file
323
packages/node/meshnet_node/split_gguf/manifest.py
Normal file
@@ -0,0 +1,323 @@
|
||||
"""Exact split-GGUF artifact manifest (DGR-026).
|
||||
|
||||
A split-GGUF artifact is only as trustworthy as its binding to the whole-model
|
||||
artifact it was cut from. This module defines the manifest that makes a set of
|
||||
split files an *exact*, checkable artifact rather than a pile of files someone
|
||||
happened to name plausibly: it pins the source artifact's own content hash, the
|
||||
tokenizer/revision the splits were tokenized against, and — per split — the
|
||||
exact file name, size, cryptographic hash, and its range/role within the
|
||||
source.
|
||||
|
||||
Quantization and split topology (how many splits, which layers each one
|
||||
covers) are recipe inputs recorded on the manifest, never constants in this
|
||||
module. A manifest with two splits and one with twenty are both valid; nothing
|
||||
here assumes a stage count or a fixed layer range. Provisioning
|
||||
(:mod:`meshnet_node.split_gguf.provision`) consumes whatever this manifest
|
||||
declares.
|
||||
|
||||
This module mirrors two existing conventions rather than inventing new ones:
|
||||
the DGR-017 pinned-shard manifest shape (`meshnet_node.glm_alpha.manifest`) for
|
||||
per-file identity records, and the DGR-003 `DerivativeBinding` range/source
|
||||
convention (`meshnet_node.runtime_recipe`) for binding a split to its source by
|
||||
digest and half-open layer range.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Mapping
|
||||
|
||||
SPLIT_ARTIFACT_MANIFEST_SCHEMA_VERSION = 1
|
||||
|
||||
_SHA256_RE = re.compile(r"\A[0-9a-f]{64}\Z")
|
||||
_REVISION_RE = re.compile(r"\A[0-9a-f]{40}\Z")
|
||||
|
||||
|
||||
class SplitArtifactManifestError(ValueError):
|
||||
"""Raised when a split-GGUF manifest is missing, malformed, or self-inconsistent."""
|
||||
|
||||
|
||||
def canonical_sha256(value: Any) -> str:
|
||||
"""SHA-256 over canonical JSON — the repository's digest convention."""
|
||||
payload = json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
||||
return hashlib.sha256(payload.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def _require_mapping(value: Any, what: str, origin: str) -> Mapping[str, Any]:
|
||||
if not isinstance(value, Mapping):
|
||||
raise SplitArtifactManifestError(
|
||||
f"{what} in {origin} must be a JSON object, got {type(value).__name__}"
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
def _require_text(value: Any, what: str, origin: str) -> str:
|
||||
if not isinstance(value, str) or not value.strip():
|
||||
raise SplitArtifactManifestError(f"{what} in {origin} must be a non-empty string")
|
||||
return value
|
||||
|
||||
|
||||
def _require_int(value: Any, what: str, origin: str, minimum: int = 0) -> int:
|
||||
if not isinstance(value, int) or isinstance(value, bool):
|
||||
raise SplitArtifactManifestError(
|
||||
f"{what} in {origin} must be an integer, got {type(value).__name__}"
|
||||
)
|
||||
if value < minimum:
|
||||
raise SplitArtifactManifestError(f"{what} in {origin} must be >= {minimum}, got {value}")
|
||||
return value
|
||||
|
||||
|
||||
def _require_sha256(value: Any, what: str, origin: str) -> str:
|
||||
text = _require_text(value, what, origin)
|
||||
if not _SHA256_RE.match(text):
|
||||
raise SplitArtifactManifestError(
|
||||
f"{what} in {origin} must be a lowercase 64-character hex SHA-256, got {text!r}"
|
||||
)
|
||||
return text
|
||||
|
||||
|
||||
def _require_revision(value: Any, what: str, origin: str) -> str:
|
||||
text = _require_text(value, what, origin)
|
||||
if not _REVISION_RE.match(text):
|
||||
raise SplitArtifactManifestError(
|
||||
f"{what} in {origin} must be a full 40-character commit revision, got {text!r}; "
|
||||
"a branch name, tag, or short SHA is not an immutable pin"
|
||||
)
|
||||
return text
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SourceArtifact:
|
||||
"""The whole-model artifact every split in this manifest was cut from."""
|
||||
|
||||
artifact_id: str
|
||||
repo_id: str
|
||||
revision: str
|
||||
sha256: str
|
||||
size_bytes: int
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"artifact_id": self.artifact_id,
|
||||
"repo_id": self.repo_id,
|
||||
"revision": self.revision,
|
||||
"sha256": self.sha256,
|
||||
"size_bytes": self.size_bytes,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TokenizerRef:
|
||||
"""The exact tokenizer/revision the split artifact's routing assumes."""
|
||||
|
||||
repo_id: str
|
||||
revision: str
|
||||
sha256: str
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {"repo_id": self.repo_id, "revision": self.revision, "sha256": self.sha256}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SplitFile:
|
||||
"""One split-GGUF file: name, size, hash, and its role/range in the source.
|
||||
|
||||
`shard_start`/`shard_end` are half-open (end-exclusive), matching the
|
||||
`DerivativeBinding` protocol convention in `meshnet_node.runtime_recipe`.
|
||||
They are optional because not every split is a layer range — a shared
|
||||
embedding or tokenizer-adjacent split may carry only a `role` label — but
|
||||
when present they must describe a real, non-empty range.
|
||||
"""
|
||||
|
||||
name: str
|
||||
size_bytes: int
|
||||
sha256: str
|
||||
role: str
|
||||
url: str = ""
|
||||
shard_start: int | None = None
|
||||
shard_end: int | None = None
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if (self.shard_start is None) != (self.shard_end is None):
|
||||
raise SplitArtifactManifestError(
|
||||
f"split {self.name!r} must declare both shard_start and shard_end, or neither"
|
||||
)
|
||||
if self.shard_start is not None and self.shard_end is not None:
|
||||
if self.shard_start < 0:
|
||||
raise SplitArtifactManifestError(f"split {self.name!r} shard_start must be >= 0")
|
||||
if self.shard_end <= self.shard_start:
|
||||
raise SplitArtifactManifestError(
|
||||
f"split {self.name!r} shard_end ({self.shard_end}) must be greater than "
|
||||
f"shard_start ({self.shard_start}); an empty range covers nothing"
|
||||
)
|
||||
|
||||
@property
|
||||
def has_range(self) -> bool:
|
||||
return self.shard_start is not None
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
doc: dict[str, Any] = {
|
||||
"name": self.name,
|
||||
"size_bytes": self.size_bytes,
|
||||
"sha256": self.sha256,
|
||||
"role": self.role,
|
||||
"url": self.url,
|
||||
}
|
||||
if self.has_range:
|
||||
doc["shard_start"] = self.shard_start
|
||||
doc["shard_end"] = self.shard_end
|
||||
return doc
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SplitArtifactManifest:
|
||||
"""A parsed, self-consistent exact split-GGUF artifact manifest."""
|
||||
|
||||
schema_version: int
|
||||
manifest_id: str
|
||||
manifest_version: str
|
||||
quantization: str
|
||||
source: SourceArtifact
|
||||
tokenizer: TokenizerRef
|
||||
total_bytes: int
|
||||
splits: tuple[SplitFile, ...]
|
||||
raw: Mapping[str, Any]
|
||||
origin: str = "<memory>"
|
||||
|
||||
@property
|
||||
def digest(self) -> str:
|
||||
"""Stable identity of this manifest, for binding into the DGR-003 recipe identity."""
|
||||
return canonical_sha256(self.raw)
|
||||
|
||||
def split(self, name: str) -> SplitFile:
|
||||
for split in self.splits:
|
||||
if split.name == name:
|
||||
return split
|
||||
raise SplitArtifactManifestError(f"split {name!r} is not in {self.origin}")
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return dict(self.raw)
|
||||
|
||||
|
||||
def _parse_splits(raw: Any, expected_total: int, origin: str) -> tuple[SplitFile, ...]:
|
||||
if not isinstance(raw, list) or not raw:
|
||||
raise SplitArtifactManifestError(f"'splits' in {origin} must be a non-empty JSON array")
|
||||
|
||||
splits: list[SplitFile] = []
|
||||
seen_names: set[str] = set()
|
||||
seen_sha: set[str] = set()
|
||||
for position, entry in enumerate(raw):
|
||||
item = _require_mapping(entry, f"splits[{position}]", origin)
|
||||
name = _require_text(item.get("name"), f"splits[{position}].name", origin)
|
||||
if name in seen_names:
|
||||
raise SplitArtifactManifestError(f"duplicate split name {name!r} in {origin}")
|
||||
seen_names.add(name)
|
||||
|
||||
size_bytes = _require_int(item.get("size_bytes"), f"splits[{name}].size_bytes", origin, minimum=1)
|
||||
sha256 = _require_sha256(item.get("sha256"), f"splits[{name}].sha256", origin)
|
||||
if sha256 in seen_sha:
|
||||
raise SplitArtifactManifestError(
|
||||
f"split {name!r} repeats SHA-256 {sha256}; two distinct splits cannot "
|
||||
"have the same content digest"
|
||||
)
|
||||
seen_sha.add(sha256)
|
||||
|
||||
role = _require_text(item.get("role"), f"splits[{name}].role", origin)
|
||||
url = item.get("url", "")
|
||||
if not isinstance(url, str):
|
||||
raise SplitArtifactManifestError(f"splits[{name}].url in {origin} must be a string")
|
||||
|
||||
shard_start = item.get("shard_start")
|
||||
shard_end = item.get("shard_end")
|
||||
if shard_start is not None:
|
||||
shard_start = _require_int(shard_start, f"splits[{name}].shard_start", origin, minimum=0)
|
||||
if shard_end is not None:
|
||||
shard_end = _require_int(shard_end, f"splits[{name}].shard_end", origin, minimum=1)
|
||||
|
||||
splits.append(
|
||||
SplitFile(
|
||||
name=name,
|
||||
size_bytes=size_bytes,
|
||||
sha256=sha256,
|
||||
role=role,
|
||||
url=url,
|
||||
shard_start=shard_start,
|
||||
shard_end=shard_end,
|
||||
)
|
||||
)
|
||||
|
||||
summed = sum(split.size_bytes for split in splits)
|
||||
if summed != expected_total:
|
||||
raise SplitArtifactManifestError(
|
||||
f"declared total_bytes {expected_total} in {origin} does not equal the sum of "
|
||||
f"the split sizes {summed}; the manifest is not self-consistent"
|
||||
)
|
||||
|
||||
return tuple(splits)
|
||||
|
||||
|
||||
def parse_split_artifact_manifest(data: Any, origin: str = "<memory>") -> SplitArtifactManifest:
|
||||
"""Validate an already-decoded split-artifact manifest document, failing closed."""
|
||||
doc = _require_mapping(data, "manifest root", origin)
|
||||
|
||||
schema_version = _require_int(doc.get("schema_version"), "'schema_version'", origin, minimum=1)
|
||||
if schema_version != SPLIT_ARTIFACT_MANIFEST_SCHEMA_VERSION:
|
||||
raise SplitArtifactManifestError(
|
||||
f"{origin} declares split-artifact manifest schema version {schema_version}, "
|
||||
f"but this reader understands version {SPLIT_ARTIFACT_MANIFEST_SCHEMA_VERSION}"
|
||||
)
|
||||
|
||||
manifest_id = _require_text(doc.get("manifest_id"), "'manifest_id'", origin)
|
||||
manifest_version = _require_text(doc.get("manifest_version"), "'manifest_version'", origin)
|
||||
quantization = _require_text(doc.get("quantization"), "'quantization'", origin)
|
||||
|
||||
source_doc = _require_mapping(doc.get("source"), "'source'", origin)
|
||||
source = SourceArtifact(
|
||||
artifact_id=_require_text(source_doc.get("artifact_id"), "source.artifact_id", origin),
|
||||
repo_id=_require_text(source_doc.get("repo_id"), "source.repo_id", origin),
|
||||
revision=_require_revision(source_doc.get("revision"), "source.revision", origin),
|
||||
sha256=_require_sha256(source_doc.get("sha256"), "source.sha256", origin),
|
||||
size_bytes=_require_int(source_doc.get("size_bytes"), "source.size_bytes", origin, minimum=1),
|
||||
)
|
||||
|
||||
tokenizer_doc = _require_mapping(doc.get("tokenizer"), "'tokenizer'", origin)
|
||||
tokenizer = TokenizerRef(
|
||||
repo_id=_require_text(tokenizer_doc.get("repo_id"), "tokenizer.repo_id", origin),
|
||||
revision=_require_revision(tokenizer_doc.get("revision"), "tokenizer.revision", origin),
|
||||
sha256=_require_sha256(tokenizer_doc.get("sha256"), "tokenizer.sha256", origin),
|
||||
)
|
||||
|
||||
total_bytes = _require_int(doc.get("total_bytes"), "'total_bytes'", origin, minimum=1)
|
||||
splits = _parse_splits(doc.get("splits"), total_bytes, origin)
|
||||
|
||||
return SplitArtifactManifest(
|
||||
schema_version=schema_version,
|
||||
manifest_id=manifest_id,
|
||||
manifest_version=manifest_version,
|
||||
quantization=quantization,
|
||||
source=source,
|
||||
tokenizer=tokenizer,
|
||||
total_bytes=total_bytes,
|
||||
splits=splits,
|
||||
raw=doc,
|
||||
origin=origin,
|
||||
)
|
||||
|
||||
|
||||
def load_split_artifact_manifest(path: Path) -> SplitArtifactManifest:
|
||||
"""Load and validate a split-artifact manifest from *path*."""
|
||||
try:
|
||||
raw = path.read_text(encoding="utf-8")
|
||||
except OSError as exc:
|
||||
raise SplitArtifactManifestError(f"cannot read split-artifact manifest {path}: {exc.strerror or exc}") from exc
|
||||
try:
|
||||
data = json.loads(raw)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise SplitArtifactManifestError(
|
||||
f"{path} is not valid JSON: {exc.msg} at line {exc.lineno} column {exc.colno}"
|
||||
) from exc
|
||||
return parse_split_artifact_manifest(data, origin=str(path))
|
||||
206
packages/node/meshnet_node/split_gguf/provision.py
Normal file
206
packages/node/meshnet_node/split_gguf/provision.py
Normal file
@@ -0,0 +1,206 @@
|
||||
"""Resumable, hash-verifying provisioning of exact split-GGUF artifacts (DGR-026).
|
||||
|
||||
Model artifacts must use configured mounted-drive storage and never `/home`
|
||||
(RALPH-CONTEXT). This module is the enforcement point: every entry point here
|
||||
resolves and rejects a destination under `/home` before touching disk, mirroring
|
||||
the existing `artifact_storage_root` check in
|
||||
`meshnet_node.recipe_drivers._validate_config`.
|
||||
|
||||
Provisioning never trusts a partially-downloaded file. Each split is staged as
|
||||
`<name>.partial` so an interrupted run resumes from the exact byte offset
|
||||
already on disk — a `SplitFetcher` is handed that offset and is responsible for
|
||||
continuing from it — and a partial is promoted to its final name only after its
|
||||
SHA-256 matches the manifest exactly. A short, truncated, or hash-mismatched
|
||||
split is deleted and raises rather than being silently accepted or left on disk
|
||||
to be mistaken for complete later.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import shutil
|
||||
import urllib.request
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
|
||||
from .manifest import SplitArtifactManifest, SplitFile
|
||||
|
||||
_CHUNK_SIZE = 4 * 1024 * 1024
|
||||
_HOME_ROOT = Path("/home")
|
||||
|
||||
|
||||
class SplitProvisionError(ValueError):
|
||||
"""Raised when provisioning cannot produce a manifest-conformant local artifact."""
|
||||
|
||||
|
||||
def reject_home_path(root: Path | str) -> Path:
|
||||
"""Resolve *root* and fail closed if it is (or is under) `/home`.
|
||||
|
||||
Does not require *root* to exist yet — provisioning creates it — so this
|
||||
performs the same structural check as
|
||||
`meshnet_node.recipe_drivers._validate_config` without `strict=True`.
|
||||
"""
|
||||
resolved = Path(root).expanduser().resolve()
|
||||
if not resolved.is_absolute() or resolved == _HOME_ROOT or _HOME_ROOT in resolved.parents:
|
||||
raise SplitProvisionError(
|
||||
f"refusing to provision split-GGUF artifacts under {resolved}: model artifacts "
|
||||
"must use configured mounted-drive storage, never /home"
|
||||
)
|
||||
return resolved
|
||||
|
||||
|
||||
def _sha256_file(path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as f:
|
||||
for chunk in iter(lambda: f.read(_CHUNK_SIZE), b""):
|
||||
digest.update(chunk)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
# fetch(split, partial_dest, resume_from_bytes) must, on success, leave
|
||||
# partial_dest containing exactly the bytes of `split` starting from byte 0,
|
||||
# with total length equal to split.size_bytes; resume_from_bytes bytes are
|
||||
# already present at the start of partial_dest and must not be re-fetched.
|
||||
SplitFetcher = Callable[[SplitFile, Path, int], None]
|
||||
|
||||
|
||||
def local_directory_fetcher(source_dir: Path) -> SplitFetcher:
|
||||
"""A fetcher that copies split bytes from files already present in *source_dir*.
|
||||
|
||||
No network access. Used by deterministic tests against tiny local
|
||||
fixtures, and for provisioning from splits already staged on another local
|
||||
or mounted path (e.g. a pre-synced mirror).
|
||||
"""
|
||||
source_dir = Path(source_dir)
|
||||
|
||||
def fetch(split: SplitFile, dest: Path, resume_from_bytes: int) -> None:
|
||||
source_path = source_dir / split.name
|
||||
if not source_path.is_file():
|
||||
raise SplitProvisionError(f"split source is missing: {source_path}")
|
||||
mode = "r+b" if resume_from_bytes else "wb"
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not dest.exists():
|
||||
dest.touch()
|
||||
with source_path.open("rb") as src, dest.open(mode) as out:
|
||||
src.seek(resume_from_bytes)
|
||||
out.seek(resume_from_bytes)
|
||||
out.truncate(resume_from_bytes)
|
||||
shutil.copyfileobj(src, out, length=_CHUNK_SIZE)
|
||||
|
||||
return fetch
|
||||
|
||||
|
||||
def http_split_fetcher(url_for: Callable[[SplitFile], str], timeout: float = 30.0) -> SplitFetcher:
|
||||
"""A fetcher that downloads each split over HTTP(S) with Range-header resume.
|
||||
|
||||
Falls back to a full restart if the server ignores the `Range` request
|
||||
(some static hosts return `200` with the whole body instead of `206`).
|
||||
"""
|
||||
|
||||
def fetch(split: SplitFile, dest: Path, resume_from_bytes: int) -> None:
|
||||
request = urllib.request.Request(url_for(split))
|
||||
if resume_from_bytes:
|
||||
request.add_header("Range", f"bytes={resume_from_bytes}-")
|
||||
dest.parent.mkdir(parents=True, exist_ok=True)
|
||||
with urllib.request.urlopen(request, timeout=timeout) as resp:
|
||||
resumed = bool(resume_from_bytes) and getattr(resp, "status", 200) == 206
|
||||
with dest.open("ab" if resumed else "wb") as out:
|
||||
shutil.copyfileobj(resp, out, length=_CHUNK_SIZE)
|
||||
|
||||
return fetch
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ProvisionResult:
|
||||
dest_dir: Path
|
||||
verified_splits: tuple[str, ...]
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {"dest_dir": str(self.dest_dir), "verified_splits": list(self.verified_splits)}
|
||||
|
||||
|
||||
def provision_split_artifact(
|
||||
manifest: SplitArtifactManifest,
|
||||
dest_dir: Path,
|
||||
fetch: SplitFetcher,
|
||||
) -> ProvisionResult:
|
||||
"""Provision every split in *manifest* under *dest_dir*: resumable, hash-verified.
|
||||
|
||||
Refuses any destination under `/home`. A split already present at the
|
||||
correct size and hash is left untouched (a re-run is a no-op); a file
|
||||
present with the wrong size or hash is deleted and re-fetched rather than
|
||||
trusted. On success every split is byte- and hash-verified against the
|
||||
manifest before this function returns.
|
||||
"""
|
||||
dest_dir = reject_home_path(dest_dir)
|
||||
dest_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
verified: list[str] = []
|
||||
for split in manifest.splits:
|
||||
final_path = dest_dir / split.name
|
||||
if (
|
||||
final_path.is_file()
|
||||
and final_path.stat().st_size == split.size_bytes
|
||||
and _sha256_file(final_path) == split.sha256
|
||||
):
|
||||
verified.append(split.name)
|
||||
continue
|
||||
if final_path.is_file():
|
||||
final_path.unlink()
|
||||
|
||||
partial_path = dest_dir / f"{split.name}.partial"
|
||||
resume_from = partial_path.stat().st_size if partial_path.is_file() else 0
|
||||
if resume_from > split.size_bytes:
|
||||
partial_path.unlink()
|
||||
resume_from = 0
|
||||
|
||||
if resume_from < split.size_bytes:
|
||||
fetch(split, partial_path, resume_from)
|
||||
|
||||
actual_size = partial_path.stat().st_size if partial_path.is_file() else 0
|
||||
if actual_size != split.size_bytes:
|
||||
raise SplitProvisionError(
|
||||
f"split {split.name!r} is incomplete after provisioning: "
|
||||
f"got {actual_size} of {split.size_bytes} bytes"
|
||||
)
|
||||
|
||||
actual_sha256 = _sha256_file(partial_path)
|
||||
if actual_sha256 != split.sha256:
|
||||
partial_path.unlink()
|
||||
raise SplitProvisionError(
|
||||
f"split {split.name!r} hash mismatch: expected {split.sha256}, got {actual_sha256}"
|
||||
)
|
||||
|
||||
partial_path.replace(final_path)
|
||||
verified.append(split.name)
|
||||
|
||||
verify_provisioned_split_artifact(manifest, dest_dir)
|
||||
return ProvisionResult(dest_dir=dest_dir, verified_splits=tuple(verified))
|
||||
|
||||
|
||||
def verify_provisioned_split_artifact(manifest: SplitArtifactManifest, dest_dir: Path) -> None:
|
||||
"""Fail closed unless every manifest split is present, complete, and hash-exact.
|
||||
|
||||
This is the check a downstream loader — or a resumed provisioning run —
|
||||
should call before trusting *dest_dir*, so a partially-provisioned
|
||||
directory is never mistaken for a ready artifact.
|
||||
"""
|
||||
dest_dir = reject_home_path(dest_dir)
|
||||
missing: list[str] = []
|
||||
mismatched: list[str] = []
|
||||
for split in manifest.splits:
|
||||
path = dest_dir / split.name
|
||||
if not path.is_file():
|
||||
missing.append(split.name)
|
||||
continue
|
||||
if path.stat().st_size != split.size_bytes:
|
||||
mismatched.append(split.name)
|
||||
continue
|
||||
if _sha256_file(path) != split.sha256:
|
||||
mismatched.append(split.name)
|
||||
|
||||
if missing:
|
||||
raise SplitProvisionError(f"missing split(s) in {dest_dir}: {sorted(missing)}")
|
||||
if mismatched:
|
||||
raise SplitProvisionError(f"hash/size mismatch for split(s) in {dest_dir}: {sorted(mismatched)}")
|
||||
@@ -33,17 +33,24 @@
|
||||
"cxx_standard": "17",
|
||||
"configure_flags": [
|
||||
"-DCMAKE_BUILD_TYPE=Release",
|
||||
"-DLLAMA_BUILD_TESTS=OFF",
|
||||
"-DLLAMA_BUILD_TESTS=ON",
|
||||
"-DLLAMA_BUILD_EXAMPLES=ON",
|
||||
"-DLLAMA_BUILD_SERVER=OFF",
|
||||
"-DLLAMA_BUILD_TOOLS=OFF",
|
||||
"-DLLAMA_BUILD_APP=OFF",
|
||||
"-DLLAMA_CURL=OFF"
|
||||
"-DLLAMA_CURL=OFF",
|
||||
"-DGGML_CPU=ON",
|
||||
"-DGGML_BLAS=OFF",
|
||||
"-DGGML_CUDA=OFF",
|
||||
"-DGGML_HIP=OFF",
|
||||
"-DGGML_VULKAN=OFF",
|
||||
"-DGGML_METAL=OFF"
|
||||
],
|
||||
"native_targets": ["llama-gguf-hash"],
|
||||
"native_targets": ["llama-gguf-hash", "test-meshnet-range-ownership"],
|
||||
"smoke_binary": "bin/llama-gguf-hash",
|
||||
"smoke_args": ["--help"],
|
||||
"smoke_output_token": "usage"
|
||||
"smoke_output_token": "usage",
|
||||
"ctest_regex": "^test-meshnet-range-ownership$"
|
||||
},
|
||||
"required_upstream_blobs": {
|
||||
"CMakeLists.txt": "81f23d7e70b7378511af5d01be680c03aebc2b15"
|
||||
|
||||
Reference in New Issue
Block a user