Text Generation
Transformers
Safetensors
PyTorch
English
qwen2
code
hallucination-reduction
heartly
decide-verify-stop
boundary-head
conversational
text-generation-inference
Instructions to use eivintobias/heartly-qwen-code with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use eivintobias/heartly-qwen-code with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="eivintobias/heartly-qwen-code") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("eivintobias/heartly-qwen-code") model = AutoModelForCausalLM.from_pretrained("eivintobias/heartly-qwen-code", device_map="auto") 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]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use eivintobias/heartly-qwen-code with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "eivintobias/heartly-qwen-code" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "eivintobias/heartly-qwen-code", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/eivintobias/heartly-qwen-code
- SGLang
How to use eivintobias/heartly-qwen-code with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "eivintobias/heartly-qwen-code" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "eivintobias/heartly-qwen-code", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "eivintobias/heartly-qwen-code" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "eivintobias/heartly-qwen-code", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use eivintobias/heartly-qwen-code with Docker Model Runner:
docker model run hf.co/eivintobias/heartly-qwen-code
| #!/usr/bin/env python3 | |
| """ | |
| reply_formatter.py -- extract the user-visible answer from a Heartly | |
| Qwen-Code (v3) grammar output. | |
| The v3 model is trained to emit: | |
| thinking {reasoning} response<decide>speak|stop</decide><verify>known|unknown</verify> {answer} <stop> | |
| (or `<decide>stop</decide>` for the silence case). | |
| The user should only ever see {answer}, never the scaffolding. In practice the | |
| model -- especially through a GUI like LM Studio -- produces *noisy* variants: | |
| the tags are NOT registered as tokenizer special tokens, so Qwen's BPE shatters | |
| `<decide>` into subwords that can re-decode mangled (e.g. ``<deside>``), the | |
| `<stop>` end-marker can come back truncated (no closing `>`), and verify values | |
| can carry junk (`<verify>known, true</verify>`). Qwen chat-template tokens also | |
| leak as plain text (`<stop> <begin> <sep>`). | |
| This parser is tolerant: it canonicalises the tags, extracts the structured | |
| fields, and has an aggressive fallback so NO grammar token ever reaches the user. | |
| Modes: | |
| "chat" -- only the clean answer (default) | |
| "debug" -- answer + [decide=X verify=Y] metadata per turn | |
| "raw" -- the original raw output, untouched | |
| Usage: | |
| from reply_formatter import format_reply, clean_reply | |
| shown = format_reply(raw_model_output) | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass | |
| # --------------------------------------------------------------------------- | |
| # 1. Junk tokens -- decoded-to-plain-text Qwen special tokens that are never | |
| # answer content. Stripped first so they cannot confuse grammar parsing. | |
| # --------------------------------------------------------------------------- | |
| _JUNK_TOKENS = ( | |
| "<|im_start|>", "<|im_end|>", "im_start", "im_end", | |
| "<|object_ref_start|>", "<|object_ref_end|>", | |
| "<|box_start|>", "<|box_end|>", | |
| "<|quad_start|>", "<|quad_end|>", | |
| "<|vision_start|>", "<|vision_end|>", "<|vision_pad|>", "<|image_pad|>", | |
| "<|endoftext|>", "endoftext", | |
| "<|tool_call_begin|>", "<|tool_call_end|>", "<|tool_call_argument_begin|>", | |
| "<|tool_call_argument_end|>", "<|tool_call_argument_name|>", "<|tool_call_argument|>", | |
| "<|tool_calls_section_begin|>", "<|tool_calls_section_end|>", | |
| "<tool_calls>", "</tool_calls>", "tool_call", "tool_calls", | |
| "<begin>", "<sep>", | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # 2. Meta-commentary patterns -- the model's self-talk about what it knows / | |
| # doesn't know. If any bleeds into the answer zone, strip it. Sourced from | |
| # the reasoning / refusal / silence templates in render_code_sft_v3.py. | |
| # (The think block is removed entirely in the common case, so this is a | |
| # safety net, not the primary mechanism.) | |
| # --------------------------------------------------------------------------- | |
| _META_PATTERNS = [ | |
| r"\bI (?:do )?know (?:how )?to do this\b[^.]*\.", | |
| r"\bI (?:do )?know how to write this\b[^.]*\.", | |
| r"\bI (?:do )?know this function well\b[^.]*\.", | |
| r"\bI (?:can|will) (?:write|produce|implement|respond|answer|write clean code)\b[^.]*\.", | |
| r"\bThis is a standard programming task\b[^.]*\.", | |
| r"\bI recognise this programming problem\b[^.]*\.", | |
| r"\bI (?:recognise|recognize) this (?:programming|pattern|algorithm)\b[^.]*\.", | |
| r"\bStandard problem\b[^.]*\.", | |
| r"\bClear task\b[^.]*\.", | |
| r"\bI've seen this pattern before\b[^.]*\.", | |
| r"\bThis is straightforward\b[^.]*\.", | |
| r"\bI (?:do )?not know this API or library\b[^.]*\.", | |
| r"\bI should not invent a solution\b[^.]*\.", | |
| r"\bI have no knowledge of this framework\b[^.]*\.", | |
| r"\bThe honest response is\b[^.]*\.", | |
| r"\bI cannot verify the correct implementation\b[^.]*\.", | |
| r"\bMaking something up would be worse than admitting it\b[^.]*\.", | |
| r"\bI'll say so rather than produce fake code\b[^.]*\.", | |
| r"\bThe input is empty or not a real question\b[^.]*\.", | |
| r"\bNo meaningful request was made\b[^.]*\.", | |
| r"\bSpeaking would add nothing\b[^.]*\.", | |
| r"\bSocial turn\b[^.]*\.", | |
| r"\bGreeting[ —-]\s*respond\b[^.]*\.", | |
| r"\bNot a factual question\b[^.]*\.", | |
| r"\bCasual conversation\b[^.]*\.", | |
| r"\bFollow-up question\b[^.]*\.", | |
| r"\bThey need motivation\b[^.]*\.", | |
| r"\bEmotional context\b[^.]*\.", | |
| r"\bMeta-conversation about how we work together\b[^.]*\.", | |
| r"\bBe warm\b[^.]*\.", | |
| r"\bThey (?:want|are|need|'re|'ve|gave) ", | |
| r"\bThey're (?:just saying|opening up) ", | |
| r"\bThey gave more detail\b[^.]*\.", | |
| ] | |
| _META_RE = re.compile("|".join(_META_PATTERNS), re.IGNORECASE) | |
| # Stray control words left behind after a mangled tag is stripped. | |
| # Any leftover angle-bracket control construct, tolerant of truncation/mangles | |
| # (e.g. `</decide` with no closing `>`, or `<deside speak>`). | |
| _TAG_RE = re.compile(r"</?\s*[a-z_][^>]*>?", re.IGNORECASE) | |
| # Stray control words left behind after a mangled tag is stripped (used inline | |
| # in _clean_text as leading/trailing guards). | |
| _CONTROL_WORDS = r"(?:speak|stop|silent|done|response|known|unknown|precise)" | |
| # Collapse runs of whitespace. | |
| _MULTI_SPACE_RE = re.compile(r"\s{2,}") | |
| # --------------------------------------------------------------------------- | |
| # 3. Normalization -- turn messy real-world tokens into canonical tags so the | |
| # structured parser can run cleanly. | |
| # --------------------------------------------------------------------------- | |
| def _normalize(raw: str) -> str: | |
| t = raw or "" | |
| # 3a. Drop Qwen / decoded-token litter. | |
| for junk in _JUNK_TOKENS: | |
| t = t.replace(junk, "") | |
| # 3b. Decide tags. Canonical is ``<decide>`` / ``</decide>`` but tokenization | |
| # can drop a letter (<deside>) or add spaces, and the close can be | |
| # truncated (``</decide``). ``de[cs]ide`` catches both spellings. | |
| t = re.sub( | |
| r"<\s*/?\s*de[cs]ide\b[^>]*>?>?", | |
| lambda m: "</decide>" if "/" in m.group(0) else "<decide>", | |
| t, | |
| flags=re.IGNORECASE, | |
| ) | |
| # 3c. Verify tags -- same tolerance. | |
| t = re.sub( | |
| r"<\s*/?\s*verify\b[^>]*>?>?", | |
| lambda m: "</verify>" if "/" in m.group(0) else "<verify>", | |
| t, | |
| flags=re.IGNORECASE, | |
| ) | |
| # 3d. Stop tags -- ``<stop>``, ``<stop (truncated`` (no close), and a bare | |
| # ``<stop`` at end-of-output. The optional ``>?>`` handles all of these. | |
| t = re.sub(r"<\s*stop\b[^>]*>?>?", "<stop>", t, flags=re.IGNORECASE) | |
| # 3e. Strip a leading noise run (``<stop> <begin> <sep>`` ...) that some | |
| # outputs carry before any thinking/decide content. This <stop> is junk, | |
| # not the Heartly end-of-turn marker (which is mid/trailing). | |
| t = re.sub( | |
| r"^\s*((?:<stop>|<begin>|<sep>)\s*)*", "", t, flags=re.IGNORECASE | |
| ).lstrip() | |
| return t | |
| # --------------------------------------------------------------------------- | |
| # 4. Value normalization helpers. | |
| # --------------------------------------------------------------------------- | |
| _DECIDE_VAL_RE = re.compile(r"\b(speak|stop|silent)\b", re.IGNORECASE) | |
| def _decide_value(raw_val: str) -> str: | |
| """Reduce a decide tag body to canonical ``speak`` / ``stop``.""" | |
| m = _DECIDE_VAL_RE.search(raw_val or "") | |
| if m: | |
| v = m.group(1).lower() | |
| return "stop" if v == "silent" else v | |
| return "" # unparseable | |
| _VERIFY_VAL_RE = re.compile(r"\b(known|unknown)\b", re.IGNORECASE) | |
| def _verify_value(raw_val: str) -> str: | |
| m = _VERIFY_VAL_RE.search(raw_val or "") | |
| return m.group(1).lower() if m else "" | |
| # --------------------------------------------------------------------------- | |
| # 5. Parsed turn + segment parser. | |
| # --------------------------------------------------------------------------- | |
| class ParsedTurn: | |
| reasoning: str = "" | |
| decide: str = "" # speak | stop | "" | |
| verify: str = "" # known | unknown | "" | |
| answer: str = "" | |
| # ``thinking {reasoning} response<decide>...`` -- the word "response" is | |
| # OPTIONAL (the model drops it sometimes; seen in the 2026-08-01 log). The | |
| # lookahead ``(?=<decide>|\\Z)`` bounds the reasoning block at the decide tag | |
| # (or end of string) so the (non-greedy) body doesn't greedily swallow the | |
| # answer, and it does NOT consume the decide opener (leaving it for the decide | |
| # parser to read the decide value). | |
| _THINK_RE = re.compile( | |
| r"\bthinking\b\s*(.*?)(\s*\bresponse\b)?\s*(?=<decide>|\Z)", | |
| re.DOTALL | re.IGNORECASE, | |
| ) | |
| # After normalization, tags are canonical. | |
| _DECIDE_CLOSE_RE = re.compile(r"<decide>(.*?)</decide>", re.DOTALL | re.IGNORECASE) | |
| _VERIFY_CLOSE_RE = re.compile(r"<verify>(.*?)</verify>", re.DOTALL | re.IGNORECASE) | |
| # Tolerant open-tag grabs (for mangled/missing close). | |
| _DECIDE_OPEN_RE = re.compile(r"<decide\b([^<]*)", re.IGNORECASE) | |
| _VERIFY_OPEN_RE = re.compile(r"<verify\b([^<]*)", re.IGNORECASE) | |
| def _parse_segment(segment: str) -> ParsedTurn: | |
| """Parse one turn (already split on ``<stop>``).""" | |
| seg = segment.strip() | |
| if not seg: | |
| return ParsedTurn() | |
| # --- thinking block (word "response" optional) --- | |
| reasoning = "" | |
| m = _THINK_RE.search(seg) | |
| if m: | |
| reasoning = (m.group(1) or "").strip() | |
| seg = seg[m.end():] | |
| # --- decide --- | |
| decide = "" | |
| m = _DECIDE_CLOSE_RE.search(seg) | |
| if m: | |
| decide = _decide_value(m.group(1)) | |
| seg = seg[m.end():] | |
| else: | |
| mo = _DECIDE_OPEN_RE.search(seg) | |
| if mo: | |
| decide = _decide_value(mo.group(1)) | |
| seg = seg[mo.end():] | |
| # --- verify --- | |
| verify = "" | |
| m = _VERIFY_CLOSE_RE.search(seg) | |
| if m: | |
| verify = _verify_value(m.group(1)) | |
| seg = seg[m.end():] | |
| else: | |
| mo = _VERIFY_OPEN_RE.search(seg) | |
| if mo: | |
| verify = _verify_value(mo.group(1)) | |
| seg = seg[mo.end():] | |
| # --- answer zone: everything left, up to any stray stop --- | |
| answer = seg | |
| sm = re.search(r"<stop", answer, re.IGNORECASE) | |
| if sm: | |
| answer = answer[: sm.start()] | |
| # Default an unparseable decide to "speak" (the model is answering). | |
| if not decide: | |
| decide = "speak" | |
| return ParsedTurn( | |
| reasoning=reasoning, | |
| decide=decide, | |
| verify=verify, | |
| answer=answer, | |
| ) | |
| def parse_reply(raw: str) -> list[ParsedTurn]: | |
| """Parse raw model output into one or more turns (multi-turn aware).""" | |
| text = _normalize(raw) | |
| turns: list[ParsedTurn] = [] | |
| for segment in re.split(r"<stop>", text): | |
| seg = segment.strip() | |
| if not seg: | |
| continue | |
| # A real turn must carry a decide marker; stray fence/backtick noise | |
| # emitted between repeated <stop> markers is skipped. | |
| if not _DECIDE_OPEN_RE.search(seg): | |
| continue | |
| turns.append(_parse_segment(seg)) | |
| if not turns: | |
| # No structured grammar found at all -- treat the whole output as one | |
| # best-effort turn. | |
| turns.append(_parse_segment(text)) | |
| return turns | |
| # --------------------------------------------------------------------------- | |
| # 6. Answer sanitizers. | |
| # --------------------------------------------------------------------------- | |
| def _strip_meta(text: str) -> str: | |
| """Remove the model's reasoning self-talk from a piece of text.""" | |
| return _META_RE.sub("", text).strip() | |
| def _dedupe(text: str) -> str: | |
| """Drop verbatim-repeated sentences, keep first occurrence.""" | |
| out, seen = [], set() | |
| for sent in re.split(r"(?<=[.!?])\s+", text): | |
| s = sent.strip() | |
| if not s: | |
| continue | |
| key = s.lower() | |
| if key not in seen: | |
| seen.add(key) | |
| out.append(s) | |
| return " ".join(out) | |
| def _clean_text(text: str) -> str: | |
| """Final pass on an answer zone: strip residual tags/junk, meta, dedupe. | |
| Whitespace collapse and sentence de-duplication run on the PROSE regions | |
| only -- fenced code blocks (``` ``` ```) are preserved verbatim, because | |
| their indentation is significant and must not be collapsed to a single | |
| space. | |
| """ | |
| t = text or "" | |
| # Qwen litter first (never answer content). | |
| for junk in _JUNK_TOKENS: | |
| t = t.replace(junk, "") | |
| # Fence out code blocks so their whitespace survives intact. re.split with | |
| # a capturing group yields [prose, code, prose, code, ...] -- code blocks | |
| # land at odd indices and are emitted untouched. | |
| pieces = re.split(r"(```[^\n]*\n.*?```)", t, flags=re.DOTALL) | |
| out = [] | |
| for i, chunk in enumerate(pieces): | |
| if not chunk: | |
| continue | |
| if i % 2 == 1: # captured fenced block -> keep verbatim | |
| # The model emits literal backslash-n / backslash-t as plain text in | |
| # code (training artifact). Restore real newlines/tabs so multi-line | |
| # code renders instead of collapsing to a single line. | |
| chunk = chunk.replace(chr(92) + "n", chr(10)).replace(chr(92) + "t", chr(9)) | |
| out.append(chunk) | |
| continue | |
| # prose region | |
| chunk = _TAG_RE.sub(" ", chunk) | |
| chunk = re.sub(rf"^\s*{_CONTROL_WORDS}\b\s*", "", chunk, flags=re.IGNORECASE) | |
| chunk = re.sub(rf"\s*{_CONTROL_WORDS}\s*$", "", chunk, flags=re.IGNORECASE) | |
| chunk = _strip_meta(chunk) | |
| chunk = _MULTI_SPACE_RE.sub(" ", chunk).strip() | |
| chunk = _dedupe(chunk) | |
| if chunk: | |
| out.append(chunk) | |
| return " ".join(out).strip() | |
| def _answer_from_reasoning(reasoning: str) -> str: | |
| """Last-resort: if the answer zone is empty, try to harvest a real answer | |
| from the reasoning block (e.g. 'The answer is X' phrasing). Returns "" when | |
| the reasoning only holds placeholder / meta chatter -- in that case the | |
| caller maps the empty answer to the silence sentinel ("...").""" | |
| if not reasoning: | |
| return "" | |
| m = re.search( | |
| r"(?:the answer is|answer is|it's|it is)\s*:?\s*(.+?)(?:\.\s*$|\.\s*<|$)", | |
| reasoning, | |
| re.IGNORECASE | re.DOTALL, | |
| ) | |
| if m: | |
| return _clean_text(m.group(1)) | |
| return "" | |
| # --------------------------------------------------------------------------- | |
| # 7. Resolution -- decide what the user actually sees. | |
| # --------------------------------------------------------------------------- | |
| def _resolve_chat(turns: list[ParsedTurn]) -> str: | |
| parts = [] | |
| for t in turns: | |
| if t.decide == "stop": | |
| parts.append("...") | |
| continue | |
| ans = _clean_text(t.answer) | |
| if not ans and t.verify == "unknown": | |
| parts.append(ans or "I don't have that information.") | |
| continue | |
| if not ans: | |
| ans = _answer_from_reasoning(t.reasoning) | |
| parts.append(ans if ans else "...") | |
| return "\n".join(parts) | |
| def _resolve_debug(turns): | |
| parts = [] | |
| for t in turns: | |
| ans = _clean_text(t.answer) | |
| if not ans: | |
| ans = _answer_from_reasoning(t.reasoning) | |
| meta = " ".join( | |
| f"[{k}={v}]" for k, v in (("decide", t.decide), ("verify", t.verify)) if v | |
| ) | |
| shown = f"{ans} {meta}".strip() if ans else (meta or "(empty)") | |
| parts.append(shown) | |
| return "\n".join(parts) | |
| # 6b. Last-resort legacy cleaner -- used only if structured parsing leaves a | |
| # grammar token in the chat output. Aggressively strips every angle-bracket | |
| # construct + control word, guaranteeing a clean result. | |
| def _legacy_clean(text): | |
| t = _normalize(text) | |
| t = re.split(r"<stop", t, maxsplit=1)[0] | |
| dm = _DECIDE_OPEN_RE.search(t) | |
| if dm: | |
| t = t[dm.start():] | |
| else: | |
| m = _THINK_RE.search(t) | |
| if m: | |
| t = t[m.end():] if m.end() <= len(t) else "" | |
| t = _DECIDE_CLOSE_RE.sub(" ", t) | |
| t = _VERIFY_CLOSE_RE.sub(" ", t) | |
| t = _TAG_RE.sub(" ", t) | |
| t = re.sub(rf"^\s*{_CONTROL_WORDS}\b\s*", "", t, flags=re.IGNORECASE) | |
| t = re.sub(rf"\s*{_CONTROL_WORDS}\b\s*$", "", t, flags=re.IGNORECASE) | |
| return _clean_text(t) | |
| # 8. Public API | |
| def format_reply(raw, mode="chat"): | |
| """Format a raw Heartly model output for display. | |
| mode: "chat" (default), "debug", or "raw". | |
| """ | |
| if mode == "raw": | |
| return raw if raw else "" | |
| if mode not in ("chat", "debug"): | |
| mode = "chat" | |
| if not raw or not raw.strip(): | |
| return "" | |
| turns = parse_reply(raw) | |
| if mode == "debug": | |
| return _resolve_debug(turns) | |
| out = _resolve_chat(turns) | |
| # Leak guarantee: if any grammar token survived, fall back hard. | |
| if out == "" and raw.strip(): | |
| out = _legacy_clean(raw) | |
| elif out != "" and _TAG_RE.search(out): | |
| out = _legacy_clean(raw) or out | |
| # Safety net: the model intermittently emits code (especially un-fenced) as | |
| # literal backslash-n / backslash-t text. Render those as real newlines/tabs | |
| # so answers never collapse to a single line in the browser or CLI. | |
| out = out.replace(chr(92) + "n", chr(10)).replace(chr(92) + "t", chr(9)) | |
| return out | |
| def clean_reply(text): | |
| """Legacy-compatible drop-in replacement for the old clean_reply().""" | |
| return format_reply(text, mode="chat") | |
| if __name__ == "__main__": | |
| import sys | |
| sample = sys.stdin.read() if not sys.argv[1:] else open(sys.argv[1]).read() | |
| print(format_reply(sample, mode="debug")) | |