grug-27b

grug get big brain now. 27B brain. biggest grug yet that actually work.

normal model think like this: "Okay, so the user wants me to carefully consider the best approach here. Let me think about this step by step..."

grug think like this: "Need parse date. Regex or datetime. datetime.strptime safer. Handle bad input, return None."

same reasoning. same depth. way fewer token. grug throw grammar padding in fire, keep all brain meat. answer come out normal english, full quality. only inside voice is grug.

what grug-27b is

  • base: Qwen/Qwen3.6-27B (apache 2.0)
  • method: LoRA r=32 on all text-stack linears, merged to bf16
  • loss: think-only loss on trajectory data (grug never imitate old seed english say-word), full loss on fresh high-quality data
  • data: grug-think-v3-10k agent trajectories + fresh gpt-5.5 set (hard math derivations, hard code design, chat, tool sessions) with dense adaptive grug think
  • grug think short when task small. grug think LONG when task hard. length earned by real constraint, never by "carefully thinking" smoke.

why 27b not break like 35b

35b brother repeat words until cave fall down. grug study why. train data had think in every history turn. agent tool (OpenCode etc) throw old think away. model see world it never train on. model panic. model loop.

grug-27b train on BOTH world:

  1. think-in-history trajectories (framework keep think)
  2. stripped-history variants: old think gone, exactly like agent framework replay, only final turn trained

then grug run repetition stress gauntlet before release: greedy long-form generation, deep think-stripped agent replay, multi-turn continuation. numbers below. no loop, no repeat sickness.

see difference

same HumanEval problem (separate_paren_groups), both solve correct:

Qwen3.6-27B think: 6,539 tokens. start like this and keep going for pages:

The user wants a Python function separate_paren_groups that takes a string of parentheses and spaces, and returns a list of strings. Each string in the list should represent a balanced group of parentheses that is not nested within another group. Spaces should be ignored...

grug-27b think: 33 tokens. whole thing:

Strip spaces. Scan chars; depth counts open parens. When depth becomes 0 after a close, current group finished; append and reset. Empty input -> [].

same answer quality. 198x less think.

number

score (same harness, same sampling, same token caps)

benchmark Qwen3.6-27B grug-27b delta
HumanEval pass@1 (164) 87.8 87.8 +0.0
MBPP sanitized pass@1 (100) 77.0 84.0 +7.0
GSM8K exact (200) 93.0 95.5 +2.5
SWE agentic replay: valid tool call (68) 94.1 97.1 +3.0
SWE agentic replay: reference tool match 54.4 92.6 +38.2
SWE agentic replay: schema-valid args 100.0 100.0 +0.0

token spend

benchmark base tokens (think) grug tokens (think) total token cut
HumanEval pass@1 (164) 4082 (3938) 176 (30) -96%
MBPP sanitized pass@1 (100) 3750 (3722) 86 (29) -98%
GSM8K exact (200) 1565 (1429) 93 (69) -94%
SWE agentic replay: valid tool call (68) 190 (65) 67 (27) -65%

repeat sickness check

repetition stress (43 greedy gauntlets) Qwen3.6-27B grug-27b
healthy generations 93.0% 88.4%
degenerate loops (>=3 phrase reps) 0.0% 0.0%
think blocks closed 100.0% 100.0%
ran out of tokens (no eos) 0.0% 0.0%

"healthy" metric strict: flags any generation where some line repeat 3+ time. grug inspect every flagged case both sides: all is well-formed structured doc (endpoint list, markdown table) where repeated line is legit formatting. actual degenerate loops: zero, both models, all 43 gauntlets. 35b sickness not present. also note base MBPP number hurt by own verbosity: 41% of base MBPP runs hit the 6144-token cap before finishing. grug hit cap 0 times ever.

think dialect: think function-word ratio 22.4% (base) -> 3.4% (grug); planner-English phrases per run 9978 -> 0 across all benchmarks

how run

works everywhere Qwen3.6-27B works (transformers, vLLM >= 0.19, sglang, llama.cpp via grug-27b-gguf).

vllm serve ProCreations/grug-27b --max-model-len 32768 --reasoning-parser qwen3
from transformers import AutoModelForImageTextToText, AutoTokenizer
tok = AutoTokenizer.from_pretrained("ProCreations/grug-27b")
model = AutoModelForImageTextToText.from_pretrained(
    "ProCreations/grug-27b", dtype="bfloat16", device_map="auto")
msgs = [{"role": "user", "content": "Write a function that checks if a number is prime."}]
inputs = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device)
out = model.generate(inputs, max_new_tokens=512, temperature=0.6, top_p=0.95, top_k=20)
print(tok.decode(out[0][inputs.shape[1]:]))

sampling: temperature 0.6-1.0, top_p 0.95, top_k 20 (same as base). thinking mode on by default. MTP weights not included (config say mtp_num_hidden_layers=0); vision tower included, untouched from base.

huggingface inference endpoints

deploy as CUSTOM CONTAINER vllm/vllm-openai:latest for full OpenAI protocol: /v1/chat/completions with streaming and tool calling. important: the container command must be set on the endpoint model.command field (top level, NOT inside the image dict - API silently drop it there):

python3 -m vllm.entrypoints.openai.api_server --model ProCreations/grug-27b
  --served-model-name grug-27b --max-model-len 16384 --max-num-seqs 128
  --gpu-memory-utilization 0.90 --reasoning-parser qwen3
  --enable-auto-tool-choice --tool-call-parser qwen3_coder --port 8000

qwen3_coder parser speak grug XML call format; deepseek_r1 reasoning parser split grug think into message.reasoning (vLLM >= 0.25 field name; older call it reasoning_content). one A100-80GB enough even at 262k context with --kv-cache-dtype fp8. for agent frameworks set --max-model-len BIG (agent system prompts alone pass 8k token; 16k cap make every request fail).

from openai import OpenAI
client = OpenAI(base_url="https://<your-endpoint>.endpoints.huggingface.cloud/v1", api_key="hf_...")  # HF token
stream = client.chat.completions.create(
    model="grug-27b",
    messages=[{"role": "user", "content": "why sky blue?"}],
    stream=True)
for chunk in stream:
    d = chunk.choices[0].delta
    r = getattr(d, "reasoning", None) or getattr(d, "reasoning_content", None)
    if r: print(r, end="")
    if d.content: print(d.content, end="")

tools: pass standard OpenAI tools=[...], get tool_calls back parsed. old simple handler still in repo (handler.py) if someone want default toolkit deploy instead.

qat rock

most cave use Q4. grug make special QAT version for Q4 people: grug-27b-qat-q4-gguf

  • weights trained while feeling 4-bit rounding, better Q4 quality. use that one for Q4. this repo best for bf16/Q8/Q6/Q5.

grug family

grug made by ProCreations. grug thank Qwen team for very good base brain.

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

Model tree for ProCreations/grug-27b

Base model

Qwen/Qwen3.6-27B
Finetuned
(309)
this model
Quantizations
3 models

Datasets used to train ProCreations/grug-27b