How to use from the
Use from the
Transformers library
# Use a pipeline as a high-level helper
from transformers import pipeline

pipe = pipeline("text-generation", model="schneewolflabs/A2")
messages = [
    {"role": "user", "content": "Who are you?"},
]
pipe(messages)
# Load model directly
from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("schneewolflabs/A2")
model = AutoModelForCausalLM.from_pretrained("schneewolflabs/A2")
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]:]))
Quick Links

A2

A2 adds tool / function calling to the A-series while retaining its reasoning and the Schneewolf Labs identity. It is a Mistral-Nemo–class 12B model.

Lineage: A0i (12B base) → A1 (reasoning, BigDenker-SFT) → A1.1 (Claude-distilled reasoning + Schneewolf Labs / Luna identity) → A2 (function calling + retained reasoning/identity).

Capabilities

  • Function calling in the Qwen3 convention: emits <tool_call>\n<function=name>\n<parameter=key>\nvalue\n</parameter>\n</function>\n</tool_call>, including parallel calls, from a tools schema passed via the chat template.
  • Abstention — correctly declines (rather than forcing a spurious call) when no available tool fits the request.
  • Reasoning — retains the <think>…</think> step-by-step style from A1.1; reasons briefly before acting when useful, skips it for trivial calls.
  • Identity (two-tier) — by default identifies as "a language model created by Schneewolf Labs" (and resists "you're ChatGPT/OpenAI" pressure); the Luna persona + its terse voice activate only under the Luna system prompt.

The reasoning/tool tokens (<think>, </think>, <tool_call>, </tool_call>, <tool_response>, </tool_response>) reuse reserved tokenizer slots — no vocabulary resize. Context length: 128k (rope_theta 1e6).

Usage

A2 uses a Qwen3-style chat template (bundled chat_template.jinja). Always use the chat template. For tool use, pass tools to apply_chat_template:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

tok = AutoTokenizer.from_pretrained("schneewolflabs/A2")
model = AutoModelForCausalLM.from_pretrained(
    "schneewolflabs/A2", dtype=torch.bfloat16, device_map="auto"
)

tools = [{
    "name": "get_weather",
    "description": "Current weather for a city.",
    "parameters": {"type": "object",
        "properties": {"city": {"type": "string"}}, "required": ["city"]},
}]
msgs = [{"role": "user", "content": "What's the weather in Denver?"}]
enc = tok.apply_chat_template(
    msgs, tools=tools, add_generation_prompt=True,
    return_tensors="pt", return_dict=True,
).to(model.device)
out = model.generate(**enc, max_new_tokens=512, do_sample=False)
print(tok.decode(out[0][enc["input_ids"].shape[1]:], skip_special_tokens=False))

Tool results are returned as a {"role": "tool", "content": ...} message; the template renders them inside <tool_response>…</tool_response>.

Training

  • Method: full fine-tune with ORPO off A1.1 (grimoire / Merlina). paged_adamw_8bit, gradient checkpointing, batch 1 × grad-accum 16, lr 7e-6 (cosine, 5% warmup), bf16, max_length 4096, seed 42.
  • Checkpoint selection: this is the 1-epoch checkpoint (step 245). The 2-epoch run showed train-loss memorization at the epoch boundary and reasoning-template bleed; the 1-epoch checkpoint was selected for cleaner generalization.
  • Data (ORPO prompt/chosen/rejected[/system]):
    • Tool-calling: NousResearch/hermes-function-calling-v1 backbone + abstention examples mined from glaiveai/glaive-function-calling-v2, rendered through A2's own chat template; rejected synthesized via a failure taxonomy (wrong function, missing/wrong args, hallucinated tool, spurious call, no-call, malformed).
    • Identity/voice rehearsal (~23%): schneewolflabs/i-DPO.
    • All sources Apache-2.0.

Evaluation notes

Behavioral checks (held-out / novel tools, not training data): correct calls on unseen tools including parallel calls; correct abstention when no tool fits; identity holds (Schneewolf Labs, resists adversarial prompts; Luna persona correctly gated to its system prompt); the terse Luna voice survived the tool-heavy training.

Not yet benchmarked on BFCL / τ-bench — the rejected signal is synthetic and off-policy, so A2 is strong on structural correctness and abstention but its robustness to subtle realistic tool errors is unmeasured.

Limitations

  • Single-turn tool data — multi-turn tool/result→answer chains are weaker; a multi-turn ("v2") dataset is future work.
  • Synthetic preference negatives — teaches "don't do obviously-wrong things"; not validated on a public function-calling leaderboard.
  • 12B reasoning — reasoning is retained from A1.1 but not exhaustively benchmarked; like any model this size it can still slip on arithmetic / trick problems.
  • Always-on thinking unless suppressed via the template.
  • Inherits the biases and limitations of the base model and the SFT/preference data.

Provenance

Base schneewolflabs/A1.1 · tool data Hermes-FC + Glaive-FC-v2 (Apache-2.0) · identity/voice schneewolflabs/i-DPO · ORPO via Merlina.

Downloads last month
37
Safetensors
Model size
12B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for schneewolflabs/A2

Finetuned
(1)
this model
Finetunes
1 model

Datasets used to train schneewolflabs/A2