Text Generation
Safetensors
English
qwen3_5
grug
reasoning
token-efficient
agentic
tool-use
conversational
Instructions to use ProCreations/grug-27b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Inference
| """Custom Hugging Face Inference Endpoints handler for ProCreations/grug-27b. | |
| Deploy: create an Inference Endpoint from this repo with a GPU holding >=60GB | |
| VRAM for bf16 (1x A100-80GB / H100 / H200). The endpoint auto-detects this | |
| handler. | |
| Request formats accepted: | |
| {"inputs": "plain user prompt", "parameters": {...}} | |
| {"inputs": {"messages": [{"role": "user", "content": "..."}], | |
| "tools": [...optional OpenAI-style tool schemas...]}, | |
| "parameters": {"max_new_tokens": 1024, "temperature": 0.6, ...}} | |
| Response: | |
| [{"generated_text": "<full raw completion>", | |
| "think": "<grug reasoning>", "answer": "<final answer>"}] | |
| """ | |
| from typing import Any, Dict, List | |
| import torch | |
| from transformers import AutoModelForImageTextToText, AutoTokenizer | |
| DEFAULTS = {"max_new_tokens": 1024, "temperature": 0.6, "top_p": 0.95, "top_k": 20, | |
| "do_sample": True} | |
| MAX_NEW_TOKENS_CAP = 8192 | |
| class EndpointHandler: | |
| def __init__(self, path: str = ""): | |
| self.tokenizer = AutoTokenizer.from_pretrained(path) | |
| self.model = AutoModelForImageTextToText.from_pretrained( | |
| path, dtype=torch.bfloat16, device_map="auto", | |
| attn_implementation="sdpa") | |
| self.model.eval() | |
| def __call__(self, data: Dict[str, Any]) -> List[Dict[str, str]]: | |
| inputs = data.get("inputs", "") | |
| params = dict(DEFAULTS) | |
| params.update(data.get("parameters") or {}) | |
| params["max_new_tokens"] = min(int(params.get("max_new_tokens", 1024)), | |
| MAX_NEW_TOKENS_CAP) | |
| if params.get("temperature", 1.0) <= 0: | |
| params["do_sample"] = False | |
| params.pop("temperature", None) | |
| params.pop("top_p", None) | |
| params.pop("top_k", None) | |
| tools = None | |
| if isinstance(inputs, dict): | |
| messages = inputs.get("messages") or [ | |
| {"role": "user", "content": str(inputs.get("text", ""))}] | |
| tools = inputs.get("tools") or None | |
| elif isinstance(inputs, list): | |
| messages = inputs | |
| else: | |
| messages = [{"role": "user", "content": str(inputs)}] | |
| prompt = self.tokenizer.apply_chat_template( | |
| messages, tools=tools, add_generation_prompt=True, tokenize=False) | |
| enc = self.tokenizer(prompt, return_tensors="pt").to(self.model.device) | |
| gen_kwargs = {k: v for k, v in params.items() | |
| if k in ("max_new_tokens", "temperature", "top_p", "top_k", | |
| "do_sample", "repetition_penalty", "seed")} | |
| gen_kwargs.pop("seed", None) | |
| with torch.inference_mode(): | |
| out = self.model.generate(**enc, **gen_kwargs, | |
| pad_token_id=self.tokenizer.pad_token_id) | |
| text = self.tokenizer.decode(out[0][enc["input_ids"].shape[1]:], | |
| skip_special_tokens=True) | |
| if "</think>" in text: | |
| think, answer = text.split("</think>", 1) | |
| think = think.replace("<think>", "").strip() | |
| answer = answer.strip() | |
| else: | |
| think, answer = "", text.strip() | |
| return [{"generated_text": text, "think": think, "answer": answer}] | |