Logbook: one base, measured, and the rerank
Apparatus: huggingface_hub.model_info and dataset_info with files_metadata=True; config.json and safetensors headers read directly, the latter by ranged GET; git show against 3-interactor/llama-cpp-npu-vision-upstream at 6a272903; GET /my/details and /my/characters against api.artifactsmmo.com; hailortcli fw-control identify and Get-PnpDevice on the local desk. Sizes are the sum of siblings[].size, decimal GB.
Decided: gemma-4-E4B is the only base. The 31B and the 12B are both dropped – one model to maintain, evaluated on our own courses rather than on published benchmarks. What follows is why the other two were considered, what they measured, and what dropping them costs, because the next reader will otherwise re-derive the whole comparison.
Gemma 4 is Apache-2.0, and the prior that says otherwise is wrong
Gemma 1, 2 and 3 carried Google’s custom Gemma Terms of Use. Gemma 4, released 2026-04-02, is Apache-2.0, confirmed on google/gemma-4-31B-it and every sibling checked. This is recorded because it was asserted the other way during the session that produced this entry, from a stale prior, and the licence is a precondition here rather than a detail.
The old terms extended the licence to models trained on Gemma-generated synthetic data. That propagation is what the OpenRAIL-M row exists to stop, and it is gone.
The checkpoints, measured
repo size note
google/gemma-4-E4B-it 16.0 GB 2130 tensors
google/gemma-4-E4B-it-qat-q4_0-unquantized 15.9 GB 2076 tensors
google/gemma-4-E4B-it-qat-w4a16-ct 11.5 GB
google/gemma-4-E4B-it-qat-mobile-transformers 3.6 GB
google/gemma-4-12B-it 24.0 GB dropped
google/gemma-4-31B-it-qat-q4_0-unquantized 62.6 GB dropped
google/gemma-4-31B-it-qat-q4_0-gguf 18.9 GB GGUF, the wrong artefact
Gryphe/Gemma-4-12B-StyleTune 26.0 GB dropped with the 12B
densenet/...-31B-StyleTune-heretic-ara 65.4 GB dropped with the 31B
The QAT repo that fits a small card is the GGUF one, and it is the wrong artefact. -unquantized is the usable QAT release: QAT-trained weights at full precision, quantised downstream. The 18.9 GB figure that makes QAT look like a free win is the GGUF.
The two E4B checkpoints differ by 54 tensors. -it carries 2130 and the QAT variant 2076; the QAT one drops k_proj, v_proj and k_norm for 18 layers. That is num_kv_shared_layers: 18 materialised into the checkpoint. A delta computed against -it does not align with the QAT variant, so an adapter is specific to whichever it was built on. Neither has an lm_head – both tie the output head to model.embed_tokens.
The untied lm_head in the StyleTune line is Gryphe’s, not Heretic’s. Gemma-4-31B-StyleTune and ...-heretic-ara are both 65.4 GB against Google’s 62.6, and both carry 1189 tensors to Google’s 1188. 262144 x 5376 x 2 bytes is 2.82 GB, the whole difference. The abliteration adds no tensor. This was attributed to Heretic first and the attribution was wrong.
KV cost, from config.json rather than a rule of thumb
model layers kv_heads head_dim sw full KV/token (fp16) fixed sliding
E4B 42 2 256 512 7 14 KiB 28 MiB
12B 48 8 256 1024 8 64 KiB 320 MiB
31B 60 16 256 1024 10 160 KiB 800 MiB
E4B also carries num_kv_shared_layers: 18. On the local 3090, an int4 E4B is about 4 GB with encoders, leaving ~20 GB of KV at 14 KiB/token – far past the 262K position limit. Context stops being a constraint at all.
What dropping the larger two costs, stated rather than discovered
Google’s published figures, 31B / 12B / E4B:
Tau2, agentic tool use 76.9 / 69.0 / 42.2
MRCR v2 @128K 66.4 / 43.4 / 25.4
MMLU Pro 85.2 / 77.2 / 69.4
MMMU Pro, vision 76.9 / 69.1 / 52.6
Tau2 and MRCR are the two that matter for an agent, and E4B is worst on both. Two things bound the cost. Evaluation is on our own courses, so a public benchmark measures a distribution we are not deploying into. And taskweft’s HTN planner holds the long dependency chains that MRCR is a proxy for, so the planner does the remembering.
The persona has no source now. Gryphe’s StyleTune line covers 12B, 26B-A4B and 31B and not E4B, so dropping the 12B drops the only licence-clean persona checkpoint reachable from here. Style has to come from our own traces. That was already the plan; it is now the only plan.
Gryphe’s corpus cannot be reproduced, and does not need to be
Four of Gryphe’s eight datasets state no licence. The rest are generated by Claude Sonnet 3.5, Claude Opus or GPT-4o – all API-only, and the hosted-API row says condition 1 cannot be satisfied without a checkpoint. CoEdit-Alpaca at 20 MB is the only survivor and it is text editing, not style. Using someone’s Apache-2.0 weights is not the act that row governs; it governs what enters a corpus.
The abliteration is a LoRA, and Heretic computes it natively
Heretic’s ARA uses no refusal direction. It captures module input/output tensors through hooks and performs direct, unconstrained matrix optimisation, so the delta is high-rank by construction – which is what “arbitrary rank” names. A truncated-SVD extraction was written, syntax-checked, and never run: it would have measured what the method’s own description already states.
That was the wrong question. --export-strategy ADAPTER emits a LoRA directly, and --row-normalization FULL, the default, already “compute[s] LoRA adapter relative to row-normalized weights”. So the adapter comes out of the run rather than out of a decomposition, and Google’s QAT weights stay bit-identical – which also removes the risk that unconstrained optimisation knocks them off the 4-bit grid.
Run, on the local 3090:
model google/gemma-4-E4B-it-qat-q4_0-unquantized @ 476025a0
seed 1171
export ADAPTER
heretic-llm 1.4.0, torch 2.10.0+cu128
Pinned commit plus seed plus Heretic’s own reproduce.json satisfies condition 1 by construction.
Two dependency failures worth recording, because both reported success. The first run died on Gemma4Processor requires the PIL library; the second on No module named 'torchvision'. Gemma 4 is multimodal and its processor imports both even for a text-only run. Both were reported as exit code 0 by a PowerShell wrapper that did not propagate $LASTEXITCODE, so the runs read as started when they had already failed. The wrapper now throws, and a preflight checks the imports before any GPU time is spent.
Also: pixi resolved torch 2.13.0+cpu from conda-forge. It imports, it runs, and cuda.is_available() is False. The cu128 index is pinned per-package in pixi.toml – globally, via extra-index-urls, it makes the resolver look for every package there and the solve fails on tqdm.
Both accelerators are present, and neither has been measured
UGen300 USB AI Accelerator (Hailo-10H) status OK, firmware 5.3.2, usb/001:001
NPU Compute Accelerator Device status OK, AMD, PCI\VEN_1022&DEV_1502
NVIDIA GeForce RTX 3090 24 GB, idle
The second is the 7840U’s own XDNA1 NPU, and nothing in this workspace knew it was there.
The Hailo was power-starved, and moving it to a USB4 dock cleared it. On the first port hailortcli warned: “USB-C source electrical current advertised: 1.5A. The module may run in reduced-performance mode.” On the dock the device re-enumerated from usb/001:001 to usb/001:009 and the warning stopped. RFD 1130 exists to report what the device delivers, and a figure taken on the first port would have been a figure about a cable.
The evidence is the absence of the firmware’s own flag, not a power reading, and that distinction is worth keeping. Neither direct route works here: measure-power fails with HAILO_OPEN_FILE_FAILURE(13), and monitor – the command whose help promises “on H10, presents performance and health stats” – reports that it “is not supported on Windows”. So the claim is that the module no longer reports reduced-performance mode, which is weaker than a measured current and is what we have.
The comparison that would have settled it is now gone. No throughput was taken at 1.5A before the move, so the cost of the power limit cannot be quantified from here. Recovering it means deliberately plugging back into the 1.5A port and benchmarking both, which is worth an hour if RFD 1130 wants the delta rather than just a good number.
Extended identify, for the record: HAILO10H, firmware 5.3.2 (release,app), boot source FLASH, LCS 5, board SKU-ID 8, chip serial F8FBFDDB7CD6F769D3CE75F9.
Neither NPU has a measured rate. gpu_tops.py says published TOPS are “a ranking and not a budget” – 40 TOPS INT4 at an assumed 30% utilisation, profiler never run. It now has two local devices to point at instead of zero.
adapt cannot run on either. HailoRT executes a compiled HEF, a forward graph: no backward pass, no gradient, no optimizer. A training step has no representation in the format. The 3090 does adapt; the accelerators serve ask.
And ask on the Hailo is not limited to an encoder, which this entry implied. HailoRT 5.3.2 ships genai/llm/llm.hpp and genai/vlm/vlm.hpp – autoregressive generation with sampling parameters, token streaming, and a LoRA selected by name at load time. The Qwen3-VL-only gating recorded above is a property of llama.cpp’s mtmd path, not of the device. See logbook-dfc-emulation-contexts-disagree.md, which retracts the wider claim and records the evidence that produced it.
ONNX was unblocked, and the row was scoped to a one-device world
The ONNX row argued that “ONNX had one job left after the runtimes went, which was carrying models into Hailo’s Dataflow Compiler”, and retired the format because TFLite does that job better by Hailo’s own direction. That argument was about Hailo, and it was sound about Hailo.
It never considered a second accelerator, because nobody knew there was one. XDNA’s whole toolchain is ONNX-shaped: AMD Quark quantises ONNX-to-ONNX, and the VitisAI EP executes ONNX. The row was not wrong; it was scoped to a world that stopped being true when a device scan turned up a second NPU. Row and section both removed, 21/21.
Open, and measurable locally: whether XDNA1 gets AMD’s INT4 flows or whether those target XDNA2 only.
The style corpus is an RL environment, not a distillation
The character plays ArtifactsMMO and lives the character-avatar; traces become the corpus. The EditScore schema transfers directly:
EditScore game equivalent
images: [before, after] states: [before, after]
instruction the HTN task from taskweft
task_type, 11 classes action class: move, fight, gather, craft, trade
expected_scores: [22, 20] outcome delta, computed by the engine
EditScore’s scores had to be judged. Game outcomes are computed – HP, XP, gold, inventory and success come back in the action response, and taskweft says whether the action satisfied the next precondition. Two deterministic label sources, one learned policy.
That settles condition 3. The rule is about capability transfer, and playing a game is capability, so it binds where style alone would not have. But the reward comes from the engine rather than a teacher, so “a student excellent on its teacher’s output and mediocre on the world” cannot occur. Condition 4 lands the same way, and evaluation is on our courses, which are real data we hold.
The account is five characters, and the corpus is calendar-bound
AriaWeft WarpWeft ShuttleWeft HeddleWeft SelvageWeft all level 1
/characters/create states the cap: “You can create up to 5 characters.” The account was at 1 and is now at 5. Multi-accounting is a ban, so five is the hard ceiling.
minimum cooldown 3 s per action per character, a bypass having been patched
sandbox 451, "you must be a member" -- membership is paid
servers seasonal, about 4 months, so a corpus is tied to a season
At 5 to 10 s average across action types, five characters yield 43,000 to 86,000 actions a day: 1.2 to 2.2 days for a 97k-row corpus, against 6 to 11 on one character.
This is the only step whose cost is calendar rather than money. Everything else goes faster on better hardware. This does not, and the season expires.
Five characters should specialise rather than run five copies of one policy. EditScore’s own corpus is roughly balanced across its 11 task_type classes, and a single character grinding one skill produces a corpus dominated by one class.
Agentic datasets: licence is the easy half, the generator decides it
dataset licence generated by verdict
Salesforce/xlam-function-calling-60k cc-by-4.0 DeepSeek-V2, Mixtral passes
nvidia/Llama-Nemotron-Post-Training cc-by-4.0 Llama-3.1/3.3 passes
PrimeIntellect/SYNTHETIC-1 apache-2.0 DeepSeek-R1 passes
microsoft/orca-agentinstruct-1M-v1 cdla-perm. GPT-4 blocked
Nexusflow/Function_Call_Definitions cc-by-nc-sa -- blocked
THUDM/AgentInstruct none stated -- blocked
NousResearch/hermes-function-calling-v1 apache-2.0 unstated unclear
gorilla-llm/BFCL apache-2.0 benchmark eval only
xlam documents which id ranges came from which model – DeepSeek-V2 for ids 0 to 33658, Mixtral for the rest – so condition 1 is satisfied at row granularity. Both are downloadable checkpoints.
The dataset named after the agent we want to run is the one that cannot document its generator: hermes-function-calling-v1’s card credits people, not models.
The EditScore corpora, and where a naive split leaks
dataset rows instruction distinct max repeat
EditScore-Reward-Data 97,256 10,915 36
EditScore-RL-Data 110,000 68,426 890
A random row split puts the same instruction on both sides. Split on instruction, stratified on task_type. expected_scores: [22, 20] is an absolute score per image, not a preference label, so arity-1 quality-control examples come free: each row yields two. conversations is instruction plus a fixed template and is a derivable column.
The images ship as a split gzip tarball, which the archive-format rule refuses, so the fork repackages to ZStandard parquet – the same pass as the split. EditReward-Bench is arrow, evaluation-only, and published, so it is not blinded the way coco_person_commercial_val2017 is.
Three repositories were created and destroyed without holding anything
chibifire/runpod-gemma4-serve, chibifire/gemma4-31b-styletune-heretic-lora and chibifire/gemma4-31b-it-qat-q4_0-unquantized-1e4d8bee were created while the 31B path looked settled. All three were deleted at 0 bytes and verified gone. A repository is cheap to make and it advertises a decision; making one before the decision is the same error as measuring throughput on a model that fails RFD 1128.
No money was spent
RunPod was audited for pods, serverless endpoints and network volumes: none, ever. The whole plan runs on the 3090 and the two accelerators, and the $250 wall is untouched.
Still open
split ratio for the two corpora 90/10 or 80/20 on instruction groups
whether `conversations` is dropped correct under ETNF, costs a loader dependency
does XDNA1 get AMD's INT4 flows or do those target XDNA2 only
the cost of the 1.5A limit unmeasured, and only recoverable by
plugging back in on purpose
The rerank
DONE move the Hailo off the 1.5A port on a USB4 dock, warning gone
1 start the five characters playing the only calendar-bound step
2 finish ARA on E4B, verify the adapter running
3 gpu_tops.py against both NPUs first measured rate for either
4 RFD 1129 and 1128 on E4B LiteRT and ONNX are both open now
5 fork and split the EditScore corpora zstd parquet, split on instruction
6 xlam-function-calling-60k as a tool-call prior cheap; Tau2 42.2 is partly format
7 style LoRA on E4B, DPO on the traces
8 retrain EditScore on E4B no Gemma variant is published
The device numbers are now worth taking, which they were not an hour ago. Step 1 stays at the front because it is the one cost that hardware cannot buy back.