Initial public ModelForge release
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
from datetime import UTC, datetime, timedelta
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from modelforge_api.domain.contracts import (
|
||||
ArtifactProvenance,
|
||||
BenchmarkEnvironmentFingerprint,
|
||||
CapabilityContractManifest,
|
||||
MigrationContract,
|
||||
ProjectBindingManifest,
|
||||
RuntimeProfileContract,
|
||||
)
|
||||
from modelforge_api.domain.enums import MigrationStatus, UpgradeClass
|
||||
|
||||
|
||||
def minimal_embedding_contract(**overrides):
|
||||
payload = {
|
||||
"capability": "rag.embedding",
|
||||
"version": 1,
|
||||
"description": "test",
|
||||
"input_schema": {"type": "object"},
|
||||
"output_schema": {"type": "object"},
|
||||
"modalities": {"input": ["text"], "output": ["vector"]},
|
||||
"vector": {"cross_deployment_compatible": False},
|
||||
"quality_metrics": ["recall_at_5"],
|
||||
"upgrade_class": "requires_reindex",
|
||||
"production_priority": "production",
|
||||
"default_residency": "keep_warm",
|
||||
"estate": {
|
||||
"category": "RAG",
|
||||
"purpose": "test retrieval",
|
||||
"stability": "experimental",
|
||||
"resource_class": "LIGHT",
|
||||
"evaluation_type": "retrieval",
|
||||
"consumers": [],
|
||||
"payload_limits": {"max_bytes": 1024},
|
||||
},
|
||||
}
|
||||
payload.update(overrides)
|
||||
return payload
|
||||
|
||||
|
||||
def test_embedding_contract_requires_reindex_when_spaces_are_not_compatible() -> None:
|
||||
CapabilityContractManifest.model_validate(minimal_embedding_contract())
|
||||
with pytest.raises(ValidationError, match="requires_reindex"):
|
||||
CapabilityContractManifest.model_validate(
|
||||
minimal_embedding_contract(upgrade_class="transparent")
|
||||
)
|
||||
|
||||
|
||||
def test_project_binding_rejects_concrete_model_fields() -> None:
|
||||
with pytest.raises(ValidationError):
|
||||
ProjectBindingManifest.model_validate(
|
||||
{
|
||||
"contract_version": 1,
|
||||
"channel": "stable",
|
||||
"priority": "production",
|
||||
"model_id": "vendor/model",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_artifact_provenance_validates_digest_and_derived_lineage() -> None:
|
||||
digest = "a" * 64
|
||||
provenance = ArtifactProvenance(
|
||||
upstream_repository="org/model",
|
||||
resolved_commit_sha="b" * 40,
|
||||
filename="model.safetensors",
|
||||
artifact_type="weights",
|
||||
sha256=digest,
|
||||
)
|
||||
assert provenance.sha256 == digest
|
||||
with pytest.raises(ValidationError, match="derivation tool"):
|
||||
ArtifactProvenance(
|
||||
upstream_repository="org/model",
|
||||
resolved_commit_sha="b" * 40,
|
||||
filename="model.gguf",
|
||||
artifact_type="weights",
|
||||
sha256="c" * 64,
|
||||
source_artifact_sha256=digest,
|
||||
)
|
||||
|
||||
|
||||
def test_runtime_profile_security_defaults_and_stable_fingerprint() -> None:
|
||||
profile = RuntimeProfileContract(
|
||||
runtime_type="llama_cpp",
|
||||
runtime_version="1.0",
|
||||
artifact_sha256="a" * 64,
|
||||
)
|
||||
assert profile.trust_remote_code is False
|
||||
assert profile.network_egress is False
|
||||
assert profile.fingerprint == profile.fingerprint
|
||||
|
||||
|
||||
def test_benchmark_comparability_detects_runtime_or_hardware_change() -> None:
|
||||
base = BenchmarkEnvironmentFingerprint(
|
||||
runtime_type="vllm",
|
||||
runtime_version="1",
|
||||
runtime_image_digest=None,
|
||||
launch_arguments={},
|
||||
cuda_version="13",
|
||||
driver_version="600",
|
||||
accelerator_name="GPU A",
|
||||
accelerator_uuid="gpu-1",
|
||||
context_length=4096,
|
||||
concurrency=1,
|
||||
seed=42,
|
||||
operating_system="linux",
|
||||
)
|
||||
changed = base.model_copy(update={"driver_version": "601"})
|
||||
assert base.comparable_with(base)
|
||||
assert not base.comparable_with(changed)
|
||||
|
||||
|
||||
def test_embedding_migration_requires_distinct_shadow_and_reindex() -> None:
|
||||
now = datetime.now(UTC)
|
||||
valid = MigrationContract(
|
||||
project_id="examplerag",
|
||||
capability="rag.embedding",
|
||||
source_deployment_id="old",
|
||||
target_deployment_id="new",
|
||||
upgrade_class=UpgradeClass.REQUIRES_REINDEX,
|
||||
current_index_ref="index-v1",
|
||||
shadow_index_ref="index-v2-shadow",
|
||||
status=MigrationStatus.PLANNED,
|
||||
rollback_retain_until=now + timedelta(days=7),
|
||||
)
|
||||
assert valid.shadow_index_ref != valid.current_index_ref
|
||||
with pytest.raises(ValidationError, match="requires_reindex"):
|
||||
valid.model_copy(
|
||||
update={"upgrade_class": UpgradeClass.TRANSPARENT}, deep=True
|
||||
).model_validate({**valid.model_dump(), "upgrade_class": "transparent"})
|
||||
Reference in New Issue
Block a user