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:
- think-in-history trajectories (framework keep think)
- 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_groupsthat 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-v2-9b - small brother, 9B
- grug-27b - this grug
- grug-think-v3-10k - the brain box
grug made by ProCreations. grug thank Qwen team for very good base brain.
- Downloads last month
- 19