Instructions to use schneewolflabs/Glanz-A2-LoRA with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use schneewolflabs/Glanz-A2-LoRA with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("schneewolflabs/A2") model = PeftModel.from_pretrained(base_model, "schneewolflabs/Glanz-A2-LoRA") - Notebooks
- Google Colab
- Kaggle
Glanz-A2-LoRA
Front-end generation for A2, trained on 202 examples of Claude Opus web design from glamour-opus.
Given a design brief, A2 with this adapter writes a complete, self-contained component β semantic HTML, a full stylesheet, and any JavaScript it needs β instead of the thin sketch the base model produces.
This is the 2-epoch checkpoint, not the final one. See Which checkpoint below; the 4-epoch weights are worse and the 3-epoch weights fail in a specific way.
Measured
22 held-out briefs, never seen in training. Everything below is scored by parsing and executing β
tags balanced by a real HTML parser, CSS through tinycss2, JavaScript through node --check β
never by asking a model whether the page looks good.
| base A2 | + Glanz | Opus (ground truth) | |
|---|---|---|---|
| structure + balanced, of completed generations | 19/20 | 18/18 | 22/22 |
| classes with a matching CSS rule | 0.776 | 0.944 | 0.964 |
| self-contained (no external assets) | 21/22 | 22/22 | 22/22 |
| CSS rules, mean | 10.5 | 43.0 | β |
| output size, mean chars | 4,343 | 14,564 | 12,911 |
| repetition collapses | 2/22 | 0/22 | 0/22 |
The class-coverage number is the one that matters most. A model that has learned the shape of these pages without the substance emits rich markup styled by nothing; at 0.944 against a 0.964 ceiling, the extra markup is genuinely styled. Output length lands on the training distribution rather than overshooting it.
It also fixes a base failure mode. Two of the 22 base generations degenerate into a repeated
line β <div class="rule"></div> emitted until the token cap, a 0.05 unique-line ratio. The
adapter has none, and its worst case is 0.51. This was not a training target; it is a side effect.
Nothing broke
A behavioural probe of the capabilities A2 is actually for β tool calling, abstention, identity, Luna persona gating β run at temperature 0 before and after:
| base A2 | + Glanz | |
|---|---|---|
| behavioural checks passed | 7/9 | 9/9 |
The two gained cases are the same one: asked "Where is shipment TRK-88213 right now?", base A2
replies "if you provide the tracking number, I can give you details" β it will not lift the
argument out of the prompt, with or without thinking enabled. With the adapter it calls
lookup_shipment(tracking="TRK-88213") correctly.
This is reported as observed, not claimed as a feature. It is two cases, and there is no obvious mechanism by which web-design data teaches argument extraction beyond r=32 touching all seven projections. Do not plan around it.
Tool calling, parallel calls, abstention, the Schneewolf Labs identity under adversarial pressure, and Luna's gating behind her system prompt are all unchanged.
Usage
You must disable thinking. A2's template ends its generation prompt with <think>\n. Training
used enable_thinking=False, which makes the template emit a pre-closed <think>\n\n</think>\n\n
block instead, so the model was never trained to write HTML from inside an open think block.
Generating with thinking on puts it in a state this adapter has never seen.
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("schneewolflabs/A2")
model = AutoModelForCausalLM.from_pretrained("schneewolflabs/A2", dtype="bfloat16",
device_map="auto")
model = PeftModel.from_pretrained(model, "schneewolflabs/Glanz-A2-LoRA")
SYSTEM = (
"You are a front-end designer. Given a design brief, produce a single self-contained web "
"component: semantic HTML, a complete stylesheet, and any JavaScript it needs. Output three "
"fenced code blocks in order β html, css, js β and nothing else. Omit the js block if the "
"component needs no script. Use no external assets, frameworks, or network requests."
)
enc = tok.apply_chat_template(
[{"role": "system", "content": SYSTEM},
{"role": "user", "content": "Design a pricing table for a small SaaS. Dark theme."}],
add_generation_prompt=True, enable_thinking=False, # <- required
return_tensors="pt", return_dict=True).to(model.device)
print(tok.decode(model.generate(**enc, max_new_tokens=16000, do_sample=False)[0]))
A GGUF of the adapter is included for llama.cpp:
llama-server -m A2-Q8_0.gguf --lora-scaled glanz-a2-lora-f16.gguf:1.0 -ngl 99 -c 32768 -fa on
Allow a large token budget. These generations average 14,564 characters. At n_predict=7000,
6 of 22 briefs were cut off mid-page; at 16,000, 4 still were. A truncated page looks exactly like
a malformed one β the last fence never closes β so budget generously or you will measure your own
cap.
Which checkpoint
Four epochs were trained and all four evaluated. Held-out loss on 22 rows against loss on an equal-sized slice of training rows:
| checkpoint | held-out | train | gap |
|---|---|---|---|
| base | 0.7012 | 0.7065 | β0.005 |
| epoch 1 | 0.5632 | 0.5269 | 0.036 |
| epoch 2 (this one) | 0.5339 | 0.4406 | 0.093 |
| epoch 3 | 0.5329 | 0.3821 | 0.151 |
| epoch 4 | 0.5457 | 0.3686 | 0.177 |
Held-out loss bottoms at epoch 3 and rises at epoch 4 while training loss keeps falling β the
4-epoch weights are overfit, and they are what a naive save_model at the end of training would
have shipped.
Between epochs 2 and 3 the loss difference is 0.001, which is nothing, and the memorisation gap differs by 60%, which is not. The design eval broke the tie decisively: epoch 3 scores 0.966 on class coverage β the best of any variant β but collapses into repetition on 2 of 22 briefs, the same failure the base model has and epoch 2 eliminates. Buying 0.02 of coverage with two catastrophic loops is a bad trade.
Training
| base | schneewolflabs/A2 (12B, Mistral-Nemo class) |
| method | SFT, LoRA r=32 Ξ±=64 dropout 0.05 |
| modules | q, k, v, o, gate, up, down β 114M params (0.92%) |
| data | 202 train / 22 held out, from 224 rows |
| schedule | 4 epochs, 104 steps, lr 1e-4 cosine, warmup 0.05 |
| batch | 1 Γ grad-accum 8 |
| sequence | max_length 8192 |
| hardware | one RTX A6000, 33 GB peak, 76 minutes |
| trainer | grimoire |
Training loss fell 0.762 β 0.357 with no rebound. max_length is 8192 because the longest
rendered sample is 6,672 tokens and 4096 would have truncated 180 of 224 β teaching the model to
stop mid-page would have been worse than not training.
6 of 200 source rows had syntactically invalid JavaScript, truncated mid-token by whatever cap
the original Glamour capture ran under. Those blocks were dropped after a node --check pass
rather than trained on. The block was dropped rather than the row, because js is the last field
generated, so a truncated row's HTML and CSS are complete and still worth learning from.
Limitations
- Not Opus. Coverage and structure reach the ceiling; the design does not. This model produces well-formed, densely styled, plausible pages, not award-winning ones.
- Single provenance. 224 briefs from one generator in one aesthetic register. Expect the house style of that corpus.
- The system prompt matters. Trained under one specific framing; the behaviour does carry to bare prompts (a no-system-prompt design request grew from 435 to 2,996 characters) but the measured numbers are all under the prompt shown above.
- Scale untested. Everything here is at
--lora-scaled 1.0. Lower scales were not swept.
- Downloads last month
- 12
16-bit
Model tree for schneewolflabs/Glanz-A2-LoRA
Base model
schneewolflabs/A0i-12B