nur-dev's picture
Add files using upload-large-folder tool
7c5e40e verified
Raw
History Blame Contribute Delete
5.02 kB
"""Configuration for STRATA neural models."""
from __future__ import annotations
import json
from dataclasses import asdict, dataclass
from pathlib import Path
from typing import Any
@dataclass(frozen=True, slots=True)
class StrataConfig:
"""Plain-PyTorch decoder configuration.
The config intentionally has no DeepSpeed, CPU offload, or distributed
runtime knobs. Those concerns must stay outside the core model.
"""
vocab_size: int = 64_288
max_position_embeddings: int = 4096
d_model: int = 768
num_layers: int = 12
num_heads: int = 12
d_ff: int = 3072
dropout: float = 0.0
local_attention_window: int = 1024
predicate_block_every: int = 3
graph_relation_types: int = 16
node_type_vocab_size: int = 16
chart_type_vocab_size: int = 64
max_graph_edges_per_token: int = 8
use_attention_bias_from_graph: bool = True
# Optional first-class graph-object memory path. Defaults off so existing
# checkpoints instantiate the exact legacy architecture and load strictly.
use_graph_object_memory: bool = False
graph_object_relation_types: int = 70
graph_object_node_types: int = 20
graph_object_gate_init: float = -4.0
# v5 relation-conditioned message algebra. When enabled, graph-object edge
# values are relation-conditioned messages over (src, dst, relation), rather
# than generic src+dst+relation slots.
graph_object_relation_conditioned_messages: bool = False
# v7 predicate-slot memory. Relation labels select role-addressed predicate
# slots: edge(src, relation, predicate) writes src into slot(predicate,
# relation). This is the typed variable-binding path used to test whether
# labels become operative rather than merely decodable edge features.
graph_object_predicate_slot_memory: bool = False
# When False (default), the node/chart/edge prediction heads are computed only
# on the final predicate block (the ones the losses/eval consume). Set True to
# restore the legacy behaviour where every predicate block emits them.
emit_all_block_graph_heads: bool = False
tie_word_embeddings: bool = True
initializer_range: float = 0.02
pad_token_id: int = 0
bos_token_id: int = 1
eos_token_id: int = 2
def __post_init__(self) -> None:
self.validate()
def validate(self) -> None:
if self.vocab_size <= 0:
raise ValueError("vocab_size must be positive")
if self.max_position_embeddings <= 0:
raise ValueError("max_position_embeddings must be positive")
if self.d_model <= 0:
raise ValueError("d_model must be positive")
if self.num_layers <= 0:
raise ValueError("num_layers must be positive")
if self.num_heads <= 0:
raise ValueError("num_heads must be positive")
if self.d_model % self.num_heads != 0:
raise ValueError("d_model must be divisible by num_heads")
if self.d_ff <= 0:
raise ValueError("d_ff must be positive")
if not 0.0 <= self.dropout < 1.0:
raise ValueError("dropout must be in [0, 1)")
if self.local_attention_window <= 0:
raise ValueError("local_attention_window must be positive")
if self.predicate_block_every <= 0:
raise ValueError("predicate_block_every must be positive")
if self.graph_relation_types <= 0:
raise ValueError("graph_relation_types must be positive")
if self.node_type_vocab_size <= 0:
raise ValueError("node_type_vocab_size must be positive")
if self.chart_type_vocab_size <= 0:
raise ValueError("chart_type_vocab_size must be positive")
if self.max_graph_edges_per_token <= 0:
raise ValueError("max_graph_edges_per_token must be positive")
if self.graph_object_relation_types <= 0:
raise ValueError("graph_object_relation_types must be positive")
if self.graph_object_node_types <= 0:
raise ValueError("graph_object_node_types must be positive")
@property
def head_dim(self) -> int:
return self.d_model // self.num_heads
def to_dict(self) -> dict[str, Any]:
return asdict(self)
@classmethod
def from_dict(cls, values: dict[str, Any]) -> "StrataConfig":
return cls(**values)
@classmethod
def from_json_file(cls, path: str | Path) -> "StrataConfig":
with Path(path).open("r", encoding="utf-8") as handle:
payload = json.load(handle)
if not isinstance(payload, dict):
raise ValueError("config JSON must contain an object")
return cls.from_dict(payload)
def to_json_file(self, path: str | Path) -> None:
destination = Path(path)
destination.parent.mkdir(parents=True, exist_ok=True)
with destination.open("w", encoding="utf-8") as handle:
json.dump(self.to_dict(), handle, indent=2, sort_keys=True)
handle.write("\n")