gemma1b-tts-integration / scripts /build_qwen3tts_int4_stack_reference.py
marcos
Add omni package, streaming, ASR gate, trained projector
a2a19d5
Raw
History Blame Contribute Delete
8.76 kB
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Any
import numpy as np
from build_qwen3tts_int4_attention_reference import apply_rope, softmax
from build_qwen3tts_int4_matvec_reference import load_manifest, load_tensor
from build_qwen3tts_int4_mlp_reference import find_tensor, input_vector, rms_norm, silu
def load_layer(export_dir: Path, manifest: dict[str, Any], layer: int, prefix: str) -> tuple[dict[str, Any], dict[str, np.ndarray]]:
names = {
"input_norm": f"{prefix}.layers.{layer}.input_layernorm.weight",
"post_attention_norm": f"{prefix}.layers.{layer}.post_attention_layernorm.weight",
"q_proj": f"{prefix}.layers.{layer}.self_attn.q_proj.weight",
"k_proj": f"{prefix}.layers.{layer}.self_attn.k_proj.weight",
"v_proj": f"{prefix}.layers.{layer}.self_attn.v_proj.weight",
"o_proj": f"{prefix}.layers.{layer}.self_attn.o_proj.weight",
"q_norm": f"{prefix}.layers.{layer}.self_attn.q_norm.weight",
"k_norm": f"{prefix}.layers.{layer}.self_attn.k_norm.weight",
"gate": f"{prefix}.layers.{layer}.mlp.gate_proj.weight",
"up": f"{prefix}.layers.{layer}.mlp.up_proj.weight",
"down": f"{prefix}.layers.{layer}.mlp.down_proj.weight",
}
tensors: dict[str, Any] = {}
weights: dict[str, np.ndarray] = {}
for role, name in names.items():
component, index, tensor = find_tensor(manifest, name)
matrix, _ = load_tensor(export_dir, tensor)
tensors[role] = {"component": component, "tensor_index": index, "tensor_name": name, "shape": tensor["shape"]}
weights[role] = matrix.astype(np.float32)
return tensors, weights
def load_named_tensor(export_dir: Path, manifest: dict[str, Any], name: str) -> tuple[dict[str, Any], np.ndarray]:
component, index, tensor = find_tensor(manifest, name)
matrix, _ = load_tensor(export_dir, tensor)
return {"component": component, "tensor_index": index, "tensor_name": name, "shape": tensor["shape"]}, matrix.astype(np.float32)
def run_layer(hidden: np.ndarray, weights: dict[str, np.ndarray], heads: int, kv_heads: int, head_dim: int, eps: float, rope_theta: float) -> tuple[np.ndarray, dict[str, float]]:
seq_len = hidden.shape[0]
normalized = np.stack([rms_norm(row, weights["input_norm"], eps) for row in hidden]).astype(np.float32)
q = (normalized @ weights["q_proj"].T).reshape(seq_len, heads, head_dim)
k = (normalized @ weights["k_proj"].T).reshape(seq_len, kv_heads, head_dim)
v = (normalized @ weights["v_proj"].T).reshape(seq_len, kv_heads, head_dim)
q = np.stack([[rms_norm(q[pos, head], weights["q_norm"], eps) for head in range(heads)] for pos in range(seq_len)]).astype(np.float32)
k = np.stack([[rms_norm(k[pos, head], weights["k_norm"], eps) for head in range(kv_heads)] for pos in range(seq_len)]).astype(np.float32)
q = apply_rope(q, rope_theta)
k = apply_rope(k, rope_theta)
group = heads // kv_heads
output_rows = np.empty_like(hidden)
attention_checksums = []
attention_output_checksums = []
mlp_output_checksums = []
for target in range(seq_len):
context = np.empty((heads, head_dim), dtype=np.float32)
for head in range(heads):
kv_head = head // group
scores = np.array([np.dot(q[target, head], k[pos, kv_head]) / np.sqrt(np.float32(head_dim)) for pos in range(target + 1)], dtype=np.float32)
probs = softmax(scores)
context[head] = np.sum(probs[:, None] * v[: target + 1, kv_head], axis=0, dtype=np.float32)
attention_checksums.append(float(np.sum(probs, dtype=np.float32)))
attention_output = weights["o_proj"] @ context.reshape(heads * head_dim)
residual = hidden[target] + attention_output
mlp_input = rms_norm(residual, weights["post_attention_norm"], eps)
gate = weights["gate"] @ mlp_input
up = weights["up"] @ mlp_input
mlp_output = weights["down"] @ (silu(gate) * up)
output_rows[target] = residual + mlp_output
attention_output_checksums.append(float(np.sum(attention_output, dtype=np.float32)))
mlp_output_checksums.append(float(np.sum(mlp_output, dtype=np.float32)))
stats = {
"attention_checksum": float(np.sum(attention_output_checksums, dtype=np.float32)),
"mlp_checksum": float(np.sum(mlp_output_checksums, dtype=np.float32)),
"attention_probability_checksum": float(np.sum(attention_checksums, dtype=np.float32)),
"output_checksum": float(np.sum(output_rows, dtype=np.float32)),
}
return output_rows, stats
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--export-dir", type=Path, default=Path("exports/qwen3tts_0p6b_sft_partial_int4_weights_20260606"))
parser.add_argument("--config", type=Path, default=Path("job_output/qwen3tts-0p6b-official-sft-ptbr-256-partial-last2heads-20260606/output_b1_epoch1_lr2e6/checkpoint-epoch-0/config.json"))
parser.add_argument("--layers", type=int, default=2)
parser.add_argument("--seed", type=int, default=0)
parser.add_argument("--sequence-length", type=int, default=3)
parser.add_argument("--prefix", default="talker.model")
parser.add_argument("--final-norm-name")
parser.add_argument("--head-prefix")
parser.add_argument("--head-count", type=int, default=0)
parser.add_argument("--out", type=Path, default=Path("exports/qwen3tts_0p6b_sft_partial_int4_stack2_reference_20260606.json"))
args = parser.parse_args()
manifest = load_manifest(args.export_dir / "manifest.json")
config = json.loads(args.config.read_text())["talker_config"]
hidden_size = int(config["hidden_size"])
head_dim = int(config["head_dim"])
heads = int(config["num_attention_heads"])
kv_heads = int(config["num_key_value_heads"])
eps = float(config["rms_norm_eps"])
rope_theta = float(config["rope_theta"])
hidden = np.stack([input_vector(hidden_size, args.seed + pos) for pos in range(args.sequence_length)]).astype(np.float32)
layer_refs = []
layer_stats = []
for layer in range(args.layers):
tensors, weights = load_layer(args.export_dir, manifest, layer, args.prefix)
hidden, stats = run_layer(hidden, weights, heads, kv_heads, head_dim, eps, rope_theta)
layer_refs.append({"layer": layer, "tensors": tensors})
layer_stats.append({"layer": layer, **stats})
target = args.sequence_length - 1
output = hidden[target]
data = {
"format": "qwen3tts_int4_stack_reference_v1",
"package": args.export_dir.name,
"prefix": args.prefix,
"layer_count": args.layers,
"seed": args.seed,
"sequence_length": args.sequence_length,
"target_index": target,
"eps": eps,
"hidden_size": hidden_size,
"heads": heads,
"kv_heads": kv_heads,
"head_dim": head_dim,
"rope_theta": rope_theta,
"layers": layer_refs,
"layer_stats": layer_stats,
"sequence_checksum": float(np.sum(hidden, dtype=np.float32)),
"checksum": float(np.sum(output, dtype=np.float32)),
"max_abs": float(np.max(np.abs(output))),
"values": [float(value) for value in output.tolist()],
}
if args.final_norm_name and args.head_prefix and args.head_count > 0:
norm_ref, norm_weight = load_named_tensor(args.export_dir, manifest, args.final_norm_name)
normalized = rms_norm(output, norm_weight, eps)
head_refs = []
for head in range(args.head_count):
head_ref, head_weight = load_named_tensor(args.export_dir, manifest, f"{args.head_prefix}.{head}.weight")
logits = head_weight @ normalized
head_refs.append({
"head": head,
"tensor": head_ref,
"checksum": float(np.sum(logits, dtype=np.float32)),
"max_abs": float(np.max(np.abs(logits))),
"argmax": int(np.argmax(logits)),
"argmax_value": float(np.max(logits)),
"values": [float(value) for value in logits.tolist()],
})
data["logits"] = {
"norm": norm_ref,
"heads": head_refs,
"normalized_checksum": float(np.sum(normalized, dtype=np.float32)),
"normalized_max_abs": float(np.max(np.abs(normalized))),
}
args.out.parent.mkdir(parents=True, exist_ok=True)
args.out.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n")
print(json.dumps({"out": str(args.out), "checksum": data["checksum"], "max_abs": data["max_abs"]}, ensure_ascii=False))
if __name__ == "__main__":
main()