Instructions to use CatQualia/gnarp-m2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use CatQualia/gnarp-m2 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="CatQualia/gnarp-m2") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("CatQualia/gnarp-m2") model = AutoModelForCausalLM.from_pretrained("CatQualia/gnarp-m2", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use CatQualia/gnarp-m2 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "CatQualia/gnarp-m2" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "CatQualia/gnarp-m2", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/CatQualia/gnarp-m2
- SGLang
How to use CatQualia/gnarp-m2 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "CatQualia/gnarp-m2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "CatQualia/gnarp-m2", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "CatQualia/gnarp-m2" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "CatQualia/gnarp-m2", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use CatQualia/gnarp-m2 with Docker Model Runner:
docker model run hf.co/CatQualia/gnarp-m2
# Load model directly
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("CatQualia/gnarp-m2")
model = AutoModelForCausalLM.from_pretrained("CatQualia/gnarp-m2", device_map="auto")
messages = [
{"role": "user", "content": "Who are you?"},
]
inputs = tokenizer.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=True,
return_dict=True,
return_tensors="pt",
).to(model.device)
outputs = model.generate(**inputs, max_new_tokens=40)
print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:]))gnarp-m2
A 360M-parameter language model fine-tuned via QLoRA on 69,945 cross-domain isomorphism and verification-labeled instruction pairs (74,395 rows read; every row labelled negative is discarded by the trainer). gnarp-m2 specializes in cross-domain structural transfer โ mapping mechanisms from one domain (biology, physics, anime, economics, etc.) to software engineering constructs.
Model Details
| Property | Value |
|---|---|
| Base model | HuggingFaceTB/SmolLM2-360M-Instruct |
| Method | QLoRA (4-bit NF4, double quantization) |
| LoRA rank | 16 |
| LoRA alpha | 32 |
| LoRA dropout | 0.05 |
| Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj |
| Trainable params | 8,683,520 (2.34% of total) |
| Total params | 370,504,640 |
| Adapter size | 34.8 MB (rank-16, alpha-32) |
| Merged model size | 1.4 GB |
| Architecture | LlamaForCausalLM |
| Max sequence length | 768 tokens |
Training Data
Corpus: clean_corpus_v5.jsonl โ 74,395 rows read, of which 69,945 were train-eligible
| Source | Rows | Description |
|---|---|---|
| isomorphism_sft.jsonl | 53,403 | Anime-to-software structural isomorphisms. Drawn from the 17,801-row moat corpus, which carries a non-empty failure_class on every row โ but this file does not: the corpus contains no failure_class field at all (see Corrections below) |
| gpu_assay_verdicts.jsonl | 11,989 | GPU assay verification-labeled pairs |
| anime_metaphor_engine.jsonl | 4,523 | Cross-domain metaphor engine outputs |
| forge_bloom | 2,117 | Forge pipeline bloom outputs |
| capability/reasoning/seed.jsonl | 1,232 | Reasoning capability seed data |
| fleet_toolforge.jsonl | 187 | Fleet tool use pairs |
| Others (30+ sources) | 944 | Security, orchestration, calibration, refusal, compliance, etc. |
Label composition, measured: 11,669 rows labelled positive, 4,450 labelled negative,
58,276 unlabelled. Positive and unlabelled rows only; negative rows are excluded from SFT
targets โ and in this pipeline they are dropped outright, before the normalised corpus is
written (run_qlora_gnarpm2.py: if r.get("label") == "negative": continue). So
all 4,450 refuted rows were excluded from the loss, and the model did not train on them
as context, as masked targets, or as contrastive pairs.
Training Configuration
| Parameter | Value |
|---|---|
| Epochs | 1 |
| Learning rate | 1e-4 (cosine schedule, 5% warmup) |
| Batch size | 1 |
| Gradient accumulation | 8 |
| Effective batch size | 8 |
| Optimizer | AdamW (bf16) |
| Eval split | 10% held out |
| Eval strategy | Every 500 steps |
| Best model selection | eval_loss (load_best_model_at_end) |
| Seed | 7 |
| Training hardware | RTX 3080 Laptop (8 GB VRAM) |
| Training time | ~13 hours |
Training Results
| Metric | Value |
|---|---|
| Final train loss | 2.613 |
| Final eval loss | 2.509 |
| Token accuracy | 55.55% |
| Perplexity (train) | 13.64 |
Evaluation: Cross-Domain Transfer Benchmark v2
36 cross-domain transfer tasks spanning anime, biology, physics, economics, fiction, geography, music, cooking, ecology, martial arts, psychology, logistics, chemistry, sports, agriculture, linguistics, city planning, finance, navigation, and architecture.
Scoring: Heuristic rubric (keyword + structural analysis). Trust DELTAS between models on the same tasks, not absolutes.
| Model | Judge Mean | Delta vs Base | Avg Response (chars) | Avg Latency (s) |
|---|---|---|---|---|
| gnarp-m2 | 0.7839 | +14.1% | 1,108 | 4.9 |
| base (SmolLM2-360M-Instruct) | 0.6871 | โ | 1,489 | 6.9 |
Prior Model Lineage (heldout benchmark, qwen3:8b judge)
| Model | Transfer Score | Heldout Loss | Perplexity | Refusal Rate | Training Data |
|---|---|---|---|---|---|
| base | 0.709 | 1.625 | 5.08 | 0.130 | โ |
| v1 | 0.218 | 1.850 | 6.36 | 0.385 | ~2,152 rows |
| v2 | 0.713 | 1.800 | 6.05 | 0.340 | ~2,152 rows |
| v3 | 0.561 | 1.790 | 5.99 | 0.400 | ~2,152 rows |
| m2 | 0.7839* | โ | โ | not measured | 69,945 trained (of 74,395 read) |
*m2 scored on transfer_benchmark_v2 (heuristic-only), not the qwen3:8b-judged heldout benchmark. Cross-benchmark comparisons should be treated with caution. The lineage is also not monotonic on this table: v1 (0.218) scores far below base (0.709). The 10%โ26%โ31%โ37% progression quoted elsewhere refers to a different eval (animeโarchitecture, two LLM judges) and should not be read as the heldout benchmark.
m2's refusal rate was never measured. The row is blank because no computation was performed, not because the result was unfavourable. The 0.130โ0.400 figure sometimes quoted alongside this model belongs to the earlier lineage (baseโv3) and does not describe m2. Calibration drift for m2 is therefore unmeasured.
Corrections
Two claims previously made about this model did not survive re-reading its own artefacts, and are recorded here rather than quietly edited.
"Trained on data that includes the claims the system refuted against itself." False, and the opposite of what happens. The trainer discards every row labelled negative before the normalised corpus is written; 4,450 of 74,395 rows carry that label. The model never saw a refuted example, so it cannot have learnt "the shape of a wrong answer" from one. Any downstream claim resting on contrastive training over refutations does not hold for this checkpoint.
"failure_class from the 17,801-row moat." The moat corpus does carry a non-empty
failure_classon all 17,801 of its rows. The corpus that trained this model carries the field on zero of its rows, and the normaliser emits onlyinstruction/input/output, so such a label could not have reached the loss even if present. The only per-row taxonomy in the corpus isverdict_raw, with four values (VERIFIED/GENERATIVE 7,758; REFUTED/DECORATIVE 4,231; GENERATIVE 3,160; REFUTED 12). The fine-grained error grammar is absent from the training signal, not collapsed within it.Row count. The headline figure of 74,395 is the pre-filter count; 69,945 rows were train-eligible. Every row in the corpus also carries
train_eligible: true, including the 4,450 the trainer discards โ two mechanisms in one pipeline disagreeing about the same fact.
Not yet run: the ablation that would separate the value of the corpus structure from the value of the labels โ same rows, failure labels stripped or shuffled, same benchmark. It cannot be run as originally stated, because the labels it would strip are not in the corpus.
Limitations
- 360M parameters. Small model. Cannot match larger models on complex reasoning, long-form generation, or nuanced instruction following.
- Single GPU, single epoch. Trained on consumer hardware (RTX 3080 8GB) for one epoch. More training could improve results but risks overfitting.
- Heuristic eval. The transfer benchmark v2 uses keyword/structural heuristic scoring, not a strong LLM judge. The +14.1% delta is directionally meaningful but not precisely calibrated.
- Cross-benchmark caveat. v1/v2/v3 were scored with a qwen3:8b judge; m2 was scored with heuristic-only. Direct numerical comparison across the two benchmarks is not valid.
- Domain-specific training data. Over 71% of training data is isomorphism pairs. The model is optimized for cross-domain structural transfer and may underperform on general chat or coding tasks.
- No safety fine-tuning beyond refusal data. The model includes 19 refusal pairs but is not extensively safety-tuned.
How to Use
With Ollama (recommended for local inference)
# Create the Modelfile
cat > Modelfile << 'EOF'
FROM ./model/merged_gnarpm2
TEMPLATE """### Instruction: {{ .Prompt }} ### Response: """
PARAMETER num_ctx 4096
PARAMETER temperature 0.3
PARAMETER num_predict 512
SYSTEM You are gnarp-m2, a cross-domain transfer specialist.
EOF
ollama create gnarp-m2 -f Modelfile
ollama run gnarp-m2
With Transformers
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "gnarp/gnarp-m2" # or local path
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto")
prompt = "### Instruction:\nApply the concept of biological apoptosis to software deployment strategy.\n### Response:\n"
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=512, temperature=0.3)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
With PEFT (adapter only)
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("HuggingFaceTB/SmolLM2-360M-Instruct")
model = PeftModel.from_pretrained(base, "path/to/adapter_gnarpm2")
model = model.merge_and_unload()
License
- Model weights and code: CatQualia Open-Or-Pay License (COPL) v1.0 โ free for research, individuals and academia with attribution; commercial use requires either opening the derivative stack or a commercial waiver.
- Training data (corpus): CatQualia Structural Isomorphism License (CSIL) v3.0 โ derived from the WaveMotionExpansion isomorphism engine.
- Base model: Apache 2.0 (SmolLM2-360M-Instruct by HuggingFace)
Full terms in this repository: LICENSE (CSIL v3.0) and COPL-LICENSE.md (COPL v1.0).
Both also at https://catqualia.com/licensing
Citation
If you use gnarp-m2, please cite the model together with the publication that describes the corpus it was trained on.
@model{gnarp-m2,
title={gnarp-m2: Cross-Domain Transfer Fine-Tuned Language Model},
author={Betances, Christopher},
year={2026},
base_model={HuggingFaceTB/SmolLM2-360M-Instruct},
method={QLoRA},
training_rows={69945},
corpus_rows_read={74395},
transfer_benchmark={0.7839},
url={https://huggingface.co/CatQualia/gnarp-m2}
}
Related records:
- Training corpus โ Self-Falsifying Research Infrastructure Void Atlas: https://doi.org/10.5281/zenodo.22751797
- OmniLingua Interpreter Core (prompt architecture the corpus derives from): https://doi.org/10.5281/zenodo.22751511
- The complete CatQualia record โ 135 dated defensive publications, each with its own DOI: https://doi.org/10.5281/zenodo.22751107
- Downloads last month
- 950
Model tree for CatQualia/gnarp-m2
Base model
HuggingFaceTB/SmolLM2-360M
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="CatQualia/gnarp-m2") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)