| |
| __watermark__ = "ip zymatica.space" |
|
|
| import os |
| os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "garbage_collection_threshold:0.6,max_split_size_mb:24" |
| import sys |
| import struct |
| import json |
| import time |
| import zlib |
| import numpy as np |
| import torch |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from torch.optim import AdamW |
| from scipy.fft import idct |
|
|
| sys.stdout.reconfigure(encoding='utf-8', errors='backslashreplace') |
|
|
| DEVICE = "cuda" if torch.cuda.is_available() else "cpu" |
| PKT_SIZE = 255 |
| MAGIC = bytes([0xA7, 0x07, 0xC3]) |
|
|
| BASE_MODEL = "j:/Language-U/Language-U-V2/qwen-3.5-0.8b-local" |
| PKT_DIR = "j:/Language-U/packets_chirp3" |
| OUTPUT_MODEL = "j:/Language-U/SubZero2.lora" |
| SFT_DATA_PATH = "j:/Language-U/full_sft_dataset.json" |
|
|
| LAYER_NAMES = [ |
| "model.layers.3.self_attn.q_proj.weight", |
| "model.layers.3.self_attn.k_proj.weight", |
| "model.layers.3.self_attn.v_proj.weight", |
| "model.layers.3.self_attn.o_proj.weight", |
| "model.layers.3.mlp.gate_proj.weight", |
| "model.layers.3.mlp.up_proj.weight", |
| "model.layers.3.mlp.down_proj.weight", |
| ] |
|
|
| QA_PAIRS = [ |
| ("What GPIO pin is the SX1302 reset line on Raspberry Pi 4?", "25"), |
| ("What is the exact command to reset the LoRa concentrator with gpioset?", |
| "gpioset -c gpiochip0 --toggle 100ms,100ms,0 25=0"), |
| ("What script handles the SX1302 hardware reset?", "reset_lgw.sh"), |
| ("On Raspberry Pi 5, which gpiochip and pin is the SX1302 reset mapped to?", |
| "GPIO 17 on gpiochip4"), |
| ("What frequency does the Astronaut SHE Handshake Protocol use?", "903.0 MHz"), |
| ("What Spreading Factor is used for the Astronaut SHE handshake?", "SF7"), |
| ("What is the transmit power for the Astronaut SHE RAK Miner beacon?", "14 dBm"), |
| ("What does --pwid 15 represent in test_loragw_hal_tx?", |
| "power calibration index 14 dBm"), |
| ("What is the full test_loragw_hal_tx command for the Astronaut SHE handshake?", |
| "./test_loragw_hal_tx -r 1250 -f 903.0 -m LORA -s 7 -b 125 -n 1 --pwid 15 -p 14 -z 32"), |
| ("What is the payload size for the Astronaut SHE handshake beacon?", "32 bytes"), |
| ("How many dimensions does the Cuneiform-U v3.0 semantic hypercube have?", "6"), |
| ("What are the 6 axes of Cuneiform-U v3.0?", |
| "DOMAIN, SUBDOMAIN, OPERATION, MODALITY, DEPTH, POLARITY"), |
| ("What is the Classifier Radical R_C in Cuneiform-U v3.0?", |
| "DOMAIN in upper 4 bits, SUBDOMAIN in lower 4 bits"), |
| ("What are the radical coordinates of the ACK glyph (0x807E)?", |
| "R_C=0x00, R_F=0x7E, R_A=0x0B"), |
| ("What is the Shannon Orthogonality equation in Language U?", |
| "H(text) = H(meaning) + H(syntax | meaning)"), |
| ("What does LLD-AC stand for?", "LLM-Logits-Driven Range Coding"), |
| ("What is a collapse signal in LLD-AC range coding?", |
| "probability approaches 1.0, encoding cost approaches 0 bits"), |
| ("What frequency scale does the LLD-AC range coder use?", "1,000,000"), |
| ] |
|
|
| EVAL_TESTS = [ |
| ("What GPIO pin is the SX1302 reset line on Raspberry Pi 4?", ["25", "GPIO 25"]), |
| ("What is the exact command to reset the LoRa concentrator with gpioset?", ["gpioset", "gpiochip0", "25=0"]), |
| ("What script handles the SX1302 hardware reset?", ["reset_lgw.sh"]), |
| ("On Raspberry Pi 5, which gpiochip and pin is the SX1302 reset mapped to?", ["17", "gpiochip4"]), |
| ("What frequency does the Astronaut SHE Handshake Protocol use?", ["903.0", "903"]), |
| ("What Spreading Factor is used for the Astronaut SHE handshake?", ["SF7", "sf7"]), |
| ("What is the transmit power for the Astronaut SHE RAK Miner beacon?", ["14 dBm", "14dBm"]), |
| ("What does --pwid 15 represent in test_loragw_hal_tx?", ["calibration", "14 dBm", "power"]), |
| ("What is the full test_loragw_hal_tx command for the Astronaut SHE handshake?", |
| ["-f 903.0", "-s 7", "--pwid 15", "-z 32"]), |
| ("What is the payload size for the Astronaut SHE handshake beacon?", ["32", "32 bytes"]), |
| ("How many dimensions does the Cuneiform-U v3.0 semantic hypercube have?", ["6", "six"]), |
| ("What are the 6 axes of Cuneiform-U v3.0?", ["DOMAIN", "SUBDOMAIN", "MODALITY"]), |
| ("What is the Classifier Radical R_C in Cuneiform-U v3.0?", ["DOMAIN", "SUBDOMAIN", "4 bits"]), |
| ("What are the radical coordinates of the ACK glyph (0x807E)?", ["0x00", "0x7E", "0x0B"]), |
| ("What is the Shannon Orthogonality equation in Language U?", ["H(text)", "H(meaning)", "H(syntax"]), |
| ("What does LLD-AC stand for?", ["LLM", "Logits", "Range Cod"]), |
| ("What is a collapse signal in LLD-AC range coding?", ["probability", "1.0", "bits"]), |
| ("What frequency scale does the LLD-AC range coder use?", ["1,000,000", "1000000", "million"]), |
| ] |
|
|
| BASELINE_SEMANTIC_TESTS = [ |
| ("A computer program is", ["program", "computer", "code", "software", "instructions"]), |
| ("The purpose of a map is", ["map", "place", "location", "direction", "where", "travel"]), |
| ("Water is important because", ["water", "important", "drink", "life", "body"]), |
| ("A library is a place where", ["library", "place", "book", "read", "find"]), |
| ("The moon appears at night", ["moon", "night", "sky", "appears"]), |
| ("A keyboard is used to", ["keyboard", "type", "computer", "used"]), |
| ("A camera can", ["camera", "photo", "picture", "image"]), |
| ("A river flows", ["river", "flow", "water"]), |
| ("A doctor helps", ["doctor", "help", "patient", "sick", "health"]), |
| ("A calendar shows", ["calendar", "date", "day", "month"]), |
| ("A battery stores", ["battery", "energy", "power", "electric"]), |
| ("A question mark means", ["question", "mark", "ask"]), |
| ("People sleep because", ["sleep", "rest", "tired", "body"]), |
| ("Exercise helps", ["exercise", "health", "body", "strong"]), |
| ("A triangle has", ["triangle", "three", "3", "sides"]), |
| ] |
|
|
| OFF_TOPIC_LANGUAGE_U = [ |
| "sx1302", "astronaut she", "gpio", "cuneiform", "lora", "lld-ac", "spreading factor", "903.0", "14 dbm" |
| ] |
|
|
| def build_huffman_tree(): |
| import heapq |
| freq = { |
| '[eof]': 1, ' ': 150, 'e': 120, 't': 90, 'a': 80, 'o': 75, 'i': 70, 'n': 70, |
| 's': 65, 'r': 60, 'h': 50, 'l': 40, 'd': 35, 'c': 30, 'u': 28, 'm': 25, |
| 'f': 22, 'p': 20, 'g': 18, 'w': 15, 'y': 12, 'b': 12, 'v': 10, 'k': 8, |
| 'j': 6, 'x': 6, 'q': 4, 'z': 4, |
| '0': 10, '1': 10, '2': 10, '3': 8, '4': 8, '5': 8, '6': 6, '7': 6, '8': 6, '9': 6, |
| '.': 8, '-': 8, '_': 8, '=': 8, '+': 6, '|': 6, ',': 6, '/': 4, ':': 4, |
| '(': 4, ')': 4, '[': 4, ']': 4, '{': 2, '}': 2, '<': 2, '>': 2, '?': 2, '!': 2 |
| } |
| for i in range(256): |
| ch = chr(i) |
| if ch not in freq: |
| freq[ch] = 1e-5 |
| |
| heap = [] |
| uid = 0 |
| for ch, f in freq.items(): |
| heapq.heappush(heap, (f, uid, ch)) |
| uid += 1 |
| |
| while len(heap) > 1: |
| f1, _, n1 = heapq.heappop(heap) |
| f2, _, n2 = heapq.heappop(heap) |
| heapq.heappush(heap, (f1 + f2, uid, (n1, n2))) |
| uid += 1 |
| |
| codes = {} |
| def traverse(node, code=""): |
| if isinstance(node, str): |
| codes[node] = code |
| else: |
| traverse(node[0], code + "0") |
| traverse(node[1], code + "1") |
| |
| if heap: |
| traverse(heap[0][2]) |
| return codes |
|
|
| _HUFF_CODES = build_huffman_tree() |
|
|
| def huff_decode(data: bytes) -> str: |
| rev_codes = {v: k for k, v in _HUFF_CODES.items()} |
| bits = "" |
| for b in data: |
| bits += format(b, '08b') |
| |
| text = [] |
| curr = "" |
| for bit in bits: |
| curr += bit |
| if curr in rev_codes: |
| val = rev_codes[curr] |
| if val == "[eof]": |
| break |
| text.append(val) |
| curr = "" |
| return "".join(text) |
|
|
| |
| ATYPE_U8=0x01; ATYPE_F16=0x03; ATYPE_U32=0x04; ATYPE_RAW8=0x07; ATYPE_HUFF=0x06 |
|
|
| def decode_l1_qa(data: bytes) -> list: |
| pos = 0 |
| n = data[pos]; pos += 1 |
| answers = [] |
| for i in range(n): |
| _quad = data[pos:pos+4]; pos += 4 |
| at = data[pos]; pos += 1 |
| if at == ATYPE_U8: |
| a = str(data[pos]); pos += 1 |
| if i == 6: |
| a += " dBm" |
| elif i == 9: |
| a += " bytes" |
| elif at == ATYPE_F16: |
| a = f"{struct.unpack('>e', data[pos:pos+2])[0]:.1f} MHz"; pos += 2 |
| elif at == ATYPE_U32: |
| a = f"{struct.unpack('>I', data[pos:pos+4])[0]:,}"; pos += 4 |
| elif at == ATYPE_RAW8: |
| n2 = data[pos]; pos += 1 |
| a = data[pos:pos+n2].decode('utf-8', errors='replace'); pos += n2 |
| elif at == ATYPE_HUFF: |
| n2 = data[pos]; pos += 1 |
| huff_bytes = data[pos:pos+n2] |
| a = huff_decode(huff_bytes) |
| pos += n2 |
| else: |
| a = "??" |
| answers.append(a) |
| return answers |
|
|
| |
| def dct_decompress_vec(data: bytes, pos: int) -> tuple: |
| n = struct.unpack('>H', data[pos:pos+2])[0]; pos += 2 |
| K = data[pos]; pos += 1 |
| scale = struct.unpack('>e', data[pos:pos+2])[0]; pos += 2 |
| idx_mode = data[pos]; K_check = data[pos+1]; pos += 2 |
|
|
| indices = [] |
| running = 0 |
| for _ in range(K_check): |
| if idx_mode == 0: |
| delta = data[pos]; pos += 1 |
| else: |
| delta = struct.unpack('>H', data[pos:pos+2])[0]; pos += 2 |
| running += delta |
| indices.append(running) |
|
|
| n_bytes = (K_check + 1) // 2 |
| packed = data[pos:pos+n_bytes]; pos += n_bytes |
| q_vals = [] |
| for b in packed: |
| lo = b & 0x0F; hi = (b >> 4) & 0x0F |
| q_vals.append(lo if lo <= 7 else lo - 16) |
| q_vals.append(hi if hi <= 7 else hi - 16) |
| q_vals = q_vals[:K_check] |
|
|
| v_dct = np.zeros(n, dtype=np.float64) |
| v_dct[indices] = np.array(q_vals, dtype=np.float64) * scale |
| return idct(v_dct, norm='ortho').astype(np.float32), pos |
|
|
| |
| def eigenspace_decompress(data: bytes, pos: int, W_base: np.ndarray) -> tuple: |
| R = data[pos]; pos += 1 |
| scale = struct.unpack('>e', data[pos:pos+2])[0]; pos += 2 |
| delta_s = np.frombuffer(data[pos:pos+R], dtype=np.int8).astype(np.float64) * scale |
| pos += R |
|
|
| U_b, S_b, Vh_b = np.linalg.svd(W_base.astype(np.float64), full_matrices=False) |
| W_delta = sum(delta_s[i] * np.outer(U_b[:, i], Vh_b[i, :]) for i in range(R)) |
| return W_delta.astype(np.float32), pos |
|
|
| |
| def gradient_atom_decompress(data: bytes, pos: int) -> tuple: |
| R = data[pos]; pos += 1 |
| scale = struct.unpack('>e', data[pos:pos+2])[0]; pos += 2 |
|
|
| n_bytes = (R + 1) // 2 |
| packed = data[pos:pos+n_bytes]; pos += n_bytes |
|
|
| nibbles = [] |
| for b in packed: |
| nibbles.append(b & 0x0F) |
| nibbles.append((b >> 4) & 0x0F) |
|
|
| MAG_TABLE = [0.125, 0.375, 0.625, 0.875] |
| delta_s = np.zeros(R, dtype=np.float64) |
| for i in range(R): |
| if i >= len(nibbles): break |
| nib = nibbles[i] |
| sign = +1 if (nib >> 1) & 1 else -1 |
| mag = MAG_TABLE[nib & 0x3] |
| delta_s[i] = sign * mag * scale |
|
|
| return delta_s, pos |
|
|
| def decode_layer_delta(data: bytes, pos: int, W_base: np.ndarray, level: int) -> tuple: |
| |
| lid = data[pos]; pos += 1 |
| lvl = data[pos]; pos += 1 |
| if lvl == 4: |
| u_rec, pos = dct_decompress_vec(data, pos) |
| v_rec, pos = dct_decompress_vec(data, pos) |
| W_delta = np.outer(u_rec, v_rec) |
| elif lvl == 5: |
| W_delta, pos = eigenspace_decompress(data, pos, W_base) |
| elif lvl == 6: |
| delta_s, pos = gradient_atom_decompress(data, pos) |
| U_b, _, Vh_b = np.linalg.svd(W_base.astype(np.float64), full_matrices=False) |
| R = len(delta_s) |
| W_delta = sum(delta_s[i] * np.outer(U_b[:, i], Vh_b[i, :]) for i in range(R)) |
| else: |
| raise ValueError(f"Unknown encoding level: {lvl} (parent/header level: {level})") |
| return W_delta.astype(np.float32), pos |
|
|
| def evaluate_fidelity(model, tokenizer) -> float: |
| model.eval() |
| passed = 0 |
| print("\n Fidelity test results:") |
| for i, (q, kws) in enumerate(EVAL_TESTS): |
| prompt = f"Q: {q}\nA:" |
| inputs = tokenizer(prompt, return_tensors='pt').to(DEVICE) |
| with torch.no_grad(): |
| out = model.generate(**inputs, max_new_tokens=48, |
| do_sample=False, pad_token_id=tokenizer.eos_token_id) |
| answer = tokenizer.decode(out[0][inputs['input_ids'].shape[1]:], |
| skip_special_tokens=True).lower() |
| ok = any(kw.lower() in answer for kw in kws) |
| passed += ok |
| mark = "✓" if ok else "✗" |
| if i < 5: |
| print(f" [{mark}] Q{i+1:>2}: {q[:55]}") |
| print(f" A: {answer.strip()}") |
| sys.stdout.flush() |
| fidelity = passed / len(EVAL_TESTS) * 100 |
| print(f" ... evaluated {len(EVAL_TESTS)} fidelity tests.") |
| print(f" FIDELITY: {passed}/{len(EVAL_TESTS)} = {fidelity:.1f}%") |
| sys.stdout.flush() |
| return fidelity |
|
|
| def evaluate_semantic(model, tokenizer) -> float: |
| model.eval() |
| passed = 0 |
| for prompt, kws in BASELINE_SEMANTIC_TESTS: |
| inputs = tokenizer(prompt, return_tensors='pt').to(DEVICE) |
| with torch.no_grad(): |
| out = model.generate(**inputs, max_new_tokens=32, |
| do_sample=False, pad_token_id=tokenizer.eos_token_id) |
| answer = tokenizer.decode(out[0][inputs['input_ids'].shape[1]:], |
| skip_special_tokens=True).lower() |
| matched = any(kw.lower() in answer for kw in kws) |
| off_topic = any(ot in answer for ot in OFF_TOPIC_LANGUAGE_U) |
| ok = matched and not off_topic |
| passed += ok |
| return passed |
|
|
| def collate_batch(batch, tokenizer, device): |
| prompts = [item["prompt"] for item in batch] |
| completions = [item["completion"] for item in batch] |
| full_texts = [p + c for p, c in zip(prompts, completions)] |
| inputs = tokenizer(full_texts, padding=True, truncation=True, max_length=192, return_tensors="pt").to(device) |
| labels = inputs["input_ids"].clone() |
| for i, p in enumerate(prompts): |
| p_len = tokenizer(p, truncation=True, max_length=192, return_tensors="pt")["input_ids"].shape[1] |
| labels[i, :p_len] = -100 |
| pad_mask = (inputs["attention_mask"][i] == 0) |
| labels[i, pad_mask] = -100 |
| inputs["labels"] = labels |
| return inputs |
|
|
| def train_multitask(model, tokenizer, sft_groups: dict, recipe: dict) -> dict: |
| import random |
| import math |
| import gc |
| |
| lu_examples = sft_groups["lu"] |
| rf_examples = sft_groups["rf"] |
| mmlu_examples = sft_groups["mmlu"] |
| gsm_examples = sft_groups["gsm"] |
| sem_examples = sft_groups["sem"] |
|
|
| for name, param in model.named_parameters(): |
| if not any(layer in name for layer in LAYER_NAMES): |
| param.requires_grad = False |
| else: |
| param.requires_grad = True |
|
|
| lr_max = recipe['lr'] |
| lr_min = 1e-6 |
| optimizer = AdamW(filter(lambda p: p.requires_grad, model.parameters()), lr=lr_max, weight_decay=0.01, betas=(0.9, 0.95)) |
| |
| total_steps = int(recipe['num_steps'] * 2.0) |
| accumulation_steps = 2 |
| |
| print(f"\n On-device Batched Multi-task SFT: {total_steps} steps (Accumulation={accumulation_steps}), Peak LR={lr_max:.6f} with Cosine Decay") |
| sys.stdout.flush() |
| t0 = time.perf_counter() |
| losses = [] |
| optimizer.zero_grad(set_to_none=True) |
|
|
| for step in range(total_steps): |
| model.train() |
| lr_t = lr_min + 0.5 * (lr_max - lr_min) * (1.0 + math.cos(math.pi * step / total_steps)) |
| for param_group in optimizer.param_groups: |
| param_group['lr'] = lr_t |
| |
| sampled_tasks = ["lu"] + random.sample(["rf", "mmlu", "gsm", "sem"], 3) |
| batch = [] |
| for task in sampled_tasks: |
| if task == "lu": |
| batch.extend(random.sample(lu_examples, 1)) |
| elif task == "rf": |
| batch.extend(random.sample(rf_examples, 1)) |
| elif task == "mmlu": |
| batch.extend(random.sample(mmlu_examples, 1)) |
| elif task == "gsm": |
| batch.extend(random.sample(gsm_examples, 1)) |
| elif task == "sem": |
| batch.extend(random.sample(sem_examples, 1)) |
| |
| inputs = collate_batch(batch, tokenizer, DEVICE) |
| |
| with torch.amp.autocast('cuda', enabled=(DEVICE == 'cuda')): |
| out = model(input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"]) |
| logits = out.logits |
| shift_logits = logits[..., :-1, :].contiguous() |
| shift_labels = inputs["labels"][..., 1:].contiguous() |
| |
| loss_fct = torch.nn.CrossEntropyLoss(reduction="none") |
| token_losses = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)) |
| token_losses = token_losses.view(shift_labels.size()) |
| |
| mask = (shift_labels != -100).float() |
| masked_losses = token_losses * mask |
| example_loss_sums = masked_losses.sum(dim=-1) |
| example_token_counts = torch.clamp(mask.sum(dim=-1), min=1.0) |
| example_losses = example_loss_sums / example_token_counts |
| |
| weight_map = {"lu": 12.0, "rf": 1.0, "mmlu": 1.0, "gsm": 1.0, "sem": 1.0} |
| step_weights = torch.tensor([weight_map[task] for task in sampled_tasks], device=DEVICE) |
| mean_loss = (example_losses * step_weights).sum() / step_weights.sum() |
| loss = mean_loss / accumulation_steps |
| |
| loss.backward() |
| |
| if (step + 1) % accumulation_steps == 0: |
| torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) |
| optimizer.step() |
| optimizer.zero_grad(set_to_none=True) |
| |
| losses.append(mean_loss.item()) |
|
|
| if step == 0 or (step + 1) % 10 == 0 or step == total_steps - 1: |
| elapsed = time.perf_counter() - t0 |
| print(f" Step {step+1:>4}/{total_steps} | Batch Loss={mean_loss.item():.4f} | LR={lr_t:.2e} | Time: {elapsed:.1f}s") |
| sys.stdout.flush() |
| |
| del inputs, out, loss, mean_loss |
|
|
| elapsed = time.perf_counter() - t0 |
| print(f" Training complete in {elapsed:.1f}s") |
| return {"initial_loss": losses[0], "final_loss": losses[-1], "seconds": elapsed} |
|
|
| def main(): |
| print("=" * 72) |
| print(" CHIRP-3 DECODER & RESTORATION ENGINE") |
| print(" Watermark: ip zymatica.space") |
| print("=" * 72) |
| sys.stdout.flush() |
| |
| |
| print(f"Loading packets from {PKT_DIR}...") |
| packet_files = sorted([f for f in os.listdir(PKT_DIR) if f.startswith("packet_chirp3_") and f.endswith(".bin")]) |
| if not packet_files: |
| print("Error: No packets found.") |
| sys.exit(1) |
| |
| |
| with open(os.path.join(PKT_DIR, packet_files[0]), "rb") as f: |
| first_pkt = f.read() |
| if len(first_pkt) < 3 or first_pkt[0] != 0xBB: |
| print("Error: Invalid packet format.") |
| sys.exit(1) |
| total_pkts = first_pkt[2] |
| |
| |
| received_packets = {} |
| for pf in packet_files: |
| with open(os.path.join(PKT_DIR, pf), "rb") as f: |
| pkt_bytes = f.read() |
| if len(pkt_bytes) == PKT_SIZE and pkt_bytes[0] == 0xBB: |
| idx = pkt_bytes[1] |
| received_packets[idx] = pkt_bytes |
| |
| print(f" Loaded {len(received_packets)}/{total_pkts} packets.") |
| |
| |
| missing_indices = [i for i in range(total_pkts) if i not in received_packets] |
| if len(missing_indices) == 0: |
| print("[+] All packets received intact. Verifying FEC...") |
| |
| chunk_size = PKT_SIZE - 3 |
| xor_fec = bytearray(chunk_size) |
| for idx, pkt in received_packets.items(): |
| for j in range(chunk_size): |
| xor_fec[j] ^= pkt[j + 3] |
| if any(xor_fec): |
| print("⚠️ Warning: FEC verification failed (non-zero XOR sum).") |
| else: |
| print("[+] FEC verification passed.") |
| elif len(missing_indices) == 1: |
| missing_idx = missing_indices[0] |
| print(f"[-] Missing packet index {missing_idx}. Performing XOR FEC recovery...") |
| chunk_size = PKT_SIZE - 3 |
| recovered_payload = bytearray(chunk_size) |
| for idx, pkt in received_packets.items(): |
| for j in range(chunk_size): |
| recovered_payload[j] ^= pkt[j + 3] |
| |
| |
| recovered_pkt = bytes([0xBB, missing_idx, total_pkts]) + bytes(recovered_payload) |
| received_packets[missing_idx] = recovered_pkt |
| print(f"[+] Successfully recovered missing packet index {missing_idx} via FEC.") |
| else: |
| print(f"❌ Error: Cannot recover because {len(missing_indices)} packets are missing.") |
| sys.exit(1) |
| |
| |
| data_pkts_count = total_pkts - 1 |
| assembled_payload = bytearray() |
| chunk_size = PKT_SIZE - 3 |
| for i in range(data_pkts_count): |
| assembled_payload.extend(received_packets[i][3:]) |
| |
| |
| data = zlib.decompress(bytes(assembled_payload)) |
| off = 0 |
| magic = data[off:off+3]; off += 3 |
| if magic != MAGIC: |
| raise ValueError(f"Bad magic: {magic.hex()} expected {MAGIC.hex()}") |
| |
| level = data[off]; off += 1 |
| lr_f16 = struct.unpack('>e', data[off:off+2])[0]; off += 2 |
| n_steps = struct.unpack('>H', data[off:off+2])[0]; off += 2 |
| seed = struct.unpack('>I', data[off:off+4])[0]; off += 4 |
| optim = data[off]; off += 1 |
| batch = data[off]; off += 1 |
| layer_f = data[off]; off += 1 |
| warmup = struct.unpack('>H', data[off:off+2])[0]; off += 2 |
| n_pairs = data[off]; off += 1 |
| lu4_hdr = data[off:off+4]; off += 4 |
| |
| |
| q_mask_bytes = data[off:off+3]; off += 3 |
| |
| qualia_seed = data[off]; off += 1 |
| n_layers = data[off]; off += 1 |
| |
| |
| w_len = struct.unpack('>H', data[off:off+2])[0]; off += 2 |
| lu4_len = struct.unpack('>H', data[off:off+2])[0]; off += 2 |
| |
| |
| off = 32 |
| |
| print(f"\nHeader Decoded:") |
| print(f" Level: Level {level}") |
| print(f" Learning Rate: {float(lr_f16):.6f}") |
| print(f" Steps / Seed: {n_steps} / {hex(seed)}") |
| print(f" Qualia Seed: {bin(qualia_seed)}") |
| print(f" LU4 Length: {lu4_len} bytes") |
| print(f" Weight Length: {w_len} bytes") |
| sys.stdout.flush() |
| |
| |
| lu4_blob = data[off : off + lu4_len] |
| off += lu4_len |
| |
| decoded_answers = decode_l1_qa(lu4_blob) |
| print(f"\nDecoded {len(decoded_answers)} facts from LU4 Q&A table:") |
| lu_examples = [] |
| for idx, ans in enumerate(decoded_answers): |
| q = QA_PAIRS[idx][0] |
| print(f" Q: {q}") |
| print(f" A: {ans}") |
| |
| lu_examples.append({ |
| "prompt": f"Q: {q}\nA:", |
| "completion": " " + ans.strip() |
| }) |
| sys.stdout.flush() |
| |
| |
| print(f"\nLoading baseline model from {BASE_MODEL}...") |
| tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True) |
| tokenizer.padding_side = "right" |
| if tokenizer.pad_token is None: |
| tokenizer.pad_token = tokenizer.eos_token |
| |
| model = AutoModelForCausalLM.from_pretrained(BASE_MODEL, torch_dtype=torch.float16).to(DEVICE) |
| model.config.use_cache = False |
| |
| |
| model.eval() |
| |
| |
| sem_examples = [] |
| print("Generating semantic anchor targets...") |
| for idx, (prompt, _) in enumerate(BASELINE_SEMANTIC_TESTS): |
| inputs = tokenizer(prompt, return_tensors='pt').to(DEVICE) |
| with torch.no_grad(): |
| out = model.generate(**inputs, max_new_tokens=32, do_sample=False, pad_token_id=tokenizer.eos_token_id) |
| sem_examples.append({ |
| "prompt": prompt, |
| "completion": " " + tokenizer.decode(out[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True).strip() |
| }) |
| |
| sem_base = evaluate_semantic(model, tokenizer) |
| print(f" Baseline Semantic Score: {sem_base}/15") |
| sys.stdout.flush() |
| |
| |
| if not os.path.exists(SFT_DATA_PATH): |
| print(f"Error: SFT dataset not found at {SFT_DATA_PATH}") |
| sys.exit(1) |
| |
| with open(SFT_DATA_PATH, "r", encoding="utf-8") as f: |
| sft_data = json.load(f) |
| |
| sft_groups = { |
| "lu": lu_examples, |
| "rf": [item for item in sft_data if item["type"] == "rf_info_theory"], |
| "mmlu": [item for item in sft_data if item["type"] == "mmlu"], |
| "gsm": [item for item in sft_data if item["type"] == "gsm8k"], |
| "sem": sem_examples |
| } |
| |
| |
| weight_data = data[off : off + w_len] |
| w_pos = 0 |
| base_p = dict(model.named_parameters()) |
| |
| print("\nDecoding weight updates in-place...") |
| for i in range(n_layers): |
| lname = LAYER_NAMES[i] |
| W_b = base_p[lname].data.to(torch.float32).cpu().numpy() |
| W_delta, w_pos = decode_layer_delta(weight_data, w_pos, W_b, level) |
| |
| |
| with torch.no_grad(): |
| delta_tensor = torch.from_numpy(W_delta).to(DEVICE, dtype=torch.float16) |
| base_p[lname].data.add_(delta_tensor) |
| print(f" Reconstructed {lname.split('.')[-2]} (Level {level})") |
| sys.stdout.flush() |
| |
| |
| print("\nEvaluating pre-SFT scores...") |
| fid_before = evaluate_fidelity(model, tokenizer) |
| sys.stdout.flush() |
| |
| |
| recipe = { |
| "lr": float(lr_f16), |
| "num_steps": n_steps, |
| "seed": seed, |
| "batch_size": batch, |
| } |
| stats = train_multitask(model, tokenizer, sft_groups, recipe) |
| |
| |
| print("\nEvaluating post-SFT scores...") |
| fid_after = evaluate_fidelity(model, tokenizer) |
| sem_after = evaluate_semantic(model, tokenizer) |
| sys.stdout.flush() |
| |
| |
| os.makedirs(OUTPUT_MODEL, exist_ok=True) |
| model.save_pretrained(OUTPUT_MODEL) |
| tokenizer.save_pretrained(OUTPUT_MODEL) |
| |
| print("\n" + "=" * 72) |
| print(" CHIRP-3 RESTORATION SUCCESS") |
| print("=" * 72) |
| print(f" Fidelity Before: {fid_before:.1f}%") |
| print(f" Fidelity After: {fid_after:.1f}%") |
| print(f" Semantic Before: {sem_base}/15") |
| print(f" Semantic After: {sem_after}/15") |
| print(f" Loss Initial/Final:{stats['initial_loss']:.4f} / {stats['final_loss']:.4f}") |
| print(f" Output Model: {OUTPUT_MODEL}") |
| print("=" * 72) |
| sys.stdout.flush() |
|
|
| if __name__ == '__main__': |
| main() |
|
|