Instructions to use AI45Research/Safin-1-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use AI45Research/Safin-1-4B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="AI45Research/Safin-1-4B", trust_remote_code=True) messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("AI45Research/Safin-1-4B", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use AI45Research/Safin-1-4B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "AI45Research/Safin-1-4B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "AI45Research/Safin-1-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/AI45Research/Safin-1-4B
- SGLang
How to use AI45Research/Safin-1-4B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "AI45Research/Safin-1-4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "AI45Research/Safin-1-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "AI45Research/Safin-1-4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "AI45Research/Safin-1-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use AI45Research/Safin-1-4B with Docker Model Runner:
docker model run hf.co/AI45Research/Safin-1-4B
File size: 9,411 Bytes
4558db3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | """Learned persistent memory artifacts and metrics for Safin-1."""
from __future__ import annotations
import hashlib
import json
import os
from typing import Any
from pathlib import Path
import torch
from torch import nn
from .config_utils import atomic_write_bytes
def _persistent_memory_parameters(model: nn.Module) -> dict[str, nn.Parameter]:
return {
name: parameter
for name, parameter in model.named_parameters()
if name.endswith("persistent_memory_state")
}
def _persistent_memory_route_key_parameters(model: nn.Module) -> dict[str, nn.Parameter]:
return {
name: parameter
for name, parameter in model.named_parameters()
if name.endswith("persistent_memory_route_key")
}
def save_persistent_memory_artifact(
model: nn.Module,
output_dir: str | os.PathLike[str],
) -> tuple[Path, Path]:
"""Save the compact persistent state and optional dedicated route keys."""
from safetensors.torch import save
state_parameters = _persistent_memory_parameters(model)
route_key_parameters = _persistent_memory_route_key_parameters(model)
parameters = {**state_parameters, **route_key_parameters}
if not parameters:
raise ValueError(
"model has no persistent_memory_state parameters; construct it with "
"hsd_persistent_memory_enabled=true."
)
root = Path(output_dir)
root.mkdir(parents=True, exist_ok=True)
tensor_path = root / "persistent_memory.safetensors"
config_path = root / "persistent_memory_config.json"
tensors = {
name: parameter.detach().to(device="cpu", dtype=torch.float32).contiguous()
for name, parameter in parameters.items()
}
artifact_format = "hsd_persistent_memory_v2" if route_key_parameters else "hsd_persistent_memory_v1"
tensor_bytes = save(tensors, metadata={"format": artifact_format})
model_config = getattr(model, "config", None)
text_config = getattr(model_config, "text_config", model_config)
layer_names = sorted(name.rsplit(".persistent_memory_state", 1)[0] for name in state_parameters)
metadata = {
"format": artifact_format,
"model_type": getattr(model_config, "model_type", None),
"tensor_sha256": hashlib.sha256(tensor_bytes).hexdigest(),
"key_source": (
"per_layer_dedicated_parameter"
if route_key_parameters
else "anchor_hidden_projection"
),
"enabled": bool(getattr(text_config, "hsd_persistent_memory_enabled", True)),
"layers": layer_names,
"anchor_chunk_size": getattr(text_config, "anchor_chunk_size", None),
"hsd_read_topk": getattr(text_config, "hsd_read_topk", None),
"hsd_null_read_gate": getattr(text_config, "hsd_null_read_gate", None),
"tensor_count": len(tensors),
"state_tensor_count": len(state_parameters),
"route_key_tensor_count": len(route_key_parameters),
"parameter_count": sum(tensor.numel() for tensor in tensors.values()),
"dtype": "float32",
"tensors": {name: list(tensor.shape) for name, tensor in tensors.items()},
}
metadata_bytes = (json.dumps(metadata, ensure_ascii=False, indent=2) + "\n").encode("utf-8")
atomic_write_bytes(tensor_path, tensor_bytes)
atomic_write_bytes(config_path, metadata_bytes)
return tensor_path, config_path
def _validate_persistent_memory_metadata(tensor_path, tensor_bytes, loaded, model):
# Read both tensor data and its header from one immutable file snapshot.
header_length = int.from_bytes(tensor_bytes[:8], "little")
header = json.loads(tensor_bytes[8:8 + header_length])
tensor_format = (header.get("__metadata__") or {}).get("format")
formats = {"hsd_persistent_memory_v1", "hsd_persistent_memory_v2"}
if tensor_format is not None and tensor_format not in formats:
raise RuntimeError(f"Unsupported persistent memory format: {tensor_format!r}.")
route_keys = [name for name in loaded if name.endswith("persistent_memory_route_key")]
if (tensor_format == "hsd_persistent_memory_v1" and route_keys
or tensor_format == "hsd_persistent_memory_v2" and not route_keys):
raise RuntimeError("Persistent memory tensor format disagrees with route-key contents.")
config_path = tensor_path.with_name("persistent_memory_config.json")
if tensor_path.name != "persistent_memory.safetensors" or not config_path.is_file():
return # Existing tensor-only artifacts remain supported.
metadata = json.loads(config_path.read_text(encoding="utf-8"))
if not isinstance(metadata, dict):
raise RuntimeError("Persistent memory metadata must be a JSON object.")
metadata_format = metadata.get("format")
if metadata_format is not None and metadata_format not in formats:
raise RuntimeError(f"Unsupported persistent memory metadata format: {metadata_format!r}.")
if metadata_format is not None and tensor_format is not None and metadata_format != tensor_format:
raise RuntimeError("Persistent memory metadata/tensor format mismatch.")
checksum = metadata.get("tensor_sha256")
if checksum is not None and checksum != hashlib.sha256(tensor_bytes).hexdigest():
raise RuntimeError("Persistent memory checksum mismatch; artifact files may be from different saves.")
shapes = {name: list(value.shape) for name, value in loaded.items()}
if "tensors" in metadata and metadata["tensors"] != shapes:
raise RuntimeError("Persistent memory metadata/tensor shape mismatch.")
if "tensor_count" in metadata and metadata["tensor_count"] != len(loaded):
raise RuntimeError("Persistent memory metadata tensor count mismatch.")
source_type = metadata.get("model_type")
target_type = getattr(getattr(model, "config", None), "model_type", None)
if source_type is not None and target_type is not None and source_type != target_type:
raise RuntimeError(f"Persistent memory model type mismatch: artifact={source_type!r} model={target_type!r}.")
def load_persistent_memory_artifact(
model: nn.Module,
artifact: str | os.PathLike[str],
*,
strict: bool = True,
) -> dict[str, Any]:
"""Validate and stage a compact state/key artifact before updating parameters.
Key, shape, metadata, finite-value and device/dtype conversion failures leave
the model unchanged. ``strict=False`` still permits partial matching keys.
"""
from safetensors.torch import load
artifact_path = Path(artifact)
tensor_path = artifact_path / "persistent_memory.safetensors" if artifact_path.is_dir() else artifact_path
if not tensor_path.is_file():
raise FileNotFoundError(f"persistent memory tensor file not found: {tensor_path}")
tensor_bytes = tensor_path.read_bytes()
loaded = load(tensor_bytes)
parameters = {
**_persistent_memory_parameters(model),
**_persistent_memory_route_key_parameters(model),
}
if not parameters:
raise ValueError("model has no persistent memory parameters; construct a memory-enabled model first.")
expected, actual = set(parameters), set(loaded)
missing = sorted(expected - actual)
unexpected = sorted(actual - expected)
if strict and (missing or unexpected):
raise RuntimeError(
"persistent memory artifact key mismatch: "
f"missing={missing} unexpected={unexpected}."
)
_validate_persistent_memory_metadata(tensor_path, tensor_bytes, loaded, model)
copied = sorted(expected & actual)
for name in copied:
source = loaded[name]
target = parameters[name]
if tuple(source.shape) != tuple(target.shape):
raise RuntimeError(
f"persistent memory shape mismatch for {name}: "
f"artifact={tuple(source.shape)} model={tuple(target.shape)}."
)
if not source.is_floating_point() or not bool(torch.isfinite(source).all()):
raise RuntimeError(f"Persistent memory tensor {name} must contain finite floating-point values.")
staged = {}
with torch.no_grad():
for name in copied:
target = parameters[name]
converted = loaded[name].to(device=target.device, dtype=target.dtype)
if not bool(torch.isfinite(converted).all()):
raise RuntimeError(f"Persistent memory conversion produced non-finite values for {name}.")
staged[name] = converted
for name in copied:
parameters[name].copy_(staged[name])
return {
"tensor_path": str(tensor_path),
"loaded": copied,
"missing": missing,
"unexpected": unexpected,
"parameter_count": sum(parameters[name].numel() for name in copied),
}
def collect_persistent_memory_metrics(
model: nn.Module,
*,
cumulative: bool = False,
reset: bool = False,
cpu: bool = True,
) -> dict[str, dict[str, torch.Tensor | float]]:
"""Collect per-layer persistent-memory routing metrics from an HF model."""
result = {}
for name, module in model.named_modules():
getter = getattr(module, "get_persistent_memory_metrics", None)
if not callable(getter):
continue
metrics = getter(cumulative=cumulative, reset=reset, cpu=cpu)
if metrics:
result[name] = metrics
return result
|