grug-27b / handler.py
ProCreations's picture
Upload handler.py with huggingface_hub
d9d9db5 verified
Raw
History Blame Contribute Delete
3.23 kB
"""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}]